Fix typescript errors

This commit is contained in:
DrMint 2024-03-13 03:15:14 +01:00
parent 493b3601b8
commit bd13e005e0
24 changed files with 96 additions and 1020 deletions

View File

@ -9,8 +9,8 @@ services:
- .:/home/node/app
- node_modules:/home/node/app/node_modules
working_dir: /home/node/app/
command: sh -c "npm install && npm run generate:types && npm run dev"
# command: sh -c "npm install && npm run generate:types && npm run build:payload && npm run serve"
# command: sh -c "npm install && npm run generate:types && npm run dev"
command: sh -c "npm install && npm run generate:types && npm run build && npm run serve"
depends_on:
- mongo
environment:

View File

@ -1,15 +1,10 @@
import payload from "payload";
import { Collections } from "../../../constants";
import { EndpointEra } from "../../../sdk";
import { ChronologyEra, ChronologyItem, Recorder } from "../../../types/collections";
import { ChronologyEra, ChronologyItem } from "../../../types/collections";
import { CollectionEndpoint } from "../../../types/payload";
import {
isEmpty,
isPayloadArrayType,
isPayloadType,
isString,
isUndefined,
} from "../../../utils/asserts";
import { isDefined, isPayloadArrayType, isPayloadType } from "../../../utils/asserts";
import { handleRecorder } from "../../../utils/endpoints";
export const getAllEndpoint: CollectionEndpoint = {
method: "get",
@ -38,16 +33,11 @@ export const getAllEndpoint: CollectionEndpoint = {
startingYear,
endingYear,
translations:
translations?.flatMap(({ language, title, description }) => {
if (isString(language)) return [];
const translation = {
language: language.id,
translations?.map(({ language, title, description }) => ({
language: isPayloadType(language) ? language.id : language,
title,
description,
};
if (isEmpty(translation.description)) delete translation.description;
return translation;
}) ?? [],
...(description ? { description } : {}),
})) ?? [],
items:
items
?.filter(isPayloadType<ChronologyItem>)
@ -63,52 +53,44 @@ export const getAllEndpoint: CollectionEndpoint = {
if (aDay !== bDay) return aDay - bDay;
return 0;
})
.flatMap(({ date, events, createdAt, updatedAt, updatedBy }) => {
if (isString(updatedBy)) return [];
const item = {
date,
.map(({ events, date: { year, day, month } }) => ({
date: {
year,
...(isDefined(day) ? { day } : {}),
...(isDefined(month) ? { month } : {}),
},
events: events.map(({ translations }) => ({
translations: translations.flatMap(
translations: translations.map(
({
language,
sourceLanguage,
description,
notes,
proofreaders = [],
transcribers = [],
translators = [],
proofreaders,
transcribers,
translators,
title,
}) => {
if (isString(language)) return [];
if (isString(sourceLanguage)) return [];
if (!isPayloadArrayType<Recorder>(proofreaders)) return [];
if (!isPayloadArrayType<Recorder>(transcribers)) return [];
if (!isPayloadArrayType<Recorder>(translators)) return [];
const event = {
language: language.id,
sourceLanguage: sourceLanguage.id,
title,
description,
notes,
proofreaders: proofreaders.map(({ id }) => id),
transcribers: transcribers.map(({ id }) => id),
translators: translators.map(({ id }) => id),
};
if (isEmpty(title)) delete event.title;
if (isEmpty(description)) delete event.description;
if (isEmpty(notes)) delete event.notes;
return event;
}
}) => ({
language: isPayloadType(language) ? language.id : language,
sourceLanguage: isPayloadType(sourceLanguage)
? sourceLanguage.id
: sourceLanguage,
...(title ? { title } : {}),
...(description ? { description } : {}),
...(notes ? { notes } : {}),
proofreaders: isPayloadArrayType(proofreaders)
? proofreaders.map(handleRecorder)
: [],
transcribers: isPayloadArrayType(transcribers)
? transcribers.map(handleRecorder)
: [],
translators: isPayloadArrayType(translators)
? translators.map(handleRecorder)
: [],
})
),
})),
createdAt: new Date(createdAt),
updatedAt: new Date(updatedAt),
updatedBy: updatedBy.id,
};
if (isUndefined(item.date.month)) delete item.date.month;
if (isUndefined(item.date.day)) delete item.date.day;
return item;
}) ?? [],
})) ?? [],
})
);

View File

@ -1,7 +1,8 @@
import { Collections } from "../../../constants";
import { createStrapiImportEndpoint } from "../../../endpoints/createStrapiImportEndpoint";
import { StrapiLanguage } from "../../../types/strapi";
import { isUndefined } from "../../../utils/asserts";
import { isDefined, isUndefined } from "../../../utils/asserts";
import { plainTextToLexical } from "../../../utils/string";
type StrapiChronologyEra = {
slug: string;
@ -29,7 +30,7 @@ export const importFromStrapi = createStrapiImportEndpoint<StrapiChronologyEra>(
return {
language: language.data?.attributes.code,
title,
description,
...(isDefined(description) ? { description: plainTextToLexical(description) } : {}),
};
}),
}),

