Abstracted Image component for Strapi images + fixed key react problem

This commit is contained in:
DrMint 2022-02-21 01:01:27 +01:00
parent 1a4b73f1f5
commit c89fdbb499
24 changed files with 218 additions and 165 deletions

View File

@ -205,8 +205,6 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
<h2 className="text-2xl">Select a language</h2> <h2 className="text-2xl">Select a language</h2>
<div className="flex flex-wrap flex-row gap-2"> <div className="flex flex-wrap flex-row gap-2">
{router.locales?.sort().map((locale) => ( {router.locales?.sort().map((locale) => (
<>
{locale !== "xx" ? (
<Button <Button
key={locale} key={locale}
active={locale === router.locale} active={locale === router.locale}
@ -215,10 +213,6 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
> >
{prettyLanguage(locale)} {prettyLanguage(locale)}
</Button> </Button>
) : (
""
)}
</>
))} ))}
</div> </div>
</div> </div>

View File

@ -2,9 +2,9 @@ import {
GetContentQuery, GetContentQuery,
GetWebsiteInterfaceQuery, GetWebsiteInterfaceQuery,
} from "graphql/operations-types"; } from "graphql/operations-types";
import { getAssetURL, ImageQuality, prettySlug } from "queries/helpers"; import { prettySlug } from "queries/helpers";
import Image from "next/image";
import Button from "components/Button"; import Button from "components/Button";
import Img, { ImageQuality } from "components/Img";
export type ThumbnailHeaderProps = { export type ThumbnailHeaderProps = {
content: { content: {
@ -28,12 +28,11 @@ export default function ThumbnailHeader(
<div className="grid place-items-center gap-12 mb-12"> <div className="grid place-items-center gap-12 mb-12">
<div className="drop-shadow-dark-lg"> <div className="drop-shadow-dark-lg">
{content.thumbnail.data ? ( {content.thumbnail.data ? (
<Image <Img
className=" rounded-xl" className=" rounded-xl"
src={getAssetURL(content.thumbnail.data.attributes.url, ImageQuality.Medium)} image={content.thumbnail.data.attributes}
alt={content.thumbnail.data.attributes.alternativeText} quality={ImageQuality.Medium}
width={content.thumbnail.data.attributes.width} priority
height={content.thumbnail.data.attributes.height}
/> />
) : ( ) : (
<div className="w-full aspect-[4/3] bg-light rounded-xl"></div> <div className="w-full aspect-[4/3] bg-light rounded-xl"></div>

88
src/components/Img.tsx Normal file
View File

@ -0,0 +1,88 @@
import { GetLibraryItemsPreviewQuery } from "graphql/operations-types";
import { ImageProps } from "next/image";
import Image from "next/image";
export enum ImageQuality {
Small = "small",
Medium = "medium",
Large = "large",
Og = "og",
}
export function getAssetURL(url: string, quality?: ImageQuality): string {
if (!quality) quality = ImageQuality.Small;
url = url.replace(/^\/uploads/, "/" + quality);
url = url.replace(/.jpg$/, ".webp");
url = url.replace(/.png$/, ".webp");
return process.env.NEXT_PUBLIC_URL_IMG + url;
}
export function getImgSizesByMaxSize(
width: number,
height: number,
maxSize: number
): { width: number; height: number } {
if (width > height) {
if (width < maxSize) return { width: width, height: height };
return { width: maxSize, height: (height / width) * maxSize };
} else {
if (height < maxSize) return { width: width, height: height };
return { width: (width / height) * maxSize, height: maxSize };
}
}
export function getImgSizesByQuality(
width: number,
height: number,
quality: ImageQuality
): { width: number; height: number } {
switch (quality) {
case ImageQuality.Og:
return getImgSizesByMaxSize(width, height, 512);
case ImageQuality.Small:
return getImgSizesByMaxSize(width, height, 512);
case ImageQuality.Medium:
return getImgSizesByMaxSize(width, height, 1024);
case ImageQuality.Large:
return getImgSizesByMaxSize(width, height, 2048);
}
}
type ImgProps = {
className?: string;
image: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["thumbnail"]["data"]["attributes"];
quality?: ImageQuality;
alt?: ImageProps["alt"];
layout?: ImageProps["layout"];
objectFit?: ImageProps["objectFit"];
priority?: ImageProps["priority"];
};
export default function Img(props: ImgProps): JSX.Element {
if (props.layout == "fill") {
return (
<Image
src={getAssetURL(props.image.url, props.quality)}
alt={props.alt ? props.alt : props.image.alternativeText}
layout={props.layout}
objectFit={props.objectFit}
priority={props.priority}
/>
);
} else {
return (
<Image
src={getAssetURL(props.image.url, props.quality)}
alt={props.alt ? props.alt : props.image.alternativeText}
{...getImgSizesByQuality(
props.image.width,
props.image.height,
props.quality ? props.quality : ImageQuality.Small
)}
layout={props.layout}
objectFit={props.objectFit}
priority={props.priority}
/>
);
}
}

View File

@ -1,8 +1,8 @@
import Link from "next/link"; import Link from "next/link";
import { GetContentsQuery } from "graphql/operations-types"; import { GetContentsQuery } from "graphql/operations-types";
import { getAssetURL, prettySlug } from "queries/helpers"; import { prettySlug } from "queries/helpers";
import Image from "next/image";
import Chip from "components/Chip"; import Chip from "components/Chip";
import Img, { ImageQuality } from "components/Img";
export type LibraryContentPreviewProps = { export type LibraryContentPreviewProps = {
item: { item: {
@ -23,12 +23,10 @@ export default function LibraryContentPreview(
<Link href={"/library/content/" + item.slug} passHref> <Link href={"/library/content/" + item.slug} passHref>
<div className="drop-shadow-dark-xl cursor-pointer grid items-end fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform"> <div className="drop-shadow-dark-xl cursor-pointer grid items-end fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform">
{item.thumbnail.data ? ( {item.thumbnail.data ? (
<Image <Img
className="rounded-md coarse:rounded-b-none" className="rounded-md coarse:rounded-b-none"
src={getAssetURL(item.thumbnail.data.attributes.url)} image={item.thumbnail.data.attributes}
alt={item.thumbnail.data.attributes.alternativeText} quality={ImageQuality.Medium}
height={item.thumbnail.data.attributes.height}
width={item.thumbnail.data.attributes.width}
/> />
) : ( ) : (
<div className="w-full aspect-[3/2] bg-light rounded-lg"></div> <div className="w-full aspect-[3/2] bg-light rounded-lg"></div>

View File

@ -1,20 +1,11 @@
import Link from "next/link"; import Link from "next/link";
import { import { GetLibraryItemsPreviewQuery } from "graphql/operations-types";
GetLibraryItemsPreviewQuery, import { prettyDate, prettyPrice, prettyItemSubType } from "queries/helpers";
GetWebsiteInterfaceQuery,
} from "graphql/operations-types";
import {
getAssetURL,
prettyDate,
prettyPrice,
prettyItemSubType,
} from "queries/helpers";
import Image from "next/image";
import Chip from "components/Chip"; import Chip from "components/Chip";
import Img, { ImageQuality } from "components/Img";
export type LibraryItemsPreviewProps = { export type LibraryItemsPreviewProps = {
className?: string; className?: string;
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
item: { item: {
slug: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["slug"]; slug: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["slug"];
thumbnail: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["thumbnail"]; thumbnail: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["thumbnail"];
@ -30,7 +21,6 @@ export default function LibraryItemsPreview(
props: LibraryItemsPreviewProps props: LibraryItemsPreviewProps
): JSX.Element { ): JSX.Element {
const item = props.item; const item = props.item;
const langui = props.langui;
return ( return (
<Link href={"/library/items/" + item.slug} passHref> <Link href={"/library/items/" + item.slug} passHref>
@ -38,11 +28,9 @@ export default function LibraryItemsPreview(
className={`drop-shadow-dark-xl cursor-pointer grid items-end hover:rounded-3xl fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform ${props.className}`} className={`drop-shadow-dark-xl cursor-pointer grid items-end hover:rounded-3xl fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform ${props.className}`}
> >
{item.thumbnail.data ? ( {item.thumbnail.data ? (
<Image <Img
src={getAssetURL(item.thumbnail.data.attributes.url)} image={item.thumbnail.data.attributes}
alt={item.thumbnail.data.attributes.alternativeText} quality={ImageQuality.Medium}
height={item.thumbnail.data.attributes.height}
width={item.thumbnail.data.attributes.width}
/> />
) : ( ) : (
<div className="w-full aspect-[21/29.7] bg-light rounded-lg"></div> <div className="w-full aspect-[21/29.7] bg-light rounded-lg"></div>

View File

@ -31,7 +31,11 @@ export default function NavOption(props: NavOptionProps): JSX.Element {
data-tip={` data-tip={`
<div class="px-4 py-3"> <div class="px-4 py-3">
<h3 class="text-2xl">${props.title}</h3> <h3 class="text-2xl">${props.title}</h3>
${props.subtitle ? `<p class="max-w-[10rem]">${props.subtitle}</p>` : ""} ${
props.subtitle
? `<p class="max-w-[10rem]">${props.subtitle}</p>`
: ""
}
</div> </div>
`} `}
data-for={props.tooltipId} data-for={props.tooltipId}

View File

@ -29,7 +29,9 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
return ( return (
<div <div
id="mainPanel" id="mainPanel"
className={`flex flex-col justify-center content-start gap-y-2 justify-items-center text-center p-8 ${mainPanelReduced && "px-4"}`} className={`flex flex-col justify-center content-start gap-y-2 justify-items-center text-center p-8 ${
mainPanelReduced && "px-4"
}`}
> >
{mainPanelReduced && isDesktop ? ( {mainPanelReduced && isDesktop ? (
<div className="grid place-items-center gap-4"> <div className="grid place-items-center gap-4">

View File

@ -38,10 +38,10 @@ export function useMediaThin() {
} }
export function useMediaMobile() { export function useMediaMobile() {
return useMediaQuery("(max-width: 150ch)"); return useMediaQuery("(max-width: 120ch)");
} }
export function useMediaDesktop() { export function useMediaDesktop() {
return useMediaQuery("(min-width: 150ch)"); return useMediaQuery("(min-width: 120ch)");
} }

View File

@ -36,7 +36,10 @@ class MyDocument extends Document {
<meta name="twitter:title" content={siteTitle}></meta> <meta name="twitter:title" content={siteTitle}></meta>
<meta name="twitter:description" content={siteDescription}></meta> <meta name="twitter:description" content={siteDescription}></meta>
<meta name="twitter:image" content={thumbnailImage}></meta> <meta name="twitter:image" content={thumbnailImage}></meta>
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta
name="apple-mobile-web-app-status-bar-style"
content="black-translucent"
/>
<link rel="manifest" href="manifest.json" /> <link rel="manifest" href="manifest.json" />
<meta name="theme-color" content="#FFEDD8" /> <meta name="theme-color" content="#FFEDD8" />
</Head> </Head>

View File

@ -20,7 +20,13 @@ export default function AboutUs(props: AboutUsProps): JSX.Element {
/> />
</SubPanel> </SubPanel>
); );
return <AppLayout title={langui.main_about_us} langui={langui} subPanel={subPanel} />; return (
<AppLayout
title={langui.main_about_us}
langui={langui}
subPanel={subPanel}
/>
);
} }
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {

View File

@ -1,13 +0,0 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from "next";
type Data = {
name: string;
};
export default function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
res.status(200).json({ name: "John Lenon" });
}

View File

@ -20,7 +20,13 @@ export default function Archives(props: ArchivesProps): JSX.Element {
/> />
</SubPanel> </SubPanel>
); );
return <AppLayout title={langui.main_archives} langui={langui} subPanel={subPanel} />; return (
<AppLayout
title={langui.main_archives}
langui={langui}
subPanel={subPanel}
/>
);
} }
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {

View File

@ -20,7 +20,13 @@ export default function Chronicles(props: ChroniclesProps): JSX.Element {
/> />
</SubPanel> </SubPanel>
); );
return <AppLayout title={langui.main_chronicles} langui={langui} subPanel={subPanel} />; return (
<AppLayout
title={langui.main_chronicles}
langui={langui}
subPanel={subPanel}
/>
);
} }
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {

View File

@ -58,7 +58,7 @@ export default function Editor(props: EditorProps): JSX.Element {
codeBlockStyle: "fenced", codeBlockStyle: "fenced",
bulletListMarker: "-", bulletListMarker: "-",
emDelimiter: "*", emDelimiter: "*",
strongDelimiter: "**" strongDelimiter: "**",
}); });
let paste = event.clipboardData.getData("text/html"); let paste = event.clipboardData.getData("text/html");

View File

@ -17,7 +17,11 @@ export default function Gallery(props: GalleryProps): JSX.Element {
); );
return ( return (
<AppLayout title={langui.main_gallery} langui={langui} contentPanel={contentPanel} /> <AppLayout
title={langui.main_gallery}
langui={langui}
contentPanel={contentPanel}
/>
); );
} }

View File

@ -10,10 +10,8 @@ import {
} from "graphql/operations-types"; } from "graphql/operations-types";
import ContentPanel from "components/Panels/ContentPanel"; import ContentPanel from "components/Panels/ContentPanel";
import HorizontalLine from "components/HorizontalLine"; import HorizontalLine from "components/HorizontalLine";
import Markdown from "markdown-to-jsx";
import SubPanel from "components/Panels/SubPanel"; import SubPanel from "components/Panels/SubPanel";
import ReturnButton from "components/PanelComponents/ReturnButton"; import ReturnButton from "components/PanelComponents/ReturnButton";
import SceneBreak from "components/Markdown/SceneBreak";
import ThumbnailHeader from "components/Content/ThumbnailHeader"; import ThumbnailHeader from "components/Content/ThumbnailHeader";
import AppLayout from "components/AppLayout"; import AppLayout from "components/AppLayout";
import Markdawn from "components/Markdown/Markdawn"; import Markdawn from "components/Markdown/Markdawn";

View File

@ -1,11 +1,7 @@
import { GetStaticProps } from "next"; import { GetStaticProps } from "next";
import SubPanel from "components/Panels/SubPanel"; import SubPanel from "components/Panels/SubPanel";
import { import { GetWebsiteInterfaceQuery } from "graphql/operations-types";
GetWebsiteInterfaceQuery, import { getWebsiteInterface } from "graphql/operations";
} from "graphql/operations-types";
import {
getWebsiteInterface,
} from "graphql/operations";
import PanelHeader from "components/PanelComponents/PanelHeader"; import PanelHeader from "components/PanelComponents/PanelHeader";
import AppLayout from "components/AppLayout"; import AppLayout from "components/AppLayout";
import NavOption from "components/PanelComponents/NavOption"; import NavOption from "components/PanelComponents/NavOption";
@ -38,7 +34,13 @@ export default function Library(props: LibraryProps): JSX.Element {
</SubPanel> </SubPanel>
); );
return <AppLayout title={langui.main_library} langui={langui} subPanel={subPanel} />; return (
<AppLayout
title={langui.main_library}
langui={langui}
subPanel={subPanel}
/>
);
} }
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {

View File

@ -1,7 +1,6 @@
import ContentPanel, { import ContentPanel, {
ContentPanelWidthSizes, ContentPanelWidthSizes,
} from "components/Panels/ContentPanel"; } from "components/Panels/ContentPanel";
import Image from "next/image";
import { GetStaticPaths, GetStaticProps } from "next"; import { GetStaticPaths, GetStaticProps } from "next";
import { import {
getLibraryItem, getLibraryItem,
@ -16,14 +15,12 @@ import {
} from "graphql/operations-types"; } from "graphql/operations-types";
import { import {
convertMmToInch, convertMmToInch,
getAssetURL,
prettyDate, prettyDate,
prettyinlineTitle, prettyinlineTitle,
prettyItemType, prettyItemType,
prettyItemSubType, prettyItemSubType,
prettyPrice, prettyPrice,
prettySlug, prettySlug,
ImageQuality,
} from "queries/helpers"; } from "queries/helpers";
import SubPanel from "components/Panels/SubPanel"; import SubPanel from "components/Panels/SubPanel";
import ReturnButton from "components/PanelComponents/ReturnButton"; import ReturnButton from "components/PanelComponents/ReturnButton";
@ -36,6 +33,7 @@ import LibraryItemsPreview from "components/Library/LibraryItemsPreview";
import InsetBox from "components/InsetBox"; import InsetBox from "components/InsetBox";
import { setSubPanelOpen } from "redux/AppLayoutSlice"; import { setSubPanelOpen } from "redux/AppLayoutSlice";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import Img, { ImageQuality } from "components/Img";
type LibrarySlugProps = { type LibrarySlugProps = {
libraryItem: GetLibraryItemQuery; libraryItem: GetLibraryItemQuery;
@ -47,6 +45,11 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
const langui = props.langui.websiteInterfaces.data[0].attributes; const langui = props.langui.websiteInterfaces.data[0].attributes;
const dispatch = useDispatch(); const dispatch = useDispatch();
const isVariantSet =
item.metadata.length > 0 &&
item.metadata[0].__typename === "ComponentMetadataOther" &&
item.metadata[0].subtype.data.attributes.slug === "variant-set";
const subPanel = ( const subPanel = (
<SubPanel> <SubPanel>
<ReturnButton <ReturnButton
@ -83,23 +86,16 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
/> />
{item.subitems.data.length > 0 ? ( {item.subitems.data.length > 0 ? (
item.metadata.length > 0 &&
item.metadata[0].__typename === "ComponentMetadataOther" &&
item.metadata[0].subtype.data.attributes.slug === "variant-set" ? (
<NavOption <NavOption
title={langui.library_item_variants} title={
url="#variants" isVariantSet
? langui.library_item_variants
: langui.library_item_subitems
}
url={isVariantSet ? "#variants" : "#subitems"}
border={true} border={true}
onClick={() => dispatch(setSubPanelOpen(false))} onClick={() => dispatch(setSubPanelOpen(false))}
/> />
) : (
<NavOption
title={langui.library_item_subitems}
url="#subitems"
border={true}
onClick={() => dispatch(setSubPanelOpen(false))}
/>
)
) : ( ) : (
"" ""
)} )}
@ -120,18 +116,14 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
const contentPanel = ( const contentPanel = (
<ContentPanel width={ContentPanelWidthSizes.large}> <ContentPanel width={ContentPanelWidthSizes.large}>
<div className="grid place-items-center gap-12"> <div className="grid place-items-center gap-12">
<div className="drop-shadow-dark-xl w-full h-[50vh] mobile:h-[80vh] mb-16 "> <div className="drop-shadow-dark-xl w-full h-[50vh] mobile:h-[80vh] mb-16 relative">
{item.thumbnail.data ? ( {item.thumbnail.data ? (
<Image <Img
src={getAssetURL( image={item.thumbnail.data.attributes}
item.thumbnail.data.attributes.url, quality={ImageQuality.Medium}
ImageQuality.Medium
)}
alt={item.thumbnail.data.attributes.alternativeText}
width={item.thumbnail.data.attributes.width}
height={item.thumbnail.data.attributes.height}
layout="fill" layout="fill"
objectFit="contain" objectFit="contain"
priority
/> />
) : ( ) : (
<div className="w-full aspect-[21/29.7] bg-light rounded-xl"></div> <div className="w-full aspect-[21/29.7] bg-light rounded-xl"></div>
@ -182,12 +174,9 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
className="relative aspect-square hover:scale-[1.02] transition-transform cursor-pointer" className="relative aspect-square hover:scale-[1.02] transition-transform cursor-pointer"
> >
<div className="bg-light absolute inset-0 rounded-lg shadow-md"></div> <div className="bg-light absolute inset-0 rounded-lg shadow-md"></div>
<Image <Img
className="rounded-lg" className="rounded-lg"
src={getAssetURL(galleryItem.attributes.url)} image={galleryItem.attributes}
alt={galleryItem.attributes.alternativeText}
width={galleryItem.attributes.width}
height={galleryItem.attributes.height}
layout="fill" layout="fill"
objectFit="cover" objectFit="cover"
/> />
@ -356,35 +345,24 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
</InsetBox> </InsetBox>
{item.subitems.data.length > 0 ? ( {item.subitems.data.length > 0 ? (
item.metadata.length > 0 && <div
item.metadata[0].__typename === "ComponentMetadataOther" && id={isVariantSet ? "variants" : "subitems"}
item.metadata[0].subtype.data.attributes.slug === "variant-set" ? ( className="grid place-items-center gap-8 w-full"
<div id="variants" className="grid place-items-center gap-8 w-full"> >
<h2 className="text-2xl">{langui.library_item_variants}</h2> <h2 className="text-2xl">
<div className="grid gap-8 items-end mobile:grid-cols-2 grid-cols-[repeat(auto-fill,minmax(15rem,1fr))] w-full"> {isVariantSet
{item.subitems.data.map((variant) => ( ? langui.library_item_variants
<LibraryItemsPreview : langui.library_item_subitems}
key={variant.id} </h2>
item={variant.attributes}
langui={langui}
/>
))}
</div>
</div>
) : (
<div id="subitems" className="grid place-items-center gap-8 w-full">
<h2 className="text-2xl">{langui.library_item_subitems}</h2>
<div className="grid gap-8 items-end mobile:grid-cols-2 grid-cols-[repeat(auto-fill,minmax(15rem,1fr))] w-full"> <div className="grid gap-8 items-end mobile:grid-cols-2 grid-cols-[repeat(auto-fill,minmax(15rem,1fr))] w-full">
{item.subitems.data.map((subitem) => ( {item.subitems.data.map((subitem) => (
<LibraryItemsPreview <LibraryItemsPreview
key={subitem.id} key={subitem.id}
item={subitem.attributes} item={subitem.attributes}
langui={langui}
/> />
))} ))}
</div> </div>
</div> </div>
)
) : ( ) : (
"" ""
)} )}

View File

@ -43,11 +43,7 @@ export default function Library(props: LibraryProps): JSX.Element {
<ContentPanel width={ContentPanelWidthSizes.large}> <ContentPanel width={ContentPanelWidthSizes.large}>
<div className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(13rem,1fr))]"> <div className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(13rem,1fr))]">
{props.libraryItems.libraryItems.data.map((item) => ( {props.libraryItems.libraryItems.data.map((item) => (
<LibraryItemsPreview <LibraryItemsPreview key={item.id} item={item.attributes} />
key={item.id}
item={item.attributes}
langui={langui}
/>
))} ))}
</div> </div>
</ContentPanel> </ContentPanel>

View File

@ -21,7 +21,9 @@ export default function Merch(props: MerchProps): JSX.Element {
</SubPanel> </SubPanel>
); );
return <AppLayout title={langui.main_merch} langui={langui} subPanel={subPanel} />; return (
<AppLayout title={langui.main_merch} langui={langui} subPanel={subPanel} />
);
} }
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {

View File

@ -21,7 +21,9 @@ export default function News(props: NewsProps): JSX.Element {
</SubPanel> </SubPanel>
); );
return <AppLayout title={langui.main_news} langui={langui} subPanel={subPanel} />; return (
<AppLayout title={langui.main_news} langui={langui} subPanel={subPanel} />
);
} }
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {

View File

@ -72,7 +72,11 @@ export default function DataChronology(
<NavOption <NavOption
key={era.id} key={era.id}
url={"#" + era.attributes.slug} url={"#" + era.attributes.slug}
title={era.attributes.title.length > 0 ? era.attributes.title[0].title : prettySlug(era.attributes.slug)} title={
era.attributes.title.length > 0
? era.attributes.title[0].title
: prettySlug(era.attributes.slug)
}
subtitle={ subtitle={
era.attributes.starting_year + " → " + era.attributes.ending_year era.attributes.starting_year + " → " + era.attributes.ending_year
} }

View File

@ -3,20 +3,6 @@ import {
GetWebsiteInterfaceQuery, GetWebsiteInterfaceQuery,
} from "graphql/operations-types"; } from "graphql/operations-types";
export enum ImageQuality {
Small = "small",
Medium = "medium",
Large = "large"
}
export function getAssetURL(url: string, quality?: ImageQuality): string {
if (!quality) quality = ImageQuality.Small;
url = url.replace(/^\/uploads/, "/" + quality);
url = url.replace(/.jpg$/, ".webp");
url = url.replace(/.png$/, ".webp");
return process.env.NEXT_PUBLIC_URL_IMG + url;
}
export function prettyDate( export function prettyDate(
datePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"] datePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"]
): string { ): string {

View File

@ -15,8 +15,8 @@ module.exports = {
monospace: ["monospace"], monospace: ["monospace"],
}, },
screens: { screens: {
desktop: { min: "150ch" }, desktop: { min: "120ch" },
mobile: { max: "150ch" }, mobile: { max: "120ch" },
thin: { max: "50ch" }, thin: { max: "50ch" },
coarse: { raw: "(pointer: coarse)" }, coarse: { raw: "(pointer: coarse)" },
fine: { raw: "(pointer: fine)" }, fine: { raw: "(pointer: fine)" },