From 39e2642c5578c35c57b6c8f6de4ee8e0f7435b07 Mon Sep 17 00:00:00 2001 From: DrMint <29893320+DrMint@users.noreply.github.com> Date: Fri, 5 Apr 2024 17:02:06 +0200 Subject: [PATCH] Added website config collection --- package.json | 2 +- src/accesses/endpoints/mustBeAdmin.ts | 9 --- src/collections/HomeFolders/HomeFolders.ts | 46 ----------- .../HomeFolders/endpoints/getAllEndpoint.ts | 47 ----------- .../WebsiteConfig/WebsiteConfig.ts | 77 +++++++++++++++++++ .../endpoints/getConfigEndpoint.ts | 51 ++++++++++++ src/collections/Wordings/Wordings.ts | 1 - src/constants.ts | 2 +- src/payload.config.ts | 4 +- src/sdk.ts | 20 +++-- src/types/collections.ts | 35 +++++---- src/types/payload.ts | 3 - 12 files changed, 167 insertions(+), 130 deletions(-) delete mode 100644 src/accesses/endpoints/mustBeAdmin.ts delete mode 100644 src/collections/HomeFolders/HomeFolders.ts delete mode 100644 src/collections/HomeFolders/endpoints/getAllEndpoint.ts create mode 100644 src/collections/WebsiteConfig/WebsiteConfig.ts create mode 100644 src/collections/WebsiteConfig/endpoints/getConfigEndpoint.ts diff --git a/package.json b/package.json index c1e681c..3f6893f 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png}\" dist/ && copyfiles -u 1 \"src/sdk.ts\" dist/ && copyfiles -u 1 \"src/constants.ts\" dist/ && copyfiles -u 1 \"src/types/collections.ts\" dist/", "generate:types": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:types", "generate:graphQLSchema": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:graphQLSchema", - "unused-exports": "ts-unused-exports ./tsconfig.json --excludePathsFromReport='src/payload.config.ts;src/sdk.ts;src/types/collections.ts'", + "unused-exports": "ts-unused-exports ./tsconfig.json --excludePathsFromReport='src/payload.config.ts;src/constants.ts;src/sdk.ts;src/types/collections.ts'", "prettier": "prettier --list-different --end-of-line auto --write src", "tsc": "tsc --noEmit", "precommit": "npm run generate:types && npm run prettier && npm run unused-exports && npm run tsc", diff --git a/src/accesses/endpoints/mustBeAdmin.ts b/src/accesses/endpoints/mustBeAdmin.ts deleted file mode 100644 index f5fbbb7..0000000 --- a/src/accesses/endpoints/mustBeAdmin.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { RecordersRoles } from "../../constants"; -import { Recorder } from "../../types/collections"; -import { EndpointAccess } from "../../types/payload"; -import { isDefined, isUndefined } from "../../utils/asserts"; - -export const mustBeAdmin: EndpointAccess = ({ user }) => { - if (isUndefined(user)) return false; - return isDefined(user.role) && user.role.includes(RecordersRoles.Admin); -}; diff --git a/src/collections/HomeFolders/HomeFolders.ts b/src/collections/HomeFolders/HomeFolders.ts deleted file mode 100644 index b1d452f..0000000 --- a/src/collections/HomeFolders/HomeFolders.ts +++ /dev/null @@ -1,46 +0,0 @@ -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 deleted file mode 100644 index 3f48752..0000000 --- a/src/collections/HomeFolders/endpoints/getAllEndpoint.ts +++ /dev/null @@ -1,47 +0,0 @@ -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/collections/WebsiteConfig/WebsiteConfig.ts b/src/collections/WebsiteConfig/WebsiteConfig.ts new file mode 100644 index 0000000..656bbf3 --- /dev/null +++ b/src/collections/WebsiteConfig/WebsiteConfig.ts @@ -0,0 +1,77 @@ +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 { getConfigEndpoint } from "./endpoints/getConfigEndpoint"; + +const fields = { + homeFolders: "homeFolders", + homeFoldersDarkThumbnail: "darkThumbnail", + homeFoldersLightThumbnail: "lightThumbnail", + homeFoldersFolder: "folder", + eras: "eras", + name: "name", + timeline: "timeline", + erasStartingYear: "startingYear", + erasEndingYear: "endingYear", + erasWording: "name", + timelineBreaks: "breaks", +} as const satisfies Record; + +export const WebsiteConfig: GlobalConfig = { + slug: Collections.WebsiteConfig, + typescript: { interface: "WebsiteConfig" }, + admin: { + group: CollectionGroups.Meta, + }, + access: { update: mustBeAdmin, read: mustBeAdmin }, + endpoints: [getConfigEndpoint], + fields: [ + { + name: fields.homeFolders, + admin: { + description: + "These will be the folders displayed on the home page, under the Library section.", + }, + type: "array", + fields: [ + rowField([ + imageField({ name: fields.homeFoldersLightThumbnail, relationTo: Collections.Images }), + imageField({ name: fields.homeFoldersDarkThumbnail, relationTo: Collections.Images }), + { + name: fields.homeFoldersFolder, + type: "relationship", + relationTo: Collections.Folders, + required: true, + }, + ]), + ], + }, + { + name: fields.timeline, + type: "group", + fields: [ + { + name: fields.timelineBreaks, + type: "number", + hasMany: true, + }, + { + name: fields.eras, + type: "array", + fields: [ + { + name: fields.erasWording, + type: "relationship", + relationTo: Collections.Wordings, + required: true, + }, + { name: fields.erasStartingYear, type: "number", required: true, min: 0 }, + { name: fields.erasEndingYear, type: "number", required: true, min: 0 }, + ], + }, + ], + }, + ], +}; diff --git a/src/collections/WebsiteConfig/endpoints/getConfigEndpoint.ts b/src/collections/WebsiteConfig/endpoints/getConfigEndpoint.ts new file mode 100644 index 0000000..2514afa --- /dev/null +++ b/src/collections/WebsiteConfig/endpoints/getConfigEndpoint.ts @@ -0,0 +1,51 @@ +import payload from "payload"; +import { Collections } from "../../../constants"; +import { EndpointWebsiteConfig } from "../../../sdk"; +import { CollectionEndpoint } from "../../../types/payload"; +import { isPayloadType, isValidPayloadImage } from "../../../utils/asserts"; +import { convertFolderToPreview } from "../../Folders/endpoints/getBySlugEndpoint"; + +export const getConfigEndpoint: CollectionEndpoint = { + method: "get", + path: "/config", + handler: async (req, res) => { + if (!req.user) { + return res.status(403).send({ + errors: [ + { + message: "You are not allowed to perform this action.", + }, + ], + }); + } + + const { homeFolders, timeline } = await payload.findGlobal({ + slug: Collections.WebsiteConfig, + }); + + const endpointWebsiteConfig: EndpointWebsiteConfig = { + homeFolders: + homeFolders?.flatMap(({ folder, darkThumbnail, lightThumbnail }) => { + if (!isPayloadType(folder)) return []; + return { + ...convertFolderToPreview(folder), + ...(isValidPayloadImage(darkThumbnail) ? { darkThumbnail } : {}), + ...(isValidPayloadImage(lightThumbnail) ? { lightThumbnail } : {}), + }; + }) ?? [], + timeline: { + breaks: timeline?.breaks ?? [], + eras: + timeline?.eras?.flatMap(({ endingYear, name, startingYear }) => { + if (!isPayloadType(name)) return []; + return { + name: isPayloadType(name) ? name.name : name, + startingYear, + endingYear, + }; + }) ?? [], + }, + }; + res.status(200).json(endpointWebsiteConfig); + }, +}; diff --git a/src/collections/Wordings/Wordings.ts b/src/collections/Wordings/Wordings.ts index 2aa6359..9e574c5 100644 --- a/src/collections/Wordings/Wordings.ts +++ b/src/collections/Wordings/Wordings.ts @@ -58,7 +58,6 @@ export const Wordings: CollectionConfig = buildCollectionConfig({ name: fields.translations, minRows: 1, required: true, - interfaceName: "CategoryTranslations", admin: { useAsTitle: fields.translationsName, }, diff --git a/src/constants.ts b/src/constants.ts index 370b181..3b95c3a 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -16,7 +16,7 @@ export enum Collections { Wordings = "wordings", Collectibles = "collectibles", GenericContents = "generic-contents", - HomeFolders = "home-folders", + WebsiteConfig = "website-config", Videos = "videos", VideosSubtitles = "videos-subtitles", VideosChannels = "videos-channels", diff --git a/src/payload.config.ts b/src/payload.config.ts index 408fa55..f1a8944 100644 --- a/src/payload.config.ts +++ b/src/payload.config.ts @@ -9,7 +9,6 @@ import { Collectibles } from "./collections/Collectibles/Collectibles"; import { Currencies } from "./collections/Currencies/Currencies"; import { Folders } from "./collections/Folders/Folders"; 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 { Pages } from "./collections/Pages/Pages"; @@ -21,6 +20,7 @@ import { Videos } from "./collections/Videos/Videos"; import { VideosChannels } from "./collections/VideosChannels/VideosChannels"; import { VideosSubtitles } from "./collections/VideosSubtitles/VideosSubtitles"; import { MediaThumbnails } from "./collections/VideosThumbnails/VideosThumbnails"; +import { WebsiteConfig } from "./collections/WebsiteConfig/WebsiteConfig"; import { Wordings } from "./collections/Wordings/Wordings"; import { Icon } from "./components/Icon"; import { Logo } from "./components/Logo"; @@ -75,7 +75,7 @@ export default buildConfig({ db: mongooseAdapter({ url: process.env.MONGODB_URI ?? "", }), - globals: [HomeFolders], + globals: [WebsiteConfig], telemetry: false, typescript: { outputFile: path.resolve(__dirname, "types/collections.ts"), diff --git a/src/sdk.ts b/src/sdk.ts index 882245d..07fcb96 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -129,9 +129,19 @@ export type EndpointFolder = EndpointFolderPreview & { parentPages: EndpointSource[]; }; -export type EndpointHomeFolder = EndpointFolderPreview & { - lightThumbnail?: PayloadImage; - darkThumbnail?: PayloadImage; +export type EndpointWebsiteConfig = { + homeFolders: (EndpointFolderPreview & { + lightThumbnail?: PayloadImage; + darkThumbnail?: PayloadImage; + })[]; + timeline: { + breaks: number[]; + eras: { + startingYear: number; + endingYear: number; + name: string; + }[]; + }; }; export type EndpointRecorder = { @@ -322,8 +332,8 @@ export type PayloadImage = { }; export const payload = { - getHomeFolders: async (): Promise => - await (await request(payloadApiUrl(Collections.HomeFolders, `all`, true))).json(), + getConfig: async (): Promise => + await (await request(payloadApiUrl(Collections.WebsiteConfig, `config`, true))).json(), getFolder: async (slug: string): Promise => await (await request(payloadApiUrl(Collections.Folders, `slug/${slug}`))).json(), getLanguages: async (): Promise => diff --git a/src/types/collections.ts b/src/types/collections.ts index bb7aa18..fd0467a 100644 --- a/src/types/collections.ts +++ b/src/types/collections.ts @@ -6,16 +6,6 @@ * and re-run `payload generate:types` to regenerate this file. */ -/** - * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "CategoryTranslations". - */ -export type CategoryTranslations = { - language: string | Language; - name: string; - id?: string | null; -}[]; - export interface Config { collections: { pages: Page; @@ -40,7 +30,7 @@ export interface Config { "payload-migrations": PayloadMigration; }; globals: { - config: Config1; + "website-config": WebsiteConfig; }; } /** @@ -802,7 +792,11 @@ export interface PageBlock { export interface Wording { id: string; name: string; - translations: CategoryTranslations; + translations: { + language: string | Language; + name: string; + id?: string | null; + }[]; updatedAt: string; createdAt: string; } @@ -842,11 +836,11 @@ export interface PayloadMigration { } /** * This interface was referenced by `Config`'s JSON-Schema - * via the `definition` "config". + * via the `definition` "website-config". */ -export interface Config1 { +export interface WebsiteConfig { id: string; - folders?: + homeFolders?: | { lightThumbnail?: string | Image | null; darkThumbnail?: string | Image | null; @@ -854,6 +848,17 @@ export interface Config1 { id?: string | null; }[] | null; + timeline?: { + breaks?: number[] | null; + eras?: + | { + name: string | Wording; + startingYear: number; + endingYear: number; + id?: string | null; + }[] + | null; + }; updatedAt?: string | null; createdAt?: string | null; } diff --git a/src/types/payload.ts b/src/types/payload.ts index 5da7c54..2de483d 100644 --- a/src/types/payload.ts +++ b/src/types/payload.ts @@ -1,6 +1,3 @@ import { Endpoint } from "payload/config"; -import { PayloadRequest } from "payload/types"; export type CollectionEndpoint = Omit; - -export type EndpointAccess = (req: PayloadRequest) => boolean;