Skip to content

Commit

Permalink
Update and improve components and stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
pookmish committed Jan 4, 2024
1 parent d43c60b commit e876149
Show file tree
Hide file tree
Showing 95 changed files with 6,911 additions and 1,482 deletions.
27 changes: 16 additions & 11 deletions app/@modal/(.)gallery-image/[uuid]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,36 @@
import InterceptionModal from "@components/elements/interception-modal";
import {randomUUID} from "crypto";
import Image from "next/image";
import {getResource} from "@lib/drupal/get-resource";
import {DrupalGalleryImageMediaType} from "@lib/types";
import {buildUrl} from "@lib/drupal/utils";
import {graphqlClient} from "@lib/gql/fetcher";
import {MediaStanfordGalleryImage} from "@lib/gql/__generated__/drupal";

const Page = async ({params: {uuid}}: { params: { uuid: string } }) => {
const captionId = randomUUID();
const media = await getResource<DrupalGalleryImageMediaType>('media--stanford_gallery_images', uuid);
if (!media) return null;
let media: MediaStanfordGalleryImage | undefined;
try {
const query = await graphqlClient().Media({uuid});
if (query.media?.__typename === 'MediaStanfordGalleryImage') media = query.media as MediaStanfordGalleryImage;
} catch (e) {
}
if (!media || !media.suGalleryImage?.url) return;

return (
<InterceptionModal aria-labelledby={captionId}>
<figure className="h-full w-fit mx-auto table">
<picture>
<Image
src={buildUrl(media.su_gallery_image.uri.url).toString()}
alt={media.su_gallery_image.resourceIdObjMeta?.alt || ''}
height={media.su_gallery_image.resourceIdObjMeta?.height}
width={media.su_gallery_image.resourceIdObjMeta?.width}
src={media.suGalleryImage.url}
alt={media.suGalleryImage.alt || ''}
height={media.suGalleryImage.height}
width={media.suGalleryImage.width}
className="max-w-full h-auto m-0 p-0"
/>
</picture>
{media.su_gallery_caption &&
{media.suGalleryCaption &&
<figcaption
id={captionId}
className="bg-white text-right p-5 m-0 table-caption caption-bottom">
{media.su_gallery_caption}
{media.suGalleryCaption}
</figcaption>
}
</figure>
Expand Down
94 changes: 47 additions & 47 deletions app/[...slug]/metadata.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,45 @@
import {decode} from 'html-entities';
import {
BasicPageNodeType,
EventNodeType,
NewsNodeType,
PersonNodeType,
PolicyNodeType,
StanfordNode,
StanfordParagraph, WysiwygParagraphType
} from "@lib/types";
import {buildUrl} from "@lib/drupal/utils";

export const getNodeMetadata = (node: StanfordNode) => {
Image,
Maybe,
NodeStanfordEvent,
NodeStanfordNews,
NodeStanfordPage,
NodeStanfordPerson, NodeStanfordPolicy,
NodeUnion, ParagraphStanfordWysiwyg, ParagraphUnion
} from "@lib/gql/__generated__/drupal";
import {getMediaFromEntityField} from "@lib/drupal/get-media-from-entity";

export const getNodeMetadata = (node: NodeUnion) => {
const defaultData = {
title: node.title,
}
switch (node.type) {
case 'node--stanford_page':
switch (node.__typename) {
case 'NodeStanfordPage':
return {
...getBasicPageMetaData(node),
...defaultData
}

case 'node--stanford_news':
case 'NodeStanfordNews':
return {
...getNewsMetaData(node),
...defaultData
}

case 'node--stanford_event':
case 'NodeStanfordEvent':
return {
...getEventMetaData(node),
...defaultData
}

case 'node--stanford_person':
case 'NodeStanfordPerson':
return {
...getPersonMetaData(node),
...defaultData
}

case 'node--stanford_policy':
case 'NodeStanfordPolicy':
return {
...getPolicyMetaData(node),
...defaultData
Expand All @@ -49,13 +49,13 @@ export const getNodeMetadata = (node: StanfordNode) => {
return defaultData;
}

const getBasicPageMetaData = (node: BasicPageNodeType) => {
const pageImage = node.su_page_image?.field_media_image;
const bannerImage =node.su_page_banner?.su_banner_image?.field_media_image
const getBasicPageMetaData = (node: NodeStanfordPage) => {
const pageImage = getMediaFromEntityField<Image>(node.suPageImage);
const bannerImage = getMediaFromEntityField<Image>(node.suPageBanner?.__typename === 'ParagraphStanfordBanner' ? node.suPageBanner?.suBannerImage : undefined);

const imageUrl = pageImage?.image_style_uri.card_956x478 || bannerImage?.image_style_uri.card_956x478
const imageAlt = pageImage?.resourceIdObjMeta?.alt || bannerImage?.resourceIdObjMeta?.alt || '';
const description = node.su_page_description || getFirstText(node.su_page_components);
const imageUrl = pageImage?.url || bannerImage?.url
const imageAlt = pageImage?.alt || bannerImage?.alt || '';
const description = node.suPageDescription || getFirstText(node.suPageComponents);

return {
description: description,
Expand All @@ -68,18 +68,18 @@ const getBasicPageMetaData = (node: BasicPageNodeType) => {
}
}

const getNewsMetaData = (node: NewsNodeType) => {
const pageImage = node.su_news_featured_media?.field_media_image;
const bannerImage = node.su_news_banner?.field_media_image;
const getNewsMetaData = (node: NodeStanfordNews) => {
const pageImage = getMediaFromEntityField<Image>(node.suNewsFeaturedMedia);
const bannerImage = getMediaFromEntityField<Image>(node.suNewsBanner);

const imageUrl = pageImage?.image_style_uri.card_956x478 || bannerImage?.image_style_uri.card_956x478
const imageAlt = pageImage?.resourceIdObjMeta?.alt || bannerImage?.resourceIdObjMeta?.alt || '';
const imageUrl = pageImage?.url || bannerImage?.url
const imageAlt = pageImage?.alt || bannerImage?.alt || '';

const description = node.su_news_dek || getFirstText(node.su_news_components);
const description = node.suNewsDek || getFirstText(node.suNewsComponents);

let publishTime;
if (node.su_news_publishing_date) {
publishTime = new Date(node.su_news_publishing_date).toISOString()
if (node.suNewsPublishingDate) {
publishTime = new Date(node.suNewsPublishingDate.time).toISOString()
}

return {
Expand All @@ -89,33 +89,33 @@ const getNewsMetaData = (node: NewsNodeType) => {
title: node.title,
description: description,
publishedTime: publishTime ?? null,
tag: node.su_news_topics?.map(term => term.name) ?? [],
tag: node.suNewsTopics?.map(term => term.name) ?? [],
images: getOpenGraphImage(imageUrl, imageAlt)
}
}
}

const getPersonMetaData = (node: PersonNodeType) => {
const pageImage = node.su_person_photo?.field_media_image;
const imageUrl = pageImage?.image_style_uri.card_956x478;
const imageAlt = pageImage?.resourceIdObjMeta?.alt || '';
const description = node.su_person_full_title ?? getCleanDescription(node.body);
const getPersonMetaData = (node: NodeStanfordPerson) => {
const pageImage = getMediaFromEntityField<Image>(node.suPersonPhoto);
const imageUrl = pageImage?.url;
const imageAlt = pageImage?.alt || '';
const description = node.suPersonFullTitle ?? getCleanDescription(node.body?.processed);

return {
description: description,
openGraph: {
type: 'profile',
title: node.title,
description: description,
firstName: node.su_person_first_name,
lastName: node.su_person_last_name,
firstName: node.suPersonFirstName,
lastName: node.suPersonLastName,
images: getOpenGraphImage(imageUrl, imageAlt)
}
}
}

const getEventMetaData = (node: EventNodeType) => {
const description = node.su_event_subheadline ?? getCleanDescription(node.body);
const getEventMetaData = (node: NodeStanfordEvent) => {
const description = node.suEventSubheadline ?? getCleanDescription(node.body?.processed);

return {
description: description,
Expand All @@ -127,8 +127,8 @@ const getEventMetaData = (node: EventNodeType) => {
}
}

const getPolicyMetaData = (node: PolicyNodeType) => {
const description = getCleanDescription(node.body?.summary || node.body?.processed);
const getPolicyMetaData = (node: NodeStanfordPolicy) => {
const description = getCleanDescription(node.body?.processed);

return {
description: description,
Expand All @@ -140,10 +140,10 @@ const getPolicyMetaData = (node: PolicyNodeType) => {
}
}

const getFirstText = (components?: StanfordParagraph[]) => {
const firstWysiwyg = components?.find(component => component.type === 'paragraph--stanford_wysiwyg') as WysiwygParagraphType;
const getFirstText = (components?: Maybe<ParagraphUnion[]>) => {
const firstWysiwyg = components?.find(component => component.__typename === 'ParagraphStanfordWysiwyg') as ParagraphStanfordWysiwyg;
if (firstWysiwyg) {
return getCleanDescription(firstWysiwyg.su_wysiwyg_text);
return getCleanDescription(firstWysiwyg.suWysiwygText?.processed);
}
}

Expand All @@ -159,7 +159,7 @@ const getOpenGraphImage = (imageUrl?: string, imageAlt?: string) => {
if (imageUrl) {
return [
{
url: buildUrl(imageUrl).toString(),
url: imageUrl,
width: 956,
height: 478,
alt: imageAlt,
Expand Down
47 changes: 10 additions & 37 deletions app/[...slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,62 +5,35 @@ import {DrupalJsonApiParams} from "drupal-jsonapi-params";
import {getPathsFromContext} from "@lib/drupal/get-paths";
import {getNodeMetadata} from "./metadata";
import {getPathFromContext, isDraftMode} from "@lib/drupal/utils";
import {PageProps, Params, StanfordNode} from "@lib/types";
import {getResourceByPath, getResourceFromContext} from "@lib/drupal/get-resource";
import {getAccessToken} from "@lib/drupal/get-access-token";
import {translatePathFromContext} from "@lib/drupal/translate-path";
import RedirectError from "@lib/redirect-error";
import {PageProps} from "@lib/types";
import {getEntityFromPath} from "@lib/gql/fetcher";
import {NodeUnion} from "@lib/gql/__generated__/drupal";

// https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config
export const revalidate = false;

const Page = async ({params}: PageProps) => {
let node = null;
try {
node = await getPageData(params);
} catch (e) {
if (e instanceof RedirectError) redirect(e.message);
}

if (!node) notFound();
const path = getPathFromContext({params})
const routeInfo = await getEntityFromPath<NodeUnion>(path)
if (routeInfo?.redirect?.url) redirect(routeInfo.redirect.url)
if (!routeInfo?.entity) notFound();

return (
<NodePage node={node}/>
<NodePage node={routeInfo.entity}/>
)
}

export const generateMetadata = async ({params}: PageProps): Promise<Metadata> => {
const path = getPathFromContext({params})

try {
const node = await getResourceByPath<StanfordNode>(path)
if (node) return getNodeMetadata(node);
const routeInfo = await getEntityFromPath<NodeUnion>(path, isDraftMode())
if (routeInfo?.entity) return getNodeMetadata(routeInfo.entity);
} catch (e) {
}
return {}
}

const getPageData = async(params: Params): Promise<StanfordNode | undefined> => {
const draftMode = isDraftMode()
const accessToken = draftMode ? await getAccessToken(true) : null;

const path = await translatePathFromContext({params}, accessToken ? {accessToken} : {});

// Check for redirect.
if (path?.redirect && path?.redirect?.[0].to) {
const currentPath = '/' + (typeof params?.slug === 'object' ? params.slug.join('/') : params?.slug);

const [destination] = path.redirect;

if (destination.to != currentPath) throw new RedirectError(destination.to);
}

if (!path || !path.jsonapi) throw new Error('Unable to translate path')
if (params?.slug?.[0] === 'node' && path?.entity?.path) throw new RedirectError(path.entity.path);

return getResourceFromContext<StanfordNode>(path.jsonapi.resourceName, {params}, {draftMode})
}

export const generateStaticParams = async () => {
const params = new DrupalJsonApiParams();
// Add a simple include so that it doesn't fetch all the data right now. The full node data comes later, we only need
Expand Down
9 changes: 5 additions & 4 deletions app/api/draft/route.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// route handler with secret and slug
import {draftMode} from 'next/headers'
import {redirect} from 'next/navigation'
import {getResourceByPath} from "@lib/drupal/get-resource";
import {StanfordNode} from "@lib/types";
import {NodeUnion} from "@lib/gql/__generated__/drupal";
import {graphqlClient} from "@lib/gql/fetcher";

export async function GET(request: Request) {
// Parse query string parameters
Expand All @@ -20,7 +20,8 @@ export async function GET(request: Request) {

// Fetch the headless CMS to check if the provided `slug` exists
// getPostBySlug would implement the required fetching logic to the headless CMS
const node = await getResourceByPath<StanfordNode>(slug);
const query = await graphqlClient().Route({path: slug});
const node = query.route?.__typename === 'RouteInternal' && query.route.entity as NodeUnion

// If the slug doesn't exist prevent draft mode from being enabled
if (!node) {
Expand All @@ -29,5 +30,5 @@ export async function GET(request: Request) {

// Redirect to the path from the fetched post
// We don't redirect to searchParams.slug as that might lead to open redirect vulnerabilities
redirect(node.path.alias)
redirect(node.path)
}
26 changes: 15 additions & 11 deletions app/gallery-image/[uuid]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import {notFound} from "next/navigation";
import {H1} from "@components/elements/headers";
import Image from "next/image";
import {getResource} from "@lib/drupal/get-resource";
import {DrupalGalleryImageMediaType} from "@lib/types";
import {buildUrl} from "@lib/drupal/utils";
import {MediaStanfordGalleryImage} from "@lib/gql/__generated__/drupal";
import {graphqlClient} from "@lib/gql/fetcher";

export const metadata = {
title: 'Gallery Image',
Expand All @@ -13,27 +12,32 @@ export const metadata = {
}

const Page = async ({params: {uuid}}: { params: { uuid: string } }) => {
const media = await getResource<DrupalGalleryImageMediaType>('media--stanford_gallery_images', uuid);
if (!media || !media.su_gallery_image.uri.url) notFound();
let media: MediaStanfordGalleryImage | undefined;
try {
const query = await graphqlClient().Media({uuid});
if (query.media?.__typename === 'MediaStanfordGalleryImage') media = query.media as MediaStanfordGalleryImage;
} catch (e) {
}
if (!media || !media.suGalleryImage?.url) notFound();

return (
<div className="centered mt-32">
<H1>{media.su_gallery_image.resourceIdObjMeta?.alt || "Media"}</H1>
<H1>{media.suGalleryImage?.alt || "Media"}</H1>

<figure className="h-full w-fit mx-auto table">
<picture>
<Image
src={buildUrl(media.su_gallery_image.uri.url).toString()}
src={media.suGalleryImage.url}
alt=""
width={media.su_gallery_image.resourceIdObjMeta?.width}
height={media.su_gallery_image.resourceIdObjMeta?.height}
width={media.suGalleryImage.width}
height={media.suGalleryImage.height}
className="max-w-full h-auto m-0 p-0"
/>
</picture>
{media.su_gallery_caption &&
{media.suGalleryCaption &&
<figcaption
className="bg-white text-right p-5 m-0 table-caption caption-bottom">
{media.su_gallery_caption}
{media.suGalleryCaption}
</figcaption>
}
</figure>
Expand Down
Loading

0 comments on commit e876149

Please sign in to comment.