Added OG metadata per page

This commit is contained in:
DrMint 2022-02-24 04:50:00 +01:00
parent 506e5383da
commit 0b6366510c
22 changed files with 189 additions and 50 deletions

View File

@ -1,20 +1,27 @@
import { GetWebsiteInterfaceQuery } from "graphql/operations-types";
import {
GetWebsiteInterfaceQuery,
StrapiImage,
} from "graphql/operations-types";
import MainPanel from "./Panels/MainPanel";
import Head from "next/head";
import { useSwipeable } from "react-swipeable";
import { useRouter } from "next/router";
import Button from "components/Button";
import { prettyLanguage } from "queries/helpers";
import { getOgImage, prettyLanguage } from "queries/helpers";
import { useMediaCoarse, useMediaMobile } from "hooks/useMediaQuery";
import ReactTooltip from "react-tooltip";
import { useAppLayout } from "contexts/AppLayoutContext";
import { ImageQuality } from "./Img";
type AppLayoutProps = {
subPanel?: React.ReactNode;
subPanelIcon?: string;
contentPanel?: React.ReactNode;
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
title: string;
title?: string;
navTitle: string;
thumbnail?: StrapiImage;
description?: string;
};
export default function AppLayout(props: AppLayoutProps): JSX.Element {
@ -68,6 +75,9 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
const turnSubIntoContent = props.subPanel && !props.contentPanel;
const ogImage = getOgImage(ImageQuality.Og, props.thumbnail);
const ogTitle = props.title ? props.title : props.navTitle;
return (
<div className={appLayout.darkMode ? "set-theme-dark" : "set-theme-light"}>
<div
@ -75,9 +85,45 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
className="fixed inset-0 touch-pan-y p-0 m-0 bg-light text-black"
>
<Head>
<title>
{props.title ? `${titlePrefix} - ${props.title}` : titlePrefix}
</title>
<title>{`${titlePrefix} - ${ogTitle}`}</title>
<meta
name="twitter:title"
content={`${titlePrefix} - ${ogTitle}`}
></meta>
{props.description && (
<>
<meta name="description" content={props.description} />
<meta
name="twitter:description"
content={props.description}
></meta>
</>
)}
{ogImage && (
<>
<meta property="og:image" content={ogImage.image}></meta>
<meta
property="og:image:secure_url"
content={ogImage.image}
></meta>
<meta
property="og:image:width"
content={ogImage.width.toString()}
></meta>
<meta
property="og:image:height"
content={ogImage.height.toString()}
></meta>
<meta property="og:image:alt" content={ogImage.alt}></meta>
<meta property="og:image:type" content="image/jpeg"></meta>
<meta name="twitter:card" content="summary_large_image"></meta>
<meta name="twitter:image" content={ogImage.image}></meta>
</>
)}
</Head>
{/* Navbar */}
@ -88,7 +134,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
>
menu
</span>
<p className="text-2xl font-black font-headers">{props.title}</p>
<p className="text-2xl font-black font-headers">{props.navTitle}</p>
<span
className="material-icons mt-[.1em] cursor-pointer"
onClick={() => appLayout.setSubPanelOpen(true)}

View File

@ -1,4 +1,4 @@
import { GetLibraryItemsPreviewQuery } from "graphql/operations-types";
import { StrapiImage } from "graphql/operations-types";
import { ImageProps } from "next/image";
import Image from "next/image";
@ -9,11 +9,11 @@ export enum ImageQuality {
Og = "og",
}
export function getAssetURL(url: string, quality?: ImageQuality): string {
if (!quality) quality = ImageQuality.Small;
export function getAssetURL(url: string, quality: ImageQuality): string {
url = url.replace(/^\/uploads/, "/" + quality);
url = url.replace(/.jpg$/, ".webp");
url = url.replace(/.png$/, ".webp");
if (quality === ImageQuality.Og) url = url.replace(/.webp$/, ".jpg");
return process.env.NEXT_PUBLIC_URL_IMG + url;
}
@ -50,7 +50,7 @@ export function getImgSizesByQuality(
type ImgProps = {
className?: string;
image: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["thumbnail"]["data"]["attributes"];
image: StrapiImage;
quality?: ImageQuality;
alt?: ImageProps["alt"];
layout?: ImageProps["layout"];
@ -67,7 +67,10 @@ export default function Img(props: ImgProps): JSX.Element {
return (
<Image
className={props.className}
src={getAssetURL(props.image.url, props.quality)}
src={getAssetURL(
props.image.url,
props.quality ? props.quality : ImageQuality.Small
)}
alt={props.alt ? props.alt : props.image.alternativeText}
width={props.layout === "fill" ? undefined : imgSize.width}
height={props.layout === "fill" ? undefined : imgSize.height}

View File

@ -39,9 +39,6 @@ export default function LibraryItemsPreview(
<div className="linearbg-obi fine:drop-shadow-shade-lg fine:absolute place-items-start bottom-2 -inset-x-0.5 opacity-[var(--cover-opacity)] transition-opacity z-20 grid p-4 gap-2">
{item.metadata && item.metadata.length > 0 ? (
<div className="flex flex-row gap-1">
{item.metadata[0].__typename === "ComponentMetadataOther"
? console.log(item.slug)
: ""}
<Chip>{prettyItemSubType(item.metadata[0])}</Chip>
</div>
) : (

View File

@ -62,6 +62,16 @@ export enum Enum_Componentsetstextset_Status {
Done = "Done",
}
export type StrapiImage = {
__typename: "UploadFile";
name: string;
alternativeText: string;
caption: string;
width: number;
height: number;
url: string;
};
// __________________________________________________________________
export type GetWebsiteInterfaceQueryVariables = Exact<{

View File

@ -19,7 +19,7 @@ export default function FourOhFour(props: FourOhFourProps): JSX.Element {
</Link>
</ContentPanel>
);
return <AppLayout title="404" langui={langui} contentPanel={contentPanel} />;
return <AppLayout navTitle="404" langui={langui} contentPanel={contentPanel} />;
}
export const getStaticProps: GetStaticProps = async (context) => {

View File

@ -24,18 +24,46 @@ class MyDocument extends Document {
return (
<Html>
<Head>
<meta name="description" content={siteDescription} />
<link rel="icon" href={siteFavicon} />
<meta property="og:image" content={thumbnailImage}></meta>
<meta property="og:image:secure_url" content={thumbnailImage}></meta>
<meta property="og:image:width" content="1200"></meta>
<meta property="og:image:height" content="630"></meta>
<meta property="og:image:alt" content="Accord's Library"></meta>
<meta property="og:image:type" content="image/jpeg"></meta>
<meta name="twitter:card" content="summary_large_image"></meta>
<meta name="twitter:title" content={siteTitle}></meta>
<meta name="twitter:description" content={siteDescription}></meta>
<meta name="twitter:image" content={thumbnailImage}></meta>
<meta
name="description"
content={siteDescription}
key="description"
/>
<link rel="icon" href={siteFavicon} key="icon" />
<meta property="og:image" content={thumbnailImage} key="ogImage" />
<meta
property="og:image:secure_url"
content={thumbnailImage}
key="ogImageSecure"
/>
<meta property="og:image:width" content="1200" key="ogImageWidth" />
<meta property="og:image:height" content="630" key="ogImageHeight" />
<meta
property="og:image:alt"
content="Accord's Library"
key="ogImageAlt"
/>
<meta
property="og:image:type"
content="image/jpeg"
key="ogImageType"
/>
<meta
name="twitter:card"
content="summary_large_image"
key="twitterCard"
/>
<meta name="twitter:title" content={siteTitle} key="twitterTitle" />
<meta
name="twitter:description"
content={siteDescription}
key="twitterDescription"
/>
<meta
name="twitter:image"
content={thumbnailImage}
key="twitterImage"
/>
<meta
name="apple-mobile-web-app-status-bar-style"
content="black-translucent"

View File

@ -22,7 +22,7 @@ export default function AboutUs(props: AboutUsProps): JSX.Element {
);
return (
<AppLayout
title={langui.main_about_us}
navTitle={langui.main_about_us}
langui={langui}
subPanel={subPanel}
/>

View File

@ -22,7 +22,7 @@ export default function Archives(props: ArchivesProps): JSX.Element {
);
return (
<AppLayout
title={langui.main_archives}
navTitle={langui.main_archives}
langui={langui}
subPanel={subPanel}
/>

View File

@ -22,7 +22,7 @@ export default function Chronicles(props: ChroniclesProps): JSX.Element {
);
return (
<AppLayout
title={langui.main_chronicles}
navTitle={langui.main_chronicles}
langui={langui}
subPanel={subPanel}
/>

View File

@ -15,6 +15,7 @@ import ThumbnailHeader from "components/Content/ThumbnailHeader";
import AppLayout from "components/AppLayout";
import SubPanel from "components/Panels/SubPanel";
import ReturnButton from "components/PanelComponents/ReturnButton";
import { prettyinlineTitle, prettySlug } from "queries/helpers";
type ContentIndexProps = {
content: GetContentQuery;
@ -26,11 +27,7 @@ export default function ContentIndex(props: ContentIndexProps): JSX.Element {
const langui = props.langui.websiteInterfaces.data[0].attributes;
const subPanel = (
<SubPanel>
<ReturnButton
href="/contents"
title={"Contents"}
langui={langui}
/>
<ReturnButton href="/contents" title={"Contents"} langui={langui} />
<HorizontalLine />
</SubPanel>
);
@ -70,7 +67,13 @@ export default function ContentIndex(props: ContentIndexProps): JSX.Element {
return (
<AppLayout
title={langui.library_content}
navTitle="Contents"
title={
content.titles.length > 0
? prettyinlineTitle(content.titles[0].pre_title, content.titles[0].title, content.titles[0].subtitle)
: prettySlug(content.slug)
}
thumbnail={content.thumbnail.data.attributes}
langui={langui}
contentPanel={contentPanel}
subPanel={subPanel}

View File

@ -15,6 +15,7 @@ import ReturnButton from "components/PanelComponents/ReturnButton";
import ThumbnailHeader from "components/Content/ThumbnailHeader";
import AppLayout from "components/AppLayout";
import Markdawn from "components/Markdown/Markdawn";
import { prettyinlineTitle, prettySlug } from "queries/helpers";
type ContentReadProps = {
content: GetContentTextQuery;
@ -51,7 +52,13 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
return (
<AppLayout
title={langui.library_content}
navTitle="Contents"
title={
content.titles.length > 0
? prettyinlineTitle(content.titles[0].pre_title, content.titles[0].title, content.titles[0].subtitle)
: prettySlug(content.slug)
}
thumbnail={content.thumbnail.data.attributes}
langui={langui}
contentPanel={contentPanel}
subPanel={subPanel}

View File

@ -10,8 +10,6 @@ import {
import { getContents, getWebsiteInterface } from "graphql/operations";
import PanelHeader from "components/PanelComponents/PanelHeader";
import AppLayout from "components/AppLayout";
import ReturnButton from "components/PanelComponents/ReturnButton";
import HorizontalLine from "components/HorizontalLine";
import LibraryContentPreview from "components/Library/LibraryContentPreview";
import { prettyinlineTitle } from "queries/helpers";
@ -63,7 +61,7 @@ export default function Library(props: LibraryProps): JSX.Element {
);
return (
<AppLayout
title={langui.library_content}
navTitle="Contents"
langui={langui}
subPanel={subPanel}
contentPanel={contentPanel}

View File

@ -85,7 +85,7 @@ export default function Editor(props: EditorProps): JSX.Element {
);
return (
<AppLayout
title="Markdawn Editor"
navTitle="Markdawn Editor"
langui={langui}
contentPanel={contentPanel}
/>

View File

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

View File

@ -143,7 +143,7 @@ export default function Home(props: HomeProps): JSX.Element {
return (
<>
<AppLayout
title={"Accords Library"}
navTitle={"Accords Library"}
langui={langui}
contentPanel={contentPanel}
/>

View File

@ -481,10 +481,17 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
return (
<AppLayout
title={langui.library_items}
navTitle={langui.main_library}
title={prettyinlineTitle("", item.title, item.subtitle)}
langui={langui}
contentPanel={contentPanel}
subPanel={subPanel}
thumbnail={item.thumbnail.data.attributes}
description={
item.descriptions.length > 0
? item.descriptions[0].description
: undefined
}
/>
);
}

View File

@ -42,7 +42,7 @@ export default function Library(props: LibraryProps): JSX.Element {
);
return (
<AppLayout
title={langui.library_items}
navTitle={langui.main_library}
langui={langui}
subPanel={subPanel}
contentPanel={contentPanel}

View File

@ -22,7 +22,11 @@ export default function Merch(props: MerchProps): JSX.Element {
);
return (
<AppLayout title={langui.main_merch} langui={langui} subPanel={subPanel} />
<AppLayout
navTitle={langui.main_merch}
langui={langui}
subPanel={subPanel}
/>
);
}

View File

@ -22,7 +22,11 @@ export default function News(props: NewsProps): JSX.Element {
);
return (
<AppLayout title={langui.main_news} langui={langui} subPanel={subPanel} />
<AppLayout
navTitle={langui.main_news}
langui={langui}
subPanel={subPanel}
/>
);
}

View File

@ -119,7 +119,7 @@ export default function DataChronology(
return (
<AppLayout
title="Chronology"
navTitle="Chronology"
langui={langui}
contentPanel={contentPanel}
subPanel={subPanel}

View File

@ -25,7 +25,7 @@ export default function Hubs(props: WikiProps): JSX.Element {
return (
<AppLayout
title={langui.main_wiki}
navTitle={langui.main_wiki}
langui={langui}
contentPanel={contentPanel}
subPanel={subPanel}

View File

@ -1,6 +1,12 @@
import {
getAssetURL,
getImgSizesByQuality,
ImageQuality,
} from "components/Img";
import {
GetLibraryItemsPreviewQuery,
GetWebsiteInterfaceQuery,
StrapiImage,
} from "graphql/operations-types";
export function prettyDate(
@ -119,3 +125,29 @@ export function capitalizeString(string: string): string {
export function convertMmToInch(mm: number): string {
return (mm * 0.03937008).toPrecision(3);
}
type OgImage = {
image: string;
width: number;
height: number;
alt: string;
};
export function getOgImage(
quality: ImageQuality,
image?: StrapiImage
): OgImage | undefined {
if (image) {
const imgSize = getImgSizesByQuality(
image.width,
image.height,
quality ? quality : ImageQuality.Small
);
return {
image: getAssetURL(image.url, quality),
width: imgSize.width,
height: imgSize.height,
alt: image.alternativeText,
};
}
}