Streamlined collection config
This commit is contained in:
		
							parent
							
								
									0a45ebb134
								
							
						
					
					
						commit
						65286f0c66
					
				| @ -1,9 +1,8 @@ | ||||
| import { CollectionConfig } from "payload/types"; | ||||
| import { slugField } from "../../fields/slugField/slugField"; | ||||
| import { CollectionGroup, KeysTypes } from "../../constants"; | ||||
| import { CollectionGroup } from "../../constants"; | ||||
| import { localizedFields } from "../../fields/translatedFields/translatedFields"; | ||||
| import { collectionSlug } from "../../utils/string"; | ||||
| import { Contents } from "../Contents/Contents"; | ||||
| import { buildCollectionConfig } from "../../utils/collectionConfig"; | ||||
| 
 | ||||
| const fields = { | ||||
|   slug: "slug", | ||||
| @ -13,17 +12,12 @@ const fields = { | ||||
|   contents: "contents", | ||||
| } as const satisfies Record<string, string>; | ||||
| 
 | ||||
| const labels = { | ||||
| export const ContentFolders = buildCollectionConfig( | ||||
|   { | ||||
|     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 }, | ||||
|   }, | ||||
|   ({ slug }) => ({ | ||||
|     defaultSort: fields.slug, | ||||
|     admin: { | ||||
|       useAsTitle: fields.slug, | ||||
| @ -62,4 +56,5 @@ export const ContentFolders: CollectionConfig = { | ||||
|         ], | ||||
|       }, | ||||
|     ], | ||||
| }; | ||||
|   }) | ||||
| ); | ||||
|  | ||||
| @ -1,6 +1,5 @@ | ||||
| import { CollectionConfig } from "payload/types"; | ||||
| import { CollectionGroup } from "../../constants"; | ||||
| import { collectionSlug } from "../../utils/string"; | ||||
| import { buildCollectionConfig } from "../../utils/collectionConfig"; | ||||
| 
 | ||||
| const fields = { | ||||
|   filename: "filename", | ||||
| @ -8,21 +7,17 @@ const fields = { | ||||
|   filesize: "filesize", | ||||
| } as const satisfies Record<string, string>; | ||||
| 
 | ||||
| const labels = { | ||||
| export const ContentThumbnails = buildCollectionConfig( | ||||
|   { | ||||
|     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 }, | ||||
|   }, | ||||
|   ({ labels }) => ({ | ||||
|     defaultSort: fields.filename, | ||||
|     admin: { | ||||
|       useAsTitle: fields.filename, | ||||
|       group: CollectionGroup.Media, | ||||
|     }, | ||||
| 
 | ||||
|     upload: { | ||||
|       staticDir: `../uploads/${labels.plural}`, | ||||
|       mimeTypes: ["image/*"], | ||||
| @ -47,6 +42,6 @@ export const ContentThumbnails: CollectionConfig = { | ||||
|         }, | ||||
|       ], | ||||
|     }, | ||||
| 
 | ||||
|     fields: [], | ||||
| }; | ||||
|   }) | ||||
| ); | ||||
|  | ||||
| @ -1,5 +1,3 @@ | ||||
| import { CollectionConfig } from "payload/types"; | ||||
| import { collectionSlug } from "../../utils/string"; | ||||
| import { CollectionGroup, FileTypes, KeysTypes } from "../../constants"; | ||||
| import { slugField } from "../../fields/slugField/slugField"; | ||||
| import { imageField } from "../../fields/imageField/imageField"; | ||||
| @ -10,6 +8,7 @@ import { isDefined } from "../../utils/asserts"; | ||||
| import { fileField } from "../../fields/fileField/fileField"; | ||||
| import { contentBlocks } from "./Blocks/blocks"; | ||||
| import { ContentThumbnails } from "../ContentThumbnails/ContentThumbnails"; | ||||
| import { buildVersionedCollectionConfig } from "../../utils/versionedCollectionConfig"; | ||||
| 
 | ||||
