Skip to content

Commit

Permalink
feat(Preview): support home page & collection page preview (#97)
Browse files Browse the repository at this point in the history
  • Loading branch information
ReenaSingh07 authored Nov 22, 2024
1 parent e4f7416 commit 488edfd
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 70 deletions.
117 changes: 67 additions & 50 deletions collection-loader.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
const get = require("lodash/get");
const flatMap = require("lodash/flatMap");
const get = require('lodash/get')
const flatMap = require('lodash/flatMap')

function loadCollectionItems(
function loadCollectionItems (
client,
collections,
{ storyFields, storyLimits = {}, defaultNestedLimit, customLayouts = [] }
{ storyFields, storyLimits = {}, defaultNestedLimit, customLayouts = [], previewId = '', qtInternalAppsKey = '' }
) {
const bulkRequestBody = collections.reduce((acc, collection, index) => {
let limit = storyLimits[get(collection, ["associated-metadata", "layout"], "")];
const customLayout = get(customLayouts, [index]);
let limit = storyLimits[get(collection, ['associated-metadata', 'layout'], '')]
const customLayout = get(customLayouts, [index])
if (customLayout) {
limit = get(customLayout, ["storyLimit"]);
limit = get(customLayout, ['storyLimit'])
}

if (!limit && get(collection, ["childCollectionLimit"])) {
limit = get(collection, ["childCollectionLimit"]);
if (!limit && get(collection, ['childCollectionLimit'])) {
limit = get(collection, ['childCollectionLimit'])
}

if (!limit && defaultNestedLimit) {
limit = defaultNestedLimit;
limit = defaultNestedLimit
}

return Object.assign(acc, {
[`${collection.slug}-${index}`]: {
_type: "collection",
_type: 'collection',
slug: collection.slug,
"story-fields": storyFields,
'story-fields': storyFields,
limit: limit
}
});
}, {});

return client.getInBulk({ requests: bulkRequestBody }).then(response => response.results);
})
}, {})
const opts = { previewId, qtInternalAppsKey }
return client.getInBulk({ requests: bulkRequestBody }, opts).then(response => response.results)
}

