Added OG metadata per page
This commit is contained in:
parent
506e5383da
commit
0b6366510c
@ -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)}
|
||||
|
@ -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}
|
||||
|
@ -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>
|
||||
) : (
|
||||
|
@ -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<{
|
||||
|
@ -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) => {
|
||||
|
@ -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"
|
||||
|
@ -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}
|
||||
/>
|
||||
|
@ -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}
|
||||
/>
|
||||
|
@ -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}
|
||||
/>
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -85,7 +85,7 @@ export default function Editor(props: EditorProps): JSX.Element {
|
||||
);
|
||||
return (
|
||||
<AppLayout
|
||||
title="Markdawn Editor"
|
||||
navTitle="Markdawn Editor"
|
||||
langui={langui}
|
||||
contentPanel={contentPanel}
|
||||
/>
|
||||
|
@ -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}
|
||||
/>
|
||||
|
@ -143,7 +143,7 @@ export default function Home(props: HomeProps): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
<AppLayout
|
||||
title={"Accord’s Library"}
|
||||
navTitle={"Accord’s Library"}
|
||||
langui={langui}
|
||||
contentPanel={contentPanel}
|
||||
/>
|
||||
|
@ -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
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ export default function DataChronology(
|
||||
|
||||
return (
|
||||
<AppLayout
|
||||
title="Chronology"
|
||||
navTitle="Chronology"
|
||||
langui={langui}
|
||||
contentPanel={contentPanel}
|
||||
subPanel={subPanel}
|
||||
|
@ -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}
|
||||
|
@ -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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user