From 0e9d792121331bf97771ac7ae2a40d2331c1c761 Mon Sep 17 00:00:00 2001 From: Tyrone Tse Date: Thu, 8 Feb 2024 16:15:14 -0600 Subject: [PATCH 01/20] Check in working code with hardcoded collectionId urn:cid:aem:8f67c491-347a-4c50-a55b-aad555671b22 which is a collection that was created with the new api to create a collection https://adobe-aem-assets-delivery-experimental.redoc.ly/#operation/createCollection Once the List All Collections API is working can this code be updated to be completed --- .../adp-add-to-collection-modal.js | 8 + scripts/collections.js | 304 +++++++++++++++++- 2 files changed, 307 insertions(+), 5 deletions(-) diff --git a/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js b/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js index fd61cc56..921c329f 100644 --- a/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js +++ b/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js @@ -155,11 +155,19 @@ export async function openModal(items) { }); } +/*Todo Delete this getCollection */ + getCollection('urn:cid:aem:8f67c491-347a-4c50-a55b-aad555671b22') + .then((collection) => { + const { etag } = collection; + patchCollection(collectionId, etag, payload); + }); +/* getCollection(collectionId) .then((collection) => { const { etag } = collection; patchCollection(collectionId, etag, payload); }); +*/ resetDialogState(); } diff --git a/scripts/collections.js b/scripts/collections.js index 1f5c0788..e090982b 100644 --- a/scripts/collections.js +++ b/scripts/collections.js @@ -7,9 +7,14 @@ import { getPathParams, logError } from './scripts.js'; import { emitEvent, EventNames } from './events.js'; export function getCollectionIdFromURL() { + /* Todo remove this comment if (window.location.pathname.startsWith('/collection/')) { return getPathParams().at(-1); } + */ + if (window.location.pathname.includes('/collection/')) { + return getPathParams().at(-1); + } return undefined; } export function getCollectionID(item) { @@ -28,7 +33,8 @@ export function getAssetIdFromCollectionItem(assetItem) { return assetItem.id; } -async function getRequestHeaders() { +/* Todo delete this function when code is complete */ +async function getRequestHeadersOriginal() { const token = await getBearerToken(); return { 'Content-Type': 'application/json', @@ -37,6 +43,22 @@ async function getRequestHeaders() { }; } + + +async function getRequestHeaders() { + const token = await getBearerToken(); + /*Todo delete logging token*/ console.log('AuthToken ',token); + + return { + 'Content-Type': 'application/json', + 'x-api-key': await getAssetHandlerApiKey(), + 'Authorization': token, + 'x-ch-request': 'collection', + 'X-Adobe-Accept-Experimental': '1', + }; +} + +/* Todo delete this function when code is complete */ async function getRequestHeadersWithIfMatch(etag) { const token = await getBearerToken(); return { @@ -46,6 +68,18 @@ async function getRequestHeadersWithIfMatch(etag) { 'If-Match': etag, }; } + +async function getRequestHeadersWithIfMatchPatchJSON(etag) { + const token = await getBearerToken(); + return { + 'Content-Type': 'application/json-patch+json', + 'x-api-key': await getAssetHandlerApiKey(), + Authorization: token, + 'If-Match': etag, + }; +} + + /** * Constructs and returns the base URL for collections. * @@ -55,14 +89,28 @@ export function getBaseCollectionsUrl() { return `${getDeliveryEnvironment()}/adobe/collections`; } + /** + * Constructs and returns the base URL for assets collections. (New) + * + * @returns {string} The base collections URL. + */ +export function getBaseAssetsCollectionsUrl() { + return `${getDeliveryEnvironment()}/adobe/assets/collections`; +} + + + + +/** + * Todo Delete this function after code is complete * Retrieves a collection by its unique identifier. * * @param {string} collectionId - The unique identifier of the collection to retrieve. * @returns {Promise} A promise that resolves with the retrieved collection. * @throws {Error} If an HTTP error or network error occurs. */ -export async function getCollection(collectionId) { +export async function getCollectionOld(collectionId) { try { const options = { method: 'GET', @@ -93,7 +141,70 @@ export async function getCollection(collectionId) { } /** - * Creates a new collection. + * Retrieves a collection by its unique identifier. + * + * @param {string} collectionId - The unique identifier of the collection to retrieve. + * @returns {Promise} A promise that resolves with the retrieved collection. + * @throws {Error} If an HTTP error or network error occurs. + */ +export async function getCollection(collectionId) { + try { + + const options = { + method: 'GET', + headers: await getRequestHeaders(), + }; + + //Todo delete logging + console.log("Options"); + console.log(options); + + //const response = await fetch(`${getBaseCollectionsUrl()}/${collectionId}`, options); + + const collectionId2='urn:cid:aem:6156b683-27ba-4e70-82b4-fe97eb38ac19'; + + const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId2}/items`, options); + + //const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId}/items`, options); + + // Handle response codes + if (response.status === 200) { + // Collection retrieved successfully + + const responseBody = await response.json(); + //responseBody.etag = response.headers.get('If-none-match');//Old getCollection + responseBody.etag = response.headers.get('Etag'); + + +//Todo Delete Debug Code + // Access the response headers + const headers = response.headers; + console.log("Show Response Headers") + // Loop through and log all headers + headers.forEach((value, name) => { + console.log(`${name}: ${value}`); + }); +//Todo Delete Debug Code + + return responseBody; + } if (response.status === 404) { + // Handle 404 error + const errorResponse = await response.json(); + throw new Error(`Failed to get collection (404): ${errorResponse.detail}`); + } else { + // Handle other response codes + throw new Error(`Failed to retrieve collection: ${response.status} ${response.statusText}`); + } + } catch (error) { + // Handle network or other errors + logError('getCollection', error); + throw error; + } +} + +/** + * Todo Delete this function after code is complete + * Creates a new collection. (Old/Deprecated) * * @param {string} title - The title of the new collection. * @param {string} description - The description of the new collection (optional). @@ -102,7 +213,7 @@ export async function getCollection(collectionId) { * @returns {Promise} A promise that resolves with the created collection. * @throws {Error} If an HTTP error or network error occurs. */ -export async function createCollection(title, description, items) { +export async function createCollectionOld(title, description, items) { try { const options = { method: 'POST', @@ -147,6 +258,62 @@ export async function createCollection(title, description, items) { } } + +/** + * Creates a new collection. + * + * @param {string} title - The title of the new collection. + * @param {string} description - The description of the new collection (optional). + * @param {Array} items - An array of items to include in the collection (optional). + * @param {object} collectionDetails - From the collection modal to be used by emitEvent + * @returns {Promise} A promise that resolves with the created collection. + * @throws {Error} If an HTTP error or network error occurs. + */ +export async function createCollection(title, description, items) { + try { + const options = { + method: 'POST', + headers: await getRequestHeaders(), + body: JSON.stringify({ title, description, items }), + }; +debugger; + const response = await fetch(`${getBaseAssetsCollectionsUrl()}`, options); + + // Handle response codes + if (response.status === 200) { + // Collection created successfully + const responseBody = await response.json(); + + const assetsArray = items.map((obj) => ({ assetId: obj.id, assetName: obj.name })); + + const collectionDetails = { + collectionName: title, + collectionId: responseBody.id, + assets: assetsArray, + }; + // Emit create creation event + emitEvent(document.documentElement, EventNames.CREATE_COLLECTION, collectionDetails); + + return responseBody; + } if (response.status === 400) { + // Handle 400 error + const errorResponse = await response.json(); + throw new Error(`Failed to create collection (400): ${errorResponse.detail}`); + } else if (response.status === 404) { + // Handle 404 error + const errorResponse = await response.json(); + throw new Error(`Failed to create collection (404): ${errorResponse.detail}`); + } else { + // Handle other response codes + throw new Error(`Failed to create collection: ${response.status} ${response.statusText}`); + } + } catch (error) { + // Handle network or other errors + logError('createCollection', error); + throw error; + } +} + /** * Lists collections with optional limit and cursor parameters. * @@ -167,15 +334,32 @@ export async function listCollection(limit = undefined, cursor = '') { queryParams.append('cursor', cursor); } +/* const options = { method: 'GET', headers: await getRequestHeaders(), }; +*/ + const options = { + method: 'GET', + headers: await getRequestHeadersOriginal(), + }; // Include the query parameters in the URL const queryString = queryParams.toString(); const url = `${getBaseCollectionsUrl()}${queryString ? `?${queryString}` : ''}`; + //New List Collection is not working yet + //const url = `${getBaseAssetsCollectionsUrl()}${queryString ? `?${queryString}` : ''}`; + + console.log('options'); + console.log(options); + + console.log('url'); + console.log(url); + + debugger; + try { const response = await fetch(url, options); // Handle response codes @@ -192,7 +376,9 @@ export async function listCollection(limit = undefined, cursor = '') { } } + /** + * Todo Delete this function after code is complete * Updates a collection using JSON patch operations. * * @param {string} collectionId - The unique identifier of the collection to patch. @@ -202,7 +388,7 @@ export async function listCollection(limit = undefined, cursor = '') { * @returns {Promise} A promise that resolves when the collection is updated. * @throws {Error} If an HTTP error or network error occurs. */ -export async function patchCollection(collectionId, etag, addOperation = '', deleteOperation = '') { +export async function patchCollectionOld(collectionId, etag, addOperation = '', deleteOperation = '') { try { const patchOperations = []; if (addOperation) { @@ -267,6 +453,114 @@ export async function patchCollection(collectionId, etag, addOperation = '', del } } + +/** + * Updates a collection using JSON patch operations. + * + * @param {string} collectionId - The unique identifier of the collection to patch. + * @param {string} etag - The entity tag (ETag) value to use for conditional requests. + * @param {object} addOperation - The JSON patch operation to add an item to the collection (optional). + * @param {object} deleteOperation - The JSON patch operation to remove an item from the collection (optional). +* @returns {Promise} A promise that resolves when the collection is updated. + * @throws {Error} If an HTTP error or network error occurs. + */ +export async function patchCollection(collectionId, etag, addOperation = '', deleteOperation = '') { + + try { + + /* Expected Body + [ + { + "op": "add", + "id": "urn:aaid:aem:ffe295fb-7e6a-462a-91f7-ab34cf6ee13d", + "type": "asset" + } + ] + */ + const patchOperations = []; + if (addOperation) { + for (const op of addOperation) { + patchOperations.push({'op':'add', 'id':op.value.id, 'type': 'asset'}); + } + } + if (deleteOperation) { + for (const op of deleteOperation) { + patchOperations.push({'op':'remove', 'id':op.value.id, 'type': 'asset'}); + } + } + const options = { + method: 'POST', + headers: await getRequestHeadersWithIfMatchPatchJSON(etag), + body: JSON.stringify(patchOperations), + }; + + console.log('options'); + console.log(options); + + debugger; + + const collectionId2='urn:cid:aem:6156b683-27ba-4e70-82b4-fe97eb38ac19'; + + + //const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId}`, options); + + const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId2}/items`, options); + + + if (response.status === 200 || response.status === 204) { + + + console.log('Patch Collection Success!!'); + + + //const responseBody = await response.json(); + + const responseBody = await getCollection(collectionId2); + + const collectionData = responseBody.self[0]; + + if (addOperation) { + const assetsArray = addOperation.map((obj) => ({ assetId: obj.value.id, assetName: obj.value.name })); + const collectionDetails = { + collectionName: collectionData.collectionMetadata.title, + collectionId: collectionData.id, + assets: assetsArray, + }; + emitEvent(document.documentElement, EventNames.ADD_TO_COLLECTION, collectionDetails); + } else if (deleteOperation) { + const assetsArray = deleteOperation.map((obj) => ({ assetId: obj.value.id, assetName: obj.value.name })); + const collectionDetails = { + collectionName: collectionData.collectionMetadata.title, + collectionId: collectionData.id, + assets: assetsArray, + }; + emitEvent(document.documentElement, EventNames.DELETE_FROM_COLLECTION, collectionDetails); + } + + + + return responseBody; + } if (response.status === 400) { + // Handle 400 error + const errorResponse = await response.json(); + throw new Error(`Failed to patch collection (400): ${errorResponse.detail}`); + } else if (response.status === 404) { + // Handle 404 error + const errorResponse = await response.json(); + throw new Error(`Failed to patch collection (404): ${errorResponse.detail}`); + } else if (response.status === 412) { + // Handle 412 error + const errorResponse = await response.json(); + throw new Error(`Failed to patch collection (412): ${errorResponse.detail}`); + } else { + throw new Error(`Failed to update collection: ${response.status} ${response.statusText}`); + } + } catch (error) { + logError('patchCollection', error); + throw error; + } +} + /** * Deletes a collection. * From 6d1488367c2a35693692d5412443bcbc60351370 Mon Sep 17 00:00:00 2001 From: Tyrone Tse Date: Wed, 14 Feb 2024 15:23:41 -0600 Subject: [PATCH 02/20] In collection.js added new function export async function searchListCollection(limit = undefined, page = 0) Pagination in files /adobe-gmo/blocks/adp-infinite-results-collections/CollectionsDatasource.js Needs to be fixed as not all the new Collections are showing up --- .../adp-add-to-collection-modal.js | 13 +- .../CollectionsDatasource.js | 64 +++++++- scripts/collections.js | 140 ++++++++++++++++-- 3 files changed, 200 insertions(+), 17 deletions(-) diff --git a/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js b/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js index 921c329f..288357c6 100644 --- a/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js +++ b/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js @@ -1,6 +1,6 @@ import { decorateIcons } from '../../scripts/lib-franklin.js'; import { - listCollection, createCollection, patchCollection, getCollection, + searchListCollection,listCollection, createCollection, patchCollection, getCollection, } from '../../scripts/collections.js'; import { getSelectedAssetsFromInfiniteResultsBlock, populateAssetViewLeftDialog } from '../../scripts/scripts.js'; import createMultiSelectedAssetsTable from '../../scripts/multi-selected-assets-table.js'; @@ -44,12 +44,21 @@ async function createDropdown(addToExistingRadioDropboxContainer) { // Function to load more data when reaching the end of the dropdown const loadMoreData = async (cursor) => { - const collectionData = await listCollection({ cursor, limit: 10 }); // Adjust the limit as needed + //const collectionData = await listCollection({ cursor, limit: 10 }); // Adjust the limit as needed + const collectionData = await searchListCollection(10, page); + //const collectionData2 = await searchListCollection(10, page); + //Todo try this for now, but replace with same logic as cursor + page = page+1; + return collectionData; }; + //Todo delete the variable cursor when searchListCollection is working let cursor = null; + let page = 0; + + // Event listener to detect scroll and load more data when at the bottom dropdownSelect.addEventListener('scroll', async () => { if (dropdownSelect.scrollTop + dropdownSelect.clientHeight >= dropdownSelect.scrollHeight) { diff --git a/blocks/adp-infinite-results-collections/CollectionsDatasource.js b/blocks/adp-infinite-results-collections/CollectionsDatasource.js index c1d16937..e1f87bd6 100644 --- a/blocks/adp-infinite-results-collections/CollectionsDatasource.js +++ b/blocks/adp-infinite-results-collections/CollectionsDatasource.js @@ -3,11 +3,12 @@ import { getCollectionID, getCollectionTitle, listCollection, + searchListCollection, } from '../../scripts/collections.js'; import { createCollectionCardElement } from '../../scripts/card-html-builder.js'; export default class CollectionsDatasource { - cursor; + //cursor; infiniteResultsContainer = null; @@ -15,10 +16,41 @@ export default class CollectionsDatasource { pageNumber = 0; + + lastPage = false; + + + async showMore() { - const list = await listCollection(5, this.cursor); - this.cursor = list.cursor; + debugger; + //const list = await listCollection(5, this.cursor); + const list = await searchListCollection(5, this.pageNumber); + //const list2 = await searchListCollection(5, this.pageNumber); + + //this.cursor = list.cursor; this.pageNumber += 1; + + + + if (list.nbPages > this.pageNumber){ + this.lastPage = true; + } + + + + + + /* + this.infiniteResultsContainer.resultsCallback( + this.container, + list.items, + () => this.showMore(), + this.pageNumber, + false, + false, + () => this.isLastPage(), + ); + */ this.infiniteResultsContainer.resultsCallback( this.container, list.items, @@ -30,15 +62,39 @@ export default class CollectionsDatasource { ); } + isLastPage() { + return this.lastPage; + } + /* isLastPage() { return !this.cursor; } + */ + async registerResultsCallback(container, infiniteResultsContainer) { this.infiniteResultsContainer = infiniteResultsContainer; this.container = container; + +/* const list = await listCollection(5, this.cursor); - this.cursor = list.cursor; + const list2 = await searchListCollection(5, this.pageNumber); +*/ + const list = await searchListCollection(5, this.pageNumber); + + //this.cursor = list.cursor; + /* + infiniteResultsContainer.resultsCallback( + container, + list.items, + () => this.showMore(), + 0, + true, + true, + () => this.isLastPage(), + ); + */ + infiniteResultsContainer.resultsCallback( container, list.items, diff --git a/scripts/collections.js b/scripts/collections.js index e090982b..e6ddc31c 100644 --- a/scripts/collections.js +++ b/scripts/collections.js @@ -43,12 +43,20 @@ async function getRequestHeadersOriginal() { }; } +async function getRequestHeadersSearchCollections() { + const token = await getBearerToken(); + return { + 'Content-Type': 'application/json', + 'x-api-key': 'asset_search_service', + 'Authorization': token, + 'x-ch-Request': 'search', + 'x-adobe-accept-experimental': '1', + }; +} async function getRequestHeaders() { const token = await getBearerToken(); - /*Todo delete logging token*/ console.log('AuthToken ',token); - return { 'Content-Type': 'application/json', 'x-api-key': await getAssetHandlerApiKey(), @@ -89,6 +97,16 @@ export function getBaseCollectionsUrl() { return `${getDeliveryEnvironment()}/adobe/collections`; } +/** + * Constructs and returns the base URL for search collections. + * + * @returns {string} The search collections URL. + */ +export function getSearchCollectionsUrl() { + return `${getDeliveryEnvironment()}/adobe/assets/search`; +} + + /** * Constructs and returns the base URL for assets collections. (New) @@ -161,11 +179,13 @@ export async function getCollection(collectionId) { //const response = await fetch(`${getBaseCollectionsUrl()}/${collectionId}`, options); - const collectionId2='urn:cid:aem:6156b683-27ba-4e70-82b4-fe97eb38ac19'; - - const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId2}/items`, options); + //const collectionId2='urn:cid:aem:6156b683-27ba-4e70-82b4-fe97eb38ac19'; - //const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId}/items`, options); + //const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId2}/items`, options); +console.log("GET Collection URL"); +console.log(`${getBaseAssetsCollectionsUrl()}/${collectionId}/items`); +debugger; + const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId}/items`, options); // Handle response codes if (response.status === 200) { @@ -345,6 +365,7 @@ export async function listCollection(limit = undefined, cursor = '') { method: 'GET', headers: await getRequestHeadersOriginal(), }; + // Include the query parameters in the URL const queryString = queryParams.toString(); const url = `${getBaseCollectionsUrl()}${queryString ? `?${queryString}` : ''}`; @@ -358,7 +379,6 @@ export async function listCollection(limit = undefined, cursor = '') { console.log('url'); console.log(url); - debugger; try { const response = await fetch(url, options); @@ -376,6 +396,102 @@ export async function listCollection(limit = undefined, cursor = '') { } } +/** + * Search Lists collections with optional limit and page parameters. + * + * @param {number} - The optional maximum number of collections to retrieve. + * @param {number} - The optional page number for paginating the results. + * @returns {Promise} A promise that resolves with a list of collections. + * @throws {Error} If an HTTP error or network error occurs. + */ + + +export async function searchListCollection(limit = undefined, page = 0) { + // Construct the query parameters + const queryParams = new URLSearchParams(); + + if (limit) { + queryParams.append('limit', limit); + } + + if (page) { + queryParams.append('page', page); + } + + const indexName ="108396-1046543_collections"; + + const data = { + "requests": [ + { + "indexName": indexName, + "params": { + "facets": [], + "highlightPostTag": "__/ais-highlight__", + "highlightPreTag": "__ais-highlight__", + "hitsPerPage": limit, + "page": page, + "query": "", + "tagFilters": "" + } + } + ] + }; + + const options = { + method: 'POST', + headers: await getRequestHeadersSearchCollections(), + body: JSON.stringify(data), + }; + + // Include the query parameters in the URL + const queryString = queryParams.toString(); + const url = `${getSearchCollectionsUrl()}${queryString ? `?${queryString}` : ''}`; + + //New List Collection is not working yet + //const url = `${getBaseAssetsCollectionsUrl()}${queryString ? `?${queryString}` : ''}`; + + console.log('options'); + console.log(options); + + console.log('url'); + console.log(url); + + try { + const response = await fetch(url, options); + // Handle response codes + if (response.status === 200) { + // Collection retrieved successfully + const responseBody = await response.json(); + // Transform the data + let transformedData = { + page: responseBody.results[0].page, + nbHits: responseBody.results[0].nbHits, + nbPages: responseBody.results[0].nbPages, + items: responseBody.results[0].hits.map(hit => ({ + id: hit.collectionId, + title: hit.collectionMetadata.metadata ? hit.collectionMetadata.metadata.title : hit.collectionMetadata.title, + description: hit.collectionMetadata.metadata ? hit.collectionMetadata.metadata.description : hit.collectionMetadata.description + })) + }; + + console.log(transformedData); + + return transformedData; + } + // Handle other response codes + throw new Error(`Failed to search list collection: ${response.status} ${response.statusText}`); + } catch (error) { + logError('searchListCollection', error); + throw error; + } +} + + +/* +export async function searchListCollection(limit = undefined, cursor = '') { +} +*/ + /** * Todo Delete this function after code is complete @@ -499,12 +615,12 @@ export async function patchCollection(collectionId, etag, addOperation = '', del debugger; - const collectionId2='urn:cid:aem:6156b683-27ba-4e70-82b4-fe97eb38ac19'; + //const collectionId2='urn:cid:aem:6156b683-27ba-4e70-82b4-fe97eb38ac19'; - //const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId}`, options); + const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId}`, options); - const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId2}/items`, options); + //const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId2}/items`, options); if (response.status === 200 || response.status === 204) { @@ -515,7 +631,9 @@ export async function patchCollection(collectionId, etag, addOperation = '', del //const responseBody = await response.json(); - const responseBody = await getCollection(collectionId2); + //const responseBody = await getCollection(collectionId2); + + const responseBody = await getCollection(collectionId); const collectionData = responseBody.self[0]; From 6382b6f6834997f3d5d87319b0c2427baabc4dba Mon Sep 17 00:00:00 2001 From: Tyrone Tse Date: Wed, 14 Feb 2024 16:55:55 -0600 Subject: [PATCH 03/20] Fixed pagination logic for this.lastPage --- .../CollectionsDatasource.js | 19 ++++--------------- scripts/collections.js | 6 ++---- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/blocks/adp-infinite-results-collections/CollectionsDatasource.js b/blocks/adp-infinite-results-collections/CollectionsDatasource.js index e1f87bd6..f3725c61 100644 --- a/blocks/adp-infinite-results-collections/CollectionsDatasource.js +++ b/blocks/adp-infinite-results-collections/CollectionsDatasource.js @@ -19,27 +19,17 @@ export default class CollectionsDatasource { lastPage = false; - - async showMore() { - debugger; //const list = await listCollection(5, this.cursor); const list = await searchListCollection(5, this.pageNumber); - //const list2 = await searchListCollection(5, this.pageNumber); //this.cursor = list.cursor; this.pageNumber += 1; - - - if (list.nbPages > this.pageNumber){ + if (this.pageNumber >= list.nbPages){ this.lastPage = true; } - - - - /* this.infiniteResultsContainer.resultsCallback( this.container, @@ -76,10 +66,9 @@ export default class CollectionsDatasource { this.infiniteResultsContainer = infiniteResultsContainer; this.container = container; -/* - const list = await listCollection(5, this.cursor); - const list2 = await searchListCollection(5, this.pageNumber); -*/ + + //const list = await listCollection(5, this.cursor); + const list = await searchListCollection(5, this.pageNumber); //this.cursor = list.cursor; diff --git a/scripts/collections.js b/scripts/collections.js index e6ddc31c..41a5a41a 100644 --- a/scripts/collections.js +++ b/scripts/collections.js @@ -184,7 +184,7 @@ export async function getCollection(collectionId) { //const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId2}/items`, options); console.log("GET Collection URL"); console.log(`${getBaseAssetsCollectionsUrl()}/${collectionId}/items`); -debugger; + const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId}/items`, options); // Handle response codes @@ -296,7 +296,7 @@ export async function createCollection(title, description, items) { headers: await getRequestHeaders(), body: JSON.stringify({ title, description, items }), }; -debugger; + const response = await fetch(`${getBaseAssetsCollectionsUrl()}`, options); // Handle response codes @@ -613,8 +613,6 @@ export async function patchCollection(collectionId, etag, addOperation = '', del console.log('options'); console.log(options); - debugger; - //const collectionId2='urn:cid:aem:6156b683-27ba-4e70-82b4-fe97eb38ac19'; From 9c58a1100407a5b48e14f55eb76e8206c12a17db Mon Sep 17 00:00:00 2001 From: Tyrone Tse Date: Fri, 16 Feb 2024 15:51:41 -0600 Subject: [PATCH 04/20] /blocks/adp-infinite-results-collection/CollectionDatasource.js => Pagination for the Collection Cards needs to be fixed /scripts/collections.js : Tested that the getCollection method only works with the new Collections created with the Create and Update Collection API calls /adobe/assets/collections/{collectionId}/ --- .../adp-add-to-collection-modal.js | 9 +- .../CollectionDatasource.js | 1 + .../CollectionsDatasource.js | 3 +- scripts/collections.js | 252 ++---------------- 4 files changed, 23 insertions(+), 242 deletions(-) diff --git a/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js b/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js index 288357c6..edb885a1 100644 --- a/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js +++ b/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js @@ -1,6 +1,6 @@ import { decorateIcons } from '../../scripts/lib-franklin.js'; import { - searchListCollection,listCollection, createCollection, patchCollection, getCollection, + searchListCollection, createCollection, patchCollection, getCollection, } from '../../scripts/collections.js'; import { getSelectedAssetsFromInfiniteResultsBlock, populateAssetViewLeftDialog } from '../../scripts/scripts.js'; import createMultiSelectedAssetsTable from '../../scripts/multi-selected-assets-table.js'; @@ -45,8 +45,9 @@ async function createDropdown(addToExistingRadioDropboxContainer) { // Function to load more data when reaching the end of the dropdown const loadMoreData = async (cursor) => { //const collectionData = await listCollection({ cursor, limit: 10 }); // Adjust the limit as needed - const collectionData = await searchListCollection(10, page); - //const collectionData2 = await searchListCollection(10, page); + //Todo fix logic to show all collections + const collectionData = await searchListCollection(100, page); + //Todo try this for now, but replace with same logic as cursor page = page+1; @@ -54,7 +55,7 @@ async function createDropdown(addToExistingRadioDropboxContainer) { }; //Todo delete the variable cursor when searchListCollection is working - let cursor = null; + //let cursor = null; let page = 0; diff --git a/blocks/adp-infinite-results-collection/CollectionDatasource.js b/blocks/adp-infinite-results-collection/CollectionDatasource.js index 7ac6cd63..3b3800ae 100644 --- a/blocks/adp-infinite-results-collection/CollectionDatasource.js +++ b/blocks/adp-infinite-results-collection/CollectionDatasource.js @@ -69,6 +69,7 @@ export default class CollectionsDatasource { } async createItemElement(item, infiniteResultsContainer) { + const assetJSON = await getAssetMetadata(getAssetIdFromCollectionItem(item)); const assetId = this.getItemId(item); const card = await createAssetCardElement( diff --git a/blocks/adp-infinite-results-collections/CollectionsDatasource.js b/blocks/adp-infinite-results-collections/CollectionsDatasource.js index f3725c61..3813b074 100644 --- a/blocks/adp-infinite-results-collections/CollectionsDatasource.js +++ b/blocks/adp-infinite-results-collections/CollectionsDatasource.js @@ -2,11 +2,12 @@ import { createLinkHref, navigateTo } from '../../scripts/scripts.js'; import { getCollectionID, getCollectionTitle, - listCollection, searchListCollection, } from '../../scripts/collections.js'; import { createCollectionCardElement } from '../../scripts/card-html-builder.js'; +//Todo Pagination needs to be fixed not all cards are shown when there are a lot collections to show + export default class CollectionsDatasource { //cursor; diff --git a/scripts/collections.js b/scripts/collections.js index 41a5a41a..83559b12 100644 --- a/scripts/collections.js +++ b/scripts/collections.js @@ -7,11 +7,6 @@ import { getPathParams, logError } from './scripts.js'; import { emitEvent, EventNames } from './events.js'; export function getCollectionIdFromURL() { - /* Todo remove this comment - if (window.location.pathname.startsWith('/collection/')) { - return getPathParams().at(-1); - } - */ if (window.location.pathname.includes('/collection/')) { return getPathParams().at(-1); } @@ -33,16 +28,6 @@ export function getAssetIdFromCollectionItem(assetItem) { return assetItem.id; } -/* Todo delete this function when code is complete */ -async function getRequestHeadersOriginal() { - const token = await getBearerToken(); - return { - 'Content-Type': 'application/json', - 'x-api-key': await getAssetHandlerApiKey(), - Authorization: token, - }; -} - async function getRequestHeadersSearchCollections() { const token = await getBearerToken(); return { @@ -54,29 +39,18 @@ async function getRequestHeadersSearchCollections() { }; } - async function getRequestHeaders() { + const token = await getBearerToken(); + return { 'Content-Type': 'application/json', 'x-api-key': await getAssetHandlerApiKey(), 'Authorization': token, - 'x-ch-request': 'collection', 'X-Adobe-Accept-Experimental': '1', }; } -/* Todo delete this function when code is complete */ -async function getRequestHeadersWithIfMatch(etag) { - const token = await getBearerToken(); - return { - 'Content-Type': 'application/json', - 'x-api-key': await getAssetHandlerApiKey(), - Authorization: token, - 'If-Match': etag, - }; -} - async function getRequestHeadersWithIfMatchPatchJSON(etag) { const token = await getBearerToken(); return { @@ -117,47 +91,6 @@ export function getBaseAssetsCollectionsUrl() { return `${getDeliveryEnvironment()}/adobe/assets/collections`; } - - - -/** - * Todo Delete this function after code is complete - * Retrieves a collection by its unique identifier. - * - * @param {string} collectionId - The unique identifier of the collection to retrieve. - * @returns {Promise} A promise that resolves with the retrieved collection. - * @throws {Error} If an HTTP error or network error occurs. - */ -export async function getCollectionOld(collectionId) { - try { - const options = { - method: 'GET', - headers: await getRequestHeaders(), - }; - - const response = await fetch(`${getBaseCollectionsUrl()}/${collectionId}`, options); - - // Handle response codes - if (response.status === 200) { - // Collection retrieved successfully - const responseBody = await response.json(); - responseBody.etag = response.headers.get('If-none-match'); - return responseBody; - } if (response.status === 404) { - // Handle 404 error - const errorResponse = await response.json(); - throw new Error(`Failed to get collection (404): ${errorResponse.detail}`); - } else { - // Handle other response codes - throw new Error(`Failed to retrieve collection: ${response.status} ${response.statusText}`); - } - } catch (error) { - // Handle network or other errors - logError('getCollection', error); - throw error; - } -} - /** * Retrieves a collection by its unique identifier. * @@ -168,43 +101,24 @@ export async function getCollectionOld(collectionId) { export async function getCollection(collectionId) { try { + const options = { method: 'GET', headers: await getRequestHeaders(), }; - //Todo delete logging - console.log("Options"); - console.log(options); - - //const response = await fetch(`${getBaseCollectionsUrl()}/${collectionId}`, options); - - //const collectionId2='urn:cid:aem:6156b683-27ba-4e70-82b4-fe97eb38ac19'; - - //const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId2}/items`, options); -console.log("GET Collection URL"); -console.log(`${getBaseAssetsCollectionsUrl()}/${collectionId}/items`); - const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId}/items`, options); // Handle response codes if (response.status === 200) { - // Collection retrieved successfully - - const responseBody = await response.json(); - //responseBody.etag = response.headers.get('If-none-match');//Old getCollection - responseBody.etag = response.headers.get('Etag'); + let responseBody = await response.json(); -//Todo Delete Debug Code - // Access the response headers - const headers = response.headers; - console.log("Show Response Headers") - // Loop through and log all headers - headers.forEach((value, name) => { - console.log(`${name}: ${value}`); - }); -//Todo Delete Debug Code + responseBody.etag = response.headers.get('Etag'); + if (responseBody.self[0].collectionMetadata.title) + responseBody.title = responseBody.self[0].collectionMetadata.title; + else + responseBody.title = ''; return responseBody; } if (response.status === 404) { @@ -335,6 +249,10 @@ export async function createCollection(title, description, items) { } /** + * Deprecated getAllCollections API not implemented yet + * + * https://adobe-aem-assets-delivery-experimental.redoc.ly/#operation/getAllCollections + * * Lists collections with optional limit and cursor parameters. * * @param {number} - The optional maximum number of collections to retrieve. @@ -354,32 +272,15 @@ export async function listCollection(limit = undefined, cursor = '') { queryParams.append('cursor', cursor); } -/* const options = { method: 'GET', headers: await getRequestHeaders(), }; -*/ - - const options = { - method: 'GET', - headers: await getRequestHeadersOriginal(), - }; // Include the query parameters in the URL const queryString = queryParams.toString(); const url = `${getBaseCollectionsUrl()}${queryString ? `?${queryString}` : ''}`; - //New List Collection is not working yet - //const url = `${getBaseAssetsCollectionsUrl()}${queryString ? `?${queryString}` : ''}`; - - console.log('options'); - console.log(options); - - console.log('url'); - console.log(url); - - try { const response = await fetch(url, options); // Handle response codes @@ -418,6 +319,7 @@ export async function searchListCollection(limit = undefined, page = 0) { queryParams.append('page', page); } + //Todo add the indexName in a config file hardcode for now const indexName ="108396-1046543_collections"; const data = { @@ -447,15 +349,6 @@ export async function searchListCollection(limit = undefined, page = 0) { const queryString = queryParams.toString(); const url = `${getSearchCollectionsUrl()}${queryString ? `?${queryString}` : ''}`; - //New List Collection is not working yet - //const url = `${getBaseAssetsCollectionsUrl()}${queryString ? `?${queryString}` : ''}`; - - console.log('options'); - console.log(options); - - console.log('url'); - console.log(url); - try { const response = await fetch(url, options); // Handle response codes @@ -473,8 +366,7 @@ export async function searchListCollection(limit = undefined, page = 0) { description: hit.collectionMetadata.metadata ? hit.collectionMetadata.metadata.description : hit.collectionMetadata.description })) }; - - console.log(transformedData); + //console.log(transformedData); return transformedData; } @@ -486,90 +378,6 @@ export async function searchListCollection(limit = undefined, page = 0) { } } - -/* -export async function searchListCollection(limit = undefined, cursor = '') { -} -*/ - - -/** - * Todo Delete this function after code is complete - * Updates a collection using JSON patch operations. - * - * @param {string} collectionId - The unique identifier of the collection to patch. - * @param {string} etag - The entity tag (ETag) value to use for conditional requests. - * @param {object} addOperation - The JSON patch operation to add an item to the collection (optional). - * @param {object} deleteOperation - The JSON patch operation to remove an item from the collection (optional). -* @returns {Promise} A promise that resolves when the collection is updated. - * @throws {Error} If an HTTP error or network error occurs. - */ -export async function patchCollectionOld(collectionId, etag, addOperation = '', deleteOperation = '') { - try { - const patchOperations = []; - if (addOperation) { - for (const op of addOperation) { - op.op = 'add'; - patchOperations.push(op); - } - } - if (deleteOperation) { - for (const op of deleteOperation) { - op.op = 'remove'; - patchOperations.push(op); - } - } - const options = { - method: 'PATCH', - headers: await getRequestHeadersWithIfMatch(etag), - body: JSON.stringify(patchOperations), - }; - const response = await fetch(`${getBaseCollectionsUrl()}/${collectionId}`, options); - - if (response.status === 200) { - const responseBody = await response.json(); - - if (addOperation) { - const assetsArray = addOperation.map((obj) => ({ assetId: obj.value.id, assetName: obj.value.name })); - const collectionDetails = { - collectionName: responseBody.title, - collectionId: responseBody.id, - assets: assetsArray, - }; - emitEvent(document.documentElement, EventNames.ADD_TO_COLLECTION, collectionDetails); - } else if (deleteOperation) { - const assetsArray = deleteOperation.map((obj) => ({ assetId: obj.value.id, assetName: obj.value.name })); - const collectionDetails = { - collectionName: responseBody.title, - collectionId: responseBody.id, - assets: assetsArray, - }; - emitEvent(document.documentElement, EventNames.DELETE_FROM_COLLECTION, collectionDetails); - } - - return responseBody; - } if (response.status === 400) { - // Handle 400 error - const errorResponse = await response.json(); - throw new Error(`Failed to patch collection (400): ${errorResponse.detail}`); - } else if (response.status === 404) { - // Handle 404 error - const errorResponse = await response.json(); - throw new Error(`Failed to patch collection (404): ${errorResponse.detail}`); - } else if (response.status === 412) { - // Handle 412 error - const errorResponse = await response.json(); - throw new Error(`Failed to patch collection (412): ${errorResponse.detail}`); - } else { - throw new Error(`Failed to update collection: ${response.status} ${response.statusText}`); - } - } catch (error) { - logError('patchCollection', error); - throw error; - } -} - - /** * Updates a collection using JSON patch operations. * @@ -581,18 +389,8 @@ export async function patchCollectionOld(collectionId, etag, addOperation = '', * @throws {Error} If an HTTP error or network error occurs. */ export async function patchCollection(collectionId, etag, addOperation = '', deleteOperation = '') { - try { - /* Expected Body - [ - { - "op": "add", - "id": "urn:aaid:aem:ffe295fb-7e6a-462a-91f7-ab34cf6ee13d", - "type": "asset" - } - ] - */ const patchOperations = []; if (addOperation) { for (const op of addOperation) { @@ -610,27 +408,10 @@ export async function patchCollection(collectionId, etag, addOperation = '', del body: JSON.stringify(patchOperations), }; - console.log('options'); - console.log(options); - - //const collectionId2='urn:cid:aem:6156b683-27ba-4e70-82b4-fe97eb38ac19'; - - const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId}`, options); - //const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId2}/items`, options); - - if (response.status === 200 || response.status === 204) { - - console.log('Patch Collection Success!!'); - - - //const responseBody = await response.json(); - - //const responseBody = await getCollection(collectionId2); - const responseBody = await getCollection(collectionId); const collectionData = responseBody.self[0]; @@ -652,9 +433,6 @@ export async function patchCollection(collectionId, etag, addOperation = '', del }; emitEvent(document.documentElement, EventNames.DELETE_FROM_COLLECTION, collectionDetails); } - - - return responseBody; } if (response.status === 400) { // Handle 400 error From cc386d64ddfdac777564293c5487cf3b641c00c6 Mon Sep 17 00:00:00 2001 From: Tyrone Tse Date: Tue, 20 Feb 2024 12:33:43 -0600 Subject: [PATCH 05/20] Updated deleteCollection function, added etag parameter as it required in the header in the new Assets Delete API --- .../adp-collection-header.js | 3 +- scripts/collections.js | 80 +++++-------------- 2 files changed, 21 insertions(+), 62 deletions(-) diff --git a/blocks/adp-collection-header/adp-collection-header.js b/blocks/adp-collection-header/adp-collection-header.js index 618a4ce5..7c6b8db5 100644 --- a/blocks/adp-collection-header/adp-collection-header.js +++ b/blocks/adp-collection-header/adp-collection-header.js @@ -4,6 +4,7 @@ import { decorateIcons } from '../../scripts/lib-franklin.js'; import { createLinkHref, navigateTo } from '../../scripts/scripts.js'; function createCollectionInfoHeader(collectionInfoHeader, collection) { + // include back to collections listing similar to hide filters button collectionInfoHeader.innerHTML = `
@@ -36,7 +37,7 @@ function createCollectionInfoHeader(collectionInfoHeader, collection) { 'Delete collection', `Are you sure you want to delete the collection "${collection.title}"?`, async () => { - await deleteCollection(collectionId, collection.title); + await deleteCollection(collectionId, collection.title, collection.etag); navigateTo(createLinkHref('/collections')); }, 'Proceed', diff --git a/scripts/collections.js b/scripts/collections.js index 83559b12..b155692e 100644 --- a/scripts/collections.js +++ b/scripts/collections.js @@ -51,6 +51,19 @@ async function getRequestHeaders() { }; } +async function getRequestHeadersWithEtag(etag) { + + const token = await getBearerToken(); + + return { + 'Content-Type': 'application/json', + 'x-api-key': await getAssetHandlerApiKey(), + 'Authorization': token, + 'X-Adobe-Accept-Experimental': '1', + 'If-Match': etag, + }; +} + async function getRequestHeadersWithIfMatchPatchJSON(etag) { const token = await getBearerToken(); return { @@ -136,63 +149,6 @@ export async function getCollection(collectionId) { } } -/** - * Todo Delete this function after code is complete - * Creates a new collection. (Old/Deprecated) - * - * @param {string} title - The title of the new collection. - * @param {string} description - The description of the new collection (optional). - * @param {Array} items - An array of items to include in the collection (optional). - * @param {object} collectionDetails - From the collection modal to be used by emitEvent - * @returns {Promise} A promise that resolves with the created collection. - * @throws {Error} If an HTTP error or network error occurs. - */ -export async function createCollectionOld(title, description, items) { - try { - const options = { - method: 'POST', - headers: await getRequestHeaders(), - body: JSON.stringify({ title, description, items }), - }; - - const response = await fetch(`${getBaseCollectionsUrl()}`, options); - - // Handle response codes - if (response.status === 200) { - // Collection created successfully - const responseBody = await response.json(); - - const assetsArray = items.map((obj) => ({ assetId: obj.id, assetName: obj.name })); - - const collectionDetails = { - collectionName: title, - collectionId: responseBody.id, - assets: assetsArray, - }; - // Emit create creation event - emitEvent(document.documentElement, EventNames.CREATE_COLLECTION, collectionDetails); - - return responseBody; - } if (response.status === 400) { - // Handle 400 error - const errorResponse = await response.json(); - throw new Error(`Failed to create collection (400): ${errorResponse.detail}`); - } else if (response.status === 404) { - // Handle 404 error - const errorResponse = await response.json(); - throw new Error(`Failed to create collection (404): ${errorResponse.detail}`); - } else { - // Handle other response codes - throw new Error(`Failed to create collection: ${response.status} ${response.statusText}`); - } - } catch (error) { - // Handle network or other errors - logError('createCollection', error); - throw error; - } -} - - /** * Creates a new collection. * @@ -366,7 +322,6 @@ export async function searchListCollection(limit = undefined, page = 0) { description: hit.collectionMetadata.metadata ? hit.collectionMetadata.metadata.description : hit.collectionMetadata.description })) }; - //console.log(transformedData); return transformedData; } @@ -459,17 +414,20 @@ export async function patchCollection(collectionId, etag, addOperation = '', del * Deletes a collection. * * @param {string} collectionId - The unique identifier of the collection to delete. + * @param {string} collectionName - Collection name used for emit delete event. + * @param {string} etag - Used for in the header for the delete operation. * @returns {Promise} A promise that resolves when the collection is updated. * @throws {Error} If an HTTP error or network error occurs. */ -export async function deleteCollection(collectionId, collectionName) { +export async function deleteCollection(collectionId, collectionName, etag) { try { + const options = { method: 'DELETE', - headers: await getRequestHeaders(), + headers: await getRequestHeadersWithEtag(etag), }; - const response = await fetch(`${getBaseCollectionsUrl()}/${collectionId}`, options); + const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId}`, options); if (response.status !== 204) { throw new Error(`Failed to delete collection: ${response.status} ${response.statusText}`); From e4303307c15748fe9e6b0f492ea8d2aa34d317a6 Mon Sep 17 00:00:00 2001 From: Tyrone Tse Date: Tue, 20 Feb 2024 14:41:52 -0600 Subject: [PATCH 06/20] Updated function patchCollection API URL from ${getBaseAssetsCollectionsUrl()}/${collectionId} to ${getBaseAssetsCollectionsUrl()}/${collectionId}/items --- scripts/collections.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/collections.js b/scripts/collections.js index b155692e..2e5fdb97 100644 --- a/scripts/collections.js +++ b/scripts/collections.js @@ -69,7 +69,8 @@ async function getRequestHeadersWithIfMatchPatchJSON(etag) { return { 'Content-Type': 'application/json-patch+json', 'x-api-key': await getAssetHandlerApiKey(), - Authorization: token, + 'Authorization': token, + 'X-Adobe-Accept-Experimental': '1', 'If-Match': etag, }; } @@ -357,13 +358,15 @@ export async function patchCollection(collectionId, etag, addOperation = '', del patchOperations.push({'op':'remove', 'id':op.value.id, 'type': 'asset'}); } } + + const options = { method: 'POST', headers: await getRequestHeadersWithIfMatchPatchJSON(etag), body: JSON.stringify(patchOperations), }; - const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId}`, options); + const response = await fetch(`${getBaseAssetsCollectionsUrl()}/${collectionId}/items`, options); if (response.status === 200 || response.status === 204) { From 6c464cf2f9f25577939de2f01745eba3df059a9e Mon Sep 17 00:00:00 2001 From: Tyrone Tse Date: Tue, 20 Feb 2024 16:15:12 -0600 Subject: [PATCH 07/20] /scripts/collections.js ==> Updated function searchListCollection(limit = undefined, page = 0), added logic when the parameter page = null to not add the page parameter in the data / body parameters /blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js : Removed hard coded getCollection('urn:cid:aem:8f67c491-347a-4c50-a55b-aad555671b22') call to call the selected collection for add to an existing collection. --- .../adp-add-to-collection-modal.js | 31 ++++++++-------- scripts/collections.js | 35 ++++++++++++++++--- 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js b/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js index edb885a1..8a1da29d 100644 --- a/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js +++ b/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js @@ -43,27 +43,30 @@ async function createDropdown(addToExistingRadioDropboxContainer) { dropdownSelect.classList.add('add-to-existing-dropdown'); // Add the new class // Function to load more data when reaching the end of the dropdown - const loadMoreData = async (cursor) => { + //const loadMoreData = async (cursor) => { + const loadMoreData = async (page) => { //const collectionData = await listCollection({ cursor, limit: 10 }); // Adjust the limit as needed //Todo fix logic to show all collections - const collectionData = await searchListCollection(100, page); + + const collectionData = await searchListCollection(20, page); //Todo try this for now, but replace with same logic as cursor - page = page+1; + //page = page+1; return collectionData; }; //Todo delete the variable cursor when searchListCollection is working - //let cursor = null; + let cursor = null; - let page = 0; + let page = null; // Event listener to detect scroll and load more data when at the bottom dropdownSelect.addEventListener('scroll', async () => { if (dropdownSelect.scrollTop + dropdownSelect.clientHeight >= dropdownSelect.scrollHeight) { - const moreData = await loadMoreData(cursor); + //const moreData = await loadMoreData(cursor); + const moreData = await loadMoreData(page); if (moreData.items.length > 0) { // Update the cursor for the next load cursor = moreData.cursor; @@ -80,10 +83,15 @@ async function createDropdown(addToExistingRadioDropboxContainer) { }); // Initial data loading - const initialData = await loadMoreData(cursor); + //const initialData = await loadMoreData(cursor); + const initialData = await loadMoreData(page); if (initialData.items.length > 0) { // Update the cursor for the next load cursor = initialData.cursor; + if (page==null) + page=0; + + page = page +1; // Populate the options in the dropdown with the initial data initialData.items.forEach((collection) => { @@ -165,19 +173,12 @@ export async function openModal(items) { }); } -/*Todo Delete this getCollection */ - getCollection('urn:cid:aem:8f67c491-347a-4c50-a55b-aad555671b22') - .then((collection) => { - const { etag } = collection; - patchCollection(collectionId, etag, payload); - }); -/* getCollection(collectionId) .then((collection) => { const { etag } = collection; patchCollection(collectionId, etag, payload); }); -*/ + resetDialogState(); } diff --git a/scripts/collections.js b/scripts/collections.js index 2e5fdb97..36db1f1d 100644 --- a/scripts/collections.js +++ b/scripts/collections.js @@ -279,9 +279,13 @@ export async function searchListCollection(limit = undefined, page = 0) { //Todo add the indexName in a config file hardcode for now const indexName ="108396-1046543_collections"; - const data = { - "requests": [ - { + let data = {}; + + if (page!=null) + { + data = { + "requests": [ + { "indexName": indexName, "params": { "facets": [], @@ -293,8 +297,29 @@ export async function searchListCollection(limit = undefined, page = 0) { "tagFilters": "" } } - ] - }; + ] + }; + } + else + { + //No page parameter + data = { + "requests": [ + { + "indexName": indexName, + "params": { + "facets": [], + "highlightPostTag": "__/ais-highlight__", + "highlightPreTag": "__ais-highlight__", + "hitsPerPage": limit, + "query": "", + "tagFilters": "" + } + } + ] + }; + } + const options = { method: 'POST', From b4a57d215f69e147cf877b03bc9ed47ae7d6e543 Mon Sep 17 00:00:00 2001 From: Tyrone Tse Date: Wed, 21 Feb 2024 11:01:50 -0600 Subject: [PATCH 08/20] Check in latest collection modal code --- .../adp-add-to-collection-modal.js | 4 +++- scripts/collections.js | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js b/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js index 8a1da29d..2b9c7a6f 100644 --- a/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js +++ b/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js @@ -48,7 +48,8 @@ async function createDropdown(addToExistingRadioDropboxContainer) { //const collectionData = await listCollection({ cursor, limit: 10 }); // Adjust the limit as needed //Todo fix logic to show all collections - const collectionData = await searchListCollection(20, page); + //const collectionData = await searchListCollection(100, page); + const collectionData = await searchListCollection(100, null); //Todo try this for now, but replace with same logic as cursor //page = page+1; @@ -64,6 +65,7 @@ async function createDropdown(addToExistingRadioDropboxContainer) { // Event listener to detect scroll and load more data when at the bottom dropdownSelect.addEventListener('scroll', async () => { +debugger; if (dropdownSelect.scrollTop + dropdownSelect.clientHeight >= dropdownSelect.scrollHeight) { //const moreData = await loadMoreData(cursor); const moreData = await loadMoreData(page); diff --git a/scripts/collections.js b/scripts/collections.js index 36db1f1d..76918438 100644 --- a/scripts/collections.js +++ b/scripts/collections.js @@ -337,6 +337,13 @@ export async function searchListCollection(limit = undefined, page = 0) { if (response.status === 200) { // Collection retrieved successfully const responseBody = await response.json(); + +//Todo delete debug +console.log('options'); +console.log(options); +console.log('responseBody'); +console.log(responseBody); +//Todo delete debug // Transform the data let transformedData = { page: responseBody.results[0].page, From 1967b56877eed535eddbc48155684db8ab7fd809 Mon Sep 17 00:00:00 2001 From: Tyrone Tse Date: Wed, 21 Feb 2024 14:45:10 -0600 Subject: [PATCH 09/20] Deleted/removed Caching for JSON data for when the app is run on localhost --- scripts/scripts.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/scripts/scripts.js b/scripts/scripts.js index 900d55cc..51339811 100644 --- a/scripts/scripts.js +++ b/scripts/scripts.js @@ -213,14 +213,6 @@ async function loadEager(doc) { } } -async function initializeServiceWorkers() { - if (window.location.hostname.includes('localhost')) { - const sw = await navigator.serviceWorker.register('/localdata.js'); - // eslint-disable-next-line no-console - console.log('ServiceWorker registered', sw); - } -} - /** * Adds the favicon. * @param {string} href The favicon URL @@ -253,9 +245,7 @@ async function loadLazy(doc) { window.location.href = NO_ACCESS_PATH; return; } - // This is a dev only service worker that caches the algolia JS SDK - // check if we are on localhost - await initializeServiceWorkers(); + // Make sure all dependencies are loaded before initializing search // - we load them in parallel by leveraging the promise } else if (await checkUserAccess()) { From 2e4adf00ffbb1a97c49a3d3e62d362c01e20d756 Mon Sep 17 00:00:00 2001 From: Tyrone Tse Date: Wed, 21 Feb 2024 17:06:54 -0600 Subject: [PATCH 10/20] /scripts/scripts.js Restored the caching of collection data for localhost /scripts/collections.js : Removed deprecated listCollection function /blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js : Removed all the commented out old code that called listCollections /blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js : Removed all the commented out old code that called listCollections --- .../adp-add-to-collection-modal.js | 32 ++----- .../CollectionsDatasource.js | 42 +--------- scripts/collections.js | 83 +------------------ scripts/scripts.js | 12 ++- 4 files changed, 19 insertions(+), 150 deletions(-) diff --git a/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js b/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js index 2b9c7a6f..c1e51e40 100644 --- a/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js +++ b/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js @@ -45,34 +45,19 @@ async function createDropdown(addToExistingRadioDropboxContainer) { // Function to load more data when reaching the end of the dropdown //const loadMoreData = async (cursor) => { const loadMoreData = async (page) => { - //const collectionData = await listCollection({ cursor, limit: 10 }); // Adjust the limit as needed - //Todo fix logic to show all collections - - //const collectionData = await searchListCollection(100, page); - const collectionData = await searchListCollection(100, null); - - //Todo try this for now, but replace with same logic as cursor - //page = page+1; - + const collectionData = await searchListCollection(100, page); return collectionData; }; - //Todo delete the variable cursor when searchListCollection is working - let cursor = null; - - let page = null; - + let page = 0; // Event listener to detect scroll and load more data when at the bottom dropdownSelect.addEventListener('scroll', async () => { -debugger; if (dropdownSelect.scrollTop + dropdownSelect.clientHeight >= dropdownSelect.scrollHeight) { - //const moreData = await loadMoreData(cursor); const moreData = await loadMoreData(page); if (moreData.items.length > 0) { - // Update the cursor for the next load - cursor = moreData.cursor; - + //Update page to next load + page++; // Populate the options in the dropdown from the additional data moreData.items.forEach((collection) => { const option = document.createElement('option'); @@ -85,15 +70,10 @@ debugger; }); // Initial data loading - //const initialData = await loadMoreData(cursor); const initialData = await loadMoreData(page); if (initialData.items.length > 0) { - // Update the cursor for the next load - cursor = initialData.cursor; - if (page==null) - page=0; - - page = page +1; + //Update page to next load + page++; // Populate the options in the dropdown with the initial data initialData.items.forEach((collection) => { diff --git a/blocks/adp-infinite-results-collections/CollectionsDatasource.js b/blocks/adp-infinite-results-collections/CollectionsDatasource.js index 3813b074..6e727043 100644 --- a/blocks/adp-infinite-results-collections/CollectionsDatasource.js +++ b/blocks/adp-infinite-results-collections/CollectionsDatasource.js @@ -6,42 +6,24 @@ import { } from '../../scripts/collections.js'; import { createCollectionCardElement } from '../../scripts/card-html-builder.js'; -//Todo Pagination needs to be fixed not all cards are shown when there are a lot collections to show - export default class CollectionsDatasource { - //cursor; infiniteResultsContainer = null; container = null; - pageNumber = 0; - - lastPage = false; async showMore() { - //const list = await listCollection(5, this.cursor); + const list = await searchListCollection(5, this.pageNumber); - //this.cursor = list.cursor; this.pageNumber += 1; if (this.pageNumber >= list.nbPages){ this.lastPage = true; } - /* - this.infiniteResultsContainer.resultsCallback( - this.container, - list.items, - () => this.showMore(), - this.pageNumber, - false, - false, - () => this.isLastPage(), - ); - */ this.infiniteResultsContainer.resultsCallback( this.container, list.items, @@ -56,35 +38,13 @@ export default class CollectionsDatasource { isLastPage() { return this.lastPage; } - /* - isLastPage() { - return !this.cursor; - } - */ - async registerResultsCallback(container, infiniteResultsContainer) { this.infiniteResultsContainer = infiniteResultsContainer; this.container = container; - - //const list = await listCollection(5, this.cursor); - const list = await searchListCollection(5, this.pageNumber); - //this.cursor = list.cursor; - /* - infiniteResultsContainer.resultsCallback( - container, - list.items, - () => this.showMore(), - 0, - true, - true, - () => this.isLastPage(), - ); - */ - infiniteResultsContainer.resultsCallback( container, list.items, diff --git a/scripts/collections.js b/scripts/collections.js index 76918438..c9ab5062 100644 --- a/scripts/collections.js +++ b/scripts/collections.js @@ -205,55 +205,6 @@ export async function createCollection(title, description, items) { } } -/** - * Deprecated getAllCollections API not implemented yet - * - * https://adobe-aem-assets-delivery-experimental.redoc.ly/#operation/getAllCollections - * - * Lists collections with optional limit and cursor parameters. - * - * @param {number} - The optional maximum number of collections to retrieve. - * @param {string} - The optional cursor for paginating the results. - * @returns {Promise} A promise that resolves with a list of collections. - * @throws {Error} If an HTTP error or network error occurs. - */ -export async function listCollection(limit = undefined, cursor = '') { - // Construct the query parameters - const queryParams = new URLSearchParams(); - - if (limit) { - queryParams.append('limit', limit); - } - - if (cursor) { - queryParams.append('cursor', cursor); - } - - const options = { - method: 'GET', - headers: await getRequestHeaders(), - }; - - // Include the query parameters in the URL - const queryString = queryParams.toString(); - const url = `${getBaseCollectionsUrl()}${queryString ? `?${queryString}` : ''}`; - - try { - const response = await fetch(url, options); - // Handle response codes - if (response.status === 200) { - // Collection retrieved successfully - const responseBody = await response.json(); - return responseBody; - } - // Handle other response codes - throw new Error(`Failed to list collection: ${response.status} ${response.statusText}`); - } catch (error) { - logError('listCollection', error); - throw error; - } -} - /** * Search Lists collections with optional limit and page parameters. * @@ -263,7 +214,6 @@ export async function listCollection(limit = undefined, cursor = '') { * @throws {Error} If an HTTP error or network error occurs. */ - export async function searchListCollection(limit = undefined, page = 0) { // Construct the query parameters const queryParams = new URLSearchParams(); @@ -279,11 +229,7 @@ export async function searchListCollection(limit = undefined, page = 0) { //Todo add the indexName in a config file hardcode for now const indexName ="108396-1046543_collections"; - let data = {}; - - if (page!=null) - { - data = { + const data = { "requests": [ { "indexName": indexName, @@ -299,27 +245,6 @@ export async function searchListCollection(limit = undefined, page = 0) { } ] }; - } - else - { - //No page parameter - data = { - "requests": [ - { - "indexName": indexName, - "params": { - "facets": [], - "highlightPostTag": "__/ais-highlight__", - "highlightPreTag": "__ais-highlight__", - "hitsPerPage": limit, - "query": "", - "tagFilters": "" - } - } - ] - }; - } - const options = { method: 'POST', @@ -338,12 +263,6 @@ export async function searchListCollection(limit = undefined, page = 0) { // Collection retrieved successfully const responseBody = await response.json(); -//Todo delete debug -console.log('options'); -console.log(options); -console.log('responseBody'); -console.log(responseBody); -//Todo delete debug // Transform the data let transformedData = { page: responseBody.results[0].page, diff --git a/scripts/scripts.js b/scripts/scripts.js index 51339811..900d55cc 100644 --- a/scripts/scripts.js +++ b/scripts/scripts.js @@ -213,6 +213,14 @@ async function loadEager(doc) { } } +async function initializeServiceWorkers() { + if (window.location.hostname.includes('localhost')) { + const sw = await navigator.serviceWorker.register('/localdata.js'); + // eslint-disable-next-line no-console + console.log('ServiceWorker registered', sw); + } +} + /** * Adds the favicon. * @param {string} href The favicon URL @@ -245,7 +253,9 @@ async function loadLazy(doc) { window.location.href = NO_ACCESS_PATH; return; } - + // This is a dev only service worker that caches the algolia JS SDK + // check if we are on localhost + await initializeServiceWorkers(); // Make sure all dependencies are loaded before initializing search // - we load them in parallel by leveraging the promise } else if (await checkUserAccess()) { From de461a62bee637a771616b178601b4d1497d8cd8 Mon Sep 17 00:00:00 2001 From: Tyrone Tse Date: Thu, 22 Feb 2024 13:18:24 -0600 Subject: [PATCH 11/20] Added code to get the Search Collection Index from the configuration file admin-config.json which is stored in a new property searchCollectionIndex e.g. { "ID": "searchCollectionIndex", "Value": "108396-1046543_collections" } --- scripts/collections.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/collections.js b/scripts/collections.js index c9ab5062..bc8679d2 100644 --- a/scripts/collections.js +++ b/scripts/collections.js @@ -6,6 +6,9 @@ import { import { getPathParams, logError } from './scripts.js'; import { emitEvent, EventNames } from './events.js'; +import { + getAdminConfig, } from './site-config.js'; + export function getCollectionIdFromURL() { if (window.location.pathname.includes('/collection/')) { return getPathParams().at(-1); @@ -226,8 +229,8 @@ export async function searchListCollection(limit = undefined, page = 0) { queryParams.append('page', page); } - //Todo add the indexName in a config file hardcode for now - const indexName ="108396-1046543_collections"; + const adminConfig=await getAdminConfig(); + const indexName=adminConfig.searchCollectionIndex; const data = { "requests": [ From 20465804dadf30190c23099aeb3f38068d627494 Mon Sep 17 00:00:00 2001 From: Tyrone Tse Date: Fri, 23 Feb 2024 13:53:03 -0600 Subject: [PATCH 12/20] Updated function loadMoreData to get all the collections to populate them in the Collection dropdown list. Deleted the dropdownSelect.addEventListener('scroll' .... as the does not support it + dropdownSelect.addEventListener('scroll', async () => { if (dropdownSelect.scrollTop + dropdownSelect.clientHeight >= dropdownSelect.scrollHeight) { const moreData = await loadMoreData(page); @@ -68,12 +69,12 @@ async function createDropdown(addToExistingRadioDropboxContainer) { } } }); + */ + const page = 0; // Initial data loading const initialData = await loadMoreData(page); if (initialData.items.length > 0) { - //Update page to next load - page++; // Populate the options in the dropdown with the initial data initialData.items.forEach((collection) => { From 8c595f8d901151c080b2313152bb74f42fc3ab45 Mon Sep 17 00:00:00 2001 From: Tyrone Tse Date: Fri, 23 Feb 2024 15:46:17 -0600 Subject: [PATCH 13/20] Deleted event listener dropdownSelect.addEventListener('scroll' .. as it not used. --- .../adp-add-to-collection-modal.js | 24 ++----------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js b/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js index b1a33029..9385cb67 100644 --- a/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js +++ b/blocks/adp-add-to-collection-modal/adp-add-to-collection-modal.js @@ -45,32 +45,12 @@ async function createDropdown(addToExistingRadioDropboxContainer) { // Function to load more data when reaching the end of the dropdown const loadMoreData = async (page) => { //Call to get the nbHits for the total number of Collections - let collectionMax = await searchListCollection(0,0); + const collectionMax = await searchListCollection(0,0); + //Get all the collections const collectionData = await searchListCollection(collectionMax.nbHits,page); return collectionData; }; - // Event listener to detect scroll and load more data when at the bottom - /* The scroll event is commented out, since the