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
	 DrMint
						DrMint