Skip to content

Commit c6e6a49

Browse files
Feat: Add item filtering by mapping status (#3164)
* feat: Add support for the migration completion flag in the collections * feat: Add item filtering by mapping * feat: Add item filtering by mapping status * fix: Set min-width for the migration banner * fix: dev file
1 parent ea74ff2 commit c6e6a49

File tree

7 files changed

+71
-27
lines changed

7 files changed

+71
-27
lines changed

src/components/CollectionProvider/CollectionProvider.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ export default class CollectionProvider extends React.PureComponent<Props> {
88
}
99

1010
fetchCollectionItems(itemsPage: number | number[] = DEFAULT_ITEMS_PAGE) {
11-
const { id, onFetchCollectionItems, itemsPageSize, fetchOptions } = this.props
11+
const { id, onFetchCollectionItems, itemsPageSize, fetchCollectionItemsOptions } = this.props
1212
if (id) {
13-
onFetchCollectionItems(id, { page: itemsPage, limit: itemsPageSize || DEFAULT_ITEMS_PAGE_SIZE, ...fetchOptions })
13+
onFetchCollectionItems(id, { page: itemsPage, limit: itemsPageSize || DEFAULT_ITEMS_PAGE_SIZE, ...fetchCollectionItemsOptions })
1414
}
1515
}
1616

@@ -31,7 +31,7 @@ export default class CollectionProvider extends React.PureComponent<Props> {
3131
itemsPage,
3232
itemsPageSize,
3333
itemSelected,
34-
fetchOptions,
34+
fetchCollectionItemsOptions,
3535
paginatedItems,
3636
onFetchCollection,
3737
onChangePage
@@ -70,7 +70,7 @@ export default class CollectionProvider extends React.PureComponent<Props> {
7070

7171
// logic to fetch the new pages requested
7272
const hasChangedPage = !equal(itemsPage, prevProps.itemsPage)
73-
const hasChangeFilter = !equal(fetchOptions, prevProps.fetchOptions)
73+
const hasChangeFilter = !equal(fetchCollectionItemsOptions, prevProps.fetchCollectionItemsOptions)
7474
if (id && ((itemsPage && hasChangedPage) || hasChangeFilter)) {
7575
const prevPages = prevProps.itemsPage
7676
this.fetchCollectionItems(

src/components/CollectionProvider/CollectionProvider.types.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Dispatch } from 'redux'
2-
import { FetchCollectionsParams } from 'lib/api/builder'
2+
import { FetchCollectionItemsParams } from 'lib/api/builder'
33
import { Collection } from 'modules/collection/types'
44
import { fetchCollectionRequest, FetchCollectionRequestAction } from 'modules/collection/actions'
55
import { Item } from 'modules/item/types'
@@ -19,7 +19,7 @@ export type Props = {
1919
itemSelected?: string | null
2020
itemsPage?: number | number[]
2121
itemsPageSize?: number
22-
fetchOptions?: Pick<FetchCollectionsParams, 'status' | 'synced'>
22+
fetchCollectionItemsOptions?: FetchCollectionItemsParams
2323
curation: CollectionCuration | null
2424
itemCurations: ItemCuration[] | null
2525
isLoading: boolean

src/components/ItemEditorPage/LeftPanel/LeftPanel.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ export default class LeftPanel extends React.PureComponent<Props, State> {
195195
itemSelected={selectedItemId}
196196
itemsPage={pages}
197197
itemsPageSize={LEFT_PANEL_PAGE_SIZE}
198-
fetchOptions={{ status: isReviewing ? CurationStatus.PENDING : undefined }}
198+
fetchCollectionItemsOptions={{ status: isReviewing ? CurationStatus.PENDING : undefined }}
199199
onChangePage={page => this.setState({ pages: [page] })}
200200
>
201201
{({ paginatedCollections, collection, paginatedItems: collectionItems, initialPage: collectionInitialPage, isLoading }) => {

src/components/ThirdPartyCollectionDetailPage/ThirdPartyCollectionDetailPage.module.css

+1
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@
213213
}
214214

215215
.migrationBanner {
216+
min-width: 1116px;
216217
color: black;
217218
display: flex;
218219
align-items: center;

src/components/ThirdPartyCollectionDetailPage/ThirdPartyCollectionDetailPage.tsx

+44-16
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { Props, PAGE_SIZE } from './ThirdPartyCollectionDetailPage.types'
3535
import { CollectionItemHeader } from './CollectionItemHeader'
3636
import { CollectionItemHeaderV2 } from './CollectionItemHeaderV2'
3737
import styles from './ThirdPartyCollectionDetailPage.module.css'
38+
import { ItemMappingStatus } from 'lib/api/builder'
3839

3940
const Info = ({ children, title, info }: { children: React.ReactNode; title: string; info?: string }) => (
4041
<div className={styles.info}>
@@ -45,6 +46,14 @@ const Info = ({ children, title, info }: { children: React.ReactNode; title: str
4546
</div>
4647
)
4748

49+
enum ItemStatus {
50+
ALL = 'ALL',
51+
SYNCED = 'SYNCED',
52+
UNSYNCED = 'UNSYNCED',
53+
MIGRATION_REQUIRED = 'MIGRATION_REQUIRED',
54+
MAPPING_PENDING = 'MAPPING_PENDING'
55+
}
56+
4857
export default function ThirdPartyCollectionDetailPage({
4958
currentPage,
5059
wallet,
@@ -62,7 +71,7 @@ export default function ThirdPartyCollectionDetailPage({
6271
const [page, setPage] = useState(currentPage)
6372
const [showSelectAllPages, setShowSelectAllPages] = useState(false)
6473
const [shouldFetchAllPages, setShouldFetchAllPages] = useState(false)
65-
const [filters, setFilters] = useState<Record<string, any>>({})
74+
const [itemStatus, setItemStatus] = useState<ItemStatus>(ItemStatus.ALL)
6675
const history = useHistory()
6776

6877
useEffect(() => {
@@ -72,9 +81,6 @@ export default function ThirdPartyCollectionDetailPage({
7281
}, [])
7382

7483
useEffect(() => {
75-
if (thirdParty && thirdParty.availableSlots === undefined && !isLoadingAvailableSlots) {
76-
onFetchAvailableSlots(thirdParty.id)
77-
}
7884
// update the state if the page query param changes
7985
if (currentPage !== page) {
8086
setPage(currentPage)
@@ -89,7 +95,7 @@ export default function ThirdPartyCollectionDetailPage({
8995
setSelectedItems(selectedItems)
9096
setShowSelectAllPages(false)
9197
}
92-
}, [page, shouldFetchAllPages, items, thirdParty, isLoadingAvailableSlots, onFetchAvailableSlots, currentPage])
98+
}, [page, shouldFetchAllPages, items, thirdParty, currentPage])
9399

94100
const handleNewItems = useCallback(() => {
95101
onOpenModal('CreateItemsModal', { collectionId: collection!.id })
@@ -173,11 +179,38 @@ export default function ThirdPartyCollectionDetailPage({
173179

174180
const handleChangeStatus = useCallback(
175181
(_event: React.SyntheticEvent<HTMLElement, Event>, { value }: DropdownProps) => {
176-
setFilters({ synced: value as boolean })
182+
setItemStatus(value as ItemStatus)
177183
},
178-
[setFilters]
184+
[setItemStatus]
179185
)
180186

187+
const itemStatusOptions = [
188+
{ value: ItemStatus.ALL, text: t('third_party_collection_detail_page.synced_filter.all') },
189+
{ value: ItemStatus.SYNCED, text: t('item_status.synced') },
190+
{ value: ItemStatus.UNSYNCED, text: t('item_status.unsynced') },
191+
...(!collection?.isMappingComplete
192+
? [
193+
{ value: ItemStatus.MIGRATION_REQUIRED, text: t('item_status.pending_migration') },
194+
{ value: ItemStatus.MAPPING_PENDING, text: t('item_status.pending_mapping') }
195+
]
196+
: [])
197+
]
198+
199+
const itemFilters = useMemo(() => {
200+
switch (itemStatus) {
201+
case ItemStatus.SYNCED:
202+
return { synced: true }
203+
case ItemStatus.UNSYNCED:
204+
return { synced: false }
205+
case ItemStatus.MIGRATION_REQUIRED:
206+
return { mappingStatus: ItemMappingStatus.UNPUBLISHED_MAPPING }
207+
case ItemStatus.MAPPING_PENDING:
208+
return { mappingStatus: ItemMappingStatus.MISSING_MAPPING }
209+
default:
210+
return {}
211+
}
212+
}, [itemStatus])
213+
181214
const renderPage = useCallback(
182215
(thirdParty: ThirdParty, allItems: Item[], paginatedItems: Item[], onFetchCollectionItemsPages: typeof fetchCollectionItemsRequest) => {
183216
const allSelectedItems = allItems.filter(item => selectedItems[item.id])
@@ -257,13 +290,8 @@ export default function ThirdPartyCollectionDetailPage({
257290
<Dropdown
258291
className={styles.syncedStatusList}
259292
direction="left"
260-
value={filters.synced}
261-
placeholder={t('third_party_collection_detail_page.synced_filter.all')}
262-
options={[
263-
{ value: undefined, text: t('third_party_collection_detail_page.synced_filter.all') },
264-
{ value: true, text: t('third_party_collection_detail_page.synced_filter.synced') },
265-
{ value: false, text: t('third_party_collection_detail_page.synced_filter.unsynced') }
266-
]}
293+
value={itemStatus}
294+
options={itemStatusOptions}
267295
onChange={handleChangeStatus}
268296
/>
269297
</div>
@@ -365,13 +393,13 @@ export default function ThirdPartyCollectionDetailPage({
365393
areAllSelected,
366394
handleChangeStatus,
367395
handleClearSelection,
368-
filters
396+
itemStatus
369397
]
370398
)
371399

372400
const shouldRender = hasAccess && collection
373401
return (
374-
<CollectionProvider id={collection?.id} itemsPage={page} itemsPageSize={PAGE_SIZE} fetchOptions={filters}>
402+
<CollectionProvider id={collection?.id} itemsPage={page} itemsPageSize={PAGE_SIZE} fetchCollectionItemsOptions={itemFilters}>
375403
{({ isLoading: isLoadingCollectionData, items, paginatedItems, onFetchCollectionItemsPages }) => (
376404
<LoggedInDetailPage
377405
className={styles.main}

src/lib/api/builder.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,19 @@ export type FetchCollectionsParams = {
5151
limit?: number
5252
}
5353

54+
export enum ItemMappingStatus {
55+
MISSING_MAPPING = 'missing_mapping',
56+
UNPUBLISHED_MAPPING = 'unpublished_mapping'
57+
}
58+
59+
export type FetchCollectionItemsParams = {
60+
status?: CurationStatus
61+
synced?: boolean
62+
mappingStatus?: ItemMappingStatus
63+
page?: number
64+
limit?: number
65+
}
66+
5467
export type RemoteItem = {
5568
id: string // uuid
5669
name: string
@@ -786,7 +799,7 @@ export class BuilderAPI extends BaseAPI {
786799
return fromRemoteItem(remoteItem)
787800
}
788801

789-
async fetchCollectionItems(collectionId: string, options: FetchCollectionsParams = {}) {
802+
async fetchCollectionItems(collectionId: string, options: FetchCollectionItemsParams = {}) {
790803
const { page, limit } = options
791804
const remoteResponse = await this.request('get', `/collections/${collectionId}/items`, { params: options, retry: retryParams })
792805
if (page && limit && remoteResponse.results) {

src/modules/item/actions.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { action } from 'typesafe-actions'
22
import { ChainId } from '@dcl/schemas'
33
import { buildTransactionPayload } from 'decentraland-dapps/dist/modules/transaction/utils'
44
import { PaginationStats } from 'lib/api/pagination'
5-
import { FetchCollectionsParams } from 'lib/api/builder'
5+
import { FetchCollectionItemsParams } from 'lib/api/builder'
66
import { Collection } from 'modules/collection/types'
77
import { BuiltFile, Item, BlockchainRarity } from './types'
88

@@ -63,12 +63,14 @@ export const fetchCollectionItemsRequest = (
6363
limit,
6464
status,
6565
synced,
66+
mappingStatus,
6667
overridePaginationData = true
67-
}: Pick<FetchCollectionsParams, 'limit' | 'status' | 'synced'> & {
68+
}: Omit<FetchCollectionItemsParams, 'page'> & {
6869
page?: number | number[]
6970
overridePaginationData?: boolean
7071
} = {}
71-
) => action(FETCH_COLLECTION_ITEMS_REQUEST, { collectionId, overridePaginationData, options: { limit, status, synced, page } })
72+
) =>
73+
action(FETCH_COLLECTION_ITEMS_REQUEST, { collectionId, overridePaginationData, options: { limit, status, synced, mappingStatus, page } })
7274
export const fetchCollectionItemsSuccess = (collectionId: string, items: Item[], paginationStats?: PaginationStats) =>
7375
action(FETCH_COLLECTION_ITEMS_SUCCESS, { items, paginationIndex: collectionId, paginationStats })
7476
export const fetchCollectionItemsFailure = (collectionId: string, error: string) =>

0 commit comments

Comments
 (0)