View File

@ -8,7 +8,7 @@ export const validateEventsTranslationsDescription: Validate<
ChronologyItem["events"][number]["translations"][number],
unknown
> = (_, { siblingData: { description, title } }) => {
if (isEmpty(description) && isEmpty(title)) {
if (!description && isEmpty(title)) {
return "This field is required if no title is set.";
}
return true;

View File

@ -8,7 +8,7 @@ export const validateEventsTranslationsTitle: Validate<
ChronologyItem["events"][number]["translations"][number],
unknown
> = (_, { siblingData: { description, title } }) => {
if (isEmpty(description) && isEmpty(title)) {
if (!description && isEmpty(title)) {
return "This field is required if no description is set.";
}
return true;

View File

@ -47,15 +47,6 @@ export const importFromStrapi = createStrapiImportEndpoint<StrapiRecorder>({
anonymize,
languages: languages.data?.map((language) => language.attributes.code),
avatar: avatarId,
biographies: bios?.map(({ language, bio }) => {
if (isUndefined(language.data))
throw new Error("A language is required for a Recorder biography");
if (isUndefined(bio)) throw new Error("A bio is required for a Recorder biography");
return {
language: language.data.attributes.code,
biography: plainTextToLexical(bio),
};
}),
},
user,
});

View File

@ -5,7 +5,6 @@ import { slugField } from "../../fields/slugField/slugField";
import { translatedFields } from "../../fields/translatedFields/translatedFields";
import { beforeDuplicateAddCopyTo } from "../../hooks/beforeDuplicateAddCopyTo";
import { buildCollectionConfig } from "../../utils/collectionConfig";
import { getAllEndpoint } from "./endpoints/getAllEndpoint";
const beforeChangeUpdateName: CollectionBeforeChangeHook = async ({ data }) => {
let name = data.slug;
@ -45,7 +44,6 @@ export const Tags: CollectionConfig = buildCollectionConfig({
beforeDuplicate: beforeDuplicateAddCopyTo(fields.slug),
},
},
endpoints: [getAllEndpoint],
hooks: { beforeChange: [beforeChangeUpdateName] },
fields: [
{ name: fields.name, type: "text", admin: { readOnly: true, hidden: true } },

View File

@ -1,41 +0,0 @@
import payload from "payload";
import { Collections } from "../../../constants";
import { EndpointTag } from "../../../sdk";
import { CollectionEndpoint } from "../../../types/payload";
import { isPayloadType } from "../../../utils/asserts";
export const getAllEndpoint: CollectionEndpoint = {
method: "get",
path: "/all",
handler: async (req, res) => {
if (!req.user) {
return res.status(403).send({
errors: [
{
message: "You are not allowed to perform this action.",
},
],
});
}
const tags = (
await payload.find({
collection: Collections.Tags,
sort: "id",
pagination: false,
})
).docs;
const result = tags.map<EndpointTag>(({ slug, translations, group }) => ({
slug,
translations:
translations?.map(({ language, name }) => ({
language: isPayloadType(language) ? language.id : language,
name,
})) ?? [],
group: isPayloadType(group) ? group.slug : group,
}));
res.status(200).json(result);
},
};

View File

@ -4,7 +4,6 @@ import { iconField } from "../../fields/iconField/iconField";
import { slugField } from "../../fields/slugField/slugField";
import { translatedFields } from "../../fields/translatedFields/translatedFields";
import { buildCollectionConfig } from "../../utils/collectionConfig";
import { getAllEndpoint } from "./endpoints/getAllEndpoint";
const fields = {
slug: "slug",
@ -21,7 +20,6 @@ export const TagsGroups: CollectionConfig = buildCollectionConfig({
useAsTitle: fields.slug,
defaultColumns: [fields.slug, fields.translations],
},
endpoints: [getAllEndpoint],
fields: [
slugField({ name: fields.slug }),
iconField({ name: fields.icon }),

View File

@ -1,42 +0,0 @@
import payload from "payload";
import { Collections } from "../../../constants";
import { EndpointTagsGroup } from "../../../sdk";
import { CollectionEndpoint } from "../../../types/payload";
import { isPayloadType } from "../../../utils/asserts";
export const getAllEndpoint: CollectionEndpoint = {
method: "get",
path: "/all",
handler: async (req, res) => {
if (!req.user) {
return res.status(403).send({
errors: [
{
message: "You are not allowed to perform this action.",
},
],
});
}
const tags = (
await payload.find({
collection: Collections.TagsGroups,
sort: "id",
pagination: false,
})
).docs;
const result = tags.map<EndpointTagsGroup>(({ slug, translations, icon }) => ({
slug,
...(icon ? { icon } : {}),
translations:
translations?.map(({ language, name }) => ({
language: isPayloadType(language) ? language.id : language,
name,
})) ?? [],
tags: [] // TODO: Add tags,
}));
res.status(200).json(result);
},
};

View File

@ -1,130 +0,0 @@
import { RowLabelArgs } from "payload/dist/admin/components/forms/RowLabel/types";
import { CollectionGroups, Collections } from "../../constants";
import { imageField } from "../../fields/imageField/imageField";
import { rowField } from "../../fields/rowField/rowField";
import { slugField } from "../../fields/slugField/slugField";
import { translatedFields } from "../../fields/translatedFields/translatedFields";
import { createEditor } from "../../utils/editor";
import { buildVersionedCollectionConfig } from "../../utils/versionedCollectionConfig";
import { AppearanceRowLabel } from "./components/AppearanceRowLabel";
import { getBySlugEndpoint } from "./endpoints/getBySlugEndpoint";
import { importFromStrapi } from "./endpoints/importFromStrapi";
const fields = {
slug: "slug",
thumbnail: "thumbnail",
type: "type",
group: "group",
appearances: "appearances",
appearancesCategories: "categories",
appearancesTranslations: "translations",
appearancesTranslationsName: "name",
appearancesTranslationsDescription: "description",
appearancesTranslationsLevel1: "level1",
appearancesTranslationsLevel2: "level2",
appearancesTranslationsLevel3: "level3",
appearancesTranslationsLevel4: "level4",
status: "_status",
};
export const Weapons = buildVersionedCollectionConfig({
slug: Collections.Weapons,
labels: { singular: "Weapon", plural: "Weapons" },
defaultSort: fields.slug,
admin: {
useAsTitle: fields.slug,
defaultColumns: [
fields.thumbnail,
fields.slug,
fields.group,
fields.type,
fields.appearances,
fields.status,
],
group: CollectionGroups.Collections,
},
endpoints: [importFromStrapi, getBySlugEndpoint],
fields: [
rowField([
slugField({ name: fields.slug }),
imageField({
name: fields.thumbnail,
relationTo: Collections.WeaponsThumbnails,
}),
]),
rowField([
{
name: fields.group,
type: "relationship",
relationTo: Collections.WeaponsGroups,
},
]),
{
name: fields.appearances,
type: "array",
required: true,
minRows: 1,
admin: {
initCollapsed: true,
components: {
RowLabel: ({ data }: RowLabelArgs) =>
AppearanceRowLabel({ keyIds: data[fields.appearancesCategories] ?? [] }),
},
},
fields: [
translatedFields({
name: fields.appearancesTranslations,
required: true,
minRows: 1,
admin: {
useAsTitle: fields.appearancesTranslationsName,
hasSourceLanguage: true,
hasCredits: true,
},
fields: [
rowField([
{
name: fields.appearancesTranslationsName,
type: "text",
required: true,
},
{
name: fields.appearancesTranslationsDescription,
type: "richText",
editor: createEditor({ inlines: true }),
},
]),
rowField([
{
name: fields.appearancesTranslationsLevel1,
label: "Level 1",
type: "richText",
editor: createEditor({ inlines: true }),
},
{
name: fields.appearancesTranslationsLevel2,
label: "Level 2",
type: "richText",
editor: createEditor({ inlines: true }),
},
]),
rowField([
{
name: fields.appearancesTranslationsLevel3,
label: "Level 3",
type: "richText",
editor: createEditor({ inlines: true }),
},
{
name: fields.appearancesTranslationsLevel4,
label: "Level 4",
type: "richText",
editor: createEditor({ inlines: true }),
},
]),
],
}),
],
},
],
});

View File

@ -1,36 +0,0 @@
import React, { useEffect, useState } from "react";
import styled from "styled-components";
import { Collections } from "../../../constants";
interface Props {
keyIds: string[];
}
const Container = styled.div`
display: flex;
place-items: center;
gap: 5px;
`;
export const AppearanceRowLabel = ({ keyIds }: Props): JSX.Element => {
const [keySlugs, setKeySlugs] = useState<string[]>([]);
useEffect(() => {
const fetchUrl = async () => {
const results = await Promise.all(
keyIds.map(async (keyId) => await (await fetch(`/api/${Collections.Keys}/${keyId}`)).json())
);
setKeySlugs(results.map((result) => result.name));
};
fetchUrl();
}, [keyIds]);
return (
<Container>
{keySlugs.map((keySlug) => (
<div id={keySlug} className="pill pill--style-white">
{keySlug}
</div>
))}
</Container>
);
};

View File

@ -1,155 +0,0 @@
import { Collections } from "../../../constants";
import { createGetByEndpoint } from "../../../endpoints/createGetByEndpoint";
import { EndpointBasicWeapon, EndpointWeapon, PayloadImage } from "../../../sdk";
import { Key, Language, Recorder, Weapon, WeaponsThumbnail } from "../../../types/collections";
import { isDefined, isUndefined, isValidPayloadImage } from "../../../utils/asserts";
export const getBySlugEndpoint = createGetByEndpoint(
Collections.Weapons,
"slug",
(weapon: Weapon): EndpointWeapon => {
let group: EndpointWeapon["group"] = undefined;
// We only send the group if the group has at least 2 weapons (1 weapon beside the current one)
// The weapons are ordered alphabetically using their slugs
if (
typeof weapon.group === "object" &&
isDefined(weapon.group.weapons) &&
weapon.group.weapons.length > 1
) {
const { slug, translations = [], weapons } = weapon.group;
const groupWeapons: EndpointBasicWeapon[] = [];
weapons.forEach((groupWeapon) => {
if (typeof groupWeapon === "object" && groupWeapon.id !== weapon.id) {
groupWeapons.push(convertWeaponToEndpointBasicWeapon(groupWeapon));
}
});
groupWeapons.sort((a, b) => a.slug.localeCompare(b.slug));
group = {
slug,
translations: translations.map(({ language, name }) => ({
language: getLanguageId(language),
name,
})),
weapons: groupWeapons,
};
}
return {
...convertWeaponToEndpointBasicWeapon(weapon),
appearances: weapon.appearances.map(({ categories, translations }) => ({
categories: categories.map(getKeyId),
translations: translations.map(
({
language,
sourceLanguage,
transcribers = [],
translators = [],
proofreaders = [],
...otherTranslatedProps
}) => ({
language: getLanguageId(language),
sourceLanguage: getLanguageId(sourceLanguage),
transcribers: transcribers.map(getRecorderId),
translators: translators.map(getRecorderId),
proofreaders: proofreaders.map(getRecorderId),
...otherTranslatedProps,
})
),
})),
group,
};
}
);
const getRecorderId = (recorder: string | Recorder) =>
typeof recorder === "object" ? recorder.id : recorder;
const getKeyId = (key: string | Key) => (typeof key === "object" ? key.id : key);
const getLanguageId = (language: string | Language) =>
typeof language === "object" ? language.id : language;
const getThumbnail = (thumbnail?: string | WeaponsThumbnail): WeaponsThumbnail | undefined => {
if (isUndefined(thumbnail)) return undefined;
if (typeof thumbnail === "string") return undefined;
delete thumbnail.weapon;
return thumbnail;
};
const getPayloadImage = (
image: Partial<PayloadImage> | undefined,
fallback: PayloadImage
): PayloadImage =>
isValidPayloadImage(image)
? {
filename: image.filename,
height: image.height,
mimeType: image.mimeType,
width: image.width,
url: image.url,
}
: {
filename: fallback.filename,
height: fallback.height,
mimeType: fallback.mimeType,
width: fallback.width,
url: fallback.url,
};
const convertWeaponToEndpointBasicWeapon = ({
slug,
thumbnail: rawThumbnail,
type,
appearances,
}: Weapon): EndpointBasicWeapon => {
const categories = new Set<string>();
appearances.forEach((appearance) =>
appearance.categories.forEach((category) => categories.add(getKeyId(category)))
);
const languages = new Set<string>();
appearances.forEach(({ translations }) =>
translations.forEach(({ language }) => languages.add(getLanguageId(language)))
);
const translations: EndpointWeapon["translations"] = [...languages.values()].map(
(targetLanguage) => {
const names = new Set<string>();
appearances.forEach(({ translations }) => {
const translation = translations.find(
({ language }) => getLanguageId(language) === targetLanguage
);
if (translation) {
names.add(translation.name);
}
});
const [name, ...aliases] = names;
if (isUndefined(name))
throw new Error("A weapon should always have a name for each of its translatiion");
return { language: targetLanguage, name: name, aliases };
}
);
const thumbnail = getThumbnail(rawThumbnail);
const images: EndpointBasicWeapon["images"] =
isValidPayloadImage(thumbnail) && isDefined(thumbnail.sizes)
? {
openGraph: getPayloadImage(thumbnail.sizes.og, thumbnail),
previewCard: getPayloadImage(thumbnail.sizes.small, thumbnail),
thumbnailHeader: getPayloadImage(thumbnail.sizes.medium, thumbnail),
lightBox: getPayloadImage(thumbnail, thumbnail),
}
: undefined;
return {
slug,
images,
type: getKeyId(type),
categories: [...categories.values()],
translations,
};
};

View File

@ -1,115 +0,0 @@
import payload from "payload";
import { Collections } from "../../../constants";
import { createStrapiImportEndpoint } from "../../../endpoints/createStrapiImportEndpoint";
import { StrapiImage, StrapiLanguage } from "../../../types/strapi";
import { isDefined, isUndefined } from "../../../utils/asserts";
import { findCategory, findWeaponType, uploadStrapiImage } from "../../../utils/localApi";
type StrapiWeapon = {
slug: string;
name: { name: string; language: StrapiLanguage }[];
weapon_group: { data?: { attributes: { slug: string } } };
thumbnail: StrapiImage;
type: { data?: { attributes: { slug: string } } };
stories: {
categories: { data: { attributes: { slug: string } }[] };
translations: {
language: StrapiLanguage;
description?: string;
level_1?: string;
level_2?: string;
level_3?: string;
level_4?: string;
}[];
}[];
};
export const importFromStrapi = createStrapiImportEndpoint<StrapiWeapon>({
strapi: {
collection: "weapon-stories",
params: {
populate: [
"name.language",
"type",
"weapon_group",
"stories.categories",
"stories.translations.language",
"thumbnail",
].join(),
},
},
payload: {
collection: Collections.Weapons,
import: async ({ slug, type, stories, name: names, weapon_group, thumbnail }, user) => {
let groupId: string | undefined;
if (isDefined(weapon_group.data)) {
try {
await payload.create({
collection: Collections.WeaponsGroups,
data: {
slug: weapon_group.data.attributes.slug,
},
user,
});
} catch (e) {}
const result = await payload.find({
collection: Collections.WeaponsGroups,
where: { slug: { equals: weapon_group.data.attributes.slug } },
});
if (result.docs[0]) {
groupId = result.docs[0].id;
}
}
const thumbnailId = await uploadStrapiImage({
collection: Collections.WeaponsThumbnails,
image: thumbnail,
});
if (isUndefined(type.data)) throw new Error("A type is required to create a Weapon");
await payload.create({
collection: Collections.Weapons,
data: {
updatedBy: user.id,
slug,
type: await findWeaponType(type.data.attributes.slug),
group: groupId,
thumbnail: thumbnailId,
appearances: await Promise.all(
stories.map(async ({ categories, translations }) => ({
categories: await Promise.all(
categories.data.map(({ attributes }) => findCategory(attributes.slug))
),
translations: translations.map(
({ language, description, level_1, level_2, level_3, level_4 }) => {
if (isUndefined(language.data))
throw new Error("A language is required to create a Weapon translation");
const name = names.find(
(name) => name.language.data?.attributes.code === language.data?.attributes.code
)?.name;
if (isUndefined(name))
throw new Error("A name is required to create a Weapon translation");
return {
language: language.data?.attributes.code,
sourceLanguage: language.data?.attributes.code,
name,
description,
level1: level_1,
level2: level_2,
level3: level_3,
level4: level_4,
transcribers: [user.id],
};
}
),
}))
),
},
user,
});
},
},
});

View File

@ -1,39 +0,0 @@
import { CollectionGroups, Collections } from "../../constants";
import { backPropagationField } from "../../fields/backPropagationField/backPropagationField";
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",
subgroupOf: "subgroupOf",
weapons: "weapons",
};
export const WeaponsGroups = buildCollectionConfig({
slug: Collections.WeaponsGroups,
labels: { singular: "Weapons Group", plural: "Weapon Groups" },
defaultSort: fields.slug,
admin: {
useAsTitle: fields.slug,
defaultColumns: [fields.slug, fields.translations, fields.weapons, fields.subgroupOf],
group: CollectionGroups.Collections,
},
timestamps: false,
fields: [
slugField({ name: fields.slug }),
translatedFields({
name: fields.translations,
admin: { useAsTitle: fields.translationsName },
fields: [{ name: fields.translationsName, type: "text", required: true }],
}),
backPropagationField({
name: fields.weapons,
relationTo: Collections.Weapons,
hasMany: true,
where: ({ id }) => ({ group: { equals: id } }),
}),
],
});

View File

@ -1,64 +0,0 @@
import { Collections } from "../../constants";
import { backPropagationField } from "../../fields/backPropagationField/backPropagationField";
import { buildImageCollectionConfig } from "../../utils/imageCollectionConfig";
const fields = {
filename: "filename",
mimeType: "mimeType",
filesize: "filesize",
weapon: "weapon",
updatedAt: "updatedAt",
} as const satisfies Record<string, string>;
export const WeaponsThumbnails = buildImageCollectionConfig({
slug: Collections.WeaponsThumbnails,
labels: {
singular: "Weapons Thumbnail",
plural: "Weapons Thumbnails",
},
admin: { defaultColumns: [fields.filename, fields.weapon, fields.updatedAt] },
upload: {
imageSizes: [
{
name: "og",
height: 512,
width: 512,
fit: "inside",
formatOptions: {
format: "jpg",
options: { progressive: true, mozjpeg: true, compressionLevel: 9, quality: 80 },
},
},
{
name: "small",
height: 256,
width: 256,
fit: "contain",
background: { r: 0, g: 0, b: 0, alpha: 0 },
formatOptions: {
format: "webp",
options: { effort: 6, quality: 70, alphaQuality: 70 },
},
},
{
name: "medium",
height: 1024,
width: 1024,
fit: "contain",
background: { r: 0, g: 0, b: 0, alpha: 0 },
formatOptions: {
format: "webp",
options: { effort: 6, quality: 80, alphaQuality: 80 },
},
},
],
},
fields: [
backPropagationField({
name: fields.weapon,
hasMany: false,
relationTo: Collections.Weapons,
where: ({ id }) => ({ thumbnail: { equals: id } }),
}),
],
});

View File

@ -1,7 +1,5 @@
import type {
CueBlock,
Image,
LineBlock,
SectionBlock,
SpacerBlock,
TranscriptBlock,
@ -22,9 +20,6 @@ export enum Collections {
RecordersThumbnails = "recorders-thumbnails",
VideosChannels = "videos-channels",
Videos = "videos",
Weapons = "weapons",
WeaponsGroups = "weapons-groups",
WeaponsThumbnails = "weapons-thumbnails",
Folders = "folders",
FoldersThumbnails = "folders-thumbnails",
Tags = "tags",
@ -275,11 +270,15 @@ export const isBlockNodeSpacerBlock = (node: RichTextBlockNode): node is RichTex
/* TODO: TO BE REMOVED WHEN https://github.com/payloadcms/payload/issues/5216 is closed */
export interface CueBlock {
content: RichTextContent;
blockType: 'cueBlock';
id?: string | null;
blockName?: string | null;
}
export interface LineBlock {
content: RichTextContent;
blockType: 'lineBlock';
id?: string | null;
blockName?: string | null;
}

View File

@ -1,72 +0,0 @@
import payload from "payload";
import { mustBeAdmin } from "../accesses/endpoints/mustBeAdmin";
import { Collections } from "../constants";
import { CollectionEndpoint } from "../types/payload";
import { isDefined } from "../utils/asserts";
type Image = {
filename: string;
id: string;
};
export const createImageRegenerationEndpoint = (collection: Collections): CollectionEndpoint => ({
method: "put",
path: "/regenerate",
handler: async (req, res) => {
if (!mustBeAdmin(req)) {
return res.status(403).send({
errors: [
{
message: "You are not allowed to perform this action.",
},
],
});
}
let page = 1;
let totalPage = 1;
let count = 0;
const errors: string[] = [];
while (page <= totalPage) {
const images = await payload.find({
collection,
page,
user: req.user,
});
await Promise.all(
images.docs.filter(isImage).map(async (image: Image) => {
try {
await payload.update({
collection,
id: image.id,
data: {},
filePath: `uploads/${collection}/${image.filename}`,
overwriteExistingFiles: true,
});
} catch (e) {
console.warn(e);
if (typeof e === "object" && isDefined(e) && "name" in e) {
errors.push(`${e.name} with ${image.id}`);
}
}
})
);
totalPage = images.totalPages;
count += images.docs.length;
page++;
}
res
.status(200)
.json({ message: `${count} entries have been regenerated successfully.`, errors });
},
});
const isImage = (item: Object): item is Image => {
if (!("id" in item) || typeof item.id !== "string") return false;
if (!("filename" in item) || typeof item.filename !== "string") return false;
return true;
};

View File

@ -1,5 +1,4 @@
import payload, { GeneratedTypes } from "payload";
import { BasePayload } from "payload/dist/payload";
import QueryString from "qs";
import { Recorder } from "../types/collections";
import { CollectionEndpoint } from "../types/payload";
@ -43,7 +42,7 @@ type Params<S> = {
convert?: (
strapiObject: S,
user: any
) => Promise<Parameters<BasePayload<GeneratedTypes>["create"]>[0]["data"]>;
) => any;
};
};

View File

@ -5,5 +5,5 @@ export const rowField = (fields: Field[]): RowField => ({
fields: fields.map(({ admin, ...otherConfig }) => ({
...otherConfig,
admin: { width: "0%", ...admin },
})),
})) as Field[],
});

View File

@ -20,9 +20,6 @@ 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 { Weapons } from "./collections/Weapons/Weapons";
import { WeaponsGroups } from "./collections/WeaponsGroups/WeaponsGroups";
import { WeaponsThumbnails } from "./collections/WeaponsThumbnails/WeaponsThumbnails";
import { Wordings } from "./collections/Wordings/Wordings";
import { Icon } from "./components/Icon";
import { Logo } from "./components/Logo";
@ -49,9 +46,6 @@ export default buildConfig({
Pages,
ChronologyItems,
ChronologyEras,
Weapons,
WeaponsGroups,
WeaponsThumbnails,
RecordersThumbnails,
Notes,
Videos,

View File

@ -41,8 +41,8 @@ const refreshToken = async () => {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
email: import.meta.env.PAYLOAD_USER,
password: import.meta.env.PAYLOAD_PASSWORD,
email: process.env.PAYLOAD_USER,
password: process.env.PAYLOAD_PASSWORD,
}),
});
logResponse(loginResult);
@ -81,7 +81,7 @@ const injectAuth = async (init?: RequestInit): Promise<RequestInit> => ({
const logResponse = (res: Response) => console.log(res.status, res.statusText, res.url);
const payloadApiUrl = (collection: Collections, endpoint?: string): string =>
`${import.meta.env.PAYLOAD_API_URL}/${collection}${endpoint === undefined ? "" : `/${endpoint}`}`;
`${process.env.PAYLOAD_API_URL}/${collection}${endpoint === undefined ? "" : `/${endpoint}`}`;
const request = async (url: string, init?: RequestInit): Promise<Response> => {
const result = await fetch(url, await injectAuth(init));
@ -96,43 +96,6 @@ const request = async (url: string, init?: RequestInit): Promise<Response> => {
// SDK and Types
export type EndpointWeapon = EndpointBasicWeapon & {
appearances: {
categories: string[];
translations: {
language: string;
sourceLanguage: string;
name: string;
description?: string;
level1?: string;
level2?: string;
level3?: string;
level4?: string;
transcribers: string[];
translators: string[];
proofreaders: string[];
}[];
}[];
group?: {
slug: string;
translations: { language: string; name: string }[];
weapons: EndpointBasicWeapon[];
};
};
export type EndpointBasicWeapon = {
slug: string;
type: string;
categories: string[];
translations: { language: string; name: string; aliases: string[] }[];
images?: {
previewCard: PayloadImage;
thumbnailHeader: PayloadImage;
lightBox: PayloadImage;
openGraph: PayloadImage;
};
};
export type EndpointEra = {
slug: string;
startingYear: number;
@ -140,7 +103,7 @@ export type EndpointEra = {
translations: {
language: string;
title: string;
description?: string;
description?: RichTextContent;
}[];
items: {
date: {
@ -153,16 +116,13 @@ export type EndpointEra = {
language: string;
sourceLanguage: string;
title?: string;
description?: string;
notes?: string;
transcribers: string[];
translators: string[];
proofreaders: string[];
description?: RichTextContent;
notes?: RichTextContent;
transcribers: EndpointRecorder[];
translators: EndpointRecorder[];
proofreaders: EndpointRecorder[];
}[];
}[];
createdAt: Date;
updatedAt: Date;
updatedBy: string;
}[];
};
@ -364,8 +324,6 @@ export type PayloadImage = {
};
export const payload = {
getWeapon: async (slug: string): Promise<EndpointWeapon> =>
await (await request(payloadApiUrl(Collections.Weapons, `slug/${slug}`))).json(),
getEras: async (): Promise<EndpointEra[]> =>
await (await request(payloadApiUrl(Collections.ChronologyEras, `all`))).json(),
getRootFolders: async (): Promise<EndpointFolderPreview[]> =>
@ -380,10 +338,6 @@ export const payload = {
await (await request(payloadApiUrl(Collections.Wordings, `all`))).json(),
getRecorders: async (): Promise<EndpointRecorder[]> =>
await (await request(payloadApiUrl(Collections.Recorders, `all`))).json(),
getTags: async (): Promise<EndpointTag[]> =>
await (await request(payloadApiUrl(Collections.Tags, `all`))).json(),
getTagsGroups: async (): Promise<EndpointTagsGroup[]> =>
await (await request(payloadApiUrl(Collections.TagsGroups, `all`))).json(),
getPage: async (slug: string): Promise<EndpointPage> =>
await (await request(payloadApiUrl(Collections.Pages, `slug/${slug}`))).json(),
getCollectible: async (slug: string): Promise<EndpointCollectible> =>

View File

@ -48,9 +48,6 @@ export interface Config {
pages: Page;
'chronology-items': ChronologyItem;
'chronology-eras': ChronologyEra;
weapons: Weapon;
'weapons-groups': WeaponsGroup;
'weapons-thumbnails': WeaponsThumbnail;
'recorders-thumbnails': RecordersThumbnail;
notes: Note;
videos: Video;
@ -64,6 +61,7 @@ export interface Config {
wordings: Wording;
collectibles: Collectible;
'generic-contents': GenericContent;
'background-images': BackgroundImage;
'payload-preferences': PayloadPreference;
'payload-migrations': PayloadMigration;
};
@ -195,7 +193,7 @@ export interface Collectible {
} | null;
id?: string | null;
}[];
backgroundImage?: string | Image | null;
backgroundImage?: string | BackgroundImage | null;
gallery?:
| {
image: string | Image;
@ -413,6 +411,31 @@ export interface TagsGroup {
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "background-images".
*/
export interface BackgroundImage {
id: string;
updatedAt: string;
createdAt: string;
url?: string | null;
filename?: string | null;
mimeType?: string | null;
filesize?: number | null;
width?: number | null;
height?: number | null;
sizes?: {
thumb?: {
url?: string | null;
width?: number | null;
height?: number | null;
mimeType?: string | null;
filesize?: number | null;
filename?: string | null;
};
};
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "recorders".
@ -484,7 +507,7 @@ export interface Page {
slug: string;
type: 'Content' | 'Post' | 'Generic';
thumbnail?: string | Image | null;
backgroundImage?: string | Image | null;
backgroundImage?: string | BackgroundImage | null;
tags?: (string | Tag)[] | null;
authors?: (string | Recorder)[] | null;
translations: {
@ -644,173 +667,6 @@ export interface ChronologyEra {
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "weapons".
*/
export interface Weapon {
id: string;
slug: string;
thumbnail?: string | WeaponsThumbnail | null;
group?: (string | null) | WeaponsGroup;
appearances: {
translations: {
language: string | Language;
sourceLanguage: string | Language;
name: string;
description?: {
root: {
children: {
type: string;
version: number;
[k: string]: unknown;
}[];
direction: ('ltr' | 'rtl') | null;
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
indent: number;
type: string;
version: number;
};
[k: string]: unknown;
} | null;
level1?: {
root: {
children: {
type: string;
version: number;
[k: string]: unknown;
}[];
direction: ('ltr' | 'rtl') | null;
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
indent: number;
type: string;
version: number;
};
[k: string]: unknown;
} | null;
level2?: {
root: {
children: {
type: string;
version: number;
[k: string]: unknown;
}[];
direction: ('ltr' | 'rtl') | null;
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
indent: number;
type: string;
version: number;
};
[k: string]: unknown;
} | null;
level3?: {
root: {
children: {
type: string;
version: number;
[k: string]: unknown;
}[];
direction: ('ltr' | 'rtl') | null;
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
indent: number;
type: string;
version: number;
};
[k: string]: unknown;
} | null;
level4?: {
root: {
children: {
type: string;
version: number;
[k: string]: unknown;
}[];
direction: ('ltr' | 'rtl') | null;
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
indent: number;
type: string;
version: number;
};
[k: string]: unknown;
} | null;
transcribers?: (string | Recorder)[] | null;
translators?: (string | Recorder)[] | null;
proofreaders?: (string | Recorder)[] | null;
id?: string | null;
}[];
id?: string | null;
}[];
updatedBy: string | Recorder;
updatedAt: string;
createdAt: string;
_status?: ('draft' | 'published') | null;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "weapons-thumbnails".
*/
export interface WeaponsThumbnail {
id: string;
weapon?: (string | null) | Weapon;
updatedAt: string;
createdAt: string;
url?: string | null;
filename?: string | null;
mimeType?: string | null;
filesize?: number | null;
width?: number | null;
height?: number | null;
sizes?: {
thumb?: {
url?: string | null;
width?: number | null;
height?: number | null;
mimeType?: string | null;
filesize?: number | null;
filename?: string | null;
};
og?: {
url?: string | null;
width?: number | null;
height?: number | null;
mimeType?: string | null;
filesize?: number | null;
filename?: string | null;
};
small?: {
url?: string | null;
width?: number | null;
height?: number | null;
mimeType?: string | null;
filesize?: number | null;
filename?: string | null;
};
medium?: {
url?: string | null;
width?: number | null;
height?: number | null;
mimeType?: string | null;
filesize?: number | null;
filename?: string | null;
};
};
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "weapons-groups".
*/
export interface WeaponsGroup {
id: string;
slug: string;
translations?:
| {
language: string | Language;
name: string;
id?: string | null;
}[]
| null;
weapons?: (string | Weapon)[] | null;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "notes".

View File

@ -2,7 +2,6 @@ import { ImageSize } from "payload/dist/uploads/types";
import { CollectionConfig } from "payload/types";
import { publicAccess } from "../accesses/publicAccess";
import { CollectionGroups } from "../constants";
import { createImageRegenerationEndpoint } from "../endpoints/createImageRegenerationEndpoint";
import { BuildCollectionConfig, buildCollectionConfig } from "./collectionConfig";
type BuildImageCollectionConfig = Omit<BuildCollectionConfig, "upload"> & {
@ -26,7 +25,6 @@ export const buildImageCollectionConfig = ({
access: {
read: publicAccess,
},
endpoints: [createImageRegenerationEndpoint(otherConfig.slug)],
upload: {
staticDir: `../uploads/${otherConfig.slug}`,
mimeTypes: ["image/*"],