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);
|
|
@ -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 },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
|
@ -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"),
|
||||
|
|
16
src/sdk.ts
16
src/sdk.ts
|
@ -129,9 +129,19 @@ export type EndpointFolder = EndpointFolderPreview & {
|
|||
parentPages: EndpointSource[];
|
||||
};
|
||||
|
||||
export type EndpointHomeFolder = EndpointFolderPreview & {
|
||||
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…
Reference in New Issue