Removed preview types and added media to RTC, collectibles and folders
This commit is contained in:
parent
b15fe7a0ce
commit
40e54ea2a0
|
@ -5,6 +5,7 @@ import { tagsField } from "../../fields/tagsField/tagsField";
|
|||
import { translatedFields } from "../../fields/translatedFields/translatedFields";
|
||||
import { buildCollectionConfig } from "../../utils/collectionConfig";
|
||||
import { createEditor } from "../../utils/editor";
|
||||
import { getByID } from "./endpoints/getByID";
|
||||
|
||||
const fields = {
|
||||
filename: "filename",
|
||||
|
@ -38,6 +39,7 @@ export const Audios = buildCollectionConfig({
|
|||
mimeTypes: ["audio/*"],
|
||||
disableLocalStorage: true,
|
||||
},
|
||||
endpoints: [getByID],
|
||||
fields: [
|
||||
rowField([
|
||||
{ name: fields.duration, type: "number", min: 0, required: true },
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
import payload from "payload";
|
||||
import { Collections } from "../../../constants";
|
||||
import { EndpointAudio, PayloadMedia } from "../../../sdk";
|
||||
import { Audio } from "../../../types/collections";
|
||||
import { CollectionEndpoint } from "../../../types/payload";
|
||||
import { isNotEmpty, isValidPayloadImage, isValidPayloadMedia } from "../../../utils/asserts";
|
||||
import {
|
||||
convertRTCToEndpointRTC,
|
||||
convertTagsEndpointTagsGroups,
|
||||
getLanguageId,
|
||||
} from "../../../utils/endpoints";
|
||||
|
||||
export const getByID: CollectionEndpoint = {
|
||||
method: "get",
|
||||
path: "/id/:id",
|
||||
handler: async (req, res) => {
|
||||
if (!req.user) {
|
||||
return res.status(403).send({
|
||||
errors: [
|
||||
{
|
||||
message: "You are not allowed to perform this action.",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (!req.params.id) {
|
||||
return res.status(400).send({ errors: [{ message: "Missing 'id' query params" }] });
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await payload.findByID({
|
||||
collection: Collections.Audios,
|
||||
id: req.params.id,
|
||||
});
|
||||
|
||||
if (!isValidPayloadMedia(result)) {
|
||||
return res.sendStatus(404);
|
||||
}
|
||||
|
||||
return res.status(200).json(convertAudioToEndpointAudio(result));
|
||||
} catch {
|
||||
return res.sendStatus(404);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export const convertAudioToEndpointAudio = ({
|
||||
url,
|
||||
tags,
|
||||
translations,
|
||||
mimeType,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
filename,
|
||||
filesize,
|
||||
duration,
|
||||
id,
|
||||
thumbnail,
|
||||
}: Audio & PayloadMedia): EndpointAudio => ({
|
||||
url,
|
||||
tagGroups: convertTagsEndpointTagsGroups(tags),
|
||||
createdAt,
|
||||
filename,
|
||||
filesize,
|
||||
id,
|
||||
mimeType,
|
||||
updatedAt,
|
||||
translations:
|
||||
translations?.map(({ language, title, description }) => ({
|
||||
language: getLanguageId(language),
|
||||
title,
|
||||
...(isNotEmpty(description) ? { description: convertRTCToEndpointRTC(description) } : {}),
|
||||
})) ?? [],
|
||||
duration,
|
||||
...(isValidPayloadImage(thumbnail) ? { thumbnail } : {}),
|
||||
});
|
|
@ -4,9 +4,10 @@ import { EndpointChronologyEvent, EndpointSource } from "../../../sdk";
|
|||
import { ChronologyEvent, CollectibleBlock } from "../../../types/collections";
|
||||
import { CollectionEndpoint } from "../../../types/payload";
|
||||
import { isDefined, isNotEmpty, isPayloadArrayType, isPayloadType } from "../../../utils/asserts";
|
||||
import { getDomainFromUrl, handleRecorder } from "../../../utils/endpoints";
|
||||
import { convertCollectibleToPreview } from "../../Collectibles/endpoints/getBySlugEndpoint";
|
||||
import { convertPageToPreview } from "../../Pages/endpoints/getBySlugEndpoint";
|
||||
import { getDomainFromUrl } from "../../../utils/endpoints";
|
||||
import { convertCollectibleToEndpointCollectible } from "../../Collectibles/endpoints/getBySlugEndpoint";
|
||||
import { convertPageToEndpointPage } from "../../Pages/endpoints/getBySlugEndpoint";
|
||||
import { convertRecorderToEndpointRecorder } from "../../Recorders/endpoints/getByUsername";
|
||||
|
||||
export const getAllEndpoint: CollectionEndpoint = {
|
||||
method: "get",
|
||||
|
@ -82,9 +83,15 @@ export const eventToEndpointEvent = ({
|
|||
...(isNotEmpty(title) ? { title } : {}),
|
||||
...(isNotEmpty(description) ? { description } : {}),
|
||||
...(isNotEmpty(notes) ? { notes } : {}),
|
||||
proofreaders: isPayloadArrayType(proofreaders) ? proofreaders.map(handleRecorder) : [],
|
||||
transcribers: isPayloadArrayType(transcribers) ? transcribers.map(handleRecorder) : [],
|
||||
translators: isPayloadArrayType(translators) ? translators.map(handleRecorder) : [],
|
||||
proofreaders: isPayloadArrayType(proofreaders)
|
||||
? proofreaders.map(convertRecorderToEndpointRecorder)
|
||||
: [],
|
||||
transcribers: isPayloadArrayType(transcribers)
|
||||
? transcribers.map(convertRecorderToEndpointRecorder)
|
||||
: [],
|
||||
translators: isPayloadArrayType(translators)
|
||||
? translators.map(convertRecorderToEndpointRecorder)
|
||||
: [],
|
||||
})
|
||||
),
|
||||
sources: handleSources(sources),
|
||||
|
@ -100,7 +107,7 @@ const handleSources = (sources: ChronologyEvent["events"][number]["sources"]): E
|
|||
if (!isPayloadType(source.collectible)) return [];
|
||||
return {
|
||||
type: "collectible",
|
||||
collectible: convertCollectibleToPreview(source.collectible),
|
||||
collectible: convertCollectibleToEndpointCollectible(source.collectible),
|
||||
...(isDefined(range) ? { range } : {}),
|
||||
};
|
||||
|
||||
|
@ -108,7 +115,7 @@ const handleSources = (sources: ChronologyEvent["events"][number]["sources"]): E
|
|||
if (!isPayloadType(source.page)) return [];
|
||||
return {
|
||||
type: "page",
|
||||
page: convertPageToPreview(source.page),
|
||||
page: convertPageToEndpointPage(source.page),
|
||||
};
|
||||
|
||||
case "urlBlock":
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { CollectibleNature, Collections } from "../../../constants";
|
||||
import { createGetByEndpoint } from "../../../endpoints/createGetByEndpoint";
|
||||
import { EndpointCollectible, EndpointCollectiblePreview, PayloadImage } from "../../../sdk";
|
||||
import { EndpointCollectible, PayloadImage } from "../../../sdk";
|
||||
import { Collectible } from "../../../types/collections";
|
||||
import {
|
||||
isDefined,
|
||||
|
@ -9,52 +9,76 @@ import {
|
|||
isPayloadType,
|
||||
isPublished,
|
||||
isValidPayloadImage,
|
||||
isValidPayloadMedia,
|
||||
} from "../../../utils/asserts";
|
||||
import { convertTagsToGroups, getDomainFromUrl, handleParentPages } from "../../../utils/endpoints";
|
||||
import { convertPageToPreview } from "../../Pages/endpoints/getBySlugEndpoint";
|
||||
import {
|
||||
convertSourceToEndpointSource,
|
||||
convertTagsEndpointTagsGroups,
|
||||
getDomainFromUrl,
|
||||
} from "../../../utils/endpoints";
|
||||
import { convertAudioToEndpointAudio } from "../../Audios/endpoints/getByID";
|
||||
import { convertPageToEndpointPage } from "../../Pages/endpoints/getBySlugEndpoint";
|
||||
import { convertVideoToEndpointVideo } from "../../Videos/endpoints/getByID";
|
||||
|
||||
export const getBySlugEndpoint = createGetByEndpoint({
|
||||
collection: Collections.Collectibles,
|
||||
attribute: "slug",
|
||||
depth: 3,
|
||||
handler: (collectible: Collectible): EndpointCollectible => {
|
||||
const {
|
||||
nature,
|
||||
urls,
|
||||
subitems,
|
||||
gallery,
|
||||
contents,
|
||||
priceEnabled,
|
||||
price,
|
||||
size,
|
||||
sizeEnabled,
|
||||
weight,
|
||||
weightEnabled,
|
||||
pageInfo,
|
||||
pageInfoEnabled,
|
||||
parentItems,
|
||||
folders,
|
||||
backgroundImage,
|
||||
} = collectible;
|
||||
handler: (collectible) => convertCollectibleToEndpointCollectible(collectible),
|
||||
});
|
||||
|
||||
return {
|
||||
...convertCollectibleToPreview(collectible),
|
||||
...(isValidPayloadImage(backgroundImage) ? { backgroundImage } : {}),
|
||||
contents: handleContents(contents),
|
||||
gallery: handleGallery(gallery),
|
||||
scans: handleScans(collectible.scans),
|
||||
nature: nature === "Physical" ? CollectibleNature.Physical : CollectibleNature.Digital,
|
||||
parentPages: handleParentPages({ collectibles: parentItems, folders }),
|
||||
subitems: isPayloadArrayType(subitems)
|
||||
? subitems.filter(isPublished).map(convertCollectibleToPreview)
|
||||
: [],
|
||||
urls: urls?.map(({ url }) => ({ url, label: getDomainFromUrl(url) })) ?? [],
|
||||
...(weightEnabled && isDefined(weight) ? { weight: weight.amount } : {}),
|
||||
...handleSize(size, sizeEnabled),
|
||||
...handlePageInfo(pageInfo, pageInfoEnabled),
|
||||
...handlePrice(price, priceEnabled),
|
||||
};
|
||||
},
|
||||
export const convertCollectibleToEndpointCollectible = ({
|
||||
nature,
|
||||
urls,
|
||||
subitems,
|
||||
gallery,
|
||||
contents,
|
||||
priceEnabled,
|
||||
price,
|
||||
size,
|
||||
sizeEnabled,
|
||||
weight,
|
||||
weightEnabled,
|
||||
pageInfo,
|
||||
pageInfoEnabled,
|
||||
parentItems,
|
||||
folders,
|
||||
backgroundImage,
|
||||
slug,
|
||||
thumbnail,
|
||||
translations,
|
||||
releaseDate,
|
||||
languages,
|
||||
scans,
|
||||
tags,
|
||||
}: Collectible): EndpointCollectible => ({
|
||||
slug,
|
||||
languages: languages?.map((language) => (isPayloadType(language) ? language.id : language)) ?? [],
|
||||
...(isDefined(releaseDate) ? { releaseDate } : {}),
|
||||
...(isValidPayloadImage(thumbnail) ? { thumbnail } : {}),
|
||||
tagGroups: convertTagsEndpointTagsGroups(tags),
|
||||
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(backgroundImage) ? { backgroundImage } : {}),
|
||||
contents: handleContents(contents),
|
||||
gallery: handleGallery(gallery),
|
||||
scans: handleScans(scans),
|
||||
nature: nature === "Physical" ? CollectibleNature.Physical : CollectibleNature.Digital,
|
||||
parentPages: convertSourceToEndpointSource({ collectibles: parentItems, folders }),
|
||||
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 = (
|
||||
|
@ -173,10 +197,10 @@ const handleContents = (contents: Collectible["contents"]): EndpointCollectible[
|
|||
|
||||
const handleContent = (): EndpointCollectible["contents"][number]["content"] | undefined => {
|
||||
switch (content.relationTo) {
|
||||
case "generic-contents":
|
||||
case Collections.GenericContents:
|
||||
return isPayloadType(content.value)
|
||||
? {
|
||||
relationTo: "generic-contents",
|
||||
relationTo: Collections.GenericContents,
|
||||
value: {
|
||||
translations: content.value.translations.map(({ language, name }) => ({
|
||||
language: isPayloadType(language) ? language.id : language,
|
||||
|
@ -186,9 +210,19 @@ const handleContents = (contents: Collectible["contents"]): EndpointCollectible[
|
|||
}
|
||||
: undefined;
|
||||
|
||||
case "pages":
|
||||
case Collections.Pages:
|
||||
return isPayloadType(content.value) && isPublished(content.value)
|
||||
? { relationTo: "pages", value: convertPageToPreview(content.value) }
|
||||
? { relationTo: Collections.Pages, value: convertPageToEndpointPage(content.value) }
|
||||
: undefined;
|
||||
|
||||
case Collections.Audios:
|
||||
return isPayloadType(content.value) && isValidPayloadMedia(content.value)
|
||||
? { relationTo: Collections.Audios, value: convertAudioToEndpointAudio(content.value) }
|
||||
: undefined;
|
||||
|
||||
case Collections.Videos:
|
||||
return isPayloadType(content.value) && isValidPayloadMedia(content.value)
|
||||
? { relationTo: Collections.Videos, value: convertVideoToEndpointVideo(content.value) }
|
||||
: undefined;
|
||||
|
||||
default:
|
||||
|
@ -203,29 +237,3 @@ const handleContents = (contents: Collectible["contents"]): EndpointCollectible[
|
|||
return [{ content: newContent, range }];
|
||||
});
|
||||
};
|
||||
|
||||
export const convertCollectibleToPreview = ({
|
||||
slug,
|
||||
thumbnail,
|
||||
translations,
|
||||
releaseDate,
|
||||
languages,
|
||||
tags,
|
||||
}: Collectible): EndpointCollectiblePreview => {
|
||||
return {
|
||||
slug,
|
||||
languages:
|
||||
languages?.map((language) => (isPayloadType(language) ? language.id : language)) ?? [],
|
||||
...(isDefined(releaseDate) ? { releaseDate } : {}),
|
||||
...(isValidPayloadImage(thumbnail) ? { thumbnail } : {}),
|
||||
tagGroups: convertTagsToGroups(tags),
|
||||
translations:
|
||||
translations?.map(({ language, title, description, pretitle, subtitle }) => ({
|
||||
language: isPayloadType(language) ? language.id : language,
|
||||
title,
|
||||
...(isNotEmpty(pretitle) ? { pretitle } : {}),
|
||||
...(isNotEmpty(subtitle) ? { subtitle } : {}),
|
||||
...(isNotEmpty(description) ? { description } : {}),
|
||||
})) ?? [],
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,79 +1,95 @@
|
|||
import { Collections } from "../../../constants";
|
||||
import { createGetByEndpoint } from "../../../endpoints/createGetByEndpoint";
|
||||
import { EndpointFolder, EndpointFolderPreview } from "../../../sdk";
|
||||
import { EndpointFolder } from "../../../sdk";
|
||||
import { Folder, Language } from "../../../types/collections";
|
||||
import { isDefined, isNotEmpty, isPayloadType, isPublished } from "../../../utils/asserts";
|
||||
import { handleParentPages } from "../../../utils/endpoints";
|
||||
import { convertCollectibleToPreview } from "../../Collectibles/endpoints/getBySlugEndpoint";
|
||||
import { convertPageToPreview } from "../../Pages/endpoints/getBySlugEndpoint";
|
||||
import {
|
||||
isDefined,
|
||||
isNotEmpty,
|
||||
isPayloadType,
|
||||
isPublished,
|
||||
isValidPayloadImage,
|
||||
isValidPayloadMedia,
|
||||
} from "../../../utils/asserts";
|
||||
import { convertSourceToEndpointSource, getLanguageId } from "../../../utils/endpoints";
|
||||
import { convertAudioToEndpointAudio } from "../../Audios/endpoints/getByID";
|
||||
import { convertCollectibleToEndpointCollectible } from "../../Collectibles/endpoints/getBySlugEndpoint";
|
||||
import { convertImageToEndpointImage } from "../../Images/endpoints/getByID";
|
||||
import { convertPageToEndpointPage } from "../../Pages/endpoints/getBySlugEndpoint";
|
||||
import { convertVideoToEndpointVideo } from "../../Videos/endpoints/getByID";
|
||||
|
||||
export const getBySlugEndpoint = createGetByEndpoint({
|
||||
collection: Collections.Folders,
|
||||
attribute: "slug",
|
||||
depth: 3,
|
||||
handler: (folder: Folder): EndpointFolder => {
|
||||
const { sections, files, parentFolders } = folder;
|
||||
return {
|
||||
...convertFolderToPreview(folder),
|
||||
sections:
|
||||
sections?.length === 1
|
||||
? {
|
||||
type: "single",
|
||||
subfolders:
|
||||
sections[0]?.subfolders?.filter(isPayloadType).map(convertFolderToPreview) ?? [],
|
||||
}
|
||||
: {
|
||||
type: "multiple",
|
||||
sections:
|
||||
sections?.filter(isValidSection).map(({ translations, subfolders }) => ({
|
||||
translations: translations.map(({ language, name }) => ({
|
||||
language: getLanguageId(language),
|
||||
name,
|
||||
})),
|
||||
subfolders: subfolders.map(convertFolderToPreview),
|
||||
})) ?? [],
|
||||
},
|
||||
files:
|
||||
files?.flatMap<EndpointFolder["files"][number]>(({ relationTo, value }) => {
|
||||
if (!isPayloadType(value) || ("_status" in value && !isPublished(value))) {
|
||||
return [];
|
||||
}
|
||||
|
||||
switch (relationTo) {
|
||||
case "collectibles":
|
||||
return [{ relationTo, value: convertCollectibleToPreview(value) }];
|
||||
case "pages":
|
||||
return [{ relationTo, value: convertPageToPreview(value) }];
|
||||
// TODO: handle media type files
|
||||
case "images":
|
||||
return [];
|
||||
case "audios":
|
||||
return [];
|
||||
case "videos":
|
||||
return [];
|
||||
}
|
||||
}) ?? [],
|
||||
parentPages: handleParentPages({ folders: parentFolders }),
|
||||
};
|
||||
},
|
||||
handler: (folder) => convertFolderToEndpointFolder(folder),
|
||||
});
|
||||
|
||||
export const convertFolderToPreview = ({
|
||||
export const convertFolderToEndpointFolder = ({
|
||||
slug,
|
||||
translations,
|
||||
icon,
|
||||
}: Folder): EndpointFolderPreview => {
|
||||
return {
|
||||
slug,
|
||||
...(isDefined(icon) ? { icon } : {}),
|
||||
translations:
|
||||
translations?.map(({ language, name, description }) => ({
|
||||
language: getLanguageId(language),
|
||||
name,
|
||||
...(isNotEmpty(description) ? { description } : {}),
|
||||
})) ?? [],
|
||||
};
|
||||
};
|
||||
translations,
|
||||
sections,
|
||||
files,
|
||||
parentFolders,
|
||||
}: Folder): EndpointFolder => ({
|
||||
slug,
|
||||
...(isDefined(icon) ? { icon } : {}),
|
||||
translations:
|
||||
translations?.map(({ language, name, description }) => ({
|
||||
language: getLanguageId(language),
|
||||
name,
|
||||
...(isNotEmpty(description) ? { description } : {}),
|
||||
})) ?? [],
|
||||
sections:
|
||||
sections?.length === 1
|
||||
? {
|
||||
type: "single",
|
||||
subfolders:
|
||||
sections[0]?.subfolders?.filter(isPayloadType).map(convertFolderToEndpointFolder) ?? [],
|
||||
}
|
||||
: {
|
||||
type: "multiple",
|
||||
sections:
|
||||
sections?.filter(isValidSection).map(({ translations, subfolders }) => ({
|
||||
translations: translations.map(({ language, name }) => ({
|
||||
language: getLanguageId(language),
|
||||
name,
|
||||
})),
|
||||
subfolders: subfolders.map(convertFolderToEndpointFolder),
|
||||
})) ?? [],
|
||||
},
|
||||
files:
|
||||
files?.flatMap<EndpointFolder["files"][number]>(({ relationTo, value }) => {
|
||||
if (!isPayloadType(value) || ("_status" in value && !isPublished(value))) {
|
||||
return [];
|
||||
}
|
||||
|
||||
switch (relationTo) {
|
||||
case Collections.Collectibles:
|
||||
return [
|
||||
{
|
||||
relationTo: Collections.Collectibles,
|
||||
value: convertCollectibleToEndpointCollectible(value),
|
||||
},
|
||||
];
|
||||
case Collections.Pages:
|
||||
return [{ relationTo: Collections.Pages, value: convertPageToEndpointPage(value) }];
|
||||
// TODO: handle media type files
|
||||
case Collections.Images:
|
||||
if (!isValidPayloadImage(value)) return [];
|
||||
return [{ relationTo: Collections.Images, value: convertImageToEndpointImage(value) }];
|
||||
case Collections.Audios:
|
||||
if (!isValidPayloadMedia(value)) return [];
|
||||
return [{ relationTo: Collections.Audios, value: convertAudioToEndpointAudio(value) }];
|
||||
case Collections.Videos:
|
||||
if (!isValidPayloadMedia(value)) return [];
|
||||
return [{ relationTo: Collections.Videos, value: convertVideoToEndpointVideo(value) }];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}) ?? [],
|
||||
parentPages: convertSourceToEndpointSource({ folders: parentFolders }),
|
||||
});
|
||||
|
||||
const isValidSection = (section: {
|
||||
translations?:
|
||||
|
@ -100,6 +116,3 @@ const isValidSection = (section: {
|
|||
}
|
||||
return section.subfolders.every(isPayloadType);
|
||||
};
|
||||
|
||||
const getLanguageId = (language: string | Language) =>
|
||||
typeof language === "object" ? language.id : language;
|
||||
|
|
|
@ -3,6 +3,7 @@ import { tagsField } from "../../fields/tagsField/tagsField";
|
|||
import { translatedFields } from "../../fields/translatedFields/translatedFields";
|
||||
import { createEditor } from "../../utils/editor";
|
||||
import { buildImageCollectionConfig } from "../../utils/imageCollectionConfig";
|
||||
import { getByID } from "./endpoints/getByID";
|
||||
|
||||
const fields = {
|
||||
filename: "filename",
|
||||
|
@ -36,6 +37,7 @@ export const Images = buildImageCollectionConfig({
|
|||
},
|
||||
],
|
||||
},
|
||||
endpoints: [getByID],
|
||||
fields: [
|
||||
translatedFields({
|
||||
name: fields.translations,
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
import payload from "payload";
|
||||
import { Collections } from "../../../constants";
|
||||
import { EndpointImage, PayloadImage } from "../../../sdk";
|
||||
import { Image } from "../../../types/collections";
|
||||
import { CollectionEndpoint } from "../../../types/payload";
|
||||
import { isNotEmpty, isValidPayloadImage } from "../../../utils/asserts";
|
||||
import {
|
||||
convertRTCToEndpointRTC,
|
||||
convertTagsEndpointTagsGroups,
|
||||
getLanguageId,
|
||||
} from "../../../utils/endpoints";
|
||||
|
||||
export const getByID: CollectionEndpoint = {
|
||||
method: "get",
|
||||
path: "/id/:id",
|
||||
handler: async (req, res) => {
|
||||
if (!req.user) {
|
||||
return res.status(403).send({
|
||||
errors: [
|
||||
{
|
||||
message: "You are not allowed to perform this action.",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (!req.params.id) {
|
||||
return res.status(400).send({ errors: [{ message: "Missing 'id' query params" }] });
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await payload.findByID({
|
||||
collection: Collections.Images,
|
||||
id: req.params.id,
|
||||
});
|
||||
|
||||
if (!isValidPayloadImage(result)) {
|
||||
return res.sendStatus(404);
|
||||
}
|
||||
|
||||
return res.status(200).json(convertImageToEndpointImage(result));
|
||||
} catch {
|
||||
return res.sendStatus(404);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export const convertImageToEndpointImage = ({
|
||||
url,
|
||||
width,
|
||||
height,
|
||||
tags,
|
||||
translations,
|
||||
mimeType,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
filename,
|
||||
filesize,
|
||||
id,
|
||||
}: Image & PayloadImage): EndpointImage => ({
|
||||
url,
|
||||
width,
|
||||
height,
|
||||
tagGroups: convertTagsEndpointTagsGroups(tags),
|
||||
createdAt,
|
||||
filename,
|
||||
filesize,
|
||||
id,
|
||||
mimeType,
|
||||
updatedAt,
|
||||
translations:
|
||||
translations?.map(({ language, title, description }) => ({
|
||||
language: getLanguageId(language),
|
||||
title,
|
||||
...(isNotEmpty(description) ? { description: convertRTCToEndpointRTC(description) } : {}),
|
||||
})) ?? [],
|
||||
});
|
|
@ -2,15 +2,13 @@ import {
|
|||
BreakBlockType,
|
||||
Collections,
|
||||
PageType,
|
||||
RichTextBreakBlock,
|
||||
RichTextContent,
|
||||
RichTextSectionBlock,
|
||||
isBlockNodeBreakBlock,
|
||||
isBlockNodeSectionBlock,
|
||||
isNodeBlockNode,
|
||||
} from "../../../constants";
|
||||
import { createGetByEndpoint } from "../../../endpoints/createGetByEndpoint";
|
||||
import { EndpointPage, EndpointPagePreview, TableOfContentEntry } from "../../../sdk";
|
||||
import { EndpointPage, TableOfContentEntry } from "../../../sdk";
|
||||
import { Page } from "../../../types/collections";
|
||||
import {
|
||||
isNotEmpty,
|
||||
|
@ -18,85 +16,70 @@ import {
|
|||
isPayloadType,
|
||||
isValidPayloadImage,
|
||||
} from "../../../utils/asserts";
|
||||
import { convertTagsToGroups, handleParentPages, handleRecorder } from "../../../utils/endpoints";
|
||||
import {
|
||||
convertRTCToEndpointRTC,
|
||||
convertSourceToEndpointSource,
|
||||
convertTagsEndpointTagsGroups,
|
||||
} from "../../../utils/endpoints";
|
||||
import { convertRecorderToEndpointRecorder } from "../../Recorders/endpoints/getByUsername";
|
||||
|
||||
export const getBySlugEndpoint = createGetByEndpoint({
|
||||
collection: Collections.Pages,
|
||||
attribute: "slug",
|
||||
handler: (page: Page): EndpointPage => {
|
||||
const { translations, collectibles, folders, backgroundImage } = page;
|
||||
|
||||
return {
|
||||
...convertPageToPreview(page),
|
||||
...(isValidPayloadImage(backgroundImage) ? { backgroundImage } : {}),
|
||||
translations: translations.map(
|
||||
({
|
||||
content,
|
||||
language,
|
||||
sourceLanguage,
|
||||
title,
|
||||
pretitle,
|
||||
subtitle,
|
||||
proofreaders,
|
||||
summary,
|
||||
transcribers,
|
||||
translators,
|
||||
}) => ({
|
||||
language: isPayloadType(language) ? language.id : language,
|
||||
sourceLanguage: isPayloadType(sourceLanguage) ? sourceLanguage.id : sourceLanguage,
|
||||
...(isNotEmpty(pretitle) ? { pretitle } : {}),
|
||||
title,
|
||||
...(isNotEmpty(subtitle) ? { subtitle } : {}),
|
||||
...(isNotEmpty(summary) ? { summary } : {}),
|
||||
content: handleContent(content),
|
||||
toc: handleToc(content),
|
||||
translators: isPayloadArrayType(translators) ? translators.map(handleRecorder) : [],
|
||||
transcribers: isPayloadArrayType(transcribers) ? transcribers.map(handleRecorder) : [],
|
||||
proofreaders: isPayloadArrayType(proofreaders) ? proofreaders.map(handleRecorder) : [],
|
||||
})
|
||||
),
|
||||
parentPages: handleParentPages({ collectibles, folders }),
|
||||
};
|
||||
},
|
||||
handler: (page) => convertPageToEndpointPage(page),
|
||||
});
|
||||
|
||||
const handleContent = (
|
||||
{ root: { children, ...others } }: RichTextContent,
|
||||
parentPrefix = ""
|
||||
): RichTextContent => {
|
||||
let index = 0;
|
||||
return {
|
||||
root: {
|
||||
...others,
|
||||
children: children.map((node) => {
|
||||
if (isNodeBlockNode(node)) {
|
||||
if (isBlockNodeSectionBlock(node)) {
|
||||
index++;
|
||||
const anchorHash = `${parentPrefix}${index}.`;
|
||||
const newNode: RichTextSectionBlock = {
|
||||
...node,
|
||||
fields: {
|
||||
...node.fields,
|
||||
content: handleContent(node.fields.content, anchorHash),
|
||||
},
|
||||
anchorHash,
|
||||
};
|
||||
return newNode;
|
||||
} else if (isBlockNodeBreakBlock(node)) {
|
||||
index++;
|
||||
const anchorHash = `${parentPrefix}${index}.`;
|
||||
const newNode: RichTextBreakBlock = {
|
||||
...node,
|
||||
anchorHash,
|
||||
};
|
||||
return newNode;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}),
|
||||
},
|
||||
};
|
||||
};
|
||||
export const convertPageToEndpointPage = ({
|
||||
translations,
|
||||
collectibles,
|
||||
folders,
|
||||
backgroundImage,
|
||||
authors,
|
||||
slug,
|
||||
tags,
|
||||
thumbnail,
|
||||
type,
|
||||
}: Page): EndpointPage => ({
|
||||
slug,
|
||||
type: type as PageType,
|
||||
...(isValidPayloadImage(thumbnail) ? { thumbnail } : {}),
|
||||
tagGroups: convertTagsEndpointTagsGroups(tags),
|
||||
authors: isPayloadArrayType(authors) ? authors.map(convertRecorderToEndpointRecorder) : [],
|
||||
...(isValidPayloadImage(backgroundImage) ? { backgroundImage } : {}),
|
||||
translations: translations.map(
|
||||
({
|
||||
content,
|
||||
language,
|
||||
sourceLanguage,
|
||||
title,
|
||||
pretitle,
|
||||
subtitle,
|
||||
proofreaders,
|
||||
summary,
|
||||
transcribers,
|
||||
translators,
|
||||
}) => ({
|
||||
language: isPayloadType(language) ? language.id : language,
|
||||
sourceLanguage: isPayloadType(sourceLanguage) ? sourceLanguage.id : sourceLanguage,
|
||||
...(isNotEmpty(pretitle) ? { pretitle } : {}),
|
||||
title,
|
||||
...(isNotEmpty(subtitle) ? { subtitle } : {}),
|
||||
...(isNotEmpty(summary) ? { summary } : {}),
|
||||
content: convertRTCToEndpointRTC(content),
|
||||
toc: handleToc(content),
|
||||
translators: isPayloadArrayType(translators)
|
||||
? translators.map(convertRecorderToEndpointRecorder)
|
||||
: [],
|
||||
transcribers: isPayloadArrayType(transcribers)
|
||||
? transcribers.map(convertRecorderToEndpointRecorder)
|
||||
: [],
|
||||
proofreaders: isPayloadArrayType(proofreaders)
|
||||
? proofreaders.map(convertRecorderToEndpointRecorder)
|
||||
: [],
|
||||
})
|
||||
),
|
||||
parentPages: convertSourceToEndpointSource({ collectibles, folders }),
|
||||
});
|
||||
|
||||
const handleToc = (content: RichTextContent, parentPrefix = ""): TableOfContentEntry[] => {
|
||||
let index = 0;
|
||||
|
@ -150,24 +133,3 @@ const handleToc = (content: RichTextContent, parentPrefix = ""): TableOfContentE
|
|||
return [];
|
||||
});
|
||||
};
|
||||
|
||||
export const convertPageToPreview = ({
|
||||
authors,
|
||||
slug,
|
||||
translations,
|
||||
tags,
|
||||
thumbnail,
|
||||
type,
|
||||
}: Page): EndpointPagePreview => ({
|
||||
slug,
|
||||
type: type as PageType,
|
||||
...(isValidPayloadImage(thumbnail) ? { thumbnail } : {}),
|
||||
tagGroups: convertTagsToGroups(tags),
|
||||
translations: translations.map(({ language, title, pretitle, subtitle }) => ({
|
||||
language: isPayloadType(language) ? language.id : language,
|
||||
...(isNotEmpty(pretitle) ? { pretitle } : {}),
|
||||
title,
|
||||
...(isNotEmpty(subtitle) ? { subtitle } : {}),
|
||||
})),
|
||||
authors: isPayloadArrayType(authors) ? authors.map(handleRecorder) : [],
|
||||
});
|
||||
|
|
|
@ -7,6 +7,7 @@ import { imageField } from "../../fields/imageField/imageField";
|
|||
import { rowField } from "../../fields/rowField/rowField";
|
||||
import { buildCollectionConfig } from "../../utils/collectionConfig";
|
||||
import { getAllEndpoint } from "./endpoints/getAllEndpoint";
|
||||
import { getByUsernameEndpoint } from "./endpoints/getByUsername";
|
||||
import { importFromStrapi } from "./endpoints/importFromStrapi";
|
||||
import { beforeLoginMustHaveAtLeastOneRole } from "./hooks/beforeLoginMustHaveAtLeastOneRole";
|
||||
|
||||
|
@ -74,7 +75,7 @@ export const Recorders = buildCollectionConfig({
|
|||
hooks: {
|
||||
beforeLogin: [beforeLoginMustHaveAtLeastOneRole],
|
||||
},
|
||||
endpoints: [importFromStrapi, getAllEndpoint],
|
||||
endpoints: [importFromStrapi, getAllEndpoint, getByUsernameEndpoint],
|
||||
timestamps: false,
|
||||
fields: [
|
||||
rowField([
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import { Collections } from "../../../constants";
|
||||
import { createGetByEndpoint } from "../../../endpoints/createGetByEndpoint";
|
||||
import { EndpointRecorder } from "../../../sdk";
|
||||
import { Recorder } from "../../../types/collections";
|
||||
import { isPayloadType, isValidPayloadImage } from "../../../utils/asserts";
|
||||
|
||||
export const getByUsernameEndpoint = createGetByEndpoint({
|
||||
collection: Collections.Recorders,
|
||||
attribute: "username",
|
||||
handler: (recorder) => convertRecorderToEndpointRecorder(recorder),
|
||||
});
|
||||
|
||||
export const convertRecorderToEndpointRecorder = ({
|
||||
id,
|
||||
languages,
|
||||
username,
|
||||
avatar,
|
||||
anonymize,
|
||||
}: Recorder): EndpointRecorder => ({
|
||||
id,
|
||||
languages: languages?.map((language) => (isPayloadType(language) ? language.id : language)) ?? [],
|
||||
username: anonymize ? `Recorder#${id.substring(0, 5)}` : username,
|
||||
...(isValidPayloadImage(avatar) ? { avatar } : {}),
|
||||
});
|
|
@ -6,6 +6,7 @@ import { tagsField } from "../../fields/tagsField/tagsField";
|
|||
import { translatedFields } from "../../fields/translatedFields/translatedFields";
|
||||
import { buildCollectionConfig } from "../../utils/collectionConfig";
|
||||
import { createEditor } from "../../utils/editor";
|
||||
import { getByID } from "./endpoints/getByID";
|
||||
|
||||
const fields = {
|
||||
filename: "filename",
|
||||
|
@ -47,13 +48,13 @@ export const Videos = buildCollectionConfig({
|
|||
mimeTypes: ["video/*"],
|
||||
disableLocalStorage: true,
|
||||
},
|
||||
endpoints: [getByID],
|
||||
fields: [
|
||||
rowField([
|
||||
{ name: fields.duration, type: "number", min: 0, required: true },
|
||||
imageField({
|
||||
name: fields.thumbnail,
|
||||
relationTo: Collections.MediaThumbnails,
|
||||
required: true,
|
||||
}),
|
||||
]),
|
||||
translatedFields({
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
import payload from "payload";
|
||||
import { Collections } from "../../../constants";
|
||||
import { EndpointVideo, PayloadMedia } from "../../../sdk";
|
||||
import { Video } from "../../../types/collections";
|
||||
import { CollectionEndpoint } from "../../../types/payload";
|
||||
import {
|
||||
isDefined,
|
||||
isEmpty,
|
||||
isNotEmpty,
|
||||
isPayloadType,
|
||||
isUndefined,
|
||||
isValidPayloadImage,
|
||||
isValidPayloadMedia,
|
||||
} from "../../../utils/asserts";
|
||||
import {
|
||||
convertRTCToEndpointRTC,
|
||||
convertTagsEndpointTagsGroups,
|
||||
getLanguageId,
|
||||
} from "../../../utils/endpoints";
|
||||
|
||||
export const getByID: CollectionEndpoint = {
|
||||
method: "get",
|
||||
path: "/id/:id",
|
||||
handler: async (req, res) => {
|
||||
if (!req.user) {
|
||||
return res.status(403).send({
|
||||
errors: [
|
||||
{
|
||||
message: "You are not allowed to perform this action.",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (!req.params.id) {
|
||||
return res.status(400).send({ errors: [{ message: "Missing 'id' query params" }] });
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await payload.findByID({
|
||||
collection: Collections.Videos,
|
||||
id: req.params.id,
|
||||
});
|
||||
|
||||
if (!isValidPayloadMedia(result)) {
|
||||
return res.sendStatus(404);
|
||||
}
|
||||
|
||||
return res.status(200).json(convertVideoToEndpointVideo(result));
|
||||
} catch {
|
||||
return res.sendStatus(404);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export const convertVideoToEndpointVideo = ({
|
||||
url,
|
||||
tags,
|
||||
translations,
|
||||
mimeType,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
filename,
|
||||
filesize,
|
||||
duration,
|
||||
id,
|
||||
thumbnail,
|
||||
platform,
|
||||
platformEnabled,
|
||||
}: Video & PayloadMedia): EndpointVideo => ({
|
||||
url,
|
||||
tagGroups: convertTagsEndpointTagsGroups(tags),
|
||||
createdAt,
|
||||
filename,
|
||||
filesize,
|
||||
id,
|
||||
mimeType,
|
||||
updatedAt,
|
||||
translations:
|
||||
translations?.map(({ language, title, description }) => ({
|
||||
language: getLanguageId(language),
|
||||
title,
|
||||
...(isNotEmpty(description) ? { description: convertRTCToEndpointRTC(description) } : {}),
|
||||
})) ?? [],
|
||||
|
||||
duration,
|
||||
...(isValidPayloadImage(thumbnail) ? { thumbnail } : {}),
|
||||
...(platformEnabled && isDefined(platform) && isPayloadType(platform.channel)
|
||||
? {
|
||||
platform: {
|
||||
channel: platform.channel,
|
||||
publishedDate: platform.publishedDate,
|
||||
url: platform.url,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
subtitles:
|
||||
translations.flatMap(({ language, subfile }) => {
|
||||
if (
|
||||
isUndefined(subfile) ||
|
||||
!isPayloadType(subfile) ||
|
||||
isUndefined(subfile.url) ||
|
||||
isEmpty(subfile.url)
|
||||
)
|
||||
return [];
|
||||
return { language: getLanguageId(language), url: subfile.url };
|
||||
}) ?? [],
|
||||
});
|
|
@ -29,7 +29,7 @@ export const VideosChannels: CollectionConfig = buildCollectionConfig({
|
|||
{ name: fields.url, type: "text", required: true, unique: true },
|
||||
rowField([
|
||||
{ name: fields.title, type: "text", required: true },
|
||||
{ name: fields.subscribers, type: "number" },
|
||||
{ name: fields.subscribers, type: "number", required: true },
|
||||
]),
|
||||
backPropagationField({
|
||||
name: fields.videos,
|
||||
|
|
|
@ -3,7 +3,7 @@ import { Collections } from "../../../constants";
|
|||
import { EndpointWebsiteConfig } from "../../../sdk";
|
||||
import { CollectionEndpoint } from "../../../types/payload";
|
||||
import { isPayloadType, isValidPayloadImage } from "../../../utils/asserts";
|
||||
import { convertFolderToPreview } from "../../Folders/endpoints/getBySlugEndpoint";
|
||||
import { convertFolderToEndpointFolder } from "../../Folders/endpoints/getBySlugEndpoint";
|
||||
|
||||
export const getConfigEndpoint: CollectionEndpoint = {
|
||||
method: "get",
|
||||
|
@ -46,7 +46,7 @@ export const getConfigEndpoint: CollectionEndpoint = {
|
|||
homeFolders?.flatMap(({ folder, darkThumbnail, lightThumbnail }) => {
|
||||
if (!isPayloadType(folder)) return [];
|
||||
return {
|
||||
...convertFolderToPreview(folder),
|
||||
...convertFolderToEndpointFolder(folder),
|
||||
...(isValidPayloadImage(darkThumbnail) ? { darkThumbnail } : {}),
|
||||
...(isValidPayloadImage(lightThumbnail) ? { lightThumbnail } : {}),
|
||||
};
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
import type {
|
||||
Audio,
|
||||
BreakBlock,
|
||||
Image,
|
||||
SectionBlock,
|
||||
TranscriptBlock,
|
||||
Video,
|
||||
} from "./types/collections";
|
||||
import { EndpointAudio, EndpointImage, EndpointVideo } from "./sdk";
|
||||
import type { BreakBlock, SectionBlock, TranscriptBlock } from "./types/collections";
|
||||
|
||||
// END MOCKING SECTION
|
||||
|
||||
|
@ -149,17 +143,17 @@ export interface RichTextUploadNode extends RichTextNode {
|
|||
|
||||
export interface RichTextUploadImageNode extends RichTextUploadNode {
|
||||
relationTo: Collections.Images;
|
||||
value: Image;
|
||||
value: EndpointImage;
|
||||
}
|
||||
|
||||
export interface RichTextUploadVideoNode extends RichTextUploadNode {
|
||||
relationTo: Collections.Videos;
|
||||
value: Video;
|
||||
value: EndpointVideo;
|
||||
}
|
||||
|
||||
export interface RichTextUploadAudioNode extends RichTextUploadNode {
|
||||
relationTo: Collections.Audios;
|
||||
value: Audio;
|
||||
value: EndpointAudio;
|
||||
}
|
||||
|
||||
export interface RichTextTextNode extends RichTextNode {
|
||||
|
|
|
@ -35,7 +35,7 @@ const configuredFtpAdapter = sftpAdapter({
|
|||
privateKey: process.env.SFTP_PRIVATE_KEY,
|
||||
},
|
||||
destinationPathRoot: process.env.SFTP_DESTINATION_PATH_ROOT ?? "",
|
||||
publicEndpoint: process.env.FTP_BASE_URL ?? "",
|
||||
publicEndpoint: process.env.SFTP_BASE_URL ?? "",
|
||||
});
|
||||
|
||||
export default buildConfig({
|
||||
|
|
128
src/sdk.ts
128
src/sdk.ts
|
@ -96,7 +96,7 @@ const request = async (url: string, init?: RequestInit): Promise<Response> => {
|
|||
|
||||
// SDK and Types
|
||||
|
||||
export type EndpointFolderPreview = {
|
||||
export type EndpointFolder = {
|
||||
slug: string;
|
||||
icon?: string;
|
||||
translations: {
|
||||
|
@ -104,33 +104,42 @@ export type EndpointFolderPreview = {
|
|||
name: string;
|
||||
description?: RichTextContent;
|
||||
}[];
|
||||
};
|
||||
|
||||
export type EndpointFolder = EndpointFolderPreview & {
|
||||
sections:
|
||||
| { type: "single"; subfolders: EndpointFolderPreview[] }
|
||||
| { type: "single"; subfolders: EndpointFolder[] }
|
||||
| {
|
||||
type: "multiple";
|
||||
sections: {
|
||||
translations: { language: string; name: string }[];
|
||||
subfolders: EndpointFolderPreview[];
|
||||
subfolders: EndpointFolder[];
|
||||
}[];
|
||||
};
|
||||
files: (
|
||||
| {
|
||||
relationTo: "collectibles";
|
||||
value: EndpointCollectiblePreview;
|
||||
relationTo: Collections.Collectibles;
|
||||
value: EndpointCollectible;
|
||||
}
|
||||
| {
|
||||
relationTo: "pages";
|
||||
value: EndpointPagePreview;
|
||||
relationTo: Collections.Pages;
|
||||
value: EndpointPage;
|
||||
}
|
||||
| {
|
||||
relationTo: Collections.Images;
|
||||
value: EndpointImage;
|
||||
}
|
||||
| {
|
||||
relationTo: Collections.Audios;
|
||||
value: EndpointAudio;
|
||||
}
|
||||
| {
|
||||
relationTo: Collections.Videos;
|
||||
value: EndpointVideo;
|
||||
}
|
||||
)[];
|
||||
parentPages: EndpointSource[];
|
||||
};
|
||||
|
||||
export type EndpointWebsiteConfig = {
|
||||
homeFolders: (EndpointFolderPreview & {
|
||||
homeFolders: (EndpointFolder & {
|
||||
lightThumbnail?: PayloadImage;
|
||||
darkThumbnail?: PayloadImage;
|
||||
})[];
|
||||
|
@ -178,23 +187,18 @@ export type EndpointTagsGroup = {
|
|||
tags: EndpointTag[];
|
||||
};
|
||||
|
||||
export type EndpointPagePreview = {
|
||||
export type EndpointPage = {
|
||||
slug: string;
|
||||
type: PageType;
|
||||
thumbnail?: PayloadImage;
|
||||
authors: EndpointRecorder[];
|
||||
tagGroups: EndpointTagsGroup[];
|
||||
backgroundImage?: PayloadImage;
|
||||
translations: {
|
||||
language: string;
|
||||
pretitle?: string;
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
export type EndpointPage = EndpointPagePreview & {
|
||||
backgroundImage?: PayloadImage;
|
||||
translations: (EndpointPagePreview["translations"][number] & {
|
||||
sourceLanguage: string;
|
||||
summary?: RichTextContent;
|
||||
content: RichTextContent;
|
||||
|
@ -202,11 +206,11 @@ export type EndpointPage = EndpointPagePreview & {
|
|||
translators: EndpointRecorder[];
|
||||
proofreaders: EndpointRecorder[];
|
||||
toc: TableOfContentEntry[];
|
||||
})[];
|
||||
}[];
|
||||
parentPages: EndpointSource[];
|
||||
};
|
||||
|
||||
export type EndpointCollectiblePreview = {
|
||||
export type EndpointCollectible = {
|
||||
slug: string;
|
||||
thumbnail?: PayloadImage;
|
||||
translations: {
|
||||
|
@ -219,9 +223,6 @@ export type EndpointCollectiblePreview = {
|
|||
tagGroups: EndpointTagsGroup[];
|
||||
releaseDate?: string;
|
||||
languages: string[];
|
||||
};
|
||||
|
||||
export type EndpointCollectible = EndpointCollectiblePreview & {
|
||||
backgroundImage?: PayloadImage;
|
||||
nature: CollectibleNature;
|
||||
gallery: PayloadImage[];
|
||||
|
@ -242,15 +243,23 @@ export type EndpointCollectible = EndpointCollectiblePreview & {
|
|||
bindingType?: CollectibleBindingTypes;
|
||||
pageOrder?: CollectiblePageOrders;
|
||||
};
|
||||
subitems: EndpointCollectiblePreview[];
|
||||
subitems: EndpointCollectible[];
|
||||
contents: {
|
||||
content:
|
||||
| {
|
||||
relationTo: "pages";
|
||||
value: EndpointPagePreview;
|
||||
relationTo: Collections.Pages;
|
||||
value: EndpointPage;
|
||||
}
|
||||
| {
|
||||
relationTo: "generic-contents";
|
||||
relationTo: Collections.Audios;
|
||||
value: EndpointAudio;
|
||||
}
|
||||
| {
|
||||
relationTo: Collections.Videos;
|
||||
value: EndpointVideo;
|
||||
}
|
||||
| {
|
||||
relationTo: Collections.GenericContents;
|
||||
value: {
|
||||
translations: {
|
||||
language: string;
|
||||
|
@ -315,21 +324,72 @@ export type EndpointSource =
|
|||
| { type: "url"; url: string; label: string }
|
||||
| {
|
||||
type: "collectible";
|
||||
collectible: EndpointCollectiblePreview;
|
||||
collectible: EndpointCollectible;
|
||||
range?:
|
||||
| { type: "page"; page: number }
|
||||
| { type: "timestamp"; timestamp: string }
|
||||
| { type: "custom"; translations: { language: string; note: string }[] };
|
||||
}
|
||||
| { type: "page"; page: EndpointPagePreview }
|
||||
| { type: "folder"; folder: EndpointFolderPreview };
|
||||
| { type: "page"; page: EndpointPage }
|
||||
| { type: "folder"; folder: EndpointFolder };
|
||||
|
||||
export type PayloadImage = {
|
||||
export type EndpointMedia = {
|
||||
id: string;
|
||||
url: string;
|
||||
filename: string;
|
||||
mimeType: string;
|
||||
filesize: number;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
tagGroups: EndpointTagsGroup[];
|
||||
translations: {
|
||||
language: string;
|
||||
title: string;
|
||||
description?: RichTextContent;
|
||||
}[];
|
||||
};
|
||||
|
||||
export type EndpointImage = EndpointMedia & {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
|
||||
export type EndpointAudio = EndpointMedia & {
|
||||
thumbnail?: PayloadImage;
|
||||
duration: number;
|
||||
};
|
||||
|
||||
export type EndpointVideo = EndpointMedia & {
|
||||
thumbnail?: PayloadImage;
|
||||
subtitles: {
|
||||
language: string;
|
||||
url: string;
|
||||
}[];
|
||||
platform?: {
|
||||
channel: {
|
||||
url: string;
|
||||
title: string;
|
||||
subscribers: number;
|
||||
};
|
||||
views?: number;
|
||||
likes?: number;
|
||||
dislikes?: number;
|
||||
url: string;
|
||||
publishedDate: string;
|
||||
};
|
||||
duration: number;
|
||||
};
|
||||
|
||||
export type PayloadMedia = {
|
||||
url: string;
|
||||
mimeType: string;
|
||||
filename: string;
|
||||
filesize: number;
|
||||
};
|
||||
|
||||
export type PayloadImage = PayloadMedia & {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
|
||||
export const payload = {
|
||||
|
@ -353,4 +413,10 @@ export const payload = {
|
|||
await (await request(payloadApiUrl(Collections.ChronologyEvents, `all`))).json(),
|
||||
getChronologyEventByID: async (id: string): Promise<EndpointChronologyEvent> =>
|
||||
await (await request(payloadApiUrl(Collections.ChronologyEvents, `id/${id}`))).json(),
|
||||
getImageByID: async (id: string): Promise<EndpointImage> =>
|
||||
await (await request(payloadApiUrl(Collections.Images, `id/${id}`))).json(),
|
||||
getAudioByID: async (id: string): Promise<EndpointAudio> =>
|
||||
await (await request(payloadApiUrl(Collections.Audios, `id/${id}`))).json(),
|
||||
getVideoByID: async (id: string): Promise<EndpointVideo> =>
|
||||
await (await request(payloadApiUrl(Collections.Videos, `id/${id}`))).json(),
|
||||
};
|
||||
|
|
|
@ -603,7 +603,7 @@ export interface MediaThumbnail {
|
|||
export interface Video {
|
||||
id: string;
|
||||
duration: number;
|
||||
thumbnail: string | MediaThumbnail;
|
||||
thumbnail?: string | MediaThumbnail | null;
|
||||
translations: {
|
||||
language: string | Language;
|
||||
title: string;
|
||||
|
@ -665,7 +665,7 @@ export interface VideosChannel {
|
|||
id: string;
|
||||
url: string;
|
||||
title: string;
|
||||
subscribers?: number | null;
|
||||
subscribers: number;
|
||||
videos?: (string | Video)[] | null;
|
||||
}
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { RichTextContent, isNodeParagraphNode } from "../constants";
|
||||
import { PayloadImage } from "../sdk";
|
||||
import { PayloadImage, PayloadMedia } from "../sdk";
|
||||
|
||||
export const isDefined = <T>(value: T | null | undefined): value is T =>
|
||||
value !== null && value !== undefined;
|
||||
|
@ -7,10 +7,11 @@ export const isDefined = <T>(value: T | null | undefined): value is T =>
|
|||
export const isUndefined = <T>(value: T | null | undefined): value is null | undefined =>
|
||||
!isDefined(value);
|
||||
|
||||
export const isNotEmpty = (value: string | null | undefined | RichTextContent): value is string =>
|
||||
!isEmpty(value);
|
||||
export const isNotEmpty = (
|
||||
value: string | null | undefined | RichTextContent
|
||||
): value is string | RichTextContent => !isEmpty(value);
|
||||
|
||||
export const isEmpty = (value: string | null | undefined | RichTextContent): value is string =>
|
||||
export const isEmpty = (value: string | null | undefined | RichTextContent): boolean =>
|
||||
isUndefined(value) ||
|
||||
(typeof value === "string" && isEmptyString(value)) ||
|
||||
(typeof value === "object" && isEmptyRichText(value));
|
||||
|
@ -26,6 +27,7 @@ export const isValidPayloadImage = (
|
|||
image:
|
||||
| {
|
||||
filename?: string | null;
|
||||
filesize?: number | null;
|
||||
mimeType?: string | null;
|
||||
width?: number | null;
|
||||
height?: number | null;
|
||||
|
@ -42,6 +44,28 @@ export const isValidPayloadImage = (
|
|||
if (isEmpty(image.mimeType)) return false;
|
||||
if (isUndefined(image.width)) return false;
|
||||
if (isUndefined(image.height)) return false;
|
||||
if (isUndefined(image.filesize)) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
export const isValidPayloadMedia = (
|
||||
media:
|
||||
| {
|
||||
filename?: string | null;
|
||||
filesize?: number | null;
|
||||
mimeType?: string | null;
|
||||
url?: string | null;
|
||||
}
|
||||
| undefined
|
||||
| null
|
||||
| string
|
||||
): media is PayloadMedia => {
|
||||
if (isUndefined(media)) return false;
|
||||
if (typeof media === "string") return false;
|
||||
if (isEmpty(media.filename)) return false;
|
||||
if (isEmpty(media.url)) return false;
|
||||
if (isEmpty(media.mimeType)) return false;
|
||||
if (isUndefined(media.filesize)) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,32 @@
|
|||
import { convertCollectibleToPreview } from "../collections/Collectibles/endpoints/getBySlugEndpoint";
|
||||
import { convertFolderToPreview } from "../collections/Folders/endpoints/getBySlugEndpoint";
|
||||
import { EndpointRecorder, EndpointSource, EndpointTag, EndpointTagsGroup } from "../sdk";
|
||||
import { Collectible, Folder, Recorder, Tag } from "../types/collections";
|
||||
import { isPayloadArrayType, isPayloadType, isPublished, isValidPayloadImage } from "./asserts";
|
||||
import { convertAudioToEndpointAudio } from "../collections/Audios/endpoints/getByID";
|
||||
import { convertCollectibleToEndpointCollectible } from "../collections/Collectibles/endpoints/getBySlugEndpoint";
|
||||
import { convertFolderToEndpointFolder } from "../collections/Folders/endpoints/getBySlugEndpoint";
|
||||
import { convertImageToEndpointImage } from "../collections/Images/endpoints/getByID";
|
||||
import { convertVideoToEndpointVideo } from "../collections/Videos/endpoints/getByID";
|
||||
import {
|
||||
RichTextBreakBlock,
|
||||
RichTextContent,
|
||||
RichTextSectionBlock,
|
||||
RichTextUploadNode,
|
||||
isBlockNodeBreakBlock,
|
||||
isBlockNodeSectionBlock,
|
||||
isNodeBlockNode,
|
||||
isNodeUploadNode,
|
||||
isUploadNodeAudioNode,
|
||||
isUploadNodeImageNode,
|
||||
isUploadNodeVideoNode,
|
||||
} from "../constants";
|
||||
import { EndpointSource, EndpointTag, EndpointTagsGroup } from "../sdk";
|
||||
import { Audio, Collectible, Folder, Image, Language, Tag, Video } from "../types/collections";
|
||||
import {
|
||||
isPayloadArrayType,
|
||||
isPayloadType,
|
||||
isPublished,
|
||||
isValidPayloadImage,
|
||||
isValidPayloadMedia,
|
||||
} from "./asserts";
|
||||
|
||||
export const convertTagsToGroups = (
|
||||
export const convertTagsEndpointTagsGroups = (
|
||||
tags: (string | Tag)[] | null | undefined
|
||||
): EndpointTagsGroup[] => {
|
||||
if (!isPayloadArrayType(tags)) {
|
||||
|
@ -44,7 +66,75 @@ export const convertTagsToGroups = (
|
|||
return groups;
|
||||
};
|
||||
|
||||
export const handleParentPages = ({
|
||||
export const convertRTCToEndpointRTC = (
|
||||
{ root: { children, ...others } }: RichTextContent,
|
||||
parentPrefix = ""
|
||||
): RichTextContent => {
|
||||
let index = 0;
|
||||
return {
|
||||
root: {
|
||||
...others,
|
||||
children: children.map((node) => {
|
||||
if (isNodeBlockNode(node)) {
|
||||
// Add anchor hash on section block (TOC)
|
||||
if (isBlockNodeSectionBlock(node)) {
|
||||
index++;
|
||||
const anchorHash = `${parentPrefix}${index}.`;
|
||||
const newNode: RichTextSectionBlock = {
|
||||
...node,
|
||||
fields: {
|
||||
...node.fields,
|
||||
content: convertRTCToEndpointRTC(node.fields.content, anchorHash),
|
||||
},
|
||||
anchorHash,
|
||||
};
|
||||
return newNode;
|
||||
// Add anchor hash on section block (TOC)
|
||||
} else if (isBlockNodeBreakBlock(node)) {
|
||||
index++;
|
||||
const anchorHash = `${parentPrefix}${index}.`;
|
||||
const newNode: RichTextBreakBlock = {
|
||||
...node,
|
||||
anchorHash,
|
||||
};
|
||||
return newNode;
|
||||
}
|
||||
} else if (isNodeUploadNode(node)) {
|
||||
const errorUploadNode: RichTextUploadNode = {
|
||||
type: "upload",
|
||||
relationTo: "error",
|
||||
version: 1,
|
||||
};
|
||||
if (isUploadNodeImageNode(node)) {
|
||||
const value = node.value as Image | string;
|
||||
if (!isPayloadType(value) || !isValidPayloadImage(value)) return errorUploadNode;
|
||||
return {
|
||||
...node,
|
||||
value: convertImageToEndpointImage(value),
|
||||
};
|
||||
} else if (isUploadNodeAudioNode(node)) {
|
||||
const value = node.value as Audio | string;
|
||||
if (!isPayloadType(value) || !isValidPayloadMedia(value)) return errorUploadNode;
|
||||
return {
|
||||
...node,
|
||||
value: convertAudioToEndpointAudio(value),
|
||||
};
|
||||
} else if (isUploadNodeVideoNode(node)) {
|
||||
const value = node.value as Video | string;
|
||||
if (!isPayloadType(value) || !isValidPayloadMedia(value)) return errorUploadNode;
|
||||
return {
|
||||
...node,
|
||||
value: convertVideoToEndpointVideo(value),
|
||||
};
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const convertSourceToEndpointSource = ({
|
||||
collectibles,
|
||||
folders,
|
||||
}: {
|
||||
|
@ -57,7 +147,7 @@ export const handleParentPages = ({
|
|||
collectibles.filter(isPublished).forEach((collectible) => {
|
||||
result.push({
|
||||
type: "collectible",
|
||||
collectible: convertCollectibleToPreview(collectible),
|
||||
collectible: convertCollectibleToEndpointCollectible(collectible),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -66,7 +156,7 @@ export const handleParentPages = ({
|
|||
folders.forEach((folder) => {
|
||||
result.push({
|
||||
type: "folder",
|
||||
folder: convertFolderToPreview(folder),
|
||||
folder: convertFolderToEndpointFolder(folder),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -74,19 +164,6 @@ export const handleParentPages = ({
|
|||
return result;
|
||||
};
|
||||
|
||||
export const handleRecorder = ({
|
||||
id,
|
||||
languages,
|
||||
username,
|
||||
avatar,
|
||||
anonymize,
|
||||
}: Recorder): EndpointRecorder => ({
|
||||
id,
|
||||
languages: languages?.map((language) => (isPayloadType(language) ? language.id : language)) ?? [],
|
||||
username: anonymize ? `Recorder#${id.substring(0, 5)}` : username,
|
||||
...(isValidPayloadImage(avatar) ? { avatar } : {}),
|
||||
});
|
||||
|
||||
export const getDomainFromUrl = (url: string): string => {
|
||||
const urlObject = new URL(url);
|
||||
let domain = urlObject.hostname;
|
||||
|
@ -95,3 +172,6 @@ export const getDomainFromUrl = (url: string): string => {
|
|||
}
|
||||
return domain;
|
||||
};
|
||||
|
||||
export const getLanguageId = (language: string | Language) =>
|
||||
typeof language === "object" ? language.id : language;
|
||||
|
|
Loading…
Reference in New Issue