// Ugly. This function updates all the items in place.
// However, this is way more readable than a pure version
function updateItemsInPlace(
function updateItemsInPlace (
client,
depth,
items,
Expand All @@ -46,43 +46,47 @@ function updateItemsInPlace(
defaultNestedLimit,
nestedCollectionLimit,
collectionOfCollectionsIndexes = [],
customLayouts = []
customLayouts = [],
previewId = "",
qtInternalAppsKey = ""
}
) {
const collections = items.filter(item => item && item.type == "collection");
const collections = items.filter(item => item && item.type == 'collection')

if (depth == 0 || collections.length == 0) return Promise.resolve();
if (depth == 0 || collections.length == 0) return Promise.resolve()

return loadCollectionItems(client, collections, {
storyFields,
storyLimits,
defaultNestedLimit,
customLayouts
customLayouts,
previewId,
qtInternalAppsKey
}).then(collectionSlugToCollection => {
collections.forEach((collection, index) => {
const slugWithIndex = `${collection.slug}-${index}`;
collection.summary = get(collectionSlugToCollection, [slugWithIndex, "summary"], "");
collection.automated = get(collectionSlugToCollection, [slugWithIndex, "automated"]);
collection["collection-cache-keys"] = get(
const slugWithIndex = `${collection.slug}-${index}`
collection.summary = get(collectionSlugToCollection, [slugWithIndex, 'summary'], '')
collection.automated = get(collectionSlugToCollection, [slugWithIndex, 'automated'])
collection['collection-cache-keys'] = get(
collectionSlugToCollection,
[slugWithIndex, "collection-cache-keys"],
[slugWithIndex, 'collection-cache-keys'],
[]
);
collection.items = get(collectionSlugToCollection, [slugWithIndex, "items"], []);
)
collection.items = get(collectionSlugToCollection, [slugWithIndex, 'items'], [])
if (nestedCollectionLimit && collection.items) {
const customLayout = get(customLayouts, [index]);
const customLayout = get(customLayouts, [index])
collection.items.forEach((item, index) => {
if (item.type === "collection") {
if (item.type === 'collection') {
if (customLayout && customLayout.nestedCollectionLimit) {
item.childCollectionLimit = get(customLayout, ["nestedCollectionLimit", index]);
} else if (nestedCollectionLimit[get(collection, ["associated-metadata", "layout"])]) {
item.childCollectionLimit = get(customLayout, ['nestedCollectionLimit', index])
} else if (nestedCollectionLimit[get(collection, ['associated-metadata', 'layout'])]) {
item.childCollectionLimit =
nestedCollectionLimit[get(collection, ["associated-metadata", "layout"])][index];
nestedCollectionLimit[get(collection, ['associated-metadata', 'layout'])][index]
}
}
});
})
}
});
})

if (collectionOfCollectionsIndexes.length) {
const updatedCollections = collections
Expand All @@ -91,21 +95,30 @@ function updateItemsInPlace(
return updateItemsInPlace(client, 1, childCollection.items, {
storyFields,
storyLimits,
defaultNestedLimit
});
});
return Promise.all(updatedCollections).then(collections => collections);
defaultNestedLimit,
previewId,
qtInternalAppsKey
})
})
return Promise.all(updatedCollections).then(collections => collections)
} else {
return updateItemsInPlace(client, depth - 1, flatMap(collections, collection => collection.items), {
storyFields,
storyLimits,
defaultNestedLimit
});
return updateItemsInPlace(
client,
depth - 1,
flatMap(collections, collection => collection.items),
{
storyFields,
storyLimits,
defaultNestedLimit,
previewId,
qtInternalAppsKey
}
)
}
});
})
}

