Removed posts and contents
This commit is contained in:
parent
8a819de41e
commit
a5b636a858
|
@ -1,230 +0,0 @@
|
|||
import { Where } from "payload/types";
|
||||
import { sectionBlock } from "../../blocks/sectionBlock";
|
||||
import { transcriptBlock } from "../../blocks/transcriptBlock";
|
||||
import { CollectionGroups, Collections, FileTypes } from "../../constants";
|
||||
import { backPropagationField } from "../../fields/backPropagationField/backPropagationField";
|
||||
import { fileField } from "../../fields/fileField/fileField";
|
||||
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 } from "../../utils/asserts";
|
||||
import { createEditor } from "../../utils/editor";
|
||||
import { buildVersionedCollectionConfig } from "../../utils/versionedCollectionConfig";
|
||||
import { getBySlugEndpoint } from "./endpoints/getBySlugEndpoint";
|
||||
import { importFromStrapi } from "./endpoints/importFromStrapi";
|
||||
import { importRelationsFromStrapi } from "./endpoints/importRelationsFromStrapi";
|
||||
|
||||
const fields = {
|
||||
slug: "slug",
|
||||
thumbnail: "thumbnail",
|
||||
translations: "translations",
|
||||
pretitle: "pretitle",
|
||||
title: "title",
|
||||
subtitle: "subtitle",
|
||||
summary: "summary",
|
||||
textContent: "textContent",
|
||||
textTranscribers: "textTranscribers",
|
||||
textTranslators: "textTranslators",
|
||||
textProofreaders: "textProofreaders",
|
||||
textNotes: "textNotes",
|
||||
video: "video",
|
||||
videoNotes: "videoNotes",
|
||||
audio: "audio",
|
||||
audioNotes: "audioNotes",
|
||||
status: "status",
|
||||
updatedBy: "updatedBy",
|
||||
previousContents: "previousContents",
|
||||
nextContents: "nextContents",
|
||||
folders: "folders",
|
||||
libraryItems: "libraryItems",
|
||||
tags: "tags",
|
||||
} as const satisfies Record<string, string>;
|
||||
|
||||
export const Contents = buildVersionedCollectionConfig({
|
||||
slug: Collections.Contents,
|
||||
labels: {
|
||||
singular: "Content",
|
||||
plural: "Contents",
|
||||
},
|
||||
defaultSort: fields.slug,
|
||||
admin: {
|
||||
useAsTitle: fields.slug,
|
||||
description:
|
||||
"All the contents (textual, audio, and video) from the Library or other online sources.",
|
||||
defaultColumns: [fields.thumbnail, fields.slug, fields.translations, fields.status],
|
||||
group: CollectionGroups.Collections,
|
||||
hooks: {
|
||||
beforeDuplicate: beforeDuplicatePiping([
|
||||
beforeDuplicateUnpublish,
|
||||
beforeDuplicateAddCopyTo(fields.slug),
|
||||
]),
|
||||
},
|
||||
},
|
||||
endpoints: [importFromStrapi, importRelationsFromStrapi, getBySlugEndpoint],
|
||||
fields: [
|
||||
rowField([
|
||||
slugField({ name: fields.slug }),
|
||||
imageField({
|
||||
name: fields.thumbnail,
|
||||
relationTo: Collections.ContentsThumbnails,
|
||||
}),
|
||||
]),
|
||||
tagsField({ name: fields.tags }),
|
||||
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 }),
|
||||
},
|
||||
{
|
||||
type: "tabs",
|
||||
admin: {
|
||||
condition: (_, siblingData) =>
|
||||
isDefined(siblingData.language) && isDefined(siblingData.sourceLanguage),
|
||||
},
|
||||
tabs: [
|
||||
{
|
||||
label: "Text",
|
||||
fields: [
|
||||
{
|
||||
name: fields.textContent,
|
||||
type: "richText",
|
||||
label: false,
|
||||
editor: createEditor({
|
||||
blocks: [sectionBlock, transcriptBlock],
|
||||
images: true,
|
||||
inlines: true,
|
||||
lists: true,
|
||||
links: true,
|
||||
relations: true,
|
||||
alignment: true,
|
||||
}),
|
||||
},
|
||||
rowField([
|
||||
{
|
||||
name: fields.textTranscribers,
|
||||
label: "Transcribers",
|
||||
type: "relationship",
|
||||
relationTo: Collections.Recorders,
|
||||
hasMany: true,
|
||||
admin: {
|
||||
condition: (_, siblingData) =>
|
||||
siblingData.language === siblingData.sourceLanguage,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: fields.textTranslators,
|
||||
label: "Translators",
|
||||
type: "relationship",
|
||||
relationTo: Collections.Recorders,
|
||||
hasMany: true,
|
||||
admin: {
|
||||
condition: (_, siblingData) =>
|
||||
siblingData.language !== siblingData.sourceLanguage,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: fields.textProofreaders,
|
||||
label: "Proofreaders",
|
||||
type: "relationship",
|
||||
relationTo: Collections.Recorders,
|
||||
hasMany: true,
|
||||
},
|
||||
]),
|
||||
{
|
||||
name: fields.textNotes,
|
||||
label: "Notes",
|
||||
type: "richText",
|
||||
editor: createEditor({ inlines: true, lists: true, links: true }),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Video",
|
||||
fields: [
|
||||
rowField([
|
||||
fileField({
|
||||
name: fields.video,
|
||||
relationTo: FileTypes.ContentVideo,
|
||||
}),
|
||||
{
|
||||
name: fields.videoNotes,
|
||||
label: "Notes",
|
||||
type: "richText",
|
||||
editor: createEditor({ inlines: true, lists: true, links: true }),
|
||||
},
|
||||
]),
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Audio",
|
||||
fields: [
|
||||
rowField([
|
||||
fileField({
|
||||
name: fields.audio,
|
||||
relationTo: FileTypes.ContentAudio,
|
||||
}),
|
||||
{
|
||||
name: fields.audioNotes,
|
||||
label: "Notes",
|
||||
type: "richText",
|
||||
editor: createEditor({ inlines: true, lists: true, links: true }),
|
||||
},
|
||||
]),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}),
|
||||
rowField([
|
||||
backPropagationField({
|
||||
name: fields.folders,
|
||||
relationTo: Collections.Folders,
|
||||
hasMany: true,
|
||||
where: ({ id }) => ({
|
||||
and: [
|
||||
{ "files.value": { equals: id } },
|
||||
{ "files.relationTo": { equals: Collections.Contents } },
|
||||
] as Where[],
|
||||
}),
|
||||
}),
|
||||
backPropagationField({
|
||||
name: fields.libraryItems,
|
||||
hasMany: true,
|
||||
relationTo: Collections.LibraryItems,
|
||||
where: ({ id }) => ({ "contents.content": { equals: id } }),
|
||||
}),
|
||||
]),
|
||||
rowField([
|
||||
backPropagationField({
|
||||
name: fields.previousContents,
|
||||
relationTo: Collections.Contents,
|
||||
hasMany: true,
|
||||
where: ({ id }) => ({ [fields.nextContents]: { equals: id } }),
|
||||
}),
|
||||
|
||||
{
|
||||
name: fields.nextContents,
|
||||
type: "relationship",
|
||||
hasMany: true,
|
||||
relationTo: Collections.Contents,
|
||||
},
|
||||
]),
|
||||
],
|
||||
});
|
|
@ -1,50 +0,0 @@
|
|||
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,123 +0,0 @@
|
|||
import type { MarkOptional } from "ts-essentials";
|
||||
import { Collections } from "../../../constants";
|
||||
import { createStrapiImportEndpoint } from "../../../endpoints/createStrapiImportEndpoint";
|
||||
import { Content } from "../../../types/collections";
|
||||
import { StrapiImage, StrapiLanguage, StrapiRecorders } from "../../../types/strapi";
|
||||
import { isNotEmpty, isUndefined } from "../../../utils/asserts";
|
||||
import {
|
||||
findCategory,
|
||||
findContentType,
|
||||
findRecorder,
|
||||
uploadStrapiImage,
|
||||
} from "../../../utils/localApi";
|
||||
import { plainTextToLexical } from "../../../utils/string";
|
||||
|
||||
type StrapiContent = {
|
||||
slug: string;
|
||||
categories: { data?: { attributes: { slug: string } }[] };
|
||||
type: { data?: { attributes: { slug: string } } };
|
||||
thumbnail: StrapiImage;
|
||||
translations: {
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
pre_title?: string;
|
||||
description?: string;
|
||||
language: StrapiLanguage;
|
||||
text_set?: {
|
||||
text: string;
|
||||
notes?: string;
|
||||
source_language: StrapiLanguage;
|
||||
transcribers: StrapiRecorders;
|
||||
translators: StrapiRecorders;
|
||||
proofreaders: StrapiRecorders;
|
||||
};
|
||||
}[];
|
||||
};
|
||||
|
||||
export const importFromStrapi = createStrapiImportEndpoint<StrapiContent>({
|
||||
strapi: {
|
||||
collection: "contents",
|
||||
params: {
|
||||
populate: [
|
||||
"type",
|
||||
"categories",
|
||||
"thumbnail",
|
||||
"translations",
|
||||
"translations.language",
|
||||
"translations.text_set",
|
||||
"translations.text_set.source_language",
|
||||
"translations.text_set.transcribers",
|
||||
"translations.text_set.translators",
|
||||
"translations.text_set.proofreaders",
|
||||
],
|
||||
},
|
||||
},
|
||||
payload: {
|
||||
collection: Collections.Contents,
|
||||
convert: async ({ slug, categories, type, thumbnail, translations }) => {
|
||||
const thumbnailId = await uploadStrapiImage({
|
||||
collection: Collections.ContentsThumbnails,
|
||||
image: thumbnail,
|
||||
});
|
||||
|
||||
const handleTranslation = async ({
|
||||
language,
|
||||
title,
|
||||
description,
|
||||
pre_title,
|
||||
subtitle,
|
||||
text_set,
|
||||
}: StrapiContent["translations"][number]) => {
|
||||
if (isUndefined(language.data))
|
||||
throw new Error("A language is required for a content translation");
|
||||
if (isUndefined(text_set)) throw new Error("Only content with text_set are supported");
|
||||
if (isUndefined(text_set.source_language.data))
|
||||
throw new Error("A language is required for a content translation text_set");
|
||||
return {
|
||||
language: language.data.attributes.code,
|
||||
sourceLanguage: text_set.source_language.data.attributes.code,
|
||||
title,
|
||||
pretitle: pre_title,
|
||||
subtitle,
|
||||
summary: isNotEmpty(description) ? plainTextToLexical(description) : undefined,
|
||||
textContent: plainTextToLexical(text_set.text),
|
||||
textNotes: isNotEmpty(text_set.notes) ? plainTextToLexical(text_set.notes) : undefined,
|
||||
textTranscribers:
|
||||
text_set.transcribers.data &&
|
||||
(await Promise.all(
|
||||
text_set.transcribers.data?.map(async (recorder) =>
|
||||
findRecorder(recorder.attributes.username)
|
||||
)
|
||||
)),
|
||||
textTranslators:
|
||||
text_set.translators.data &&
|
||||
(await Promise.all(
|
||||
text_set.translators.data?.map(async (recorder) =>
|
||||
findRecorder(recorder.attributes.username)
|
||||
)
|
||||
)),
|
||||
textProofreaders:
|
||||
text_set.proofreaders.data &&
|
||||
(await Promise.all(
|
||||
text_set.proofreaders.data?.map(async (recorder) =>
|
||||
findRecorder(recorder.attributes.username)
|
||||
)
|
||||
)),
|
||||
};
|
||||
};
|
||||
|
||||
const data: MarkOptional<Content, "createdAt" | "id" | "updatedAt" | "updatedBy"> = {
|
||||
slug,
|
||||
categories:
|
||||
categories.data &&
|
||||
(await Promise.all(
|
||||
categories.data.map(async (category) => await findCategory(category.attributes.slug))
|
||||
)),
|
||||
type: type.data && (await findContentType(type.data?.attributes.slug)),
|
||||
thumbnail: thumbnailId,
|
||||
translations: await Promise.all(translations.map(handleTranslation)),
|
||||
};
|
||||
return data;
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,38 +0,0 @@
|
|||
import payload from "payload";
|
||||
import { Collections } from "../../../constants";
|
||||
import { createStrapiImportEndpoint } from "../../../endpoints/createStrapiImportEndpoint";
|
||||
import { findContent } from "../../../utils/localApi";
|
||||
|
||||
type StrapiContent = {
|
||||
slug: string;
|
||||
next_contents: { data: { attributes: { slug: string } }[] };
|
||||
};
|
||||
|
||||
export const importRelationsFromStrapi = createStrapiImportEndpoint<StrapiContent>({
|
||||
strapi: {
|
||||
collection: "contents",
|
||||
params: {
|
||||
populate: ["next_contents"],
|
||||
},
|
||||
},
|
||||
payload: {
|
||||
path: "/strapi/related-content",
|
||||
collection: Collections.Contents,
|
||||
import: async ({ slug, next_contents }, user) => {
|
||||
if (next_contents.data.length === 0) return;
|
||||
const currentContent = await findContent(slug);
|
||||
const nextContents: string[] = [];
|
||||
for (const nextContent of next_contents.data) {
|
||||
const result = await findContent(nextContent.attributes.slug);
|
||||
nextContents.push(result);
|
||||
}
|
||||
|
||||
payload.update({
|
||||
collection: Collections.Contents,
|
||||
id: currentContent,
|
||||
data: { nextContents },
|
||||
user,
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,50 +0,0 @@
|
|||
import { Collections } from "../../constants";
|
||||
import { backPropagationField } from "../../fields/backPropagationField/backPropagationField";
|
||||
import { buildImageCollectionConfig } from "../../utils/imageCollectionConfig";
|
||||
|
||||
const fields = {
|
||||
filename: "filename",
|
||||
mimeType: "mimeType",
|
||||
filesize: "filesize",
|
||||
contents: "contents",
|
||||
updatedAt: "updatedAt",
|
||||
} as const satisfies Record<string, string>;
|
||||
|
||||
export const ContentsThumbnails = buildImageCollectionConfig({
|
||||
slug: Collections.ContentsThumbnails,
|
||||
labels: {
|
||||
singular: "Contents Thumbnail",
|
||||
plural: "Contents Thumbnails",
|
||||
},
|
||||
admin: { defaultColumns: [fields.filename, fields.contents, fields.updatedAt] },
|
||||
upload: {
|
||||
imageSizes: [
|
||||
{
|
||||
name: "og",
|
||||
height: 750,
|
||||
width: 1125,
|
||||
formatOptions: {
|
||||
format: "jpg",
|
||||
options: { progressive: true, mozjpeg: true, compressionLevel: 9, quality: 80 },
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "medium",
|
||||
height: 1000,
|
||||
width: 1500,
|
||||
formatOptions: {
|
||||
format: "webp",
|
||||
options: { effort: 6, quality: 80, alphaQuality: 80 },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
fields: [
|
||||
backPropagationField({
|
||||
name: fields.contents,
|
||||
hasMany: true,
|
||||
relationTo: Collections.Contents,
|
||||
where: ({ id }) => ({ thumbnail: { equals: id } }),
|
||||
}),
|
||||
],
|
||||
});
|
|
@ -73,7 +73,7 @@ export const Folders = buildCollectionConfig({
|
|||
],
|
||||
}),
|
||||
{
|
||||
name: fields.sectionsSubfolders,
|
||||
name: fields.sectionsSubfolders,
|
||||
type: "relationship",
|
||||
relationTo: Collections.Folders,
|
||||
hasMany: true,
|
||||
|
@ -83,7 +83,7 @@ export const Folders = buildCollectionConfig({
|
|||
{
|
||||
type: "relationship",
|
||||
name: fields.files,
|
||||
relationTo: [Collections.LibraryItems, Collections.Contents, Collections.Pages],
|
||||
relationTo: [Collections.LibraryItems, Collections.Pages],
|
||||
hasMany: true,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
LibraryItemsTextualBindingTypes,
|
||||
LibraryItemsTextualPageOrders,
|
||||
LibraryItemsTypes,
|
||||
PageType,
|
||||
} from "../../constants";
|
||||
import { backPropagationField } from "../../fields/backPropagationField/backPropagationField";
|
||||
import { componentField } from "../../fields/componentField/componentField";
|
||||
|
@ -734,8 +735,12 @@ export const LibraryItems = buildVersionedCollectionConfig({
|
|||
{
|
||||
name: fields.contentsContent,
|
||||
type: "relationship",
|
||||
relationTo: Collections.Contents,
|
||||
relationTo: Collections.Pages,
|
||||
admin: {
|
||||
allowCreate: false,
|
||||
},
|
||||
required: true,
|
||||
filterOptions: { type: { equals: PageType.Content } },
|
||||
},
|
||||
{
|
||||
type: "row",
|
||||
|
|
|
@ -56,7 +56,7 @@ export const Pages = buildVersionedCollectionConfig({
|
|||
BeforeListTable: [
|
||||
() =>
|
||||
QuickFilters({
|
||||
slug: Collections.Posts,
|
||||
slug: Collections.Pages,
|
||||
filterGroups: [publishStatusFilters],
|
||||
}),
|
||||
],
|
||||
|
|
|
@ -1,173 +0,0 @@
|
|||
import { sectionBlock } from "../../blocks/sectionBlock";
|
||||
import { transcriptBlock } from "../../blocks/transcriptBlock";
|
||||
import { QuickFilters, publishStatusFilters } from "../../components/QuickFilters";
|
||||
import { CollectionGroups, Collections, KeysTypes } from "../../constants";
|
||||
import { imageField } from "../../fields/imageField/imageField";
|
||||
import { keysField } from "../../fields/keysField/keysField";
|
||||
import { rowField } from "../../fields/rowField/rowField";
|
||||
import { slugField } from "../../fields/slugField/slugField";
|
||||
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 { importFromStrapi } from "./endpoints/importFromStrapi";
|
||||
|
||||
const fields = {
|
||||
slug: "slug",
|
||||
hidden: "hidden",
|
||||
thumbnail: "thumbnail",
|
||||
categories: "categories",
|
||||
authors: "authors",
|
||||
publishedDate: "publishedDate",
|
||||
translations: "translations",
|
||||
sourceLanguage: "sourceLanguage",
|
||||
title: "title",
|
||||
summary: "summary",
|
||||
content: "content",
|
||||
translators: "translators",
|
||||
proofreaders: "proofreaders",
|
||||
} as const satisfies Record<string, string>;
|
||||
|
||||
export const Posts = buildVersionedCollectionConfig({
|
||||
slug: Collections.Posts,
|
||||
labels: {
|
||||
singular: "Post",
|
||||
plural: "Posts",
|
||||
},
|
||||
defaultSort: fields.slug,
|
||||
admin: {
|
||||
useAsTitle: fields.slug,
|
||||
description:
|
||||
"News articles written by our Recorders! Here you will find announcements about \
|
||||
new merch/items releases, guides, theories, unboxings, showcases...",
|
||||
defaultColumns: [fields.thumbnail, fields.slug, fields.categories],
|
||||
group: CollectionGroups.Collections,
|
||||
components: {
|
||||
BeforeListTable: [
|
||||
() =>
|
||||
QuickFilters({
|
||||
slug: Collections.Posts,
|
||||
filterGroups: [publishStatusFilters],
|
||||
}),
|
||||
],
|
||||
},
|
||||
hooks: {
|
||||
beforeDuplicate: beforeDuplicatePiping([
|
||||
beforeDuplicateUnpublish,
|
||||
beforeDuplicateAddCopyTo(fields.slug),
|
||||
]),
|
||||
},
|
||||
preview: (doc) => `https://accords-library.com/news/${doc.slug}`,
|
||||
},
|
||||
endpoints: [importFromStrapi],
|
||||
fields: [
|
||||
rowField([
|
||||
slugField({ name: fields.slug }),
|
||||
imageField({
|
||||
name: fields.thumbnail,
|
||||
relationTo: Collections.PostsThumbnails,
|
||||
}),
|
||||
]),
|
||||
rowField([
|
||||
{
|
||||
name: fields.authors,
|
||||
type: "relationship",
|
||||
relationTo: Collections.Recorders,
|
||||
required: true,
|
||||
minRows: 1,
|
||||
hasMany: true,
|
||||
},
|
||||
keysField({ name: fields.categories, relationTo: KeysTypes.Categories, hasMany: true }),
|
||||
]),
|
||||
translatedFields({
|
||||
name: fields.translations,
|
||||
admin: { useAsTitle: fields.title, hasSourceLanguage: true },
|
||||
required: true,
|
||||
minRows: 1,
|
||||
fields: [
|
||||
{ name: fields.title, type: "text", required: true },
|
||||
{
|
||||
name: fields.summary,
|
||||
type: "richText",
|
||||
editor: createEditor({ inlines: true, lists: true, links: true }),
|
||||
},
|
||||
{
|
||||
name: fields.content,
|
||||
type: "richText",
|
||||
editor: createEditor({
|
||||
images: true,
|
||||
inlines: true,
|
||||
alignment: true,
|
||||
blocks: [sectionBlock, transcriptBlock],
|
||||
links: true,
|
||||
lists: true,
|
||||
}),
|
||||
},
|
||||
rowField([
|
||||
{
|
||||
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,
|
||||
},
|
||||
]),
|
||||
],
|
||||
}),
|
||||
{
|
||||
name: fields.publishedDate,
|
||||
type: "date",
|
||||
defaultValue: new Date().toISOString(),
|
||||
admin: {
|
||||
date: { pickerAppearance: "dayOnly", displayFormat: "yyyy-MM-dd" },
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: fields.hidden,
|
||||
type: "checkbox",
|
||||
required: false,
|
||||
defaultValue: false,
|
||||
admin: {
|
||||
description: "If enabled, the post won't appear in the 'News' section",
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
|
@ -1,115 +0,0 @@
|
|||
import { DateTime } from "luxon";
|
||||
import type { MarkOptional } from "ts-essentials";
|
||||
import { Collections } from "../../../constants";
|
||||
import { createStrapiImportEndpoint } from "../../../endpoints/createStrapiImportEndpoint";
|
||||
import type { Post } from "../../../types/collections";
|
||||
import { StrapiImage, StrapiLanguage, StrapiRecorders } from "../../../types/strapi";
|
||||
import { isDefined, isUndefined } from "../../../utils/asserts";
|
||||
import { findCategory, findRecorder, uploadStrapiImage } from "../../../utils/localApi";
|
||||
import { plainTextToLexical } from "../../../utils/string";
|
||||
|
||||
type StrapiPost = {
|
||||
slug: string;
|
||||
categories: { data: { attributes: { slug: string } }[] };
|
||||
authors: StrapiRecorders;
|
||||
hidden: boolean;
|
||||
thumbnail: StrapiImage;
|
||||
translations: {
|
||||
title: string;
|
||||
excerpt?: string;
|
||||
body: string;
|
||||
translators: StrapiRecorders;
|
||||
proofreaders: StrapiRecorders;
|
||||
language: StrapiLanguage;
|
||||
source_language: StrapiLanguage;
|
||||
}[];
|
||||
date: {
|
||||
day: number;
|
||||
month: number;
|
||||
year: number;
|
||||
};
|
||||
};
|
||||
|
||||
export const importFromStrapi = createStrapiImportEndpoint<StrapiPost>({
|
||||
strapi: {
|
||||
collection: "posts",
|
||||
params: {
|
||||
populate: [
|
||||
"date",
|
||||
"authors",
|
||||
"thumbnail",
|
||||
"categories",
|
||||
"translations",
|
||||
"translations.language",
|
||||
"translations.translators",
|
||||
"translations.proofreaders",
|
||||
"translations.source_language",
|
||||
],
|
||||
},
|
||||
},
|
||||
payload: {
|
||||
collection: Collections.Posts,
|
||||
convert: async ({
|
||||
slug,
|
||||
date: { day, month, year },
|
||||
hidden,
|
||||
authors,
|
||||
thumbnail,
|
||||
categories,
|
||||
translations,
|
||||
}) => {
|
||||
const thumbnailId = await uploadStrapiImage({
|
||||
collection: Collections.PostsThumbnails,
|
||||
image: thumbnail,
|
||||
});
|
||||
|
||||
const handleTranslation = async ({
|
||||
language,
|
||||
title,
|
||||
body,
|
||||
excerpt,
|
||||
proofreaders,
|
||||
source_language,
|
||||
translators,
|
||||
}: StrapiPost["translations"][number]): Promise<Post["translations"][number]> => {
|
||||
if (isUndefined(language.data))
|
||||
throw new Error("A language is required for a post translation");
|
||||
if (isUndefined(source_language.data))
|
||||
throw new Error("A source_language is required for a post translation");
|
||||
return {
|
||||
language: language.data.attributes.code,
|
||||
sourceLanguage: source_language.data.attributes.code,
|
||||
title,
|
||||
content: plainTextToLexical(body),
|
||||
summary: isDefined(excerpt) ? plainTextToLexical(excerpt) : undefined,
|
||||
translators:
|
||||
translators.data &&
|
||||
(await Promise.all(
|
||||
translators.data?.map(async (recorder) => findRecorder(recorder.attributes.username))
|
||||
)),
|
||||
proofreaders:
|
||||
proofreaders.data &&
|
||||
(await Promise.all(
|
||||
proofreaders.data?.map(async (recorder) => findRecorder(recorder.attributes.username))
|
||||
)),
|
||||
};
|
||||
};
|
||||
|
||||
const data: MarkOptional<Post, "createdAt" | "id" | "updatedAt" | "updatedBy"> = {
|
||||
slug,
|
||||
publishedDate:
|
||||
DateTime.fromObject({ day, month, year }).toISO() ?? new Date().toISOString(),
|
||||
categories: await Promise.all(
|
||||
categories.data.map((category) => findCategory(category.attributes.slug))
|
||||
),
|
||||
translations: await Promise.all(translations.map(handleTranslation)),
|
||||
authors: await Promise.all(
|
||||
authors.data?.map((author) => findRecorder(author.attributes.username)) ?? []
|
||||
),
|
||||
thumbnail: thumbnailId,
|
||||
hidden,
|
||||
};
|
||||
return data;
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,50 +0,0 @@
|
|||
import { Collections } from "../../constants";
|
||||
import { backPropagationField } from "../../fields/backPropagationField/backPropagationField";
|
||||
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 PostsThumbnails = buildImageCollectionConfig({
|
||||
slug: Collections.PostsThumbnails,
|
||||
labels: {
|
||||
singular: "Post Thumbnail",
|
||||
plural: "Post Thumbnails",
|
||||
},
|
||||
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: 80 },
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "medium",
|
||||
height: 1000,
|
||||
width: 1500,
|
||||
formatOptions: {
|
||||
format: "webp",
|
||||
options: { effort: 6, quality: 80, alphaQuality: 80 },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
fields: [
|
||||
backPropagationField({
|
||||
name: fields.posts,
|
||||
hasMany: true,
|
||||
relationTo: Collections.Posts,
|
||||
where: ({ id }) => ({ thumbnail: { equals: id } }),
|
||||
}),
|
||||
],
|
||||
});
|
|
@ -5,8 +5,6 @@ import type { CueBlock, LineBlock, SectionBlock, TranscriptBlock } from "./types
|
|||
export enum Collections {
|
||||
ChronologyEras = "chronology-eras",
|
||||
ChronologyItems = "chronology-items",
|
||||
Contents = "contents",
|
||||
ContentsThumbnails = "contents-thumbnails",
|
||||
Currencies = "currencies",
|
||||
Files = "files",
|
||||
Keys = "keys",
|
||||
|
@ -16,10 +14,8 @@ export enum Collections {
|
|||
LibraryItemsScans = "library-items-scans",
|
||||
LibraryItemsGallery = "library-items-gallery",
|
||||
Notes = "notes",
|
||||
Posts = "posts",
|
||||
Pages = "pages",
|
||||
PagesThumbnails = "pages-thumbnails",
|
||||
PostsThumbnails = "posts-thumbnails",
|
||||
Recorders = "recorders",
|
||||
RecordersThumbnails = "recorders-thumbnails",
|
||||
VideosChannels = "videos-channels",
|
||||
|
|
|
@ -4,8 +4,6 @@ import path from "path";
|
|||
import { buildConfig } from "payload/config";
|
||||
import { ChronologyEras } from "./collections/ChronologyEras/ChronologyEras";
|
||||
import { ChronologyItems } from "./collections/ChronologyItems/ChronologyItems";
|
||||
import { Contents } from "./collections/Contents/Contents";
|
||||
import { ContentsThumbnails } from "./collections/ContentsThumbnails/ContentsThumbnails";
|
||||
import { Currencies } from "./collections/Currencies/Currencies";
|
||||
import { Files } from "./collections/Files/Files";
|
||||
import { Folders } from "./collections/Folders/Folders";
|
||||
|
@ -19,8 +17,6 @@ import { LibraryItemsScans } from "./collections/LibraryItemsScans/LibraryItemsS
|
|||
import { LibraryItemsThumbnails } from "./collections/LibraryItemsThumbnails/LibraryItemsThumbnails";
|
||||
import { Notes } from "./collections/Notes/Notes";
|
||||
import { Pages } from "./collections/Pages/Pages";
|
||||
import { Posts } from "./collections/Posts/Posts";
|
||||
import { PostsThumbnails } from "./collections/PostsThumbnails/PostsThumbnails";
|
||||
import { Recorders } from "./collections/Recorders/Recorders";
|
||||
import { RecordersThumbnails } from "./collections/RecordersThumbnails/RecordersThumbnails";
|
||||
import { Tags } from "./collections/Tags/Tags";
|
||||
|
@ -53,20 +49,16 @@ export default buildConfig({
|
|||
Folders,
|
||||
FoldersThumbnails,
|
||||
LibraryItems,
|
||||
Contents,
|
||||
Posts,
|
||||
Pages,
|
||||
ChronologyItems,
|
||||
ChronologyEras,
|
||||
Weapons,
|
||||
WeaponsGroups,
|
||||
WeaponsThumbnails,
|
||||
ContentsThumbnails,
|
||||
LibraryItemsThumbnails,
|
||||
LibraryItemsScans,
|
||||
LibraryItemsGallery,
|
||||
RecordersThumbnails,
|
||||
PostsThumbnails,
|
||||
Files,
|
||||
Notes,
|
||||
Videos,
|
||||
|
|
|
@ -33,26 +33,6 @@ export const findRecorder = async (name: string): Promise<string> => {
|
|||
return recorder.docs[0].id;
|
||||
};
|
||||
|
||||
export const findContentType = async (name: string): Promise<string> => {
|
||||
const key = await payload.find({
|
||||
collection: Collections.Keys,
|
||||
where: { name: { equals: name }, type: { equals: KeysTypes.Contents } },
|
||||
depth: 0,
|
||||
});
|
||||
if (!key.docs[0]) throw new Error(`Content type ${name} wasn't found`);
|
||||
return key.docs[0].id;
|
||||
};
|
||||
|
||||
export const findContent = async (slug: string): Promise<string> => {
|
||||
const content = await payload.find({
|
||||
collection: Collections.Contents,
|
||||
where: { slug: { equals: slug } },
|
||||
depth: 0,
|
||||
});
|
||||
if (!content.docs[0]) throw new Error(`Content ${slug} wasn't found`);
|
||||
return content.docs[0].id;
|
||||
};
|
||||
|
||||
type UploadStrapiImage = {
|
||||
image: StrapiImage;
|
||||
collection: Collections;
|
||||
|
|
Loading…
Reference in New Issue