Skip to content

Commit

Permalink
Merge pull request #304 from poap-xyz/release/v1.13.20
Browse files Browse the repository at this point in the history
Release v1.13.20
  • Loading branch information
jm42 authored May 22, 2024
2 parents f548f84 + b9892a9 commit 39063e1
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 120 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@poap-xyz/poap-family",
"version": "1.13.19",
"version": "1.13.20",
"author": {
"name": "POAP",
"url": "https://poap.xyz"
Expand Down
4 changes: 2 additions & 2 deletions src/components/AddressOwner.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { DropProps } from 'models/drop'
import TokenImage from 'components/TokenImage'
import LinkToScan from 'components/LinkToScan'
import ButtonAddressProfile from 'components/ButtonAddressProfile'
import 'styles/owner.css'
import 'styles/address-owner.css'

/**
* @param {PropTypes.InferProps<AddressOwner.propTypes>} props
Expand All @@ -30,7 +30,7 @@ function AddressOwner({
)

return (
<div className="owner">
<div className="address-owner">
<div className="owner-name">
{settings && settings.openProfiles
? (
Expand Down
215 changes: 122 additions & 93 deletions src/components/EventsOwners.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ import { useMemo, useState } from 'react'
import { chunks } from 'utils/array'
import { DropProps } from 'models/drop'
import {
filterInCommon,
getAddressInCommonAddresses,
getAddressInCommonEventIds,
sortInCommonEntries,
} from 'models/in-common'
import ButtonLink from 'components/ButtonLink'
import Card from 'components/Card'
Expand Down Expand Up @@ -44,133 +42,165 @@ function inverseOwnersSortedEntries(owners) {
* @param {PropTypes.InferProps<EventsOwners.propTypes>} props
*/
function EventsOwners({
children,
owners,
inCommon: initialInCommon = {},
events = {},
eventsOwners,
inCommon,
events,
all = false,
}) {
/**
* @type {ReturnType<typeof useState<boolean>>}
*/
const [showAll, setShowAll] = useState(all)

let ownersEntries = useMemo(
() => inverseOwnersSortedEntries(owners),
[owners]
let ownersEvents = useMemo(
() => inverseOwnersSortedEntries(eventsOwners),
[eventsOwners]
)

const ownersEventIds = Object.keys(owners).map(
(rawEventId) => parseInt(rawEventId)
const eventIds = useMemo(
() => Object.keys(eventsOwners).map(
(rawEventId) => parseInt(rawEventId)
),
[eventsOwners]
)

const eventsTotal = ownersEventIds.length
const ownersTotal = ownersEntries.length
const ownersTotal = ownersEvents.length
const eventsTotal = eventIds.length

/**
* @type {string[]}
*/
const inCommonAddresses = useMemo(
const inCommonOwnersTotal = useMemo(
() => {
const inCommonAddresses = []
for (const [ownerAddress, ownerEventIds] of ownersEntries) {
for (const [ownerAddress, ownerEventIds] of ownersEvents) {
if (ownerEventIds.length === eventsTotal) {
inCommonAddresses.push(ownerAddress)
}
}
return inCommonAddresses
return inCommonAddresses.length
},
[ownersEntries, eventsTotal]
[ownersEvents, eventsTotal]
)

const inCommonOwnersTotal = inCommonAddresses.length

if (ownersTotal > inCommonOwnersTotal && !showAll && !all) {
ownersEntries = ownersEntries.slice(0, inCommonOwnersTotal)
ownersEvents = ownersEvents.slice(0, inCommonOwnersTotal)
}

const ownersEntriesChunks = chunks(ownersEntries, 10)

const inCommonEntries = useMemo(
() => initialInCommon == null ? [] : sortInCommonEntries(
Object
.entries(filterInCommon(initialInCommon))
.map(([rawEventId, addresses]) => [parseInt(rawEventId), addresses])
),
[initialInCommon]
)

const inCommon = Object.fromEntries(inCommonEntries)
const ownersEventsChunks = chunks(ownersEvents, 10)

return (
<div className="events-owners">
<Card>
{(all || showAll) && <h4>{ownersTotal} collector{ownersTotal === 1 ? '' : 's'}</h4>}
{!all && !showAll && <h4>{inCommonOwnersTotal} collector{inCommonOwnersTotal === 1 ? '' : 's'} in common</h4>}
{children}
<div className="in-common-owners">
{ownersEntriesChunks.map(
(ownersEntriesChunk, chunkIndex) => (
<ul key={chunkIndex} className="owners">
{ownersEntriesChunk.map(
([address, eventIds]) => {
const inCommonEventIds = getAddressInCommonEventIds(
inCommon,
address
)
const inCommonAddresses = getAddressInCommonAddresses(
inCommon,
inCommonEventIds,
address
)
return (
<li key={address} className="owners-item">
<AddressOwner
address={address}
events={events}
eventIds={ownersEventIds}
ownerEventIds={eventIds}
inCommonEventIds={inCommonEventIds}
inCommonAddresses={inCommonAddresses}
linkToScan={false}
/>
</li>
)
}
)}
{chunkIndex + 1 === ownersEntriesChunks.length && ownersTotal > inCommonOwnersTotal && !all && (
<li key="show-more">
<div className="show-more">
<ButtonLink onClick={() => setShowAll((prevShowAll) => !prevShowAll)}>
{showAll ? (inCommonOwnersTotal === 0 ? 'hide all' : `show ${inCommonOwnersTotal}${all ? '' : ' in common'}`) : `show all ${ownersTotal}`}
</ButtonLink>
</div>
{(all || showAll) && (
<h4>{ownersTotal} collector{ownersTotal === 1 ? '' : 's'}</h4>
)}
{!all && !showAll && (
<h4>
{inCommonOwnersTotal}{' '}
collector{inCommonOwnersTotal === 1 ? '' : 's'}{' '}
in common
</h4>
)}
<div className="events-owners-chunks">
{ownersEventsChunks.map((ownersEventsChunk, chunkIndex) => (
<ul key={chunkIndex}>
{ownersEventsChunk.map(([owner, ownerEventIds]) => {
const inCommonEventIds = getAddressInCommonEventIds(
inCommon,
owner
)
const inCommonAddresses = getAddressInCommonAddresses(
inCommon,
inCommonEventIds,
owner
)
return (
<li key={owner} className="owner-list-item">
<AddressOwner
address={owner}
events={events}
eventIds={eventIds}
ownerEventIds={ownerEventIds}
inCommonEventIds={inCommonEventIds}
inCommonAddresses={inCommonAddresses}
linkToScan={false}
/>
</li>
)}
</ul>
)
)}
)
})}
{(
chunkIndex + 1 === ownersEventsChunks.length &&
ownersTotal > inCommonOwnersTotal &&
!all
) && (
<li key="show-more">
<div className="show-more">
<ButtonLink
onClick={() => setShowAll((prevShowAll) => !prevShowAll)}
>
{
showAll
? (
inCommonOwnersTotal === 0
? 'hide all'
: `show ${inCommonOwnersTotal}` +
`${all ? '' : ' in common'}`
)
: `show all ${ownersTotal}`
}
</ButtonLink>
</div>
</li>
)}
</ul>
))}
</div>
{inCommonOwnersTotal === 0 && ownersEntries.length === 0 && (
{inCommonOwnersTotal === 0 && ownersTotal === 0 && (
<div className="show-more">
<ButtonLink onClick={() => setShowAll((prevShowAll) => !prevShowAll)}>
{showAll ? (inCommonOwnersTotal === 0 ? 'hide all' : `show ${inCommonOwnersTotal}${all ? '' : ' in common'}`) : `show all ${ownersTotal}`}
<ButtonLink
onClick={() => setShowAll((prevShowAll) => !prevShowAll)}
>
{
showAll
? (
inCommonOwnersTotal === 0
? 'hide all'
: `show ${inCommonOwnersTotal}` +
`${all ? '' : ' in common'}`
)
: `show all ${ownersTotal}`
}
</ButtonLink>
</div>
)}
{ownersEntries.length > 0 && (
{ownersTotal > 0 && (
<ButtonGroup right={true}>
<ButtonExportAddressCsv
filename={`collectors-drop${Object.keys(events).length === 1 ? '' : 's'}-${Object.keys(events).join('+')}`}
name={Object.keys(events).length === 1 ? Object.values(events)[0].name : undefined}
addresses={ownersEntries.map(([address]) => address)}
title={`Generates CSV file with collectors in common between drop${Object.keys(events).length === 1 ? '' : 's'} #${Object.keys(events).join(', #')}`}
filename={
`collectors-` +
`drop${eventsTotal === 1 ? '' : 's'}-` +
`${eventIds.join('+')}`
}
name={
eventsTotal === 1
? events[eventIds[0]].name
: undefined
}
addresses={ownersEvents.map(([address]) => address)}
title={
`Generates CSV file with collectors in common ` +
`between drop${eventsTotal === 1 ? '' : 's'} ` +
`#${eventIds.join(', #')}`
}
/>
<ButtonExpand
link={true}
title={`Expands${showAll ? ' all' : ''} collectors${showAll ? '' : ' in common'} between drop${Object.keys(events).length === 1 ? '' : 's'} #${Object.keys(events).join(', #')}`}
addresses={ownersEntries.map(([ownerAddress]) => ownerAddress)}
eventIds={ownersEventIds}
title={
`Expands${showAll ? ' all' : ''} ` +
`collectors${showAll ? '' : ' in common'} between ` +
`drop${eventsTotal === 1 ? '' : 's'} ` +
`#${eventIds.join(', #')}`
}
addresses={ownersEvents.map(([ownerAddress]) => ownerAddress)}
eventIds={eventIds}
/>
</ButtonGroup>
)}
Expand All @@ -180,8 +210,7 @@ function EventsOwners({
}

EventsOwners.propTypes = {
children: PropTypes.node,
owners: PropTypes.objectOf(
eventsOwners: PropTypes.objectOf(
PropTypes.arrayOf(
PropTypes.string.isRequired
).isRequired
Expand All @@ -190,7 +219,7 @@ EventsOwners.propTypes = {
PropTypes.arrayOf(
PropTypes.string.isRequired
).isRequired
),
).isRequired,
events: PropTypes.objectOf(
PropTypes.shape(DropProps).isRequired
).isRequired,
Expand Down
37 changes: 24 additions & 13 deletions src/pages/Events.js
Original file line number Diff line number Diff line change
Expand Up @@ -1107,22 +1107,33 @@ function Events() {
/**
* @type {Record<number, string[]>}
*/
let inCommon = {}
if (status === STATUS_LOADING_COMPLETE) {
inCommon = mergeAllInCommon(
Object.values(eventData).map(
(oneEventData) => oneEventData?.inCommon ?? {}
),
all
)
}
const inCommon = useMemo(
() => {
if (status !== STATUS_LOADING_COMPLETE) {
return {}
}
return mergeAllInCommon(
Object.values(eventData).map(
(oneEventData) => oneEventData?.inCommon ?? {}
),
all
)
},
[eventData, status, all]
)

/**
* @type {Record<number, { id: number; name: string; description?: string; image_url: string; original_url: string; city: string | null; country: string | null; start_date: string; end_date: string; expiry_date: string }>}
*/
const allEvents = Object.values(eventData).reduce(
(allEvents, data) => ({ ...allEvents, ...data.events }),
{}
const allEvents = useMemo(
() => Object.values(eventData).reduce(
(allEvents, data) => ({
...allEvents,
...data.events,
}),
{}
),
[eventData]
)

const refreshCache = () => {
Expand Down Expand Up @@ -1407,7 +1418,7 @@ function Events() {
</>
)}
<EventsOwners
owners={owners}
eventsOwners={owners}
inCommon={inCommon}
events={allEvents}
all={all}
Expand Down
10 changes: 5 additions & 5 deletions src/styles/owner.css → src/styles/address-owner.css
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
.owner {
.address-owner {
display: flex;
gap: .5rem;
justify-content: space-between;
}

.owner .owner-name {
.address-owner .owner-name {
flex-grow: 1;
width: 25.8rem;
}

.owner-event-empty {
.address-owner .owner-event-empty {
display: inline-block;
width: 18px;
height: 18px;
}

.owner-scan {
.address-owner .owner-scan {
width: 16px;
height: 16px;
background:
Expand All @@ -32,7 +32,7 @@
cursor: pointer;
}

.owner-scan:hover {
.address-owner .owner-scan:hover {
background:
linear-gradient(to right, #7d73e2 2px, transparent 2px) 0 0,
linear-gradient(to right, #7d73e2 2px, transparent 2px) 0 100%,
Expand Down
Loading

0 comments on commit 39063e1

Please sign in to comment.