Simplified crediting
This commit is contained in:
		
							parent
							
								
									40e54ea2a0
								
							
						
					
					
						commit
						f46bdcaa03
					
				| @ -1,4 +1,5 @@ | ||||
| import { CollectionGroups, Collections } from "../../constants"; | ||||
| import { creditsField } from "../../fields/creditsField/creditsField"; | ||||
| import { imageField } from "../../fields/imageField/imageField"; | ||||
| import { rowField } from "../../fields/rowField/rowField"; | ||||
| import { tagsField } from "../../fields/tagsField/tagsField"; | ||||
| @ -18,6 +19,7 @@ const fields = { | ||||
|   thumbnail: "thumbnail", | ||||
|   duration: "duration", | ||||
|   tags: "tags", | ||||
|   credits: "credits", | ||||
| }; | ||||
| 
 | ||||
| export const Audios = buildCollectionConfig({ | ||||
| @ -63,5 +65,6 @@ export const Audios = buildCollectionConfig({ | ||||
|       ], | ||||
|     }), | ||||
|     tagsField({ name: fields.tags }), | ||||
|     creditsField({ name: fields.credits }), | ||||
|   ], | ||||
| }); | ||||
|  | ||||
| @ -5,6 +5,7 @@ import { Audio } from "../../../types/collections"; | ||||
| import { CollectionEndpoint } from "../../../types/payload"; | ||||
| import { isNotEmpty, isValidPayloadImage, isValidPayloadMedia } from "../../../utils/asserts"; | ||||
| import { | ||||
|   convertCreditsToEndpointCredits, | ||||
|   convertRTCToEndpointRTC, | ||||
|   convertTagsEndpointTagsGroups, | ||||
|   getLanguageId, | ||||
| @ -57,6 +58,7 @@ export const convertAudioToEndpointAudio = ({ | ||||
|   duration, | ||||
|   id, | ||||
|   thumbnail, | ||||
|   credits, | ||||
| }: Audio & PayloadMedia): EndpointAudio => ({ | ||||
|   url, | ||||
|   tagGroups: convertTagsEndpointTagsGroups(tags), | ||||
| @ -74,4 +76,5 @@ export const convertAudioToEndpointAudio = ({ | ||||
|     })) ?? [], | ||||
|   duration, | ||||
|   ...(isValidPayloadImage(thumbnail) ? { thumbnail } : {}), | ||||
|   credits: convertCreditsToEndpointCredits(credits), | ||||
| }); | ||||
|  | ||||
| @ -5,6 +5,7 @@ import { | ||||
|   publishStatusFilters, | ||||
| } from "../../components/QuickFilters"; | ||||
| import { CollectionGroups, Collections } from "../../constants"; | ||||
| import { creditsField } from "../../fields/creditsField/creditsField"; | ||||
| import { rowField } from "../../fields/rowField/rowField"; | ||||
| import { translatedFields } from "../../fields/translatedFields/translatedFields"; | ||||
| import { createEditor } from "../../utils/editor"; | ||||
| @ -28,6 +29,7 @@ const fields = { | ||||
|   eventsTranslationsTitle: "title", | ||||
|   eventsTranslationsDescription: "description", | ||||
|   eventsTranslationsNotes: "notes", | ||||
|   eventsCredits: "credits", | ||||
|   date: "date", | ||||
|   dateYear: "year", | ||||
|   dateMonth: "month", | ||||
| @ -119,7 +121,6 @@ export const ChronologyEvents: CollectionConfig = buildVersionedCollectionConfig | ||||
|           admin: { | ||||
|             useAsTitle: fields.eventsTranslationsTitle, | ||||
|             hasSourceLanguage: true, | ||||
|             hasCredits: true, | ||||
|           }, | ||||
|           fields: [ | ||||
|             { | ||||
| @ -138,6 +139,7 @@ export const ChronologyEvents: CollectionConfig = buildVersionedCollectionConfig | ||||
|               type: "richText", | ||||
|               editor: createEditor({ inlines: true, lists: true, links: true }), | ||||
|             }, | ||||
|             creditsField({ name: fields.eventsCredits }), | ||||
|           ], | ||||
|         }), | ||||
|       ], | ||||
|  | ||||
| @ -3,11 +3,10 @@ import { Collections } from "../../../constants"; | ||||
| import { EndpointChronologyEvent, EndpointSource } from "../../../sdk"; | ||||
| import { ChronologyEvent, CollectibleBlock } from "../../../types/collections"; | ||||
| import { CollectionEndpoint } from "../../../types/payload"; | ||||
| import { isDefined, isNotEmpty, isPayloadArrayType, isPayloadType } from "../../../utils/asserts"; | ||||
| import { getDomainFromUrl } from "../../../utils/endpoints"; | ||||
| import { isDefined, isNotEmpty, isPayloadType } from "../../../utils/asserts"; | ||||
| import { convertCreditsToEndpointCredits, getDomainFromUrl } from "../../../utils/endpoints"; | ||||
| import { convertCollectibleToEndpointCollectible } from "../../Collectibles/endpoints/getBySlugEndpoint"; | ||||
| import { convertPageToEndpointPage } from "../../Pages/endpoints/getBySlugEndpoint"; | ||||
| import { convertRecorderToEndpointRecorder } from "../../Recorders/endpoints/getByUsername"; | ||||
| 
 | ||||
| export const getAllEndpoint: CollectionEndpoint = { | ||||
|   method: "get", | ||||
| @ -68,30 +67,13 @@ export const eventToEndpointEvent = ({ | ||||
|   }, | ||||
|   events: events.map<EndpointChronologyEvent["events"][number]>(({ sources, translations }) => ({ | ||||
|     translations: translations.map( | ||||
|       ({ | ||||
|         language, | ||||
|         sourceLanguage, | ||||
|         description, | ||||
|         notes, | ||||
|         proofreaders, | ||||
|         title, | ||||
|         transcribers, | ||||
|         translators, | ||||
|       }) => ({ | ||||
|       ({ language, sourceLanguage, description, notes, title, credits }) => ({ | ||||
|         language: isPayloadType(language) ? language.id : language, | ||||
|         sourceLanguage: isPayloadType(sourceLanguage) ? sourceLanguage.id : sourceLanguage, | ||||
|         ...(isNotEmpty(title) ? { title } : {}), | ||||
|         ...(isNotEmpty(description) ? { description } : {}), | ||||
|         ...(isNotEmpty(notes) ? { notes } : {}), | ||||
|         proofreaders: isPayloadArrayType(proofreaders) | ||||
|           ? proofreaders.map(convertRecorderToEndpointRecorder) | ||||
|           : [], | ||||
|         transcribers: isPayloadArrayType(transcribers) | ||||
|           ? transcribers.map(convertRecorderToEndpointRecorder) | ||||
|           : [], | ||||
|         translators: isPayloadArrayType(translators) | ||||
|           ? translators.map(convertRecorderToEndpointRecorder) | ||||
|           : [], | ||||
|         credits: convertCreditsToEndpointCredits(credits), | ||||
|       }) | ||||
|     ), | ||||
|     sources: handleSources(sources), | ||||
|  | ||||
| @ -6,10 +6,10 @@ import { | ||||
|   CollectiblePageOrders, | ||||
|   CollectionGroups, | ||||
|   Collections, | ||||
|   PageType, | ||||
| } from "../../constants"; | ||||
| import { backPropagationField } from "../../fields/backPropagationField/backPropagationField"; | ||||
| import { componentField } from "../../fields/componentField/componentField"; | ||||
| import { creditsField } from "../../fields/creditsField/creditsField"; | ||||
| import { imageField } from "../../fields/imageField/imageField"; | ||||
| import { rowField } from "../../fields/rowField/rowField"; | ||||
| import { slugField } from "../../fields/slugField/slugField"; | ||||
| @ -54,9 +54,7 @@ const fields = { | ||||
|   urlsUrl: "url", | ||||
| 
 | ||||
|   scans: "scans", | ||||
|   scansScanners: "scanners", | ||||
|   scansCleaners: "cleaners", | ||||
|   scansTypesetters: "typesetters", | ||||
|   scansCredits: "credits", | ||||
| 
 | ||||
|   scansCover: "cover", | ||||
|   scansCoverFlapFront: "flapFront", | ||||
| @ -232,28 +230,7 @@ export const Collectibles = buildVersionedCollectionConfig({ | ||||
|             componentField({ | ||||
|               name: fields.scans, | ||||
|               fields: [ | ||||
|                 rowField([ | ||||
|                   { | ||||
|                     name: fields.scansScanners, | ||||
|                     type: "relationship", | ||||
|                     relationTo: Collections.Recorders, | ||||
|                     hasMany: true, | ||||
|                     required: true, | ||||
|                   }, | ||||
|                   { | ||||
|                     name: fields.scansCleaners, | ||||
|                     type: "relationship", | ||||
|                     relationTo: Collections.Recorders, | ||||
|                     hasMany: true, | ||||
|                     required: true, | ||||
|                   }, | ||||
|                   { | ||||
|                     name: fields.scansTypesetters, | ||||
|                     type: "relationship", | ||||
|                     relationTo: Collections.Recorders, | ||||
|                     hasMany: true, | ||||
|                   }, | ||||
|                 ]), | ||||
|                 creditsField({ name: fields.scansCredits }), | ||||
|                 componentField({ | ||||
|                   name: fields.scansCover, | ||||
|                   fields: [ | ||||
| @ -621,15 +598,6 @@ export const Collectibles = buildVersionedCollectionConfig({ | ||||
|                     allowCreate: false, | ||||
|                   }, | ||||
|                   required: true, | ||||
|                   filterOptions: ({ relationTo }) => { | ||||
|                     switch (relationTo) { | ||||
|                       case Collections.Pages: | ||||
|                         return { type: { equals: PageType.Content } }; | ||||
| 
 | ||||
|                       default: | ||||
|                         return true; | ||||
|                     } | ||||
|                   }, | ||||
|                 }, | ||||
|                 { | ||||
|                   name: "range", | ||||
|  | ||||
							
								
								
									
										34
									
								
								src/collections/CreditsRoles/CreditsRoles.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/collections/CreditsRoles/CreditsRoles.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| import { CollectionConfig } from "payload/types"; | ||||
| import { CollectionGroups, Collections } from "../../constants"; | ||||
| import { iconField } from "../../fields/iconField/iconField"; | ||||
| import { slugField } from "../../fields/slugField/slugField"; | ||||
| import { translatedFields } from "../../fields/translatedFields/translatedFields"; | ||||
| import { buildCollectionConfig } from "../../utils/collectionConfig"; | ||||
| 
 | ||||
| const fields = { | ||||
|   slug: "slug", | ||||
|   translations: "translations", | ||||
|   translationsName: "name", | ||||
|   icon: "icon", | ||||
| }; | ||||
| 
 | ||||
| export const CreditsRoles: CollectionConfig = buildCollectionConfig({ | ||||
|   slug: Collections.CreditsRole, | ||||
|   labels: { singular: "Credits Role", plural: "Credits Roles" }, | ||||
|   admin: { | ||||
|     group: CollectionGroups.Meta, | ||||
|     useAsTitle: fields.slug, | ||||
|     defaultColumns: [fields.slug, fields.translations], | ||||
|   }, | ||||
|   fields: [ | ||||
|     slugField({ name: fields.slug }), | ||||
|     iconField({ name: fields.icon }), | ||||
|     translatedFields({ | ||||
|       name: fields.translations, | ||||
|       admin: { useAsTitle: fields.translationsName }, | ||||
|       required: true, | ||||
|       minRows: 1, | ||||
|       fields: [{ name: fields.translationsName, type: "text", required: true }], | ||||
|     }), | ||||
|   ], | ||||
| }); | ||||
| @ -1,4 +1,5 @@ | ||||
| import { Collections } from "../../constants"; | ||||
| import { creditsField } from "../../fields/creditsField/creditsField"; | ||||
| import { tagsField } from "../../fields/tagsField/tagsField"; | ||||
| import { translatedFields } from "../../fields/translatedFields/translatedFields"; | ||||
| import { createEditor } from "../../utils/editor"; | ||||
| @ -15,6 +16,7 @@ const fields = { | ||||
|   translationsTitle: "title", | ||||
|   translationsDescription: "description", | ||||
|   tags: "tags", | ||||
|   credits: "credits", | ||||
| } as const satisfies Record<string, string>; | ||||
| 
 | ||||
| export const Images = buildImageCollectionConfig({ | ||||
| @ -52,5 +54,6 @@ export const Images = buildImageCollectionConfig({ | ||||
|       ], | ||||
|     }), | ||||
|     tagsField({ name: fields.tags }), | ||||
|     creditsField({ name: fields.credits }), | ||||
|   ], | ||||
| }); | ||||
|  | ||||
| @ -5,6 +5,7 @@ import { Image } from "../../../types/collections"; | ||||
| import { CollectionEndpoint } from "../../../types/payload"; | ||||
| import { isNotEmpty, isValidPayloadImage } from "../../../utils/asserts"; | ||||
| import { | ||||
|   convertCreditsToEndpointCredits, | ||||
|   convertRTCToEndpointRTC, | ||||
|   convertTagsEndpointTagsGroups, | ||||
|   getLanguageId, | ||||
| @ -57,6 +58,7 @@ export const convertImageToEndpointImage = ({ | ||||
|   filename, | ||||
|   filesize, | ||||
|   id, | ||||
|   credits, | ||||
| }: Image & PayloadImage): EndpointImage => ({ | ||||
|   url, | ||||
|   width, | ||||
| @ -74,4 +76,5 @@ export const convertImageToEndpointImage = ({ | ||||
|       title, | ||||
|       ...(isNotEmpty(description) ? { description: convertRTCToEndpointRTC(description) } : {}), | ||||
|     })) ?? [], | ||||
|   credits: convertCreditsToEndpointCredits(credits), | ||||
| }); | ||||
|  | ||||
| @ -3,8 +3,9 @@ import { breakBlock } from "../../blocks/breakBlock"; | ||||
| import { sectionBlock } from "../../blocks/sectionBlock"; | ||||
| import { transcriptBlock } from "../../blocks/transcriptBlock"; | ||||
| import { QuickFilters, publishStatusFilters } from "../../components/QuickFilters"; | ||||
| import { CollectionGroups, Collections, PageType } from "../../constants"; | ||||
| import { CollectionGroups, Collections } from "../../constants"; | ||||
| import { backPropagationField } from "../../fields/backPropagationField/backPropagationField"; | ||||
| import { creditsField } from "../../fields/creditsField/creditsField"; | ||||
| import { imageField } from "../../fields/imageField/imageField"; | ||||
| import { rowField } from "../../fields/rowField/rowField"; | ||||
| import { slugField } from "../../fields/slugField/slugField"; | ||||
| @ -13,15 +14,12 @@ import { translatedFields } from "../../fields/translatedFields/translatedFields | ||||
| import { beforeDuplicateAddCopyTo } from "../../hooks/beforeDuplicateAddCopyTo"; | ||||
| import { beforeDuplicatePiping } from "../../hooks/beforeDuplicatePiping"; | ||||
| import { beforeDuplicateUnpublish } from "../../hooks/beforeDuplicateUnpublish"; | ||||
| import { isDefined, isUndefined } from "../../utils/asserts"; | ||||
| import { createEditor } from "../../utils/editor"; | ||||
| import { buildVersionedCollectionConfig } from "../../utils/versionedCollectionConfig"; | ||||
| import { getBySlugEndpoint } from "./endpoints/getBySlugEndpoint"; | ||||
| 
 | ||||
| const fields = { | ||||
|   slug: "slug", | ||||
|   type: "type", | ||||
|   authors: "authors", | ||||
|   thumbnail: "thumbnail", | ||||
|   backgroundImage: "backgroundImage", | ||||
|   translations: "translations", | ||||
| @ -32,17 +30,11 @@ const fields = { | ||||
|   subtitle: "subtitle", | ||||
|   summary: "summary", | ||||
|   content: "content", | ||||
|   transcribers: "transcribers", | ||||
|   translators: "translators", | ||||
|   proofreaders: "proofreaders", | ||||
|   credits: "credits", | ||||
|   collectibles: "collectibles", | ||||
|   folders: "folders", | ||||
| } as const satisfies Record<string, string>; | ||||
| 
 | ||||
| const pageTypesWithAuthor = [PageType.Post]; | ||||
| const pageTypesWithCollectibles = [PageType.Content]; | ||||
| const pageTypesWithTranscribers = [PageType.Content]; | ||||
| 
 | ||||
| export const Pages = buildVersionedCollectionConfig({ | ||||
|   slug: Collections.Pages, | ||||
|   labels: { | ||||
| @ -56,7 +48,6 @@ export const Pages = buildVersionedCollectionConfig({ | ||||
|       fields.slug, | ||||
|       fields.thumbnail, | ||||
|       fields.backgroundImage, | ||||
|       fields.type, | ||||
|       fields.tags, | ||||
|       fields.translations, | ||||
|       fields.folders, | ||||
| @ -81,19 +72,7 @@ export const Pages = buildVersionedCollectionConfig({ | ||||
|   }, | ||||
|   endpoints: [getBySlugEndpoint], | ||||
|   fields: [ | ||||
|     rowField([ | ||||
|       slugField({ name: fields.slug }), | ||||
|       { | ||||
|         name: fields.type, | ||||
|         type: "radio", | ||||
|         required: true, | ||||
|         defaultValue: PageType.Generic, | ||||
|         options: Object.entries(PageType).map(([_, value]) => ({ | ||||
|           label: value, | ||||
|           value: value, | ||||
|         })), | ||||
|       }, | ||||
|     ]), | ||||
|     slugField({ name: fields.slug }), | ||||
|     rowField([ | ||||
|       imageField({ | ||||
|         name: fields.thumbnail, | ||||
| @ -109,20 +88,7 @@ export const Pages = buildVersionedCollectionConfig({ | ||||
|         }, | ||||
|       }), | ||||
|     ]), | ||||
|     rowField([ | ||||
|       tagsField({ name: fields.tags }), | ||||
|       { | ||||
|         name: fields.authors, | ||||
|         type: "relationship", | ||||
|         admin: { | ||||
|           condition: (_, siblingData) => pageTypesWithAuthor.includes(siblingData[fields.type]), | ||||
|         }, | ||||
|         relationTo: Collections.Recorders, | ||||
|         required: true, | ||||
|         minRows: 1, | ||||
|         hasMany: true, | ||||
|       }, | ||||
|     ]), | ||||
|     tagsField({ name: fields.tags }), | ||||
|     translatedFields({ | ||||
|       name: fields.translations, | ||||
|       admin: { useAsTitle: fields.title, hasSourceLanguage: true }, | ||||
| @ -156,66 +122,7 @@ export const Pages = buildVersionedCollectionConfig({ | ||||
|             lists: true, | ||||
|           }), | ||||
|         }, | ||||
|         rowField([ | ||||
|           { | ||||
|             name: fields.transcribers, | ||||
|             type: "relationship", | ||||
|             relationTo: Collections.Recorders, | ||||
|             hasMany: true, | ||||
|             admin: { | ||||
|               condition: (data, siblingData) => { | ||||
|                 if (!pageTypesWithTranscribers.includes(data[fields.type])) { | ||||
|                   return false; | ||||
|                 } | ||||
|                 if (isUndefined(siblingData.language) || isUndefined(siblingData.sourceLanguage)) { | ||||
|                   return false; | ||||
|                 } | ||||
|                 return siblingData.language === siblingData.sourceLanguage; | ||||
|               }, | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|             name: fields.translators, | ||||
|             type: "relationship", | ||||
|             relationTo: Collections.Recorders, | ||||
|             hasMany: true, | ||||
|             hooks: { | ||||
|               beforeChange: [ | ||||
|                 ({ siblingData }) => { | ||||
|                   if (siblingData.language === siblingData.sourceLanguage) { | ||||
|                     delete siblingData.translators; | ||||
|                   } | ||||
|                 }, | ||||
|               ], | ||||
|             }, | ||||
|             admin: { | ||||
|               condition: (_, siblingData) => { | ||||
|                 if (isUndefined(siblingData.language) || isUndefined(siblingData.sourceLanguage)) { | ||||
|                   return false; | ||||
|                 } | ||||
|                 return siblingData.language !== siblingData.sourceLanguage; | ||||
|               }, | ||||
|             }, | ||||
|             validate: (translators, { siblingData }) => { | ||||
|               if (isUndefined(siblingData.language) || isUndefined(siblingData.sourceLanguage)) { | ||||
|                 return true; | ||||
|               } | ||||
|               if (siblingData.language === siblingData.sourceLanguage) { | ||||
|                 return true; | ||||
|               } | ||||
|               if (isDefined(translators) && translators.length > 0) { | ||||
|                 return true; | ||||
|               } | ||||
|               return "This field is required when the language is different from the source language."; | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|             name: fields.proofreaders, | ||||
|             type: "relationship", | ||||
|             relationTo: Collections.Recorders, | ||||
|             hasMany: true, | ||||
|           }, | ||||
|         ]), | ||||
|         creditsField({ name: fields.credits }), | ||||
|       ], | ||||
|     }), | ||||
|     rowField([ | ||||
| @ -234,10 +141,6 @@ export const Pages = buildVersionedCollectionConfig({ | ||||
|         name: fields.collectibles, | ||||
|         hasMany: true, | ||||
|         relationTo: Collections.Collectibles, | ||||
|         admin: { | ||||
|           condition: (_, siblingData) => | ||||
|             pageTypesWithCollectibles.includes(siblingData[fields.type]), | ||||
|         }, | ||||
|         where: ({ id }) => ({ | ||||
|           and: [ | ||||
|             { "contents.content.value": { equals: id } }, | ||||
|  | ||||
| @ -1,7 +1,6 @@ | ||||
| import { | ||||
|   BreakBlockType, | ||||
|   Collections, | ||||
|   PageType, | ||||
|   RichTextContent, | ||||
|   isBlockNodeBreakBlock, | ||||
|   isBlockNodeSectionBlock, | ||||
| @ -10,18 +9,13 @@ import { | ||||
| import { createGetByEndpoint } from "../../../endpoints/createGetByEndpoint"; | ||||
| import { EndpointPage, TableOfContentEntry } from "../../../sdk"; | ||||
| import { Page } from "../../../types/collections"; | ||||
| import { isNotEmpty, isPayloadType, isValidPayloadImage } from "../../../utils/asserts"; | ||||
| import { | ||||
|   isNotEmpty, | ||||
|   isPayloadArrayType, | ||||
|   isPayloadType, | ||||
|   isValidPayloadImage, | ||||
| } from "../../../utils/asserts"; | ||||
| import { | ||||
|   convertCreditsToEndpointCredits, | ||||
|   convertRTCToEndpointRTC, | ||||
|   convertSourceToEndpointSource, | ||||
|   convertTagsEndpointTagsGroups, | ||||
| } from "../../../utils/endpoints"; | ||||
| import { convertRecorderToEndpointRecorder } from "../../Recorders/endpoints/getByUsername"; | ||||
| 
 | ||||
| export const getBySlugEndpoint = createGetByEndpoint({ | ||||
|   collection: Collections.Pages, | ||||
| @ -34,31 +28,16 @@ export const convertPageToEndpointPage = ({ | ||||
|   collectibles, | ||||
|   folders, | ||||
|   backgroundImage, | ||||
|   authors, | ||||
|   slug, | ||||
|   tags, | ||||
|   thumbnail, | ||||
|   type, | ||||
| }: Page): EndpointPage => ({ | ||||
|   slug, | ||||
|   type: type as PageType, | ||||
|   ...(isValidPayloadImage(thumbnail) ? { thumbnail } : {}), | ||||
|   tagGroups: convertTagsEndpointTagsGroups(tags), | ||||
|   authors: isPayloadArrayType(authors) ? authors.map(convertRecorderToEndpointRecorder) : [], | ||||
|   ...(isValidPayloadImage(backgroundImage) ? { backgroundImage } : {}), | ||||
|   translations: translations.map( | ||||
|     ({ | ||||
|       content, | ||||
|       language, | ||||
|       sourceLanguage, | ||||
|       title, | ||||
|       pretitle, | ||||
|       subtitle, | ||||
|       proofreaders, | ||||
|       summary, | ||||
|       transcribers, | ||||
|       translators, | ||||
|     }) => ({ | ||||
|     ({ content, language, sourceLanguage, title, pretitle, subtitle, summary, credits }) => ({ | ||||
|       language: isPayloadType(language) ? language.id : language, | ||||
|       sourceLanguage: isPayloadType(sourceLanguage) ? sourceLanguage.id : sourceLanguage, | ||||
|       ...(isNotEmpty(pretitle) ? { pretitle } : {}), | ||||
| @ -67,15 +46,7 @@ export const convertPageToEndpointPage = ({ | ||||
|       ...(isNotEmpty(summary) ? { summary } : {}), | ||||
|       content: convertRTCToEndpointRTC(content), | ||||
|       toc: handleToc(content), | ||||
|       translators: isPayloadArrayType(translators) | ||||
|         ? translators.map(convertRecorderToEndpointRecorder) | ||||
|         : [], | ||||
|       transcribers: isPayloadArrayType(transcribers) | ||||
|         ? transcribers.map(convertRecorderToEndpointRecorder) | ||||
|         : [], | ||||
|       proofreaders: isPayloadArrayType(proofreaders) | ||||
|         ? proofreaders.map(convertRecorderToEndpointRecorder) | ||||
|         : [], | ||||
|       credits: convertCreditsToEndpointCredits(credits), | ||||
|     }) | ||||
|   ), | ||||
|   parentPages: convertSourceToEndpointSource({ collectibles, folders }), | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| import { CollectionGroups, Collections } from "../../constants"; | ||||
| import { componentField } from "../../fields/componentField/componentField"; | ||||
| import { creditsField } from "../../fields/creditsField/creditsField"; | ||||
| import { imageField } from "../../fields/imageField/imageField"; | ||||
| import { rowField } from "../../fields/rowField/rowField"; | ||||
| import { tagsField } from "../../fields/tagsField/tagsField"; | ||||
| @ -27,6 +28,7 @@ const fields = { | ||||
|   platformUrl: "url", | ||||
|   platformLikes: "likes", | ||||
|   platformDislikes: "dislikes", | ||||
|   credits: "credits", | ||||
| }; | ||||
| 
 | ||||
| export const Videos = buildCollectionConfig({ | ||||
| @ -78,6 +80,7 @@ export const Videos = buildCollectionConfig({ | ||||
|       ], | ||||
|     }), | ||||
|     tagsField({ name: fields.tags }), | ||||
|     creditsField({ name: fields.credits }), | ||||
|     componentField({ | ||||
|       name: fields.platform, | ||||
|       admin: { | ||||
|  | ||||
| @ -13,6 +13,7 @@ import { | ||||
|   isValidPayloadMedia, | ||||
| } from "../../../utils/asserts"; | ||||
| import { | ||||
|   convertCreditsToEndpointCredits, | ||||
|   convertRTCToEndpointRTC, | ||||
|   convertTagsEndpointTagsGroups, | ||||
|   getLanguageId, | ||||
| @ -67,6 +68,7 @@ export const convertVideoToEndpointVideo = ({ | ||||
|   thumbnail, | ||||
|   platform, | ||||
|   platformEnabled, | ||||
|   credits, | ||||
| }: Video & PayloadMedia): EndpointVideo => ({ | ||||
|   url, | ||||
|   tagGroups: convertTagsEndpointTagsGroups(tags), | ||||
| @ -105,4 +107,5 @@ export const convertVideoToEndpointVideo = ({ | ||||
|         return []; | ||||
|       return { language: getLanguageId(language), url: subfile.url }; | ||||
|     }) ?? [], | ||||
|   credits: convertCreditsToEndpointCredits(credits), | ||||
| }); | ||||
|  | ||||
| @ -23,6 +23,7 @@ export enum Collections { | ||||
|   VideosChannels = "videos-channels", | ||||
|   MediaThumbnails = "media-thumbnails", | ||||
|   Scans = "scans", | ||||
|   CreditsRole = "credits-roles", | ||||
| } | ||||
| 
 | ||||
| export enum CollectionGroups { | ||||
| @ -79,12 +80,6 @@ export enum CollectionStatus { | ||||
|   Published = "published", | ||||
| } | ||||
| 
 | ||||
| export enum PageType { | ||||
|   Content = "Content", | ||||
|   Post = "Post", | ||||
|   Generic = "Generic", | ||||
| } | ||||
| 
 | ||||
| /* RICH TEXT */ | ||||
| 
 | ||||
| export type RichTextContent = { | ||||
|  | ||||
							
								
								
									
										43
									
								
								src/fields/creditsField/creditsField.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/fields/creditsField/creditsField.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| import { array } from "payload/dist/fields/validations"; | ||||
| import { ArrayField } from "payload/types"; | ||||
| import { Collections } from "../../constants"; | ||||
| import { Credits } from "../../types/collections"; | ||||
| import { hasDuplicates, isDefined, isPayloadType, isUndefined } from "../../utils/asserts"; | ||||
| 
 | ||||
| type Props = Omit<ArrayField, "type" | "fields">; | ||||
| 
 | ||||
| export const creditsField = ({ validate, admin, ...props }: Props): ArrayField => ({ | ||||
|   ...props, | ||||
|   type: "array", | ||||
|   admin: { initCollapsed: true, ...admin }, | ||||
|   interfaceName: "Credits", | ||||
|   validate: (value, options) => { | ||||
|     const defaultValidation = array(value, options); | ||||
|     if (defaultValidation !== true) return defaultValidation; | ||||
| 
 | ||||
|     if (isDefined(validate)) { | ||||
|       const propsValidation = validate(value, options); | ||||
|       if (propsValidation !== true) return propsValidation; | ||||
|     } | ||||
| 
 | ||||
|     const data = options.data[props.name] as Credits | undefined | null; | ||||
|     if (isUndefined(data)) return true; | ||||
| 
 | ||||
|     const roles = data.map((row) => (isPayloadType(row.role) ? row.role.id : row.role)); | ||||
|     if (hasDuplicates(roles)) { | ||||
|       return `There cannot be multiple ${props.name} with the same role`; | ||||
|     } | ||||
| 
 | ||||
|     return true; | ||||
|   }, | ||||
|   fields: [ | ||||
|     { name: "role", type: "relationship", relationTo: Collections.CreditsRole, required: true }, | ||||
|     { | ||||
|       name: "recorders", | ||||
|       type: "relationship", | ||||
|       relationTo: Collections.Recorders, | ||||
|       required: true, | ||||
|       hasMany: true, | ||||
|     }, | ||||
|   ], | ||||
| }); | ||||
| @ -19,7 +19,6 @@ type LocalizedFieldsProps = Omit<ArrayField, "type" | "admin"> & { | ||||
|   admin?: ArrayField["admin"] & { | ||||
|     useAsTitle?: string; | ||||
|     hasSourceLanguage?: boolean; | ||||
|     hasCredits?: boolean; | ||||
|   }; | ||||
| }; | ||||
| type ArrayData = { [fieldsNames.language]?: string }[] | number | undefined; | ||||
| @ -40,92 +39,12 @@ const sourceLanguageField: Field = { | ||||
|   admin: { allowCreate: false }, | ||||
| }; | ||||
| 
 | ||||
| const creditFields: Field = { | ||||
|   type: "row", | ||||
|   admin: { | ||||
|     condition: (_, siblingData) => | ||||
|       isDefined(siblingData[fieldsNames.language]) && | ||||
|       isDefined(siblingData[fieldsNames.sourceLanguage]), | ||||
|   }, | ||||
|   fields: [ | ||||
|     { | ||||
|       name: fieldsNames.transcribers, | ||||
|       label: "Transcribers", | ||||
|       type: "relationship", | ||||
|       relationTo: "recorders", | ||||
|       hasMany: true, | ||||
|       hooks: { | ||||
|         beforeChange: [ | ||||
|           ({ siblingData }) => { | ||||
|             if (siblingData[fieldsNames.language] !== siblingData[fieldsNames.sourceLanguage]) { | ||||
|               delete siblingData[fieldsNames.transcribers]; | ||||
|             } | ||||
|           }, | ||||
|         ], | ||||
|       }, | ||||
|       admin: { | ||||
|         condition: (_, siblingData) => siblingData.language === siblingData.sourceLanguage, | ||||
|         width: "0%", | ||||
|       }, | ||||
|       validate: (count, { siblingData }) => { | ||||
|         if (siblingData[fieldsNames.language] !== siblingData[fieldsNames.sourceLanguage]) { | ||||
|           return true; | ||||
|         } | ||||
|         if (isDefined(count) && count.length > 0) { | ||||
|           return true; | ||||
|         } | ||||
|         return `This field is required when the ${fieldsNames.language} \ | ||||
|         is the same as the ${fieldsNames.sourceLanguage}.`;
 | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       name: fieldsNames.translators, | ||||
|       label: "Translators", | ||||
|       type: "relationship", | ||||
|       relationTo: "recorders", | ||||
|       hasMany: true, | ||||
|       hooks: { | ||||
|         beforeChange: [ | ||||
|           ({ siblingData }) => { | ||||
|             if (siblingData[fieldsNames.language] === siblingData[fieldsNames.sourceLanguage]) { | ||||
|               delete siblingData[fieldsNames.translators]; | ||||
|             } | ||||
|           }, | ||||
|         ], | ||||
|       }, | ||||
|       admin: { | ||||
|         condition: (_, siblingData) => | ||||
|           siblingData[fieldsNames.language] !== siblingData[fieldsNames.sourceLanguage], | ||||
|         width: "0%", | ||||
|       }, | ||||
|       validate: (count, { siblingData }) => { | ||||
|         if (siblingData[fieldsNames.language] === siblingData[fieldsNames.sourceLanguage]) { | ||||
|           return true; | ||||
|         } | ||||
|         if (isDefined(count) && count.length > 0) { | ||||
|           return true; | ||||
|         } | ||||
|         return `This field is required when the ${fieldsNames.language} \ | ||||
|         is different from the ${fieldsNames.sourceLanguage}.`;
 | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       name: fieldsNames.proofreaders, | ||||
|       label: "Proofreaders", | ||||
|       type: "relationship", | ||||
|       relationTo: "recorders", | ||||
|       hasMany: true, | ||||
|       admin: { width: "0%" }, | ||||
|     }, | ||||
|   ], | ||||
| }; | ||||
| 
 | ||||
| type FieldData = Record<string, any> & { [fieldsNames.language]: string }; | ||||
| 
 | ||||
| export const translatedFields = ({ | ||||
|   fields, | ||||
|   validate, | ||||
|   admin: { useAsTitle, hasSourceLanguage, hasCredits, ...admin } = {}, | ||||
|   admin: { useAsTitle, hasSourceLanguage, ...admin } = {}, | ||||
|   ...otherProps | ||||
| }: LocalizedFieldsProps): ArrayField => ({ | ||||
|   ...otherProps, | ||||
| @ -172,6 +91,5 @@ export const translatedFields = ({ | ||||
|   fields: [ | ||||
|     rowField(hasSourceLanguage ? [languageField, sourceLanguageField] : [languageField]), | ||||
|     ...fields, | ||||
|     ...(hasCredits ? [creditFields] : []), | ||||
|   ], | ||||
| }); | ||||
|  | ||||
| @ -7,6 +7,7 @@ import { sftpAdapter } from "payloadcms-sftp-storage"; | ||||
| import { Audios } from "./collections/Audios/Audios"; | ||||
| import { ChronologyEvents } from "./collections/ChronologyEvents/ChronologyEvents"; | ||||
| import { Collectibles } from "./collections/Collectibles/Collectibles"; | ||||
| import { CreditsRoles } from "./collections/CreditsRoles/CreditsRoles"; | ||||
| import { Currencies } from "./collections/Currencies/Currencies"; | ||||
| import { Folders } from "./collections/Folders/Folders"; | ||||
| import { GenericContents } from "./collections/GenericContents/GenericContents"; | ||||
| @ -68,6 +69,7 @@ export default buildConfig({ | ||||
| 
 | ||||
|     Tags, | ||||
|     TagsGroups, | ||||
|     CreditsRoles, | ||||
|     Recorders, | ||||
|     Languages, | ||||
|     Currencies, | ||||
|  | ||||
							
								
								
									
										25
									
								
								src/sdk.ts
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								src/sdk.ts
									
									
									
									
									
								
							| @ -3,7 +3,6 @@ import { | ||||
|   CollectibleNature, | ||||
|   CollectiblePageOrders, | ||||
|   Collections, | ||||
|   PageType, | ||||
|   RichTextContent, | ||||
| } from "./constants"; | ||||
| import { Currency, Language } from "./types/collections"; | ||||
| @ -187,11 +186,22 @@ export type EndpointTagsGroup = { | ||||
|   tags: EndpointTag[]; | ||||
| }; | ||||
| 
 | ||||
| export type EndpointRole = { | ||||
|   icon: string; | ||||
|   translations: { | ||||
|     language: string; | ||||
|     name: string; | ||||
|   }[]; | ||||
| }; | ||||
| 
 | ||||
| export type EndpointCredit = { | ||||
|   role: EndpointRole; | ||||
|   recorders: EndpointRecorder[]; | ||||
| }; | ||||
| 
 | ||||
| export type EndpointPage = { | ||||
|   slug: string; | ||||
|   type: PageType; | ||||
|   thumbnail?: PayloadImage; | ||||
|   authors: EndpointRecorder[]; | ||||
|   tagGroups: EndpointTagsGroup[]; | ||||
|   backgroundImage?: PayloadImage; | ||||
|   translations: { | ||||
| @ -202,9 +212,7 @@ export type EndpointPage = { | ||||
|     sourceLanguage: string; | ||||
|     summary?: RichTextContent; | ||||
|     content: RichTextContent; | ||||
|     transcribers: EndpointRecorder[]; | ||||
|     translators: EndpointRecorder[]; | ||||
|     proofreaders: EndpointRecorder[]; | ||||
|     credits: EndpointCredit[]; | ||||
|     toc: TableOfContentEntry[]; | ||||
|   }[]; | ||||
|   parentPages: EndpointSource[]; | ||||
| @ -313,9 +321,7 @@ export type EndpointChronologyEvent = { | ||||
|       title?: string; | ||||
|       description?: RichTextContent; | ||||
|       notes?: RichTextContent; | ||||
|       transcribers: EndpointRecorder[]; | ||||
|       translators: EndpointRecorder[]; | ||||
|       proofreaders: EndpointRecorder[]; | ||||
|       credits: EndpointCredit[]; | ||||
|     }[]; | ||||
|   }[]; | ||||
| }; | ||||
| @ -347,6 +353,7 @@ export type EndpointMedia = { | ||||
|     title: string; | ||||
|     description?: RichTextContent; | ||||
|   }[]; | ||||
|   credits: EndpointCredit[]; | ||||
| }; | ||||
| 
 | ||||
| export type EndpointImage = EndpointMedia & { | ||||
|  | ||||
| @ -6,6 +6,18 @@ | ||||
|  * and re-run `payload generate:types` to regenerate this file. | ||||
|  */ | ||||
| 
 | ||||
| /** | ||||
|  * This interface was referenced by `Config`'s JSON-Schema | ||||
|  * via the `definition` "Credits". | ||||
|  */ | ||||
| export type Credits = | ||||
|   | { | ||||
|       role: string | CreditsRole; | ||||
|       recorders: (string | Recorder)[]; | ||||
|       id?: string | null; | ||||
|     }[] | ||||
|   | null; | ||||
| 
 | ||||
| export interface Config { | ||||
|   collections: { | ||||
|     pages: Page; | ||||
| @ -21,6 +33,7 @@ export interface Config { | ||||
|     scans: Scan; | ||||
|     tags: Tag; | ||||
|     "tags-groups": TagsGroup; | ||||
|     "credits-roles": CreditsRole; | ||||
|     recorders: Recorder; | ||||
|     languages: Language; | ||||
|     currencies: Currency; | ||||
| @ -40,11 +53,9 @@ export interface Config { | ||||
| export interface Page { | ||||
|   id: string; | ||||
|   slug: string; | ||||
|   type: "Content" | "Post" | "Generic"; | ||||
|   thumbnail?: string | Image | null; | ||||
|   backgroundImage?: string | Image | null; | ||||
|   tags?: (string | Tag)[] | null; | ||||
|   authors?: (string | Recorder)[] | null; | ||||
|   translations: { | ||||
|     language: string | Language; | ||||
|     sourceLanguage: string | Language; | ||||
| @ -81,9 +92,7 @@ export interface Page { | ||||
|       }; | ||||
|       [k: string]: unknown; | ||||
|     }; | ||||
|     transcribers?: (string | Recorder)[] | null; | ||||
|     translators?: (string | Recorder)[] | null; | ||||
|     proofreaders?: (string | Recorder)[] | null; | ||||
|     credits?: Credits; | ||||
|     id?: string | null; | ||||
|   }[]; | ||||
|   folders?: (string | Folder)[] | null; | ||||
| @ -122,6 +131,7 @@ export interface Image { | ||||
|       }[] | ||||
|     | null; | ||||
|   tags?: (string | Tag)[] | null; | ||||
|   credits?: Credits; | ||||
|   updatedAt: string; | ||||
|   createdAt: string; | ||||
|   url?: string | null; | ||||
| @ -190,6 +200,22 @@ export interface TagsGroup { | ||||
|   updatedAt: string; | ||||
|   createdAt: string; | ||||
| } | ||||
| /** | ||||
|  * This interface was referenced by `Config`'s JSON-Schema | ||||
|  * via the `definition` "credits-roles". | ||||
|  */ | ||||
| export interface CreditsRole { | ||||
|   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". | ||||
| @ -321,9 +347,7 @@ export interface Collectible { | ||||
|     | null; | ||||
|   scansEnabled?: boolean | null; | ||||
|   scans?: { | ||||
|     scanners: (string | Recorder)[]; | ||||
|     cleaners: (string | Recorder)[]; | ||||
|     typesetters?: (string | Recorder)[] | null; | ||||
|     credits?: Credits; | ||||
|     coverEnabled?: boolean | null; | ||||
|     cover?: { | ||||
|       front?: string | Scan | null; | ||||
| @ -554,6 +578,7 @@ export interface Audio { | ||||
|     id?: string | null; | ||||
|   }[]; | ||||
|   tags?: (string | Tag)[] | null; | ||||
|   credits?: Credits; | ||||
|   updatedAt: string; | ||||
|   createdAt: string; | ||||
|   url?: string | null; | ||||
| @ -626,6 +651,7 @@ export interface Video { | ||||
|     id?: string | null; | ||||
|   }[]; | ||||
|   tags?: (string | Tag)[] | null; | ||||
|   credits?: Credits; | ||||
|   platformEnabled?: boolean | null; | ||||
|   platform?: { | ||||
|     channel: string | VideosChannel; | ||||
| @ -716,9 +742,7 @@ export interface ChronologyEvent { | ||||
|         }; | ||||
|         [k: string]: unknown; | ||||
|       } | null; | ||||
|       transcribers?: (string | Recorder)[] | null; | ||||
|       translators?: (string | Recorder)[] | null; | ||||
|       proofreaders?: (string | Recorder)[] | null; | ||||
|       credits?: Credits; | ||||
|       id?: string | null; | ||||
|     }[]; | ||||
|     id?: string | null; | ||||
|  | ||||
| @ -2,6 +2,7 @@ import { convertAudioToEndpointAudio } from "../collections/Audios/endpoints/get | ||||
| import { convertCollectibleToEndpointCollectible } from "../collections/Collectibles/endpoints/getBySlugEndpoint"; | ||||
| import { convertFolderToEndpointFolder } from "../collections/Folders/endpoints/getBySlugEndpoint"; | ||||
| import { convertImageToEndpointImage } from "../collections/Images/endpoints/getByID"; | ||||
| import { convertRecorderToEndpointRecorder } from "../collections/Recorders/endpoints/getByUsername"; | ||||
| import { convertVideoToEndpointVideo } from "../collections/Videos/endpoints/getByID"; | ||||
| import { | ||||
|   RichTextBreakBlock, | ||||
| @ -16,8 +17,24 @@ import { | ||||
|   isUploadNodeImageNode, | ||||
|   isUploadNodeVideoNode, | ||||
| } from "../constants"; | ||||
| import { EndpointSource, EndpointTag, EndpointTagsGroup } from "../sdk"; | ||||
| import { Audio, Collectible, Folder, Image, Language, Tag, Video } from "../types/collections"; | ||||
| import { | ||||
|   EndpointCredit, | ||||
|   EndpointRole, | ||||
|   EndpointSource, | ||||
|   EndpointTag, | ||||
|   EndpointTagsGroup, | ||||
| } from "../sdk"; | ||||
| import { | ||||
|   Audio, | ||||
|   Collectible, | ||||
|   Credits, | ||||
|   CreditsRole, | ||||
|   Folder, | ||||
|   Image, | ||||
|   Language, | ||||
|   Tag, | ||||
|   Video, | ||||
| } from "../types/collections"; | ||||
| import { | ||||
|   isPayloadArrayType, | ||||
|   isPayloadType, | ||||
| @ -106,21 +123,21 @@ export const convertRTCToEndpointRTC = ( | ||||
|             version: 1, | ||||
|           }; | ||||
|           if (isUploadNodeImageNode(node)) { | ||||
|             const value = node.value as Image | string; | ||||
|             const value = node.value as unknown as Image | string; | ||||
|             if (!isPayloadType(value) || !isValidPayloadImage(value)) return errorUploadNode; | ||||
|             return { | ||||
|               ...node, | ||||
|               value: convertImageToEndpointImage(value), | ||||
|             }; | ||||
|           } else if (isUploadNodeAudioNode(node)) { | ||||
|             const value = node.value as Audio | string; | ||||
|             const value = node.value as unknown as Audio | string; | ||||
|             if (!isPayloadType(value) || !isValidPayloadMedia(value)) return errorUploadNode; | ||||
|             return { | ||||
|               ...node, | ||||
|               value: convertAudioToEndpointAudio(value), | ||||
|             }; | ||||
|           } else if (isUploadNodeVideoNode(node)) { | ||||
|             const value = node.value as Video | string; | ||||
|             const value = node.value as unknown as Video | string; | ||||
|             if (!isPayloadType(value) || !isValidPayloadMedia(value)) return errorUploadNode; | ||||
|             return { | ||||
|               ...node, | ||||
| @ -175,3 +192,22 @@ export const getDomainFromUrl = (url: string): string => { | ||||
| 
 | ||||
| export const getLanguageId = (language: string | Language) => | ||||
|   typeof language === "object" ? language.id : language; | ||||
| 
 | ||||
| const convertRoleToEndpointRole = ({ icon, translations }: CreditsRole): EndpointRole => ({ | ||||
|   icon: icon ?? "material-symbols:person", | ||||
|   translations: translations.map(({ language, name }) => ({ | ||||
|     language: getLanguageId(language), | ||||
|     name, | ||||
|   })), | ||||
| }); | ||||
| 
 | ||||
| export const convertCreditsToEndpointCredits = (credits?: Credits | null): EndpointCredit[] => | ||||
|   credits?.flatMap<EndpointCredit>(({ recorders, role }) => { | ||||
|     if (!isPayloadArrayType(recorders) || !isPayloadType(role)) return []; | ||||
|     return [ | ||||
|       { | ||||
|         role: convertRoleToEndpointRole(role), | ||||
|         recorders: recorders.map(convertRecorderToEndpointRecorder), | ||||
|       }, | ||||
|     ]; | ||||
|   }) ?? []; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 DrMint
						DrMint