improve sources and parent pages
This commit is contained in:
parent
0c4d5e4007
commit
1d5e34f1a6
1
TODO.md
1
TODO.md
|
@ -8,6 +8,7 @@
|
|||
## Mid term
|
||||
|
||||
- Support for nameless section
|
||||
- [Timeline] Error if collectible not published?
|
||||
- [Collectibles] Create page for gallery
|
||||
- [Collectibles] Create page for scans
|
||||
- When the tags overflow, the tag group name should be align start (see http://localhost:12499/en/pages/magnitude-negative-chapter-1)
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
import Html from "./components/Html.astro";
|
||||
import Topbar from "./components/Topbar/Topbar.astro";
|
||||
import Footer from "./components/Footer.astro";
|
||||
import type { ParentPage, PayloadImage } from "src/shared/payload/payload-sdk";
|
||||
import type { EndpointSource, PayloadImage } from "src/shared/payload/payload-sdk";
|
||||
import AppLayoutBackgroundImg from "./components/AppLayoutBackgroundImg.astro";
|
||||
import type { ComponentProps } from "astro/types";
|
||||
|
||||
interface Props {
|
||||
openGraph?: ComponentProps<typeof Html>["openGraph"];
|
||||
parentPages?: ParentPage[];
|
||||
parentPages?: EndpointSource[];
|
||||
hideFooterLinks?: boolean;
|
||||
backgroundImage?: PayloadImage | undefined;
|
||||
}
|
||||
|
|
|
@ -4,12 +4,12 @@ import Button from "components/Button.astro";
|
|||
import ThemeSelector from "./components/ThemeSelector.astro";
|
||||
import LanguageSelector from "./components/LanguageSelector.astro";
|
||||
import CurrencySelector from "./components/CurrencySelector.astro";
|
||||
import type { ParentPage } from "src/shared/payload/payload-sdk";
|
||||
import ParentPagesButton from "./components/ParentPagesButton.astro";
|
||||
import { getI18n } from "src/i18n/i18n";
|
||||
import type { EndpointSource } from "src/shared/payload/payload-sdk";
|
||||
|
||||
interface Props {
|
||||
parentPages?: ParentPage[] | undefined;
|
||||
parentPages?: EndpointSource[] | undefined;
|
||||
hideHomeButton?: boolean;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
---
|
||||
import Tooltip from "components/Tooltip.astro";
|
||||
import type { ParentPage } from "src/shared/payload/payload-sdk";
|
||||
import ParentPageLink from "./ParentPageLink.astro";
|
||||
import { Icon } from "astro-icon/components";
|
||||
import { getI18n } from "src/i18n/i18n";
|
||||
import ReturnToButton from "./ReturnToButton.astro";
|
||||
import type { EndpointSource } from "src/shared/payload/payload-sdk";
|
||||
import SourceRow from "components/SourceRow.astro";
|
||||
|
||||
interface Props {
|
||||
parentPages: ParentPage[];
|
||||
parentPages: EndpointSource[];
|
||||
}
|
||||
|
||||
const { parentPages } = Astro.props;
|
||||
|
@ -24,9 +24,11 @@ const { t } = await getI18n(Astro.locals.currentLocale);
|
|||
<Tooltip trigger="click">
|
||||
<div id="tooltip-content" slot="tooltip-content">
|
||||
<p>{t("header.nav.parentPages.tooltip")}</p>
|
||||
{parentPages.map((parentPage) => (
|
||||
<ParentPageLink parentPage={parentPage} />
|
||||
))}
|
||||
<div>
|
||||
{parentPages.map((parentPage) => (
|
||||
<SourceRow source={parentPage} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div class="pressable-label">
|
||||
<Icon name="material-symbols:keyboard-return" />
|
||||
|
@ -44,7 +46,14 @@ const { t } = await getI18n(Astro.locals.currentLocale);
|
|||
|
||||
<style>
|
||||
#tooltip-content {
|
||||
display: grid;
|
||||
gap: 1em;
|
||||
> p {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,44 +1,32 @@
|
|||
---
|
||||
import { Icon } from "astro-icon/components";
|
||||
import { getI18n } from "src/i18n/i18n";
|
||||
import { Collections, type ParentPage } from "src/shared/payload/payload-sdk";
|
||||
import type { EndpointSource } from "src/shared/payload/payload-sdk";
|
||||
|
||||
interface Props {
|
||||
parentPage: ParentPage;
|
||||
parentPage: EndpointSource;
|
||||
}
|
||||
|
||||
const { parentPage } = Astro.props;
|
||||
const { getLocalizedMatch, getLocalizedUrl, t } = await getI18n(Astro.locals.currentLocale);
|
||||
const { formatEndpointSource } = await getI18n(Astro.locals.currentLocale);
|
||||
|
||||
const translation = getLocalizedMatch(parentPage.translations);
|
||||
|
||||
let href = "";
|
||||
let collectionLabel = "";
|
||||
switch (parentPage.collection) {
|
||||
case Collections.Folders:
|
||||
href = getLocalizedUrl(`/folders/${parentPage.slug}`);
|
||||
collectionLabel = t("header.nav.parentPages.collections.folder");
|
||||
break;
|
||||
|
||||
case Collections.Collectibles:
|
||||
href = getLocalizedUrl(`/collectibles/${parentPage.slug}`);
|
||||
collectionLabel = t("header.nav.parentPages.collections.collectible");
|
||||
break;
|
||||
|
||||
default:
|
||||
href = "/404";
|
||||
break;
|
||||
}
|
||||
const {
|
||||
href,
|
||||
typeLabel,
|
||||
label,
|
||||
target = undefined,
|
||||
rel = undefined,
|
||||
} = formatEndpointSource(parentPage);
|
||||
---
|
||||
|
||||
{/* ------------------------------------------- HTML ------------------------------------------- */}
|
||||
|
||||
<a href={href}>
|
||||
<a href={href} target={target} rel={rel}>
|
||||
<div class="pressable-label">
|
||||
<Icon name="material-symbols:keyboard-return" />
|
||||
<p>
|
||||
<span>{collectionLabel}</span>
|
||||
{translation.name}
|
||||
<span>{typeLabel}</span>
|
||||
{label}
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
|
|
|
@ -1,38 +1,26 @@
|
|||
---
|
||||
import { getI18n } from "src/i18n/i18n";
|
||||
import { Collections, type ParentPage } from "src/shared/payload/payload-sdk";
|
||||
import type { EndpointSource } from "src/shared/payload/payload-sdk";
|
||||
|
||||
interface Props {
|
||||
parentPage: ParentPage;
|
||||
source: EndpointSource;
|
||||
}
|
||||
|
||||
const { parentPage } = Astro.props;
|
||||
const { getLocalizedMatch, getLocalizedUrl, t } = await getI18n(Astro.locals.currentLocale);
|
||||
const { source } = Astro.props;
|
||||
const { formatEndpointSource } = await getI18n(Astro.locals.currentLocale);
|
||||
|
||||
const translation = getLocalizedMatch(parentPage.translations);
|
||||
|
||||
let href = "";
|
||||
let collectionLabel = "";
|
||||
switch (parentPage.collection) {
|
||||
case Collections.Folders:
|
||||
href = getLocalizedUrl(`/folders/${parentPage.slug}`);
|
||||
collectionLabel = t("header.nav.parentPages.collections.folder");
|
||||
break;
|
||||
|
||||
case Collections.Collectibles:
|
||||
href = getLocalizedUrl(`/collectibles/${parentPage.slug}`);
|
||||
collectionLabel = t("header.nav.parentPages.collections.collectible");
|
||||
break;
|
||||
|
||||
default:
|
||||
href = "/404";
|
||||
break;
|
||||
}
|
||||
const {
|
||||
href,
|
||||
typeLabel,
|
||||
label,
|
||||
target = undefined,
|
||||
rel = undefined,
|
||||
} = formatEndpointSource(source);
|
||||
---
|
||||
|
||||
{/* ------------------------------------------- HTML ------------------------------------------- */}
|
||||
|
||||
<a href={href}><div>{collectionLabel}</div><p>{translation.name}</p></a>
|
||||
<a href={href} target={target} rel={rel}><div>{typeLabel}</div><p>{label}</p></a>
|
||||
|
||||
{/* ------------------------------------------- CSS -------------------------------------------- */}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import type { WordingKey } from "src/i18n/wordings-keys";
|
||||
import type { ChronologyEvent } from "src/shared/payload/payload-sdk";
|
||||
import type { ChronologyEvent, EndpointSource } from "src/shared/payload/payload-sdk";
|
||||
import { cache } from "src/utils/cachedPayload";
|
||||
import { capitalize } from "src/utils/format";
|
||||
import { capitalize, formatInlineTitle } from "src/utils/format";
|
||||
|
||||
export const defaultLocale = "en";
|
||||
|
||||
|
@ -173,6 +173,70 @@ export const getI18n = async (locale: string) => {
|
|||
);
|
||||
};
|
||||
|
||||
const formatEndpointSource = (source: EndpointSource) => {
|
||||
switch (source.type) {
|
||||
case "url":
|
||||
return {
|
||||
href: source.url,
|
||||
typeLabel: t("global.sources.typeLabel.url"),
|
||||
label: source.label,
|
||||
target: "_blank",
|
||||
rel: "noopener noreferrer",
|
||||
};
|
||||
|
||||
case "collectible":
|
||||
const rangeLabel = (() => {
|
||||
switch (source.range?.type) {
|
||||
case "timestamp":
|
||||
return t("global.sources.typeLabel.collectible.range.timestamp", {
|
||||
page: source.range.timestamp,
|
||||
});
|
||||
|
||||
case "page":
|
||||
return t("global.sources.typeLabel.collectible.range.page", {
|
||||
page: source.range.page,
|
||||
});
|
||||
|
||||
case "custom":
|
||||
return t("global.sources.typeLabel.collectible.range.custom", {
|
||||
note: getLocalizedMatch(source.range.translations).note,
|
||||
});
|
||||
|
||||
case undefined:
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
})();
|
||||
|
||||
return {
|
||||
href: getLocalizedUrl(`/collectibles/${source.collectible.slug}`),
|
||||
typeLabel: t("global.sources.typeLabel.collectible"),
|
||||
label: formatInlineTitle(getLocalizedMatch(source.collectible.translations)) + rangeLabel,
|
||||
};
|
||||
|
||||
case "page":
|
||||
return {
|
||||
href: getLocalizedUrl(`/pages/${source.page.slug}`),
|
||||
typeLabel: t("global.sources.typeLabel.page"),
|
||||
label: formatInlineTitle(getLocalizedMatch(source.page.translations)),
|
||||
};
|
||||
|
||||
case "folder":
|
||||
return {
|
||||
href: getLocalizedUrl(`/folders/${source.folder.slug}`),
|
||||
typeLabel: t("global.sources.typeLabel.folder"),
|
||||
label: getLocalizedMatch(source.folder.translations).name,
|
||||
};
|
||||
|
||||
default:
|
||||
return {
|
||||
href: "/404",
|
||||
label: `Invalid type ${source["type"]}`,
|
||||
typeLabel: "Error",
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
t,
|
||||
getLocalizedMatch,
|
||||
|
@ -185,5 +249,6 @@ export const getI18n = async (locale: string) => {
|
|||
formatMillimeters,
|
||||
formatNumber,
|
||||
formatTimelineDate,
|
||||
formatEndpointSource,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -104,4 +104,11 @@ export type WordingKey =
|
|||
| "timeline.year.during"
|
||||
| "timeline.eventFooter.languages"
|
||||
| "timeline.eventFooter.sources"
|
||||
| "timeline.eventFooter.note";
|
||||
| "timeline.eventFooter.note"
|
||||
| "global.sources.typeLabel.url"
|
||||
| "global.sources.typeLabel.page"
|
||||
| "global.sources.typeLabel.collectible"
|
||||
| "global.sources.typeLabel.folder"
|
||||
| "global.sources.typeLabel.collectible.range.page"
|
||||
| "global.sources.typeLabel.collectible.range.timestamp"
|
||||
| "global.sources.typeLabel.collectible.range.custom";
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
---
|
||||
import { Icon } from "astro-icon/components";
|
||||
import SourceRow from "components/SourceRow.astro";
|
||||
import Tooltip from "components/Tooltip.astro";
|
||||
import { getI18n } from "src/i18n/i18n";
|
||||
import type { EndpointSource } from "src/shared/payload/payload-sdk";
|
||||
import { formatInlineTitle } from "src/utils/format";
|
||||
|
||||
interface Props {
|
||||
sources: EndpointSource[];
|
||||
|
@ -11,30 +11,12 @@ interface Props {
|
|||
|
||||
const { sources } = Astro.props;
|
||||
|
||||
const { getLocalizedUrl, getLocalizedMatch, t } = await getI18n(Astro.locals.currentLocale);
|
||||
const { t } = await getI18n(Astro.locals.currentLocale);
|
||||
---
|
||||
|
||||
<Tooltip trigger="click">
|
||||
<div id="tooltip-content" slot="tooltip-content">
|
||||
{
|
||||
sources.map((source) =>
|
||||
source.type === "url" ? (
|
||||
<a class="pressable-link" href={source.url} target={"_blank"} rel={"noopener noreferrer"}>
|
||||
{source.label}
|
||||
</a>
|
||||
) : source.type === "collectible" ? (
|
||||
<a
|
||||
class="pressable-link"
|
||||
href={getLocalizedUrl(`/collectibles/${source.collectible.slug}`)}>
|
||||
{formatInlineTitle(getLocalizedMatch(source.collectible.translations))}
|
||||
</a>
|
||||
) : (
|
||||
<a class="pressable-link" href={getLocalizedUrl(`/pages/${source.page.slug}`)}>
|
||||
{formatInlineTitle(getLocalizedMatch(source.page.translations))}
|
||||
</a>
|
||||
)
|
||||
)
|
||||
}
|
||||
{sources.map((source) => <SourceRow source={source} />)}
|
||||
</div>
|
||||
<div class="pressable-label">
|
||||
<Icon name="material-symbols:edit-note" />
|
||||
|
|
|
@ -862,9 +862,6 @@ export interface SectionBlock {
|
|||
blockType: "sectionBlock";
|
||||
}
|
||||
|
||||
declare module "payload" {
|
||||
export interface GeneratedTypes extends Config {}
|
||||
}
|
||||
|
||||
/////////////// CONSTANTS ///////////////
|
||||
|
||||
|
@ -1299,7 +1296,7 @@ export type EndpointFolder = EndpointFolderPreview & {
|
|||
value: EndpointPagePreview;
|
||||
}
|
||||
)[];
|
||||
parentPages: ParentPage[];
|
||||
parentPages: EndpointSource[];
|
||||
};
|
||||
|
||||
export type EndpointHomeFolder = EndpointFolderPreview & {
|
||||
|
@ -1369,13 +1366,7 @@ export type EndpointPage = EndpointPagePreview & {
|
|||
proofreaders: EndpointRecorder[];
|
||||
toc: TableOfContentEntry[];
|
||||
})[];
|
||||
parentPages: ParentPage[];
|
||||
};
|
||||
|
||||
export type ParentPage = {
|
||||
slug: string;
|
||||
collection: Collections;
|
||||
translations: { language: string; name: string }[];
|
||||
parentPages: EndpointSource[];
|
||||
};
|
||||
|
||||
export type EndpointCollectiblePreview = {
|
||||
|
@ -1450,7 +1441,7 @@ export type EndpointCollectible = EndpointCollectiblePreview & {
|
|||
}[];
|
||||
};
|
||||
}[];
|
||||
parentPages: ParentPage[];
|
||||
parentPages: EndpointSource[];
|
||||
};
|
||||
|
||||
export type TableOfContentEntry = {
|
||||
|
@ -1493,7 +1484,8 @@ export type EndpointSource =
|
|||
| { type: "timestamp"; timestamp: string }
|
||||
| { type: "custom"; translations: { language: string; note: string }[] };
|
||||
}
|
||||
| { type: "page"; page: EndpointPagePreview };
|
||||
| { type: "page"; page: EndpointPagePreview }
|
||||
| { type: "folder"; folder: EndpointFolderPreview };
|
||||
|
||||
export type PayloadImage = {
|
||||
url: string;
|
||||
|
@ -1523,5 +1515,5 @@ export const payload = {
|
|||
getChronologyEvents: async (): Promise<EndpointChronologyEvent[]> =>
|
||||
await (await request(payloadApiUrl(Collections.ChronologyEvents, `all`))).json(),
|
||||
getChronologyEventByID: async (id: string): Promise<EndpointChronologyEvent> =>
|
||||
await (await request(payloadApiUrl(Collections.ChronologyEvents, id))).json(),
|
||||
await (await request(payloadApiUrl(Collections.ChronologyEvents, `id/${id}`))).json(),
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue