Added folders
This commit is contained in:
parent
cbd0251ad5
commit
e8d8c8e6a8
|
@ -3,7 +3,7 @@
|
||||||
"editor.rulers": [100],
|
"editor.rulers": [100],
|
||||||
"typescript.preferences.importModuleSpecifier": "non-relative",
|
"typescript.preferences.importModuleSpecifier": "non-relative",
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll": true,
|
"source.fixAll": "explicit",
|
||||||
"source.organizeImports": true
|
"source.organizeImports": "explicit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ version: "3"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
payload:
|
payload:
|
||||||
image: node:18-alpine
|
image: docker.io/library/node:18-alpine
|
||||||
ports:
|
ports:
|
||||||
- "${PAYLOAD_PORT}:${PAYLOAD_PORT}"
|
- "${PAYLOAD_PORT}:${PAYLOAD_PORT}"
|
||||||
volumes:
|
volumes:
|
||||||
|
@ -20,7 +20,7 @@ services:
|
||||||
NODE_ENV: development
|
NODE_ENV: development
|
||||||
|
|
||||||
mongo:
|
mongo:
|
||||||
image: mongo:latest
|
image: docker.io/library/mongo:latest
|
||||||
ports:
|
ports:
|
||||||
- "${MONGODB_PORT}:27017"
|
- "${MONGODB_PORT}:27017"
|
||||||
command:
|
command:
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
21
package.json
21
package.json
|
@ -24,23 +24,24 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource/vollkorn": "^5.0.17",
|
"@fontsource/vollkorn": "^5.0.17",
|
||||||
"@payloadcms/bundler-webpack": "^1.0.4",
|
"@payloadcms/bundler-webpack": "^1.0.5",
|
||||||
"@payloadcms/db-mongodb": "^1.0.4",
|
"@payloadcms/db-mongodb": "^1.0.8",
|
||||||
"@payloadcms/richtext-lexical": "^0.1.15",
|
"@payloadcms/richtext-lexical": "^0.1.17",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"language-tags": "^1.0.9",
|
"language-tags": "^1.0.9",
|
||||||
"luxon": "^3.4.3",
|
"luxon": "^3.4.3",
|
||||||
"payload": "^2.0.13",
|
"payload": "^2.1.1",
|
||||||
"styled-components": "^6.1.0"
|
"sharp": "^0.33.2",
|
||||||
|
"styled-components": "^6.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/dotenv": "^8.2.0",
|
"@types/dotenv": "^8.2.0",
|
||||||
"@types/express": "^4.17.20",
|
"@types/express": "^4.17.21",
|
||||||
"@types/language-tags": "^1.0.3",
|
"@types/language-tags": "^1.0.4",
|
||||||
"@types/luxon": "^3.3.3",
|
"@types/luxon": "^3.3.4",
|
||||||
"@types/qs": "^6.9.9",
|
"@types/qs": "^6.9.10",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"@types/styled-components": "^5.1.29",
|
"@types/styled-components": "^5.1.30",
|
||||||
"copyfiles": "^2.4.1",
|
"copyfiles": "^2.4.1",
|
||||||
"nodemon": "^3.0.1",
|
"nodemon": "^3.0.1",
|
||||||
"npm-check-updates": "^16.14.6",
|
"npm-check-updates": "^16.14.6",
|
||||||
|
|
|
@ -18,7 +18,6 @@ import { validateEventsTranslationsTitle } from "./validations/validateEventsTra
|
||||||
const fields = {
|
const fields = {
|
||||||
name: "name",
|
name: "name",
|
||||||
events: "events",
|
events: "events",
|
||||||
eventsSource: "source",
|
|
||||||
eventsTranslations: "translations",
|
eventsTranslations: "translations",
|
||||||
eventsTranslationsTitle: "title",
|
eventsTranslationsTitle: "title",
|
||||||
eventsTranslationsDescription: "description",
|
eventsTranslationsDescription: "description",
|
||||||
|
@ -98,13 +97,6 @@ export const ChronologyItems: CollectionConfig = buildVersionedCollectionConfig(
|
||||||
required: true,
|
required: true,
|
||||||
minRows: 1,
|
minRows: 1,
|
||||||
fields: [
|
fields: [
|
||||||
{
|
|
||||||
name: fields.eventsSource,
|
|
||||||
type: "relationship",
|
|
||||||
relationTo: [Collections.Contents, Collections.LibraryItems],
|
|
||||||
// required: true,
|
|
||||||
admin: { allowCreate: false },
|
|
||||||
},
|
|
||||||
translatedFields({
|
translatedFields({
|
||||||
name: fields.eventsTranslations,
|
name: fields.eventsTranslations,
|
||||||
required: true,
|
required: true,
|
||||||
|
|
|
@ -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,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
|
@ -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,
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
],
|
|
||||||
});
|
|
|
@ -704,15 +704,16 @@ export const LibraryItems = buildVersionedCollectionConfig({
|
||||||
label: "Contents",
|
label: "Contents",
|
||||||
fields: [
|
fields: [
|
||||||
rowField([
|
rowField([
|
||||||
backPropagationField({
|
// TODO: Uncomment when the Folders are ready
|
||||||
name: fields.parentFolders,
|
// backPropagationField({
|
||||||
relationTo: Collections.LibraryFolders,
|
// name: fields.parentFolders,
|
||||||
hasMany: true,
|
// relationTo: Collections.Folders,
|
||||||
where: ({ id }) => ({ items: { equals: id } }),
|
// hasMany: true,
|
||||||
admin: {
|
// where: ({ id }) => ({ files: { equals: id } }),
|
||||||
description: `You can set the folders from the "Library Folders" collection`,
|
// admin: {
|
||||||
},
|
// description: `You can set the folders from the "Folders" collection`,
|
||||||
}),
|
// },
|
||||||
|
// }),
|
||||||
backPropagationField({
|
backPropagationField({
|
||||||
name: fields.parentItems,
|
name: fields.parentItems,
|
||||||
relationTo: Collections.LibraryItems,
|
relationTo: Collections.LibraryItems,
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { beforeDuplicateUnpublish } from "../../hooks/beforeDuplicateUnpublish";
|
||||||
import { isDefined, isUndefined } from "../../utils/asserts";
|
import { isDefined, isUndefined } from "../../utils/asserts";
|
||||||
import { createEditor } from "../../utils/editor";
|
import { createEditor } from "../../utils/editor";
|
||||||
import { buildVersionedCollectionConfig } from "../../utils/versionedCollectionConfig";
|
import { buildVersionedCollectionConfig } from "../../utils/versionedCollectionConfig";
|
||||||
|
import { importFromStrapi } from "./endpoints/importFromStrapi";
|
||||||
|
|
||||||
const fields = {
|
const fields = {
|
||||||
slug: "slug",
|
slug: "slug",
|
||||||
|
@ -60,6 +61,7 @@ export const Posts = buildVersionedCollectionConfig({
|
||||||
},
|
},
|
||||||
preview: (doc) => `https://accords-library.com/news/${doc.slug}`,
|
preview: (doc) => `https://accords-library.com/news/${doc.slug}`,
|
||||||
},
|
},
|
||||||
|
endpoints: [importFromStrapi],
|
||||||
fields: [
|
fields: [
|
||||||
rowField([
|
rowField([
|
||||||
slugField({ name: fields.slug }),
|
slugField({ name: fields.slug }),
|
||||||
|
@ -72,7 +74,7 @@ export const Posts = buildVersionedCollectionConfig({
|
||||||
{
|
{
|
||||||
name: fields.authors,
|
name: fields.authors,
|
||||||
type: "relationship",
|
type: "relationship",
|
||||||
relationTo: [Collections.Recorders],
|
relationTo: Collections.Recorders,
|
||||||
required: true,
|
required: true,
|
||||||
minRows: 1,
|
minRows: 1,
|
||||||
hasMany: true,
|
hasMany: true,
|
||||||
|
|
|
@ -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;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
|
@ -65,7 +65,7 @@ export const Recorders = buildCollectionConfig({
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
auth: true,
|
auth: { tokenExpiration: 24 * 60 * 60 },
|
||||||
access: {
|
access: {
|
||||||
unlock: mustBeAdminForCollections,
|
unlock: mustBeAdminForCollections,
|
||||||
update: mustBeAdminOrSelf,
|
update: mustBeAdminOrSelf,
|
||||||
|
|
|
@ -8,7 +8,6 @@ export enum Collections {
|
||||||
Files = "files",
|
Files = "files",
|
||||||
Keys = "keys",
|
Keys = "keys",
|
||||||
Languages = "languages",
|
Languages = "languages",
|
||||||
LibraryFolders = "library-folders",
|
|
||||||
LibraryItems = "library-items",
|
LibraryItems = "library-items",
|
||||||
LibraryItemsThumbnails = "library-items-thumbnails",
|
LibraryItemsThumbnails = "library-items-thumbnails",
|
||||||
LibraryItemsScans = "library-items-scans",
|
LibraryItemsScans = "library-items-scans",
|
||||||
|
@ -23,6 +22,7 @@ export enum Collections {
|
||||||
Weapons = "weapons",
|
Weapons = "weapons",
|
||||||
WeaponsGroups = "weapons-groups",
|
WeaponsGroups = "weapons-groups",
|
||||||
WeaponsThumbnails = "weapons-thumbnails",
|
WeaponsThumbnails = "weapons-thumbnails",
|
||||||
|
Folders = "folders"
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CollectionGroups {
|
export enum CollectionGroups {
|
||||||
|
|
|
@ -9,9 +9,9 @@ import { ContentsFolders } from "./collections/ContentsFolders/ContentsFolders";
|
||||||
import { ContentsThumbnails } from "./collections/ContentsThumbnails/ContentsThumbnails";
|
import { ContentsThumbnails } from "./collections/ContentsThumbnails/ContentsThumbnails";
|
||||||
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 { Keys } from "./collections/Keys/Keys";
|
import { Keys } from "./collections/Keys/Keys";
|
||||||
import { Languages } from "./collections/Languages/Languages";
|
import { Languages } from "./collections/Languages/Languages";
|
||||||
import { LibraryFolders } from "./collections/LibraryFolders/LibraryFolders";
|
|
||||||
import { LibraryItems } from "./collections/LibraryItems/LibraryItems";
|
import { LibraryItems } from "./collections/LibraryItems/LibraryItems";
|
||||||
import { LibraryItemsGallery } from "./collections/LibraryItemsGallery/LibraryItemsGallery";
|
import { LibraryItemsGallery } from "./collections/LibraryItemsGallery/LibraryItemsGallery";
|
||||||
import { LibraryItemsScans } from "./collections/LibraryItemsScans/LibraryItemsScans";
|
import { LibraryItemsScans } from "./collections/LibraryItemsScans/LibraryItemsScans";
|
||||||
|
@ -46,7 +46,7 @@ export default buildConfig({
|
||||||
},
|
},
|
||||||
editor: createEditor({}),
|
editor: createEditor({}),
|
||||||
collections: [
|
collections: [
|
||||||
LibraryFolders,
|
Folders,
|
||||||
LibraryItems,
|
LibraryItems,
|
||||||
Contents,
|
Contents,
|
||||||
ContentsFolders,
|
ContentsFolders,
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -26,7 +26,7 @@ export const buildVersionedCollectionConfig = ({
|
||||||
}: BuildVersionedCollectionConfig): CollectionConfig => ({
|
}: BuildVersionedCollectionConfig): CollectionConfig => ({
|
||||||
...otherParams,
|
...otherParams,
|
||||||
timestamps: true,
|
timestamps: true,
|
||||||
versions: { drafts: { autosave: { interval: 2000 } } },
|
versions: { drafts: { autosave: false } },
|
||||||
hooks: {
|
hooks: {
|
||||||
...otherHooks,
|
...otherHooks,
|
||||||
beforeChange: [...(beforeChange ?? []), beforeChangeUpdatedBy],
|
beforeChange: [...(beforeChange ?? []), beforeChangeUpdatedBy],
|
||||||
|
|
Loading…
Reference in New Issue