From c89fdbb49993746ce365e0b3121e5686d5c1e3f8 Mon Sep 17 00:00:00 2001 From: DrMint Date: Mon, 21 Feb 2022 01:01:27 +0100 Subject: [PATCH] Abstracted Image component for Strapi images + fixed key react problem --- src/components/AppLayout.tsx | 22 ++-- src/components/Content/ThumbnailHeader.tsx | 13 +-- src/components/Img.tsx | 88 +++++++++++++++ .../Library/LibraryContentPreview.tsx | 12 +- .../Library/LibraryItemsPreview.tsx | 24 +--- src/components/PanelComponents/NavOption.tsx | 6 +- src/components/Panels/MainPanel.tsx | 4 +- src/hooks/useMediaQuery.ts | 4 +- src/pages/_document.tsx | 5 +- src/pages/about-us/index.tsx | 8 +- src/pages/api/hello.ts | 13 --- src/pages/archives/index.tsx | 8 +- src/pages/chronicles/index.tsx | 8 +- src/pages/editor.tsx | 2 +- src/pages/gallery/index.tsx | 6 +- src/pages/library/content/[slug]/read.tsx | 2 - src/pages/library/index.tsx | 16 +-- src/pages/library/items/[slug].tsx | 104 +++++++----------- src/pages/library/items/index.tsx | 6 +- src/pages/merch/index.tsx | 4 +- src/pages/news/index.tsx | 4 +- src/pages/wiki/chronology.tsx | 6 +- src/queries/helpers.ts | 14 --- tailwind.config.js | 4 +- 24 files changed, 218 insertions(+), 165 deletions(-) create mode 100644 src/components/Img.tsx delete mode 100644 src/pages/api/hello.ts diff --git a/src/components/AppLayout.tsx b/src/components/AppLayout.tsx index b27dcf1..3751eb9 100644 --- a/src/components/AppLayout.tsx +++ b/src/components/AppLayout.tsx @@ -205,20 +205,14 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {

Select a language

{router.locales?.sort().map((locale) => ( - <> - {locale !== "xx" ? ( - - ) : ( - "" - )} - + ))}
diff --git a/src/components/Content/ThumbnailHeader.tsx b/src/components/Content/ThumbnailHeader.tsx index 57128e1..2acdd59 100644 --- a/src/components/Content/ThumbnailHeader.tsx +++ b/src/components/Content/ThumbnailHeader.tsx @@ -2,9 +2,9 @@ import { GetContentQuery, GetWebsiteInterfaceQuery, } from "graphql/operations-types"; -import { getAssetURL, ImageQuality, prettySlug } from "queries/helpers"; -import Image from "next/image"; +import { prettySlug } from "queries/helpers"; import Button from "components/Button"; +import Img, { ImageQuality } from "components/Img"; export type ThumbnailHeaderProps = { content: { @@ -28,12 +28,11 @@ export default function ThumbnailHeader(
{content.thumbnail.data ? ( - {content.thumbnail.data.attributes.alternativeText} ) : (
diff --git a/src/components/Img.tsx b/src/components/Img.tsx new file mode 100644 index 0000000..23c9861 --- /dev/null +++ b/src/components/Img.tsx @@ -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 ( + {props.alt + ); + } else { + return ( + {props.alt + ); + } +} diff --git a/src/components/Library/LibraryContentPreview.tsx b/src/components/Library/LibraryContentPreview.tsx index 858bc9a..21ae3f6 100644 --- a/src/components/Library/LibraryContentPreview.tsx +++ b/src/components/Library/LibraryContentPreview.tsx @@ -1,8 +1,8 @@ import Link from "next/link"; import { GetContentsQuery } from "graphql/operations-types"; -import { getAssetURL, prettySlug } from "queries/helpers"; -import Image from "next/image"; +import { prettySlug } from "queries/helpers"; import Chip from "components/Chip"; +import Img, { ImageQuality } from "components/Img"; export type LibraryContentPreviewProps = { item: { @@ -23,12 +23,10 @@ export default function LibraryContentPreview(
{item.thumbnail.data ? ( - {item.thumbnail.data.attributes.alternativeText} ) : (
diff --git a/src/components/Library/LibraryItemsPreview.tsx b/src/components/Library/LibraryItemsPreview.tsx index d301cae..789b1d8 100644 --- a/src/components/Library/LibraryItemsPreview.tsx +++ b/src/components/Library/LibraryItemsPreview.tsx @@ -1,20 +1,11 @@ import Link from "next/link"; -import { - GetLibraryItemsPreviewQuery, - GetWebsiteInterfaceQuery, -} from "graphql/operations-types"; -import { - getAssetURL, - prettyDate, - prettyPrice, - prettyItemSubType, -} from "queries/helpers"; -import Image from "next/image"; +import { GetLibraryItemsPreviewQuery } from "graphql/operations-types"; +import { prettyDate, prettyPrice, prettyItemSubType } from "queries/helpers"; import Chip from "components/Chip"; +import Img, { ImageQuality } from "components/Img"; export type LibraryItemsPreviewProps = { className?: string; - langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"]; item: { slug: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["slug"]; thumbnail: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["thumbnail"]; @@ -30,7 +21,6 @@ export default function LibraryItemsPreview( props: LibraryItemsPreviewProps ): JSX.Element { const item = props.item; - const langui = props.langui; return ( @@ -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}`} > {item.thumbnail.data ? ( - {item.thumbnail.data.attributes.alternativeText} ) : (
diff --git a/src/components/PanelComponents/NavOption.tsx b/src/components/PanelComponents/NavOption.tsx index cee27a9..2721773 100644 --- a/src/components/PanelComponents/NavOption.tsx +++ b/src/components/PanelComponents/NavOption.tsx @@ -31,7 +31,11 @@ export default function NavOption(props: NavOptionProps): JSX.Element { data-tip={`

${props.title}

- ${props.subtitle ? `

${props.subtitle}

` : ""} + ${ + props.subtitle + ? `

${props.subtitle}

` + : "" + }
`} data-for={props.tooltipId} diff --git a/src/components/Panels/MainPanel.tsx b/src/components/Panels/MainPanel.tsx index 21843f9..70c8b2d 100644 --- a/src/components/Panels/MainPanel.tsx +++ b/src/components/Panels/MainPanel.tsx @@ -29,7 +29,9 @@ export default function MainPanel(props: MainPanelProps): JSX.Element { return (
{mainPanelReduced && isDesktop ? (
diff --git a/src/hooks/useMediaQuery.ts b/src/hooks/useMediaQuery.ts index af83360..e16e37b 100644 --- a/src/hooks/useMediaQuery.ts +++ b/src/hooks/useMediaQuery.ts @@ -38,10 +38,10 @@ export function useMediaThin() { } export function useMediaMobile() { - return useMediaQuery("(max-width: 150ch)"); + return useMediaQuery("(max-width: 120ch)"); } export function useMediaDesktop() { - return useMediaQuery("(min-width: 150ch)"); + return useMediaQuery("(min-width: 120ch)"); } diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx index 104c237..d1ad957 100644 --- a/src/pages/_document.tsx +++ b/src/pages/_document.tsx @@ -36,7 +36,10 @@ class MyDocument extends Document { - + diff --git a/src/pages/about-us/index.tsx b/src/pages/about-us/index.tsx index 0537f28..ac266c5 100644 --- a/src/pages/about-us/index.tsx +++ b/src/pages/about-us/index.tsx @@ -20,7 +20,13 @@ export default function AboutUs(props: AboutUsProps): JSX.Element { /> ); - return ; + return ( + + ); } export const getStaticProps: GetStaticProps = async (context) => { diff --git a/src/pages/api/hello.ts b/src/pages/api/hello.ts deleted file mode 100644 index e406545..0000000 --- a/src/pages/api/hello.ts +++ /dev/null @@ -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 -) { - res.status(200).json({ name: "John Lenon" }); -} diff --git a/src/pages/archives/index.tsx b/src/pages/archives/index.tsx index ec4b32b..67c500b 100644 --- a/src/pages/archives/index.tsx +++ b/src/pages/archives/index.tsx @@ -20,7 +20,13 @@ export default function Archives(props: ArchivesProps): JSX.Element { /> ); - return ; + return ( + + ); } export const getStaticProps: GetStaticProps = async (context) => { diff --git a/src/pages/chronicles/index.tsx b/src/pages/chronicles/index.tsx index dc9da8b..db705d4 100644 --- a/src/pages/chronicles/index.tsx +++ b/src/pages/chronicles/index.tsx @@ -20,7 +20,13 @@ export default function Chronicles(props: ChroniclesProps): JSX.Element { /> ); - return ; + return ( + + ); } export const getStaticProps: GetStaticProps = async (context) => { diff --git a/src/pages/editor.tsx b/src/pages/editor.tsx index 37930df..09d20be 100644 --- a/src/pages/editor.tsx +++ b/src/pages/editor.tsx @@ -58,7 +58,7 @@ export default function Editor(props: EditorProps): JSX.Element { codeBlockStyle: "fenced", bulletListMarker: "-", emDelimiter: "*", - strongDelimiter: "**" + strongDelimiter: "**", }); let paste = event.clipboardData.getData("text/html"); diff --git a/src/pages/gallery/index.tsx b/src/pages/gallery/index.tsx index 6298749..a37b980 100644 --- a/src/pages/gallery/index.tsx +++ b/src/pages/gallery/index.tsx @@ -17,7 +17,11 @@ export default function Gallery(props: GalleryProps): JSX.Element { ); return ( - + ); } diff --git a/src/pages/library/content/[slug]/read.tsx b/src/pages/library/content/[slug]/read.tsx index 2930771..85da72f 100644 --- a/src/pages/library/content/[slug]/read.tsx +++ b/src/pages/library/content/[slug]/read.tsx @@ -10,10 +10,8 @@ import { } from "graphql/operations-types"; import ContentPanel from "components/Panels/ContentPanel"; import HorizontalLine from "components/HorizontalLine"; -import Markdown from "markdown-to-jsx"; import SubPanel from "components/Panels/SubPanel"; import ReturnButton from "components/PanelComponents/ReturnButton"; -import SceneBreak from "components/Markdown/SceneBreak"; import ThumbnailHeader from "components/Content/ThumbnailHeader"; import AppLayout from "components/AppLayout"; import Markdawn from "components/Markdown/Markdawn"; diff --git a/src/pages/library/index.tsx b/src/pages/library/index.tsx index 3e5f4b9..67c0671 100644 --- a/src/pages/library/index.tsx +++ b/src/pages/library/index.tsx @@ -1,11 +1,7 @@ import { GetStaticProps } from "next"; import SubPanel from "components/Panels/SubPanel"; -import { - GetWebsiteInterfaceQuery, -} from "graphql/operations-types"; -import { - getWebsiteInterface, -} from "graphql/operations"; +import { GetWebsiteInterfaceQuery } from "graphql/operations-types"; +import { getWebsiteInterface } from "graphql/operations"; import PanelHeader from "components/PanelComponents/PanelHeader"; import AppLayout from "components/AppLayout"; import NavOption from "components/PanelComponents/NavOption"; @@ -38,7 +34,13 @@ export default function Library(props: LibraryProps): JSX.Element { ); - return ; + return ( + + ); } export const getStaticProps: GetStaticProps = async (context) => { diff --git a/src/pages/library/items/[slug].tsx b/src/pages/library/items/[slug].tsx index 68bf528..192310e 100644 --- a/src/pages/library/items/[slug].tsx +++ b/src/pages/library/items/[slug].tsx @@ -1,7 +1,6 @@ import ContentPanel, { ContentPanelWidthSizes, } from "components/Panels/ContentPanel"; -import Image from "next/image"; import { GetStaticPaths, GetStaticProps } from "next"; import { getLibraryItem, @@ -16,14 +15,12 @@ import { } from "graphql/operations-types"; import { convertMmToInch, - getAssetURL, prettyDate, prettyinlineTitle, prettyItemType, prettyItemSubType, prettyPrice, prettySlug, - ImageQuality, } from "queries/helpers"; import SubPanel from "components/Panels/SubPanel"; import ReturnButton from "components/PanelComponents/ReturnButton"; @@ -36,6 +33,7 @@ import LibraryItemsPreview from "components/Library/LibraryItemsPreview"; import InsetBox from "components/InsetBox"; import { setSubPanelOpen } from "redux/AppLayoutSlice"; import { useDispatch } from "react-redux"; +import Img, { ImageQuality } from "components/Img"; type LibrarySlugProps = { libraryItem: GetLibraryItemQuery; @@ -46,7 +44,12 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element { const item = props.libraryItem.libraryItems.data[0].attributes; const langui = props.langui.websiteInterfaces.data[0].attributes; 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 = ( {item.subitems.data.length > 0 ? ( - item.metadata.length > 0 && - item.metadata[0].__typename === "ComponentMetadataOther" && - item.metadata[0].subtype.data.attributes.slug === "variant-set" ? ( - dispatch(setSubPanelOpen(false))} - /> - ) : ( - dispatch(setSubPanelOpen(false))} - /> - ) + dispatch(setSubPanelOpen(false))} + /> ) : ( "" )} @@ -120,18 +116,14 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element { const contentPanel = (
-
+
{item.thumbnail.data ? ( - {item.thumbnail.data.attributes.alternativeText} ) : (
@@ -182,12 +174,9 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element { className="relative aspect-square hover:scale-[1.02] transition-transform cursor-pointer" >
- {galleryItem.attributes.alternativeText} @@ -356,35 +345,24 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element { {item.subitems.data.length > 0 ? ( - item.metadata.length > 0 && - item.metadata[0].__typename === "ComponentMetadataOther" && - item.metadata[0].subtype.data.attributes.slug === "variant-set" ? ( -
-

{langui.library_item_variants}

-
- {item.subitems.data.map((variant) => ( - - ))} -
+
+

+ {isVariantSet + ? langui.library_item_variants + : langui.library_item_subitems} +

+
+ {item.subitems.data.map((subitem) => ( + + ))}
- ) : ( -
-

{langui.library_item_subitems}

-
- {item.subitems.data.map((subitem) => ( - - ))} -
-
- ) +
) : ( "" )} diff --git a/src/pages/library/items/index.tsx b/src/pages/library/items/index.tsx index 3779369..d37a4b1 100644 --- a/src/pages/library/items/index.tsx +++ b/src/pages/library/items/index.tsx @@ -43,11 +43,7 @@ export default function Library(props: LibraryProps): JSX.Element {
{props.libraryItems.libraryItems.data.map((item) => ( - + ))}
diff --git a/src/pages/merch/index.tsx b/src/pages/merch/index.tsx index 2f033f9..f374b63 100644 --- a/src/pages/merch/index.tsx +++ b/src/pages/merch/index.tsx @@ -21,7 +21,9 @@ export default function Merch(props: MerchProps): JSX.Element { ); - return ; + return ( + + ); } export const getStaticProps: GetStaticProps = async (context) => { diff --git a/src/pages/news/index.tsx b/src/pages/news/index.tsx index 08ad1d3..bbdd4b8 100644 --- a/src/pages/news/index.tsx +++ b/src/pages/news/index.tsx @@ -21,7 +21,9 @@ export default function News(props: NewsProps): JSX.Element { ); - return ; + return ( + + ); } export const getStaticProps: GetStaticProps = async (context) => { diff --git a/src/pages/wiki/chronology.tsx b/src/pages/wiki/chronology.tsx index 78f5969..c4b7265 100644 --- a/src/pages/wiki/chronology.tsx +++ b/src/pages/wiki/chronology.tsx @@ -72,7 +72,11 @@ export default function DataChronology( 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={ era.attributes.starting_year + " → " + era.attributes.ending_year } diff --git a/src/queries/helpers.ts b/src/queries/helpers.ts index a8c7171..da527d4 100644 --- a/src/queries/helpers.ts +++ b/src/queries/helpers.ts @@ -3,20 +3,6 @@ import { GetWebsiteInterfaceQuery, } 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( datePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"] ): string { diff --git a/tailwind.config.js b/tailwind.config.js index ea65354..834825a 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -15,8 +15,8 @@ module.exports = { monospace: ["monospace"], }, screens: { - desktop: { min: "150ch" }, - mobile: { max: "150ch" }, + desktop: { min: "120ch" }, + mobile: { max: "120ch" }, thin: { max: "50ch" }, coarse: { raw: "(pointer: coarse)" }, fine: { raw: "(pointer: fine)" },