Added recorders pages

This commit is contained in:
DrMint 2024-05-16 14:15:49 +02:00
parent 0e148f06cf
commit 91e67a7645
8 changed files with 132 additions and 19 deletions

View File

@ -3,7 +3,6 @@
## Short term ## Short term
- Number of audio players seems limited (on Chrome and Firefox) - Number of audio players seems limited (on Chrome and Firefox)
- Create a tool to upload scans images and apply them to collectible
- Automatically generate different sizes of images - Automatically generate different sizes of images
- Handle relationship in RichText Content - Handle relationship in RichText Content
@ -15,7 +14,6 @@
- [Timeline] Error if collectible not published? - [Timeline] Error if collectible not published?
- [Timeline] display source language - [Timeline] display source language
- [Timeline] Add details button in footer with credits + last updated / created - [Timeline] Add details button in footer with credits + last updated / created
- When the tags overflow, the tag group name should be align start (see http://localhost:12499/en/pages/magnitude-negative-chapter-1)
- [SDK] create a initPayload() that return a payload sdk (and stop hard wirring to ENV or node-cache) - [SDK] create a initPayload() that return a payload sdk (and stop hard wirring to ENV or node-cache)
- [Videos] see why no video on Firefox and no poster on Chrome https://v3.accords-library.com/en/videos/661b672825d380e548dbb8c8 - [Videos] see why no video on Firefox and no poster on Chrome https://v3.accords-library.com/en/videos/661b672825d380e548dbb8c8
- [Videos] Display platform info + channel page - [Videos] Display platform info + channel page
@ -41,6 +39,7 @@
- Convert Rich text to simple text for indexing and open graph purposes - Convert Rich text to simple text for indexing and open graph purposes
- Anonymous comments - Anonymous comments
- [Images] add images group (which could be named or not) - [Images] add images group (which could be named or not)
- [Recorders] add list of contributions on recorders' pages
## Bonus ## Bonus

View File

@ -21,7 +21,7 @@ const { t } = await getI18n(Astro.locals.currentLocale);
parentPages.length === 1 && parentPages[0] ? ( parentPages.length === 1 && parentPages[0] ? (
<ReturnToButton parentPage={parentPages[0]} /> <ReturnToButton parentPage={parentPages[0]} />
) : ( ) : (
<Tooltip trigger="click"> <Tooltip trigger="click" class="when-js">
<div id="tooltip-content" slot="tooltip-content"> <div id="tooltip-content" slot="tooltip-content">
<p>{t("header.nav.parentPages.tooltip")}</p> <p>{t("header.nav.parentPages.tooltip")}</p>
<div> <div>

View File

@ -8,7 +8,7 @@ interface Props {
} }
const { credits } = Astro.props; const { credits } = Astro.props;
const { getLocalizedMatch } = await getI18n(Astro.locals.currentLocale); const { getLocalizedMatch, getLocalizedUrl } = await getI18n(Astro.locals.currentLocale);
--- ---
{/* ------------------------------------------- HTML ------------------------------------------- */} {/* ------------------------------------------- HTML ------------------------------------------- */}
@ -19,7 +19,10 @@ const { getLocalizedMatch } = await getI18n(Astro.locals.currentLocale);
<Metadata <Metadata
icon={icon} icon={icon}
title={getLocalizedMatch(translations).name} title={getLocalizedMatch(translations).name}
values={recorders.map(({ username }) => ({ name: username }))} values={recorders.map(({ username, id }) => ({
name: username,
href: getLocalizedUrl(`/recorders/${id}`),
}))}
/> />
)) ))
} }

View File

