Added website config collection
This commit is contained in:
		
							parent
							
								
									af7c5ee5a0
								
							
						
					
					
						commit
						39e2642c55
					
				| @ -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", | ||||
|  | ||||
| @ -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<Recorder> = ({ user }) => { | ||||
|   if (isUndefined(user)) return false; | ||||
|   return isDefined(user.role) && user.role.includes(RecordersRoles.Admin); | ||||
| }; | ||||
| @ -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<string, string>; | ||||
| 
 | ||||
| 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, | ||||
|           }, | ||||
|         ]), | ||||
|       ], | ||||
|     }, | ||||
|   ], | ||||
| }; | ||||
| @ -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<EndpointHomeFolder>( | ||||
|         ({ 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); | ||||
							
								
								
									
										77
									
								
								src/collections/WebsiteConfig/WebsiteConfig.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/collections/WebsiteConfig/WebsiteConfig.ts
									
									
									
									
									
										Normal file
									
								
							| @ -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<string, string>; | ||||
| 
 | ||||
| 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 }, | ||||
|           ], | ||||
|         }, | ||||
|       ], | ||||
|     }, | ||||
|   ], | ||||
| }; | ||||
							
								
								
									
										51
									
								
								src/collections/WebsiteConfig/endpoints/getConfigEndpoint.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/collections/WebsiteConfig/endpoints/getConfigEndpoint.ts
									
									
									
									
									
										Normal file
									
								
							| @ -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); | ||||
|   }, | ||||
| }; | ||||
| @ -58,7 +58,6 @@ export const Wordings: CollectionConfig = buildCollectionConfig({ | ||||
|       name: fields.translations, | ||||
|       minRows: 1, | ||||
|       required: true, | ||||
|       interfaceName: "CategoryTranslations", | ||||
|       admin: { | ||||
|         useAsTitle: fields.translationsName, | ||||
|       }, | ||||
|  | ||||
| @ -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", | ||||
|  | ||||
| @ -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"), | ||||
|  | ||||
							
								
								
									
										20
									
								
								src/sdk.ts
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								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<EndpointHomeFolder[]> => | ||||
|     await (await request(payloadApiUrl(Collections.HomeFolders, `all`, true))).json(), | ||||
|   getConfig: async (): Promise<EndpointWebsiteConfig> => | ||||
|     await (await request(payloadApiUrl(Collections.WebsiteConfig, `config`, true))).json(), | ||||
|   getFolder: async (slug: string): Promise<EndpointFolder> => | ||||
|     await (await request(payloadApiUrl(Collections.Folders, `slug/${slug}`))).json(), | ||||
|   getLanguages: async (): Promise<Language[]> => | ||||
|  | ||||
| @ -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; | ||||
| } | ||||
|  | ||||
| @ -1,6 +1,3 @@ | ||||
| import { Endpoint } from "payload/config"; | ||||
| import { PayloadRequest } from "payload/types"; | ||||
| 
 | ||||
| export type CollectionEndpoint = Omit<Endpoint, "root">; | ||||
| 
 | ||||
| export type EndpointAccess<U> = (req: PayloadRequest<U>) => boolean; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 DrMint
						DrMint