diff --git a/src/collections/Folders/Folders.ts b/src/collections/Folders/Folders.ts index e5c77bf..18d1d4f 100644 --- a/src/collections/Folders/Folders.ts +++ b/src/collections/Folders/Folders.ts @@ -1,6 +1,5 @@ import { CollectionGroups, Collections } from "../../constants"; import { iconField } from "../../fields/iconField/iconField"; -import { imageField } from "../../fields/imageField/imageField"; import { rowField } from "../../fields/rowField/rowField"; import { slugField } from "../../fields/slugField/slugField"; import { translatedFields } from "../../fields/translatedFields/translatedFields"; @@ -19,8 +18,6 @@ const fields = { sectionsTranslations: "translations", sectionsTranslationsName: "name", files: "files", - darkThumbnail: "darkThumbnail", - lightThumbnail: "lightThumbnail", icon: "icon", } as const satisfies Record; @@ -38,10 +35,6 @@ export const Folders = buildCollectionConfig({ endpoints: [getRootFoldersEndpoint, getBySlugEndpoint], fields: [ rowField([slugField({ name: fields.slug }), iconField({ name: fields.icon })]), - rowField([ - imageField({ name: fields.lightThumbnail, relationTo: Collections.FoldersThumbnails }), - imageField({ name: fields.darkThumbnail, relationTo: Collections.FoldersThumbnails }), - ]), translatedFields({ name: fields.translations, admin: { useAsTitle: fields.translationsName }, diff --git a/src/collections/Folders/endpoints/getBySlugEndpoint.ts b/src/collections/Folders/endpoints/getBySlugEndpoint.ts index a8f0067..fc8f509 100644 --- a/src/collections/Folders/endpoints/getBySlugEndpoint.ts +++ b/src/collections/Folders/endpoints/getBySlugEndpoint.ts @@ -2,7 +2,7 @@ import { Collections } from "../../../constants"; import { createGetByEndpoint } from "../../../endpoints/createGetByEndpoint"; import { EndpointFolder, EndpointFolderPreview } from "../../../sdk"; import { Folder, Language } from "../../../types/collections"; -import { isDefined, isPayloadType, isValidPayloadImage } from "../../../utils/asserts"; +import { isDefined, isPayloadType } from "../../../utils/asserts"; import { convertCollectibleToPreview } from "../../Collectibles/endpoints/getBySlugEndpoint"; import { convertPageToPreview } from "../../Pages/endpoints/getBySlugEndpoint"; @@ -44,13 +44,12 @@ export const getBySlugEndpoint = createGetByEndpoint( } }) ?? [], }; - }, 3 + }, + 3 ); export const convertFolderToPreview = ({ slug, - darkThumbnail, - lightThumbnail, translations, icon, }: Folder): EndpointFolderPreview => { @@ -63,8 +62,6 @@ export const convertFolderToPreview = ({ name, ...(description ? { description } : {}), })) ?? [], - darkThumbnail: isValidPayloadImage(darkThumbnail) ? darkThumbnail : undefined, - lightThumbnail: isValidPayloadImage(lightThumbnail) ? lightThumbnail : undefined, }; }; diff --git a/src/collections/FoldersThumbnails/FoldersThumbnails.ts b/src/collections/FoldersThumbnails/FoldersThumbnails.ts deleted file mode 100644 index 5cafae8..0000000 --- a/src/collections/FoldersThumbnails/FoldersThumbnails.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Collections } from "../../constants"; -import { buildImageCollectionConfig } from "../../utils/imageCollectionConfig"; - -const fields = { - filename: "filename", - mimeType: "mimeType", - filesize: "filesize", - updatedAt: "updatedAt", -} as const satisfies Record; - -export const FoldersThumbnails = buildImageCollectionConfig({ - slug: Collections.FoldersThumbnails, - labels: { - singular: "Folders Thumbnail", - plural: "Folders Thumbnails", - }, - admin: { defaultColumns: [fields.filename, fields.updatedAt] }, - upload: { - imageSizes: [], - }, - fields: [], -}); diff --git a/src/collections/HomeFolders/HomeFolders.ts b/src/collections/HomeFolders/HomeFolders.ts new file mode 100644 index 0000000..b1d452f --- /dev/null +++ b/src/collections/HomeFolders/HomeFolders.ts @@ -0,0 +1,46 @@ +import { GlobalConfig } from "payload/types"; +import { mustBeAdmin } from "../../accesses/collections/mustBeAdmin"; +import { CollectionGroups, Collections } from "../../constants"; +import { imageField } from "../../fields/imageField/imageField"; +import { rowField } from "../../fields/rowField/rowField"; +import { getAllEndpoint } from "./endpoints/getAllEndpoint"; + +const fields = { + folders: "folders", + darkThumbnail: "darkThumbnail", + lightThumbnail: "lightThumbnail", + folder: "folder", + icon: "icon", +} as const satisfies Record; + +export const HomeFolders: GlobalConfig = { + slug: Collections.HomeFolders, + typescript: { interface: "HomeFolder" }, + admin: { + group: CollectionGroups.Meta, + }, + access: { update: mustBeAdmin }, + endpoints: [getAllEndpoint], + fields: [ + { + name: fields.folders, + admin: { + description: + "These will be the folders displayed on the home page, under the Library section.", + }, + type: "array", + fields: [ + rowField([ + imageField({ name: fields.lightThumbnail, relationTo: Collections.Images }), + imageField({ name: fields.darkThumbnail, relationTo: Collections.Images }), + { + name: fields.folder, + type: "relationship", + relationTo: Collections.Folders, + required: true, + }, + ]), + ], + }, + ], +}; diff --git a/src/collections/HomeFolders/endpoints/getAllEndpoint.ts b/src/collections/HomeFolders/endpoints/getAllEndpoint.ts new file mode 100644 index 0000000..3f48752 --- /dev/null +++ b/src/collections/HomeFolders/endpoints/getAllEndpoint.ts @@ -0,0 +1,47 @@ +import payload from "payload"; +import { Collections } from "../../../constants"; +import { EndpointHomeFolder } from "../../../sdk"; +import { Folder } from "../../../types/collections"; +import { CollectionEndpoint } from "../../../types/payload"; +import { isPayloadType, isValidPayloadImage } from "../../../utils/asserts"; +import { convertFolderToPreview } from "../../Folders/endpoints/getBySlugEndpoint"; + +export const getAllEndpoint: CollectionEndpoint = { + method: "get", + path: "/all", + handler: async (req, res) => { + if (!req.user) { + return res.status(403).send({ + errors: [ + { + message: "You are not allowed to perform this action.", + }, + ], + }); + } + + const homeFolders = await payload.findGlobal({ + slug: Collections.HomeFolders, + }); + + const result = + homeFolders.folders?.flatMap( + ({ folder, darkThumbnail, lightThumbnail }) => { + if (!isPayloadType(folder)) return []; + if (isEmptyFolder(folder)) return []; + return [ + { + ...(isValidPayloadImage(darkThumbnail) ? { darkThumbnail } : {}), + ...(isValidPayloadImage(lightThumbnail) ? { lightThumbnail } : {}), + ...convertFolderToPreview(folder), + }, + ]; + } + ) ?? []; + + res.status(200).json(result); + }, +}; + +const isEmptyFolder = ({ sections, files }: Folder): boolean => + (!files || files.length === 0) && (!sections || sections.length === 0); diff --git a/src/constants.ts b/src/constants.ts index 195dfab..970f5b7 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -20,7 +20,6 @@ export enum Collections { VideosChannels = "videos-channels", Videos = "videos", Folders = "folders", - FoldersThumbnails = "folders-thumbnails", Tags = "tags", TagsGroups = "tags-groups", Images = "images", @@ -28,6 +27,7 @@ export enum Collections { Collectibles = "collectibles", GenericContents = "generic-contents", BackgroundImages = "background-images", + HomeFolders = "home-folders", } export enum CollectionGroups { diff --git a/src/payload.config.ts b/src/payload.config.ts index f463789..2e1ccbf 100644 --- a/src/payload.config.ts +++ b/src/payload.config.ts @@ -8,8 +8,8 @@ import { ChronologyItems } from "./collections/ChronologyItems/ChronologyItems"; import { Collectibles } from "./collections/Collectibles/Collectibles"; import { Currencies } from "./collections/Currencies/Currencies"; import { Folders } from "./collections/Folders/Folders"; -import { FoldersThumbnails } from "./collections/FoldersThumbnails/FoldersThumbnails"; import { GenericContents } from "./collections/GenericContents/GenericContents"; +import { HomeFolders } from "./collections/HomeFolders/HomeFolders"; import { Images } from "./collections/Images/Images"; import { Languages } from "./collections/Languages/Languages"; import { Notes } from "./collections/Notes/Notes"; @@ -41,30 +41,31 @@ export default buildConfig({ }, editor: createEditor({}), collections: [ - Folders, - FoldersThumbnails, Pages, + Collectibles, + Folders, ChronologyItems, ChronologyEras, - RecordersThumbnails, Notes, + + Images, + BackgroundImages, + RecordersThumbnails, Videos, VideosChannels, - Languages, - Currencies, - Recorders, + Tags, TagsGroups, - Images, + Recorders, + Languages, + Currencies, Wordings, - Collectibles, GenericContents, - BackgroundImages, ], db: mongooseAdapter({ url: process.env.MONGODB_URI ?? "mongodb://mongo:27017/payload", }), - globals: [], + globals: [HomeFolders], telemetry: false, typescript: { outputFile: path.resolve(__dirname, "types/collections.ts"), diff --git a/src/sdk.ts b/src/sdk.ts index 0eb86a4..7ef5add 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -126,6 +126,16 @@ export type EndpointEra = { }[]; }; +export type EndpointFolderPreview = { + slug: string; + icon?: string; + translations: { + language: string; + name: string; + description?: RichTextContent; + }[]; +}; + export type EndpointFolder = EndpointFolderPreview & { sections: | { type: "single"; subfolders: EndpointFolderPreview[] } @@ -148,14 +158,7 @@ export type EndpointFolder = EndpointFolderPreview & { )[]; }; -export type EndpointFolderPreview = { - slug: string; - icon?: string; - translations: { - language: string; - name: string; - description?: RichTextContent; - }[]; +export type EndpointHomeFolder = EndpointFolderPreview & { lightThumbnail?: PayloadImage; darkThumbnail?: PayloadImage; }; diff --git a/src/types/collections.ts b/src/types/collections.ts index 9e0d878..e4bdaff 100644 --- a/src/types/collections.ts +++ b/src/types/collections.ts @@ -43,29 +43,244 @@ export type CategoryTranslations = { export interface Config { collections: { - folders: Folder; - 'folders-thumbnails': FoldersThumbnail; pages: Page; + collectibles: Collectible; + folders: Folder; 'chronology-items': ChronologyItem; 'chronology-eras': ChronologyEra; - 'recorders-thumbnails': RecordersThumbnail; notes: Note; + images: Image; + 'background-images': BackgroundImage; + 'recorders-thumbnails': RecordersThumbnail; videos: Video; 'videos-channels': VideosChannel; - languages: Language; - currencies: Currency; - recorders: Recorder; tags: Tag; 'tags-groups': TagsGroup; - images: Image; + recorders: Recorder; + languages: Language; + currencies: Currency; wordings: Wording; - collectibles: Collectible; 'generic-contents': GenericContent; - 'background-images': BackgroundImage; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; }; - globals: {}; + globals: { + 'home-folders': HomeFolder; + }; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "pages". + */ +export interface Page { + id: string; + slug: string; + type: 'Content' | 'Post' | 'Generic'; + thumbnail?: string | Image | null; + backgroundImage?: string | BackgroundImage | null; + tags?: (string | Tag)[] | null; + authors?: (string | Recorder)[] | null; + translations: { + language: string | Language; + sourceLanguage: string | Language; + pretitle?: string | null; + title: string; + subtitle?: string | null; + summary?: { + root: { + children: { + type: string; + version: number; + [k: string]: unknown; + }[]; + direction: ('ltr' | 'rtl') | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + type: string; + version: number; + }; + [k: string]: unknown; + } | null; + content: { + root: { + children: { + type: string; + version: number; + [k: string]: unknown; + }[]; + direction: ('ltr' | 'rtl') | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + type: string; + version: number; + }; + [k: string]: unknown; + }; + transcribers?: (string | Recorder)[] | null; + translators?: (string | Recorder)[] | null; + proofreaders?: (string | Recorder)[] | null; + id?: string | null; + }[]; + folders?: (string | Folder)[] | null; + collectibles?: (string | Collectible)[] | null; + updatedBy: string | Recorder; + updatedAt: string; + createdAt: string; + _status?: ('draft' | 'published') | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "images". + */ +export interface Image { + id: string; + updatedAt: string; + createdAt: string; + url?: string | null; + filename?: string | null; + mimeType?: string | null; + filesize?: number | null; + width?: number | null; + height?: number | null; + sizes?: { + thumb?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + og?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + }; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "background-images". + */ +export interface BackgroundImage { + id: string; + updatedAt: string; + createdAt: string; + url?: string | null; + filename?: string | null; + mimeType?: string | null; + filesize?: number | null; + width?: number | null; + height?: number | null; + sizes?: { + thumb?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + }; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "tags". + */ +export interface Tag { + id: string; + name?: string | null; + slug: string; + translations: { + language: string | Language; + name: string; + id?: string | null; + }[]; + group: string | TagsGroup; + updatedAt: string; + createdAt: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "languages". + */ +export interface Language { + id: string; + name: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "tags-groups". + */ +export interface TagsGroup { + id: string; + slug: string; + icon?: string | null; + translations: { + language: string | Language; + name: string; + id?: string | null; + }[]; + updatedAt: string; + createdAt: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "recorders". + */ +export interface Recorder { + id: string; + username: string; + avatar?: string | RecordersThumbnail | null; + languages?: (string | Language)[] | null; + biographies?: RecorderBiographies; + role?: ('Admin' | 'Recorder' | 'Api')[] | null; + anonymize: boolean; + email: string; + resetPasswordToken?: string | null; + resetPasswordExpiration?: string | null; + salt?: string | null; + hash?: string | null; + loginAttempts?: number | null; + lockUntil?: string | null; + password?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "recorders-thumbnails". + */ +export interface RecordersThumbnail { + id: string; + recorder?: (string | null) | Recorder; + updatedAt: string; + createdAt: string; + url?: string | null; + filename?: string | null; + mimeType?: string | null; + filesize?: number | null; + width?: number | null; + height?: number | null; + sizes?: { + thumb?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + square?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + }; } /** * This interface was referenced by `Config`'s JSON-Schema @@ -75,30 +290,26 @@ export interface Folder { id: string; slug: string; icon?: string | null; - lightThumbnail?: string | FoldersThumbnail | null; - darkThumbnail?: string | FoldersThumbnail | null; - translations?: - | { - language: string | Language; - name: string; - description?: { - root: { - children: { - type: string; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - type: string; - version: number; - }; + translations: { + language: string | Language; + name: string; + description?: { + root: { + children: { + type: string; + version: number; [k: string]: unknown; - } | null; - id?: string | null; - }[] - | null; + }[]; + direction: ('ltr' | 'rtl') | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + type: string; + version: number; + }; + [k: string]: unknown; + } | null; + id?: string | null; + }[]; sections?: | { translations?: @@ -127,39 +338,6 @@ export interface Folder { updatedAt: string; createdAt: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "folders-thumbnails". - */ -export interface FoldersThumbnail { - id: string; - updatedAt: string; - createdAt: string; - url?: string | null; - filename?: string | null; - mimeType?: string | null; - filesize?: number | null; - width?: number | null; - height?: number | null; - sizes?: { - thumb?: { - url?: string | null; - width?: number | null; - height?: number | null; - mimeType?: string | null; - filesize?: number | null; - filename?: string | null; - }; - }; -} -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "languages". - */ -export interface Language { - id: string; - name: string; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "collectibles". @@ -345,152 +523,6 @@ export interface Collectible { createdAt: string; _status?: ('draft' | 'published') | null; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "images". - */ -export interface Image { - id: string; - updatedAt: string; - createdAt: string; - url?: string | null; - filename?: string | null; - mimeType?: string | null; - filesize?: number | null; - width?: number | null; - height?: number | null; - sizes?: { - thumb?: { - url?: string | null; - width?: number | null; - height?: number | null; - mimeType?: string | null; - filesize?: number | null; - filename?: string | null; - }; - og?: { - url?: string | null; - width?: number | null; - height?: number | null; - mimeType?: string | null; - filesize?: number | null; - filename?: string | null; - }; - }; -} -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "tags". - */ -export interface Tag { - id: string; - name?: string | null; - slug: string; - translations: { - language: string | Language; - name: string; - id?: string | null; - }[]; - group: string | TagsGroup; - updatedAt: string; - createdAt: string; -} -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "tags-groups". - */ -export interface TagsGroup { - id: string; - slug: string; - icon?: string | null; - translations: { - language: string | Language; - name: string; - id?: string | null; - }[]; - updatedAt: string; - createdAt: string; -} -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "background-images". - */ -export interface BackgroundImage { - id: string; - updatedAt: string; - createdAt: string; - url?: string | null; - filename?: string | null; - mimeType?: string | null; - filesize?: number | null; - width?: number | null; - height?: number | null; - sizes?: { - thumb?: { - url?: string | null; - width?: number | null; - height?: number | null; - mimeType?: string | null; - filesize?: number | null; - filename?: string | null; - }; - }; -} -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "recorders". - */ -export interface Recorder { - id: string; - username: string; - avatar?: string | RecordersThumbnail | null; - languages?: (string | Language)[] | null; - biographies?: RecorderBiographies; - role?: ('Admin' | 'Recorder' | 'Api')[] | null; - anonymize: boolean; - email: string; - resetPasswordToken?: string | null; - resetPasswordExpiration?: string | null; - salt?: string | null; - hash?: string | null; - loginAttempts?: number | null; - lockUntil?: string | null; - password?: string | null; -} -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "recorders-thumbnails". - */ -export interface RecordersThumbnail { - id: string; - recorder?: (string | null) | Recorder; - updatedAt: string; - createdAt: string; - url?: string | null; - filename?: string | null; - mimeType?: string | null; - filesize?: number | null; - width?: number | null; - height?: number | null; - sizes?: { - thumb?: { - url?: string | null; - width?: number | null; - height?: number | null; - mimeType?: string | null; - filesize?: number | null; - filename?: string | null; - }; - square?: { - url?: string | null; - width?: number | null; - height?: number | null; - mimeType?: string | null; - filesize?: number | null; - filename?: string | null; - }; - }; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "currencies". @@ -498,66 +530,6 @@ export interface RecordersThumbnail { export interface Currency { id: string; } -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "pages". - */ -export interface Page { - id: string; - slug: string; - type: 'Content' | 'Post' | 'Generic'; - thumbnail?: string | Image | null; - backgroundImage?: string | BackgroundImage | null; - tags?: (string | Tag)[] | null; - authors?: (string | Recorder)[] | null; - translations: { - language: string | Language; - sourceLanguage: string | Language; - pretitle?: string | null; - title: string; - subtitle?: string | null; - summary?: { - root: { - children: { - type: string; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - type: string; - version: number; - }; - [k: string]: unknown; - } | null; - content: { - root: { - children: { - type: string; - version: number; - [k: string]: unknown; - }[]; - direction: ('ltr' | 'rtl') | null; - format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; - indent: number; - type: string; - version: number; - }; - [k: string]: unknown; - }; - transcribers?: (string | Recorder)[] | null; - translators?: (string | Recorder)[] | null; - proofreaders?: (string | Recorder)[] | null; - id?: string | null; - }[]; - folders?: (string | Folder)[] | null; - collectibles?: (string | Collectible)[] | null; - updatedBy: string | Recorder; - updatedAt: string; - createdAt: string; - _status?: ('draft' | 'published') | null; -} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "generic-contents". @@ -762,6 +734,23 @@ export interface PayloadMigration { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "home-folders". + */ +export interface HomeFolder { + id: string; + folders?: + | { + lightThumbnail?: string | Image | null; + darkThumbnail?: string | Image | null; + folder: string | Folder; + id?: string | null; + }[] + | null; + updatedAt?: string | null; + createdAt?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "LineBlock".