More updates
This commit is contained in:
parent
8d68ff50ce
commit
b436967b3e
|
@ -0,0 +1,65 @@
|
||||||
|
import { CollectionConfig } from "payload/types";
|
||||||
|
import { slugField } from "../../fields/slugField/slugField";
|
||||||
|
import { CollectionGroup, KeysTypes } from "../../constants";
|
||||||
|
import { localizedFields } from "../../fields/translatedFields/translatedFields";
|
||||||
|
import { collectionSlug } from "../../utils/string";
|
||||||
|
import { Contents } from "../Contents/Contents";
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
slug: "slug",
|
||||||
|
translations: "translations",
|
||||||
|
name: "name",
|
||||||
|
subfolders: "subfolders",
|
||||||
|
contents: "contents",
|
||||||
|
} as const satisfies Record<string, string>;
|
||||||
|
|
||||||
|
const labels = {
|
||||||
|
singular: "Content Folder",
|
||||||
|
plural: "Content Folders",
|
||||||
|
} as const satisfies { singular: string; plural: string };
|
||||||
|
|
||||||
|
const slug = collectionSlug(labels.plural);
|
||||||
|
|
||||||
|
export const ContentFolders: CollectionConfig = {
|
||||||
|
slug,
|
||||||
|
labels,
|
||||||
|
typescript: { interface: labels.singular },
|
||||||
|
defaultSort: fields.slug,
|
||||||
|
admin: {
|
||||||
|
useAsTitle: fields.slug,
|
||||||
|
defaultColumns: [fields.slug, fields.translations],
|
||||||
|
group: CollectionGroup.Collections,
|
||||||
|
},
|
||||||
|
timestamps: false,
|
||||||
|
versions: false,
|
||||||
|
fields: [
|
||||||
|
slugField({ name: fields.slug }),
|
||||||
|
localizedFields({
|
||||||
|
name: fields.translations,
|
||||||
|
interfaceName: "ContentFoldersTranslation",
|
||||||
|
admin: {
|
||||||
|
useAsTitle: fields.name,
|
||||||
|
},
|
||||||
|
fields: [{ name: fields.name, type: "text", required: true }],
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
type: "row",
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: "relationship",
|
||||||
|
name: fields.subfolders,
|
||||||
|
relationTo: [slug],
|
||||||
|
hasMany: true,
|
||||||
|
admin: { width: "50%" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "relationship",
|
||||||
|
name: fields.contents,
|
||||||
|
relationTo: [Contents.slug],
|
||||||
|
hasMany: true,
|
||||||
|
admin: { width: "50%" },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
|
@ -0,0 +1,52 @@
|
||||||
|
import { CollectionConfig } from "payload/types";
|
||||||
|
import { CollectionGroup } from "../../constants";
|
||||||
|
import { collectionSlug } from "../../utils/string";
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
filename: "filename",
|
||||||
|
mimeType: "mimeType",
|
||||||
|
filesize: "filesize",
|
||||||
|
} as const satisfies Record<string, string>;
|
||||||
|
|
||||||
|
const labels = {
|
||||||
|
singular: "Content Thumbnail",
|
||||||
|
plural: "Content Thumbnails",
|
||||||
|
} as const satisfies { singular: string; plural: string };
|
||||||
|
|
||||||
|
export const ContentThumbnails: CollectionConfig = {
|
||||||
|
slug: collectionSlug(labels.plural),
|
||||||
|
labels,
|
||||||
|
typescript: { interface: labels.singular },
|
||||||
|
defaultSort: fields.filename,
|
||||||
|
admin: {
|
||||||
|
useAsTitle: fields.filename,
|
||||||
|
group: CollectionGroup.Media,
|
||||||
|
},
|
||||||
|
|
||||||
|
upload: {
|
||||||
|
staticDir: `../uploads/${labels.plural}`,
|
||||||
|
mimeTypes: ["image/*"],
|
||||||
|
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: [],
|
||||||
|
};
|
|
@ -1,169 +1,93 @@
|
||||||
import { Block, BlockField } from "payload/types";
|
|
||||||
import { cueBlock } from "./cueBlock";
|
import { cueBlock } from "./cueBlock";
|
||||||
import { textBlock } from "./textBlock";
|
import { textBlock } from "./textBlock";
|
||||||
import { transcriptBlock } from "./transcriptBlock";
|
import { transcriptBlock } from "./transcriptBlock";
|
||||||
import { lineBlock } from "./lineBlock";
|
import { lineBlock } from "./lineBlock";
|
||||||
|
import { quoteBlock } from "./quoteBlock";
|
||||||
|
import { BlocksConfig, generateBlocks } from "../../../utils/recursiveBlocks";
|
||||||
|
|
||||||
const INITIAL_DEPTH = 1;
|
const enum BlockName {
|
||||||
const MAX_DEPTH = 4;
|
|
||||||
|
|
||||||
enum BlockName {
|
|
||||||
Text = "Text",
|
Text = "Text",
|
||||||
Section = "Section",
|
Section = "Section",
|
||||||
Tabs = "Tabs",
|
Tabs = "Tabs",
|
||||||
Tab = "Tab",
|
Tab = "Tab",
|
||||||
Columns = "Columns",
|
|
||||||
Column = "Column",
|
|
||||||
Transcript = "Transcript",
|
Transcript = "Transcript",
|
||||||
Collapsible = "Collapsible",
|
|
||||||
Accordion = "Accordion",
|
|
||||||
Line = "Line",
|
Line = "Line",
|
||||||
Cue = "Cue",
|
Cue = "Cue",
|
||||||
|
Quote = "Quote",
|
||||||
}
|
}
|
||||||
|
|
||||||
const rootBlocksNames: BlockName[] = [
|
const blocksConfig: BlocksConfig<BlockName> = {
|
||||||
BlockName.Section,
|
Text: {
|
||||||
BlockName.Collapsible,
|
root: true,
|
||||||
BlockName.Columns,
|
block: textBlock,
|
||||||
BlockName.Tabs,
|
},
|
||||||
BlockName.Accordion,
|
Section: {
|
||||||
BlockName.Text,
|
root: true,
|
||||||
BlockName.Transcript,
|
block: {
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
const recursiveBlocks: BlockName[] = [
|
|
||||||
BlockName.Section,
|
|
||||||
BlockName.Collapsible,
|
|
||||||
BlockName.Accordion,
|
|
||||||
BlockName.Tabs,
|
|
||||||
BlockName.Tab,
|
|
||||||
BlockName.Column,
|
|
||||||
BlockName.Columns,
|
|
||||||
];
|
|
||||||
|
|
||||||
const blocksChildren: Record<BlockName, BlockName[]> = {
|
|
||||||
Tabs: [BlockName.Tab],
|
|
||||||
Columns: [BlockName.Column],
|
|
||||||
Section: rootBlocksNames,
|
|
||||||
Collapsible: rootBlocksNames,
|
|
||||||
Tab: rootBlocksNames,
|
|
||||||
Column: rootBlocksNames,
|
|
||||||
Accordion: [BlockName.Collapsible],
|
|
||||||
Text: [],
|
|
||||||
Transcript: [BlockName.Line, BlockName.Cue],
|
|
||||||
Cue: [],
|
|
||||||
Line: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
export type RecursiveBlock = Omit<Block, "fields"> & {
|
|
||||||
fields: Omit<BlockField, "blocks" | "type"> & {
|
|
||||||
newDepth: (currentDepth: number) => number;
|
|
||||||
blocks: BlockName[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: Check for loops in the block graph instead of manually defining recursive blocks
|
|
||||||
const isNotRecursiveBlock = (name: BlockName): boolean => !recursiveBlocks.includes(name);
|
|
||||||
|
|
||||||
const implementationForRecursiveBlocks = (
|
|
||||||
currentDepth: number,
|
|
||||||
{ slug, interfaceName, labels, fields: { newDepth, blocks, ...fieldsProps } }: RecursiveBlock
|
|
||||||
): Block => ({
|
|
||||||
slug: [slug, currentDepth].join("_"),
|
|
||||||
interfaceName: [interfaceName, currentDepth].join("_"),
|
|
||||||
labels,
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
...fieldsProps,
|
|
||||||
type: "blocks",
|
|
||||||
blocks: blocks
|
|
||||||
.filter((block) => {
|
|
||||||
if (currentDepth < MAX_DEPTH) return true;
|
|
||||||
if (blocks.filter(isNotRecursiveBlock).length === 0) return true;
|
|
||||||
return isNotRecursiveBlock(block);
|
|
||||||
})
|
|
||||||
.map((block) => implementations[block](newDepth(currentDepth))),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const implementations: Record<BlockName, (currentDepth: number) => Block> = {
|
|
||||||
Cue: () => cueBlock,
|
|
||||||
Text: () => textBlock,
|
|
||||||
Transcript: () => transcriptBlock,
|
|
||||||
Line: () => lineBlock,
|
|
||||||
Section: (currentDepth) =>
|
|
||||||
implementationForRecursiveBlocks(currentDepth, {
|
|
||||||
slug: "section",
|
slug: "section",
|
||||||
interfaceName: "Section",
|
|
||||||
labels: { singular: "Section", plural: "Sections" },
|
labels: { singular: "Section", plural: "Sections" },
|
||||||
fields: {
|
recursion: {
|
||||||
name: "content",
|
name: "content",
|
||||||
|
condition: (depth) => depth < 5,
|
||||||
newDepth: (depth) => depth + 1,
|
newDepth: (depth) => depth + 1,
|
||||||
blocks: blocksChildren.Section,
|
blocks: [
|
||||||
|
BlockName.Section,
|
||||||
|
BlockName.Tabs,
|
||||||
|
BlockName.Transcript,
|
||||||
|
BlockName.Quote,
|
||||||
|
BlockName.Text,
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
Accordion: (currentDepth) =>
|
},
|
||||||
implementationForRecursiveBlocks(currentDepth, {
|
Tabs: {
|
||||||
slug: "accordion",
|
root: true,
|
||||||
interfaceName: "Accordion",
|
block: {
|
||||||
labels: { singular: "Accordion", plural: "Accordions" },
|
|
||||||
fields: {
|
|
||||||
name: "content",
|
|
||||||
newDepth: (depth) => depth + 1,
|
|
||||||
blocks: blocksChildren.Accordion,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
Collapsible: (currentDepth) =>
|
|
||||||
implementationForRecursiveBlocks(currentDepth, {
|
|
||||||
slug: "collapsible",
|
|
||||||
interfaceName: "Collapsible",
|
|
||||||
labels: { singular: "Collapsible", plural: "Collapsibles" },
|
|
||||||
fields: {
|
|
||||||
name: "content",
|
|
||||||
newDepth: (depth) => depth + 1,
|
|
||||||
blocks: blocksChildren.Collapsible,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
Tabs: (currentDepth) =>
|
|
||||||
implementationForRecursiveBlocks(currentDepth, {
|
|
||||||
slug: "tabs",
|
slug: "tabs",
|
||||||
interfaceName: "Tabs",
|
|
||||||
labels: { singular: "Tabs", plural: "Tabs" },
|
labels: { singular: "Tabs", plural: "Tabs" },
|
||||||
fields: { name: "tabs", newDepth: (depth) => depth, blocks: blocksChildren.Tabs },
|
recursion: {
|
||||||
}),
|
name: "tabs",
|
||||||
Tab: (currentDepth) =>
|
|
||||||
implementationForRecursiveBlocks(currentDepth, {
|
|
||||||
slug: "tab",
|
|
||||||
interfaceName: "Tab",
|
|
||||||
labels: { singular: "Tab", plural: "Tabs" },
|
|
||||||
fields: {
|
|
||||||
name: "content",
|
|
||||||
newDepth: (depth) => depth + 1,
|
|
||||||
blocks: blocksChildren.Tab,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
Columns: (currentDepth) =>
|
|
||||||
implementationForRecursiveBlocks(currentDepth, {
|
|
||||||
slug: "columns",
|
|
||||||
interfaceName: "Columns",
|
|
||||||
labels: { singular: "Columns", plural: "Columns" },
|
|
||||||
fields: {
|
|
||||||
name: "columns",
|
|
||||||
newDepth: (depth) => depth,
|
newDepth: (depth) => depth,
|
||||||
blocks: blocksChildren.Columns,
|
condition: (depth, parents) => !parents.includes(BlockName.Tabs) && depth < 5,
|
||||||
|
blocks: [BlockName.Tab],
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
Column: (currentDepth) =>
|
},
|
||||||
implementationForRecursiveBlocks(currentDepth, {
|
Tab: {
|
||||||
slug: "column",
|
root: false,
|
||||||
interfaceName: "Column",
|
block: {
|
||||||
labels: { singular: "Column", plural: "Columns" },
|
slug: "tab",
|
||||||
fields: { name: "content", newDepth: (depth) => depth + 1, blocks: blocksChildren.Column },
|
labels: { singular: "Tab", plural: "Tabs" },
|
||||||
}),
|
recursion: {
|
||||||
|
name: "content",
|
||||||
|
condition: (depth) => depth < 5,
|
||||||
|
newDepth: (depth) => depth + 1,
|
||||||
|
blocks: [
|
||||||
|
BlockName.Section,
|
||||||
|
BlockName.Tabs,
|
||||||
|
BlockName.Transcript,
|
||||||
|
BlockName.Quote,
|
||||||
|
BlockName.Text,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Transcript: {
|
||||||
|
root: true,
|
||||||
|
block: transcriptBlock,
|
||||||
|
},
|
||||||
|
Cue: {
|
||||||
|
root: false,
|
||||||
|
block: cueBlock,
|
||||||
|
},
|
||||||
|
Line: {
|
||||||
|
root: false,
|
||||||
|
block: lineBlock,
|
||||||
|
},
|
||||||
|
Quote: {
|
||||||
|
root: true,
|
||||||
|
block: quoteBlock,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const rootBlocks: Block[] = rootBlocksNames
|
export const contentBlocks = generateBlocks(blocksConfig);
|
||||||
.filter((block) => block in implementations)
|
|
||||||
.map((block) => implementations[block](INITIAL_DEPTH));
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { Block } from "payload/types";
|
||||||
|
|
||||||
|
export const quoteBlock: Block = {
|
||||||
|
slug: "quoteBlock",
|
||||||
|
interfaceName: "QuoteBlock",
|
||||||
|
labels: { singular: "Quote", plural: "Quotes" },
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "from",
|
||||||
|
type: "text",
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "content",
|
||||||
|
type: "richText",
|
||||||
|
label: false,
|
||||||
|
required: true,
|
||||||
|
admin: {
|
||||||
|
hideGutter: true,
|
||||||
|
elements: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
|
@ -1,14 +1,15 @@
|
||||||
import { CollectionConfig } from "payload/types";
|
import { CollectionConfig } from "payload/types";
|
||||||
import { collectionSlug } from "../../utils/string";
|
import { collectionSlug } from "../../utils/string";
|
||||||
import { CollectionGroup, FileTypes, TagsTypes } from "../../constants";
|
import { CollectionGroup, FileTypes, KeysTypes } from "../../constants";
|
||||||
import { slugField } from "../../fields/slugField/slugField";
|
import { slugField } from "../../fields/slugField/slugField";
|
||||||
import { imageField } from "../../fields/imageField/imageField";
|
import { imageField } from "../../fields/imageField/imageField";
|
||||||
import { Tags } from "../Tags/Tags";
|
import { Keys } from "../Keys/Keys";
|
||||||
import { localizedFields } from "../../fields/translatedFields/translatedFields";
|
import { localizedFields } from "../../fields/translatedFields/translatedFields";
|
||||||
import { Recorders } from "../Recorders/Recorders";
|
import { Recorders } from "../Recorders/Recorders";
|
||||||
import { isDefined } from "../../utils/asserts";
|
import { isDefined } from "../../utils/asserts";
|
||||||
import { fileField } from "../../fields/fileField/fileField";
|
import { fileField } from "../../fields/fileField/fileField";
|
||||||
import { rootBlocks } from "./Blocks/blocks";
|
import { contentBlocks } from "./Blocks/blocks";
|
||||||
|
import { ContentThumbnails } from "../ContentThumbnails/ContentThumbnails";
|
||||||
|
|
||||||
const fields = {
|
const fields = {
|
||||||
slug: "slug",
|
slug: "slug",
|
||||||
|
@ -29,6 +30,7 @@ const fields = {
|
||||||
videoNotes: "videoNotes",
|
videoNotes: "videoNotes",
|
||||||
audio: "audio",
|
audio: "audio",
|
||||||
audioNotes: "videoNotes",
|
audioNotes: "videoNotes",
|
||||||
|
status: "status",
|
||||||
} as const satisfies Record<string, string>;
|
} as const satisfies Record<string, string>;
|
||||||
|
|
||||||
const labels = {
|
const labels = {
|
||||||
|
@ -43,42 +45,47 @@ export const Contents: CollectionConfig = {
|
||||||
defaultSort: fields.slug,
|
defaultSort: fields.slug,
|
||||||
admin: {
|
admin: {
|
||||||
useAsTitle: fields.slug,
|
useAsTitle: fields.slug,
|
||||||
defaultColumns: [fields.slug, fields.thumbnail, fields.categories],
|
defaultColumns: [
|
||||||
|
fields.slug,
|
||||||
|
fields.thumbnail,
|
||||||
|
fields.categories,
|
||||||
|
fields.type,
|
||||||
|
fields.translations,
|
||||||
|
fields.status,
|
||||||
|
],
|
||||||
group: CollectionGroup.Collections,
|
group: CollectionGroup.Collections,
|
||||||
preview: (doc) => `https://accords-library.com/contents/${doc.slug}`,
|
preview: (doc) => `https://accords-library.com/contents/${doc.slug}`,
|
||||||
},
|
},
|
||||||
timestamps: true,
|
timestamps: true,
|
||||||
versions: { drafts: true },
|
versions: { drafts: { autosave: true } },
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
type: "row",
|
type: "row",
|
||||||
fields: [
|
fields: [
|
||||||
slugField({ name: fields.slug, admin: { width: "50%" } }),
|
slugField({ name: fields.slug, admin: { width: "50%" } }),
|
||||||
imageField({ name: fields.thumbnail, admin: { width: "50%" } }),
|
imageField({
|
||||||
|
name: fields.thumbnail,
|
||||||
|
relationTo: ContentThumbnails.slug,
|
||||||
|
admin: { width: "50%" },
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "testing",
|
|
||||||
type: "blocks",
|
|
||||||
admin: { initCollapsed: true },
|
|
||||||
blocks: rootBlocks,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
type: "row",
|
type: "row",
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: fields.categories,
|
name: fields.categories,
|
||||||
type: "relationship",
|
type: "relationship",
|
||||||
relationTo: [Tags.slug],
|
relationTo: [Keys.slug],
|
||||||
filterOptions: { type: { equals: TagsTypes.Categories } },
|
filterOptions: { type: { equals: KeysTypes.Categories } },
|
||||||
hasMany: true,
|
hasMany: true,
|
||||||
admin: { allowCreate: false, width: "50%" },
|
admin: { allowCreate: false, width: "50%" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: fields.type,
|
name: fields.type,
|
||||||
type: "relationship",
|
type: "relationship",
|
||||||
relationTo: [Tags.slug],
|
relationTo: [Keys.slug],
|
||||||
filterOptions: { type: { equals: TagsTypes.Contents } },
|
filterOptions: { type: { equals: KeysTypes.Contents } },
|
||||||
admin: { allowCreate: false, width: "50%" },
|
admin: { allowCreate: false, width: "50%" },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -148,8 +155,10 @@ export const Contents: CollectionConfig = {
|
||||||
{
|
{
|
||||||
name: fields.textContent,
|
name: fields.textContent,
|
||||||
label: "Content",
|
label: "Content",
|
||||||
type: "richText",
|
labels: { singular: "Block", plural: "Blocks" },
|
||||||
admin: { hideGutter: true },
|
type: "blocks",
|
||||||
|
admin: { initCollapsed: true },
|
||||||
|
blocks: contentBlocks,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: fields.textNotes,
|
name: fields.textNotes,
|
||||||
|
|
|
@ -1,22 +1,27 @@
|
||||||
import { CollectionConfig } from "payload/types";
|
import { CollectionConfig } from "payload/types";
|
||||||
import { slugField } from "../../fields/slugField/slugField";
|
import { slugField } from "../../fields/slugField/slugField";
|
||||||
import { CollectionGroup, TagsTypes } from "../../constants";
|
import { CollectionGroup, KeysTypes } from "../../constants";
|
||||||
import { localizedFields } from "../../fields/translatedFields/translatedFields";
|
import { localizedFields } from "../../fields/translatedFields/translatedFields";
|
||||||
import { collectionSlug } from "../../utils/string";
|
import { collectionSlug } from "../../utils/string";
|
||||||
|
import { Key } from "../../types/collections";
|
||||||
|
import { isDefined } from "../../utils/asserts";
|
||||||
|
|
||||||
const fields = {
|
const fields = {
|
||||||
slug: "slug",
|
slug: "slug",
|
||||||
translations: "translations",
|
translations: "translations",
|
||||||
type: "type",
|
type: "type",
|
||||||
name: "name",
|
name: "name",
|
||||||
|
short: "short",
|
||||||
} as const satisfies Record<string, string>;
|
} as const satisfies Record<string, string>;
|
||||||
|
|
||||||
const labels = {
|
const labels = {
|
||||||
singular: "Tag",
|
singular: "Key",
|
||||||
plural: "Tags",
|
plural: "Keys",
|
||||||
} as const satisfies { singular: string; plural: string };
|
} as const satisfies { singular: string; plural: string };
|
||||||
|
|
||||||
export const Tags: CollectionConfig = {
|
const keysTypesWithShort: (keyof typeof KeysTypes)[] = ["Categories", "GamePlatforms"];
|
||||||
|
|
||||||
|
export const Keys: CollectionConfig = {
|
||||||
slug: collectionSlug(labels.plural),
|
slug: collectionSlug(labels.plural),
|
||||||
labels,
|
labels,
|
||||||
typescript: { interface: labels.singular },
|
typescript: { interface: labels.singular },
|
||||||
|
@ -34,7 +39,7 @@ export const Tags: CollectionConfig = {
|
||||||
name: fields.type,
|
name: fields.type,
|
||||||
type: "select",
|
type: "select",
|
||||||
required: true,
|
required: true,
|
||||||
options: Object.entries(TagsTypes).map(([value, label]) => ({ label, value })),
|
options: Object.entries(KeysTypes).map(([value, label]) => ({ label, value })),
|
||||||
},
|
},
|
||||||
localizedFields({
|
localizedFields({
|
||||||
name: fields.translations,
|
name: fields.translations,
|
||||||
|
@ -42,7 +47,23 @@ export const Tags: CollectionConfig = {
|
||||||
admin: {
|
admin: {
|
||||||
useAsTitle: fields.name,
|
useAsTitle: fields.name,
|
||||||
},
|
},
|
||||||
fields: [{ name: fields.name, type: "text", required: true }],
|
fields: [
|
||||||
|
{
|
||||||
|
type: "row",
|
||||||
|
fields: [
|
||||||
|
{ name: fields.name, type: "text", required: true, admin: { width: "50%" } },
|
||||||
|
{
|
||||||
|
name: fields.short,
|
||||||
|
type: "text",
|
||||||
|
admin: {
|
||||||
|
condition: (data: Partial<Key>) =>
|
||||||
|
isDefined(data.type) && keysTypesWithShort.includes(data.type),
|
||||||
|
width: "50%",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
};
|
};
|
|
@ -0,0 +1,64 @@
|
||||||
|
import { CollectionConfig } from "payload/types";
|
||||||
|
import { CollectionGroup } from "../../constants";
|
||||||
|
import { collectionSlug } from "../../utils/string";
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
filename: "filename",
|
||||||
|
mimeType: "mimeType",
|
||||||
|
filesize: "filesize",
|
||||||
|
} as const satisfies Record<string, string>;
|
||||||
|
|
||||||
|
const labels = {
|
||||||
|
singular: "Library Item Thumbnail",
|
||||||
|
plural: "Library Item Thumbnails",
|
||||||
|
} as const satisfies { singular: string; plural: string };
|
||||||
|
|
||||||
|
export const LibraryItemThumbnails: CollectionConfig = {
|
||||||
|
slug: collectionSlug(labels.plural),
|
||||||
|
labels,
|
||||||
|
typescript: { interface: labels.singular },
|
||||||
|
defaultSort: fields.filename,
|
||||||
|
admin: {
|
||||||
|
useAsTitle: fields.filename,
|
||||||
|
group: CollectionGroup.Media,
|
||||||
|
},
|
||||||
|
|
||||||
|
upload: {
|
||||||
|
staticDir: `../uploads/${labels.plural}`,
|
||||||
|
mimeTypes: ["image/*"],
|
||||||
|
imageSizes: [
|
||||||
|
{
|
||||||
|
name: "og",
|
||||||
|
height: 1024,
|
||||||
|
width: 1024,
|
||||||
|
fit: "contain",
|
||||||
|
formatOptions: {
|
||||||
|
format: "jpg",
|
||||||
|
options: { progressive: true, mozjpeg: true, compressionLevel: 9, quality: 80 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "medium",
|
||||||
|
height: 1024,
|
||||||
|
width: 1024,
|
||||||
|
fit: "contain",
|
||||||
|
formatOptions: {
|
||||||
|
format: "webp",
|
||||||
|
options: { effort: 6, quality: 80, alphaQuality: 80 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "large",
|
||||||
|
height: 2048,
|
||||||
|
width: 2048,
|
||||||
|
fit: "contain",
|
||||||
|
formatOptions: {
|
||||||
|
format: "webp",
|
||||||
|
options: { effort: 6, quality: 80, alphaQuality: 80 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
fields: [],
|
||||||
|
};
|
|
@ -1,9 +1,19 @@
|
||||||
import { CollectionConfig } from "payload/types";
|
import { CollectionConfig } from "payload/types";
|
||||||
import { CollectionGroup } from "../../constants";
|
import {
|
||||||
|
CollectionGroup,
|
||||||
|
KeysTypes,
|
||||||
|
LibraryItemsTextualBindingTypes,
|
||||||
|
LibraryItemsTextualPageOrders,
|
||||||
|
LibraryItemsTypes,
|
||||||
|
} from "../../constants";
|
||||||
import { slugField } from "../../fields/slugField/slugField";
|
import { slugField } from "../../fields/slugField/slugField";
|
||||||
import { imageField } from "../../fields/imageField/imageField";
|
import { imageField } from "../../fields/imageField/imageField";
|
||||||
import { collectionSlug } from "../../utils/string";
|
import { collectionSlug } from "../../utils/string";
|
||||||
import { isDefined, isUndefined } from "../../utils/asserts";
|
import { isDefined, isUndefined } from "../../utils/asserts";
|
||||||
|
import { LibraryItemThumbnails } from "../LibraryItemThumbnails/LibraryItemThumbnails";
|
||||||
|
import { LibraryItem } from "../../types/collections";
|
||||||
|
import { Keys } from "../Keys/Keys";
|
||||||
|
import { Languages } from "../Languages";
|
||||||
|
|
||||||
const fields = {
|
const fields = {
|
||||||
status: "status",
|
status: "status",
|
||||||
|
@ -20,6 +30,16 @@ const fields = {
|
||||||
width: "width",
|
width: "width",
|
||||||
height: "height",
|
height: "height",
|
||||||
thickness: "thickness",
|
thickness: "thickness",
|
||||||
|
releaseDate: "releaseDate",
|
||||||
|
itemType: "itemType",
|
||||||
|
textual: "textual",
|
||||||
|
textualSubtype: "subtype",
|
||||||
|
textualBindingType: "bindingType",
|
||||||
|
textualPageCount: "pageCount",
|
||||||
|
textualPageOrder: "pageOrder",
|
||||||
|
textualLanguages: "languages",
|
||||||
|
audio: "audio",
|
||||||
|
audioSubtype: "audioSubtype",
|
||||||
} as const satisfies Record<string, string>;
|
} as const satisfies Record<string, string>;
|
||||||
|
|
||||||
const labels = {
|
const labels = {
|
||||||
|
@ -50,13 +70,17 @@ export const LibraryItems: CollectionConfig = {
|
||||||
preview: (doc) => `https://accords-library.com/library/${doc.slug}`,
|
preview: (doc) => `https://accords-library.com/library/${doc.slug}`,
|
||||||
},
|
},
|
||||||
timestamps: true,
|
timestamps: true,
|
||||||
versions: { drafts: true },
|
versions: { drafts: { autosave: true } },
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
type: "row",
|
type: "row",
|
||||||
fields: [
|
fields: [
|
||||||
slugField({ name: fields.slug, admin: { width: "50%" } }),
|
slugField({ name: fields.slug, admin: { width: "50%" } }),
|
||||||
imageField({ name: fields.thumbnail, admin: { width: "50%" } }),
|
imageField({
|
||||||
|
name: fields.thumbnail,
|
||||||
|
relationTo: LibraryItemThumbnails.slug,
|
||||||
|
admin: { width: "50%" },
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -144,5 +168,106 @@ export const LibraryItems: CollectionConfig = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: fields.itemType,
|
||||||
|
type: "radio",
|
||||||
|
options: Object.entries(LibraryItemsTypes).map(([value, label]) => ({ label, value })),
|
||||||
|
admin: {
|
||||||
|
layout: "horizontal",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: fields.textual,
|
||||||
|
type: "group",
|
||||||
|
admin: {
|
||||||
|
condition: (data: Partial<LibraryItem>) => data.itemType === LibraryItemsTypes.Textual,
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: "row",
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: fields.textualSubtype,
|
||||||
|
label: "Subtype",
|
||||||
|
type: "relationship",
|
||||||
|
relationTo: [Keys.slug],
|
||||||
|
filterOptions: { type: { equals: KeysTypes.LibraryTextual } },
|
||||||
|
hasMany: true,
|
||||||
|
admin: { allowCreate: false, width: "50%" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: fields.textualLanguages,
|
||||||
|
type: "relationship",
|
||||||
|
relationTo: [Languages.slug],
|
||||||
|
hasMany: true,
|
||||||
|
admin: { allowCreate: false, width: "50%" },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "row",
|
||||||
|
fields: [
|
||||||
|
{ name: fields.textualPageCount, type: "number", min: 1, admin: { width: "33%" } },
|
||||||
|
{
|
||||||
|
name: fields.textualBindingType,
|
||||||
|
label: "Binding Type",
|
||||||
|
type: "radio",
|
||||||
|
options: Object.entries(LibraryItemsTextualBindingTypes).map(([value, label]) => ({
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
})),
|
||||||
|
admin: {
|
||||||
|
layout: "horizontal",
|
||||||
|
width: "33%",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: fields.textualPageOrder,
|
||||||
|
label: "Page Order",
|
||||||
|
type: "radio",
|
||||||
|
options: Object.entries(LibraryItemsTextualPageOrders).map(([value, label]) => ({
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
})),
|
||||||
|
admin: {
|
||||||
|
layout: "horizontal",
|
||||||
|
width: "33%",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: fields.audio,
|
||||||
|
type: "group",
|
||||||
|
admin: {
|
||||||
|
condition: (data: Partial<LibraryItem>) => data.itemType === LibraryItemsTypes.Audio,
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: "row",
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: fields.audioSubtype,
|
||||||
|
label: "Subtype",
|
||||||
|
type: "relationship",
|
||||||
|
relationTo: [Keys.slug],
|
||||||
|
filterOptions: { type: { equals: KeysTypes.LibraryAudio } },
|
||||||
|
hasMany: true,
|
||||||
|
admin: { allowCreate: false, width: "50%" },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: fields.releaseDate,
|
||||||
|
type: "date",
|
||||||
|
admin: {
|
||||||
|
date: { pickerAppearance: "dayOnly", displayFormat: "yyyy-MM-dd" },
|
||||||
|
position: "sidebar",
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,15 +6,14 @@ const fields = {
|
||||||
filename: "filename",
|
filename: "filename",
|
||||||
mimeType: "mimeType",
|
mimeType: "mimeType",
|
||||||
filesize: "filesize",
|
filesize: "filesize",
|
||||||
alt: "alt",
|
|
||||||
} as const satisfies Record<string, string>;
|
} as const satisfies Record<string, string>;
|
||||||
|
|
||||||
const labels = {
|
const labels = {
|
||||||
singular: "Image",
|
singular: "Post Thumbnail",
|
||||||
plural: "Images",
|
plural: "Post Thumbnails",
|
||||||
} as const satisfies { singular: string; plural: string };
|
} as const satisfies { singular: string; plural: string };
|
||||||
|
|
||||||
export const Images: CollectionConfig = {
|
export const PostThumbnails: CollectionConfig = {
|
||||||
slug: collectionSlug(labels.plural),
|
slug: collectionSlug(labels.plural),
|
||||||
labels,
|
labels,
|
||||||
typescript: { interface: labels.singular },
|
typescript: { interface: labels.singular },
|
||||||
|
@ -27,13 +26,27 @@ export const Images: CollectionConfig = {
|
||||||
upload: {
|
upload: {
|
||||||
staticDir: `../uploads/${labels.plural}`,
|
staticDir: `../uploads/${labels.plural}`,
|
||||||
mimeTypes: ["image/*"],
|
mimeTypes: ["image/*"],
|
||||||
|
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: [
|
fields: [],
|
||||||
{
|
|
||||||
name: fields.alt,
|
|
||||||
label: "Alt Text",
|
|
||||||
type: "text",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
};
|
|
@ -1,16 +1,18 @@
|
||||||
import { CollectionConfig } from "payload/types";
|
import { CollectionConfig } from "payload/types";
|
||||||
import { slugField } from "../../fields/slugField/slugField";
|
import { slugField } from "../../fields/slugField/slugField";
|
||||||
import { imageField } from "../../fields/imageField/imageField";
|
import { imageField } from "../../fields/imageField/imageField";
|
||||||
import { CollectionGroup, TagsTypes } from "../../constants";
|
import { CollectionGroup, KeysTypes } from "../../constants";
|
||||||
import { Recorders } from "../Recorders/Recorders";
|
import { Recorders } from "../Recorders/Recorders";
|
||||||
import { localizedFields } from "../../fields/translatedFields/translatedFields";
|
import { localizedFields } from "../../fields/translatedFields/translatedFields";
|
||||||
import { isDefined, isUndefined } from "../../utils/asserts";
|
import { isDefined, isUndefined } from "../../utils/asserts";
|
||||||
import { removeTranslatorsForTranscripts } from "./hooks/beforeValidate";
|
import { removeTranslatorsForTranscripts } from "./hooks/beforeValidate";
|
||||||
import { Tags } from "../Tags/Tags";
|
import { Keys } from "../Keys/Keys";
|
||||||
import { collectionSlug } from "../../utils/string";
|
import { collectionSlug } from "../../utils/string";
|
||||||
|
import { PostThumbnails } from "../PostThumbnails/PostThumbnails";
|
||||||
|
|
||||||
const fields = {
|
const fields = {
|
||||||
slug: "slug",
|
slug: "slug",
|
||||||
|
hidden: "hidden",
|
||||||
thumbnail: "thumbnail",
|
thumbnail: "thumbnail",
|
||||||
categories: "categories",
|
categories: "categories",
|
||||||
authors: "authors",
|
authors: "authors",
|
||||||
|
@ -44,13 +46,17 @@ export const Posts: CollectionConfig = {
|
||||||
beforeValidate: [removeTranslatorsForTranscripts],
|
beforeValidate: [removeTranslatorsForTranscripts],
|
||||||
},
|
},
|
||||||
timestamps: true,
|
timestamps: true,
|
||||||
versions: { drafts: true },
|
versions: { drafts: { autosave: true } },
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
type: "row",
|
type: "row",
|
||||||
fields: [
|
fields: [
|
||||||
slugField({ name: fields.slug, admin: { width: "50%" } }),
|
slugField({ name: fields.slug, admin: { width: "50%" } }),
|
||||||
imageField({ name: fields.thumbnail, admin: { width: "50%" } }),
|
imageField({
|
||||||
|
name: fields.thumbnail,
|
||||||
|
relationTo: PostThumbnails.slug,
|
||||||
|
admin: { width: "50%" },
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -63,15 +69,15 @@ export const Posts: CollectionConfig = {
|
||||||
required: true,
|
required: true,
|
||||||
minRows: 1,
|
minRows: 1,
|
||||||
hasMany: true,
|
hasMany: true,
|
||||||
admin: { width: "50%" },
|
admin: { width: "35%" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: fields.categories,
|
name: fields.categories,
|
||||||
type: "relationship",
|
type: "relationship",
|
||||||
relationTo: [Tags.slug],
|
relationTo: [Keys.slug],
|
||||||
filterOptions: { type: { equals: TagsTypes.Categories } },
|
filterOptions: { type: { equals: KeysTypes.Categories } },
|
||||||
hasMany: true,
|
hasMany: true,
|
||||||
admin: { allowCreate: false, width: "50%" },
|
admin: { allowCreate: false, width: "35%" },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -138,5 +144,15 @@ export const Posts: CollectionConfig = {
|
||||||
},
|
},
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: fields.hidden,
|
||||||
|
type: "checkbox",
|
||||||
|
required: false,
|
||||||
|
defaultValue: false,
|
||||||
|
admin: {
|
||||||
|
description: "If enabled, the post won't appear in the 'News' section",
|
||||||
|
position: "sidebar",
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
import { CollectionConfig } from "payload/types";
|
||||||
|
import { CollectionGroup } from "../../constants";
|
||||||
|
import { collectionSlug } from "../../utils/string";
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
filename: "filename",
|
||||||
|
mimeType: "mimeType",
|
||||||
|
filesize: "filesize",
|
||||||
|
} as const satisfies Record<string, string>;
|
||||||
|
|
||||||
|
const labels = {
|
||||||
|
singular: "Recorder Thumbnail",
|
||||||
|
plural: "Recorder Thumbnails",
|
||||||
|
} as const satisfies { singular: string; plural: string };
|
||||||
|
|
||||||
|
export const RecorderThumbnails: CollectionConfig = {
|
||||||
|
slug: collectionSlug(labels.plural),
|
||||||
|
labels,
|
||||||
|
typescript: { interface: labels.singular },
|
||||||
|
defaultSort: fields.filename,
|
||||||
|
admin: {
|
||||||
|
useAsTitle: fields.filename,
|
||||||
|
group: CollectionGroup.Media,
|
||||||
|
},
|
||||||
|
|
||||||
|
upload: {
|
||||||
|
staticDir: `../uploads/${labels.plural}`,
|
||||||
|
adminThumbnail: "small",
|
||||||
|
mimeTypes: ["image/*"],
|
||||||
|
imageSizes: [
|
||||||
|
{
|
||||||
|
name: "og",
|
||||||
|
height: 256,
|
||||||
|
width: 256,
|
||||||
|
formatOptions: {
|
||||||
|
format: "jpg",
|
||||||
|
options: { progressive: true, mozjpeg: true, compressionLevel: 9, quality: 80 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "small",
|
||||||
|
height: 128,
|
||||||
|
width: 128,
|
||||||
|
formatOptions: {
|
||||||
|
format: "webp",
|
||||||
|
options: { effort: 6, quality: 80, alphaQuality: 80 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
fields: [],
|
||||||
|
};
|
|
@ -1,12 +1,11 @@
|
||||||
import { CollectionConfig } from "payload/types";
|
import { CollectionConfig } from "payload/types";
|
||||||
import { localizedFields } from "../../fields/translatedFields/translatedFields";
|
import { localizedFields } from "../../fields/translatedFields/translatedFields";
|
||||||
import { Languages } from "../Languages";
|
import { Languages } from "../Languages";
|
||||||
import { Images } from "../Images/Images";
|
|
||||||
import { Cell } from "../../fields/imageField/Cell";
|
|
||||||
import { beforeDuplicate } from "./hooks/beforeDuplicate";
|
import { beforeDuplicate } from "./hooks/beforeDuplicate";
|
||||||
import { imageField } from "../../fields/imageField/imageField";
|
|
||||||
import { CollectionGroup } from "../../constants";
|
import { CollectionGroup } from "../../constants";
|
||||||
import { collectionSlug } from "../../utils/string";
|
import { collectionSlug } from "../../utils/string";
|
||||||
|
import { RecorderThumbnails } from "../RecorderThumbnails/RecorderThumbnails";
|
||||||
|
import { imageField } from "../../fields/imageField/imageField";
|
||||||
|
|
||||||
const fields = {
|
const fields = {
|
||||||
username: "username",
|
username: "username",
|
||||||
|
@ -32,7 +31,13 @@ export const Recorders: CollectionConfig = {
|
||||||
hooks: { beforeDuplicate },
|
hooks: { beforeDuplicate },
|
||||||
description:
|
description:
|
||||||
"Recorders are contributors of the Accord's Library project. Create a Recorder here to be able to credit them in other collections",
|
"Recorders are contributors of the Accord's Library project. Create a Recorder here to be able to credit them in other collections",
|
||||||
defaultColumns: [fields.username, fields.anonymize, fields.biographies, fields.languages],
|
defaultColumns: [
|
||||||
|
fields.username,
|
||||||
|
fields.avatar,
|
||||||
|
fields.anonymize,
|
||||||
|
fields.biographies,
|
||||||
|
fields.languages,
|
||||||
|
],
|
||||||
group: CollectionGroup.Meta,
|
group: CollectionGroup.Meta,
|
||||||
},
|
},
|
||||||
timestamps: false,
|
timestamps: false,
|
||||||
|
@ -40,25 +45,18 @@ export const Recorders: CollectionConfig = {
|
||||||
{
|
{
|
||||||
type: "row",
|
type: "row",
|
||||||
fields: [
|
fields: [
|
||||||
imageField({ name: fields.avatar }),
|
|
||||||
{
|
{
|
||||||
name: fields.username,
|
name: fields.username,
|
||||||
type: "text",
|
type: "text",
|
||||||
unique: true,
|
unique: true,
|
||||||
required: true,
|
required: true,
|
||||||
admin: { description: "The username must be unique" },
|
admin: { description: "The username must be unique", width: "33%" },
|
||||||
},
|
|
||||||
{
|
|
||||||
name: fields.anonymize,
|
|
||||||
type: "checkbox",
|
|
||||||
required: true,
|
|
||||||
defaultValue: false,
|
|
||||||
admin: {
|
|
||||||
width: "50%",
|
|
||||||
description:
|
|
||||||
"If enabled, this recorder's username will not be made public. Instead they will be referred to as 'Recorder#0000' where '0000' is a random four digit number",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
imageField({
|
||||||
|
name: fields.avatar,
|
||||||
|
relationTo: RecorderThumbnails.slug,
|
||||||
|
admin: { width: "66%" },
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -81,5 +79,16 @@ export const Recorders: CollectionConfig = {
|
||||||
},
|
},
|
||||||
fields: [{ name: fields.biography, type: "textarea" }],
|
fields: [{ name: fields.biography, type: "textarea" }],
|
||||||
}),
|
}),
|
||||||
|
{
|
||||||
|
name: fields.anonymize,
|
||||||
|
type: "checkbox",
|
||||||
|
required: true,
|
||||||
|
defaultValue: false,
|
||||||
|
admin: {
|
||||||
|
description:
|
||||||
|
"If enabled, this recorder's username will not be made public. Instead they will be referred to as 'Recorder#0000' where '0000' is a random four digit number",
|
||||||
|
position: "sidebar",
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,7 @@ export enum CollectionGroup {
|
||||||
Administration = "Administration",
|
Administration = "Administration",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum TagsTypes {
|
export enum KeysTypes {
|
||||||
Contents = "Contents",
|
Contents = "Contents",
|
||||||
LibraryAudio = "Library / Audio",
|
LibraryAudio = "Library / Audio",
|
||||||
LibraryVideo = "Library / Video",
|
LibraryVideo = "Library / Video",
|
||||||
|
@ -15,6 +15,7 @@ export enum TagsTypes {
|
||||||
Weapons = "Weapons",
|
Weapons = "Weapons",
|
||||||
GamePlatforms = "Game Platforms",
|
GamePlatforms = "Game Platforms",
|
||||||
Categories = "Categories",
|
Categories = "Categories",
|
||||||
|
Wordings = "Wordings",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum FileTypes {
|
export enum FileTypes {
|
||||||
|
@ -23,3 +24,21 @@ export enum FileTypes {
|
||||||
ContentVideo = "Content / Video",
|
ContentVideo = "Content / Video",
|
||||||
ContentAudio = "Content / Audio",
|
ContentAudio = "Content / Audio",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum LibraryItemsTypes {
|
||||||
|
Textual = "Textual",
|
||||||
|
Audio = "Audio",
|
||||||
|
Video = "Video",
|
||||||
|
Game = "Game",
|
||||||
|
Other = "Other",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum LibraryItemsTextualBindingTypes {
|
||||||
|
Paperback = "Paperback",
|
||||||
|
Hardcover = "Hardcover",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum LibraryItemsTextualPageOrders {
|
||||||
|
LeftToRight = "Left to right",
|
||||||
|
RightToLeft = "Right to left",
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
import { UploadField } from "payload/types";
|
import { UploadField } from "payload/types";
|
||||||
import { Images } from "../../collections/Images/Images";
|
|
||||||
import { Cell } from "./Cell";
|
import { Cell } from "./Cell";
|
||||||
|
|
||||||
type Props = Omit<UploadField, "type" | "relationTo">;
|
type Props = Omit<UploadField, "type">;
|
||||||
|
|
||||||
export const imageField = ({ admin, ...otherProps }: Props): UploadField => ({
|
export const imageField = ({ admin, ...otherProps }: Props): UploadField => ({
|
||||||
...otherProps,
|
...otherProps,
|
||||||
type: "upload",
|
type: "upload",
|
||||||
relationTo: Images.slug,
|
|
||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
Cell,
|
Cell,
|
||||||
|
|
|
@ -3,12 +3,16 @@ import path from "path";
|
||||||
import { Users } from "./collections/Users";
|
import { Users } from "./collections/Users";
|
||||||
import { Languages } from "./collections/Languages";
|
import { Languages } from "./collections/Languages";
|
||||||
import { Recorders } from "./collections/Recorders/Recorders";
|
import { Recorders } from "./collections/Recorders/Recorders";
|
||||||
import { Images } from "./collections/Images/Images";
|
|
||||||
import { Posts } from "./collections/Posts/Posts";
|
import { Posts } from "./collections/Posts/Posts";
|
||||||
import { Tags } from "./collections/Tags/Tags";
|
import { Keys } from "./collections/Keys/Keys";
|
||||||
import { LibraryItems } from "./collections/LibraryItems/LibraryItems";
|
import { LibraryItems } from "./collections/LibraryItems/LibraryItems";
|
||||||
import { Contents } from "./collections/Contents/Contents";
|
import { Contents } from "./collections/Contents/Contents";
|
||||||
import { Files } from "./collections/Files/Files";
|
import { Files } from "./collections/Files/Files";
|
||||||
|
import { RecorderThumbnails } from "./collections/RecorderThumbnails/RecorderThumbnails";
|
||||||
|
import { PostThumbnails } from "./collections/PostThumbnails/PostThumbnails";
|
||||||
|
import { LibraryItemThumbnails } from "./collections/LibraryItemThumbnails/LibraryItemThumbnails";
|
||||||
|
import { ContentThumbnails } from "./collections/ContentThumbnails/ContentThumbnails";
|
||||||
|
import { ContentFolders } from "./collections/ContentFolders/ContentFolders";
|
||||||
import { Logo } from "./components/Logo";
|
import { Logo } from "./components/Logo";
|
||||||
import { Icon } from "./components/Icon";
|
import { Icon } from "./components/Icon";
|
||||||
|
|
||||||
|
@ -21,15 +25,30 @@ export default buildConfig({
|
||||||
favicon: "/public/favicon.ico",
|
favicon: "/public/favicon.ico",
|
||||||
ogImage: "og.jpg",
|
ogImage: "og.jpg",
|
||||||
titleSuffix: "- Accord’s Library",
|
titleSuffix: "- Accord’s Library",
|
||||||
},
|
},
|
||||||
css: path.resolve(__dirname, "styles.scss"),
|
css: path.resolve(__dirname, "styles.scss"),
|
||||||
},
|
},
|
||||||
|
collections: [
|
||||||
|
LibraryItems,
|
||||||
|
Contents,
|
||||||
|
ContentFolders,
|
||||||
|
Posts,
|
||||||
|
ContentThumbnails,
|
||||||
|
LibraryItemThumbnails,
|
||||||
|
RecorderThumbnails,
|
||||||
|
PostThumbnails,
|
||||||
|
Files,
|
||||||
|
Languages,
|
||||||
|
Recorders,
|
||||||
|
Keys,
|
||||||
|
Users,
|
||||||
|
],
|
||||||
globals: [],
|
globals: [],
|
||||||
telemetry: false,
|
telemetry: false,
|
||||||
typescript: {
|
typescript: {
|
||||||
outputFile: path.resolve(__dirname, "types/collections.ts"),
|
outputFile: path.resolve(__dirname, "types/collections.ts"),
|
||||||
},
|
},
|
||||||
graphQL: {
|
graphQL: {
|
||||||
schemaOutputFile: path.resolve(__dirname, "generated-schema.graphql"),
|
disable: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
export type CategoryTranslations = {
|
export type CategoryTranslations = {
|
||||||
language: string | Language;
|
language: string | Language;
|
||||||
name: string;
|
name: string;
|
||||||
|
short?: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
}[];
|
}[];
|
||||||
export type RecorderBiographies = {
|
export type RecorderBiographies = {
|
||||||
|
@ -16,25 +17,39 @@ export type RecorderBiographies = {
|
||||||
biography?: string;
|
biography?: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
}[];
|
}[];
|
||||||
|
export type ContentFoldersTranslation = {
|
||||||
|
language: string | Language;
|
||||||
|
name: string;
|
||||||
|
id?: string;
|
||||||
|
}[];
|
||||||
|
|
||||||
export interface Config {
|
export interface Config {
|
||||||
collections: {
|
collections: {
|
||||||
'library-items': LibraryItem;
|
'library-items': LibraryItem;
|
||||||
contents: Content;
|
contents: Content;
|
||||||
|
'content-folders': ContentFolder;
|
||||||
posts: Post;
|
posts: Post;
|
||||||
images: Image;
|
'content-thumbnails': ContentThumbnail;
|
||||||
|
'library-item-thumbnails': LibraryItemThumbnail;
|
||||||
|
'recorder-thumbnails': RecorderThumbnail;
|
||||||
|
'post-thumbnails': PostThumbnail;
|
||||||
files: File;
|
files: File;
|
||||||
languages: Language;
|
languages: Language;
|
||||||
recorders: Recorder;
|
recorders: Recorder;
|
||||||
tags: Tag;
|
keys: Key;
|
||||||
users: User;
|
users: User;
|
||||||
};
|
};
|
||||||
globals: {};
|
globals: {};
|
||||||
}
|
}
|
||||||
export interface LibraryItem {
|
export interface LibraryItem {
|
||||||
id: string;
|
id: string;
|
||||||
|
/**
|
||||||
|
* @minItems 2
|
||||||
|
* @maxItems 2
|
||||||
|
*/
|
||||||
|
test?: [number, number];
|
||||||
slug: string;
|
slug: string;
|
||||||
thumbnail?: string | Image;
|
thumbnail?: string | LibraryItemThumbnail;
|
||||||
pretitle?: string;
|
pretitle?: string;
|
||||||
title: string;
|
title: string;
|
||||||
subtitle?: string;
|
subtitle?: string;
|
||||||
|
@ -47,13 +62,37 @@ export interface LibraryItem {
|
||||||
height?: number;
|
height?: number;
|
||||||
thickness?: number;
|
thickness?: number;
|
||||||
};
|
};
|
||||||
|
itemType?: 'Textual' | 'Audio' | 'Video' | 'Game' | 'Other';
|
||||||
|
textual?: {
|
||||||
|
subtype?:
|
||||||
|
| {
|
||||||
|
value: string;
|
||||||
|
relationTo: 'keys';
|
||||||
|
}[]
|
||||||
|
| {
|
||||||
|
value: Key;
|
||||||
|
relationTo: 'keys';
|
||||||
|
}[];
|
||||||
|
languages?:
|
||||||
|
| {
|
||||||
|
value: string;
|
||||||
|
relationTo: 'languages';
|
||||||
|
}[]
|
||||||
|
| {
|
||||||
|
value: Language;
|
||||||
|
relationTo: 'languages';
|
||||||
|
}[];
|
||||||
|
pageCount?: number;
|
||||||
|
bindingType?: 'Paperback' | 'Hardcover';
|
||||||
|
pageOrder?: 'LeftToRight' | 'RightToLeft';
|
||||||
|
};
|
||||||
|
releaseDate?: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
_status?: 'draft' | 'published';
|
_status?: 'draft' | 'published';
|
||||||
}
|
}
|
||||||
export interface Image {
|
export interface LibraryItemThumbnail {
|
||||||
id: string;
|
id: string;
|
||||||
alt?: string;
|
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
|
@ -62,24 +101,69 @@ export interface Image {
|
||||||
filesize?: number;
|
filesize?: number;
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number;
|
height?: number;
|
||||||
|
sizes?: {
|
||||||
|
og?: {
|
||||||
|
url?: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
mimeType?: string;
|
||||||
|
filesize?: number;
|
||||||
|
filename?: string;
|
||||||
|
};
|
||||||
|
medium?: {
|
||||||
|
url?: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
mimeType?: string;
|
||||||
|
filesize?: number;
|
||||||
|
filename?: string;
|
||||||
|
};
|
||||||
|
large?: {
|
||||||
|
url?: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
mimeType?: string;
|
||||||
|
filesize?: number;
|
||||||
|
filename?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export interface Key {
|
||||||
|
id: string;
|
||||||
|
slug: string;
|
||||||
|
type:
|
||||||
|
| 'Contents'
|
||||||
|
| 'LibraryAudio'
|
||||||
|
| 'LibraryVideo'
|
||||||
|
| 'LibraryTextual'
|
||||||
|
| 'LibraryGroup'
|
||||||
|
| 'Library'
|
||||||
|
| 'Weapons'
|
||||||
|
| 'GamePlatforms'
|
||||||
|
| 'Categories'
|
||||||
|
| 'Wordings';
|
||||||
|
translations?: CategoryTranslations;
|
||||||
|
}
|
||||||
|
export interface Language {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
}
|
}
|
||||||
export interface Content {
|
export interface Content {
|
||||||
id: string;
|
id: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
thumbnail?: string | Image;
|
thumbnail?: string | ContentThumbnail;
|
||||||
testing?: (Section_1 | Collapsible_1 | Columns_1 | Tabs_1 | Accordion_1 | TextBlock | TranscriptBlock)[];
|
|
||||||
categories?:
|
categories?:
|
||||||
| {
|
| {
|
||||||
value: string;
|
value: string;
|
||||||
relationTo: 'tags';
|
relationTo: 'keys';
|
||||||
}[]
|
}[]
|
||||||
| {
|
| {
|
||||||
value: Tag;
|
value: Key;
|
||||||
relationTo: 'tags';
|
relationTo: 'keys';
|
||||||
}[];
|
}[];
|
||||||
type?: {
|
type?: {
|
||||||
value: string | Tag;
|
value: string | Key;
|
||||||
relationTo: 'tags';
|
relationTo: 'keys';
|
||||||
};
|
};
|
||||||
translations: {
|
translations: {
|
||||||
language: string | Language;
|
language: string | Language;
|
||||||
|
@ -91,9 +175,7 @@ export interface Content {
|
||||||
textTranscribers?: string[] | Recorder[];
|
textTranscribers?: string[] | Recorder[];
|
||||||
textTranslators?: string[] | Recorder[];
|
textTranslators?: string[] | Recorder[];
|
||||||
textProofreaders?: string[] | Recorder[];
|
textProofreaders?: string[] | Recorder[];
|
||||||
textContent?: {
|
textContent?: (TextBlock | Section | Tabs | TranscriptBlock | QuoteBlock)[];
|
||||||
[k: string]: unknown;
|
|
||||||
}[];
|
|
||||||
textNotes?: string;
|
textNotes?: string;
|
||||||
video?: string | File;
|
video?: string | File;
|
||||||
videoNotes?: string;
|
videoNotes?: string;
|
||||||
|
@ -104,29 +186,71 @@ export interface Content {
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
_status?: 'draft' | 'published';
|
_status?: 'draft' | 'published';
|
||||||
}
|
}
|
||||||
export interface Section_1 {
|
export interface ContentThumbnail {
|
||||||
content?: (Section_2 | Collapsible_2 | Columns_2 | Tabs_2 | Accordion_2 | TextBlock | TranscriptBlock)[];
|
id: string;
|
||||||
id?: string;
|
updatedAt: string;
|
||||||
blockName?: string;
|
createdAt: string;
|
||||||
blockType: 'section_1';
|
url?: string;
|
||||||
|
filename?: string;
|
||||||
|
mimeType?: string;
|
||||||
|
filesize?: number;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
sizes?: {
|
||||||
|
og?: {
|
||||||
|
url?: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
mimeType?: string;
|
||||||
|
filesize?: number;
|
||||||
|
filename?: string;
|
||||||
|
};
|
||||||
|
medium?: {
|
||||||
|
url?: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
mimeType?: string;
|
||||||
|
filesize?: number;
|
||||||
|
filename?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
export interface Section_2 {
|
export interface Recorder {
|
||||||
content?: (Section_3 | Collapsible_3 | Columns_3 | Tabs_3 | Accordion_3 | TextBlock | TranscriptBlock)[];
|
id: string;
|
||||||
id?: string;
|
username: string;
|
||||||
blockName?: string;
|
avatar?: string | RecorderThumbnail;
|
||||||
blockType: 'section_2';
|
languages?: string[] | Language[];
|
||||||
|
biographies?: RecorderBiographies;
|
||||||
|
anonymize: boolean;
|
||||||
}
|
}
|
||||||
export interface Section_3 {
|
export interface RecorderThumbnail {
|
||||||
content?: (Section_4 | Collapsible_4 | Columns_4 | Tabs_4 | Accordion_4 | TextBlock | TranscriptBlock)[];
|
id: string;
|
||||||
id?: string;
|
updatedAt: string;
|
||||||
blockName?: string;
|
createdAt: string;
|
||||||
blockType: 'section_3';
|
url?: string;
|
||||||
}
|
filename?: string;
|
||||||
export interface Section_4 {
|
mimeType?: string;
|
||||||
content?: (TextBlock | TranscriptBlock)[];
|
filesize?: number;
|
||||||
id?: string;
|
width?: number;
|
||||||
blockName?: string;
|
height?: number;
|
||||||
blockType: 'section_4';
|
sizes?: {
|
||||||
|
og?: {
|
||||||
|
url?: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
mimeType?: string;
|
||||||
|
filesize?: number;
|
||||||
|
filename?: string;
|
||||||
|
};
|
||||||
|
small?: {
|
||||||
|
url?: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
mimeType?: string;
|
||||||
|
filesize?: number;
|
||||||
|
filename?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
export interface TextBlock {
|
export interface TextBlock {
|
||||||
content: {
|
content: {
|
||||||
|
@ -136,6 +260,42 @@ export interface TextBlock {
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'textBlock';
|
blockType: 'textBlock';
|
||||||
}
|
}
|
||||||
|
export interface Section {
|
||||||
|
content?: (Section_Section | Section_Tabs | TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
|
id?: string;
|
||||||
|
blockName?: string;
|
||||||
|
blockType: 'section';
|
||||||
|
}
|
||||||
|
export interface Section_Section {
|
||||||
|
content?: (Section_Section_Section | Section_Section_Tabs | TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
|
id?: string;
|
||||||
|
blockName?: string;
|
||||||
|
blockType: 'section';
|
||||||
|
}
|
||||||
|
export interface Section_Section_Section {
|
||||||
|
content?: (
|
||||||
|
| Section_Section_Section_Section
|
||||||
|
| Section_Section_Section_Tabs
|
||||||
|
| TranscriptBlock
|
||||||
|
| QuoteBlock
|
||||||
|
| TextBlock
|
||||||
|
)[];
|
||||||
|
id?: string;
|
||||||
|
blockName?: string;
|
||||||
|
blockType: 'section';
|
||||||
|
}
|
||||||
|
export interface Section_Section_Section_Section {
|
||||||
|
content?: (Section_Section_Section_Section_Section | TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
|
id?: string;
|
||||||
|
blockName?: string;
|
||||||
|
blockType: 'section';
|
||||||
|
}
|
||||||
|
export interface Section_Section_Section_Section_Section {
|
||||||
|
content?: (TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
|
id?: string;
|
||||||
|
blockName?: string;
|
||||||
|
blockType: 'section';
|
||||||
|
}
|
||||||
export interface TranscriptBlock {
|
export interface TranscriptBlock {
|
||||||
lines: (LineBlock | CueBlock)[];
|
lines: (LineBlock | CueBlock)[];
|
||||||
id?: string;
|
id?: string;
|
||||||
|
@ -156,182 +316,122 @@ export interface CueBlock {
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'cueBlock';
|
blockType: 'cueBlock';
|
||||||
}
|
}
|
||||||
export interface Collapsible_4 {
|
export interface QuoteBlock {
|
||||||
content?: (TextBlock | TranscriptBlock)[];
|
from: string;
|
||||||
|
content: {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'collapsible_4';
|
blockType: 'quoteBlock';
|
||||||
}
|
}
|
||||||
export interface Columns_4 {
|
export interface Section_Section_Section_Tabs {
|
||||||
columns?: Column_4[];
|
tabs?: Section_Section_Section_Tabs_Tab[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'columns_4';
|
blockType: 'tabs';
|
||||||
}
|
}
|
||||||
export interface Column_4 {
|
export interface Section_Section_Section_Tabs_Tab {
|
||||||
content?: (TextBlock | TranscriptBlock)[];
|
content?: (Section_Section_Section_Tabs_Tab_Section | TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'column_4';
|
blockType: 'tab';
|
||||||
}
|
}
|
||||||
export interface Tabs_4 {
|
export interface Section_Section_Section_Tabs_Tab_Section {
|
||||||
tabs?: Tab_4[];
|
content?: (TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'tabs_4';
|
blockType: 'section';
|
||||||
}
|
}
|
||||||
export interface Tab_4 {
|
export interface Section_Section_Tabs {
|
||||||
content?: (TextBlock | TranscriptBlock)[];
|
tabs?: Section_Section_Tabs_Tab[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'tab_4';
|
blockType: 'tabs';
|
||||||
}
|
}
|
||||||
export interface Accordion_4 {
|
export interface Section_Section_Tabs_Tab {
|
||||||
content?: Collapsible_5[];
|
content?: (Section_Section_Tabs_Tab_Section | TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'accordion_4';
|
blockType: 'tab';
|
||||||
}
|
}
|
||||||
export interface Collapsible_5 {
|
export interface Section_Section_Tabs_Tab_Section {
|
||||||
content?: (TextBlock | TranscriptBlock)[];
|
content?: (Section_Section_Tabs_Tab_Section_Section | TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'collapsible_5';
|
blockType: 'section';
|
||||||
}
|
}
|
||||||
export interface Collapsible_3 {
|
export interface Section_Section_Tabs_Tab_Section_Section {
|
||||||
content?: (Section_4 | Collapsible_4 | Columns_4 | Tabs_4 | Accordion_4 | TextBlock | TranscriptBlock)[];
|
content?: (TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'collapsible_3';
|
blockType: 'section';
|
||||||
}
|
}
|
||||||
export interface Columns_3 {
|
export interface Section_Tabs {
|
||||||
columns?: Column_3[];
|
tabs?: Section_Tabs_Tab[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'columns_3';
|
blockType: 'tabs';
|
||||||
}
|
}
|
||||||
export interface Column_3 {
|
export interface Section_Tabs_Tab {
|
||||||
content?: (Section_4 | Collapsible_4 | Columns_4 | Tabs_4 | Accordion_4 | TextBlock | TranscriptBlock)[];
|
content?: (Section_Tabs_Tab_Section | TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'column_3';
|
blockType: 'tab';
|
||||||
}
|
}
|
||||||
export interface Tabs_3 {
|
export interface Section_Tabs_Tab_Section {
|
||||||
tabs?: Tab_3[];
|
content?: (Section_Tabs_Tab_Section_Section | TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'tabs_3';
|
blockType: 'section';
|
||||||
}
|
}
|
||||||
export interface Tab_3 {
|
export interface Section_Tabs_Tab_Section_Section {
|
||||||
content?: (Section_4 | Collapsible_4 | Columns_4 | Tabs_4 | Accordion_4 | TextBlock | TranscriptBlock)[];
|
content?: (Section_Tabs_Tab_Section_Section_Section | TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'tab_3';
|
blockType: 'section';
|
||||||
}
|
}
|
||||||
export interface Accordion_3 {
|
export interface Section_Tabs_Tab_Section_Section_Section {
|
||||||
content?: Collapsible_4[];
|
content?: (TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'accordion_3';
|
blockType: 'section';
|
||||||
}
|
}
|
||||||
export interface Collapsible_2 {
|
export interface Tabs {
|
||||||
content?: (Section_3 | Collapsible_3 | Columns_3 | Tabs_3 | Accordion_3 | TextBlock | TranscriptBlock)[];
|
tabs?: Tabs_Tab[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'collapsible_2';
|
blockType: 'tabs';
|
||||||
}
|
}
|
||||||
export interface Columns_2 {
|
export interface Tabs_Tab {
|
||||||
columns?: Column_2[];
|
content?: (Tabs_Tab_Section | TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'columns_2';
|
blockType: 'tab';
|
||||||
}
|
}
|
||||||
export interface Column_2 {
|
export interface Tabs_Tab_Section {
|
||||||
content?: (Section_3 | Collapsible_3 | Columns_3 | Tabs_3 | Accordion_3 | TextBlock | TranscriptBlock)[];
|
content?: (Tabs_Tab_Section_Section | TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'column_2';
|
blockType: 'section';
|
||||||
}
|
}
|
||||||
export interface Tabs_2 {
|
export interface Tabs_Tab_Section_Section {
|
||||||
tabs?: Tab_2[];
|
content?: (Tabs_Tab_Section_Section_Section | TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'tabs_2';
|
blockType: 'section';
|
||||||
}
|
}
|
||||||
export interface Tab_2 {
|
export interface Tabs_Tab_Section_Section_Section {
|
||||||
content?: (Section_3 | Collapsible_3 | Columns_3 | Tabs_3 | Accordion_3 | TextBlock | TranscriptBlock)[];
|
content?: (Tabs_Tab_Section_Section_Section_Section | TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'tab_2';
|
blockType: 'section';
|
||||||
}
|
}
|
||||||
export interface Accordion_2 {
|
export interface Tabs_Tab_Section_Section_Section_Section {
|
||||||
content?: Collapsible_3[];
|
content?: (TranscriptBlock | QuoteBlock | TextBlock)[];
|
||||||
id?: string;
|
id?: string;
|
||||||
blockName?: string;
|
blockName?: string;
|
||||||
blockType: 'accordion_2';
|
blockType: 'section';
|
||||||
}
|
|
||||||
export interface Collapsible_1 {
|
|
||||||
content?: (Section_2 | Collapsible_2 | Columns_2 | Tabs_2 | Accordion_2 | TextBlock | TranscriptBlock)[];
|
|
||||||
id?: string;
|
|
||||||
blockName?: string;
|
|
||||||
blockType: 'collapsible_1';
|
|
||||||
}
|
|
||||||
export interface Columns_1 {
|
|
||||||
columns?: Column_1[];
|
|
||||||
id?: string;
|
|
||||||
blockName?: string;
|
|
||||||
blockType: 'columns_1';
|
|
||||||
}
|
|
||||||
export interface Column_1 {
|
|
||||||
content?: (Section_2 | Collapsible_2 | Columns_2 | Tabs_2 | Accordion_2 | TextBlock | TranscriptBlock)[];
|
|
||||||
id?: string;
|
|
||||||
blockName?: string;
|
|
||||||
blockType: 'column_1';
|
|
||||||
}
|
|
||||||
export interface Tabs_1 {
|
|
||||||
tabs?: Tab_1[];
|
|
||||||
id?: string;
|
|
||||||
blockName?: string;
|
|
||||||
blockType: 'tabs_1';
|
|
||||||
}
|
|
||||||
export interface Tab_1 {
|
|
||||||
content?: (Section_2 | Collapsible_2 | Columns_2 | Tabs_2 | Accordion_2 | TextBlock | TranscriptBlock)[];
|
|
||||||
id?: string;
|
|
||||||
blockName?: string;
|
|
||||||
blockType: 'tab_1';
|
|
||||||
}
|
|
||||||
export interface Accordion_1 {
|
|
||||||
content?: Collapsible_2[];
|
|
||||||
id?: string;
|
|
||||||
blockName?: string;
|
|
||||||
blockType: 'accordion_1';
|
|
||||||
}
|
|
||||||
export interface Tag {
|
|
||||||
id: string;
|
|
||||||
slug: string;
|
|
||||||
type:
|
|
||||||
| 'Contents'
|
|
||||||
| 'LibraryAudio'
|
|
||||||
| 'LibraryVideo'
|
|
||||||
| 'LibraryTextual'
|
|
||||||
| 'LibraryGroup'
|
|
||||||
| 'Library'
|
|
||||||
| 'Weapons'
|
|
||||||
| 'GamePlatforms'
|
|
||||||
| 'Categories';
|
|
||||||
translations?: CategoryTranslations;
|
|
||||||
}
|
|
||||||
export interface Language {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
export interface Recorder {
|
|
||||||
id: string;
|
|
||||||
avatar?: string | Image;
|
|
||||||
username: string;
|
|
||||||
anonymize: boolean;
|
|
||||||
languages?: string[] | Language[];
|
|
||||||
biographies?: RecorderBiographies;
|
|
||||||
}
|
}
|
||||||
export interface File {
|
export interface File {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -340,10 +440,33 @@ export interface File {
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
export interface ContentFolder {
|
||||||
|
id: string;
|
||||||
|
slug: string;
|
||||||
|
translations?: ContentFoldersTranslation;
|
||||||
|
subfolders?:
|
||||||
|
| {
|
||||||
|
value: string;
|
||||||
|
relationTo: 'content-folders';
|
||||||
|
}[]
|
||||||
|
| {
|
||||||
|
value: ContentFolder;
|
||||||
|
relationTo: 'content-folders';
|
||||||
|
}[];
|
||||||
|
contents?:
|
||||||
|
| {
|
||||||
|
value: string;
|
||||||
|
relationTo: 'contents';
|
||||||
|
}[]
|
||||||
|
| {
|
||||||
|
value: Content;
|
||||||
|
relationTo: 'contents';
|
||||||
|
}[];
|
||||||
|
}
|
||||||
export interface Post {
|
export interface Post {
|
||||||
id: string;
|
id: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
thumbnail?: string | Image;
|
thumbnail?: string | PostThumbnail;
|
||||||
authors:
|
authors:
|
||||||
| {
|
| {
|
||||||
value: string;
|
value: string;
|
||||||
|
@ -356,11 +479,11 @@ export interface Post {
|
||||||
categories?:
|
categories?:
|
||||||
| {
|
| {
|
||||||
value: string;
|
value: string;
|
||||||
relationTo: 'tags';
|
relationTo: 'keys';
|
||||||
}[]
|
}[]
|
||||||
| {
|
| {
|
||||||
value: Tag;
|
value: Key;
|
||||||
relationTo: 'tags';
|
relationTo: 'keys';
|
||||||
}[];
|
}[];
|
||||||
translations: {
|
translations: {
|
||||||
language: string | Language;
|
language: string | Language;
|
||||||
|
@ -375,10 +498,40 @@ export interface Post {
|
||||||
id?: string;
|
id?: string;
|
||||||
}[];
|
}[];
|
||||||
publishedDate: string;
|
publishedDate: string;
|
||||||
|
hidden?: boolean;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
_status?: 'draft' | 'published';
|
_status?: 'draft' | 'published';
|
||||||
}
|
}
|
||||||
|
export interface PostThumbnail {
|
||||||
|
id: string;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
url?: string;
|
||||||
|
filename?: string;
|
||||||
|
mimeType?: string;
|
||||||
|
filesize?: number;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
sizes?: {
|
||||||
|
og?: {
|
||||||
|
url?: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
mimeType?: string;
|
||||||
|
filesize?: number;
|
||||||
|
filename?: string;
|
||||||
|
};
|
||||||
|
medium?: {
|
||||||
|
url?: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
mimeType?: string;
|
||||||
|
filesize?: number;
|
||||||
|
filename?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
export interface User {
|
export interface User {
|
||||||
id: string;
|
id: string;
|
||||||
email: string;
|
email: string;
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
import { Block, BlockField } from "payload/types";
|
||||||
|
|
||||||
|
const isDefined = <T>(value: T | null | undefined): value is T =>
|
||||||
|
value !== null && value !== undefined;
|
||||||
|
|
||||||
|
const recursionFieldName = "recursion" as const;
|
||||||
|
|
||||||
|
type BlockConfig<T extends string> = {
|
||||||
|
root: boolean;
|
||||||
|
block: RecursiveBlock<T> | Block;
|
||||||
|
};
|
||||||
|
|
||||||
|
type RecursiveBlock<T extends string> = Omit<Block, "fields" | "interfaceName"> & {
|
||||||
|
[recursionFieldName]: Omit<BlockField, "blocks" | "type"> & {
|
||||||
|
newDepth: (currentDepth: number) => number;
|
||||||
|
condition: (currentDepth: number, parents: T[]) => boolean;
|
||||||
|
blocks: T[];
|
||||||
|
};
|
||||||
|
fields?: Block["fields"];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BlocksConfig<T extends string> = Record<T, BlockConfig<T>>;
|
||||||
|
|
||||||
|
export const generateBlocks = <T extends string>(blocksConfig: BlocksConfig<T>): Block[] => {
|
||||||
|
const isRecursiveBlock = (block: RecursiveBlock<T> | Block): block is RecursiveBlock<T> =>
|
||||||
|
recursionFieldName in block;
|
||||||
|
|
||||||
|
const getInterfaceName = (parents: T[], currentBlockName: T): string => {
|
||||||
|
const capitalize = (text: string): string => {
|
||||||
|
if (text.length === 0) return text;
|
||||||
|
const [firstLetter, ...rest] = text;
|
||||||
|
return [firstLetter.toUpperCase(), ...rest].join("");
|
||||||
|
};
|
||||||
|
return [...parents, currentBlockName]
|
||||||
|
.map((blockName) => blocksConfig[blockName].block.slug)
|
||||||
|
.map(capitalize)
|
||||||
|
.join("_");
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCurrentDepth = (parents: T[]): number =>
|
||||||
|
parents.reduce((acc, blockName) => {
|
||||||
|
const block = blocksConfig[blockName].block;
|
||||||
|
if (!isRecursiveBlock(block)) return acc;
|
||||||
|
return block[recursionFieldName].newDepth(acc);
|
||||||
|
}, 1);
|
||||||
|
|
||||||
|
const generateRecursiveBlocks = (parents: T[], blockName: T): Block | undefined => {
|
||||||
|
const currentDepth = getCurrentDepth(parents);
|
||||||
|
const block = blocksConfig[blockName].block;
|
||||||
|
if (!isRecursiveBlock(block)) return block;
|
||||||
|
|
||||||
|
const {
|
||||||
|
slug,
|
||||||
|
labels,
|
||||||
|
fields = [],
|
||||||
|
recursion: { newDepth, blocks, condition, ...fieldsProps },
|
||||||
|
} = block;
|
||||||
|
|
||||||
|
const generatedBlocks = blocks
|
||||||
|
.filter((blockName) => {
|
||||||
|
const block = blocksConfig[blockName].block;
|
||||||
|
if (!isRecursiveBlock(block)) return true;
|
||||||
|
return block[recursionFieldName].condition(currentDepth, parents);
|
||||||
|
})
|
||||||
|
.map((nextBlockName) => generateRecursiveBlocks([...parents, blockName], nextBlockName))
|
||||||
|
.filter(isDefined);
|
||||||
|
|
||||||
|
// Cut dead branches (branches without leafs)
|
||||||
|
if (generatedBlocks.length === 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
slug,
|
||||||
|
interfaceName: getInterfaceName(parents, blockName),
|
||||||
|
labels,
|
||||||
|
fields: [
|
||||||
|
...fields,
|
||||||
|
{
|
||||||
|
...fieldsProps,
|
||||||
|
type: "blocks",
|
||||||
|
blocks: generatedBlocks,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const rootBlockNames = Object.entries<BlockConfig<T>>(blocksConfig)
|
||||||
|
.filter(([_, blockConfig]) => blockConfig.root)
|
||||||
|
.map(([blockName]) => blockName as T);
|
||||||
|
|
||||||
|
return rootBlockNames
|
||||||
|
.map((blockName) => generateRecursiveBlocks([], blockName))
|
||||||
|
.filter(isDefined);
|
||||||
|
};
|
|
@ -1,11 +1,8 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es5",
|
"target": "ES2022",
|
||||||
"lib": [
|
"moduleResolution": "NodeNext",
|
||||||
"dom",
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
"dom.iterable",
|
|
||||||
"esnext"
|
|
||||||
],
|
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"strict": false,
|
"strict": false,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
|
@ -14,21 +11,13 @@
|
||||||
"rootDir": "./src",
|
"rootDir": "./src",
|
||||||
"jsx": "react",
|
"jsx": "react",
|
||||||
"paths": {
|
"paths": {
|
||||||
"payload/generated-types": [
|
"payload/generated-types": ["./src/payload-types.ts"]
|
||||||
"./src/payload-types.ts",
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["src"],
|
||||||
"src"
|
"exclude": ["node_modules", "dist", "build"],
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"node_modules",
|
|
||||||
"dist",
|
|
||||||
"build",
|
|
||||||
],
|
|
||||||
"ts-node": {
|
"ts-node": {
|
||||||
"transpileOnly": true,
|
"transpileOnly": true,
|
||||||
"swc": true,
|
"swc": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue