Added collectibles
This commit is contained in:
parent
6cb23eb82e
commit
e9fbb0a3b7
|
@ -0,0 +1,701 @@
|
||||||
|
import { RowLabelArgs } from "payload/dist/admin/components/forms/RowLabel/types";
|
||||||
|
import { Where } from "payload/types";
|
||||||
|
import {
|
||||||
|
CollectibleBindingTypes,
|
||||||
|
CollectibleNature,
|
||||||
|
CollectiblePageOrders,
|
||||||
|
CollectionGroups,
|
||||||
|
Collections,
|
||||||
|
PageType,
|
||||||
|
} from "../../constants";
|
||||||
|
import { backPropagationField } from "../../fields/backPropagationField/backPropagationField";
|
||||||
|
import { componentField } from "../../fields/componentField/componentField";
|
||||||
|
import { imageField } from "../../fields/imageField/imageField";
|
||||||
|
import { rowField } from "../../fields/rowField/rowField";
|
||||||
|
import { slugField } from "../../fields/slugField/slugField";
|
||||||
|
import { tagsField } from "../../fields/tagsField/tagsField";
|
||||||
|
import { translatedFields } from "../../fields/translatedFields/translatedFields";
|
||||||
|
import { beforeDuplicateAddCopyTo } from "../../hooks/beforeDuplicateAddCopyTo";
|
||||||
|
import { beforeDuplicatePiping } from "../../hooks/beforeDuplicatePiping";
|
||||||
|
import { beforeDuplicateUnpublish } from "../../hooks/beforeDuplicateUnpublish";
|
||||||
|
import { createEditor } from "../../utils/editor";
|
||||||
|
import { buildVersionedCollectionConfig } from "../../utils/versionedCollectionConfig";
|
||||||
|
import { RowLabel } from "./components/RowLabel";
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
status: "_status",
|
||||||
|
slug: "slug",
|
||||||
|
thumbnail: "thumbnail",
|
||||||
|
nature: "nature",
|
||||||
|
tags: "tags",
|
||||||
|
languages: "languages",
|
||||||
|
|
||||||
|
translations: "translations",
|
||||||
|
pretitle: "pretitle",
|
||||||
|
title: "title",
|
||||||
|
subtitle: "subtitle",
|
||||||
|
description: "description",
|
||||||
|
|
||||||
|
price: "price",
|
||||||
|
priceAmount: "amount",
|
||||||
|
priceCurrency: "currency",
|
||||||
|
|
||||||
|
size: "size",
|
||||||
|
sizeWidth: "width",
|
||||||
|
sizeHeight: "height",
|
||||||
|
sizeThickness: "thickness",
|
||||||
|
|
||||||
|
weight: "weight",
|
||||||
|
weightAmount: "amount",
|
||||||
|
|
||||||
|
urls: "urls",
|
||||||
|
urlsUrl: "url",
|
||||||
|
|
||||||
|
scans: "scans",
|
||||||
|
scansScanners: "scanners",
|
||||||
|
scansCleaners: "cleaners",
|
||||||
|
scansTypesetters: "typesetters",
|
||||||
|
|
||||||
|
scansCover: "cover",
|
||||||
|
scansCoverFlapFront: "flapFront",
|
||||||
|
scansCoverFront: "front",
|
||||||
|
scansCoverSpine: "spine",
|
||||||
|
scansCoverBack: "back",
|
||||||
|
scansCoverFlapBack: "flapBack",
|
||||||
|
scansCoverInsideFlapFront: "insideFlapFront",
|
||||||
|
scansCoverInsideFront: "insideFront",
|
||||||
|
scansCoverInsideBack: "insideBack",
|
||||||
|
scansCoverInsideFlapBack: "insideFlapBack",
|
||||||
|
|
||||||
|
scansDustjacket: "dustjacket",
|
||||||
|
scansDustjacketFlapFront: "flapFront",
|
||||||
|
scansDustjacketFront: "front",
|
||||||
|
scansDustjacketSpine: "spine",
|
||||||
|
scansDustjacketBack: "back",
|
||||||
|
scansDustjacketFlapBack: "flapBack",
|
||||||
|
scansDustjacketInsideFlapFront: "insideFlapFront",
|
||||||
|
scansDustjacketInsideFront: "insideFront",
|
||||||
|
scansDustjacketInsideSpine: "insideSpine",
|
||||||
|
scansDustjacketInsideBack: "insideBack",
|
||||||
|
scansDustjacketInsideFlapBack: "insideFlapBack",
|
||||||
|
|
||||||
|
scansObi: "obi",
|
||||||
|
scansObiFlapFront: "flapFront",
|
||||||
|
scansObiFront: "front",
|
||||||
|
scansObiSpine: "spine",
|
||||||
|
scansObiBack: "back",
|
||||||
|
scansObiFlapBack: "flapBack",
|
||||||
|
scansObiInsideFlapFront: "insideFlapFront",
|
||||||
|
scansObiInsideFront: "insideFront",
|
||||||
|
scansObiInsideSpine: "insideSpine",
|
||||||
|
scansObiInsideBack: "insideBack",
|
||||||
|
scansObiInsideFlapBack: "insideFlapBack",
|
||||||
|
|
||||||
|
scansPages: "pages",
|
||||||
|
scansPagesPage: "page",
|
||||||
|
scansPagesImage: "image",
|
||||||
|
|
||||||
|
gallery: "gallery",
|
||||||
|
galleryImage: "image",
|
||||||
|
|
||||||
|
releaseDate: "releaseDate",
|
||||||
|
|
||||||
|
parentItems: "parentItems",
|
||||||
|
subitems: "subitems",
|
||||||
|
folders: "folders",
|
||||||
|
|
||||||
|
contents: "contents",
|
||||||
|
contentsContent: "content",
|
||||||
|
|
||||||
|
pageInfo: "pageInfo",
|
||||||
|
pageInfoBindingType: "bindingType",
|
||||||
|
pageInfoPageCount: "pageCount",
|
||||||
|
pageInfoPageOrder: "pageOrder",
|
||||||
|
} as const satisfies Record<string, string>;
|
||||||
|
|
||||||
|
export const Collectibles = buildVersionedCollectionConfig({
|
||||||
|
slug: Collections.Collectibles,
|
||||||
|
labels: {
|
||||||
|
singular: "Collectible",
|
||||||
|
plural: "Collectibles",
|
||||||
|
},
|
||||||
|
defaultSort: fields.slug,
|
||||||
|
admin: {
|
||||||
|
useAsTitle: fields.slug,
|
||||||
|
defaultColumns: [fields.slug, fields.status],
|
||||||
|
group: CollectionGroups.Collections,
|
||||||
|
hooks: {
|
||||||
|
beforeDuplicate: beforeDuplicatePiping([
|
||||||
|
beforeDuplicateUnpublish,
|
||||||
|
beforeDuplicateAddCopyTo(fields.slug),
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: "tabs",
|
||||||
|
tabs: [
|
||||||
|
{
|
||||||
|
label: "Overview",
|
||||||
|
fields: [
|
||||||
|
rowField([
|
||||||
|
slugField({ name: fields.slug }),
|
||||||
|
imageField({
|
||||||
|
name: fields.thumbnail,
|
||||||
|
relationTo: Collections.Images,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
|
||||||
|
rowField([
|
||||||
|
{
|
||||||
|
name: fields.nature,
|
||||||
|
type: "radio",
|
||||||
|
required: true,
|
||||||
|
defaultValue: CollectibleNature.Physical,
|
||||||
|
options: Object.entries(CollectibleNature).map(([value, label]) => ({
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: fields.languages,
|
||||||
|
type: "relationship",
|
||||||
|
relationTo: Collections.Languages,
|
||||||
|
hasMany: true,
|
||||||
|
admin: {
|
||||||
|
allowCreate: false,
|
||||||
|
description:
|
||||||
|
"Languages used by this collectible: language(s) available for a game,\
|
||||||
|
in a video, a book is written in... Leave empty if inapplicable",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
|
||||||
|
tagsField({ name: fields.tags }),
|
||||||
|
|
||||||
|
translatedFields({
|
||||||
|
name: fields.translations,
|
||||||
|
admin: { useAsTitle: fields.title },
|
||||||
|
required: true,
|
||||||
|
minRows: 1,
|
||||||
|
fields: [
|
||||||
|
rowField([
|
||||||
|
{ name: fields.pretitle, type: "text" },
|
||||||
|
{ name: fields.title, type: "text", required: true },
|
||||||
|
{ name: fields.subtitle, type: "text" },
|
||||||
|
]),
|
||||||
|
{
|
||||||
|
name: fields.description,
|
||||||
|
type: "richText",
|
||||||
|
editor: createEditor({ inlines: true, lists: true, links: true }),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Images",
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: fields.gallery,
|
||||||
|
type: "array",
|
||||||
|
admin: {
|
||||||
|
description:
|
||||||
|
"Additional images of the item (unboxing, on shelf, promotional images...)",
|
||||||
|
},
|
||||||
|
labels: { singular: "Image", plural: "Images" },
|
||||||
|
fields: [
|
||||||
|
imageField({
|
||||||
|
name: fields.galleryImage,
|
||||||
|
relationTo: Collections.LibraryItemsGallery,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
componentField({
|
||||||
|
name: fields.scansCover,
|
||||||
|
fields: [
|
||||||
|
rowField([
|
||||||
|
imageField({
|
||||||
|
name: fields.scansCoverFront,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansCoverSpine,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansCoverBack,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
rowField([
|
||||||
|
imageField({
|
||||||
|
name: fields.scansCoverInsideFront,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansCoverInsideBack,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
rowField([
|
||||||
|
imageField({
|
||||||
|
name: fields.scansCoverFlapFront,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansCoverFlapBack,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansCoverInsideFlapFront,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansCoverInsideFlapBack,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
componentField({
|
||||||
|
name: fields.scansDustjacket,
|
||||||
|
label: "Dust Jacket",
|
||||||
|
admin: {
|
||||||
|
description:
|
||||||
|
"The dust jacket of a book is the detachable outer cover with folded \
|
||||||
|
flaps that hold it to the front and back book covers",
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
rowField([
|
||||||
|
imageField({
|
||||||
|
name: fields.scansDustjacketFront,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansDustjacketSpine,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansDustjacketBack,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
rowField([
|
||||||
|
imageField({
|
||||||
|
name: fields.scansDustjacketInsideFront,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansDustjacketInsideSpine,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansDustjacketInsideBack,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
rowField([
|
||||||
|
imageField({
|
||||||
|
name: fields.scansDustjacketFlapFront,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansDustjacketFlapBack,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansDustjacketInsideFlapFront,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansDustjacketInsideFlapBack,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
componentField({
|
||||||
|
name: fields.scansObi,
|
||||||
|
label: "Obi",
|
||||||
|
admin: {
|
||||||
|
description:
|
||||||
|
"An obi is a strip of paper looped around a book or other product. \
|
||||||
|
it typically add marketing claims, or other relevant information about the product.",
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
rowField([
|
||||||
|
imageField({
|
||||||
|
name: fields.scansObiFront,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansObiSpine,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansObiBack,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
rowField([
|
||||||
|
imageField({
|
||||||
|
name: fields.scansObiInsideFront,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansObiInsideSpine,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansObiInsideBack,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
rowField([
|
||||||
|
imageField({
|
||||||
|
name: fields.scansObiFlapFront,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansObiFlapBack,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansObiInsideFlapFront,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
imageField({
|
||||||
|
name: fields.scansObiInsideFlapBack,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: fields.scansPages,
|
||||||
|
type: "array",
|
||||||
|
admin: {
|
||||||
|
initCollapsed: true,
|
||||||
|
description:
|
||||||
|
"Make sure the page number corresponds to the page number written on \
|
||||||
|
the scan. You can use negative page numbers if necessary.",
|
||||||
|
components: {
|
||||||
|
RowLabel: ({ data }: RowLabelArgs) => RowLabel(data),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
rowField([
|
||||||
|
{
|
||||||
|
name: fields.scansPagesPage,
|
||||||
|
type: "number",
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
imageField({
|
||||||
|
name: fields.scansPagesImage,
|
||||||
|
relationTo: Collections.LibraryItemsScans,
|
||||||
|
required: true,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Details",
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: fields.urls,
|
||||||
|
label: "URLs",
|
||||||
|
type: "array",
|
||||||
|
admin: {
|
||||||
|
description: "Links to official websites where to get/buy the item.",
|
||||||
|
},
|
||||||
|
fields: [{ name: fields.urlsUrl, type: "text", required: true }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: fields.releaseDate,
|
||||||
|
type: "date",
|
||||||
|
admin: {
|
||||||
|
date: { pickerAppearance: "dayOnly", displayFormat: "yyyy-MM-dd" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
componentField({
|
||||||
|
name: fields.price,
|
||||||
|
admin: {
|
||||||
|
description:
|
||||||
|
"Add pricing information about this collectible. Leave this unchecked if the collectible is not for sale or set the amount to 0 if it is free.",
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
rowField([
|
||||||
|
{
|
||||||
|
name: fields.priceAmount,
|
||||||
|
type: "number",
|
||||||
|
required: true,
|
||||||
|
min: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: fields.priceCurrency,
|
||||||
|
type: "relationship",
|
||||||
|
relationTo: Collections.Currencies,
|
||||||
|
required: true,
|
||||||
|
admin: { allowCreate: false },
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
componentField({
|
||||||
|
name: fields.size,
|
||||||
|
admin: {
|
||||||
|
condition: ({ nature }) => nature === CollectibleNature.Physical,
|
||||||
|
description: "Add physical size information about this collectible",
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
rowField([
|
||||||
|
{
|
||||||
|
name: fields.sizeWidth,
|
||||||
|
type: "number",
|
||||||
|
required: true,
|
||||||
|
admin: { step: 1, description: "in mm." },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: fields.sizeHeight,
|
||||||
|
type: "number",
|
||||||
|
required: true,
|
||||||
|
admin: { step: 1, description: "in mm." },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: fields.sizeThickness,
|
||||||
|
type: "number",
|
||||||
|
admin: { step: 1, description: "in mm." },
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
componentField({
|
||||||
|
name: fields.weight,
|
||||||
|
admin: {
|
||||||
|
condition: ({ nature }) => nature === CollectibleNature.Physical,
|
||||||
|
description: "Add physical weight information about this collectible",
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: fields.weightAmount,
|
||||||
|
type: "number",
|
||||||
|
required: true,
|
||||||
|
admin: { step: 1, description: "in g." },
|
||||||
|
min: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
componentField({
|
||||||
|
name: fields.pageInfo,
|
||||||
|
label: "Page information",
|
||||||
|
admin: {
|
||||||
|
description:
|
||||||
|
"If the collectible is book-like (has pages),\
|
||||||
|
use this to add additional information about its format.",
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: fields.pageInfoPageCount,
|
||||||
|
type: "number",
|
||||||
|
required: true,
|
||||||
|
min: 1,
|
||||||
|
},
|
||||||
|
rowField([
|
||||||
|
{
|
||||||
|
name: fields.pageInfoBindingType,
|
||||||
|
type: "radio",
|
||||||
|
options: Object.entries(CollectibleBindingTypes).map(([value, label]) => ({
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
})),
|
||||||
|
admin: {
|
||||||
|
condition: ({ nature }) => nature === CollectibleNature.Physical,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: fields.pageInfoPageOrder,
|
||||||
|
type: "radio",
|
||||||
|
options: Object.entries(CollectiblePageOrders).map(([value, label]) => ({
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Contents",
|
||||||
|
fields: [
|
||||||
|
rowField([
|
||||||
|
backPropagationField({
|
||||||
|
name: fields.folders,
|
||||||
|
relationTo: Collections.Folders,
|
||||||
|
hasMany: true,
|
||||||
|
where: ({ id }) => ({
|
||||||
|
and: [
|
||||||
|
{ "files.value": { equals: id } },
|
||||||
|
{ "files.relationTo": { equals: Collections.Collectibles } },
|
||||||
|
] as Where[],
|
||||||
|
}),
|
||||||
|
admin: {
|
||||||
|
description: `You can go to the "Folders" collection to include this collectible in a folder.`,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
backPropagationField({
|
||||||
|
name: fields.parentItems,
|
||||||
|
relationTo: Collections.Collectibles,
|
||||||
|
hasMany: true,
|
||||||
|
where: ({ id }) => ({ [fields.subitems]: { equals: id } }),
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: fields.subitems,
|
||||||
|
type: "relationship",
|
||||||
|
hasMany: true,
|
||||||
|
relationTo: Collections.Collectibles,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
{
|
||||||
|
name: fields.contents,
|
||||||
|
type: "array",
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: fields.contentsContent,
|
||||||
|
type: "relationship",
|
||||||
|
// TODO: Add audio and video files
|
||||||
|
relationTo: [Collections.Pages, Collections.GenericContents],
|
||||||
|
admin: {
|
||||||
|
allowCreate: false,
|
||||||
|
},
|
||||||
|
required: true,
|
||||||
|
filterOptions: ({ relationTo }) => {
|
||||||
|
switch (relationTo) {
|
||||||
|
case Collections.Pages:
|
||||||
|
return { type: { equals: PageType.Content } };
|
||||||
|
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "range",
|
||||||
|
type: "blocks",
|
||||||
|
maxRows: 1,
|
||||||
|
admin: { className: "no-label" },
|
||||||
|
blocks: [
|
||||||
|
{
|
||||||
|
slug: "pageRange",
|
||||||
|
labels: { singular: "Page Range", plural: "Page Ranges" },
|
||||||
|
fields: [
|
||||||
|
rowField([
|
||||||
|
{
|
||||||
|
name: "start",
|
||||||
|
type: "number",
|
||||||
|
required: true,
|
||||||
|
admin: {
|
||||||
|
description:
|
||||||
|
"Make sure the page range corresponds to the pages as written\
|
||||||
|
on the collectible. You can use negative page numbers if necessary.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ name: "end", type: "number", required: true },
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: "timeRange",
|
||||||
|
labels: { singular: "Time Range", plural: "Time Ranges" },
|
||||||
|
fields: [
|
||||||
|
rowField([
|
||||||
|
{
|
||||||
|
name: "start",
|
||||||
|
type: "text",
|
||||||
|
required: true,
|
||||||
|
defaultValue: "00:00:00",
|
||||||
|
validate: (value) =>
|
||||||
|
/\d{2}:\d{2}:\d{2}/g.test(value)
|
||||||
|
? true
|
||||||
|
: "The format should be hh:mm:ss\
|
||||||
|
(e.g: 01:23:45 for 1 hour, 23 minutes, and 45 seconds)",
|
||||||
|
admin: {
|
||||||
|
description:
|
||||||
|
"hh:mm:ss (e.g: 01:23:45 for 1 hour, 23 minutes, and 45 seconds)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "end",
|
||||||
|
type: "text",
|
||||||
|
required: true,
|
||||||
|
defaultValue: "00:00:00",
|
||||||
|
validate: (value) =>
|
||||||
|
/\d{2}:\d{2}:\d{2}/g.test(value)
|
||||||
|
? true
|
||||||
|
: "The format should be hh:mm:ss\
|
||||||
|
(e.g: 01:23:45 for 1 hour, 23 minutes, and 45 seconds)",
|
||||||
|
admin: {
|
||||||
|
description:
|
||||||
|
"hh:mm:ss (e.g: 01:23:45 for 1 hour, 23 minutes, and 45 seconds)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: "other",
|
||||||
|
labels: { singular: "Other", plural: "Others" },
|
||||||
|
fields: [
|
||||||
|
translatedFields({
|
||||||
|
admin: { className: "no-label" },
|
||||||
|
name: "translations",
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "note",
|
||||||
|
type: "richText",
|
||||||
|
editor: createEditor({ inlines: true, lists: true, links: true }),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
|
@ -0,0 +1,26 @@
|
||||||
|
import React from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
import { isDefined } from "../../../utils/asserts";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
page?: number;
|
||||||
|
image?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Container = styled.div`
|
||||||
|
display: flex;
|
||||||
|
place-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Title = styled.div`
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const RowLabel = ({ page, image }: Props): JSX.Element => (
|
||||||
|
<Container>
|
||||||
|
{isDefined(page) && <div className="pill pill--style-white">{`Page ${page}`}</div>}
|
||||||
|
{isDefined(image) && <Title>{image}</Title>}
|
||||||
|
</Container>
|
||||||
|
);
|
|
@ -83,7 +83,7 @@ export const Folders = buildCollectionConfig({
|
||||||
{
|
{
|
||||||
type: "relationship",
|
type: "relationship",
|
||||||
name: fields.files,
|
name: fields.files,
|
||||||
relationTo: [Collections.LibraryItems, Collections.Pages],
|
relationTo: [Collections.Collectibles, Collections.Pages],
|
||||||
hasMany: true,
|
hasMany: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
import { CollectionConfig } from "payload/types";
|
||||||
|
import { QuickFilters } from "../../components/QuickFilters";
|
||||||
|
import { CollectionGroups, Collections, LanguageCodes } from "../../constants";
|
||||||
|
import { rowField } from "../../fields/rowField/rowField";
|
||||||
|
import { translatedFields } from "../../fields/translatedFields/translatedFields";
|
||||||
|
import { beforeDuplicateAddCopyTo } from "../../hooks/beforeDuplicateAddCopyTo";
|
||||||
|
import { buildCollectionConfig } from "../../utils/collectionConfig";
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
name: "name",
|
||||||
|
translations: "translations",
|
||||||
|
translationsName: "name",
|
||||||
|
} as const satisfies Record<string, string>;
|
||||||
|
|
||||||
|
export const GenericContents: CollectionConfig = buildCollectionConfig({
|
||||||
|
slug: Collections.GenericContents,
|
||||||
|
labels: {
|
||||||
|
singular: "Generic Content",
|
||||||
|
plural: "Generic Contents",
|
||||||
|
},
|
||||||
|
defaultSort: fields.name,
|
||||||
|
admin: {
|
||||||
|
useAsTitle: fields.name,
|
||||||
|
defaultColumns: [fields.name, fields.translations],
|
||||||
|
group: CollectionGroups.Meta,
|
||||||
|
hooks: {
|
||||||
|
beforeDuplicate: beforeDuplicateAddCopyTo(fields.name),
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
BeforeListTable: [
|
||||||
|
() =>
|
||||||
|
QuickFilters({
|
||||||
|
slug: Collections.GenericContents,
|
||||||
|
filterGroups: [
|
||||||
|
Object.entries(LanguageCodes).map(([key, value]) => ({
|
||||||
|
label: `∅ ${value}`,
|
||||||
|
filter: { where: { "translations.language": { not_equals: key } } },
|
||||||
|
})),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: fields.name,
|
||||||
|
type: "text",
|
||||||
|
required: true,
|
||||||
|
unique: true,
|
||||||
|
},
|
||||||
|
translatedFields({
|
||||||
|
name: fields.translations,
|
||||||
|
minRows: 1,
|
||||||
|
required: true,
|
||||||
|
interfaceName: "CategoryTranslations",
|
||||||
|
admin: {
|
||||||
|
useAsTitle: fields.translationsName,
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
rowField([
|
||||||
|
{
|
||||||
|
name: fields.translationsName,
|
||||||
|
type: "textarea",
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
|
@ -1,11 +1,11 @@
|
||||||
import { RowLabelArgs } from "payload/dist/admin/components/forms/RowLabel/types";
|
import { RowLabelArgs } from "payload/dist/admin/components/forms/RowLabel/types";
|
||||||
import {
|
import {
|
||||||
|
CollectibleBindingTypes,
|
||||||
|
CollectiblePageOrders,
|
||||||
CollectionGroups,
|
CollectionGroups,
|
||||||
Collections,
|
Collections,
|
||||||
FileTypes,
|
FileTypes,
|
||||||
KeysTypes,
|
KeysTypes,
|
||||||
LibraryItemsTextualBindingTypes,
|
|
||||||
LibraryItemsTextualPageOrders,
|
|
||||||
LibraryItemsTypes,
|
LibraryItemsTypes,
|
||||||
PageType,
|
PageType,
|
||||||
} from "../../constants";
|
} from "../../constants";
|
||||||
|
@ -493,7 +493,7 @@ export const LibraryItems = buildVersionedCollectionConfig({
|
||||||
{
|
{
|
||||||
name: fields.textualBindingType,
|
name: fields.textualBindingType,
|
||||||
type: "radio",
|
type: "radio",
|
||||||
options: Object.entries(LibraryItemsTextualBindingTypes).map(
|
options: Object.entries(CollectibleBindingTypes).map(
|
||||||
([value, label]) => ({
|
([value, label]) => ({
|
||||||
label,
|
label,
|
||||||
value,
|
value,
|
||||||
|
@ -507,7 +507,7 @@ export const LibraryItems = buildVersionedCollectionConfig({
|
||||||
{
|
{
|
||||||
name: fields.textualPageOrder,
|
name: fields.textualPageOrder,
|
||||||
type: "radio",
|
type: "radio",
|
||||||
options: Object.entries(LibraryItemsTextualPageOrders).map(
|
options: Object.entries(CollectiblePageOrders).map(
|
||||||
([value, label]) => ({
|
([value, label]) => ({
|
||||||
label,
|
label,
|
||||||
value,
|
value,
|
||||||
|
|
|
@ -49,6 +49,8 @@ export const Tags: CollectionConfig = buildCollectionConfig({
|
||||||
translatedFields({
|
translatedFields({
|
||||||
name: fields.translations,
|
name: fields.translations,
|
||||||
admin: { useAsTitle: fields.translationsName },
|
admin: { useAsTitle: fields.translationsName },
|
||||||
|
required: true,
|
||||||
|
minRows: 1,
|
||||||
fields: [{ name: fields.translationsName, type: "text", required: true }],
|
fields: [{ name: fields.translationsName, type: "text", required: true }],
|
||||||
}),
|
}),
|
||||||
{ name: fields.group, type: "relationship", required: true, relationTo: Collections.TagsGroups },
|
{ name: fields.group, type: "relationship", required: true, relationTo: Collections.TagsGroups },
|
||||||
|
|
|
@ -28,6 +28,8 @@ export const TagsGroups: CollectionConfig = buildCollectionConfig({
|
||||||
translatedFields({
|
translatedFields({
|
||||||
name: fields.translations,
|
name: fields.translations,
|
||||||
admin: { useAsTitle: fields.translationsName },
|
admin: { useAsTitle: fields.translationsName },
|
||||||
|
required: true,
|
||||||
|
minRows: 1,
|
||||||
fields: [{ name: fields.translationsName, type: "text", required: true }],
|
fields: [{ name: fields.translationsName, type: "text", required: true }],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|
|
@ -34,7 +34,9 @@ export enum Collections {
|
||||||
Tags = "tags",
|
Tags = "tags",
|
||||||
TagsGroups = "tags-groups",
|
TagsGroups = "tags-groups",
|
||||||
Images = "images",
|
Images = "images",
|
||||||
Wordings = "wordings"
|
Wordings = "wordings",
|
||||||
|
Collectibles = "collectibles",
|
||||||
|
GenericContents = "generic-contents",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CollectionGroups {
|
export enum CollectionGroups {
|
||||||
|
@ -80,12 +82,12 @@ export enum LibraryItemsTypes {
|
||||||
Other = "Other",
|
Other = "Other",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum LibraryItemsTextualBindingTypes {
|
export enum CollectibleBindingTypes {
|
||||||
Paperback = "Paperback",
|
Paperback = "Paperback",
|
||||||
Hardcover = "Hardcover",
|
Hardcover = "Hardcover",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum LibraryItemsTextualPageOrders {
|
export enum CollectiblePageOrders {
|
||||||
LeftToRight = "Left to right",
|
LeftToRight = "Left to right",
|
||||||
RightToLeft = "Right to left",
|
RightToLeft = "Right to left",
|
||||||
}
|
}
|
||||||
|
@ -109,7 +111,7 @@ export enum VideoSources {
|
||||||
|
|
||||||
export enum PageType {
|
export enum PageType {
|
||||||
Content = "Content",
|
Content = "Content",
|
||||||
Article = "Article",
|
Post = "Post",
|
||||||
Generic = "Generic",
|
Generic = "Generic",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +122,17 @@ export enum SpacerSizes {
|
||||||
XLarge = "Extra Large",
|
XLarge = "Extra Large",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum CollectibleNature {
|
||||||
|
Physical = "Physical",
|
||||||
|
Digital = "Digital",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum CollectibleContentType {
|
||||||
|
None = "None",
|
||||||
|
Indexes = "Index-based",
|
||||||
|
Pages = "Page-based",
|
||||||
|
}
|
||||||
|
|
||||||
/* RICH TEXT */
|
/* RICH TEXT */
|
||||||
|
|
||||||
export type RichTextContent = {
|
export type RichTextContent = {
|
||||||
|
|
|
@ -4,10 +4,12 @@ import path from "path";
|
||||||
import { buildConfig } from "payload/config";
|
import { buildConfig } from "payload/config";
|
||||||
import { ChronologyEras } from "./collections/ChronologyEras/ChronologyEras";
|
import { ChronologyEras } from "./collections/ChronologyEras/ChronologyEras";
|
||||||
import { ChronologyItems } from "./collections/ChronologyItems/ChronologyItems";
|
import { ChronologyItems } from "./collections/ChronologyItems/ChronologyItems";
|
||||||
|
import { Collectibles } from "./collections/Collectibles/Collectibles";
|
||||||
import { Currencies } from "./collections/Currencies/Currencies";
|
import { Currencies } from "./collections/Currencies/Currencies";
|
||||||
import { Files } from "./collections/Files/Files";
|
import { Files } from "./collections/Files/Files";
|
||||||
import { Folders } from "./collections/Folders/Folders";
|
import { Folders } from "./collections/Folders/Folders";
|
||||||
import { FoldersThumbnails } from "./collections/FoldersThumbnails/FoldersThumbnails";
|
import { FoldersThumbnails } from "./collections/FoldersThumbnails/FoldersThumbnails";
|
||||||
|
import { GenericContents } from "./collections/GenericContents/GenericContents";
|
||||||
import { Images } from "./collections/Images/Images";
|
import { Images } from "./collections/Images/Images";
|
||||||
import { Keys } from "./collections/Keys/Keys";
|
import { Keys } from "./collections/Keys/Keys";
|
||||||
import { Languages } from "./collections/Languages/Languages";
|
import { Languages } from "./collections/Languages/Languages";
|
||||||
|
@ -71,7 +73,9 @@ export default buildConfig({
|
||||||
Tags,
|
Tags,
|
||||||
TagsGroups,
|
TagsGroups,
|
||||||
Images,
|
Images,
|
||||||
Wordings
|
Wordings,
|
||||||
|
Collectibles,
|
||||||
|
GenericContents,
|
||||||
],
|
],
|
||||||
db: mongooseAdapter({
|
db: mongooseAdapter({
|
||||||
url: process.env.MONGODB_URI ?? "mongodb://mongo:27017/payload",
|
url: process.env.MONGODB_URI ?? "mongodb://mongo:27017/payload",
|
||||||
|
|
|
@ -64,25 +64,22 @@ html[data-theme="light"] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide header on blocks with classname "no-label"
|
// Hide header on fields with classname "no-label"
|
||||||
|
|
||||||
.field-type.no-label > header {
|
.field-type.no-label > header {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lexical-block__block-pill-transcriptBlock + .section-title {
|
.lexical-block__block-pill-transcriptBlock + .section-title,
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lexical-block__block-pill-spacerBlock + .section-title {
|
.lexical-block__block-pill-spacerBlock + .section-title {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.blocks-field__block-pill-cueBlock + .section-title {
|
.blocks-field__block-pill-cueBlock + .section-title,
|
||||||
display: none;
|
.blocks-field__block-pill-spacerBlock + .section-title,
|
||||||
}
|
.blocks-field__block-pill-pageRange + .section-title,
|
||||||
|
.blocks-field__block-pill-timeRange + .section-title,
|
||||||
.blocks-field__block-pill-spacerBlock + .section-title {
|
.blocks-field__block-pill-other + .section-title {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue