From f8c99272ceb1d5ded34ab949613cc56ee07abff5 Mon Sep 17 00:00:00 2001 From: LautaroPetaccio Date: Thu, 3 Oct 2024 12:13:05 -0300 Subject: [PATCH 1/2] fix: Load LW collections separetely from their items --- .../CollectionProvider.container.ts | 4 +- .../CollectionProvider/CollectionProvider.tsx | 6 +- .../CollectionProvider.types.ts | 20 +- .../ItemEditorPage/LeftPanel/LeftPanel.tsx | 11 +- .../CreateThirdPartyCollectionModal.tsx | 8 +- ...hirdPartyCollectionDetailPage.container.ts | 7 +- .../ThirdPartyCollectionDetailPage.module.css | 22 ++ .../ThirdPartyCollectionDetailPage.tsx | 230 ++++++++++-------- .../ThirdPartyImage.module.css | 2 +- src/routing/locations.ts | 7 +- 10 files changed, 192 insertions(+), 125 deletions(-) diff --git a/src/components/CollectionProvider/CollectionProvider.container.ts b/src/components/CollectionProvider/CollectionProvider.container.ts index f2326fdbb..c68d31e63 100644 --- a/src/components/CollectionProvider/CollectionProvider.container.ts +++ b/src/components/CollectionProvider/CollectionProvider.container.ts @@ -31,8 +31,8 @@ const mapState = (state: RootState, ownProps: OwnProps): MapStateProps => { itemCurations, curation, isConnected: isConnected(state), - isLoading: - isLoadingType(getLoading(state), FETCH_COLLECTION_REQUEST) || + isLoadingCollection: isLoadingType(getLoading(state), FETCH_COLLECTION_REQUEST), + isLoadingCollectionItems: isLoadingType(getLoadingItemCurations(state), FETCH_ITEM_CURATIONS_REQUEST) || isLoadingType(getLoadingItems(state), FETCH_COLLECTION_ITEMS_REQUEST) } diff --git a/src/components/CollectionProvider/CollectionProvider.tsx b/src/components/CollectionProvider/CollectionProvider.tsx index 4ef17ce8a..effacb481 100644 --- a/src/components/CollectionProvider/CollectionProvider.tsx +++ b/src/components/CollectionProvider/CollectionProvider.tsx @@ -87,7 +87,8 @@ export default class CollectionProvider extends React.PureComponent { paginatedItems, curation, itemCurations, - isLoading, + isLoadingCollection, + isLoadingCollectionItems, children, onFetchCollectionItems } = this.props @@ -102,7 +103,8 @@ export default class CollectionProvider extends React.PureComponent { paginatedCollections, curation, itemCurations, - isLoading, + isLoadingCollection, + isLoadingCollectionItems, onFetchCollectionItemsPages: onFetchCollectionItems })} diff --git a/src/components/CollectionProvider/CollectionProvider.types.ts b/src/components/CollectionProvider/CollectionProvider.types.ts index a4534e7b3..063b9c812 100644 --- a/src/components/CollectionProvider/CollectionProvider.types.ts +++ b/src/components/CollectionProvider/CollectionProvider.types.ts @@ -22,7 +22,8 @@ export type Props = { fetchCollectionItemsOptions?: FetchCollectionItemsParams curation: CollectionCuration | null itemCurations: ItemCuration[] | null - isLoading: boolean + isLoadingCollection: boolean + isLoadingCollectionItems: boolean isConnected: boolean children: ({ collection, @@ -31,7 +32,8 @@ export type Props = { curation, itemCurations, initialPage, - isLoading, + isLoadingCollection, + isLoadingCollectionItems, onFetchCollectionItemsPages }: { collection: Collection | null @@ -41,7 +43,8 @@ export type Props = { curation: CollectionCuration | null itemCurations: ItemCuration[] | null initialPage: number - isLoading: boolean + isLoadingCollection: boolean + isLoadingCollectionItems: boolean onFetchCollectionItemsPages: typeof fetchCollectionItemsRequest }) => React.ReactNode onFetchCollection: typeof fetchCollectionRequest @@ -51,7 +54,16 @@ export type Props = { export type MapStateProps = Pick< Props, - 'id' | 'collection' | 'items' | 'isLoading' | 'isConnected' | 'curation' | 'itemCurations' | 'paginatedItems' | 'paginatedCollections' + | 'id' + | 'collection' + | 'items' + | 'isLoadingCollection' + | 'isLoadingCollectionItems' + | 'isConnected' + | 'curation' + | 'itemCurations' + | 'paginatedItems' + | 'paginatedCollections' > export type MapDispatchProps = Pick export type MapDispatch = Dispatch diff --git a/src/components/ItemEditorPage/LeftPanel/LeftPanel.tsx b/src/components/ItemEditorPage/LeftPanel/LeftPanel.tsx index e1e9eb6ce..30f60f44b 100644 --- a/src/components/ItemEditorPage/LeftPanel/LeftPanel.tsx +++ b/src/components/ItemEditorPage/LeftPanel/LeftPanel.tsx @@ -208,12 +208,15 @@ export default class LeftPanel extends React.PureComponent { collection, paginatedItems: collectionItems, initialPage: collectionInitialPage, - isLoading, + isLoadingCollection, + isLoadingCollectionItems, itemCurations }) => { const items = this.getItems(collection, collectionItems, itemCurations) const isCollectionTab = this.isCollectionTabActive() - const showLoader = isLoading && ((isCollectionTab && collections.length === 0) || (!isCollectionTab && items.length === 0)) + const showLoader = + (isLoadingCollection || isLoadingCollectionItems) && + ((isCollectionTab && collections.length === 0) || (!isCollectionTab && items.length === 0)) const initialPage = selectedCollectionId && collection ? collectionInitialPage : this.state.initialPage if (showLoader) { return @@ -262,7 +265,7 @@ export default class LeftPanel extends React.PureComponent { hasHeader={items.length > 0} selectedCollectionId={selectedCollectionId} onLoadPage={this.loadPage} - isLoading={isLoading} + isLoading={isLoadingCollection} /> ) : null} {showItems ? ( @@ -280,7 +283,7 @@ export default class LeftPanel extends React.PureComponent { onSetItems={onSetItems} wearableController={wearableController} initialPage={initialPage} - isLoading={isLoading || isLoadingOrphanItems} + isLoading={isLoadingCollectionItems || isLoadingOrphanItems} onLoadRandomPage={() => this.loadRandomPage(items)} onLoadPage={this.loadPage} onSetReviewedItems={onSetReviewedItems} diff --git a/src/components/Modals/CreateThirdPartyCollectionModal/CreateThirdPartyCollectionModal.tsx b/src/components/Modals/CreateThirdPartyCollectionModal/CreateThirdPartyCollectionModal.tsx index 6f4791d03..f54064e75 100644 --- a/src/components/Modals/CreateThirdPartyCollectionModal/CreateThirdPartyCollectionModal.tsx +++ b/src/components/Modals/CreateThirdPartyCollectionModal/CreateThirdPartyCollectionModal.tsx @@ -263,7 +263,7 @@ export const CreateThirdPartyCollectionModal: FC = (props: Props) => { />
- {thirdParties.length && !isLinkedWearablesPaymentsEnabled && ( + {thirdParties.length && !isLinkedWearablesPaymentsEnabled ? ( = (props: Props) => { disabled={isLoading} value={selectedThirdParty?.id} /> - )} - {isLinkedWearablesPaymentsEnabled && collectionNameField} + ) : null} + {isLinkedWearablesPaymentsEnabled ? collectionNameField : undefined} {isLinkedWearablesV2Enabled && (
{thirdPartyContractNetworkOptions.length > 0 && !isLinkedWearablesPaymentsEnabled ? ( @@ -315,7 +315,7 @@ export const CreateThirdPartyCollectionModal: FC = (props: Props) => { )}
)} - {!isLinkedWearablesPaymentsEnabled && collectionNameField} + {!isLinkedWearablesPaymentsEnabled ? collectionNameField : null} {!isLinkedWearablesV2Enabled && ( { thirdParty: collection && isThirdPartyCollection(collection) ? getCollectionThirdParty(state, collection) : null, authorizations: getAuthorizations(state), isLoading: - isLoadingType(getLoadingCollection(state), FETCH_COLLECTIONS_REQUEST) || isLoadingType(getLoadingCollection(state), DELETE_COLLECTION_REQUEST) || - isLoadingType(getLoadingItem(state), FETCH_COLLECTION_ITEMS_REQUEST) || isLoadingThirdParties(state) || !!(isThirdParty && collection && isLoadingThirdParty(state, extractThirdPartyId(collection.urn))), isLoadingAvailableSlots: isFetchingAvailableSlots(state), diff --git a/src/components/ThirdPartyCollectionDetailPage/ThirdPartyCollectionDetailPage.module.css b/src/components/ThirdPartyCollectionDetailPage/ThirdPartyCollectionDetailPage.module.css index b3c4efe09..97aa640e0 100644 --- a/src/components/ThirdPartyCollectionDetailPage/ThirdPartyCollectionDetailPage.module.css +++ b/src/components/ThirdPartyCollectionDetailPage/ThirdPartyCollectionDetailPage.module.css @@ -1,3 +1,13 @@ +/* Login wrapper */ + +.main, +.main > :global(.ui.container) { + display: flex; + flex-direction: column; + min-height: 0; + flex: 1; +} + .slots { font-weight: bold; text-transform: uppercase; @@ -146,6 +156,8 @@ margin-top: 16px; gap: 16px; min-width: 1400px; + flex: 1; + min-width: 0; } .info { @@ -285,3 +297,13 @@ .standardBadge { background-color: #43404a; } + +/* Loader */ + +.loader { + display: flex; + justify-content: center; + align-items: center; + min-height: 0; + flex: 1; +} diff --git a/src/components/ThirdPartyCollectionDetailPage/ThirdPartyCollectionDetailPage.tsx b/src/components/ThirdPartyCollectionDetailPage/ThirdPartyCollectionDetailPage.tsx index f925d78c5..b95e305e9 100644 --- a/src/components/ThirdPartyCollectionDetailPage/ThirdPartyCollectionDetailPage.tsx +++ b/src/components/ThirdPartyCollectionDetailPage/ThirdPartyCollectionDetailPage.tsx @@ -21,6 +21,7 @@ import { extractThirdPartyId } from 'lib/urn' import { isUserManagerOfThirdParty } from 'modules/thirdParty/utils' import { Item } from 'modules/item/types' import { ThirdParty } from 'modules/thirdParty/types' +import { CollectionType } from 'modules/collection/types' import { fetchCollectionItemsRequest } from 'modules/item/actions' import LoggedInDetailPage from 'components/LoggedInDetailPage' import CollectionProvider from 'components/CollectionProvider' @@ -126,7 +127,7 @@ export default function ThirdPartyCollectionDetailPage({ if (isComingFromTheCollectionsPage) { history.goBack() } else { - history.push(locations.collections()) + history.push(locations.collections(CollectionType.THIRD_PARTY)) } }, [history, isComingFromTheCollectionsPage]) @@ -231,7 +232,13 @@ export default function ThirdPartyCollectionDetailPage({ }, [itemStatus]) const renderPage = useCallback( - (thirdParty: ThirdParty, allItems: Item[], paginatedItems: Item[], onFetchCollectionItemsPages: typeof fetchCollectionItemsRequest) => { + ( + thirdParty: ThirdParty, + allItems: Item[], + paginatedItems: Item[], + isLoadingCollectionItems: boolean, + onFetchCollectionItemsPages: typeof fetchCollectionItemsRequest + ) => { const allSelectedItems = allItems.filter(item => selectedItems[item.id]) const selectedItemsCount = allSelectedItems.length const isCollectionLinked = Boolean(collection?.linkedContractAddress && collection?.linkedContractNetwork) @@ -259,11 +266,17 @@ export default function ThirdPartyCollectionDetailPage({ {!collection.isPublished && }
-
Linked Wearables
+
+ {t('third_party_collection_detail_page.type')} +
{thirdParty.isProgrammatic ? ( -
Programmatic
+
+ {t('third_party_collection_detail_page.programmatic')} +
) : ( -
Standard
+
+ {t('third_party_collection_detail_page.standard')} +
)}
@@ -312,108 +325,116 @@ export default function ThirdPartyCollectionDetailPage({ )}
- {(collection.itemCount ?? 0) > 0 && ( -
- {paginatedItems.length > 0 && ( -
- {t('third_party_collection_detail_page.search_info', { - page: (page - 1) * PAGE_SIZE + 1, - pageTotal: Math.min(total, page * PAGE_SIZE), - total - })} -
- )} - + {isLoadingCollectionItems ? ( +
+
- )} - {paginatedItems.length ? ( + ) : ( <> - {selectedItemsCount > 0 ? ( -
- {t('third_party_collection_detail_page.selection', { count: selectedItemsCount })} -   - - {t('third_party_collection_detail_page.clear_selection')} - - .   - {showSelectAllPages && totalPages > 1 ? ( - handleSelectAllItems(onFetchCollectionItemsPages)}> - {t('third_party_collection_detail_page.select_all', { total })} - - ) : null} -   + {(collection.itemCount ?? 0) > 0 && ( +
+ {paginatedItems.length > 0 && ( +
+ {t('third_party_collection_detail_page.search_info', { + page: (page - 1) * PAGE_SIZE + 1, + pageTotal: Math.min(total, page * PAGE_SIZE), + total + })} +
+ )} +
- ) : null} + )} + {paginatedItems.length ? ( + <> + {selectedItemsCount > 0 ? ( +
+ {t('third_party_collection_detail_page.selection', { count: selectedItemsCount })} +   + + {t('third_party_collection_detail_page.clear_selection')} + + .   + {showSelectAllPages && totalPages > 1 ? ( + handleSelectAllItems(onFetchCollectionItemsPages)}> + {t('third_party_collection_detail_page.select_all', { total })} + + ) : null} +   +
+ ) : null} -
- {isThirdPartyV2Enabled && isCollectionLinked ? ( - , data: CheckboxProps) => - handleSelectPageChange(paginatedItems, data) - } - /> - ) : ( - , data: CheckboxProps) => - handleSelectPageChange(paginatedItems, data) - } - /> - )} +
+ {isThirdPartyV2Enabled && isCollectionLinked ? ( + , data: CheckboxProps) => + handleSelectPageChange(paginatedItems, data) + } + /> + ) : ( + , data: CheckboxProps) => + handleSelectPageChange(paginatedItems, data) + } + /> + )} - {paginatedItems.map(item => - isThirdPartyV2Enabled && isCollectionLinked ? ( - - ) : ( - - ) - )} + {paginatedItems.map(item => + isThirdPartyV2Enabled && isCollectionLinked ? ( + + ) : ( + + ) + )} - {totalPages > 1 ? ( - - ) : null} -
- - ) : ( -
-
- {isCollectionEmpty ? ( - <> -

{t('third_party_collection_detail_page.start_adding_items')}

-

{t('third_party_collection_detail_page.cant_remove')}

+ {totalPages > 1 ? ( + + ) : null} +
) : ( - <> -

{t('third_party_collection_detail_page.not_found')}

-

{t('third_party_collection_detail_page.try_again')}

- +
+
+ {isCollectionEmpty ? ( + <> +

{t('third_party_collection_detail_page.start_adding_items')}

+

{t('third_party_collection_detail_page.cant_remove')}

+ + ) : ( + <> +

{t('third_party_collection_detail_page.not_found')}

+

{t('third_party_collection_detail_page.try_again')}

+ + )} +
)} -
+ )}
@@ -436,15 +457,20 @@ export default function ThirdPartyCollectionDetailPage({ ) const shouldRender = hasAccess && collection + return ( - {({ isLoading: isLoadingCollectionData, items, paginatedItems, onFetchCollectionItemsPages }) => ( + {({ isLoadingCollection, isLoadingCollectionItems, items, paginatedItems, onFetchCollectionItemsPages }) => ( - {shouldRender && thirdParty ? renderPage(thirdParty, items, paginatedItems, onFetchCollectionItemsPages) : } + {shouldRender && thirdParty ? ( + renderPage(thirdParty, items, paginatedItems, isLoadingCollectionItems, onFetchCollectionItemsPages) + ) : ( + + )} )} diff --git a/src/components/ThirdPartyImage/ThirdPartyImage.module.css b/src/components/ThirdPartyImage/ThirdPartyImage.module.css index b45543ca4..818eef201 100644 --- a/src/components/ThirdPartyImage/ThirdPartyImage.module.css +++ b/src/components/ThirdPartyImage/ThirdPartyImage.module.css @@ -16,5 +16,5 @@ right: 0; width: 32px; height: 32px; - z-index: 20; + z-index: 1; } diff --git a/src/routing/locations.ts b/src/routing/locations.ts index c366b6f0e..f15a43952 100644 --- a/src/routing/locations.ts +++ b/src/routing/locations.ts @@ -30,7 +30,12 @@ export const locations = { activity: () => '/activity', settings: () => '/settings', sceneDetail: (projectId = ':projectId') => `/scenes/${projectId}`, - collections: () => '/collections', + collections: (type?: CollectionType) => { + if (type) { + return `/collections?section=${type === CollectionType.STANDARD ? 'standard_collections' : 'third_party_collections'}` + } + return '/collections' + }, itemDetail: (itemId = ':itemId') => `/items/${itemId}`, collectionDetail: (collectionId = ':collectionId', type: CollectionType = CollectionType.STANDARD, options?: CollectionDetailOptions) => { switch (type) { From 7d0beab9de7d43a0c0f07bc614ea3fa63810e025 Mon Sep 17 00:00:00 2001 From: LautaroPetaccio Date: Thu, 3 Oct 2024 12:20:03 -0300 Subject: [PATCH 2/2] fix: Loading of collection in CollectionDetailPage --- .../CollectionDetailPage/CollectionDetailPage.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/CollectionDetailPage/CollectionDetailPage.tsx b/src/components/CollectionDetailPage/CollectionDetailPage.tsx index e615a0eb1..3287c3432 100644 --- a/src/components/CollectionDetailPage/CollectionDetailPage.tsx +++ b/src/components/CollectionDetailPage/CollectionDetailPage.tsx @@ -439,11 +439,11 @@ export default function CollectionDetailPage({ const HUGE_PAGE_SIZE = 5000 // TODO: Remove this ASAP and implement pagination return ( - {({ isLoading: isLoadingCollectionData, items }) => ( + {({ isLoadingCollection, isLoadingCollectionItems, items }) => ( {hasAccess ? renderPage(items) : }