Use attributes instead of group tags

This commit is contained in:
DrMint 2024-05-15 13:44:50 +02:00
parent c6165c251c
commit 46613c8500
24 changed files with 363 additions and 149 deletions

View File

@ -0,0 +1,25 @@
import { Block } from "payload/types";
import { AttributeTypes, Collections } from "../../constants";
import { rowField } from "../../fields/rowField/rowField";
export const numberBlock: Block = {
slug: "numberBlock",
interfaceName: "NumberBlock",
labels: { singular: "Number attribute", plural: "Number attributes" },
fields: [
rowField([
{
name: "name",
type: "relationship",
relationTo: Collections.Attributes,
filterOptions: () => ({ type: { equals: AttributeTypes.Number } }),
required: true,
},
{
name: "number",
type: "number",
required: true,
},
]),
],
};

View File

@ -0,0 +1,28 @@
import { Block } from "payload/types";
import { AttributeTypes, Collections } from "../../constants";
import { rowField } from "../../fields/rowField/rowField";
export const tagsBlock: Block = {
slug: "tagsBlock",
interfaceName: "TagsBlock",
labels: { singular: "Tags attribute", plural: "Tags attributes" },
fields: [
rowField([
{
name: "name",
type: "relationship",
relationTo: Collections.Attributes,
filterOptions: () => ({ type: { equals: AttributeTypes.Tags } }),
required: true,
},
{
name: "tags",
type: "relationship",
relationTo: Collections.Tags,
required: true,
hasMany: true,
minRows: 1,
},
]),
],
};

View File

@ -0,0 +1,25 @@
import { Block } from "payload/types";
import { AttributeTypes, Collections } from "../../constants";
import { rowField } from "../../fields/rowField/rowField";
export const textBlock: Block = {
slug: "textBlock",
interfaceName: "TextBlock",
labels: { singular: "Text attribute", plural: "Text attributes" },
fields: [
rowField([
{
name: "name",
type: "relationship",
relationTo: Collections.Attributes,
filterOptions: () => ({ type: { equals: AttributeTypes.Text } }),
required: true,
},
{
name: "text",
type: "textarea",
required: true,
},
]),
],
};

View File

@ -0,0 +1,51 @@
import { CollectionConfig } from "payload/types";
import { mustBeAdmin } from "../../accesses/fields/mustBeAdmin";
import { AttributeTypes, CollectionGroups, Collections } from "../../constants";
import { iconField } from "../../fields/iconField/iconField";
import { rowField } from "../../fields/rowField/rowField";
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",
type: "type",
};
export const Attributes: CollectionConfig = buildCollectionConfig({
slug: Collections.Attributes,
labels: { singular: "Attribute", plural: "Attributes" },
admin: {
group: CollectionGroups.Meta,
useAsTitle: fields.slug,
defaultColumns: [fields.slug, fields.icon, fields.type, fields.translations],
},
fields: [
rowField([
slugField({ name: fields.slug }),
iconField({ name: fields.icon }),
{
name: fields.type,
type: "select",
access: {
update: mustBeAdmin,
},
required: true,
options: Object.values(AttributeTypes).map((value) => ({
label: value,
value: value,
})),
},
]),
translatedFields({
name: fields.translations,
admin: { useAsTitle: fields.translationsName },
required: true,
minRows: 1,
fields: [{ name: fields.translationsName, type: "text", required: true }],
}),
],
});

View File

@ -1,4 +1,5 @@
import { CollectionGroups, Collections } from "../../constants";
import { attributesField } from "../../fields/attributesField/attributesField";
import { creditsField } from "../../fields/creditsField/creditsField";
import { imageField } from "../../fields/imageField/imageField";
import { rowField } from "../../fields/rowField/rowField";
@ -21,6 +22,7 @@ const fields = {
thumbnail: "thumbnail",
duration: "duration",
tags: "tags",
attributes: "attributes",
credits: "credits",
};
@ -72,6 +74,7 @@ export const Audios = buildCollectionConfig({
],
}),
tagsField({ name: fields.tags }),
attributesField({ name: fields.attributes }),
creditsField({ name: fields.credits }),
],
});

View File

@ -5,9 +5,9 @@ import { Audio } from "../../../types/collections";
import { CollectionEndpoint } from "../../../types/payload";
import { isNotEmpty, isValidPayloadImage, isValidPayloadMedia } from "../../../utils/asserts";
import {
convertAttributesToEndpointAttributes,
convertCreditsToEndpointCredits,
convertRTCToEndpointRTC,
convertTagsEndpointTagsGroups,
getLanguageId,
} from "../../../utils/endpoints";
@ -48,7 +48,7 @@ export const getByID: CollectionEndpoint = {
export const convertAudioToEndpointAudio = ({
url,
tags,
attributes,
translations,
mimeType,
createdAt,
@ -61,7 +61,7 @@ export const convertAudioToEndpointAudio = ({
credits,
}: Audio & PayloadMedia): EndpointAudio => ({
url,
tagGroups: convertTagsEndpointTagsGroups(tags),
attributes: convertAttributesToEndpointAttributes(attributes),
createdAt,
filename,
filesize,

View File

@ -7,6 +7,7 @@ import {
CollectionGroups,
Collections,
} from "../../constants";
import { attributesField } from "../../fields/attributesField/attributesField";
import { backPropagationField } from "../../fields/backPropagationField/backPropagationField";
import { componentField } from "../../fields/componentField/componentField";
import { creditsField } from "../../fields/creditsField/creditsField";
@ -34,6 +35,7 @@ const fields = {
backgroundImage: "backgroundImage",
nature: "nature",
tags: "tags",
attributes: "attributes",
languages: "languages",
translations: "translations",
@ -189,6 +191,7 @@ export const Collectibles = buildVersionedCollectionConfig({
]),
tagsField({ name: fields.tags }),
attributesField({ name: fields.attributes }),
translatedFields({
name: fields.translations,

View File

@ -12,8 +12,8 @@ import {
isValidPayloadMedia,
} from "../../../utils/asserts";
import {
convertAttributesToEndpointAttributes,
convertSourceToEndpointSource,
convertTagsEndpointTagsGroups,
getDomainFromUrl,
} from "../../../utils/endpoints";
import { convertAudioToEndpointAudio } from "../../Audios/endpoints/getByID";
@ -52,7 +52,7 @@ export const convertCollectibleToEndpointCollectible = ({
releaseDate,
languages,
scans: rawScans,
tags,
attributes,
createdAt,
updatedAt,
scansEnabled,
@ -72,7 +72,7 @@ export const convertCollectibleToEndpointCollectible = ({
...(isValidPayloadImage(backgroundImage)
? { backgroundImage: convertImageToEndpointImage(backgroundImage) }
: {}),
tagGroups: convertTagsEndpointTagsGroups(tags),
attributes: convertAttributesToEndpointAttributes(attributes),
translations:
translations?.map(({ language, title, description, pretitle, subtitle }) => ({
language: isPayloadType(language) ? language.id : language,

View File

@ -1,4 +1,5 @@
import { Collections } from "../../constants";
import { attributesField } from "../../fields/attributesField/attributesField";
import { creditsField } from "../../fields/creditsField/creditsField";
import { rowField } from "../../fields/rowField/rowField";
import { tagsField } from "../../fields/tagsField/tagsField";
@ -19,6 +20,7 @@ const fields = {
translationsSubtitle: "subtitle",
translationsDescription: "description",
tags: "tags",
attributes: "attributes",
credits: "credits",
} as const satisfies Record<string, string>;
@ -64,6 +66,7 @@ export const Images = buildImageCollectionConfig({
],
}),
tagsField({ name: fields.tags }),
attributesField({ name: fields.attributes }),
creditsField({ name: fields.credits }),
],
});

View File

@ -5,9 +5,9 @@ import { Image } from "../../../types/collections";
import { CollectionEndpoint } from "../../../types/payload";
import { isNotEmpty, isValidPayloadImage } from "../../../utils/asserts";
import {
convertAttributesToEndpointAttributes,
convertCreditsToEndpointCredits,
convertRTCToEndpointRTC,
convertTagsEndpointTagsGroups,
getLanguageId,
} from "../../../utils/endpoints";
@ -50,7 +50,7 @@ export const convertImageToEndpointImage = ({
url,
width,
height,
tags,
attributes,
translations,
mimeType,
createdAt,
@ -63,7 +63,7 @@ export const convertImageToEndpointImage = ({
url,
width,
height,
tagGroups: convertTagsEndpointTagsGroups(tags),
attributes: convertAttributesToEndpointAttributes(attributes),
createdAt,
filename,
filesize,

View File

@ -4,6 +4,7 @@ import { sectionBlock } from "../../blocks/sectionBlock";
import { transcriptBlock } from "../../blocks/transcriptBlock";
import { QuickFilters, publishStatusFilters } from "../../components/QuickFilters";
import { CollectionGroups, Collections } from "../../constants";
import { attributesField } from "../../fields/attributesField/attributesField";
import { backPropagationField } from "../../fields/backPropagationField/backPropagationField";
import { creditsField } from "../../fields/creditsField/creditsField";
import { imageField } from "../../fields/imageField/imageField";
@ -24,6 +25,7 @@ const fields = {
backgroundImage: "backgroundImage",
translations: "translations",
tags: "tags",
attributes: "attributes",
sourceLanguage: "sourceLanguage",
pretitle: "pretitle",
title: "title",
@ -89,6 +91,7 @@ export const Pages = buildVersionedCollectionConfig({
}),
]),
tagsField({ name: fields.tags }),
attributesField({ name: fields.attributes }),
translatedFields({
name: fields.translations,
admin: { useAsTitle: fields.title, hasSourceLanguage: true },

View File

@ -11,10 +11,10 @@ import { EndpointPage, TableOfContentEntry } from "../../../sdk";
import { Page } from "../../../types/collections";
import { isNotEmpty, isPayloadType, isValidPayloadImage } from "../../../utils/asserts";
import {
convertAttributesToEndpointAttributes,
convertCreditsToEndpointCredits,
convertRTCToEndpointRTC,
convertSourceToEndpointSource,
convertTagsEndpointTagsGroups,
} from "../../../utils/endpoints";
import { convertImageToEndpointImage } from "../../Images/endpoints/getByID";
import { convertRecorderToEndpointRecorder } from "../../Recorders/endpoints/getByUsername";
@ -31,7 +31,7 @@ export const convertPageToEndpointPage = ({
folders,
backgroundImage,
slug,
tags,
attributes,
thumbnail,
createdAt,
updatedAt,
@ -42,7 +42,7 @@ export const convertPageToEndpointPage = ({
...(isValidPayloadImage(backgroundImage)
? { backgroundImage: convertImageToEndpointImage(backgroundImage) }
: {}),
tagGroups: convertTagsEndpointTagsGroups(tags),
attributes: convertAttributesToEndpointAttributes(attributes),
translations: translations.map(
({ content, language, sourceLanguage, title, pretitle, subtitle, summary, credits }) => ({
language: isPayloadType(language) ? language.id : language,

View File

@ -1,36 +1,16 @@
import payload from "payload";
import { CollectionBeforeChangeHook, CollectionConfig } from "payload/types";
import { CollectionConfig } from "payload/types";
import { CollectionGroups, Collections } from "../../constants";
import { rowField } from "../../fields/rowField/rowField";
import { slugField } from "../../fields/slugField/slugField";
import { translatedFields } from "../../fields/translatedFields/translatedFields";
import { beforeDuplicateAddCopyTo } from "../../hooks/beforeDuplicateAddCopyTo";
import { buildCollectionConfig } from "../../utils/collectionConfig";
const beforeChangeUpdateName: CollectionBeforeChangeHook = async ({ data }) => {
let name = data.slug;
const parentId = data[fields.group];
if (parentId) {
const parent = await payload.findByID({
collection: Collections.TagsGroups,
id: data[fields.group],
});
name = `${parent.slug} / ${data.slug}`;
}
return {
...data,
[fields.name]: name,
};
};
const fields = {
slug: "slug",
name: "name",
translations: "translations",
translationsName: "name",
group: "group",
page: "page",
};
export const Tags: CollectionConfig = buildCollectionConfig({
@ -38,16 +18,27 @@ export const Tags: CollectionConfig = buildCollectionConfig({
labels: { singular: "Tag", plural: "Tags" },
admin: {
group: CollectionGroups.Meta,
useAsTitle: fields.name,
defaultColumns: [fields.slug, fields.group, fields.translations],
useAsTitle: fields.slug,
defaultColumns: [fields.slug, fields.translations],
hooks: {
beforeDuplicate: beforeDuplicateAddCopyTo(fields.slug),
},
},
hooks: { beforeChange: [beforeChangeUpdateName] },
fields: [
{ name: fields.name, type: "text", admin: { readOnly: true, hidden: true } },
rowField([
slugField({ name: fields.slug }),
{
name: fields.page,
type: "relationship",
relationTo: Collections.Pages,
admin: {
description:
"You can declare a 'definition' page where more information of the tag will be presented.\
The selected page will then feature a new section\
where elements tagged with this tag will be listed.",
},
},
]),
translatedFields({
name: fields.translations,
admin: { useAsTitle: fields.translationsName },
@ -55,11 +46,5 @@ export const Tags: CollectionConfig = buildCollectionConfig({
minRows: 1,
fields: [{ name: fields.translationsName, type: "text", required: true }],
}),
{
name: fields.group,
type: "relationship",
required: true,
relationTo: Collections.TagsGroups,
},
],
});

View File

@ -1,34 +0,0 @@
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 TagsGroups: CollectionConfig = buildCollectionConfig({
slug: Collections.TagsGroups,
labels: { singular: "Tags Group", plural: "Tags Groups" },
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 }],
}),
],
});

View File

@ -1,4 +1,5 @@
import { CollectionGroups, Collections } from "../../constants";
import { attributesField } from "../../fields/attributesField/attributesField";
import { componentField } from "../../fields/componentField/componentField";
import { creditsField } from "../../fields/creditsField/creditsField";
import { imageField } from "../../fields/imageField/imageField";
@ -23,6 +24,7 @@ const fields = {
thumbnail: "thumbnail",
duration: "duration",
tags: "tags",
attributes: "attributes",
platform: "platform",
platformChannel: "channel",
platformViews: "views",
@ -87,6 +89,7 @@ export const Videos = buildCollectionConfig({
],
}),
tagsField({ name: fields.tags }),
attributesField({ name: fields.attributes }),
creditsField({ name: fields.credits }),
componentField({
name: fields.platform,

View File

@ -13,9 +13,9 @@ import {
isValidPayloadMedia,
} from "../../../utils/asserts";
import {
convertAttributesToEndpointAttributes,
convertCreditsToEndpointCredits,
convertRTCToEndpointRTC,
convertTagsEndpointTagsGroups,
getLanguageId,
} from "../../../utils/endpoints";
@ -56,7 +56,7 @@ export const getByID: CollectionEndpoint = {
export const convertVideoToEndpointVideo = ({
url,
tags,
attributes,
translations,
mimeType,
createdAt,
@ -71,7 +71,7 @@ export const convertVideoToEndpointVideo = ({
credits,
}: Video & PayloadMedia): EndpointVideo => ({
url,
tagGroups: convertTagsEndpointTagsGroups(tags),
attributes: convertAttributesToEndpointAttributes(attributes),
createdAt,
filename,
filesize,

View File

@ -4,26 +4,26 @@ import type { BreakBlock, SectionBlock, TranscriptBlock } from "./types/collecti
// END MOCKING SECTION
export enum Collections {
Attributes = "attributes",
Audios = "audios",
ChronologyEvents = "chronology-events",
Collectibles = "collectibles",
CreditsRole = "credits-roles",
Currencies = "currencies",
Folders = "folders",
GenericContents = "generic-contents",
Images = "images",
Languages = "languages",
MediaThumbnails = "media-thumbnails",
Pages = "pages",
Recorders = "recorders",
Folders = "folders",
Tags = "tags",
TagsGroups = "tags-groups",
Images = "images",
Wordings = "wordings",
Collectibles = "collectibles",
GenericContents = "generic-contents",
WebsiteConfig = "website-config",
Videos = "videos",
VideosSubtitles = "videos-subtitles",
VideosChannels = "videos-channels",
MediaThumbnails = "media-thumbnails",
Scans = "scans",
CreditsRole = "credits-roles",
Tags = "tags",
Videos = "videos",
VideosChannels = "videos-channels",
VideosSubtitles = "videos-subtitles",
Wordings = "wordings",
WebsiteConfig = "website-config",
}
export enum CollectionGroups {
@ -80,6 +80,12 @@ export enum CollectionStatus {
Published = "published",
}
export enum AttributeTypes {
Number = "Number",
Text = "Text",
Tags = "Tags",
}
/* RICH TEXT */
export type RichTextContent = {

View File

@ -0,0 +1,12 @@
import { BlockField } from "payload/dist/fields/config/types";
import { numberBlock } from "../../blocks/attributeBlocks/numberBlock";
import { tagsBlock } from "../../blocks/attributeBlocks/tagsBlock";
import { textBlock } from "../../blocks/attributeBlocks/textBlock";
type AttributesFieldProps = Omit<BlockField, "type" | "blocks">;
export const attributesField = ({ ...props }: AttributesFieldProps): BlockField => ({
...props,
type: "blocks",
blocks: [tagsBlock, numberBlock, textBlock],
});

View File

@ -4,6 +4,7 @@ import { cloudStorage } from "@payloadcms/plugin-cloud-storage";
import path from "path";
import { buildConfig } from "payload/config";
import { sftpAdapter } from "payloadcms-sftp-storage";
import { Attributes } from "./collections/Attributes/Attributes";
import { Audios } from "./collections/Audios/Audios";
import { ChronologyEvents } from "./collections/ChronologyEvents/ChronologyEvents";
import { Collectibles } from "./collections/Collectibles/Collectibles";
@ -13,15 +14,14 @@ import { Folders } from "./collections/Folders/Folders";
import { GenericContents } from "./collections/GenericContents/GenericContents";
import { Images } from "./collections/Images/Images";
import { Languages } from "./collections/Languages/Languages";
import { MediaThumbnails } from "./collections/MediaThumbnails/MediaThumbnails";
import { Pages } from "./collections/Pages/Pages";
import { Recorders } from "./collections/Recorders/Recorders";
import { Scans } from "./collections/Scans/Scans";
import { Tags } from "./collections/Tags/Tags";
import { TagsGroups } from "./collections/TagsGroups/TagsGroups";
import { Videos } from "./collections/Videos/Videos";
import { VideosChannels } from "./collections/VideosChannels/VideosChannels";
import { VideosSubtitles } from "./collections/VideosSubtitles/VideosSubtitles";
import { MediaThumbnails } from "./collections/VideosThumbnails/VideosThumbnails";
import { WebsiteConfig } from "./collections/WebsiteConfig/WebsiteConfig";
import { Wordings } from "./collections/Wordings/Wordings";
import { Icon } from "./components/Icon";
@ -68,7 +68,7 @@ export default buildConfig({
Scans,
Tags,
TagsGroups,
Attributes,
CreditsRoles,
Recorders,
Languages,

View File

@ -1,4 +1,5 @@
import {
AttributeTypes,
CollectibleBindingTypes,
CollectibleNature,
CollectiblePageOrders,
@ -173,22 +174,42 @@ export type EndpointWording = {
export type EndpointTag = {
slug: string;
page?: EndpointPage;
translations: {
language: string;
name: string;
}[];
};
export type EndpointTagsGroup = {
export type EndpointGenericAttribute = {
slug: string;
icon: string;
translations: {
language: string;
name: string;
}[];
tags: EndpointTag[];
};
export type EndpointNumberAttribute = EndpointGenericAttribute & {
type: AttributeTypes.Number;
value: number;
};
export type EndpointTextAttribute = EndpointGenericAttribute & {
type: AttributeTypes.Text;
value: string;
};
export type EndpointTagsAttribute = EndpointGenericAttribute & {
type: AttributeTypes.Tags;
value: EndpointTag[];
};
export type EndpointAttribute =
| EndpointNumberAttribute
| EndpointTextAttribute
| EndpointTagsAttribute;
export type EndpointRole = {
icon: string;
translations: {
@ -205,7 +226,7 @@ export type EndpointCredit = {
export type EndpointPage = {
slug: string;
thumbnail?: EndpointImage;
tagGroups: EndpointTagsGroup[];
attributes: EndpointAttribute[];
backgroundImage?: EndpointImage;
translations: {
language: string;
@ -234,7 +255,7 @@ export type EndpointCollectible = {
subtitle?: string;
description?: RichTextContent;
}[];
tagGroups: EndpointTagsGroup[];
attributes: EndpointAttribute[];
releaseDate?: string;
languages: string[];
backgroundImage?: EndpointImage;
@ -458,7 +479,7 @@ export type EndpointMedia = {
filesize: number;
updatedAt: string;
createdAt: string;
tagGroups: EndpointTagsGroup[];
attributes: EndpointAttribute[];
translations: {
language: string;
pretitle?: string;

View File

@ -75,6 +75,9 @@ html[data-theme="light"] {
}
.blocks-field__block-pill-cueBlock + .section-title,
.blocks-field__block-pill-tagsBlock + .section-title,
.blocks-field__block-pill-textBlock + .section-title,
.blocks-field__block-pill-numberBlock + .section-title,
.blocks-field__block-pill-pageRange + .section-title,
.blocks-field__block-pill-timeRange + .section-title,
.blocks-field__block-pill-urlBlock + .section-title,

View File

@ -32,7 +32,7 @@ export interface Config {
"videos-channels": VideosChannel;
scans: Scan;
tags: Tag;
"tags-groups": TagsGroup;
attributes: Attribute;
"credits-roles": CreditsRole;
recorders: Recorder;
languages: Language;
@ -56,6 +56,7 @@ export interface Page {
thumbnail?: string | Image | null;
backgroundImage?: string | Image | null;
tags?: (string | Tag)[] | null;
attributes?: (TagsBlock | NumberBlock | TextBlock)[] | null;
translations: {
language: string | Language;
sourceLanguage: string | Language;
@ -133,6 +134,7 @@ export interface Image {
}[]
| null;
tags?: (string | Tag)[] | null;
attributes?: (TagsBlock | NumberBlock | TextBlock)[] | null;
credits?: Credits;
updatedAt: string;
createdAt: string;
@ -175,25 +177,36 @@ export interface Language {
*/
export interface Tag {
id: string;
name?: string | null;
slug: string;
page?: (string | null) | Page;
translations: {
language: string | Language;
name: string;
id?: string | null;
}[];
group: string | TagsGroup;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "tags-groups".
* via the `definition` "TagsBlock".
*/
export interface TagsGroup {
export interface TagsBlock {
name: string | Attribute;
tags: (string | Tag)[];
id?: string | null;
blockName?: string | null;
blockType: "tagsBlock";
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "attributes".
*/
export interface Attribute {
id: string;
slug: string;
icon?: string | null;
type: "Number" | "Text" | "Tags";
translations: {
language: string | Language;
name: string;
@ -202,6 +215,28 @@ export interface TagsGroup {
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "NumberBlock".
*/
export interface NumberBlock {
name: string | Attribute;
number: number;
id?: string | null;
blockName?: string | null;
blockType: "numberBlock";
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "TextBlock".
*/
export interface TextBlock {
name: string | Attribute;
text: string;
id?: string | null;
blockName?: string | null;
blockType: "textBlock";
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "credits-roles".
@ -318,6 +353,7 @@ export interface Collectible {
nature: "Physical" | "Digital";
languages?: (string | Language)[] | null;
tags?: (string | Tag)[] | null;
attributes?: (TagsBlock | NumberBlock | TextBlock)[] | null;
translations: {
language: string | Language;
pretitle?: string | null;
@ -582,6 +618,7 @@ export interface Audio {
id?: string | null;
}[];
tags?: (string | Tag)[] | null;
attributes?: (TagsBlock | NumberBlock | TextBlock)[] | null;
credits?: Credits;
updatedAt: string;
createdAt: string;
@ -657,6 +694,7 @@ export interface Video {
id?: string | null;
}[];
tags?: (string | Tag)[] | null;
attributes?: (TagsBlock | NumberBlock | TextBlock)[] | null;
credits?: Credits;
platformEnabled?: boolean | null;
platform?: {

View File

@ -2,9 +2,11 @@ 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 { convertPageToEndpointPage } from "../collections/Pages/endpoints/getBySlugEndpoint";
import { convertRecorderToEndpointRecorder } from "../collections/Recorders/endpoints/getByUsername";
import { convertVideoToEndpointVideo } from "../collections/Videos/endpoints/getByID";
import {
AttributeTypes,
RichTextBreakBlock,
RichTextContent,
RichTextSectionBlock,
@ -18,11 +20,11 @@ import {
isUploadNodeVideoNode,
} from "../constants";
import {
EndpointAttribute,
EndpointCredit,
EndpointRole,
EndpointSource,
EndpointTag,
EndpointTagsGroup,
} from "../sdk";
import {
Audio,
@ -32,10 +34,15 @@ import {
Folder,
Image,
Language,
NumberBlock,
Tag,
TagsBlock,
TextBlock,
Video,
} from "../types/collections";
import {
isDefined,
isEmpty,
isPayloadArrayType,
isPayloadType,
isPublished,
@ -43,45 +50,14 @@ import {
isValidPayloadMedia,
} from "./asserts";
export const convertTagsEndpointTagsGroups = (
tags: (string | Tag)[] | null | undefined
): EndpointTagsGroup[] => {
if (!isPayloadArrayType(tags)) {
return [];
}
const groups: EndpointTagsGroup[] = [];
tags.forEach(({ translations, slug, group }) => {
if (isPayloadType(group)) {
const existingGroup = groups.find((existingGroup) => existingGroup.slug === group.slug);
const endpointTag: EndpointTag = {
const convertTagToEndpointTag = ({ slug, page, translations }: Tag): EndpointTag => ({
slug,
...(page && isPayloadType(page) ? { page: convertPageToEndpointPage(page) } : {}),
translations: translations.map(({ language, name }) => ({
language: isPayloadType(language) ? language.id : language,
name,
})),
};
if (existingGroup) {
existingGroup.tags.push(endpointTag);
} else {
groups.push({
slug: group.slug,
icon: group.icon ?? "material-symbols:category-outline",
tags: [endpointTag],
translations: group.translations.map(({ language, name }) => ({
language: isPayloadType(language) ? language.id : language,
name,
})),
});
}
}
});
return groups;
};
export const convertRTCToEndpointRTC = (
{ root: { children, ...others } }: RichTextContent,
@ -233,3 +209,66 @@ export const convertCreditsToEndpointCredits = (credits?: Credits | null): Endpo
},
];
}) ?? [];
export const convertAttributesToEndpointAttributes = (
attributes: (TagsBlock | NumberBlock | TextBlock)[] | null | undefined
): EndpointAttribute[] =>
attributes?.map(convertAttributeToEndpointAttribute).filter(isDefined) ?? [];
const convertAttributeToEndpointAttribute = (
attribute: TagsBlock | NumberBlock | TextBlock
): EndpointAttribute | undefined => {
switch (attribute.blockType) {
case "numberBlock": {
const { name, number } = attribute;
if (!isPayloadType(name)) return;
const { slug, icon, translations } = name;
return {
slug,
icon: icon ?? "material-symbols:category-outline",
translations: translations.map(({ language, name }) => ({
language: isPayloadType(language) ? language.id : language,
name,
})),
type: AttributeTypes.Number,
value: number,
};
}
case "textBlock": {
const { name, text } = attribute;
if (!isPayloadType(name)) return;
if (isEmpty(text)) return;
const { slug, icon, translations } = name;
return {
slug,
icon: icon ?? "material-symbols:category-outline",
translations: translations.map(({ language, name }) => ({
language: isPayloadType(language) ? language.id : language,
name,
})),
type: AttributeTypes.Text,
value: text,
};
}
case "tagsBlock": {
const { name, tags } = attribute;
if (!isPayloadType(name)) return;
if (!isPayloadArrayType(tags)) return;
if (tags.length === 0) return;
const { slug, icon, translations } = name;
return {
slug,
icon: icon ?? "material-symbols:category-outline",
translations: translations.map(({ language, name }) => ({
language: isPayloadType(language) ? language.id : language,
name,
})),
type: AttributeTypes.Tags,
value: tags.map(convertTagToEndpointTag),
};
}
}
};