function loadNestedCollectionData(
function loadNestedCollectionData (
client,
collection,
{
Expand All @@ -115,7 +128,9 @@ function loadNestedCollectionData(
defaultNestedLimit,
nestedCollectionLimit,
collectionOfCollectionsIndexes,
customLayouts
customLayouts,
previewId,
qtInternalAppsKey
}
) {
return updateItemsInPlace(client, depth, collection.items, {
Expand All @@ -124,8 +139,10 @@ function loadNestedCollectionData(
defaultNestedLimit,
nestedCollectionLimit,
collectionOfCollectionsIndexes,
customLayouts
}).then(() => collection);
customLayouts,
previewId,
qtInternalAppsKey
}).then(() => collection)
}

module.exports = { loadNestedCollectionData };
module.exports = { loadNestedCollectionData }
72 changes: 55 additions & 17 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ class Story extends BaseAPI {
* @param {Object} requests
* @see {@link https://developers.quintype.com/swagger/#/story/post_api_v1_c_request POST /api/v1/bulk-request} API documentation for a list of parameters and fields
*/
static getInBulk(client, requests) {
static getInBulk(client, requests, opts = {}) {
function wrapResult(result) {
if (!result.stories) return result;
return Object.assign({}, result, {
Expand All @@ -231,9 +231,12 @@ class Story extends BaseAPI {
}

return client
.getInBulk({
requests: mapValues(r => Object.assign({ _type: "stories" }, r), requests)
})
.getInBulk(
{
requests: mapValues(r => Object.assign({ _type: "stories" }, r), requests)
},
opts
)
.then(response => BulkResults.build(mapValues(result => wrapResult(result), response["results"])));
}
}
Expand Down Expand Up @@ -355,13 +358,15 @@ class Collection extends BaseAPI {
customLayouts = []
} = options;
const storyFields = _.get(params, ["story-fields"], DEFAULT_STORY_FIELDS);

if (!slug) {
return Promise.resolve(null);
}

const opts =
options?.previewId && options?.qtInternalAppsKey
? { previewId: options?.previewId, qtInternalAppsKey: options?.qtInternalAppsKey }
: {};
return client
.getCollectionBySlug(slug, params)
.getCollectionBySlug(slug, params, opts)
.then(response => {
const collection = response ? response["collection"] || response : null;
return (
Expand All @@ -373,7 +378,9 @@ class Collection extends BaseAPI {
defaultNestedLimit,
nestedCollectionLimit,
collectionOfCollectionsIndexes,
customLayouts
customLayouts,
previewId: options?.previewId || "",
qtInternalAppsKey: options?.qtInternalAppsKey || ""
})
);
})
Expand Down Expand Up @@ -919,7 +926,15 @@ class Client {
return this.request("/api/v1/preview/story/" + publicPreviewKey).catch(e => catch404(e, {}));
}

getCollectionBySlug(slug, params) {
getCollectionBySlug(slug, params, opts = {}) {
if (opts?.previewId && opts?.qtInternalAppsKey) {
return this.request(`/api/v1/preview/${opts?.previewId}/collections/${slug}`, {
qs: params,
headers: {
"qt-internal-apps-key": opts?.qtInternalAppsKey
}
}).catch(e => catch404(e, null));
}
return this.request("/api/v1/collections/" + slug, {
qs: params
}).catch(e => catch404(e, null));
Expand Down Expand Up @@ -1041,10 +1056,9 @@ class Client {
});
}

async getInBulk(requests) {
async getInBulk(requests, opts = {}) {
const config = await this.getConfig();
const requestHash = hash({ ...requests, ...{ publisherId: config["publisher-id"] } });

async function getBulkLocation() {
const response = await this.request("/api/v1/bulk-request", {
method: ENABLE_AXIOS ? "post" : "POST",
Expand All @@ -1056,20 +1070,44 @@ class Client {
simple: false,
resolveWithFullResponse: true
});

if (response.statusCode === 303 && response.caseless.get("Location")) {
const contentLocation = response.caseless.get("Location");
await memoryCache.set(requestHash, contentLocation, BULK_REQ_TTL_CACHE);
return contentLocation;
} else {
throw new Error(`Could Not Convert POST bulk to a get, got status ${response.statusCode}`);
}
throw new Error(`Could Not Convert POST bulk to a get, got status ${response.statusCode}`);
}

async function getBulkPreviewData() {
const response = await this.request(`/api/v1/preview/${opts?.previewId}/bulk-request`, {
method: ENABLE_AXIOS ? "post" : "POST",
...(ENABLE_AXIOS && { data: requests }),
...(!ENABLE_AXIOS && { body: requests }),
headers: {
"content-type": "text/plain",
"qt-internal-apps-key": opts?.qtInternalAppsKey
},
simple: false,
resolveWithFullResponse: true
});
if (response.statusCode === 200) {
const data = response.toJSON();
return data?.body;
}
throw new Error(`Could Not Convert POST bulk to a get, got status ${response.statusCode}`);
}

let cachedRequestHash = await memoryCache.get(requestHash);
if (!cachedRequestHash) {
cachedRequestHash = await getBulkLocation.bind(this)();
if (opts?.qtInternalAppsKey && opts?.previewId) {
const data = await getBulkPreviewData.bind(this)();
return data;
} else {
let cachedRequestHash = await memoryCache.get(requestHash);
if (!cachedRequestHash) {
cachedRequestHash = await getBulkLocation.bind(this)();
}
return this.request(cachedRequestHash);
}
return this.request(cachedRequestHash);
}

getAmpStoryBySlug(slug) {
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@quintype/backend",
"version": "2.5.1",
"version": "2.5.2-collection-preview.2",
"description": "client for accessing quintype API",
"main": "index.js",
"scripts": {
Expand Down

0 comments on commit 488edfd

Please sign in to comment.