| const fields = { | ||||
|   slug: "slug", | ||||
| @ -31,20 +30,20 @@ const fields = { | ||||
|   audio: "audio", | ||||
|   audioNotes: "videoNotes", | ||||
|   status: "status", | ||||
|   updatedBy: "updatedBy", | ||||
| } as const satisfies Record<string, string>; | ||||
| 
 | ||||
| const labels = { | ||||
| export const Contents = buildVersionedCollectionConfig( | ||||
|   { | ||||
|     singular: "Content", | ||||
|     plural: "Contents", | ||||
| } as const satisfies { singular: string; plural: string }; | ||||
| 
 | ||||
| export const Contents: CollectionConfig = { | ||||
|   slug: collectionSlug(labels.plural), | ||||
|   labels, | ||||
|   typescript: { interface: labels.singular }, | ||||
|   }, | ||||
|   () => ({ | ||||
|     defaultSort: fields.slug, | ||||
|     admin: { | ||||
|       useAsTitle: fields.slug, | ||||
|       description: | ||||
|         "All the contents (textual, audio, and video) from the Library or other online sources.", | ||||
|       defaultColumns: [ | ||||
|         fields.slug, | ||||
|         fields.thumbnail, | ||||
| @ -56,8 +55,6 @@ export const Contents: CollectionConfig = { | ||||
|       group: CollectionGroup.Collections, | ||||
|       preview: (doc) => `https://accords-library.com/contents/${doc.slug}`, | ||||
|     }, | ||||
|   timestamps: true, | ||||
|   versions: { drafts: { autosave: true } }, | ||||
|     fields: [ | ||||
|       { | ||||
|         type: "row", | ||||
| @ -214,4 +211,5 @@ export const Contents: CollectionConfig = { | ||||
|         ], | ||||
|       }), | ||||
|     ], | ||||
| }; | ||||
|   }) | ||||
| ); | ||||
|  | ||||
| @ -1,27 +1,22 @@ | ||||
| import { CollectionConfig } from "payload/types"; | ||||
| import { CollectionGroup, FileTypes } from "../../constants"; | ||||
| import { collectionSlug } from "../../utils/string"; | ||||
| import { buildCollectionConfig } from "../../utils/collectionConfig"; | ||||
| 
 | ||||
| const fields = { | ||||
|   filename: "filename", | ||||
|   type: "type", | ||||
| } as const satisfies Record<string, string>; | ||||
| 
 | ||||
| const labels = { | ||||
| export const Files = buildCollectionConfig( | ||||
|   { | ||||
|     singular: "File", | ||||
|     plural: "Files", | ||||
| } as const satisfies { singular: string; plural: string }; | ||||
| 
 | ||||
| export const Files: CollectionConfig = { | ||||
|   slug: collectionSlug(labels.plural), | ||||
|   labels, | ||||
|   typescript: { interface: labels.singular }, | ||||
|   }, | ||||
|   () => ({ | ||||
|     defaultSort: fields.filename, | ||||
|     admin: { | ||||
|       useAsTitle: fields.filename, | ||||
|       group: CollectionGroup.Media, | ||||
|     }, | ||||
| 
 | ||||
|     fields: [ | ||||
|       { | ||||
|         name: fields.filename, | ||||
| @ -35,4 +30,5 @@ export const Files: CollectionConfig = { | ||||
|         options: Object.entries(FileTypes).map(([value, label]) => ({ label, value })), | ||||
|       }, | ||||
|     ], | ||||
| }; | ||||
|   }) | ||||
| ); | ||||
|  | ||||
| @ -2,9 +2,9 @@ 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 { Key } from "../../types/collections"; | ||||
| import { isDefined } from "../../utils/asserts"; | ||||
| import { buildCollectionConfig } from "../../utils/collectionConfig"; | ||||
| 
 | ||||
| const fields = { | ||||
|   slug: "slug", | ||||
| @ -14,17 +14,14 @@ const fields = { | ||||
|   short: "short", | ||||
| } as const satisfies Record<string, string>; | ||||
| 
 | ||||
| const labels = { | ||||
|   singular: "Key", | ||||
|   plural: "Keys", | ||||
| } as const satisfies { singular: string; plural: string }; | ||||
| 
 | ||||
| const keysTypesWithShort: (keyof typeof KeysTypes)[] = ["Categories", "GamePlatforms"]; | ||||
| 
 | ||||
| export const Keys: CollectionConfig = { | ||||
|   slug: collectionSlug(labels.plural), | ||||
|   labels, | ||||
|   typescript: { interface: labels.singular }, | ||||
| export const Keys: CollectionConfig = buildCollectionConfig( | ||||
|   { | ||||
|     singular: "Key", | ||||
|     plural: "Keys", | ||||
|   }, | ||||
|   () => ({ | ||||
|     defaultSort: fields.slug, | ||||
|     admin: { | ||||
|       useAsTitle: fields.slug, | ||||
| @ -66,4 +63,5 @@ export const Keys: CollectionConfig = { | ||||
|         ], | ||||
|       }), | ||||
|     ], | ||||
| }; | ||||
|   }) | ||||
| ); | ||||
|  | ||||
| @ -1,21 +1,17 @@ | ||||
| import { CollectionConfig } from "payload/types"; | ||||
| import { CollectionGroup } from "../constants"; | ||||
| import { collectionSlug } from "../utils/string"; | ||||
| import { buildCollectionConfig } from "../utils/collectionConfig"; | ||||
| 
 | ||||
| const fields = { | ||||
|   id: "id", | ||||
|   name: "name", | ||||
| } as const satisfies Record<string, string>; | ||||
| 
 | ||||
| const labels = { | ||||
| export const Languages = buildCollectionConfig( | ||||
|   { | ||||
|     singular: "Language", | ||||
|     plural: "Languages", | ||||
| } as const satisfies { singular: string; plural: string }; | ||||
| 
 | ||||
| export const Languages: CollectionConfig = { | ||||
|   slug: collectionSlug(labels.plural), | ||||
|   labels, | ||||
|   typescript: { interface: labels.singular }, | ||||
|   }, | ||||
|   () => ({ | ||||
|     defaultSort: fields.name, | ||||
|     admin: { | ||||
|       useAsTitle: fields.name, | ||||
| @ -43,4 +39,5 @@ export const Languages: CollectionConfig = { | ||||
|         required: true, | ||||
|       }, | ||||
|     ], | ||||
| }; | ||||
|   }) | ||||
| ); | ||||
|  | ||||
| @ -1,6 +1,5 @@ | ||||
| import { CollectionConfig } from "payload/types"; | ||||
| import { CollectionGroup } from "../../constants"; | ||||
| import { collectionSlug } from "../../utils/string"; | ||||
| import { buildCollectionConfig } from "../../utils/collectionConfig"; | ||||
| 
 | ||||
| const fields = { | ||||
|   filename: "filename", | ||||
| @ -8,21 +7,17 @@ const fields = { | ||||
|   filesize: "filesize", | ||||
| } as const satisfies Record<string, string>; | ||||
| 
 | ||||
| const labels = { | ||||
| export const LibraryItemThumbnails = buildCollectionConfig( | ||||
|   { | ||||
|     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 }, | ||||
|   }, | ||||
|   ({ labels }) => ({ | ||||
|     defaultSort: fields.filename, | ||||
|     admin: { | ||||
|       useAsTitle: fields.filename, | ||||
|       group: CollectionGroup.Media, | ||||
|     }, | ||||
| 
 | ||||
|     upload: { | ||||
|       staticDir: `../uploads/${labels.plural}`, | ||||
|       mimeTypes: ["image/*"], | ||||
| @ -59,6 +54,6 @@ export const LibraryItemThumbnails: CollectionConfig = { | ||||
|         }, | ||||
|       ], | ||||
|     }, | ||||
| 
 | ||||
|     fields: [], | ||||
| }; | ||||
|   }) | ||||
| ); | ||||
|  | ||||
| @ -1,4 +1,3 @@ | ||||
| import { CollectionConfig } from "payload/types"; | ||||
| import { | ||||
|   CollectionGroup, | ||||
|   KeysTypes, | ||||
| @ -8,12 +7,12 @@ import { | ||||
| } from "../../constants"; | ||||
| import { slugField } from "../../fields/slugField/slugField"; | ||||
| import { imageField } from "../../fields/imageField/imageField"; | ||||
| import { collectionSlug } from "../../utils/string"; | ||||
| 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"; | ||||
| import { buildVersionedCollectionConfig } from "../../utils/versionedCollectionConfig"; | ||||
| 
 | ||||
| const fields = { | ||||
|   status: "status", | ||||
| @ -42,11 +41,6 @@ const fields = { | ||||
|   audioSubtype: "audioSubtype", | ||||
| } as const satisfies Record<string, string>; | ||||
| 
 | ||||
| const labels = { | ||||
|   singular: "Library Item", | ||||
|   plural: "Library Items", | ||||
| } as const satisfies { singular: string; plural: string }; | ||||
| 
 | ||||
| const validateSizeValue = (value?: number) => { | ||||
|   if (isDefined(value) && value <= 0) return "This value must be greater than 0"; | ||||
|   return true; | ||||
| @ -58,19 +52,22 @@ const validateRequiredSizeValue = (value?: number) => { | ||||
|   return true; | ||||
| }; | ||||
| 
 | ||||
| export const LibraryItems: CollectionConfig = { | ||||
|   slug: collectionSlug(labels.plural), | ||||
|   labels, | ||||
|   typescript: { interface: labels.singular }, | ||||
| export const LibraryItems = buildVersionedCollectionConfig( | ||||
|   { | ||||
|     singular: "Library Item", | ||||
|     plural: "Library Items", | ||||
|   }, | ||||
|   () => ({ | ||||
|     defaultSort: fields.slug, | ||||
|     admin: { | ||||
|       useAsTitle: fields.slug, | ||||
|       description: | ||||
|         "A comprehensive list of all Yokoverse’s side materials (books, novellas, artbooks, \ | ||||
| stage plays, manga, drama CDs, and comics).", | ||||
|       defaultColumns: [fields.slug, fields.thumbnail, fields.status], | ||||
|       group: CollectionGroup.Collections, | ||||
|       preview: (doc) => `https://accords-library.com/library/${doc.slug}`, | ||||
|     }, | ||||
|   timestamps: true, | ||||
|   versions: { drafts: { autosave: true } }, | ||||
|     fields: [ | ||||
|       { | ||||
|         type: "row", | ||||
| @ -270,4 +267,5 @@ export const LibraryItems: CollectionConfig = { | ||||
|         }, | ||||
|       }, | ||||
|     ], | ||||
| }; | ||||
|   }) | ||||
| ); | ||||
|  | ||||
| @ -1,6 +1,5 @@ | ||||
| import { CollectionConfig } from "payload/types"; | ||||
| import { CollectionGroup } from "../../constants"; | ||||
| import { collectionSlug } from "../../utils/string"; | ||||
| import { buildCollectionConfig } from "../../utils/collectionConfig"; | ||||
| 
 | ||||
| const fields = { | ||||
|   filename: "filename", | ||||
| @ -8,21 +7,17 @@ const fields = { | ||||
|   filesize: "filesize", | ||||
| } as const satisfies Record<string, string>; | ||||
| 
 | ||||
| const labels = { | ||||
| export const PostThumbnails = buildCollectionConfig( | ||||
|   { | ||||
|     singular: "Post Thumbnail", | ||||
|     plural: "Post Thumbnails", | ||||
| } as const satisfies { singular: string; plural: string }; | ||||
| 
 | ||||
| export const PostThumbnails: CollectionConfig = { | ||||
|   slug: collectionSlug(labels.plural), | ||||
|   labels, | ||||
|   typescript: { interface: labels.singular }, | ||||
|   }, | ||||
|   ({ labels }) => ({ | ||||
|     defaultSort: fields.filename, | ||||
|     admin: { | ||||
|       useAsTitle: fields.filename, | ||||
|       group: CollectionGroup.Media, | ||||
|     }, | ||||
| 
 | ||||
|     upload: { | ||||
|       staticDir: `../uploads/${labels.plural}`, | ||||
|       mimeTypes: ["image/*"], | ||||
| @ -47,6 +42,6 @@ export const PostThumbnails: CollectionConfig = { | ||||
|         }, | ||||
|       ], | ||||
|     }, | ||||
| 
 | ||||
|     fields: [], | ||||
| }; | ||||
|   }) | ||||
| ); | ||||
|  | ||||
| @ -1,4 +1,3 @@ | ||||
| import { CollectionConfig } from "payload/types"; | ||||
| import { slugField } from "../../fields/slugField/slugField"; | ||||
| import { imageField } from "../../fields/imageField/imageField"; | ||||
| import { CollectionGroup, KeysTypes } from "../../constants"; | ||||
| @ -7,8 +6,8 @@ import { localizedFields } from "../../fields/translatedFields/translatedFields" | ||||
| import { isDefined, isUndefined } from "../../utils/asserts"; | ||||
| import { removeTranslatorsForTranscripts } from "./hooks/beforeValidate"; | ||||
| import { Keys } from "../Keys/Keys"; | ||||
| import { collectionSlug } from "../../utils/string"; | ||||
| import { PostThumbnails } from "../PostThumbnails/PostThumbnails"; | ||||
| import { buildVersionedCollectionConfig } from "../../utils/versionedCollectionConfig"; | ||||
| 
 | ||||
| const fields = { | ||||
|   slug: "slug", | ||||
| @ -26,18 +25,18 @@ const fields = { | ||||
|   proofreaders: "proofreaders", | ||||
| } as const satisfies Record<string, string>; | ||||
| 
 | ||||
| const labels = { | ||||
| export const Posts = buildVersionedCollectionConfig( | ||||
|   { | ||||
|     singular: "Post", | ||||
|     plural: "Posts", | ||||
| } as const satisfies { singular: string; plural: string }; | ||||
| 
 | ||||
| export const Posts: CollectionConfig = { | ||||
|   slug: collectionSlug(labels.plural), | ||||
|   labels, | ||||
|   typescript: { interface: labels.singular }, | ||||
|   }, | ||||
|   () => ({ | ||||
|     defaultSort: fields.slug, | ||||
|     admin: { | ||||
|       useAsTitle: fields.slug, | ||||
|       description: | ||||
|         "News articles written by our Recorders! Here you will find announcements about \ | ||||
| new merch/items releases, guides, theories, unboxings, showcases...", | ||||
|       defaultColumns: [fields.slug, fields.thumbnail, fields.categories], | ||||
|       group: CollectionGroup.Collections, | ||||
|       preview: (doc) => `https://accords-library.com/news/${doc.slug}`, | ||||
| @ -45,8 +44,6 @@ export const Posts: CollectionConfig = { | ||||
|     hooks: { | ||||
|       beforeValidate: [removeTranslatorsForTranscripts], | ||||
|     }, | ||||
|   timestamps: true, | ||||
|   versions: { drafts: { autosave: true } }, | ||||
|     fields: [ | ||||
|       { | ||||
|         type: "row", | ||||
| @ -110,7 +107,10 @@ export const Posts: CollectionConfig = { | ||||
|                   width: "50%", | ||||
|                 }, | ||||
|                 validate: (translators, { siblingData }) => { | ||||
|                 if (isUndefined(siblingData.language) || isUndefined(siblingData.sourceLanguage)) { | ||||
|                   if ( | ||||
|                     isUndefined(siblingData.language) || | ||||
|                     isUndefined(siblingData.sourceLanguage) | ||||
|                   ) { | ||||
|                     return true; | ||||
|                   } | ||||
|                   if (siblingData.language === siblingData.sourceLanguage) { | ||||
| @ -155,4 +155,5 @@ export const Posts: CollectionConfig = { | ||||
|         }, | ||||
|       }, | ||||
|     ], | ||||
| }; | ||||
|   }) | ||||
| ); | ||||
|  | ||||
| @ -5,7 +5,7 @@ export const removeTranslatorsForTranscripts: CollectionBeforeValidateHook<Post> | ||||
|   data: { translations, ...data }, | ||||
| }) => ({ | ||||
|   ...data, | ||||
|   translations: translations.map(({ translators, ...translation }) => { | ||||
|   translations: translations?.map(({ translators, ...translation }) => { | ||||
|     if (translation.language === translation.sourceLanguage) { | ||||
|       return { ...translation, translators: [] }; | ||||
|     } | ||||
|  | ||||
| @ -1,6 +1,5 @@ | ||||
| import { CollectionConfig } from "payload/types"; | ||||
| import { CollectionGroup } from "../../constants"; | ||||
| import { collectionSlug } from "../../utils/string"; | ||||
| import { buildCollectionConfig } from "../../utils/collectionConfig"; | ||||
| 
 | ||||
| const fields = { | ||||
|   filename: "filename", | ||||
| @ -8,21 +7,17 @@ const fields = { | ||||
|   filesize: "filesize", | ||||
| } as const satisfies Record<string, string>; | ||||
| 
 | ||||
| const labels = { | ||||
| export const RecorderThumbnails = buildCollectionConfig( | ||||
|   { | ||||
|     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 }, | ||||
|   }, | ||||
|   ({ labels }) => ({ | ||||
|     defaultSort: fields.filename, | ||||
|     admin: { | ||||
|       useAsTitle: fields.filename, | ||||
|       group: CollectionGroup.Media, | ||||
|     }, | ||||
| 
 | ||||
|     upload: { | ||||
|       staticDir: `../uploads/${labels.plural}`, | ||||
|       adminThumbnail: "small", | ||||
| @ -48,6 +43,6 @@ export const RecorderThumbnails: CollectionConfig = { | ||||
|         }, | ||||
|       ], | ||||
|     }, | ||||
| 
 | ||||
|     fields: [], | ||||
| }; | ||||
|   }) | ||||
| ); | ||||
|  | ||||
| @ -1,11 +1,10 @@ | ||||
| import { CollectionConfig } from "payload/types"; | ||||
| import { localizedFields } from "../../fields/translatedFields/translatedFields"; | ||||
| import { Languages } from "../Languages"; | ||||
| import { beforeDuplicate } from "./hooks/beforeDuplicate"; | ||||
| import { CollectionGroup } from "../../constants"; | ||||
| import { collectionSlug } from "../../utils/string"; | ||||
| import { RecorderThumbnails } from "../RecorderThumbnails/RecorderThumbnails"; | ||||
| import { imageField } from "../../fields/imageField/imageField"; | ||||
| import { buildCollectionConfig } from "../../utils/collectionConfig"; | ||||
| 
 | ||||
| const fields = { | ||||
|   username: "username", | ||||
| @ -16,15 +15,12 @@ const fields = { | ||||
|   avatar: "avatar", | ||||
| } as const satisfies Record<string, string>; | ||||
| 
 | ||||
| const labels = { | ||||
| export const Recorders = buildCollectionConfig( | ||||
|   { | ||||
|     singular: "Recorder", | ||||
|     plural: "Recorders", | ||||
| } as const satisfies { singular: string; plural: string }; | ||||
| 
 | ||||
| export const Recorders: CollectionConfig = { | ||||
|   slug: collectionSlug(labels.plural), | ||||
|   labels, | ||||
|   typescript: { interface: labels.singular }, | ||||
|   }, | ||||
|   () => ({ | ||||
|     defaultSort: fields.username, | ||||
|     admin: { | ||||
|       useAsTitle: fields.username, | ||||
| @ -91,4 +87,5 @@ export const Recorders: CollectionConfig = { | ||||
|         }, | ||||
|       }, | ||||
|     ], | ||||
| }; | ||||
|   }) | ||||
| ); | ||||
|  | ||||
| @ -1,27 +1,60 @@ | ||||
| import { CollectionConfig } from "payload/types"; | ||||
| import { CollectionGroup } from "../constants"; | ||||
| import { collectionSlug } from "../utils/string"; | ||||
| import { CollectionGroup, UserRoles } from "../constants"; | ||||
| import { Recorders } from "./Recorders/Recorders"; | ||||
| import { buildCollectionConfig } from "../utils/collectionConfig"; | ||||
| 
 | ||||
| const fields = { | ||||
|   recorder: "recorder", | ||||
|   name: "name", | ||||
|   email: "email", | ||||
|   role: "role", | ||||
| } as const satisfies Record<string, string>; | ||||
| 
 | ||||
| const labels = { | ||||
| export const Users = buildCollectionConfig( | ||||
|   { | ||||
|     singular: "User", | ||||
|     plural: "Users", | ||||
| } as const satisfies { singular: string; plural: string }; | ||||
| 
 | ||||
| export const Users: CollectionConfig = { | ||||
|   slug: collectionSlug(labels.plural), | ||||
|   }, | ||||
|   () => ({ | ||||
|     auth: true, | ||||
|   labels, | ||||
|   typescript: { interface: labels.singular }, | ||||
|   defaultSort: fields.email, | ||||
|     defaultSort: fields.recorder, | ||||
|     admin: { | ||||
|     useAsTitle: fields.email, | ||||
|     defaultColumns: [fields.email], | ||||
|       useAsTitle: fields.name, | ||||
|       defaultColumns: [fields.recorder, fields.name, fields.email, fields.role], | ||||
|       group: CollectionGroup.Administration, | ||||
|     }, | ||||
|     timestamps: false, | ||||
|   fields: [], | ||||
| }; | ||||
|     fields: [ | ||||
|       { | ||||
|         type: "row", | ||||
|         fields: [ | ||||
|           { | ||||
|             name: fields.recorder, | ||||
|             type: "relationship", | ||||
|             relationTo: Recorders.slug, | ||||
|             required: true, | ||||
|             admin: { width: "33%" }, | ||||
|           }, | ||||
|           { | ||||
|             name: fields.name, | ||||
|             type: "text", | ||||
|             required: true, | ||||
|             unique: true, | ||||
|             admin: { width: "33%" }, | ||||
|           }, | ||||
|           { | ||||
|             name: fields.role, | ||||
|             required: true, | ||||
|             defaultValue: [UserRoles.Recorder], | ||||
|             type: "select", | ||||
|             hasMany: true, | ||||
|             options: Object.entries(UserRoles).map(([value, label]) => ({ | ||||
|               label, | ||||
|               value, | ||||
|             })), | ||||
|             admin: { width: "33%" }, | ||||
|           }, | ||||
|         ], | ||||
|       }, | ||||
|     ], | ||||
|   }) | ||||
| ); | ||||
|  | ||||
| @ -42,3 +42,8 @@ export enum LibraryItemsTextualPageOrders { | ||||
|   LeftToRight = "Left to right", | ||||
|   RightToLeft = "Right to left", | ||||
| } | ||||
| 
 | ||||
| export enum UserRoles { | ||||
|   Admin = "Admin", | ||||
|   Recorder = "Recorder", | ||||
| } | ||||
|  | ||||
| @ -1,11 +1,13 @@ | ||||
| import { Props } from "payload/components/views/Cell"; | ||||
| import { useState, useEffect } from "react"; | ||||
| import React from "react"; | ||||
| import { isUndefined } from "../../utils/asserts"; | ||||
| 
 | ||||
| export const Cell = ({ cellData, field }: Props): JSX.Element => { | ||||
|   const [imageURL, setImageURL] = useState<string>(); | ||||
|   useEffect(() => { | ||||
|     const fetchUrl = async () => { | ||||
|       if (isUndefined(cellData)) return; | ||||
|       if (typeof cellData !== "string") return; | ||||
|       if (field.type !== "upload") return; | ||||
|       const result = await (await fetch(`/api/${field.relationTo}/${cellData}`)).json(); | ||||
|  | ||||
| @ -44,10 +44,11 @@ export const localizedFields = ({ | ||||
|     components: { | ||||
|       Cell: ({ cellData }) => | ||||
|         Cell({ | ||||
|           cellData: cellData.map((row) => ({ | ||||
|           cellData: | ||||
|             cellData?.map((row) => ({ | ||||
|               language: row.language, | ||||
|               title: isDefined(useAsTitle) ? row[useAsTitle] : undefined, | ||||
|           })), | ||||
|             })) ?? [], | ||||
|         }), | ||||
|       RowLabel: ({ data }) => | ||||
|         RowLabel({ | ||||
|  | ||||
| @ -93,6 +93,7 @@ export interface LibraryItem { | ||||
|         }[]; | ||||
|   }; | ||||
|   releaseDate?: string; | ||||
|   lastModifiedBy: string | User; | ||||
|   updatedAt: string; | ||||
|   createdAt: string; | ||||
|   _status?: "draft" | "published"; | ||||
| @ -154,6 +155,57 @@ export interface Language { | ||||
|   id: string; | ||||
|   name: string; | ||||
| } | ||||
| export interface User { | ||||
|   id: string; | ||||
|   recorder: string | Recorder; | ||||
|   name: string; | ||||
|   role: ("Admin" | "Recorder")[]; | ||||
|   email: string; | ||||
|   resetPasswordToken?: string; | ||||
|   resetPasswordExpiration?: string; | ||||
|   salt?: string; | ||||
|   hash?: string; | ||||
|   loginAttempts?: number; | ||||
|   lockUntil?: string; | ||||
|   password?: string; | ||||
| } | ||||
| export interface Recorder { | ||||
|   id: string; | ||||
|   username: string; | ||||
|   avatar?: string | RecorderThumbnail; | ||||
|   languages?: string[] | Language[]; | ||||
|   biographies?: RecorderBiographies; | ||||
|   anonymize: boolean; | ||||
| } | ||||
| export interface RecorderThumbnail { | ||||
|   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; | ||||
|     }; | ||||
|     small?: { | ||||
|       url?: string; | ||||
|       width?: number; | ||||
|       height?: number; | ||||
|       mimeType?: string; | ||||
|       filesize?: number; | ||||
|       filename?: string; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
| export interface Content { | ||||
|   id: string; | ||||
|   slug: string; | ||||
| @ -188,6 +240,7 @@ export interface Content { | ||||
|     audio?: string | File; | ||||
|     id?: string; | ||||
|   }[]; | ||||
|   lastModifiedBy: string | User; | ||||
|   updatedAt: string; | ||||
|   createdAt: string; | ||||
|   _status?: "draft" | "published"; | ||||
| @ -221,43 +274,6 @@ export interface ContentThumbnail { | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
| export interface Recorder { | ||||
|   id: string; | ||||
|   username: string; | ||||
|   avatar?: string | RecorderThumbnail; | ||||
|   languages?: string[] | Language[]; | ||||
|   biographies?: RecorderBiographies; | ||||
|   anonymize: boolean; | ||||
| } | ||||
| export interface RecorderThumbnail { | ||||
|   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; | ||||
|     }; | ||||
|     small?: { | ||||
|       url?: string; | ||||
|       width?: number; | ||||
|       height?: number; | ||||
|       mimeType?: string; | ||||
|       filesize?: number; | ||||
|       filename?: string; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
| export interface TextBlock { | ||||
|   content: { | ||||
|     [k: string]: unknown; | ||||
| @ -511,6 +527,7 @@ export interface Post { | ||||
|   }[]; | ||||
|   publishedDate: string; | ||||
|   hidden?: boolean; | ||||
|   lastModifiedBy: string | User; | ||||
|   updatedAt: string; | ||||
|   createdAt: string; | ||||
|   _status?: "draft" | "published"; | ||||
| @ -544,14 +561,3 @@ export interface PostThumbnail { | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
| export interface User { | ||||
|   id: string; | ||||
|   email: string; | ||||
|   resetPasswordToken?: string; | ||||
|   resetPasswordExpiration?: string; | ||||
|   salt?: string; | ||||
|   hash?: string; | ||||
|   loginAttempts?: number; | ||||
|   lockUntil?: string; | ||||
|   password?: string; | ||||
| } | ||||
|  | ||||
							
								
								
									
										22
									
								
								src/utils/collectionConfig.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/utils/collectionConfig.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| import { CollectionConfig } from "payload/types"; | ||||
| import slugify from "slugify"; | ||||
| 
 | ||||
| export type BuildCollectionConfig = Omit<CollectionConfig, "slug" | "typescript" | "labels">; | ||||
| 
 | ||||
| export type GenerationFunctionProps = { | ||||
|   labels: { singular: string; plural: string }; | ||||
|   slug: string; | ||||
| }; | ||||
| 
 | ||||
| export const buildCollectionConfig = ( | ||||
|   labels: { singular: string; plural: string }, | ||||
|   generationFunction: (props: GenerationFunctionProps) => BuildCollectionConfig | ||||
| ): CollectionConfig => { | ||||
|   const slug = slugify(labels.plural, { lower: true, strict: true, trim: true }); | ||||
|   const config = generationFunction({ labels, slug }); | ||||
|   return { | ||||
|     ...config, | ||||
|     slug, | ||||
|     typescript: { interface: labels.singular }, | ||||
|   }; | ||||
| }; | ||||
| @ -1,11 +1,7 @@ | ||||
| import ISO6391 from "iso-639-1"; | ||||
| import slugify from "slugify"; | ||||
| 
 | ||||
| export const shortenEllipsis = (text: string, length: number): string => | ||||
|   text.length - 3 > length ? `${text.substring(0, length)}...` : text; | ||||
| 
 | ||||
| export const formatLanguageCode = (code: string): string => | ||||
|   ISO6391.validate(code) ? ISO6391.getName(code) : code; | ||||
| 
 | ||||
| export const collectionSlug = (text: string): string => | ||||
|   slugify(text, { lower: true, strict: true, trim: true }); | ||||
|  | ||||
							
								
								
									
										52
									
								
								src/utils/versionedCollectionConfig.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/utils/versionedCollectionConfig.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | ||||
| import { CollectionBeforeChangeHook, CollectionConfig, RelationshipField } from "payload/types"; | ||||
| import { Users } from "../collections/Users"; | ||||
| import { | ||||
|   BuildCollectionConfig, | ||||
|   GenerationFunctionProps, | ||||
|   buildCollectionConfig, | ||||
| } from "./collectionConfig"; | ||||
| 
 | ||||
| const fields = { lastModifiedBy: "lastModifiedBy" }; | ||||
| 
 | ||||
| const beforeChangeLastModifiedBy: CollectionBeforeChangeHook = async ({ | ||||
|   data: { updatedBy, ...data }, | ||||
|   req, | ||||
| }) => { | ||||
|   console.log(data, req.user); | ||||
|   return { | ||||
|     ...data, | ||||
|     [fields.lastModifiedBy]: req.user.id, | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| const lastModifiedByField = (): RelationshipField => ({ | ||||
|   name: fields.lastModifiedBy, | ||||
|   type: "relationship", | ||||
|   required: true, | ||||
|   relationTo: Users.slug, | ||||
|   admin: { readOnly: true, position: "sidebar" }, | ||||
| }); | ||||
| 
 | ||||
| type BuildVersionedCollectionConfig = Omit<BuildCollectionConfig, "timestamps" | "versions">; | ||||
| 
 | ||||
| export const buildVersionedCollectionConfig = ( | ||||
|   labels: { singular: string; plural: string }, | ||||
|   generationFunction: (props: GenerationFunctionProps) => BuildVersionedCollectionConfig | ||||
| ): CollectionConfig => { | ||||
|   const { | ||||
|     hooks: { beforeChange, ...otherHooks } = {}, | ||||
|     fields, | ||||
|     ...otherParams | ||||
|   } = buildCollectionConfig(labels, generationFunction); | ||||
| 
 | ||||
|   return { | ||||
|     ...otherParams, | ||||
|     timestamps: true, | ||||
|     versions: { drafts: { autosave: { interval: 2000 } } }, | ||||
|     hooks: { | ||||
|       ...otherHooks, | ||||
|       beforeChange: [...(beforeChange ?? []), beforeChangeLastModifiedBy], | ||||
|     }, | ||||
|     fields: [...fields, lastModifiedByField()], | ||||
|   }; | ||||
| }; | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 DrMint
						DrMint