@ -38,7 +38,6 @@ if (values.length === 0) return;
display: grid; display: grid;
grid-template-columns: auto 1fr; grid-template-columns: auto 1fr;
gap: 0.5em 1em; gap: 0.5em 1em;
align-items: center;
@media (max-width: 35em) { @media (max-width: 35em) {
grid-template-columns: 1fr; grid-template-columns: 1fr;
@ -46,7 +45,6 @@ if (values.length === 0) return;
& > #title { & > #title {
display: flex; display: flex;
place-items: center;
gap: 8px; gap: 8px;
& > p { & > p {

View File

@ -10,6 +10,7 @@ import { getI18n } from "src/i18n/i18n";
import AsideLayout from "components/AppLayout/AsideLayout.astro"; import AsideLayout from "components/AppLayout/AsideLayout.astro";
import AppLayoutDescription from "components/AppLayout/components/AppLayoutDescription.astro"; import AppLayoutDescription from "components/AppLayout/components/AppLayoutDescription.astro";
import Attributes from "components/Attributes.astro"; import Attributes from "components/Attributes.astro";
import type { Attribute } from "src/utils/attributes";
export const partial = true; export const partial = true;
@ -31,18 +32,16 @@ const { getLocalizedMatch } = await getI18n(lang);
const { pretitle, title, subtitle, summary, content, credits, toc, language, sourceLanguage } = const { pretitle, title, subtitle, summary, content, credits, toc, language, sourceLanguage } =
getLocalizedMatch(translations); getLocalizedMatch(translations);
const metaAttributes = [ const metaAttributes: Attribute[] = [
{ {
title: t("global.media.attributes.createdAt"), title: t("global.media.attributes.createdAt"),
icon: "material-symbols:calendar-add-on-outline", icon: "material-symbols:calendar-add-on-outline",
values: [{ name: formatDate(new Date(createdAt)) }], values: [{ name: formatDate(new Date(createdAt)) }],
withBorder: false,
}, },
{ {
title: t("global.media.attributes.updatedAt"), title: t("global.media.attributes.updatedAt"),
icon: "material-symbols:edit-calendar", icon: "material-symbols:edit-calendar",
values: [{ name: formatDate(new Date(updatedAt)) }], values: [{ name: formatDate(new Date(updatedAt)) }],
withBorder: false,
}, },
]; ];
@ -50,7 +49,7 @@ if (updatedBy) {
metaAttributes.push({ metaAttributes.push({
title: t("global.media.attributes.updatedBy"), title: t("global.media.attributes.updatedBy"),
icon: "material-symbols:person-edit-outline", icon: "material-symbols:person-edit-outline",
values: [{ name: updatedBy.username }], values: [{ name: updatedBy.username, href: getLocalizedUrl(`/recorders/${updatedBy.id}`) }],
withBorder: true, withBorder: true,
}); });
} }

View File

@ -16,6 +16,7 @@ import AsideLayout from "components/AppLayout/AsideLayout.astro";
import AppLayoutDescription from "components/AppLayout/components/AppLayoutDescription.astro"; import AppLayoutDescription from "components/AppLayout/components/AppLayoutDescription.astro";
import { convert } from "src/utils/currencies"; import { convert } from "src/utils/currencies";
import Attributes from "components/Attributes.astro"; import Attributes from "components/Attributes.astro";
import type { Attribute } from "src/utils/attributes";
const { slug } = Astro.params; const { slug } = Astro.params;
const { getLocalizedMatch, getLocalizedUrl, t, formatDate, formatPrice } = await getI18n( const { getLocalizedMatch, getLocalizedUrl, t, formatDate, formatPrice } = await getI18n(
@ -53,18 +54,16 @@ const {
const translation = getLocalizedMatch(translations); const translation = getLocalizedMatch(translations);
const { pretitle, title, subtitle, description } = translation; const { pretitle, title, subtitle, description } = translation;
const metaAttributes = [ const metaAttributes: Attribute[] = [
{ {
title: t("global.media.attributes.createdAt"), title: t("global.media.attributes.createdAt"),
icon: "material-symbols:calendar-add-on-outline", icon: "material-symbols:calendar-add-on-outline",
values: [{ name: formatDate(new Date(createdAt)) }], values: [{ name: formatDate(new Date(createdAt)) }],
withBorder: false,
}, },
{ {
title: t("global.media.attributes.updatedAt"), title: t("global.media.attributes.updatedAt"),
icon: "material-symbols:edit-calendar", icon: "material-symbols:edit-calendar",
values: [{ name: formatDate(new Date(updatedAt)) }], values: [{ name: formatDate(new Date(updatedAt)) }],
withBorder: false,
}, },
]; ];
@ -72,7 +71,7 @@ if (updatedBy) {
metaAttributes.push({ metaAttributes.push({
title: t("global.media.attributes.updatedBy"), title: t("global.media.attributes.updatedBy"),
icon: "material-symbols:person-edit-outline", icon: "material-symbols:person-edit-outline",
values: [{ name: updatedBy.username }], values: [{ name: updatedBy.username, href: getLocalizedUrl(`/recorders/${updatedBy.id}`) }],
withBorder: true, withBorder: true,
}); });
} }
@ -259,7 +258,6 @@ if (price) {
max-height: 80vh; max-height: 80vh;
width: auto; width: auto;
height: auto; height: auto;
border-radius: 16px;
box-shadow: 0 5px 20px -10px var(--color-shadow); box-shadow: 0 5px 20px -10px var(--color-shadow);
transition: 100ms scale; transition: 100ms scale;

View File

@ -0,0 +1,91 @@
---
import AppLayout from "components/AppLayout/AppLayout.astro";
import AsideLayout from "components/AppLayout/AsideLayout.astro";
import AppLayoutTitle from "components/AppLayout/components/AppLayoutTitle.astro";
import Attributes from "components/Attributes.astro";
import RichText from "components/RichText/RichText.astro";
import { getI18n } from "src/i18n/i18n";
import { payload } from "src/shared/payload/payload-sdk";
import type { Attribute } from "src/utils/attributes";
import { formatLocale } from "src/utils/format";
import { fetchOr404 } from "src/utils/responses";
const id = Astro.params.id!;
const recorder = await fetchOr404(() => payload.getRecorderByID(id));
if (recorder instanceof Response) {
return recorder;
}
const { t, getLocalizedMatch } = await getI18n(Astro.locals.currentLocale);
const { username, languages, avatar, translations } = recorder;
const { biography } =
translations.length > 0 ? getLocalizedMatch(translations) : { biography: undefined };
const additionalAttributes: Attribute[] = [];
if (languages.length > 0) {
additionalAttributes.push({
title: t("collectibles.languages"),
icon: "material-symbols:translate",
values: languages.map((lang) => ({ name: formatLocale(lang) })),
withBorder: true,
});
}
---
{/* ------------------------------------------- HTML ------------------------------------------- */}
<AppLayout>
<AsideLayout>
<Fragment slot="header">
<AppLayoutTitle pretitle={`Recorder#${id.substring(0, 5)}`} title={username} />
</Fragment>
{
avatar && (
<Fragment slot="header-aside">
<img src={avatar.url} width={avatar.width} height={avatar.height} />
</Fragment>
)
}
{
avatar && additionalAttributes.length > 0 && (
<Fragment slot="aside">
<Attributes attributes={additionalAttributes} />
</Fragment>
)
}
<div id="info">
{
!avatar && additionalAttributes.length > 0 && (
<Attributes attributes={additionalAttributes} />
)
}
{biography && <RichText content={biography} />}
</div>
</AsideLayout>
</AppLayout>
{/* ------------------------------------------- CSS -------------------------------------------- */}
<style>
img {
max-width: min(35rem, 100%);
max-height: 50vh;
width: auto;
height: auto;
margin-bottom: 2em;
@media (max-width: 1280.5px) {
margin-top: 2em;
}
}
#info {
margin-top: 2em;
}
</style>

View File

@ -262,6 +262,27 @@ export interface Recorder {
username: string; username: string;
avatar?: string | Image | null; avatar?: string | Image | null;
languages?: (string | Language)[] | null; languages?: (string | Language)[] | null;
translations?:
| {
language: string | Language;
biography: {
root: {
type: string;
children: {
type: string;
version: number;
[k: string]: unknown;
}[];
direction: ("ltr" | "rtl") | null;
format: "left" | "start" | "center" | "right" | "end" | "justify" | "";
indent: number;
version: number;
};
[k: string]: unknown;
};
id?: string | null;
}[]
| null;
role?: ("Admin" | "Recorder" | "Api")[] | null; role?: ("Admin" | "Recorder" | "Api")[] | null;
anonymize: boolean; anonymize: boolean;
email: string; email: string;
@ -1471,6 +1492,10 @@ export type EndpointRecorder = {
id: string; id: string;
username: string; username: string;
avatar?: EndpointImage; avatar?: EndpointImage;
translations: {
language: string;
biography: RichTextContent;
}[];
languages: string[]; languages: string[];
}; };
@ -1854,8 +1879,6 @@ export const payload = {
await (await request(payloadApiUrl(Collections.Currencies, `all`))).json(), await (await request(payloadApiUrl(Collections.Currencies, `all`))).json(),
getWordings: async (): Promise<EndpointWording[]> => getWordings: async (): Promise<EndpointWording[]> =>
await (await request(payloadApiUrl(Collections.Wordings, `all`))).json(), await (await request(payloadApiUrl(Collections.Wordings, `all`))).json(),
getRecorders: async (): Promise<EndpointRecorder[]> =>
await (await request(payloadApiUrl(Collections.Recorders, `all`))).json(),
getPage: async (slug: string): Promise<EndpointPage> => getPage: async (slug: string): Promise<EndpointPage> =>
await (await request(payloadApiUrl(Collections.Pages, `slug/${slug}`))).json(), await (await request(payloadApiUrl(Collections.Pages, `slug/${slug}`))).json(),
getCollectible: async (slug: string): Promise<EndpointCollectible> => getCollectible: async (slug: string): Promise<EndpointCollectible> =>
@ -1888,4 +1911,6 @@ export const payload = {
await (await request(payloadApiUrl(Collections.Audios, `id/${id}`))).json(), await (await request(payloadApiUrl(Collections.Audios, `id/${id}`))).json(),
getVideoByID: async (id: string): Promise<EndpointVideo> => getVideoByID: async (id: string): Promise<EndpointVideo> =>
await (await request(payloadApiUrl(Collections.Videos, `id/${id}`))).json(), await (await request(payloadApiUrl(Collections.Videos, `id/${id}`))).json(),
getRecorderByID: async (id: string): Promise<EndpointRecorder> =>
await (await request(payloadApiUrl(Collections.Recorders, `id/${id}`))).json(),
}; };