Added gallery and scans endpoints
This commit is contained in:
parent
1e84ae379b
commit
5afdea7010
|
@ -22,6 +22,10 @@ import { createEditor } from "../../utils/editor";
|
||||||
import { buildVersionedCollectionConfig } from "../../utils/versionedCollectionConfig";
|
import { buildVersionedCollectionConfig } from "../../utils/versionedCollectionConfig";
|
||||||
import { RowLabel } from "./components/RowLabel";
|
import { RowLabel } from "./components/RowLabel";
|
||||||
import { getBySlugEndpoint } from "./endpoints/getBySlugEndpoint";
|
import { getBySlugEndpoint } from "./endpoints/getBySlugEndpoint";
|
||||||
|
import { getBySlugEndpointGallery } from "./endpoints/getBySlugEndpointGallery";
|
||||||
|
import { getBySlugEndpointGalleryImage } from "./endpoints/getBySlugEndpointGalleryImage";
|
||||||
|
import { getBySlugEndpointScanPage } from "./endpoints/getBySlugEndpointScanPage";
|
||||||
|
import { getBySlugEndpointScans } from "./endpoints/getBySlugEndpointScans";
|
||||||
|
|
||||||
const fields = {
|
const fields = {
|
||||||
status: "_status",
|
status: "_status",
|
||||||
|
@ -137,7 +141,13 @@ export const Collectibles = buildVersionedCollectionConfig({
|
||||||
]),
|
]),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
endpoints: [getBySlugEndpoint],
|
endpoints: [
|
||||||
|
getBySlugEndpoint,
|
||||||
|
getBySlugEndpointScans,
|
||||||
|
getBySlugEndpointScanPage,
|
||||||
|
getBySlugEndpointGallery,
|
||||||
|
getBySlugEndpointGalleryImage,
|
||||||
|
],
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
type: "tabs",
|
type: "tabs",
|
||||||
|
|
|
@ -32,7 +32,7 @@ export const convertCollectibleToEndpointCollectible = ({
|
||||||
nature,
|
nature,
|
||||||
urls,
|
urls,
|
||||||
subitems,
|
subitems,
|
||||||
gallery,
|
gallery: rawGallery,
|
||||||
contents,
|
contents,
|
||||||
priceEnabled,
|
priceEnabled,
|
||||||
price,
|
price,
|
||||||
|
@ -50,39 +50,47 @@ export const convertCollectibleToEndpointCollectible = ({
|
||||||
translations,
|
translations,
|
||||||
releaseDate,
|
releaseDate,
|
||||||
languages,
|
languages,
|
||||||
scans,
|
scans: rawScans,
|
||||||
tags,
|
tags,
|
||||||
}: Collectible): EndpointCollectible => ({
|
}: Collectible): EndpointCollectible => {
|
||||||
slug,
|
const gallery = handleGallery(rawGallery);
|
||||||
languages: languages?.map((language) => (isPayloadType(language) ? language.id : language)) ?? [],
|
const scans = handleScans(rawScans);
|
||||||
...(isDefined(releaseDate) ? { releaseDate } : {}),
|
|
||||||
...(isValidPayloadImage(thumbnail) ? { thumbnail: convertImageToEndpointImage(thumbnail) } : {}),
|
return {
|
||||||
...(isValidPayloadImage(backgroundImage)
|
slug,
|
||||||
? { backgroundImage: convertImageToEndpointImage(backgroundImage) }
|
languages:
|
||||||
: {}),
|
languages?.map((language) => (isPayloadType(language) ? language.id : language)) ?? [],
|
||||||
tagGroups: convertTagsEndpointTagsGroups(tags),
|
...(isDefined(releaseDate) ? { releaseDate } : {}),
|
||||||
translations:
|
...(isValidPayloadImage(thumbnail)
|
||||||
translations?.map(({ language, title, description, pretitle, subtitle }) => ({
|
? { thumbnail: convertImageToEndpointImage(thumbnail) }
|
||||||
language: isPayloadType(language) ? language.id : language,
|
: {}),
|
||||||
title,
|
...(isValidPayloadImage(backgroundImage)
|
||||||
...(isNotEmpty(pretitle) ? { pretitle } : {}),
|
? { backgroundImage: convertImageToEndpointImage(backgroundImage) }
|
||||||
...(isNotEmpty(subtitle) ? { subtitle } : {}),
|
: {}),
|
||||||
...(isNotEmpty(description) ? { description } : {}),
|
tagGroups: convertTagsEndpointTagsGroups(tags),
|
||||||
})) ?? [],
|
translations:
|
||||||
contents: handleContents(contents),
|
translations?.map(({ language, title, description, pretitle, subtitle }) => ({
|
||||||
gallery: handleGallery(gallery),
|
language: isPayloadType(language) ? language.id : language,
|
||||||
scans: handleScans(scans),
|
title,
|
||||||
nature: nature === "Physical" ? CollectibleNature.Physical : CollectibleNature.Digital,
|
...(isNotEmpty(pretitle) ? { pretitle } : {}),
|
||||||
parentPages: convertSourceToEndpointSource({ collectibles: parentItems, folders }),
|
...(isNotEmpty(subtitle) ? { subtitle } : {}),
|
||||||
subitems: isPayloadArrayType(subitems)
|
...(isNotEmpty(description) ? { description } : {}),
|
||||||
? subitems.filter(isPublished).map(convertCollectibleToEndpointCollectible)
|
})) ?? [],
|
||||||
: [],
|
contents: handleContents(contents),
|
||||||
urls: urls?.map(({ url }) => ({ url, label: getDomainFromUrl(url) })) ?? [],
|
...(gallery ? { gallery } : {}),
|
||||||
...(weightEnabled && isDefined(weight) ? { weight: weight.amount } : {}),
|
...(scans ? { scans } : {}),
|
||||||
...handleSize(size, sizeEnabled),
|
nature: nature === "Physical" ? CollectibleNature.Physical : CollectibleNature.Digital,
|
||||||
...handlePageInfo(pageInfo, pageInfoEnabled),
|
parentPages: convertSourceToEndpointSource({ collectibles: parentItems, folders }),
|
||||||
...handlePrice(price, priceEnabled),
|
subitems: isPayloadArrayType(subitems)
|
||||||
});
|
? subitems.filter(isPublished).map(convertCollectibleToEndpointCollectible)
|
||||||
|
: [],
|
||||||
|
urls: urls?.map(({ url }) => ({ url, label: getDomainFromUrl(url) })) ?? [],
|
||||||
|
...(weightEnabled && isDefined(weight) ? { weight: weight.amount } : {}),
|
||||||
|
...handleSize(size, sizeEnabled),
|
||||||
|
...handlePageInfo(pageInfo, pageInfoEnabled),
|
||||||
|
...handlePrice(price, priceEnabled),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const handlePrice = (
|
const handlePrice = (
|
||||||
price: Collectible["price"],
|
price: Collectible["price"],
|
||||||
|
@ -122,13 +130,11 @@ const handlePageInfo = (
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleGallery = (gallery: Collectible["gallery"]): EndpointCollectible["gallery"] =>
|
const handleGallery = (gallery: Collectible["gallery"]): EndpointCollectible["gallery"] => {
|
||||||
gallery
|
const thumbnail = gallery?.[0]?.image;
|
||||||
?.flatMap(({ image }) => {
|
if (!thumbnail || !isValidPayloadImage(thumbnail)) return;
|
||||||
if (!isValidPayloadImage(image)) return [];
|
return { count: gallery.length, thumbnail: convertImageToEndpointImage(thumbnail) };
|
||||||
return convertImageToEndpointImage(image);
|
};
|
||||||
})
|
|
||||||
.slice(0, 10) ?? [];
|
|
||||||
|
|
||||||
const handleScans = (scans: Collectible["scans"]): EndpointCollectible["scans"] => {
|
const handleScans = (scans: Collectible["scans"]): EndpointCollectible["scans"] => {
|
||||||
const result =
|
const result =
|
||||||
|
@ -137,23 +143,23 @@ const handleScans = (scans: Collectible["scans"]): EndpointCollectible["scans"]
|
||||||
return image;
|
return image;
|
||||||
}) ?? [];
|
}) ?? [];
|
||||||
|
|
||||||
|
const totalCount =
|
||||||
|
Object.keys(scans?.cover ?? {}).length +
|
||||||
|
Object.keys(scans?.dustjacket ?? {}).length +
|
||||||
|
Object.keys(scans?.obi ?? {}).length +
|
||||||
|
result.length;
|
||||||
|
|
||||||
if (isValidPayloadImage(scans?.cover?.front)) {
|
if (isValidPayloadImage(scans?.cover?.front)) {
|
||||||
result.push(scans.cover.front);
|
result.push(scans.cover.front);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isValidPayloadImage(scans?.cover?.back)) {
|
|
||||||
result.push(scans.cover.back);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isValidPayloadImage(scans?.dustjacket?.front)) {
|
if (isValidPayloadImage(scans?.dustjacket?.front)) {
|
||||||
result.push(scans.dustjacket.front);
|
result.push(scans.dustjacket.front);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isValidPayloadImage(scans?.dustjacket?.back)) {
|
const thumbnail = result?.[0];
|
||||||
result.push(scans.dustjacket.back);
|
if (!thumbnail || !isValidPayloadImage(thumbnail)) return;
|
||||||
}
|
return { count: totalCount, thumbnail };
|
||||||
|
|
||||||
return result.slice(0, 10);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleContents = (contents: Collectible["contents"]): EndpointCollectible["contents"] => {
|
const handleContents = (contents: Collectible["contents"]): EndpointCollectible["contents"] => {
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { Collections } from "../../../constants";
|
||||||
|
import { createGetByEndpoint } from "../../../endpoints/createGetByEndpoint";
|
||||||
|
import { EndpointCollectibleGallery } from "../../../sdk";
|
||||||
|
import { isNotEmpty, isPayloadType, isValidPayloadImage } from "../../../utils/asserts";
|
||||||
|
import { convertSourceToEndpointSource } from "../../../utils/endpoints";
|
||||||
|
import { convertImageToEndpointImage } from "../../Images/endpoints/getByID";
|
||||||
|
|
||||||
|
export const getBySlugEndpointGallery = createGetByEndpoint({
|
||||||
|
collection: Collections.Collectibles,
|
||||||
|
attribute: "slug",
|
||||||
|
suffix: "/gallery",
|
||||||
|
depth: 3,
|
||||||
|
handler: (collectible): EndpointCollectibleGallery => {
|
||||||
|
const { slug, thumbnail, translations, gallery } = collectible;
|
||||||
|
return {
|
||||||
|
slug,
|
||||||
|
translations:
|
||||||
|
translations?.map(({ language, title, description, pretitle, subtitle }) => ({
|
||||||
|
language: isPayloadType(language) ? language.id : language,
|
||||||
|
title,
|
||||||
|
...(isNotEmpty(pretitle) ? { pretitle } : {}),
|
||||||
|
...(isNotEmpty(subtitle) ? { subtitle } : {}),
|
||||||
|
...(isNotEmpty(description) ? { description } : {}),
|
||||||
|
})) ?? [],
|
||||||
|
...(isValidPayloadImage(thumbnail)
|
||||||
|
? { thumbnail: convertImageToEndpointImage(thumbnail) }
|
||||||
|
: {}),
|
||||||
|
images:
|
||||||
|
gallery?.flatMap(({ image }) =>
|
||||||
|
isValidPayloadImage(image) ? convertImageToEndpointImage(image) : []
|
||||||
|
) ?? [],
|
||||||
|
parentPages: convertSourceToEndpointSource({ collectibles: [collectible] }),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,104 @@
|
||||||
|
import payload from "payload";
|
||||||
|
import { Collections } from "../../../constants";
|
||||||
|
import { EndpointCollectibleGalleryImage } from "../../../sdk";
|
||||||
|
import { Collectible, Image } from "../../../types/collections";
|
||||||
|
import { CollectionEndpoint } from "../../../types/payload";
|
||||||
|
import { isDefined, isNotEmpty, isPayloadType, isValidPayloadImage } from "../../../utils/asserts";
|
||||||
|
import { convertSourceToEndpointSource } from "../../../utils/endpoints";
|
||||||
|
import { convertImageToEndpointImage } from "../../Images/endpoints/getByID";
|
||||||
|
|
||||||
|
export const getBySlugEndpointGalleryImage: CollectionEndpoint = {
|
||||||
|
path: "/slug/:slug/gallery/:index",
|
||||||
|
method: "get",
|
||||||
|
handler: async (req, res) => {
|
||||||
|
if (!req.user) {
|
||||||
|
return res.status(403).send({
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message: "You are not allowed to perform this action.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { slug, index } = req.params;
|
||||||
|
|
||||||
|
if (!slug) {
|
||||||
|
return res.status(400).send({ error: "Missing 'slug' in endpoint path" });
|
||||||
|
}
|
||||||
|
if (!index) {
|
||||||
|
return res.status(400).send({ error: "Missing 'index' in endpoint path" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await payload.find({
|
||||||
|
collection: Collections.Collectibles,
|
||||||
|
where: { slug: { equals: slug } },
|
||||||
|
});
|
||||||
|
|
||||||
|
const collectible = result.docs[0];
|
||||||
|
|
||||||
|
if (!collectible || !collectible.gallery) {
|
||||||
|
return res.sendStatus(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
const image = getImageFromIndex(index, collectible.gallery);
|
||||||
|
|
||||||
|
if (!image || !isValidPayloadImage(image)) {
|
||||||
|
return res.sendStatus(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
const previousIndex = getPreviousIndex(index);
|
||||||
|
const nextIndex = getNextIndex(index, collectible.gallery);
|
||||||
|
|
||||||
|
const scanPage: EndpointCollectibleGalleryImage = {
|
||||||
|
image: convertImageToEndpointImage(image),
|
||||||
|
parentPages: convertSourceToEndpointSource({ gallery: [collectible] }),
|
||||||
|
slug,
|
||||||
|
...(isValidPayloadImage(collectible.thumbnail)
|
||||||
|
? { thumbnail: convertImageToEndpointImage(collectible.thumbnail) }
|
||||||
|
: {}),
|
||||||
|
translations:
|
||||||
|
collectible.translations?.map(({ language, title, description, pretitle, subtitle }) => ({
|
||||||
|
language: isPayloadType(language) ? language.id : language,
|
||||||
|
title,
|
||||||
|
...(isNotEmpty(pretitle) ? { pretitle } : {}),
|
||||||
|
...(isNotEmpty(subtitle) ? { subtitle } : {}),
|
||||||
|
...(isNotEmpty(description) ? { description } : {}),
|
||||||
|
})) ?? [],
|
||||||
|
...(isDefined(previousIndex) ? { previousIndex } : {}),
|
||||||
|
...(isDefined(nextIndex) ? { nextIndex } : {}),
|
||||||
|
};
|
||||||
|
|
||||||
|
res.status(200).send(scanPage);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const getPreviousIndex = (index: string): string | undefined => {
|
||||||
|
const pageIndex = parseInt(index, 10);
|
||||||
|
if (isNaN(pageIndex)) return;
|
||||||
|
if (pageIndex <= 0) return;
|
||||||
|
return (pageIndex - 1).toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getNextIndex = (
|
||||||
|
index: string,
|
||||||
|
gallery: NonNullable<Collectible["gallery"]>
|
||||||
|
): string | undefined => {
|
||||||
|
const pageIndex = parseInt(index, 10);
|
||||||
|
if (isNaN(pageIndex)) return;
|
||||||
|
if (pageIndex >= gallery.length - 1) return;
|
||||||
|
return (pageIndex + 1).toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getImageFromIndex = (
|
||||||
|
index: string,
|
||||||
|
gallery: NonNullable<Collectible["gallery"]>
|
||||||
|
): string | Image | null | undefined => {
|
||||||
|
const pageIndex = parseInt(index, 10);
|
||||||
|
if (isNaN(pageIndex)) return;
|
||||||
|
|
||||||
|
const page = gallery[pageIndex];
|
||||||
|
if (!page) return;
|
||||||
|
|
||||||
|
return page.image;
|
||||||
|
};
|
|
@ -0,0 +1,179 @@
|
||||||
|
import payload from "payload";
|
||||||
|
import { Collections } from "../../../constants";
|
||||||
|
import { EndpointCollectibleScanPage } from "../../../sdk";
|
||||||
|
import { Collectible, Scan } from "../../../types/collections";
|
||||||
|
import { CollectionEndpoint } from "../../../types/payload";
|
||||||
|
import { isDefined, isNotEmpty, isPayloadType, isValidPayloadImage } from "../../../utils/asserts";
|
||||||
|
import { convertSourceToEndpointSource } from "../../../utils/endpoints";
|
||||||
|
import { convertImageToEndpointImage } from "../../Images/endpoints/getByID";
|
||||||
|
|
||||||
|
export const getBySlugEndpointScanPage: CollectionEndpoint = {
|
||||||
|
path: "/slug/:slug/scans/:index",
|
||||||
|
method: "get",
|
||||||
|
handler: async (req, res) => {
|
||||||
|
if (!req.user) {
|
||||||
|
return res.status(403).send({
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message: "You are not allowed to perform this action.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { slug, index } = req.params;
|
||||||
|
|
||||||
|
if (!slug) {
|
||||||
|
return res.status(400).send({ error: "Missing 'slug' in endpoint path" });
|
||||||
|
}
|
||||||
|
if (!index) {
|
||||||
|
return res.status(400).send({ error: "Missing 'index' in endpoint path" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await payload.find({
|
||||||
|
collection: Collections.Collectibles,
|
||||||
|
where: { slug: { equals: slug } },
|
||||||
|
});
|
||||||
|
|
||||||
|
const collectible = result.docs[0];
|
||||||
|
|
||||||
|
if (!collectible || !collectible.scansEnabled || !collectible.scans) {
|
||||||
|
return res.sendStatus(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
const image = getImageFromIndex(index, collectible.scans);
|
||||||
|
|
||||||
|
if (!image || !isValidPayloadImage(image)) {
|
||||||
|
return res.sendStatus(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
const previousIndex = getPreviousIndex(index, collectible.scans);
|
||||||
|
const nextIndex = getNextIndex(index, collectible.scans);
|
||||||
|
|
||||||
|
const scanPage: EndpointCollectibleScanPage = {
|
||||||
|
image: { ...image, index },
|
||||||
|
parentPages: convertSourceToEndpointSource({ scans: [collectible] }),
|
||||||
|
slug,
|
||||||
|
...(isValidPayloadImage(collectible.thumbnail)
|
||||||
|
? { thumbnail: convertImageToEndpointImage(collectible.thumbnail) }
|
||||||
|
: {}),
|
||||||
|
translations:
|
||||||
|
collectible.translations?.map(({ language, title, description, pretitle, subtitle }) => ({
|
||||||
|
language: isPayloadType(language) ? language.id : language,
|
||||||
|
title,
|
||||||
|
...(isNotEmpty(pretitle) ? { pretitle } : {}),
|
||||||
|
...(isNotEmpty(subtitle) ? { subtitle } : {}),
|
||||||
|
...(isNotEmpty(description) ? { description } : {}),
|
||||||
|
})) ?? [],
|
||||||
|
...(isDefined(previousIndex) ? { previousIndex } : {}),
|
||||||
|
...(isDefined(nextIndex) ? { nextIndex } : {}),
|
||||||
|
};
|
||||||
|
|
||||||
|
res.status(200).send(scanPage);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const getPreviousIndex = (
|
||||||
|
index: string,
|
||||||
|
scans: NonNullable<Collectible["scans"]>
|
||||||
|
): string | undefined => {
|
||||||
|
const pageIndex = parseInt(index, 10);
|
||||||
|
if (isNaN(pageIndex)) return;
|
||||||
|
|
||||||
|
const page = scans.pages?.find(({ page }) => page === pageIndex - 1);
|
||||||
|
if (!page) return;
|
||||||
|
|
||||||
|
return page.page.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getNextIndex = (
|
||||||
|
index: string,
|
||||||
|
scans: NonNullable<Collectible["scans"]>
|
||||||
|
): string | undefined => {
|
||||||
|
const pageIndex = parseInt(index, 10);
|
||||||
|
if (isNaN(pageIndex)) return;
|
||||||
|
|
||||||
|
const page = scans.pages?.find(({ page }) => page === pageIndex + 1);
|
||||||
|
if (!page) return;
|
||||||
|
|
||||||
|
return page.page.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getImageFromIndex = (
|
||||||
|
index: string,
|
||||||
|
scans: NonNullable<Collectible["scans"]>
|
||||||
|
): string | Scan | null | undefined => {
|
||||||
|
switch (index) {
|
||||||
|
case "cover-flap-front":
|
||||||
|
return scans.cover?.flapFront;
|
||||||
|
case "cover-front":
|
||||||
|
return scans.cover?.front;
|
||||||
|
case "cover-spine":
|
||||||
|
return scans.cover?.spine;
|
||||||
|
case "cover-back":
|
||||||
|
return scans.cover?.back;
|
||||||
|
case "cover-flap-back":
|
||||||
|
return scans.cover?.flapBack;
|
||||||
|
|
||||||
|
case "cover-inside-flap-front":
|
||||||
|
return scans.cover?.insideFlapFront;
|
||||||
|
case "cover-inside-front":
|
||||||
|
return scans.cover?.insideFront;
|
||||||
|
case "cover-inside-back":
|
||||||
|
return scans.cover?.insideBack;
|
||||||
|
case "cover-inside-flap-back":
|
||||||
|
return scans.cover?.insideFlapBack;
|
||||||
|
|
||||||
|
case "dustjacket-flap-front":
|
||||||
|
return scans.dustjacket?.flapFront;
|
||||||
|
case "dustjacket-front":
|
||||||
|
return scans.dustjacket?.front;
|
||||||
|
case "dustjacket-spine":
|
||||||
|
return scans.dustjacket?.spine;
|
||||||
|
case "dustjacket-back":
|
||||||
|
return scans.dustjacket?.back;
|
||||||
|
case "dustjacket-flap-back":
|
||||||
|
return scans.dustjacket?.flapBack;
|
||||||
|
|
||||||
|
case "dustjacket-inside-flap-front":
|
||||||
|
return scans.dustjacket?.insideFlapFront;
|
||||||
|
case "dustjacket-inside-front":
|
||||||
|
return scans.dustjacket?.insideFront;
|
||||||
|
case "dustjacket-inside-spine":
|
||||||
|
return scans.dustjacket?.insideSpine;
|
||||||
|
case "dustjacket-inside-back":
|
||||||
|
return scans.dustjacket?.insideBack;
|
||||||
|
case "dustjacket-inside-flap-back":
|
||||||
|
return scans.dustjacket?.insideFlapBack;
|
||||||
|
|
||||||
|
case "obi-flap-front":
|
||||||
|
return scans.obi?.flapFront;
|
||||||
|
case "obi-front":
|
||||||
|
return scans.obi?.front;
|
||||||
|
case "obi-spine":
|
||||||
|
return scans.obi?.spine;
|
||||||
|
case "obi-back":
|
||||||
|
return scans.obi?.back;
|
||||||
|
case "obi-flap-back":
|
||||||
|
return scans.obi?.flapBack;
|
||||||
|
|
||||||
|
case "obi-inside-flap-front":
|
||||||
|
return scans.obi?.insideFlapFront;
|
||||||
|
case "obi-inside-front":
|
||||||
|
return scans.obi?.insideFront;
|
||||||
|
case "obi-inside-spine":
|
||||||
|
return scans.obi?.insideSpine;
|
||||||
|
case "obi-inside-back":
|
||||||
|
return scans.obi?.insideBack;
|
||||||
|
case "obi-inside-flap-back":
|
||||||
|
return scans.obi?.insideFlapBack;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pageIndex = parseInt(index, 10);
|
||||||
|
if (isNaN(pageIndex)) return;
|
||||||
|
|
||||||
|
const page = scans.pages?.find(({ page }) => page === pageIndex);
|
||||||
|
if (!page) return;
|
||||||
|
|
||||||
|
return page.image;
|
||||||
|
};
|
|
@ -0,0 +1,167 @@
|
||||||
|
import { Collections } from "../../../constants";
|
||||||
|
import { createGetByEndpoint } from "../../../endpoints/createGetByEndpoint";
|
||||||
|
import { EndpointCollectibleScans } from "../../../sdk";
|
||||||
|
import { Collectible } from "../../../types/collections";
|
||||||
|
import { isNotEmpty, isPayloadType, isValidPayloadImage } from "../../../utils/asserts";
|
||||||
|
import {
|
||||||
|
convertCreditsToEndpointCredits,
|
||||||
|
convertSourceToEndpointSource,
|
||||||
|
} from "../../../utils/endpoints";
|
||||||
|
import { convertImageToEndpointImage } from "../../Images/endpoints/getByID";
|
||||||
|
|
||||||
|
export const getBySlugEndpointScans = createGetByEndpoint({
|
||||||
|
collection: Collections.Collectibles,
|
||||||
|
attribute: "slug",
|
||||||
|
suffix: "/scans",
|
||||||
|
depth: 3,
|
||||||
|
handler: (collectible): EndpointCollectibleScans => {
|
||||||
|
const { slug, thumbnail, translations, scans, scansEnabled } = collectible;
|
||||||
|
return {
|
||||||
|
slug,
|
||||||
|
translations:
|
||||||
|
translations?.map(({ language, title, description, pretitle, subtitle }) => ({
|
||||||
|
language: isPayloadType(language) ? language.id : language,
|
||||||
|
title,
|
||||||
|
...(isNotEmpty(pretitle) ? { pretitle } : {}),
|
||||||
|
...(isNotEmpty(subtitle) ? { subtitle } : {}),
|
||||||
|
...(isNotEmpty(description) ? { description } : {}),
|
||||||
|
})) ?? [],
|
||||||
|
...(isValidPayloadImage(thumbnail)
|
||||||
|
? { thumbnail: convertImageToEndpointImage(thumbnail) }
|
||||||
|
: {}),
|
||||||
|
...(scansEnabled && scans ? handleScans(scans) : { credits: [], pages: [] }),
|
||||||
|
parentPages: convertSourceToEndpointSource({ collectibles: [collectible] }),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleScans = ({
|
||||||
|
credits,
|
||||||
|
cover,
|
||||||
|
coverEnabled,
|
||||||
|
dustjacket,
|
||||||
|
dustjacketEnabled,
|
||||||
|
obi,
|
||||||
|
obiEnabled,
|
||||||
|
pages,
|
||||||
|
}: NonNullable<Collectible["scans"]>): Pick<
|
||||||
|
EndpointCollectibleScans,
|
||||||
|
"cover" | "obi" | "dustjacket" | "pages" | "credits"
|
||||||
|
> => ({
|
||||||
|
credits: convertCreditsToEndpointCredits(credits),
|
||||||
|
pages:
|
||||||
|
pages?.flatMap(({ image, page }) =>
|
||||||
|
isValidPayloadImage(image) ? { ...image, index: page.toString() } : []
|
||||||
|
) ?? [],
|
||||||
|
...(coverEnabled && cover ? { cover: handleCover(cover) } : {}),
|
||||||
|
...(dustjacketEnabled && dustjacket ? { dustjacket: handleDustjacket(dustjacket) } : {}),
|
||||||
|
...(obiEnabled && obi ? { obi: handleObi(obi) } : {}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleCover = ({
|
||||||
|
back,
|
||||||
|
flapBack,
|
||||||
|
flapFront,
|
||||||
|
front,
|
||||||
|
insideBack,
|
||||||
|
insideFlapBack,
|
||||||
|
insideFlapFront,
|
||||||
|
insideFront,
|
||||||
|
spine,
|
||||||
|
}: NonNullable<NonNullable<Collectible["scans"]>["cover"]>): EndpointCollectibleScans["cover"] => ({
|
||||||
|
...(isValidPayloadImage(back) ? { back: { ...back, index: "cover-back" } } : {}),
|
||||||
|
...(isValidPayloadImage(flapBack) ? { flapBack: { ...flapBack, index: "cover-flap-back" } } : {}),
|
||||||
|
...(isValidPayloadImage(flapFront)
|
||||||
|
? { flapFront: { ...flapFront, index: "cover-flap-front" } }
|
||||||
|
: {}),
|
||||||
|
...(isValidPayloadImage(front) ? { front: { ...front, index: "cover-front" } } : {}),
|
||||||
|
...(isValidPayloadImage(insideBack)
|
||||||
|
? { insideBack: { ...insideBack, index: "cover-inside-back" } }
|
||||||
|
: {}),
|
||||||
|
...(isValidPayloadImage(insideFlapBack)
|
||||||
|
? { insideFlapBack: { ...insideFlapBack, index: "cover-inside-flap-back" } }
|
||||||
|
: {}),
|
||||||
|
...(isValidPayloadImage(insideFlapFront)
|
||||||
|
? { insideFlapFront: { ...insideFlapFront, index: "cover-inside-flap-front" } }
|
||||||
|
: {}),
|
||||||
|
...(isValidPayloadImage(insideFront)
|
||||||
|
? { insideFront: { ...insideFront, index: "cover-inside-front" } }
|
||||||
|
: {}),
|
||||||
|
...(isValidPayloadImage(spine) ? { spine: { ...spine, index: "cover-spine" } } : {}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleDustjacket = ({
|
||||||
|
back,
|
||||||
|
flapBack,
|
||||||
|
flapFront,
|
||||||
|
front,
|
||||||
|
insideBack,
|
||||||
|
insideFlapBack,
|
||||||
|
insideFlapFront,
|
||||||
|
insideFront,
|
||||||
|
insideSpine,
|
||||||
|
spine,
|
||||||
|
}: NonNullable<
|
||||||
|
NonNullable<Collectible["scans"]>["dustjacket"]
|
||||||
|
>): EndpointCollectibleScans["dustjacket"] => ({
|
||||||
|
...(isValidPayloadImage(back) ? { back: { ...back, index: "dustjacket-back" } } : {}),
|
||||||
|
...(isValidPayloadImage(flapBack)
|
||||||
|
? { flapBack: { ...flapBack, index: "dustjacket-flap-back" } }
|
||||||
|
: {}),
|
||||||
|
...(isValidPayloadImage(flapFront)
|
||||||
|
? { flapFront: { ...flapFront, index: "dustjacket-flap-front" } }
|
||||||
|
: {}),
|
||||||
|
...(isValidPayloadImage(front) ? { front: { ...front, index: "dustjacket-front" } } : {}),
|
||||||
|
...(isValidPayloadImage(insideBack)
|
||||||
|
? { insideBack: { ...insideBack, index: "dustjacket-inside-back" } }
|
||||||
|
: {}),
|
||||||
|
...(isValidPayloadImage(insideFlapBack)
|
||||||
|
? { insideFlapBack: { ...insideFlapBack, index: "dustjacket-inside-flap-back" } }
|
||||||
|
: {}),
|
||||||
|
...(isValidPayloadImage(insideFlapFront)
|
||||||
|
? { insideFlapFront: { ...insideFlapFront, index: "dustjacket-inside-flap-front" } }
|
||||||
|
: {}),
|
||||||
|
...(isValidPayloadImage(insideFront)
|
||||||
|
? { insideFront: { ...insideFront, index: "dustjacket-inside-front" } }
|
||||||
|
: {}),
|
||||||
|
...(isValidPayloadImage(spine) ? { spine: { ...spine, index: "dustjacket-spine" } } : {}),
|
||||||
|
...(isValidPayloadImage(insideSpine)
|
||||||
|
? { insideSpine: { ...insideSpine, index: "dustjacket-inside-spine" } }
|
||||||
|
: {}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleObi = ({
|
||||||
|
back,
|
||||||
|
flapBack,
|
||||||
|
flapFront,
|
||||||
|
front,
|
||||||
|
insideBack,
|
||||||
|
insideFlapBack,
|
||||||
|
insideFlapFront,
|
||||||
|
insideFront,
|
||||||
|
insideSpine,
|
||||||
|
spine,
|
||||||
|
}: NonNullable<NonNullable<Collectible["scans"]>["obi"]>): EndpointCollectibleScans["obi"] => ({
|
||||||
|
...(isValidPayloadImage(back) ? { back: { ...back, index: "obi-back" } } : {}),
|
||||||
|
...(isValidPayloadImage(flapBack) ? { flapBack: { ...flapBack, index: "obi-flap-back" } } : {}),
|
||||||
|
...(isValidPayloadImage(flapFront)
|
||||||
|
? { flapFront: { ...flapFront, index: "obi-flap-front" } }
|
||||||
|
: {}),
|
||||||
|
...(isValidPayloadImage(front) ? { front: { ...front, index: "obi-front" } } : {}),
|
||||||
|
...(isValidPayloadImage(insideBack)
|
||||||
|
? { insideBack: { ...insideBack, index: "obi-inside-back" } }
|
||||||
|
: {}),
|
||||||
|
...(isValidPayloadImage(insideFlapBack)
|
||||||
|
? { insideFlapBack: { ...insideFlapBack, index: "obi-inside-flap-back" } }
|
||||||
|
: {}),
|
||||||
|
...(isValidPayloadImage(insideFlapFront)
|
||||||
|
? { insideFlapFront: { ...insideFlapFront, index: "obi-inside-flap-front" } }
|
||||||
|
: {}),
|
||||||
|
...(isValidPayloadImage(insideFront)
|
||||||
|
? { insideFront: { ...insideFront, index: "obi-inside-front" } }
|
||||||
|
: {}),
|
||||||
|
...(isValidPayloadImage(spine) ? { spine: { ...spine, index: "obi-spine" } } : {}),
|
||||||
|
...(isValidPayloadImage(insideSpine)
|
||||||
|
? { insideSpine: { ...insideSpine, index: "obi-inside-spine" } }
|
||||||
|
: {}),
|
||||||
|
});
|
|
@ -7,6 +7,7 @@ interface Params<C extends keyof GeneratedTypes["collections"], R> {
|
||||||
attribute: string;
|
attribute: string;
|
||||||
handler: (doc: GeneratedTypes["collections"][C]) => Promise<R> | R;
|
handler: (doc: GeneratedTypes["collections"][C]) => Promise<R> | R;
|
||||||
depth?: number;
|
depth?: number;
|
||||||
|
suffix?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createGetByEndpoint = <C extends keyof GeneratedTypes["collections"], R>({
|
export const createGetByEndpoint = <C extends keyof GeneratedTypes["collections"], R>({
|
||||||
|
@ -14,8 +15,9 @@ export const createGetByEndpoint = <C extends keyof GeneratedTypes["collections"
|
||||||
collection,
|
collection,
|
||||||
handler,
|
handler,
|
||||||
depth,
|
depth,
|
||||||
|
suffix = "",
|
||||||
}: Params<C, R>): CollectionEndpoint => ({
|
}: Params<C, R>): CollectionEndpoint => ({
|
||||||
path: `/${attribute}/:${attribute}`,
|
path: `/${attribute}/:${attribute}${suffix}`,
|
||||||
method: "get",
|
method: "get",
|
||||||
handler: async (req, res) => {
|
handler: async (req, res) => {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
|
|
124
src/sdk.ts
124
src/sdk.ts
|
@ -233,8 +233,8 @@ export type EndpointCollectible = {
|
||||||
languages: string[];
|
languages: string[];
|
||||||
backgroundImage?: EndpointImage;
|
backgroundImage?: EndpointImage;
|
||||||
nature: CollectibleNature;
|
nature: CollectibleNature;
|
||||||
gallery: EndpointImage[];
|
gallery?: { count: number; thumbnail: EndpointImage };
|
||||||
scans: PayloadImage[];
|
scans?: { count: number; thumbnail: PayloadImage };
|
||||||
urls: { url: string; label: string }[];
|
urls: { url: string; label: string }[];
|
||||||
price?: {
|
price?: {
|
||||||
amount: number;
|
amount: number;
|
||||||
|
@ -298,6 +298,104 @@ export type EndpointCollectible = {
|
||||||
parentPages: EndpointSource[];
|
parentPages: EndpointSource[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type EndpointCollectibleScans = {
|
||||||
|
slug: string;
|
||||||
|
thumbnail?: EndpointImage;
|
||||||
|
translations: {
|
||||||
|
language: string;
|
||||||
|
pretitle?: string;
|
||||||
|
title: string;
|
||||||
|
subtitle?: string;
|
||||||
|
description?: RichTextContent;
|
||||||
|
}[];
|
||||||
|
credits: EndpointCredit[];
|
||||||
|
cover?: {
|
||||||
|
front?: EndpointScanImage;
|
||||||
|
spine?: EndpointScanImage;
|
||||||
|
back?: EndpointScanImage;
|
||||||
|
insideFront?: EndpointScanImage;
|
||||||
|
insideBack?: EndpointScanImage;
|
||||||
|
flapFront?: EndpointScanImage;
|
||||||
|
flapBack?: EndpointScanImage;
|
||||||
|
insideFlapFront?: EndpointScanImage;
|
||||||
|
insideFlapBack?: EndpointScanImage;
|
||||||
|
};
|
||||||
|
dustjacket?: {
|
||||||
|
front?: EndpointScanImage;
|
||||||
|
spine?: EndpointScanImage;
|
||||||
|
back?: EndpointScanImage;
|
||||||
|
insideFront?: EndpointScanImage;
|
||||||
|
insideSpine?: EndpointScanImage;
|
||||||
|
insideBack?: EndpointScanImage;
|
||||||
|
flapFront?: EndpointScanImage;
|
||||||
|
flapBack?: EndpointScanImage;
|
||||||
|
insideFlapFront?: EndpointScanImage;
|
||||||
|
insideFlapBack?: EndpointScanImage;
|
||||||
|
};
|
||||||
|
obi?: {
|
||||||
|
front?: EndpointScanImage;
|
||||||
|
spine?: EndpointScanImage;
|
||||||
|
back?: EndpointScanImage;
|
||||||
|
insideFront?: EndpointScanImage;
|
||||||
|
insideSpine?: EndpointScanImage;
|
||||||
|
insideBack?: EndpointScanImage;
|
||||||
|
flapFront?: EndpointScanImage;
|
||||||
|
flapBack?: EndpointScanImage;
|
||||||
|
insideFlapFront?: EndpointScanImage;
|
||||||
|
insideFlapBack?: EndpointScanImage;
|
||||||
|
};
|
||||||
|
pages: EndpointScanImage[];
|
||||||
|
parentPages: EndpointSource[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EndpointCollectibleGallery = {
|
||||||
|
slug: string;
|
||||||
|
thumbnail?: EndpointImage;
|
||||||
|
translations: {
|
||||||
|
language: string;
|
||||||
|
pretitle?: string;
|
||||||
|
title: string;
|
||||||
|
subtitle?: string;
|
||||||
|
description?: RichTextContent;
|
||||||
|
}[];
|
||||||
|
images: EndpointImage[];
|
||||||
|
parentPages: EndpointSource[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EndpointCollectibleGalleryImage = {
|
||||||
|
slug: string;
|
||||||
|
thumbnail?: EndpointImage;
|
||||||
|
translations: {
|
||||||
|
language: string;
|
||||||
|
pretitle?: string;
|
||||||
|
title: string;
|
||||||
|
subtitle?: string;
|
||||||
|
}[];
|
||||||
|
image: EndpointImage;
|
||||||
|
previousIndex?: string;
|
||||||
|
nextIndex?: string;
|
||||||
|
parentPages: EndpointSource[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EndpointCollectibleScanPage = {
|
||||||
|
slug: string;
|
||||||
|
thumbnail?: EndpointImage;
|
||||||
|
translations: {
|
||||||
|
language: string;
|
||||||
|
pretitle?: string;
|
||||||
|
title: string;
|
||||||
|
subtitle?: string;
|
||||||
|
}[];
|
||||||
|
image: EndpointScanImage;
|
||||||
|
previousIndex?: string;
|
||||||
|
nextIndex?: string;
|
||||||
|
parentPages: EndpointSource[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EndpointScanImage = PayloadImage & {
|
||||||
|
index: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type TableOfContentEntry = {
|
export type TableOfContentEntry = {
|
||||||
prefix: string;
|
prefix: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -337,7 +435,9 @@ export type EndpointSource =
|
||||||
| { type: "custom"; translations: { language: string; note: string }[] };
|
| { type: "custom"; translations: { language: string; note: string }[] };
|
||||||
}
|
}
|
||||||
| { type: "page"; page: EndpointPage }
|
| { type: "page"; page: EndpointPage }
|
||||||
| { type: "folder"; folder: EndpointFolder };
|
| { type: "folder"; folder: EndpointFolder }
|
||||||
|
| { type: "scans"; collectible: EndpointCollectible }
|
||||||
|
| { type: "gallery"; collectible: EndpointCollectible };
|
||||||
|
|
||||||
export type EndpointMedia = {
|
export type EndpointMedia = {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -416,6 +516,24 @@ export const payload = {
|
||||||
await (await request(payloadApiUrl(Collections.Pages, `slug/${slug}`))).json(),
|
await (await request(payloadApiUrl(Collections.Pages, `slug/${slug}`))).json(),
|
||||||
getCollectible: async (slug: string): Promise<EndpointCollectible> =>
|
getCollectible: async (slug: string): Promise<EndpointCollectible> =>
|
||||||
await (await request(payloadApiUrl(Collections.Collectibles, `slug/${slug}`))).json(),
|
await (await request(payloadApiUrl(Collections.Collectibles, `slug/${slug}`))).json(),
|
||||||
|
getCollectibleScans: async (slug: string): Promise<EndpointCollectibleScans> =>
|
||||||
|
await (await request(payloadApiUrl(Collections.Collectibles, `slug/${slug}/scans`))).json(),
|
||||||
|
getCollectibleScanPage: async (
|
||||||
|
slug: string,
|
||||||
|
index: string
|
||||||
|
): Promise<EndpointCollectibleScanPage> =>
|
||||||
|
await (
|
||||||
|
await request(payloadApiUrl(Collections.Collectibles, `slug/${slug}/scans/${index}`))
|
||||||
|
).json(),
|
||||||
|
getCollectibleGallery: async (slug: string): Promise<EndpointCollectibleGallery> =>
|
||||||
|
await (await request(payloadApiUrl(Collections.Collectibles, `slug/${slug}/gallery`))).json(),
|
||||||
|
getCollectibleGalleryImage: async (
|
||||||
|
slug: string,
|
||||||
|
index: string
|
||||||
|
): Promise<EndpointCollectibleGalleryImage> =>
|
||||||
|
await (
|
||||||
|
await request(payloadApiUrl(Collections.Collectibles, `slug/${slug}/gallery/${index}`))
|
||||||
|
).json(),
|
||||||
getChronologyEvents: async (): Promise<EndpointChronologyEvent[]> =>
|
getChronologyEvents: async (): Promise<EndpointChronologyEvent[]> =>
|
||||||
await (await request(payloadApiUrl(Collections.ChronologyEvents, `all`))).json(),
|
await (await request(payloadApiUrl(Collections.ChronologyEvents, `all`))).json(),
|
||||||
getChronologyEventByID: async (id: string): Promise<EndpointChronologyEvent> =>
|
getChronologyEventByID: async (id: string): Promise<EndpointChronologyEvent> =>
|
||||||
|
|
|
@ -154,8 +154,12 @@ export const convertRTCToEndpointRTC = (
|
||||||
export const convertSourceToEndpointSource = ({
|
export const convertSourceToEndpointSource = ({
|
||||||
collectibles,
|
collectibles,
|
||||||
folders,
|
folders,
|
||||||
|
gallery,
|
||||||
|
scans,
|
||||||
}: {
|
}: {
|
||||||
collectibles?: (string | Collectible)[] | null | undefined;
|
collectibles?: (string | Collectible)[] | null | undefined;
|
||||||
|
scans?: (string | Collectible)[] | null | undefined;
|
||||||
|
gallery?: (string | Collectible)[] | null | undefined;
|
||||||
folders?: (string | Folder)[] | null | undefined;
|
folders?: (string | Folder)[] | null | undefined;
|
||||||
}): EndpointSource[] => {
|
}): EndpointSource[] => {
|
||||||
const result: EndpointSource[] = [];
|
const result: EndpointSource[] = [];
|
||||||
|
@ -169,6 +173,24 @@ export const convertSourceToEndpointSource = ({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (scans && isPayloadArrayType(scans)) {
|
||||||
|
scans.filter(isPublished).forEach((collectible) => {
|
||||||
|
result.push({
|
||||||
|
type: "scans",
|
||||||
|
collectible: convertCollectibleToEndpointCollectible(collectible),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gallery && isPayloadArrayType(gallery)) {
|
||||||
|
gallery.filter(isPublished).forEach((collectible) => {
|
||||||
|
result.push({
|
||||||
|
type: "gallery",
|
||||||
|
collectible: convertCollectibleToEndpointCollectible(collectible),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (folders && isPayloadArrayType(folders)) {
|
if (folders && isPayloadArrayType(folders)) {
|
||||||
folders.forEach((folder) => {
|
folders.forEach((folder) => {
|
||||||
result.push({
|
result.push({
|
||||||
|
|
Loading…
Reference in New Issue