Lots as always
This commit is contained in:
parent
b91159e61f
commit
18142c7f31
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
|
@ -24,12 +24,12 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource/vollkorn": "5.0.18",
|
"@fontsource/vollkorn": "5.0.18",
|
||||||
"@payloadcms/bundler-webpack": "1.0.6",
|
"@payloadcms/bundler-webpack": "1.0.6",
|
||||||
"@payloadcms/db-mongodb": "1.4.0",
|
"@payloadcms/db-mongodb": "1.4.3",
|
||||||
"@payloadcms/richtext-lexical": "0.5.2",
|
"@payloadcms/richtext-lexical": "0.7.0",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"language-tags": "1.0.9",
|
"language-tags": "1.0.9",
|
||||||
"luxon": "3.4.4",
|
"luxon": "3.4.4",
|
||||||
"payload": "2.9.0",
|
"payload": "2.11.2",
|
||||||
"sharp": "0.33.2",
|
"sharp": "0.33.2",
|
||||||
"styled-components": "6.1.8"
|
"styled-components": "6.1.8"
|
||||||
},
|
},
|
||||||
|
@ -38,14 +38,14 @@
|
||||||
"@types/express": "4.17.21",
|
"@types/express": "4.17.21",
|
||||||
"@types/language-tags": "1.0.4",
|
"@types/language-tags": "1.0.4",
|
||||||
"@types/luxon": "3.4.2",
|
"@types/luxon": "3.4.2",
|
||||||
"@types/qs": "6.9.11",
|
"@types/qs": "6.9.12",
|
||||||
"@types/react-router-dom": "5.3.3",
|
"@types/react-router-dom": "5.3.3",
|
||||||
"@types/styled-components": "5.1.34",
|
"@types/styled-components": "5.1.34",
|
||||||
"copyfiles": "2.4.1",
|
"copyfiles": "2.4.1",
|
||||||
"nodemon": "3.0.3",
|
"nodemon": "3.1.0",
|
||||||
"npm-check-updates": "16.14.14",
|
"npm-check-updates": "16.14.15",
|
||||||
"prettier": "3.2.4",
|
"prettier": "3.2.5",
|
||||||
"ts-node": "10.9.1",
|
"ts-node": "10.9.2",
|
||||||
"ts-unused-exports": "10.0.1",
|
"ts-unused-exports": "10.0.1",
|
||||||
"typescript": "5.3.3"
|
"typescript": "5.3.3"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Block } from "payload/types";
|
import { Block } from "payload/types";
|
||||||
import { createEditor } from "../utils/editor";
|
import { createEditor } from "../utils/editor";
|
||||||
|
import { cueBlock } from "./cueBlock";
|
||||||
|
|
||||||
export const lineBlock: Block = {
|
export const lineBlock: Block = {
|
||||||
slug: "lineBlock",
|
slug: "lineBlock",
|
||||||
|
@ -14,7 +15,7 @@ export const lineBlock: Block = {
|
||||||
admin: {
|
admin: {
|
||||||
className: "reduced-margins",
|
className: "reduced-margins",
|
||||||
},
|
},
|
||||||
editor: createEditor({ inlines: true, lists: true, links: true }),
|
editor: createEditor({ inlines: true, lists: true, links: true, blocks: [cueBlock] }),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,7 +28,7 @@ export const getAllEndpoint: CollectionEndpoint = {
|
||||||
const eras: ChronologyEra[] = (
|
const eras: ChronologyEra[] = (
|
||||||
await payload.find({
|
await payload.find({
|
||||||
collection: Collections.ChronologyEras,
|
collection: Collections.ChronologyEras,
|
||||||
limit: 100,
|
pagination: false,
|
||||||
})
|
})
|
||||||
).docs;
|
).docs;
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
|
import { Where } from "payload/types";
|
||||||
import { sectionBlock } from "../../blocks/sectionBlock";
|
import { sectionBlock } from "../../blocks/sectionBlock";
|
||||||
import { transcriptBlock } from "../../blocks/transcriptBlock";
|
import { transcriptBlock } from "../../blocks/transcriptBlock";
|
||||||
import { CollectionGroups, Collections, FileTypes, KeysTypes } from "../../constants";
|
import { CollectionGroups, Collections, FileTypes } from "../../constants";
|
||||||
import { backPropagationField } from "../../fields/backPropagationField/backPropagationField";
|
import { backPropagationField } from "../../fields/backPropagationField/backPropagationField";
|
||||||
import { fileField } from "../../fields/fileField/fileField";
|
import { fileField } from "../../fields/fileField/fileField";
|
||||||
import { imageField } from "../../fields/imageField/imageField";
|
import { imageField } from "../../fields/imageField/imageField";
|
||||||
import { keysField } from "../../fields/keysField/keysField";
|
|
||||||
import { rowField } from "../../fields/rowField/rowField";
|
import { rowField } from "../../fields/rowField/rowField";
|
||||||
import { slugField } from "../../fields/slugField/slugField";
|
import { slugField } from "../../fields/slugField/slugField";
|
||||||
|
import { tagsField } from "../../fields/tagsField/tagsField";
|
||||||
import { translatedFields } from "../../fields/translatedFields/translatedFields";
|
import { translatedFields } from "../../fields/translatedFields/translatedFields";
|
||||||
import { beforeDuplicateAddCopyTo } from "../../hooks/beforeDuplicateAddCopyTo";
|
import { beforeDuplicateAddCopyTo } from "../../hooks/beforeDuplicateAddCopyTo";
|
||||||
import { beforeDuplicatePiping } from "../../hooks/beforeDuplicatePiping";
|
import { beforeDuplicatePiping } from "../../hooks/beforeDuplicatePiping";
|
||||||
|
@ -14,14 +15,13 @@ import { beforeDuplicateUnpublish } from "../../hooks/beforeDuplicateUnpublish";
|
||||||
import { isDefined } from "../../utils/asserts";
|
import { isDefined } from "../../utils/asserts";
|
||||||
import { createEditor } from "../../utils/editor";
|
import { createEditor } from "../../utils/editor";
|
||||||
import { buildVersionedCollectionConfig } from "../../utils/versionedCollectionConfig";
|
import { buildVersionedCollectionConfig } from "../../utils/versionedCollectionConfig";
|
||||||
|
import { getBySlugEndpoint } from "./endpoints/getBySlugEndpoint";
|
||||||
import { importFromStrapi } from "./endpoints/importFromStrapi";
|
import { importFromStrapi } from "./endpoints/importFromStrapi";
|
||||||
import { importRelationsFromStrapi } from "./endpoints/importRelationsFromStrapi";
|
import { importRelationsFromStrapi } from "./endpoints/importRelationsFromStrapi";
|
||||||
|
|
||||||
const fields = {
|
const fields = {
|
||||||
slug: "slug",
|
slug: "slug",
|
||||||
thumbnail: "thumbnail",
|
thumbnail: "thumbnail",
|
||||||
categories: "categories",
|
|
||||||
type: "type",
|
|
||||||
translations: "translations",
|
translations: "translations",
|
||||||
pretitle: "pretitle",
|
pretitle: "pretitle",
|
||||||
title: "title",
|
title: "title",
|
||||||
|
@ -42,6 +42,7 @@ const fields = {
|
||||||
nextContents: "nextContents",
|
nextContents: "nextContents",
|
||||||
folders: "folders",
|
folders: "folders",
|
||||||
libraryItems: "libraryItems",
|
libraryItems: "libraryItems",
|
||||||
|
tags: "tags",
|
||||||
} as const satisfies Record<string, string>;
|
} as const satisfies Record<string, string>;
|
||||||
|
|
||||||
export const Contents = buildVersionedCollectionConfig({
|
export const Contents = buildVersionedCollectionConfig({
|
||||||
|
@ -55,14 +56,7 @@ export const Contents = buildVersionedCollectionConfig({
|
||||||
useAsTitle: fields.slug,
|
useAsTitle: fields.slug,
|
||||||
description:
|
description:
|
||||||
"All the contents (textual, audio, and video) from the Library or other online sources.",
|
"All the contents (textual, audio, and video) from the Library or other online sources.",
|
||||||
defaultColumns: [
|
defaultColumns: [fields.thumbnail, fields.slug, fields.translations, fields.status],
|
||||||
fields.thumbnail,
|
|
||||||
fields.slug,
|
|
||||||
fields.categories,
|
|
||||||
fields.type,
|
|
||||||
fields.translations,
|
|
||||||
fields.status,
|
|
||||||
],
|
|
||||||
group: CollectionGroups.Collections,
|
group: CollectionGroups.Collections,
|
||||||
hooks: {
|
hooks: {
|
||||||
beforeDuplicate: beforeDuplicatePiping([
|
beforeDuplicate: beforeDuplicatePiping([
|
||||||
|
@ -71,7 +65,7 @@ export const Contents = buildVersionedCollectionConfig({
|
||||||
]),
|
]),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
endpoints: [importFromStrapi, importRelationsFromStrapi],
|
endpoints: [importFromStrapi, importRelationsFromStrapi, getBySlugEndpoint],
|
||||||
fields: [
|
fields: [
|
||||||
rowField([
|
rowField([
|
||||||
slugField({ name: fields.slug }),
|
slugField({ name: fields.slug }),
|
||||||
|
@ -80,23 +74,7 @@ export const Contents = buildVersionedCollectionConfig({
|
||||||
relationTo: Collections.ContentsThumbnails,
|
relationTo: Collections.ContentsThumbnails,
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
rowField([
|
tagsField({ name: fields.tags }),
|
||||||
keysField({
|
|
||||||
name: fields.categories,
|
|
||||||
relationTo: KeysTypes.Categories,
|
|
||||||
hasMany: true,
|
|
||||||
}),
|
|
||||||
keysField({
|
|
||||||
name: fields.type,
|
|
||||||
relationTo: KeysTypes.Contents,
|
|
||||||
}),
|
|
||||||
backPropagationField({
|
|
||||||
name: fields.libraryItems,
|
|
||||||
hasMany: true,
|
|
||||||
relationTo: Collections.LibraryItems,
|
|
||||||
where: ({ id }) => ({ "contents.content": { equals: id } }),
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
translatedFields({
|
translatedFields({
|
||||||
name: fields.translations,
|
name: fields.translations,
|
||||||
admin: { useAsTitle: fields.title, hasSourceLanguage: true },
|
admin: { useAsTitle: fields.title, hasSourceLanguage: true },
|
||||||
|
@ -217,19 +195,30 @@ export const Contents = buildVersionedCollectionConfig({
|
||||||
rowField([
|
rowField([
|
||||||
backPropagationField({
|
backPropagationField({
|
||||||
name: fields.folders,
|
name: fields.folders,
|
||||||
|
relationTo: Collections.Folders,
|
||||||
hasMany: true,
|
hasMany: true,
|
||||||
relationTo: Collections.ContentsFolders,
|
where: ({ id }) => ({
|
||||||
where: ({ id }) => ({ contents: { equals: id } }),
|
and: [
|
||||||
admin: {
|
{ "files.value": { equals: id } },
|
||||||
description: `You can set the folder(s) from the "Contents Folders" collection`,
|
{ "files.relationTo": { equals: Collections.Contents } },
|
||||||
},
|
] as Where[],
|
||||||
}),
|
}),
|
||||||
|
}),
|
||||||
|
backPropagationField({
|
||||||
|
name: fields.libraryItems,
|
||||||
|
hasMany: true,
|
||||||
|
relationTo: Collections.LibraryItems,
|
||||||
|
where: ({ id }) => ({ "contents.content": { equals: id } }),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
rowField([
|
||||||
backPropagationField({
|
backPropagationField({
|
||||||
name: fields.previousContents,
|
name: fields.previousContents,
|
||||||
relationTo: Collections.Contents,
|
relationTo: Collections.Contents,
|
||||||
hasMany: true,
|
hasMany: true,
|
||||||
where: ({ id }) => ({ [fields.nextContents]: { equals: id } }),
|
where: ({ id }) => ({ [fields.nextContents]: { equals: id } }),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
{
|
{
|
||||||
name: fields.nextContents,
|
name: fields.nextContents,
|
||||||
type: "relationship",
|
type: "relationship",
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { Collections } from "../../../constants";
|
||||||
|
import { createGetByEndpoint } from "../../../endpoints/createGetByEndpoint";
|
||||||
|
import { EndpointContent } from "../../../sdk";
|
||||||
|
import { Content } from "../../../types/collections";
|
||||||
|
import { isPayloadArrayType, isPayloadType, isValidPayloadImage } from "../../../utils/asserts";
|
||||||
|
import { convertTagsToGroups } from "../../../utils/tags";
|
||||||
|
|
||||||
|
export const getBySlugEndpoint = createGetByEndpoint(
|
||||||
|
Collections.Contents,
|
||||||
|
"slug",
|
||||||
|
({ thumbnail, slug, translations, tags }: Content): EndpointContent => ({
|
||||||
|
slug,
|
||||||
|
...(isValidPayloadImage(thumbnail) ? { thumbnail } : {}),
|
||||||
|
tagGroups: convertTagsToGroups(tags),
|
||||||
|
translations: translations.map((translation) => {
|
||||||
|
const { language, sourceLanguage, title, subtitle, pretitle, summary } = translation;
|
||||||
|
const text = handleTextContent(translation);
|
||||||
|
|
||||||
|
return {
|
||||||
|
language: isPayloadType(language) ? language.id : language,
|
||||||
|
sourceLanguage: isPayloadType(sourceLanguage) ? sourceLanguage.id : sourceLanguage,
|
||||||
|
...(pretitle ? { pretitle } : {}),
|
||||||
|
title,
|
||||||
|
...(subtitle ? { subtitle } : {}),
|
||||||
|
...(summary ? { summary } : {}),
|
||||||
|
format: { ...(text ? { text } : {}) },
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
const handleTextContent = ({
|
||||||
|
textContent,
|
||||||
|
textNotes,
|
||||||
|
textProofreaders,
|
||||||
|
textTranscribers,
|
||||||
|
textTranslators,
|
||||||
|
}: Content["translations"][number]): EndpointContent["translations"][number]["format"]["text"] => {
|
||||||
|
if (!textContent) return undefined;
|
||||||
|
|
||||||
|
return {
|
||||||
|
content: textContent,
|
||||||
|
toc: [],
|
||||||
|
translators: isPayloadArrayType(textTranslators) ? textTranslators.map(({ id }) => id) : [],
|
||||||
|
transcribers: isPayloadArrayType(textTranscribers) ? textTranscribers.map(({ id }) => id) : [],
|
||||||
|
proofreaders: isPayloadArrayType(textProofreaders) ? textProofreaders.map(({ id }) => id) : [],
|
||||||
|
...(textNotes ? { notes: textNotes } : {}),
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,56 +0,0 @@
|
||||||
import { CollectionGroups, Collections } from "../../constants";
|
|
||||||
import { rowField } from "../../fields/rowField/rowField";
|
|
||||||
import { slugField } from "../../fields/slugField/slugField";
|
|
||||||
import { translatedFields } from "../../fields/translatedFields/translatedFields";
|
|
||||||
import { buildCollectionConfig } from "../../utils/collectionConfig";
|
|
||||||
import { importFromStrapi } from "./endpoints/importFromStrapi";
|
|
||||||
|
|
||||||
const fields = {
|
|
||||||
slug: "slug",
|
|
||||||
translations: "translations",
|
|
||||||
name: "name",
|
|
||||||
subfolders: "subfolders",
|
|
||||||
contents: "contents",
|
|
||||||
} as const satisfies Record<string, string>;
|
|
||||||
|
|
||||||
export const ContentsFolders = buildCollectionConfig({
|
|
||||||
slug: Collections.ContentsFolders,
|
|
||||||
labels: {
|
|
||||||
singular: "Contents Folder",
|
|
||||||
plural: "Contents Folders",
|
|
||||||
},
|
|
||||||
defaultSort: fields.slug,
|
|
||||||
admin: {
|
|
||||||
useAsTitle: fields.slug,
|
|
||||||
defaultColumns: [fields.slug, fields.translations],
|
|
||||||
disableDuplicate: true,
|
|
||||||
group: CollectionGroups.Collections,
|
|
||||||
},
|
|
||||||
endpoints: [importFromStrapi],
|
|
||||||
timestamps: false,
|
|
||||||
versions: false,
|
|
||||||
fields: [
|
|
||||||
slugField({ name: fields.slug }),
|
|
||||||
translatedFields({
|
|
||||||
name: fields.translations,
|
|
||||||
admin: {
|
|
||||||
useAsTitle: fields.name,
|
|
||||||
},
|
|
||||||
fields: [{ name: fields.name, type: "text", required: true }],
|
|
||||||
}),
|
|
||||||
rowField([
|
|
||||||
{
|
|
||||||
type: "relationship",
|
|
||||||
name: fields.subfolders,
|
|
||||||
relationTo: Collections.ContentsFolders,
|
|
||||||
hasMany: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "relationship",
|
|
||||||
name: fields.contents,
|
|
||||||
relationTo: Collections.Contents,
|
|
||||||
hasMany: true,
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
],
|
|
||||||
});
|
|
|
@ -1,125 +0,0 @@
|
||||||
import payload from "payload";
|
|
||||||
import QueryString from "qs";
|
|
||||||
import { Collections } from "../../../constants";
|
|
||||||
import { CollectionEndpoint } from "../../../types/payload";
|
|
||||||
import { StrapiLanguage } from "../../../types/strapi";
|
|
||||||
import { isUndefined } from "../../../utils/asserts";
|
|
||||||
import { findContent } from "../../../utils/localApi";
|
|
||||||
|
|
||||||
type StrapiContentsFolder = {
|
|
||||||
id: string;
|
|
||||||
attributes: {
|
|
||||||
slug: string;
|
|
||||||
titles?: { title: string; language: StrapiLanguage }[];
|
|
||||||
subfolders: { data: StrapiContentsFolder[] };
|
|
||||||
contents: { data: { attributes: { slug: string } }[] };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const getStrapiContentFolder = async (id: number): Promise<StrapiContentsFolder> => {
|
|
||||||
const paramsWithPagination = QueryString.stringify({
|
|
||||||
populate: [
|
|
||||||
"contents",
|
|
||||||
"subfolders",
|
|
||||||
"subfolders.contents",
|
|
||||||
"subfolders.titles",
|
|
||||||
"subfolders.titles.language",
|
|
||||||
"subfolders.subfolders",
|
|
||||||
"subfolders.subfolders.contents",
|
|
||||||
"subfolders.subfolders.titles",
|
|
||||||
"subfolders.subfolders.titles.language",
|
|
||||||
"subfolders.subfolders.subfolders",
|
|
||||||
"subfolders.subfolders.subfolders.contents",
|
|
||||||
"subfolders.subfolders.subfolders.titles",
|
|
||||||
"subfolders.subfolders.subfolders.titles.language",
|
|
||||||
"subfolders.subfolders.subfolders.subfolders",
|
|
||||||
"subfolders.subfolders.subfolders.subfolders.contents",
|
|
||||||
"subfolders.subfolders.subfolders.subfolders.titles",
|
|
||||||
"subfolders.subfolders.subfolders.subfolders.titles.language",
|
|
||||||
"subfolders.subfolders.subfolders.subfolders.subfolders",
|
|
||||||
"subfolders.subfolders.subfolders.subfolders.subfolders.contents",
|
|
||||||
"subfolders.subfolders.subfolders.subfolders.subfolders.titles",
|
|
||||||
"subfolders.subfolders.subfolders.subfolders.subfolders.titles.language",
|
|
||||||
"subfolders.subfolders.subfolders.subfolders.subfolders.subfolders",
|
|
||||||
"subfolders.subfolders.subfolders.subfolders.subfolders.subfolders.contents",
|
|
||||||
"subfolders.subfolders.subfolders.subfolders.subfolders.subfolders.titles",
|
|
||||||
"subfolders.subfolders.subfolders.subfolders.subfolders.subfolders.titles.language",
|
|
||||||
"subfolders.subfolders.subfolders.subfolders.subfolders.subfolders.subfolders",
|
|
||||||
"subfolders.subfolders.subfolders.subfolders.subfolders.subfolders.subfolders.contents",
|
|
||||||
"subfolders.subfolders.subfolders.subfolders.subfolders.subfolders.subfolders.titles",
|
|
||||||
"subfolders.subfolders.subfolders.subfolders.subfolders.subfolders.subfolders.titles.language",
|
|
||||||
],
|
|
||||||
});
|
|
||||||
const uri = `${process.env.STRAPI_URI}/api/contents-folders/${id}?${paramsWithPagination}`;
|
|
||||||
const fetchResult = await fetch(uri, {
|
|
||||||
method: "get",
|
|
||||||
headers: { authorization: `Bearer ${process.env.STRAPI_TOKEN}` },
|
|
||||||
});
|
|
||||||
const { data } = await fetchResult.json();
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const importFromStrapi: CollectionEndpoint = {
|
|
||||||
method: "post",
|
|
||||||
path: "/strapi",
|
|
||||||
handler: async (req, res) => {
|
|
||||||
if (!req.user) {
|
|
||||||
return res.status(403).send({
|
|
||||||
errors: [
|
|
||||||
{
|
|
||||||
message: "You are not allowed to perform this action.",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let foldersCreated = 0;
|
|
||||||
const errors: string[] = [];
|
|
||||||
|
|
||||||
const createContentFolder = async (data: StrapiContentsFolder): Promise<string> => {
|
|
||||||
const { slug, titles } = data.attributes;
|
|
||||||
|
|
||||||
const subfolders = await Promise.all(
|
|
||||||
data.attributes.subfolders.data.map(createContentFolder)
|
|
||||||
);
|
|
||||||
|
|
||||||
const contents: string[] = [];
|
|
||||||
for (const content of data.attributes.contents.data) {
|
|
||||||
try {
|
|
||||||
const result = await findContent(content.attributes.slug);
|
|
||||||
contents.push(result);
|
|
||||||
} catch (e) {
|
|
||||||
errors.push(`Couldn't add ${content.attributes.slug} to folder ${slug}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await payload.create({
|
|
||||||
collection: Collections.ContentsFolders,
|
|
||||||
data: {
|
|
||||||
slug,
|
|
||||||
subfolders,
|
|
||||||
contents,
|
|
||||||
translations: titles?.map(({ title, language }) => {
|
|
||||||
if (isUndefined(language.data))
|
|
||||||
throw new Error("A language is required for a content folder translation");
|
|
||||||
return { language: language.data.attributes.code, name: title };
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
user: req.user,
|
|
||||||
});
|
|
||||||
foldersCreated++;
|
|
||||||
return result.id;
|
|
||||||
};
|
|
||||||
|
|
||||||
const rootFolder = await getStrapiContentFolder(72);
|
|
||||||
try {
|
|
||||||
await createContentFolder(rootFolder);
|
|
||||||
} catch (e) {
|
|
||||||
res.status(500).json({ message: "Something went wrong", error: e });
|
|
||||||
}
|
|
||||||
|
|
||||||
res
|
|
||||||
.status(200)
|
|
||||||
.json({ message: `${foldersCreated} entries have been added successfully.`, errors });
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -20,11 +20,11 @@ export const getAllEndpoint: CollectionEndpoint = {
|
||||||
const currencies: Currency[] = (
|
const currencies: Currency[] = (
|
||||||
await payload.find({
|
await payload.find({
|
||||||
collection: Collections.Currencies,
|
collection: Collections.Currencies,
|
||||||
limit: 100,
|
sort: "id",
|
||||||
sort: "id"
|
pagination: false,
|
||||||
})
|
})
|
||||||
).docs;
|
).docs;
|
||||||
|
|
||||||
res.status(200).header("Cache-Control", "max-age=60").json(currencies);
|
res.status(200).json(currencies);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -83,7 +83,7 @@ export const Folders = buildCollectionConfig({
|
||||||
{
|
{
|
||||||
type: "relationship",
|
type: "relationship",
|
||||||
name: fields.files,
|
name: fields.files,
|
||||||
relationTo: [Collections.LibraryItems, Collections.Contents],
|
relationTo: [Collections.LibraryItems, Collections.Contents, Collections.Pages],
|
||||||
hasMany: true,
|
hasMany: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { Collections } from "../../../constants";
|
import { Collections } from "../../../constants";
|
||||||
import { createGetByEndpoint } from "../../../endpoints/createGetByEndpoint";
|
import { createGetByEndpoint } from "../../../endpoints/createGetByEndpoint";
|
||||||
import { EndpointFolder, EndpointFolderPreview, PayloadImage } from "../../../sdk";
|
import { EndpointFolder, EndpointFolderPreview } from "../../../sdk";
|
||||||
import { Folder, FoldersThumbnail, Language } from "../../../types/collections";
|
import { Folder, Language } from "../../../types/collections";
|
||||||
import { isDefined, isUndefined, isValidPayloadImage } from "../../../utils/asserts";
|
import { isDefined, isPayloadType, isValidPayloadImage } from "../../../utils/asserts";
|
||||||
|
|
||||||
export const getBySlugEndpoint = createGetByEndpoint(
|
export const getBySlugEndpoint = createGetByEndpoint(
|
||||||
Collections.Folders,
|
Collections.Folders,
|
||||||
|
@ -15,7 +15,7 @@ export const getBySlugEndpoint = createGetByEndpoint(
|
||||||
? {
|
? {
|
||||||
type: "single",
|
type: "single",
|
||||||
subfolders:
|
subfolders:
|
||||||
folder.sections[0]?.subfolders?.filter(isValidFolder).map(convertFolderToPreview) ??
|
folder.sections[0]?.subfolders?.filter(isPayloadType).map(convertFolderToPreview) ??
|
||||||
[],
|
[],
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
|
@ -29,6 +29,20 @@ export const getBySlugEndpoint = createGetByEndpoint(
|
||||||
subfolders: subfolders.map(convertFolderToPreview),
|
subfolders: subfolders.map(convertFolderToPreview),
|
||||||
})) ?? [],
|
})) ?? [],
|
||||||
},
|
},
|
||||||
|
files:
|
||||||
|
folder.files?.flatMap<EndpointFolder["files"][number]>(({ relationTo, value }) => {
|
||||||
|
if (!isPayloadType(value)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
switch (relationTo) {
|
||||||
|
case "contents":
|
||||||
|
return [{ relationTo, value }];
|
||||||
|
case "library-items":
|
||||||
|
return [{ relationTo, value }];
|
||||||
|
case "pages":
|
||||||
|
return [{ relationTo, value }];
|
||||||
|
}
|
||||||
|
}) ?? [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -47,10 +61,10 @@ export const convertFolderToPreview = ({
|
||||||
translations?.map(({ language, name, description }) => ({
|
translations?.map(({ language, name, description }) => ({
|
||||||
language: getLanguageId(language),
|
language: getLanguageId(language),
|
||||||
name,
|
name,
|
||||||
description: JSON.stringify(description),
|
...(description ? { description } : {}),
|
||||||
})) ?? [],
|
})) ?? [],
|
||||||
darkThumbnail: getThumbnail(darkThumbnail),
|
darkThumbnail: isValidPayloadImage(darkThumbnail) ? darkThumbnail : undefined,
|
||||||
lightThumbnail: getThumbnail(lightThumbnail),
|
lightThumbnail: isValidPayloadImage(lightThumbnail) ? lightThumbnail : undefined,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,19 +91,7 @@ const isValidSection = (section: {
|
||||||
if (!section.subfolders) {
|
if (!section.subfolders) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return section.subfolders.every(isValidFolder);
|
return section.subfolders.every(isPayloadType);
|
||||||
};
|
|
||||||
|
|
||||||
export const isValidFolder = (folder: string | Folder): folder is Folder =>
|
|
||||||
typeof folder !== "string";
|
|
||||||
|
|
||||||
const getThumbnail = (
|
|
||||||
thumbnail: string | FoldersThumbnail | null | undefined
|
|
||||||
): PayloadImage | undefined => {
|
|
||||||
if (isUndefined(thumbnail)) return undefined;
|
|
||||||
if (typeof thumbnail === "string") return undefined;
|
|
||||||
if (!isValidPayloadImage(thumbnail)) return undefined;
|
|
||||||
return thumbnail;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getLanguageId = (language: string | Language) =>
|
const getLanguageId = (language: string | Language) =>
|
||||||
|
|
|
@ -2,7 +2,8 @@ import payload from "payload";
|
||||||
import { Collections } from "../../../constants";
|
import { Collections } from "../../../constants";
|
||||||
import { EndpointFolderPreview } from "../../../sdk";
|
import { EndpointFolderPreview } from "../../../sdk";
|
||||||
import { CollectionEndpoint } from "../../../types/payload";
|
import { CollectionEndpoint } from "../../../types/payload";
|
||||||
import { convertFolderToPreview, isValidFolder } from "./getBySlugEndpoint";
|
import { isPayloadType } from "../../../utils/asserts";
|
||||||
|
import { convertFolderToPreview } from "./getBySlugEndpoint";
|
||||||
|
|
||||||
|
|
||||||
export const getRootFoldersEndpoint: CollectionEndpoint = {
|
export const getRootFoldersEndpoint: CollectionEndpoint = {
|
||||||
|
@ -39,7 +40,7 @@ export const getRootFoldersEndpoint: CollectionEndpoint = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = folders.filter(isValidFolder).map<EndpointFolderPreview>(convertFolderToPreview);
|
const result = folders.filter(isPayloadType).map<EndpointFolderPreview>(convertFolderToPreview);
|
||||||
|
|
||||||
res.status(200).json(result);
|
res.status(200).json(result);
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,18 +16,7 @@ export const FoldersThumbnails = buildImageCollectionConfig({
|
||||||
},
|
},
|
||||||
admin: { defaultColumns: [fields.filename, fields.updatedAt] },
|
admin: { defaultColumns: [fields.filename, fields.updatedAt] },
|
||||||
upload: {
|
upload: {
|
||||||
imageSizes: [
|
imageSizes: [],
|
||||||
{
|
|
||||||
name: "medium",
|
|
||||||
height: 400,
|
|
||||||
width: 200,
|
|
||||||
fit: "contain",
|
|
||||||
formatOptions: {
|
|
||||||
format: "webp",
|
|
||||||
options: { effort: 6, quality: 80, alphaQuality: 80 },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
fields: [],
|
fields: [],
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { Collections } from "../../constants";
|
||||||
|
import { buildImageCollectionConfig } from "../../utils/imageCollectionConfig";
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
filename: "filename",
|
||||||
|
mimeType: "mimeType",
|
||||||
|
filesize: "filesize",
|
||||||
|
posts: "posts",
|
||||||
|
updatedAt: "updatedAt",
|
||||||
|
} as const satisfies Record<string, string>;
|
||||||
|
|
||||||
|
export const Images = buildImageCollectionConfig({
|
||||||
|
slug: Collections.Images,
|
||||||
|
labels: {
|
||||||
|
singular: "Image",
|
||||||
|
plural: "Images",
|
||||||
|
},
|
||||||
|
admin: { defaultColumns: [fields.filename, fields.posts, fields.updatedAt] },
|
||||||
|
upload: {
|
||||||
|
imageSizes: [
|
||||||
|
{
|
||||||
|
name: "og",
|
||||||
|
height: 750,
|
||||||
|
width: 1125,
|
||||||
|
formatOptions: {
|
||||||
|
format: "jpg",
|
||||||
|
options: { progressive: true, mozjpeg: true, compressionLevel: 9, quality: 60 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
fields: [],
|
||||||
|
});
|
|
@ -8,6 +8,7 @@ import { beforeDuplicateAddCopyTo } from "../../hooks/beforeDuplicateAddCopyTo";
|
||||||
import { Key } from "../../types/collections";
|
import { Key } from "../../types/collections";
|
||||||
import { isDefined, isUndefined } from "../../utils/asserts";
|
import { isDefined, isUndefined } from "../../utils/asserts";
|
||||||
import { buildCollectionConfig } from "../../utils/collectionConfig";
|
import { buildCollectionConfig } from "../../utils/collectionConfig";
|
||||||
|
import { getAllEndpoint } from "./endpoints/getAllEndpoint";
|
||||||
import { importFromStrapi } from "./endpoints/importFromStrapi";
|
import { importFromStrapi } from "./endpoints/importFromStrapi";
|
||||||
|
|
||||||
const fields = {
|
const fields = {
|
||||||
|
@ -74,7 +75,7 @@ export const Keys = buildCollectionConfig({
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
endpoints: [importFromStrapi],
|
endpoints: [importFromStrapi, getAllEndpoint],
|
||||||
timestamps: false,
|
timestamps: false,
|
||||||
versions: false,
|
versions: false,
|
||||||
fields: [
|
fields: [
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
import payload from "payload";
|
||||||
|
import { Collections } from "../../../constants";
|
||||||
|
import { EndpointKey } from "../../../sdk";
|
||||||
|
import { Key } from "../../../types/collections";
|
||||||
|
import { CollectionEndpoint } from "../../../types/payload";
|
||||||
|
import { isPayloadType } from "../../../utils/asserts";
|
||||||
|
|
||||||
|
export const getAllEndpoint: CollectionEndpoint = {
|
||||||
|
method: "get",
|
||||||
|
path: "/all",
|
||||||
|
handler: async (req, res) => {
|
||||||
|
if (!req.user) {
|
||||||
|
return res.status(403).send({
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message: "You are not allowed to perform this action.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const keys: Key[] = (
|
||||||
|
await payload.find({
|
||||||
|
collection: Collections.Keys,
|
||||||
|
sort: "id",
|
||||||
|
pagination: false,
|
||||||
|
})
|
||||||
|
).docs;
|
||||||
|
|
||||||
|
const result: EndpointKey[] = keys.map(({ translations, ...others }) => ({
|
||||||
|
...others,
|
||||||
|
translations:
|
||||||
|
translations?.map(({ language, name, short }) => ({
|
||||||
|
language: isPayloadType(language) ? language.id : language,
|
||||||
|
name,
|
||||||
|
short: short ?? name,
|
||||||
|
})) ?? [],
|
||||||
|
}));
|
||||||
|
|
||||||
|
res.status(200).json(result);
|
||||||
|
},
|
||||||
|
};
|
|
@ -20,8 +20,8 @@ export const getAllEndpoint: CollectionEndpoint = {
|
||||||
const languages: Language[] = (
|
const languages: Language[] = (
|
||||||
await payload.find({
|
await payload.find({
|
||||||
collection: Collections.Languages,
|
collection: Collections.Languages,
|
||||||
limit: 100,
|
sort: "name",
|
||||||
sort: "name"
|
pagination: false,
|
||||||
})
|
})
|
||||||
).docs;
|
).docs;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,215 @@
|
||||||
|
import { Where } from "payload/types";
|
||||||
|
import { sectionBlock } from "../../blocks/sectionBlock";
|
||||||
|
import { QuickFilters, publishStatusFilters } from "../../components/QuickFilters";
|
||||||
|
import { CollectionGroups, Collections, PageType } from "../../constants";
|
||||||
|
import { backPropagationField } from "../../fields/backPropagationField/backPropagationField";
|
||||||
|
import { imageField } from "../../fields/imageField/imageField";
|
||||||
|
import { rowField } from "../../fields/rowField/rowField";
|
||||||
|
import { slugField } from "../../fields/slugField/slugField";
|
||||||
|
import { tagsField } from "../../fields/tagsField/tagsField";
|
||||||
|
import { translatedFields } from "../../fields/translatedFields/translatedFields";
|
||||||
|
import { beforeDuplicateAddCopyTo } from "../../hooks/beforeDuplicateAddCopyTo";
|
||||||
|
import { beforeDuplicatePiping } from "../../hooks/beforeDuplicatePiping";
|
||||||
|
import { beforeDuplicateUnpublish } from "../../hooks/beforeDuplicateUnpublish";
|
||||||
|
import { isDefined, isUndefined } from "../../utils/asserts";
|
||||||
|
import { createEditor } from "../../utils/editor";
|
||||||
|
import { buildVersionedCollectionConfig } from "../../utils/versionedCollectionConfig";
|
||||||
|
import { getBySlugEndpoint } from "./endpoints/getBySlugEndpoint";
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
slug: "slug",
|
||||||
|
type: "type",
|
||||||
|
authors: "authors",
|
||||||
|
thumbnail: "thumbnail",
|
||||||
|
translations: "translations",
|
||||||
|
tags: "tags",
|
||||||
|
sourceLanguage: "sourceLanguage",
|
||||||
|
pretitle: "pretitle",
|
||||||
|
title: "title",
|
||||||
|
subtitle: "subtitle",
|
||||||
|
summary: "summary",
|
||||||
|
content: "content",
|
||||||
|
transcribers: "transcribers",
|
||||||
|
translators: "translators",
|
||||||
|
proofreaders: "proofreaders",
|
||||||
|
collectibles: "collectibles",
|
||||||
|
folders: "folders",
|
||||||
|
} as const satisfies Record<string, string>;
|
||||||
|
|
||||||
|
const pageTypesWithAuthor = [PageType.Article];
|
||||||
|
const pageTypesWithCollectibles = [PageType.Content];
|
||||||
|
const pageTypesWithTranscribers = [PageType.Content];
|
||||||
|
|
||||||
|
export const Pages = buildVersionedCollectionConfig({
|
||||||
|
slug: Collections.Pages,
|
||||||
|
labels: {
|
||||||
|
singular: "Page",
|
||||||
|
plural: "Pages",
|
||||||
|
},
|
||||||
|
defaultSort: fields.slug,
|
||||||
|
admin: {
|
||||||
|
useAsTitle: fields.slug,
|
||||||
|
defaultColumns: [fields.thumbnail, fields.slug],
|
||||||
|
group: CollectionGroups.Collections,
|
||||||
|
components: {
|
||||||
|
BeforeListTable: [
|
||||||
|
() =>
|
||||||
|
QuickFilters({
|
||||||
|
slug: Collections.Posts,
|
||||||
|
filterGroups: [publishStatusFilters],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
hooks: {
|
||||||
|
beforeDuplicate: beforeDuplicatePiping([
|
||||||
|
beforeDuplicateUnpublish,
|
||||||
|
beforeDuplicateAddCopyTo(fields.slug),
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
endpoints: [getBySlugEndpoint],
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: fields.type,
|
||||||
|
type: "radio",
|
||||||
|
required: true,
|
||||||
|
defaultValue: PageType.Generic,
|
||||||
|
options: Object.entries(PageType).map(([value, label]) => ({ label, value })),
|
||||||
|
},
|
||||||
|
rowField([
|
||||||
|
slugField({ name: fields.slug }),
|
||||||
|
imageField({
|
||||||
|
name: fields.thumbnail,
|
||||||
|
relationTo: Collections.Images,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
rowField([
|
||||||
|
tagsField({ name: fields.tags }),
|
||||||
|
{
|
||||||
|
name: fields.authors,
|
||||||
|
type: "relationship",
|
||||||
|
admin: {
|
||||||
|
condition: (_, siblingData) => pageTypesWithAuthor.includes(siblingData[fields.type]),
|
||||||
|
},
|
||||||
|
relationTo: Collections.Recorders,
|
||||||
|
required: true,
|
||||||
|
minRows: 1,
|
||||||
|
hasMany: true,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
translatedFields({
|
||||||
|
name: fields.translations,
|
||||||
|
admin: { useAsTitle: fields.title, hasSourceLanguage: true },
|
||||||
|
required: true,
|
||||||
|
minRows: 1,
|
||||||
|
fields: [
|
||||||
|
rowField([
|
||||||
|
{ name: fields.pretitle, type: "text" },
|
||||||
|
{ name: fields.title, type: "text", required: true },
|
||||||
|
{ name: fields.subtitle, type: "text" },
|
||||||
|
]),
|
||||||
|
{
|
||||||
|
name: fields.summary,
|
||||||
|
type: "richText",
|
||||||
|
editor: createEditor({ inlines: true, lists: true, links: true }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: fields.content,
|
||||||
|
type: "richText",
|
||||||
|
required: true,
|
||||||
|
editor: createEditor({
|
||||||
|
images: true,
|
||||||
|
inlines: true,
|
||||||
|
alignment: true,
|
||||||
|
blocks: [sectionBlock],
|
||||||
|
links: true,
|
||||||
|
lists: true,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
rowField([
|
||||||
|
{
|
||||||
|
name: fields.transcribers,
|
||||||
|
type: "relationship",
|
||||||
|
relationTo: Collections.Recorders,
|
||||||
|
hasMany: true,
|
||||||
|
admin: {
|
||||||
|
condition: (data, siblingData) => {
|
||||||
|
if (!pageTypesWithTranscribers.includes(data[fields.type])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isUndefined(siblingData.language) || isUndefined(siblingData.sourceLanguage)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return siblingData.language === siblingData.sourceLanguage;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: fields.translators,
|
||||||
|
type: "relationship",
|
||||||
|
relationTo: Collections.Recorders,
|
||||||
|
hasMany: true,
|
||||||
|
hooks: {
|
||||||
|
beforeChange: [
|
||||||
|
({ siblingData }) => {
|
||||||
|
if (siblingData.language === siblingData.sourceLanguage) {
|
||||||
|
delete siblingData.translators;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
admin: {
|
||||||
|
condition: (_, siblingData) => {
|
||||||
|
if (isUndefined(siblingData.language) || isUndefined(siblingData.sourceLanguage)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return siblingData.language !== siblingData.sourceLanguage;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
validate: (translators, { siblingData }) => {
|
||||||
|
if (isUndefined(siblingData.language) || isUndefined(siblingData.sourceLanguage)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (siblingData.language === siblingData.sourceLanguage) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (isDefined(translators) && translators.length > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return "This field is required when the language is different from the source language.";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: fields.proofreaders,
|
||||||
|
type: "relationship",
|
||||||
|
relationTo: Collections.Recorders,
|
||||||
|
hasMany: true,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
rowField([
|
||||||
|
backPropagationField({
|
||||||
|
name: fields.folders,
|
||||||
|
relationTo: Collections.Folders,
|
||||||
|
hasMany: true,
|
||||||
|
where: ({ id }) => ({
|
||||||
|
and: [
|
||||||
|
{ "files.value": { equals: id } },
|
||||||
|
{ "files.relationTo": { equals: Collections.Pages } },
|
||||||
|
] as Where[],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
backPropagationField({
|
||||||
|
name: fields.collectibles,
|
||||||
|
hasMany: true,
|
||||||
|
relationTo: Collections.LibraryItems,
|
||||||
|
admin: {
|
||||||
|
condition: (_, siblingData) =>
|
||||||
|
pageTypesWithCollectibles.includes(siblingData[fields.type]),
|
||||||
|
},
|
||||||
|
where: ({ id }) => ({ "contents.content": { equals: id } }),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
});
|
|
@ -0,0 +1,134 @@
|
||||||
|
import {
|
||||||
|
Collections,
|
||||||
|
PageType,
|
||||||
|
RichTextContent,
|
||||||
|
isBlockNodeSectionBlock,
|
||||||
|
isNodeBlockNode,
|
||||||
|
} from "../../../constants";
|
||||||
|
import { createGetByEndpoint } from "../../../endpoints/createGetByEndpoint";
|
||||||
|
import { EndpointPage, ParentPage, TableOfContentEntry } from "../../../sdk";
|
||||||
|
import { Page } from "../../../types/collections";
|
||||||
|
import { isPayloadArrayType, isPayloadType, isValidPayloadImage } from "../../../utils/asserts";
|
||||||
|
import { convertTagsToGroups } from "../../../utils/tags";
|
||||||
|
|
||||||
|
export const getBySlugEndpoint = createGetByEndpoint(
|
||||||
|
Collections.Pages,
|
||||||
|
"slug",
|
||||||
|
({
|
||||||
|
authors,
|
||||||
|
slug,
|
||||||
|
translations,
|
||||||
|
tags,
|
||||||
|
thumbnail,
|
||||||
|
_status,
|
||||||
|
collectibles,
|
||||||
|
folders,
|
||||||
|
type,
|
||||||
|
}: Page): EndpointPage => ({
|
||||||
|
slug,
|
||||||
|
type: type as PageType,
|
||||||
|
...(isValidPayloadImage(thumbnail) ? { thumbnail } : {}),
|
||||||
|
tagGroups: convertTagsToGroups(tags),
|
||||||
|
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,
|
||||||
|
...(pretitle ? { pretitle } : {}),
|
||||||
|
title,
|
||||||
|
...(subtitle ? { subtitle } : {}),
|
||||||
|
...(summary ? { summary } : {}),
|
||||||
|
content: handleContent(content),
|
||||||
|
toc: handleToc(content),
|
||||||
|
translators: isPayloadArrayType(translators) ? translators.map(({ id }) => id) : [],
|
||||||
|
transcribers: isPayloadArrayType(transcribers) ? transcribers.map(({ id }) => id) : [],
|
||||||
|
proofreaders: isPayloadArrayType(proofreaders) ? proofreaders.map(({ id }) => id) : [],
|
||||||
|
})
|
||||||
|
),
|
||||||
|
authors: isPayloadArrayType(authors) ? authors.map(({ id }) => id) : [],
|
||||||
|
status: _status === "published" ? "published" : "draft",
|
||||||
|
parentPages: handleParentPages({ collectibles, folders }),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleContent = (
|
||||||
|
{ root: { children, ...others } }: RichTextContent,
|
||||||
|
parentPrefix = ""
|
||||||
|
): RichTextContent => {
|
||||||
|
let sectionCount = 0;
|
||||||
|
return {
|
||||||
|
root: {
|
||||||
|
...others,
|
||||||
|
children: children.map((node) => {
|
||||||
|
if (isNodeBlockNode(node) && isBlockNodeSectionBlock(node)) {
|
||||||
|
sectionCount++;
|
||||||
|
const anchorHash = `${parentPrefix}${sectionCount}.`;
|
||||||
|
return {
|
||||||
|
...node,
|
||||||
|
fields: {
|
||||||
|
...node.fields,
|
||||||
|
anchorHash,
|
||||||
|
lines: handleContent(node.fields.lines, anchorHash),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleToc = (content: RichTextContent, parentPrefix = ""): TableOfContentEntry[] =>
|
||||||
|
content.root.children
|
||||||
|
.filter(isNodeBlockNode)
|
||||||
|
.filter(isBlockNodeSectionBlock)
|
||||||
|
.map(({ fields }, index) => ({
|
||||||
|
prefix: `${parentPrefix}${index + 1}.`,
|
||||||
|
title: fields.blockName,
|
||||||
|
children: handleToc(fields.lines, `${index + 1}.`),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const handleParentPages = ({
|
||||||
|
collectibles,
|
||||||
|
folders,
|
||||||
|
}: Pick<Page, "collectibles" | "folders">): ParentPage[] => {
|
||||||
|
const result: ParentPage[] = [];
|
||||||
|
|
||||||
|
if (collectibles && isPayloadArrayType(collectibles)) {
|
||||||
|
collectibles.forEach(({ slug, title }) => {
|
||||||
|
result.push({
|
||||||
|
collection: Collections.LibraryItems,
|
||||||
|
slug,
|
||||||
|
translations: [{ language: "en", name: title }],
|
||||||
|
tag: "collectible",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (folders && isPayloadArrayType(folders)) {
|
||||||
|
folders.forEach(({ slug, translations }) => {
|
||||||
|
result.push({
|
||||||
|
collection: Collections.Folders,
|
||||||
|
slug,
|
||||||
|
translations:
|
||||||
|
translations?.map(({ language, name }) => ({
|
||||||
|
language: isPayloadType(language) ? language.id : language,
|
||||||
|
name,
|
||||||
|
})) ?? [],
|
||||||
|
tag: "folders",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
|
@ -8,6 +8,7 @@ import { rowField } from "../../fields/rowField/rowField";
|
||||||
import { translatedFields } from "../../fields/translatedFields/translatedFields";
|
import { translatedFields } from "../../fields/translatedFields/translatedFields";
|
||||||
import { buildCollectionConfig } from "../../utils/collectionConfig";
|
import { buildCollectionConfig } from "../../utils/collectionConfig";
|
||||||
import { createEditor } from "../../utils/editor";
|
import { createEditor } from "../../utils/editor";
|
||||||
|
import { getAllEndpoint } from "./endpoints/getAllEndpoint";
|
||||||
import { importFromStrapi } from "./endpoints/importFromStrapi";
|
import { importFromStrapi } from "./endpoints/importFromStrapi";
|
||||||
import { beforeLoginMustHaveAtLeastOneRole } from "./hooks/beforeLoginMustHaveAtLeastOneRole";
|
import { beforeLoginMustHaveAtLeastOneRole } from "./hooks/beforeLoginMustHaveAtLeastOneRole";
|
||||||
|
|
||||||
|
@ -75,7 +76,7 @@ export const Recorders = buildCollectionConfig({
|
||||||
hooks: {
|
hooks: {
|
||||||
beforeLogin: [beforeLoginMustHaveAtLeastOneRole],
|
beforeLogin: [beforeLoginMustHaveAtLeastOneRole],
|
||||||
},
|
},
|
||||||
endpoints: [importFromStrapi],
|
endpoints: [importFromStrapi, getAllEndpoint],
|
||||||
timestamps: false,
|
timestamps: false,
|
||||||
fields: [
|
fields: [
|
||||||
rowField([
|
rowField([
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
import payload from "payload";
|
||||||
|
import { Collections } from "../../../constants";
|
||||||
|
import { EndpointRecorder } from "../../../sdk";
|
||||||
|
import { CollectionEndpoint } from "../../../types/payload";
|
||||||
|
import { isPayloadArrayType, isPayloadType, isValidPayloadImage } from "../../../utils/asserts";
|
||||||
|
|
||||||
|
export const getAllEndpoint: CollectionEndpoint = {
|
||||||
|
method: "get",
|
||||||
|
path: "/all",
|
||||||
|
handler: async (req, res) => {
|
||||||
|
if (!req.user) {
|
||||||
|
return res.status(403).send({
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message: "You are not allowed to perform this action.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const recorders = (
|
||||||
|
await payload.find({
|
||||||
|
collection: Collections.Recorders,
|
||||||
|
sort: "id",
|
||||||
|
pagination: false,
|
||||||
|
})
|
||||||
|
).docs;
|
||||||
|
|
||||||
|
const result: EndpointRecorder[] = recorders.map(
|
||||||
|
({ anonymize, id, username, avatar, biographies, languages }) => ({
|
||||||
|
id,
|
||||||
|
username: anonymize ? `Recorder#${id.substring(0, 5)}` : username,
|
||||||
|
...(isValidPayloadImage(avatar) ? { avatar } : {}),
|
||||||
|
languages: isPayloadArrayType(languages) ? languages.map(({ id }) => id) : [],
|
||||||
|
biographies:
|
||||||
|
biographies?.map(({ biography, language }) => ({
|
||||||
|
language: isPayloadType(language) ? language.id : language,
|
||||||
|
biography,
|
||||||
|
})) ?? [],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
res.status(200).json(result);
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,56 @@
|
||||||
|
import payload from "payload";
|
||||||
|
import { CollectionBeforeChangeHook, CollectionConfig } from "payload/types";
|
||||||
|
import { CollectionGroups, Collections } from "../../constants";
|
||||||
|
import { slugField } from "../../fields/slugField/slugField";
|
||||||
|
import { translatedFields } from "../../fields/translatedFields/translatedFields";
|
||||||
|
import { buildCollectionConfig } from "../../utils/collectionConfig";
|
||||||
|
import { getAllEndpoint } from "./endpoints/getAllEndpoint";
|
||||||
|
|
||||||
|
const beforeChangeUpdateName: CollectionBeforeChangeHook = async ({ data }) => {
|
||||||
|
let name = data.slug;
|
||||||
|
|
||||||
|
const parentId = data[fields.group];
|
||||||
|
|
||||||
|
if (parentId) {
|
||||||
|
const parent = await payload.findByID({
|
||||||
|
collection: Collections.TagsGroups,
|
||||||
|
id: data[fields.group],
|
||||||
|
});
|
||||||
|
name = `${parent.slug} / ${data.slug}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...data,
|
||||||
|
[fields.name]: name,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
slug: "slug",
|
||||||
|
name: "name",
|
||||||
|
translations: "translations",
|
||||||
|
translationsName: "name",
|
||||||
|
group: "group",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Tags: CollectionConfig = buildCollectionConfig({
|
||||||
|
slug: Collections.Tags,
|
||||||
|
labels: { singular: "Tag", plural: "Tags" },
|
||||||
|
admin: {
|
||||||
|
group: CollectionGroups.Meta,
|
||||||
|
useAsTitle: fields.name,
|
||||||
|
defaultColumns: [fields.slug, fields.group, fields.translations],
|
||||||
|
},
|
||||||
|
endpoints: [getAllEndpoint],
|
||||||
|
hooks: { beforeChange: [beforeChangeUpdateName] },
|
||||||
|
fields: [
|
||||||
|
{ name: fields.name, type: "text", admin: { readOnly: true, hidden: true } },
|
||||||
|
slugField({ name: fields.slug }),
|
||||||
|
translatedFields({
|
||||||
|
name: fields.translations,
|
||||||
|
admin: { useAsTitle: fields.translationsName },
|
||||||
|
fields: [{ name: fields.translationsName, type: "text", required: true }],
|
||||||
|
}),
|
||||||
|
{ name: fields.group, type: "relationship", required: true, relationTo: Collections.TagsGroups },
|
||||||
|
],
|
||||||
|
});
|
|
@ -0,0 +1,41 @@
|
||||||
|
import payload from "payload";
|
||||||
|
import { Collections } from "../../../constants";
|
||||||
|
import { EndpointTag } from "../../../sdk";
|
||||||
|
import { CollectionEndpoint } from "../../../types/payload";
|
||||||
|
import { isPayloadType } from "../../../utils/asserts";
|
||||||
|
|
||||||
|
export const getAllEndpoint: CollectionEndpoint = {
|
||||||
|
method: "get",
|
||||||
|
path: "/all",
|
||||||
|
handler: async (req, res) => {
|
||||||
|
if (!req.user) {
|
||||||
|
return res.status(403).send({
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message: "You are not allowed to perform this action.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const tags = (
|
||||||
|
await payload.find({
|
||||||
|
collection: Collections.Tags,
|
||||||
|
sort: "id",
|
||||||
|
pagination: false,
|
||||||
|
})
|
||||||
|
).docs;
|
||||||
|
|
||||||
|
const result = tags.map<EndpointTag>(({ slug, translations, group }) => ({
|
||||||
|
slug,
|
||||||
|
translations:
|
||||||
|
translations?.map(({ language, name }) => ({
|
||||||
|
language: isPayloadType(language) ? language.id : language,
|
||||||
|
name,
|
||||||
|
})) ?? [],
|
||||||
|
group: isPayloadType(group) ? group.slug : group,
|
||||||
|
}));
|
||||||
|
|
||||||
|
res.status(200).json(result);
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { CollectionConfig } from "payload/types";
|
||||||
|
import { CollectionGroups, Collections } from "../../constants";
|
||||||
|
import { iconField } from "../../fields/iconField/iconField";
|
||||||
|
import { slugField } from "../../fields/slugField/slugField";
|
||||||
|
import { translatedFields } from "../../fields/translatedFields/translatedFields";
|
||||||
|
import { buildCollectionConfig } from "../../utils/collectionConfig";
|
||||||
|
import { getAllEndpoint } from "./endpoints/getAllEndpoint";
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
slug: "slug",
|
||||||
|
translations: "translations",
|
||||||
|
translationsName: "name",
|
||||||
|
icon: "icon",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TagsGroups: CollectionConfig = buildCollectionConfig({
|
||||||
|
slug: Collections.TagsGroups,
|
||||||
|
labels: { singular: "Tags Group", plural: "Tags Groups" },
|
||||||
|
admin: {
|
||||||
|
group: CollectionGroups.Meta,
|
||||||
|
useAsTitle: fields.slug,
|
||||||
|
defaultColumns: [fields.slug, fields.translations],
|
||||||
|
},
|
||||||
|
endpoints: [getAllEndpoint],
|
||||||
|
fields: [
|
||||||
|
slugField({ name: fields.slug }),
|
||||||
|
iconField({ name: fields.icon }),
|
||||||
|
translatedFields({
|
||||||
|
name: fields.translations,
|
||||||
|
admin: { useAsTitle: fields.translationsName },
|
||||||
|
fields: [{ name: fields.translationsName, type: "text", required: true }],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
|
@ -0,0 +1,42 @@
|
||||||
|
import payload from "payload";
|
||||||
|
import { Collections } from "../../../constants";
|
||||||
|
import { EndpointTagsGroup } from "../../../sdk";
|
||||||
|
import { CollectionEndpoint } from "../../../types/payload";
|
||||||
|
import { isPayloadType } from "../../../utils/asserts";
|
||||||
|
|
||||||
|
export const getAllEndpoint: CollectionEndpoint = {
|
||||||
|
method: "get",
|
||||||
|
path: "/all",
|
||||||
|
handler: async (req, res) => {
|
||||||
|
if (!req.user) {
|
||||||
|
return res.status(403).send({
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message: "You are not allowed to perform this action.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const tags = (
|
||||||
|
await payload.find({
|
||||||
|
collection: Collections.TagsGroups,
|
||||||
|
sort: "id",
|
||||||
|
pagination: false,
|
||||||
|
})
|
||||||
|
).docs;
|
||||||
|
|
||||||
|
const result = tags.map<EndpointTagsGroup>(({ slug, translations, icon }) => ({
|
||||||
|
slug,
|
||||||
|
...(icon ? { icon } : {}),
|
||||||
|
translations:
|
||||||
|
translations?.map(({ language, name }) => ({
|
||||||
|
language: isPayloadType(language) ? language.id : language,
|
||||||
|
name,
|
||||||
|
})) ?? [],
|
||||||
|
tags: [] // TODO: Add tags,
|
||||||
|
}));
|
||||||
|
|
||||||
|
res.status(200).json(result);
|
||||||
|
},
|
||||||
|
};
|
164
src/constants.ts
164
src/constants.ts
|
@ -1,7 +1,10 @@
|
||||||
|
import { CueBlock, LineBlock, SectionBlock, TranscriptBlock } from "./types/collections";
|
||||||
|
|
||||||
|
// END MOCKING SECTION
|
||||||
|
|
||||||
export enum Collections {
|
export enum Collections {
|
||||||
ChronologyEras = "chronology-eras",
|
ChronologyEras = "chronology-eras",
|
||||||
ChronologyItems = "chronology-items",
|
ChronologyItems = "chronology-items",
|
||||||
ContentsFolders = "contents-folders",
|
|
||||||
Contents = "contents",
|
Contents = "contents",
|
||||||
ContentsThumbnails = "contents-thumbnails",
|
ContentsThumbnails = "contents-thumbnails",
|
||||||
Currencies = "currencies",
|
Currencies = "currencies",
|
||||||
|
@ -12,8 +15,10 @@ export enum Collections {
|
||||||
LibraryItemsThumbnails = "library-items-thumbnails",
|
LibraryItemsThumbnails = "library-items-thumbnails",
|
||||||
LibraryItemsScans = "library-items-scans",
|
LibraryItemsScans = "library-items-scans",
|
||||||
LibraryItemsGallery = "library-items-gallery",
|
LibraryItemsGallery = "library-items-gallery",
|
||||||
Notes = "Notes",
|
Notes = "notes",
|
||||||
Posts = "posts",
|
Posts = "posts",
|
||||||
|
Pages = "pages",
|
||||||
|
PagesThumbnails = "pages-thumbnails",
|
||||||
PostsThumbnails = "posts-thumbnails",
|
PostsThumbnails = "posts-thumbnails",
|
||||||
Recorders = "recorders",
|
Recorders = "recorders",
|
||||||
RecordersThumbnails = "recorders-thumbnails",
|
RecordersThumbnails = "recorders-thumbnails",
|
||||||
|
@ -23,7 +28,10 @@ export enum Collections {
|
||||||
WeaponsGroups = "weapons-groups",
|
WeaponsGroups = "weapons-groups",
|
||||||
WeaponsThumbnails = "weapons-thumbnails",
|
WeaponsThumbnails = "weapons-thumbnails",
|
||||||
Folders = "folders",
|
Folders = "folders",
|
||||||
FoldersThumbnails = "FoldersThumbnails",
|
FoldersThumbnails = "folders-thumbnails",
|
||||||
|
Tags = "tags",
|
||||||
|
TagsGroups = "tags-groups",
|
||||||
|
Images = "images",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CollectionGroups {
|
export enum CollectionGroups {
|
||||||
|
@ -95,3 +103,153 @@ export enum VideoSources {
|
||||||
NicoNico = "NicoNico",
|
NicoNico = "NicoNico",
|
||||||
Tumblr = "Tumblr",
|
Tumblr = "Tumblr",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum PageType {
|
||||||
|
Content = "Content",
|
||||||
|
Article = "Article",
|
||||||
|
Generic = "Generic",
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RICH TEXT */
|
||||||
|
|
||||||
|
export type RichTextContent = {
|
||||||
|
root: {
|
||||||
|
children: RichTextNode[];
|
||||||
|
direction: ("ltr" | "rtl") | null;
|
||||||
|
format: "left" | "start" | "center" | "right" | "end" | "justify" | "";
|
||||||
|
indent: number;
|
||||||
|
type: string;
|
||||||
|
version: number;
|
||||||
|
};
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RichTextNode = {
|
||||||
|
type: string;
|
||||||
|
version: number;
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface RichTextNodeWithChildren extends RichTextNode {
|
||||||
|
children: RichTextNode[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RichTextParagraphNode extends RichTextNodeWithChildren {
|
||||||
|
type: "paragraph";
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RichTextListNode extends RichTextNode {
|
||||||
|
type: "list";
|
||||||
|
children: RichTextNodeWithChildren[];
|
||||||
|
listType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RichTextListNumberNode extends RichTextListNode {
|
||||||
|
listType: "number";
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RichTextListBulletNode extends RichTextListNode {
|
||||||
|
listType: "bullet";
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RichTextListCheckNode extends RichTextListNode {
|
||||||
|
listType: "check";
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RichTextTextNode extends RichTextNode {
|
||||||
|
type: "text";
|
||||||
|
format: number;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RichTextLinkNode extends RichTextNodeWithChildren {
|
||||||
|
type: "link";
|
||||||
|
fields: {
|
||||||
|
linkType: "internal" | "custom";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RichTextLinkInternalNode extends RichTextLinkNode {
|
||||||
|
fields: {
|
||||||
|
linkType: "internal";
|
||||||
|
newTab: boolean;
|
||||||
|
doc: {
|
||||||
|
relationTo: string;
|
||||||
|
value: any;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RichTextLinkCustomNode extends RichTextLinkNode {
|
||||||
|
fields: {
|
||||||
|
linkType: "custom";
|
||||||
|
newTab: boolean;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RichTextBlockNode extends RichTextNode {
|
||||||
|
type: "block";
|
||||||
|
fields: {
|
||||||
|
blockType: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RichTextSectionBlock extends RichTextBlockNode {
|
||||||
|
fields: SectionBlock & { anchorHash: string };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RichTextTranscriptBlock extends RichTextBlockNode {
|
||||||
|
fields: TranscriptBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isNodeParagraphNode = (node: RichTextNode): node is RichTextParagraphNode =>
|
||||||
|
node.type === "paragraph";
|
||||||
|
|
||||||
|
export const isNodeListNode = (node: RichTextNode): node is RichTextListNode =>
|
||||||
|
node.type === "list";
|
||||||
|
|
||||||
|
export const isListNodeNumberListNode = (node: RichTextListNode): node is RichTextListNumberNode =>
|
||||||
|
node.listType === "number";
|
||||||
|
|
||||||
|
export const isListNodeBulletListNode = (node: RichTextListNode): node is RichTextListBulletNode =>
|
||||||
|
node.listType === "bullet";
|
||||||
|
|
||||||
|
export const isListNodeCheckListNode = (node: RichTextListNode): node is RichTextListCheckNode =>
|
||||||
|
node.listType === "check";
|
||||||
|
|
||||||
|
export const isNodeTextNode = (node: RichTextNode): node is RichTextTextNode =>
|
||||||
|
node.type === "text";
|
||||||
|
|
||||||
|
export const isNodeLinkNode = (node: RichTextNode): node is RichTextLinkNode =>
|
||||||
|
node.type === "link";
|
||||||
|
|
||||||
|
export const isLinkNodeInternalLinkNode = (
|
||||||
|
node: RichTextLinkNode
|
||||||
|
): node is RichTextLinkInternalNode => node.fields.linkType === "internal";
|
||||||
|
|
||||||
|
export const isLinkNodeCustomLinkNode = (node: RichTextLinkNode): node is RichTextLinkCustomNode =>
|
||||||
|
node.fields.linkType === "custom";
|
||||||
|
|
||||||
|
export const isNodeBlockNode = (node: RichTextNode): node is RichTextBlockNode =>
|
||||||
|
node.type === "block";
|
||||||
|
|
||||||
|
export const isBlockNodeSectionBlock = (node: RichTextBlockNode): node is RichTextSectionBlock =>
|
||||||
|
node.fields.blockType === "sectionBlock";
|
||||||
|
|
||||||
|
export const isBlockNodeTranscriptBlock = (
|
||||||
|
node: RichTextBlockNode
|
||||||
|
): node is RichTextTranscriptBlock => node.fields.blockType === "transcriptBlock";
|
||||||
|
|
||||||
|
/* BLOCKS */
|
||||||
|
|
||||||
|
export interface GenericBlock {
|
||||||
|
content: unknown;
|
||||||
|
blockType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isBlockCueBlock = (block: GenericBlock): block is CueBlock =>
|
||||||
|
block.blockType === "cueBlock";
|
||||||
|
|
||||||
|
export const isBlockLineBlock = (block: GenericBlock): block is LineBlock =>
|
||||||
|
block.blockType === "lineBlock";
|
||||||
|
|
|
@ -5,4 +5,8 @@ type Props = Omit<TextField, "type" | "hasMany" | "maxRows" | "minRows">;
|
||||||
export const iconField = (props: Props): TextField => ({
|
export const iconField = (props: Props): TextField => ({
|
||||||
...props,
|
...props,
|
||||||
type: "text",
|
type: "text",
|
||||||
|
admin: {
|
||||||
|
description:
|
||||||
|
"Select an icon from here: https://icones.js.org/collection/material-symbols. Only outline and regular variants are usable on the website.",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { FieldBase, RelationshipField } from "payload/dist/fields/config/types";
|
import { FieldBase, SingleRelationshipField } from "payload/dist/fields/config/types";
|
||||||
import { Collections, KeysTypes } from "../../constants";
|
import { Collections, KeysTypes } from "../../constants";
|
||||||
|
|
||||||
type KeysField = FieldBase & {
|
type KeysField = FieldBase & {
|
||||||
relationTo: KeysTypes;
|
relationTo: KeysTypes;
|
||||||
hasMany?: boolean;
|
hasMany?: boolean;
|
||||||
admin?: RelationshipField["admin"];
|
admin?: SingleRelationshipField["admin"];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const keysField = ({
|
export const keysField = ({
|
||||||
|
@ -12,7 +12,7 @@ export const keysField = ({
|
||||||
hasMany = false,
|
hasMany = false,
|
||||||
admin,
|
admin,
|
||||||
...props
|
...props
|
||||||
}: KeysField): RelationshipField => ({
|
}: KeysField): SingleRelationshipField => ({
|
||||||
...props,
|
...props,
|
||||||
admin: {
|
admin: {
|
||||||
allowCreate: false,
|
allowCreate: false,
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { FieldBase, SingleRelationshipField } from "payload/dist/fields/config/types";
|
||||||
|
import { Collections } from "../../constants";
|
||||||
|
|
||||||
|
type KeysField = FieldBase & {
|
||||||
|
admin?: SingleRelationshipField["admin"];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const tagsField = ({ admin, ...props }: KeysField): SingleRelationshipField => ({
|
||||||
|
...props,
|
||||||
|
admin: {
|
||||||
|
allowCreate: false,
|
||||||
|
...admin,
|
||||||
|
},
|
||||||
|
type: "relationship",
|
||||||
|
hasMany: true,
|
||||||
|
relationTo: Collections.Tags,
|
||||||
|
});
|
|
@ -5,12 +5,12 @@ import { buildConfig } from "payload/config";
|
||||||
import { ChronologyEras } from "./collections/ChronologyEras/ChronologyEras";
|
import { ChronologyEras } from "./collections/ChronologyEras/ChronologyEras";
|
||||||
import { ChronologyItems } from "./collections/ChronologyItems/ChronologyItems";
|
import { ChronologyItems } from "./collections/ChronologyItems/ChronologyItems";
|
||||||
import { Contents } from "./collections/Contents/Contents";
|
import { Contents } from "./collections/Contents/Contents";
|
||||||
import { ContentsFolders } from "./collections/ContentsFolders/ContentsFolders";
|
|
||||||
import { ContentsThumbnails } from "./collections/ContentsThumbnails/ContentsThumbnails";
|
import { ContentsThumbnails } from "./collections/ContentsThumbnails/ContentsThumbnails";
|
||||||
import { Currencies } from "./collections/Currencies/Currencies";
|
import { Currencies } from "./collections/Currencies/Currencies";
|
||||||
import { Files } from "./collections/Files/Files";
|
import { Files } from "./collections/Files/Files";
|
||||||
import { Folders } from "./collections/Folders/Folders";
|
import { Folders } from "./collections/Folders/Folders";
|
||||||
import { FoldersThumbnails } from "./collections/FoldersThumbnails/FoldersThumbnails";
|
import { FoldersThumbnails } from "./collections/FoldersThumbnails/FoldersThumbnails";
|
||||||
|
import { Images } from "./collections/Images/Images";
|
||||||
import { Keys } from "./collections/Keys/Keys";
|
import { Keys } from "./collections/Keys/Keys";
|
||||||
import { Languages } from "./collections/Languages/Languages";
|
import { Languages } from "./collections/Languages/Languages";
|
||||||
import { LibraryItems } from "./collections/LibraryItems/LibraryItems";
|
import { LibraryItems } from "./collections/LibraryItems/LibraryItems";
|
||||||
|
@ -18,10 +18,13 @@ import { LibraryItemsGallery } from "./collections/LibraryItemsGallery/LibraryIt
|
||||||
import { LibraryItemsScans } from "./collections/LibraryItemsScans/LibraryItemsScans";
|
import { LibraryItemsScans } from "./collections/LibraryItemsScans/LibraryItemsScans";
|
||||||
import { LibraryItemsThumbnails } from "./collections/LibraryItemsThumbnails/LibraryItemsThumbnails";
|
import { LibraryItemsThumbnails } from "./collections/LibraryItemsThumbnails/LibraryItemsThumbnails";
|
||||||
import { Notes } from "./collections/Notes/Notes";
|
import { Notes } from "./collections/Notes/Notes";
|
||||||
|
import { Pages } from "./collections/Pages/Pages";
|
||||||
import { Posts } from "./collections/Posts/Posts";
|
import { Posts } from "./collections/Posts/Posts";
|
||||||
import { PostsThumbnails } from "./collections/PostsThumbnails/PostsThumbnails";
|
import { PostsThumbnails } from "./collections/PostsThumbnails/PostsThumbnails";
|
||||||
import { Recorders } from "./collections/Recorders/Recorders";
|
import { Recorders } from "./collections/Recorders/Recorders";
|
||||||
import { RecordersThumbnails } from "./collections/RecordersThumbnails/RecordersThumbnails";
|
import { RecordersThumbnails } from "./collections/RecordersThumbnails/RecordersThumbnails";
|
||||||
|
import { Tags } from "./collections/Tags/Tags";
|
||||||
|
import { TagsGroups } from "./collections/TagsGroups/TagsGroups";
|
||||||
import { Videos } from "./collections/Videos/Videos";
|
import { Videos } from "./collections/Videos/Videos";
|
||||||
import { VideosChannels } from "./collections/VideosChannels/VideosChannels";
|
import { VideosChannels } from "./collections/VideosChannels/VideosChannels";
|
||||||
import { Weapons } from "./collections/Weapons/Weapons";
|
import { Weapons } from "./collections/Weapons/Weapons";
|
||||||
|
@ -51,8 +54,8 @@ export default buildConfig({
|
||||||
FoldersThumbnails,
|
FoldersThumbnails,
|
||||||
LibraryItems,
|
LibraryItems,
|
||||||
Contents,
|
Contents,
|
||||||
ContentsFolders,
|
|
||||||
Posts,
|
Posts,
|
||||||
|
Pages,
|
||||||
ChronologyItems,
|
ChronologyItems,
|
||||||
ChronologyEras,
|
ChronologyEras,
|
||||||
Weapons,
|
Weapons,
|
||||||
|
@ -72,6 +75,9 @@ export default buildConfig({
|
||||||
Currencies,
|
Currencies,
|
||||||
Recorders,
|
Recorders,
|
||||||
Keys,
|
Keys,
|
||||||
|
Tags,
|
||||||
|
TagsGroups,
|
||||||
|
Images
|
||||||
],
|
],
|
||||||
db: mongooseAdapter({
|
db: mongooseAdapter({
|
||||||
url: process.env.MONGODB_URI ?? "mongodb://mongo:27017/payload",
|
url: process.env.MONGODB_URI ?? "mongodb://mongo:27017/payload",
|
||||||
|
|
152
src/sdk.ts
152
src/sdk.ts
|
@ -1,5 +1,5 @@
|
||||||
import { Collections } from "./constants";
|
import { Collections, PageType, RichTextContent } from "./constants";
|
||||||
import { Currency, Language } from "./types/collections";
|
import { Content, Currency, Key, Language, LibraryItem, Page } from "./types/collections";
|
||||||
|
|
||||||
class NodeCache {
|
class NodeCache {
|
||||||
constructor(_params: any) {}
|
constructor(_params: any) {}
|
||||||
|
@ -34,8 +34,8 @@ const refreshToken = async () => {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
email: process.env.PAYLOAD_USER,
|
email: import.meta.env.PAYLOAD_USER,
|
||||||
password: process.env.PAYLOAD_PASSWORD,
|
password: import.meta.env.PAYLOAD_PASSWORD,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
logResponse(loginResult);
|
logResponse(loginResult);
|
||||||
|
@ -74,7 +74,7 @@ const injectAuth = async (init?: RequestInit): Promise<RequestInit> => ({
|
||||||
const logResponse = (res: Response) => console.log(res.status, res.statusText, res.url);
|
const logResponse = (res: Response) => console.log(res.status, res.statusText, res.url);
|
||||||
|
|
||||||
const payloadApiUrl = (collection: Collections, endpoint?: string): string =>
|
const payloadApiUrl = (collection: Collections, endpoint?: string): string =>
|
||||||
`${process.env.PAYLOAD_API_URL}/${collection}${endpoint === undefined ? "" : `/${endpoint}`}`;
|
`${import.meta.env.PAYLOAD_API_URL}/${collection}${endpoint === undefined ? "" : `/${endpoint}`}`;
|
||||||
|
|
||||||
const request = async (url: string, init?: RequestInit): Promise<Response> => {
|
const request = async (url: string, init?: RequestInit): Promise<Response> => {
|
||||||
const result = await fetch(url, await injectAuth(init));
|
const result = await fetch(url, await injectAuth(init));
|
||||||
|
@ -159,14 +159,7 @@ export type EndpointEra = {
|
||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type EndpointFolder = {
|
export type EndpointFolder = EndpointFolderPreview & {
|
||||||
slug: string;
|
|
||||||
icon?: string;
|
|
||||||
translations: {
|
|
||||||
language: string;
|
|
||||||
name: string;
|
|
||||||
description?: string;
|
|
||||||
}[];
|
|
||||||
sections:
|
sections:
|
||||||
| { type: "single"; subfolders: EndpointFolderPreview[] }
|
| { type: "single"; subfolders: EndpointFolderPreview[] }
|
||||||
| {
|
| {
|
||||||
|
@ -176,8 +169,20 @@ export type EndpointFolder = {
|
||||||
subfolders: EndpointFolderPreview[];
|
subfolders: EndpointFolderPreview[];
|
||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
lightThumbnail?: PayloadImage;
|
files: (
|
||||||
darkThumbnail?: PayloadImage;
|
| {
|
||||||
|
relationTo: "library-items";
|
||||||
|
value: LibraryItem;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
relationTo: "contents";
|
||||||
|
value: Content;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
relationTo: "pages";
|
||||||
|
value: Page;
|
||||||
|
}
|
||||||
|
)[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type EndpointFolderPreview = {
|
export type EndpointFolderPreview = {
|
||||||
|
@ -186,12 +191,115 @@ export type EndpointFolderPreview = {
|
||||||
translations: {
|
translations: {
|
||||||
language: string;
|
language: string;
|
||||||
name: string;
|
name: string;
|
||||||
description?: string;
|
description?: RichTextContent;
|
||||||
}[];
|
}[];
|
||||||
lightThumbnail?: PayloadImage;
|
lightThumbnail?: PayloadImage;
|
||||||
darkThumbnail?: PayloadImage;
|
darkThumbnail?: PayloadImage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type EndpointContent = {
|
||||||
|
slug: string;
|
||||||
|
thumbnail?: PayloadImage;
|
||||||
|
tagGroups: TagGroup[];
|
||||||
|
translations: {
|
||||||
|
language: string;
|
||||||
|
sourceLanguage: string;
|
||||||
|
pretitle?: string;
|
||||||
|
title: string;
|
||||||
|
subtitle?: string;
|
||||||
|
summary?: RichTextContent;
|
||||||
|
format: {
|
||||||
|
text?: {
|
||||||
|
content: RichTextContent;
|
||||||
|
toc: TableOfContentEntry[];
|
||||||
|
transcribers: string[];
|
||||||
|
translators: string[];
|
||||||
|
proofreaders: string[];
|
||||||
|
notes?: RichTextContent;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EndpointRecorder = {
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
avatar?: PayloadImage;
|
||||||
|
languages: string[];
|
||||||
|
biographies: {
|
||||||
|
language: string;
|
||||||
|
biography: RichTextContent;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EndpointKey = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
type: Key["type"];
|
||||||
|
translations: {
|
||||||
|
language: string;
|
||||||
|
name: string;
|
||||||
|
short: string;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EndpointTag = {
|
||||||
|
slug: string;
|
||||||
|
translations: {
|
||||||
|
language: string;
|
||||||
|
name: string;
|
||||||
|
}[];
|
||||||
|
group: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EndpointTagsGroup = {
|
||||||
|
slug: string;
|
||||||
|
icon?: string;
|
||||||
|
translations: {
|
||||||
|
language: string;
|
||||||
|
name: string;
|
||||||
|
}[];
|
||||||
|
tags: EndpointTag[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EndpointPage = {
|
||||||
|
slug: string;
|
||||||
|
type: PageType;
|
||||||
|
thumbnail?: PayloadImage;
|
||||||
|
authors: string[];
|
||||||
|
tagGroups: TagGroup[];
|
||||||
|
translations: {
|
||||||
|
language: string;
|
||||||
|
sourceLanguage: string;
|
||||||
|
pretitle?: string;
|
||||||
|
title: string;
|
||||||
|
subtitle?: string;
|
||||||
|
summary?: RichTextContent;
|
||||||
|
content: RichTextContent;
|
||||||
|
transcribers: string[];
|
||||||
|
translators: string[];
|
||||||
|
proofreaders: string[];
|
||||||
|
toc: TableOfContentEntry[];
|
||||||
|
}[];
|
||||||
|
status: "draft" | "published";
|
||||||
|
parentPages: ParentPage[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ParentPage = {
|
||||||
|
slug: string;
|
||||||
|
collection: Collections;
|
||||||
|
translations: { language: string; name: string }[];
|
||||||
|
tag: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TagGroup = { slug: string; icon: string; values: string[] };
|
||||||
|
|
||||||
|
export type TableOfContentEntry = {
|
||||||
|
prefix: string;
|
||||||
|
title: string;
|
||||||
|
children: TableOfContentEntry[];
|
||||||
|
};
|
||||||
|
|
||||||
export type PayloadImage = {
|
export type PayloadImage = {
|
||||||
url: string;
|
url: string;
|
||||||
width: number;
|
width: number;
|
||||||
|
@ -213,4 +321,16 @@ export const payload = {
|
||||||
await (await request(payloadApiUrl(Collections.Languages, `all`))).json(),
|
await (await request(payloadApiUrl(Collections.Languages, `all`))).json(),
|
||||||
getCurrencies: async (): Promise<Currency[]> =>
|
getCurrencies: async (): Promise<Currency[]> =>
|
||||||
await (await request(payloadApiUrl(Collections.Currencies, `all`))).json(),
|
await (await request(payloadApiUrl(Collections.Currencies, `all`))).json(),
|
||||||
|
getContent: async (slug: string): Promise<EndpointContent> =>
|
||||||
|
await (await request(payloadApiUrl(Collections.Contents, `slug/${slug}`))).json(),
|
||||||
|
getKeys: async (): Promise<EndpointKey[]> =>
|
||||||
|
await (await request(payloadApiUrl(Collections.Keys, `all`))).json(),
|
||||||
|
getRecorders: async (): Promise<EndpointRecorder[]> =>
|
||||||
|
await (await request(payloadApiUrl(Collections.Recorders, `all`))).json(),
|
||||||
|
getTags: async (): Promise<EndpointTag[]> =>
|
||||||
|
await (await request(payloadApiUrl(Collections.Tags, `all`))).json(),
|
||||||
|
getTagsGroups: async (): Promise<EndpointTagsGroup[]> =>
|
||||||
|
await (await request(payloadApiUrl(Collections.TagsGroups, `all`))).json(),
|
||||||
|
getPage: async (slug: string): Promise<EndpointPage> =>
|
||||||
|
await (await request(payloadApiUrl(Collections.Pages, `slug/${slug}`))).json(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -59,19 +59,32 @@ const start = async () => {
|
||||||
app.use("/public", express.static(path.join(__dirname, "../public")));
|
app.use("/public", express.static(path.join(__dirname, "../public")));
|
||||||
|
|
||||||
app.get("/api/sdk", (_, res) => {
|
app.get("/api/sdk", (_, res) => {
|
||||||
const collections = readFileSync(path.join(__dirname, "types/collections.ts"), "utf-8");
|
const removeMockingSection = (text: string): string => {
|
||||||
|
const lines = text.split("\n");
|
||||||
|
const endMockingLine = lines.findIndex((line) => line === "// END MOCKING SECTION") ?? 0;
|
||||||
|
return lines.slice(endMockingLine + 1).join("\n");
|
||||||
|
};
|
||||||
|
|
||||||
const constantsHeader = "/////////////// CONSTANTS ///////////////\n";
|
const removeDeclare = (text: string): string => {
|
||||||
const constants = readFileSync(path.join(__dirname, "constants.ts"), "utf-8");
|
const lines = text.split("\n");
|
||||||
|
const startDeclareLine =
|
||||||
|
lines.findIndex((line) => line === "declare module 'payload' {") ?? 0;
|
||||||
|
return lines.slice(0, startDeclareLine).join("\n");
|
||||||
|
};
|
||||||
|
|
||||||
const sdkHeader = "////////////////// SDK //////////////////\n";
|
const result = [];
|
||||||
const sdkLines = readFileSync(path.join(__dirname, "sdk.ts"), "utf-8").split("\n");
|
|
||||||
const endMockingLine = sdkLines.findIndex((line) => line === "// END MOCKING SECTION") ?? 0;
|
result.push(removeDeclare(readFileSync(path.join(__dirname, "types/collections.ts"), "utf-8")));
|
||||||
const sdk =
|
|
||||||
`import NodeCache from "node-cache";\n\n` + sdkLines.slice(endMockingLine + 1).join("\n");
|
result.push("/////////////// CONSTANTS ///////////////");
|
||||||
|
result.push(removeMockingSection(readFileSync(path.join(__dirname, "constants.ts"), "utf-8")));
|
||||||
|
|
||||||
|
result.push("////////////////// SDK //////////////////");
|
||||||
|
result.push(`import NodeCache from "node-cache";`);
|
||||||
|
result.push(removeMockingSection(readFileSync(path.join(__dirname, "sdk.ts"), "utf-8")));
|
||||||
|
|
||||||
res.type("text/plain");
|
res.type("text/plain");
|
||||||
res.send([collections, constantsHeader, constants, sdkHeader, sdk].join("\n\n"));
|
res.send(result.join("\n\n"));
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/robots.txt", (_, res) => {
|
app.get("/robots.txt", (_, res) => {
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
* and re-run `payload generate:types` to regenerate this file.
|
* and re-run `payload generate:types` to regenerate this file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "RecorderBiographies".
|
||||||
|
*/
|
||||||
export type RecorderBiographies =
|
export type RecorderBiographies =
|
||||||
| {
|
| {
|
||||||
language: string | Language;
|
language: string | Language;
|
||||||
|
@ -27,6 +31,10 @@ export type RecorderBiographies =
|
||||||
id?: string | null;
|
id?: string | null;
|
||||||
}[]
|
}[]
|
||||||
| null;
|
| null;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "CategoryTranslations".
|
||||||
|
*/
|
||||||
export type CategoryTranslations =
|
export type CategoryTranslations =
|
||||||
| {
|
| {
|
||||||
language: string | Language;
|
language: string | Language;
|
||||||
|
@ -39,11 +47,11 @@ export type CategoryTranslations =
|
||||||
export interface Config {
|
export interface Config {
|
||||||
collections: {
|
collections: {
|
||||||
folders: Folder;
|
folders: Folder;
|
||||||
FoldersThumbnails: FoldersThumbnail;
|
'folders-thumbnails': FoldersThumbnail;
|
||||||
'library-items': LibraryItem;
|
'library-items': LibraryItem;
|
||||||
contents: Content;
|
contents: Content;
|
||||||
'contents-folders': ContentsFolder;
|
|
||||||
posts: Post;
|
posts: Post;
|
||||||
|
pages: Page;
|
||||||
'chronology-items': ChronologyItem;
|
'chronology-items': ChronologyItem;
|
||||||
'chronology-eras': ChronologyEra;
|
'chronology-eras': ChronologyEra;
|
||||||
weapons: Weapon;
|
weapons: Weapon;
|
||||||
|
@ -56,18 +64,25 @@ export interface Config {
|
||||||
'recorders-thumbnails': RecordersThumbnail;
|
'recorders-thumbnails': RecordersThumbnail;
|
||||||
'posts-thumbnails': PostThumbnail;
|
'posts-thumbnails': PostThumbnail;
|
||||||
files: File;
|
files: File;
|
||||||
Notes: Note;
|
notes: Note;
|
||||||
videos: Video;
|
videos: Video;
|
||||||
'videos-channels': VideosChannel;
|
'videos-channels': VideosChannel;
|
||||||
languages: Language;
|
languages: Language;
|
||||||
currencies: Currency;
|
currencies: Currency;
|
||||||
recorders: Recorder;
|
recorders: Recorder;
|
||||||
keys: Key;
|
keys: Key;
|
||||||
|
tags: Tag;
|
||||||
|
'tags-groups': TagsGroup;
|
||||||
|
images: Image;
|
||||||
'payload-preferences': PayloadPreference;
|
'payload-preferences': PayloadPreference;
|
||||||
'payload-migrations': PayloadMigration;
|
'payload-migrations': PayloadMigration;
|
||||||
};
|
};
|
||||||
globals: {};
|
globals: {};
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "folders".
|
||||||
|
*/
|
||||||
export interface Folder {
|
export interface Folder {
|
||||||
id: string;
|
id: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
|
@ -119,11 +134,19 @@ export interface Folder {
|
||||||
relationTo: 'contents';
|
relationTo: 'contents';
|
||||||
value: string | Content;
|
value: string | Content;
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
relationTo: 'pages';
|
||||||
|
value: string | Page;
|
||||||
|
}
|
||||||
)[]
|
)[]
|
||||||
| null;
|
| null;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "folders-thumbnails".
|
||||||
|
*/
|
||||||
export interface FoldersThumbnail {
|
export interface FoldersThumbnail {
|
||||||
id: string;
|
id: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
|
@ -143,20 +166,20 @@ export interface FoldersThumbnail {
|
||||||
filesize?: number | null;
|
filesize?: number | null;
|
||||||
filename?: string | null;
|
filename?: string | null;
|
||||||
};
|
};
|
||||||
medium?: {
|
|
||||||
url?: string | null;
|
|
||||||
width?: number | null;
|
|
||||||
height?: number | null;
|
|
||||||
mimeType?: string | null;
|
|
||||||
filesize?: number | null;
|
|
||||||
filename?: string | null;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "languages".
|
||||||
|
*/
|
||||||
export interface Language {
|
export interface Language {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "library-items".
|
||||||
|
*/
|
||||||
export interface LibraryItem {
|
export interface LibraryItem {
|
||||||
id: string;
|
id: string;
|
||||||
itemType?: ('Textual' | 'Audio' | 'Video' | 'Game' | 'Other') | null;
|
itemType?: ('Textual' | 'Audio' | 'Video' | 'Game' | 'Other') | null;
|
||||||
|
@ -323,6 +346,10 @@ export interface LibraryItem {
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
_status?: ('draft' | 'published') | null;
|
_status?: ('draft' | 'published') | null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "library-items-thumbnails".
|
||||||
|
*/
|
||||||
export interface LibraryItemThumbnail {
|
export interface LibraryItemThumbnail {
|
||||||
id: string;
|
id: string;
|
||||||
libraryItem?: (string | LibraryItem)[] | null;
|
libraryItem?: (string | LibraryItem)[] | null;
|
||||||
|
@ -361,6 +388,10 @@ export interface LibraryItemThumbnail {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "library-items-gallery".
|
||||||
|
*/
|
||||||
export interface LibraryItemGallery {
|
export interface LibraryItemGallery {
|
||||||
id: string;
|
id: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
|
@ -390,6 +421,10 @@ export interface LibraryItemGallery {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "recorders".
|
||||||
|
*/
|
||||||
export interface Recorder {
|
export interface Recorder {
|
||||||
id: string;
|
id: string;
|
||||||
username: string;
|
username: string;
|
||||||
|
@ -407,6 +442,10 @@ export interface Recorder {
|
||||||
lockUntil?: string | null;
|
lockUntil?: string | null;
|
||||||
password?: string | null;
|
password?: string | null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "recorders-thumbnails".
|
||||||
|
*/
|
||||||
export interface RecordersThumbnail {
|
export interface RecordersThumbnail {
|
||||||
id: string;
|
id: string;
|
||||||
recorder?: (string | null) | Recorder;
|
recorder?: (string | null) | Recorder;
|
||||||
|
@ -437,6 +476,10 @@ export interface RecordersThumbnail {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "library-items-scans".
|
||||||
|
*/
|
||||||
export interface LibraryItemScans {
|
export interface LibraryItemScans {
|
||||||
id: string;
|
id: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
|
@ -482,6 +525,10 @@ export interface LibraryItemScans {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "files".
|
||||||
|
*/
|
||||||
export interface File {
|
export interface File {
|
||||||
id: string;
|
id: string;
|
||||||
filename: string;
|
filename: string;
|
||||||
|
@ -489,6 +536,10 @@ export interface File {
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "keys".
|
||||||
|
*/
|
||||||
export interface Key {
|
export interface Key {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -505,16 +556,22 @@ export interface Key {
|
||||||
| 'Wordings';
|
| 'Wordings';
|
||||||
translations?: CategoryTranslations;
|
translations?: CategoryTranslations;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "currencies".
|
||||||
|
*/
|
||||||
export interface Currency {
|
export interface Currency {
|
||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "contents".
|
||||||
|
*/
|
||||||
export interface Content {
|
export interface Content {
|
||||||
id: string;
|
id: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
thumbnail?: string | ContentsThumbnail | null;
|
thumbnail?: string | ContentsThumbnail | null;
|
||||||
categories?: (string | Key)[] | null;
|
tags?: (string | Tag)[] | null;
|
||||||
type?: (string | null) | Key;
|
|
||||||
libraryItems?: (string | LibraryItem)[] | null;
|
|
||||||
translations: {
|
translations: {
|
||||||
language: string | Language;
|
language: string | Language;
|
||||||
sourceLanguage: string | Language;
|
sourceLanguage: string | Language;
|
||||||
|
@ -603,7 +660,8 @@ export interface Content {
|
||||||
} | null;
|
} | null;
|
||||||
id?: string | null;
|
id?: string | null;
|
||||||
}[];
|
}[];
|
||||||
folders?: (string | ContentsFolder)[] | null;
|
folders?: (string | Folder)[] | null;
|
||||||
|
libraryItems?: (string | LibraryItem)[] | null;
|
||||||
previousContents?: (string | Content)[] | null;
|
previousContents?: (string | Content)[] | null;
|
||||||
nextContents?: (string | Content)[] | null;
|
nextContents?: (string | Content)[] | null;
|
||||||
updatedBy: string | Recorder;
|
updatedBy: string | Recorder;
|
||||||
|
@ -611,6 +669,10 @@ export interface Content {
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
_status?: ('draft' | 'published') | null;
|
_status?: ('draft' | 'published') | null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "contents-thumbnails".
|
||||||
|
*/
|
||||||
export interface ContentsThumbnail {
|
export interface ContentsThumbnail {
|
||||||
id: string;
|
id: string;
|
||||||
contents?: (string | Content)[] | null;
|
contents?: (string | Content)[] | null;
|
||||||
|
@ -649,8 +711,13 @@ export interface ContentsThumbnail {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
export interface ContentsFolder {
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "tags".
|
||||||
|
*/
|
||||||
|
export interface Tag {
|
||||||
id: string;
|
id: string;
|
||||||
|
name?: string | null;
|
||||||
slug: string;
|
slug: string;
|
||||||
translations?:
|
translations?:
|
||||||
| {
|
| {
|
||||||
|
@ -659,9 +726,124 @@ export interface ContentsFolder {
|
||||||
id?: string | null;
|
id?: string | null;
|
||||||
}[]
|
}[]
|
||||||
| null;
|
| null;
|
||||||
subfolders?: (string | ContentsFolder)[] | null;
|
group: string | TagsGroup;
|
||||||
contents?: (string | Content)[] | null;
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "tags-groups".
|
||||||
|
*/
|
||||||
|
export interface TagsGroup {
|
||||||
|
id: string;
|
||||||
|
slug: string;
|
||||||
|
icon?: string | null;
|
||||||
|
translations?:
|
||||||
|
| {
|
||||||
|
language: string | Language;
|
||||||
|
name: string;
|
||||||
|
id?: string | null;
|
||||||
|
}[]
|
||||||
|
| null;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "pages".
|
||||||
|
*/
|
||||||
|
export interface Page {
|
||||||
|
id: string;
|
||||||
|
type: 'Content' | 'Article' | 'Generic';
|
||||||
|
slug: string;
|
||||||
|
thumbnail?: string | Image | null;
|
||||||
|
tags?: (string | Tag)[] | null;
|
||||||
|
authors?: (string | Recorder)[] | null;
|
||||||
|
translations: {
|
||||||
|
language: string | Language;
|
||||||
|
sourceLanguage: string | Language;
|
||||||
|
pretitle?: string | null;
|
||||||
|
title: string;
|
||||||
|
subtitle?: string | null;
|
||||||
|
summary?: {
|
||||||
|
root: {
|
||||||
|
children: {
|
||||||
|
type: string;
|
||||||
|
version: number;
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
direction: ('ltr' | 'rtl') | null;
|
||||||
|
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
|
||||||
|
indent: number;
|
||||||
|
type: string;
|
||||||
|
version: number;
|
||||||
|
};
|
||||||
|
[k: string]: unknown;
|
||||||
|
} | null;
|
||||||
|
content: {
|
||||||
|
root: {
|
||||||
|
children: {
|
||||||
|
type: string;
|
||||||
|
version: number;
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
direction: ('ltr' | 'rtl') | null;
|
||||||
|
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
|
||||||
|
indent: number;
|
||||||
|
type: string;
|
||||||
|
version: number;
|
||||||
|
};
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
transcribers?: (string | Recorder)[] | null;
|
||||||
|
translators?: (string | Recorder)[] | null;
|
||||||
|
proofreaders?: (string | Recorder)[] | null;
|
||||||
|
id?: string | null;
|
||||||
|
}[];
|
||||||
|
folders?: (string | Folder)[] | null;
|
||||||
|
collectibles?: (string | LibraryItem)[] | null;
|
||||||
|
updatedBy: string | Recorder;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
_status?: ('draft' | 'published') | null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "images".
|
||||||
|
*/
|
||||||
|
export interface Image {
|
||||||
|
id: string;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
url?: string | null;
|
||||||
|
filename?: string | null;
|
||||||
|
mimeType?: string | null;
|
||||||
|
filesize?: number | null;
|
||||||
|
width?: number | null;
|
||||||
|
height?: number | null;
|
||||||
|
sizes?: {
|
||||||
|
thumb?: {
|
||||||
|
url?: string | null;
|
||||||
|
width?: number | null;
|
||||||
|
height?: number | null;
|
||||||
|
mimeType?: string | null;
|
||||||
|
filesize?: number | null;
|
||||||
|
filename?: string | null;
|
||||||
|
};
|
||||||
|
og?: {
|
||||||
|
url?: string | null;
|
||||||
|
width?: number | null;
|
||||||
|
height?: number | null;
|
||||||
|
mimeType?: string | null;
|
||||||
|
filesize?: number | null;
|
||||||
|
filename?: string | null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "posts".
|
||||||
|
*/
|
||||||
export interface Post {
|
export interface Post {
|
||||||
id: string;
|
id: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
|
@ -713,6 +895,10 @@ export interface Post {
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
_status?: ('draft' | 'published') | null;
|
_status?: ('draft' | 'published') | null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "posts-thumbnails".
|
||||||
|
*/
|
||||||
export interface PostThumbnail {
|
export interface PostThumbnail {
|
||||||
id: string;
|
id: string;
|
||||||
posts?: (string | Post)[] | null;
|
posts?: (string | Post)[] | null;
|
||||||
|
@ -751,6 +937,10 @@ export interface PostThumbnail {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "chronology-items".
|
||||||
|
*/
|
||||||
export interface ChronologyItem {
|
export interface ChronologyItem {
|
||||||
id: string;
|
id: string;
|
||||||
name?: string | null;
|
name?: string | null;
|
||||||
|
@ -806,6 +996,10 @@ export interface ChronologyItem {
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
_status?: ('draft' | 'published') | null;
|
_status?: ('draft' | 'published') | null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "chronology-eras".
|
||||||
|
*/
|
||||||
export interface ChronologyEra {
|
export interface ChronologyEra {
|
||||||
id: string;
|
id: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
|
@ -837,6 +1031,10 @@ export interface ChronologyEra {
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "weapons".
|
||||||
|
*/
|
||||||
export interface Weapon {
|
export interface Weapon {
|
||||||
id: string;
|
id: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
|
@ -936,6 +1134,10 @@ export interface Weapon {
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
_status?: ('draft' | 'published') | null;
|
_status?: ('draft' | 'published') | null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "weapons-thumbnails".
|
||||||
|
*/
|
||||||
export interface WeaponsThumbnail {
|
export interface WeaponsThumbnail {
|
||||||
id: string;
|
id: string;
|
||||||
weapon?: (string | null) | Weapon;
|
weapon?: (string | null) | Weapon;
|
||||||
|
@ -982,6 +1184,10 @@ export interface WeaponsThumbnail {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "weapons-groups".
|
||||||
|
*/
|
||||||
export interface WeaponsGroup {
|
export interface WeaponsGroup {
|
||||||
id: string;
|
id: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
|
@ -994,6 +1200,10 @@ export interface WeaponsGroup {
|
||||||
| null;
|
| null;
|
||||||
weapons?: (string | Weapon)[] | null;
|
weapons?: (string | Weapon)[] | null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "notes".
|
||||||
|
*/
|
||||||
export interface Note {
|
export interface Note {
|
||||||
id: string;
|
id: string;
|
||||||
note: {
|
note: {
|
||||||
|
@ -1014,6 +1224,10 @@ export interface Note {
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "videos".
|
||||||
|
*/
|
||||||
export interface Video {
|
export interface Video {
|
||||||
id: string;
|
id: string;
|
||||||
uid: string;
|
uid: string;
|
||||||
|
@ -1026,12 +1240,20 @@ export interface Video {
|
||||||
publishedDate: string;
|
publishedDate: string;
|
||||||
channel?: (string | null) | VideosChannel;
|
channel?: (string | null) | VideosChannel;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "videos-channels".
|
||||||
|
*/
|
||||||
export interface VideosChannel {
|
export interface VideosChannel {
|
||||||
id: string;
|
id: string;
|
||||||
uid: string;
|
uid: string;
|
||||||
title: string;
|
title: string;
|
||||||
subscribers?: number | null;
|
subscribers?: number | null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "payload-preferences".
|
||||||
|
*/
|
||||||
export interface PayloadPreference {
|
export interface PayloadPreference {
|
||||||
id: string;
|
id: string;
|
||||||
user: {
|
user: {
|
||||||
|
@ -1051,6 +1273,10 @@ export interface PayloadPreference {
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "payload-migrations".
|
||||||
|
*/
|
||||||
export interface PayloadMigration {
|
export interface PayloadMigration {
|
||||||
id: string;
|
id: string;
|
||||||
name?: string | null;
|
name?: string | null;
|
||||||
|
@ -1058,6 +1284,84 @@ export interface PayloadMigration {
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "LineBlock".
|
||||||
|
*/
|
||||||
|
export interface LineBlock {
|
||||||
|
content: {
|
||||||
|
root: {
|
||||||
|
children: {
|
||||||
|
type: string;
|
||||||
|
version: number;
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
direction: ('ltr' | 'rtl') | null;
|
||||||
|
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
|
||||||
|
indent: number;
|
||||||
|
type: string;
|
||||||
|
version: number;
|
||||||
|
};
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
blockType: 'lineBlock';
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "CueBlock".
|
||||||
|
*/
|
||||||
|
export interface CueBlock {
|
||||||
|
content: {
|
||||||
|
root: {
|
||||||
|
children: {
|
||||||
|
type: string;
|
||||||
|
version: number;
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
direction: ('ltr' | 'rtl') | null;
|
||||||
|
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
|
||||||
|
indent: number;
|
||||||
|
type: string;
|
||||||
|
version: number;
|
||||||
|
};
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
blockType: 'cueBlock';
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "TranscriptBlock".
|
||||||
|
*/
|
||||||
|
export interface TranscriptBlock {
|
||||||
|
lines: (LineBlock | CueBlock)[];
|
||||||
|
id?: string | null;
|
||||||
|
blockName?: string | null;
|
||||||
|
blockType: 'transcriptBlock';
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "SectionBlock".
|
||||||
|
*/
|
||||||
|
export interface SectionBlock {
|
||||||
|
lines: {
|
||||||
|
root: {
|
||||||
|
children: {
|
||||||
|
type: string;
|
||||||
|
version: number;
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
direction: ('ltr' | 'rtl') | null;
|
||||||
|
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
|
||||||
|
indent: number;
|
||||||
|
type: string;
|
||||||
|
version: number;
|
||||||
|
};
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
id?: string | null;
|
||||||
|
blockName?: string | null;
|
||||||
|
blockType: 'sectionBlock';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
declare module 'payload' {
|
declare module 'payload' {
|
||||||
|
|
|
@ -32,9 +32,12 @@ export const isValidPayloadImage = (
|
||||||
height?: number | null;
|
height?: number | null;
|
||||||
url?: string | null;
|
url?: string | null;
|
||||||
}
|
}
|
||||||
| undefined | null
|
| undefined
|
||||||
|
| null
|
||||||
|
| string
|
||||||
): image is PayloadImage => {
|
): image is PayloadImage => {
|
||||||
if (isUndefined(image)) return false;
|
if (isUndefined(image)) return false;
|
||||||
|
if (typeof image === "string") return false;
|
||||||
if (isEmpty(image.filename)) return false;
|
if (isEmpty(image.filename)) return false;
|
||||||
if (isEmpty(image.url)) return false;
|
if (isEmpty(image.url)) return false;
|
||||||
if (isEmpty(image.mimeType)) return false;
|
if (isEmpty(image.mimeType)) return false;
|
||||||
|
@ -49,5 +52,6 @@ export const isString = <T extends Object>(value: string | T): value is string =
|
||||||
export const isPayloadType = <T extends Object>(value: string | T): value is T =>
|
export const isPayloadType = <T extends Object>(value: string | T): value is T =>
|
||||||
typeof value === "object";
|
typeof value === "object";
|
||||||
|
|
||||||
export const isPayloadArrayType = <T extends Object>(value: string[] | T[]): value is T[] =>
|
export const isPayloadArrayType = <T extends Object>(
|
||||||
value.every(isPayloadType<T>);
|
value: (string | T)[] | null | undefined
|
||||||
|
): value is T[] => isDefined(value) && value.every(isPayloadType<T>);
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { TagGroup } from "../sdk";
|
||||||
|
import { Tag } from "../types/collections";
|
||||||
|
import { isPayloadArrayType, isPayloadType } from "./asserts";
|
||||||
|
|
||||||
|
export const convertTagsToGroups = (tags: (string | Tag)[] | null | undefined): TagGroup[] => {
|
||||||
|
if (!isPayloadArrayType(tags)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const groups: TagGroup[] = [];
|
||||||
|
|
||||||
|
tags.forEach(({ group, slug }) => {
|
||||||
|
if (isPayloadType(group)) {
|
||||||
|
const existingGroup = groups.find((existingGroup) => existingGroup.slug === group.slug);
|
||||||
|
if (existingGroup) {
|
||||||
|
existingGroup.values.push(slug);
|
||||||
|
} else {
|
||||||
|
groups.push({
|
||||||
|
slug: group.slug,
|
||||||
|
icon: group.icon ?? "material-symbols:category-outline",
|
||||||
|
values: [slug],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return groups;
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue