Added folders

This commit is contained in:
DrMint 2024-01-20 03:25:52 +01:00
parent cbd0251ad5
commit e8d8c8e6a8
16 changed files with 1300 additions and 814 deletions

View File

@ -3,7 +3,7 @@
"editor.rulers": [100],
"typescript.preferences.importModuleSpecifier": "non-relative",
"editor.codeActionsOnSave": {
"source.fixAll": true,
"source.organizeImports": true
"source.fixAll": "explicit",
"source.organizeImports": "explicit"
}
}

BIN
bun.lockb

Binary file not shown.

View File

@ -2,7 +2,7 @@ version: "3"
services:
payload:
image: node:18-alpine
image: docker.io/library/node:18-alpine
ports:
- "${PAYLOAD_PORT}:${PAYLOAD_PORT}"
volumes:
@ -20,7 +20,7 @@ services:
NODE_ENV: development
mongo:
image: mongo:latest
image: docker.io/library/mongo:latest
ports:
- "${MONGODB_PORT}:27017"
command:

776
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -24,23 +24,24 @@
},
"dependencies": {
"@fontsource/vollkorn": "^5.0.17",
"@payloadcms/bundler-webpack": "^1.0.4",
"@payloadcms/db-mongodb": "^1.0.4",
"@payloadcms/richtext-lexical": "^0.1.15",
"@payloadcms/bundler-webpack": "^1.0.5",
"@payloadcms/db-mongodb": "^1.0.8",
"@payloadcms/richtext-lexical": "^0.1.17",
"cross-env": "^7.0.3",
"language-tags": "^1.0.9",
"luxon": "^3.4.3",
"payload": "^2.0.13",
"styled-components": "^6.1.0"
"payload": "^2.1.1",
"sharp": "^0.33.2",
"styled-components": "^6.1.1"
},
"devDependencies": {
"@types/dotenv": "^8.2.0",
"@types/express": "^4.17.20",
"@types/language-tags": "^1.0.3",
"@types/luxon": "^3.3.3",
"@types/qs": "^6.9.9",
"@types/express": "^4.17.21",
"@types/language-tags": "^1.0.4",
"@types/luxon": "^3.3.4",
"@types/qs": "^6.9.10",
"@types/react-router-dom": "^5.3.3",
"@types/styled-components": "^5.1.29",
"@types/styled-components": "^5.1.30",
"copyfiles": "^2.4.1",
"nodemon": "^3.0.1",
"npm-check-updates": "^16.14.6",

View File

@ -18,7 +18,6 @@ import { validateEventsTranslationsTitle } from "./validations/validateEventsTra
const fields = {
name: "name",
events: "events",
eventsSource: "source",
eventsTranslations: "translations",
eventsTranslationsTitle: "title",
eventsTranslationsDescription: "description",
@ -98,13 +97,6 @@ export const ChronologyItems: CollectionConfig = buildVersionedCollectionConfig(
required: true,
minRows: 1,
fields: [
{
name: fields.eventsSource,
type: "relationship",
relationTo: [Collections.Contents, Collections.LibraryItems],
// required: true,
admin: { allowCreate: false },
},
translatedFields({
name: fields.eventsTranslations,
required: true,

View File

@ -0,0 +1,64 @@
import { CollectionGroups, Collections } from "../../constants";
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",
sections: "sections",
sectionsSubfolders: "subfolders",
sectionsName: "name",
files: "files",
} as const satisfies Record<string, string>;
export const Folders = buildCollectionConfig({
slug: Collections.Folders,
labels: { singular: "Folder", plural: "Folders" },
admin: {
useAsTitle: fields.slug,
group: CollectionGroups.Collections,
},
fields: [
slugField({ name: fields.slug }),
translatedFields({
name: fields.translations,
fields: [
{
name: fields.translationsName,
type: "text",
required: true,
},
],
}),
{
name: "sections",
type: "array",
fields: [
rowField([
{
name: fields.sectionsName,
type: "text",
admin: {
condition: (data) => data[fields.sections]?.length > 1,
},
},
{
name: fields.sectionsSubfolders,
type: "relationship",
relationTo: Collections.Folders,
hasMany: true,
},
]),
],
},
{
type: "relationship",
name: fields.files,
relationTo: [Collections.LibraryItems, Collections.Contents],
hasMany: true,
},
],
});

View File

@ -1,71 +0,0 @@
import { CollectionGroups, Collections } from "../../constants";
import { backPropagationField } from "../../fields/backPropagationField/backPropagationField";
import { rowField } from "../../fields/rowField/rowField";
import { slugField } from "../../fields/slugField/slugField";
import { translatedFields } from "../../fields/translatedFields/translatedFields";
import { buildCollectionConfig } from "../../utils/collectionConfig";
import { createEditor } from "../../utils/editor";
const fields = {
slug: "slug",
translations: "translations",
name: "name",
description: "description",
subfolders: "subfolders",
items: "items",
parentFolders: "parentFolders",
} as const satisfies Record<string, string>;
export const LibraryFolders = buildCollectionConfig({
slug: Collections.LibraryFolders,
labels: {
singular: "Library Folder",
plural: "Library Folders",
},
defaultSort: fields.slug,
admin: {
useAsTitle: fields.slug,
defaultColumns: [fields.slug, fields.translations],
disableDuplicate: true,
group: CollectionGroups.Collections,
},
timestamps: false,
versions: false,
fields: [
slugField({ name: fields.slug }),
translatedFields({
name: fields.translations,
admin: {
useAsTitle: fields.name,
},
fields: [
{ name: fields.name, type: "text", required: true },
{
name: fields.description,
type: "richText",
editor: createEditor({ inlines: true, lists: true, links: true }),
},
],
}),
rowField([
backPropagationField({
name: fields.parentFolders,
relationTo: Collections.LibraryFolders,
hasMany: true,
where: ({ id }) => ({ [fields.subfolders]: { equals: id } }),
}),
{
type: "relationship",
name: fields.subfolders,
relationTo: Collections.LibraryFolders,
hasMany: true,
},
{
type: "relationship",
name: fields.items,
relationTo: Collections.LibraryItems,
hasMany: true,
},
]),
],
});

View File

@ -704,15 +704,16 @@ export const LibraryItems = buildVersionedCollectionConfig({
label: "Contents",
fields: [
rowField([
backPropagationField({
name: fields.parentFolders,
relationTo: Collections.LibraryFolders,
hasMany: true,
where: ({ id }) => ({ items: { equals: id } }),
admin: {
description: `You can set the folders from the "Library Folders" collection`,
},
}),
// TODO: Uncomment when the Folders are ready
// backPropagationField({
// name: fields.parentFolders,
// relationTo: Collections.Folders,
// hasMany: true,
// where: ({ id }) => ({ files: { equals: id } }),
// admin: {
// description: `You can set the folders from the "Folders" collection`,
// },
// }),
backPropagationField({
name: fields.parentItems,
relationTo: Collections.LibraryItems,

View File

@ -12,6 +12,7 @@ import { beforeDuplicateUnpublish } from "../../hooks/beforeDuplicateUnpublish";
import { isDefined, isUndefined } from "../../utils/asserts";
import { createEditor } from "../../utils/editor";
import { buildVersionedCollectionConfig } from "../../utils/versionedCollectionConfig";
import { importFromStrapi } from "./endpoints/importFromStrapi";
const fields = {
slug: "slug",
@ -60,6 +61,7 @@ export const Posts = buildVersionedCollectionConfig({
},
preview: (doc) => `https://accords-library.com/news/${doc.slug}`,
},
endpoints: [importFromStrapi],
fields: [
rowField([
slugField({ name: fields.slug }),
@ -72,7 +74,7 @@ export const Posts = buildVersionedCollectionConfig({
{
name: fields.authors,
type: "relationship",
relationTo: [Collections.Recorders],
relationTo: Collections.Recorders,
required: true,
minRows: 1,
hasMany: true,

View File

@ -0,0 +1,115 @@
import { DateTime } from "luxon";
import type { MarkOptional } from "ts-essentials";
import { Collections } from "../../../constants";
import { createStrapiImportEndpoint } from "../../../endpoints/createStrapiImportEndpoint";
import type { Post } from "../../../types/collections";
import { StrapiImage, StrapiLanguage, StrapiRecorders } from "../../../types/strapi";
import { isDefined, isUndefined } from "../../../utils/asserts";
import { findCategory, findRecorder, uploadStrapiImage } from "../../../utils/localApi";
import { plainTextToLexical } from "../../../utils/string";
type StrapiPost = {
slug: string;
categories: { data: { attributes: { slug: string } }[] };
authors: StrapiRecorders;
hidden: boolean;
thumbnail: StrapiImage;
translations: {
title: string;
excerpt?: string;
body: string;
translators: StrapiRecorders;
proofreaders: StrapiRecorders;
language: StrapiLanguage;
source_language: StrapiLanguage;
}[];
date: {
day: number;
month: number;
year: number;
};
};
export const importFromStrapi = createStrapiImportEndpoint<StrapiPost>({
strapi: {
collection: "posts",
params: {
populate: [
"date",
"authors",
"thumbnail",
"categories",
"translations",
"translations.language",
"translations.translators",
"translations.proofreaders",
"translations.source_language",
],
},
},
payload: {
collection: Collections.Posts,
convert: async ({
slug,
date: { day, month, year },
hidden,
authors,
thumbnail,
categories,
translations,
}) => {
const thumbnailId = await uploadStrapiImage({
collection: Collections.PostsThumbnails,
image: thumbnail,
});
const handleTranslation = async ({
language,
title,
body,
excerpt,
proofreaders,
source_language,
translators,
}: StrapiPost["translations"][number]): Promise<Post["translations"][number]> => {
if (isUndefined(language.data))
throw new Error("A language is required for a post translation");
if (isUndefined(source_language.data))
throw new Error("A source_language is required for a post translation");
return {
language: language.data.attributes.code,
sourceLanguage: source_language.data.attributes.code,
title,
content: plainTextToLexical(body),
summary: isDefined(excerpt) ? plainTextToLexical(excerpt) : undefined,
translators:
translators.data &&
(await Promise.all(
translators.data?.map(async (recorder) => findRecorder(recorder.attributes.username))
)),
proofreaders:
proofreaders.data &&
(await Promise.all(
proofreaders.data?.map(async (recorder) => findRecorder(recorder.attributes.username))
)),
};
};
const data: MarkOptional<Post, "createdAt" | "id" | "updatedAt" | "updatedBy"> = {
slug,
publishedDate:
DateTime.fromObject({ day, month, year }).toISO() ?? new Date().toISOString(),
categories: await Promise.all(
categories.data.map((category) => findCategory(category.attributes.slug))
),
translations: await Promise.all(translations.map(handleTranslation)),
authors: await Promise.all(
authors.data?.map((author) => findRecorder(author.attributes.username)) ?? []
),
thumbnail: thumbnailId,
hidden,
};
return data;
},
},
});

View File

@ -65,7 +65,7 @@ export const Recorders = buildCollectionConfig({
],
},
},
auth: true,
auth: { tokenExpiration: 24 * 60 * 60 },
access: {
unlock: mustBeAdminForCollections,
update: mustBeAdminOrSelf,

View File

@ -8,7 +8,6 @@ export enum Collections {
Files = "files",
Keys = "keys",
Languages = "languages",
LibraryFolders = "library-folders",
LibraryItems = "library-items",
LibraryItemsThumbnails = "library-items-thumbnails",
LibraryItemsScans = "library-items-scans",
@ -23,6 +22,7 @@ export enum Collections {
Weapons = "weapons",
WeaponsGroups = "weapons-groups",
WeaponsThumbnails = "weapons-thumbnails",
Folders = "folders"
}
export enum CollectionGroups {

View File

@ -9,9 +9,9 @@ import { ContentsFolders } from "./collections/ContentsFolders/ContentsFolders";
import { ContentsThumbnails } from "./collections/ContentsThumbnails/ContentsThumbnails";
import { Currencies } from "./collections/Currencies/Currencies";
import { Files } from "./collections/Files/Files";
import { Folders } from "./collections/Folders/Folders";
import { Keys } from "./collections/Keys/Keys";
import { Languages } from "./collections/Languages/Languages";
import { LibraryFolders } from "./collections/LibraryFolders/LibraryFolders";
import { LibraryItems } from "./collections/LibraryItems/LibraryItems";
import { LibraryItemsGallery } from "./collections/LibraryItemsGallery/LibraryItemsGallery";
import { LibraryItemsScans } from "./collections/LibraryItemsScans/LibraryItemsScans";
@ -46,7 +46,7 @@ export default buildConfig({
},
editor: createEditor({}),
collections: [
LibraryFolders,
Folders,
LibraryItems,
Contents,
ContentsFolders,

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@ export const buildVersionedCollectionConfig = ({
}: BuildVersionedCollectionConfig): CollectionConfig => ({
...otherParams,
timestamps: true,
versions: { drafts: { autosave: { interval: 2000 } } },
versions: { drafts: { autosave: false } },
hooks: {
...otherHooks,
beforeChange: [...(beforeChange ?? []), beforeChangeUpdatedBy],