Skip to content

Commit

Permalink
Merge pull request #160 from jerboa88/151-configure-pdf-generation-fo…
Browse files Browse the repository at this point in the history
…r-resume

151 configure pdf generation for resume
  • Loading branch information
jerboa88 authored Jul 26, 2024
2 parents 8377dd6 + b212264 commit 8eef67b
Show file tree
Hide file tree
Showing 13 changed files with 108 additions and 128 deletions.
10 changes: 7 additions & 3 deletions gatsby-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import {
} from './src/common/constants';
import {
type AbsolutePathString,
type EmptyObject,
EntryPage,
type IndexPageContext,
type PageMetadata,
type ProjectPageContext,
type ResumePageContext,
} from './src/common/types';
Expand Down Expand Up @@ -133,7 +135,10 @@ function sortByCreatedAt(a: Queries.GithubRepo, b: Queries.GithubRepo) {

// Create the resume page
function createResumePage(githubRepos: Queries.GithubRepo[]) {
const path = '/resume';
const pageMetadata: PageMetadata | EmptyObject = getPageMetadata(path) || {};
const context: ResumePageContext = {
pageMetadata,
githubRepos: getSubsetOfGithubRepos(
githubRepos,
EntryPage.Resume,
Expand All @@ -142,9 +147,9 @@ function createResumePage(githubRepos: Queries.GithubRepo[]) {
};

createPage({
path: '/resume',
path: path,
component: RESUME_PAGE_TEMPLATE,
socialImageComponent: INDEX_OG_IMAGE_TEMPLATE,
socialImageComponent: OTHER_OG_IMAGE_TEMPLATE,
context: context,
});
}
Expand Down Expand Up @@ -256,7 +261,6 @@ export const createPages: GatsbyNode['createPages'] = async ({ graphql }) => {
// TODO: Re-enable this when project pages are implemented
// createProjectPages(githubRepos);
createIndexPage(githubRepos, authorBioHtml);
// TODO: Re-enable this when the resume page is implemented
createResumePage(githubRepos);
createRedirects();
};
24 changes: 20 additions & 4 deletions src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,18 +355,34 @@ export type GithubRepo = {

// export type GithubRepo = Queries.GithubReposQuery;

// Page context for the index page
// Page context to add to the index page
export type IndexPageContext = {
githubRepos: Queries.GithubRepo[];
authorBioHtml: string;
};

// Page context for project pages
// Page context to add to project pages
export type ProjectPageContext = {
githubRepo: Queries.GithubRepo;
};

// Page context for the resume page
export type ResumePageContext = {
// Page context to add to the resume page
export type ResumePageContext = PageMetadataProp & {
githubRepos: Queries.GithubRepo[];
};

// Page context for the privacy policy page
export type PrivacyPageContext = PageMetadataProp;

// Page context for the 404 page
export type NotFoundPageContext = PageMetadataProp;

// Page context for the index social image page
export type IndexSocialImagePageContext = IndexPageContext & ImageMetadataProp;

// Page context for other social image pages
export type OtherSocialImagePageContext = PageMetadataProp & ImageMetadataProp;

// Page context for project social image pages
export type ProjectSocialImagePageContext = ProjectPageContext &
ImageMetadataProp;
8 changes: 5 additions & 3 deletions src/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { panic } from '../node/logger';
import { getSiteMetadata } from './config-manager';
import type { PropsWithClassName, SentenceString } from './types';
import type { PropsWithClassName, SentenceString, UrlString } from './types';

// Constants

Expand Down Expand Up @@ -195,8 +195,10 @@ export function removeTrailingSlash(path: string) {
}

// Remove the protocol from a URL
export function removeProtocol(url: string) {
return url.replace(/.*?:\/\//g, '');
export function removeProtocol(url: UrlString | URL) {
const urlString = url instanceof URL ? url.toString() : url;

return urlString.replace(/.*?:\/\//g, '');
}

// Return the first n elements of an array
Expand Down
31 changes: 16 additions & 15 deletions src/components/layout/resume-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,16 @@ import {
} from '@fortawesome/free-solid-svg-icons';
import { getSiteMetadata } from '../../common/config-manager';
import { type CityAndStateString, TooltipPosition } from '../../common/types';
import { removeProtocol } from '../../common/utils';
import { getAbsoluteUrl, removeProtocol } from '../../common/utils';
import { GhostButton } from '../input/ghost-button';
import { GhostButtonLink } from '../links/ghost-button-link';
import { Heading } from '../text/heading';

// Constants

const SITE_METADATA = getSiteMetadata();
const CONTACT_URL = '/#contact';
const PLACEHOLDER_PHONE = '(***) ***-****';
const PLACEHOLDER_EMAIL = '*****@*****.com';
const CONTACT_PATH = '/contact';
const CONTACT_URL = removeProtocol(getAbsoluteUrl(CONTACT_PATH));
const COMMON_GHOST_BUTTON_LINK_PROPS = {
tooltipPosition: TooltipPosition.Left,
className: '!p-0',
Expand All @@ -44,19 +43,21 @@ export function ResumeHeader() {
</span>
</Heading>
<ul>
{phone && (
<li>
<GhostButtonLink
to={phone ? `tel:${phone}` : CONTACT_PATH}
text={phone}
icon={faPhoneSquare}
tooltipText="Give me a call"
{...COMMON_GHOST_BUTTON_LINK_PROPS}
/>
</li>
)}
<li>
<GhostButtonLink
to={phone ? `tel:${phone}` : CONTACT_URL}
text={phone ?? PLACEHOLDER_PHONE}
icon={faPhoneSquare}
tooltipText="Give me a call"
{...COMMON_GHOST_BUTTON_LINK_PROPS}
/>
</li>
<li>
<GhostButtonLink
to={email ? `mailto:${email}` : CONTACT_URL}
text={email ?? PLACEHOLDER_EMAIL}
to={email ? `mailto:${email}` : CONTACT_PATH}
text={email ?? CONTACT_URL}
icon={faEnvelopeSquare}
tooltipText="Send me an email"
{...COMMON_GHOST_BUTTON_LINK_PROPS}
Expand Down
22 changes: 12 additions & 10 deletions src/components/seo/page-head.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { getSiteMetadata, getTheme } from '../../common/config-manager';
import {
type PageMetadata,
type PageMetadataProp,
type PropsWithClassName,
SocialImageType,
type SocialImagesMetadataProp,
Expand All @@ -19,9 +19,11 @@ import {

// Types

interface Props extends PropsWithClassName, SocialImagesMetadataProp {
interface Props
extends PropsWithClassName,
PageMetadataProp,
SocialImagesMetadataProp {
path: string;
metadata: PageMetadata;
structuredData: object;
theme?: ThemeType;
}
Expand All @@ -35,7 +37,7 @@ const THEME = getTheme(ThemeType.Dark);
export function PageHead({
className,
path,
metadata,
pageMetadata,
structuredData,
socialImagesMetadata,
theme = ThemeType.Dark,
Expand All @@ -53,14 +55,14 @@ export function PageHead({
<>
<html lang="en-US" data-theme={theme} {...classNameProps} />
<body {...classNameProps} />
<title>{metadata.title}</title>
<title>{pageMetadata.title}</title>
<meta name="author" content={SITE_METADATA.author.name.full} />
<meta name="description" content={metadata.description} />
<meta name="description" content={pageMetadata.description} />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

{/* OpenGraph meta tags */}
<meta property="og:title" content={metadata.title} />
<meta property="og:description" content={metadata.description} />
<meta property="og:title" content={pageMetadata.title} />
<meta property="og:description" content={pageMetadata.description} />
<meta property="og:type" content="website" />
<meta property="og:url" content={pageUrl.toString()} />
<meta property="og:image" content={ogImageUrl.toString()} />
Expand All @@ -80,12 +82,12 @@ export function PageHead({

{/* Twitter meta tags */}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={metadata.title} />
<meta name="twitter:title" content={pageMetadata.title} />
<meta
name="twitter:creator"
content={SITE_METADATA.author.username.twitter}
/>
<meta name="twitter:description" content={metadata.description} />
<meta name="twitter:description" content={pageMetadata.description} />
<meta name="twitter:image" content={twitterImageUrl.toString()} />

<meta name="google" content="nositelinkssearchbox" />
Expand Down
12 changes: 5 additions & 7 deletions src/pages/404.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { HeadProps, PageProps } from 'gatsby';
import { useRef } from 'react';
import { getSiteMetadata } from '../common/config-manager';
import type {
PageMetadataProp,
NotFoundPageContext,
SocialImagesMetadataProp,
} from '../common/types';
import { getAbsoluteUrl } from '../common/utils';
Expand All @@ -18,9 +18,7 @@ import { PageHead } from '../components/seo/page-head';

// Types

interface PageContext {
pageContext: PageMetadataProp & SocialImagesMetadataProp;
}
type PageContext = NotFoundPageContext & SocialImagesMetadataProp;

// Constants

Expand All @@ -29,7 +27,7 @@ const SITE_METADATA = getSiteMetadata();
// biome-ignore lint/style/noDefaultExport: Pages must use default exports
export default function NotFoundPage({
pageContext: { pageMetadata },
}: PageContext & PageProps) {
}: PageProps<null, PageContext>) {
// Cat ASCII art from https://emojicombos.com/cat
const sadCat = [
' \uFF0F\uFF1E\u3000\u0020\u30D5',
Expand Down Expand Up @@ -77,7 +75,7 @@ export default function NotFoundPage({
export const Head = ({
location,
pageContext: { pageMetadata, socialImagesMetadata },
}: PageContext & HeadProps) => {
}: HeadProps<null, PageContext>) => {
const pageTitle = `${pageMetadata.title} | ${SITE_METADATA.shortTitle}`;
const metadata = {
title: pageTitle,
Expand All @@ -94,7 +92,7 @@ export const Head = ({
return (
<PageHead
path={location.pathname}
{...{ metadata, structuredData, socialImagesMetadata }}
{...{ pageMetadata: metadata, structuredData, socialImagesMetadata }}
/>
);
};
26 changes: 7 additions & 19 deletions src/pages/privacy-policy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { graphql } from 'gatsby';
import { useRef } from 'react';
import { getSiteMetadata } from '../common/config-manager';
import type {
PageMetadataProp,
PrivacyPageContext,
SocialImagesMetadataProp,
} from '../common/types';
import { getAbsoluteUrl } from '../common/utils';
Expand All @@ -20,19 +20,7 @@ import { Article } from '../components/text/article';

// Types

interface PageContextProp {
pageContext: PageMetadataProp & SocialImagesMetadataProp;
}

interface DataProp {
data: {
file: {
childMarkdownRemark: {
html: string;
};
};
};
}
type PageContext = PrivacyPageContext & SocialImagesMetadataProp;

// Constants

Expand All @@ -42,8 +30,8 @@ const SITE_METADATA = getSiteMetadata();
export default function PrivacyPolicyPage({
data,
pageContext: { pageMetadata },
}: PageContextProp & DataProp & PageProps) {
const articleHtml = data.file.childMarkdownRemark.html;
}: PageProps<Queries.PrivacyPolicyPageQuery, PageContext>) {
const articleHtml = data?.file?.childMarkdownRemark?.html;

return (
<PageLayout>
Expand All @@ -55,7 +43,7 @@ export default function PrivacyPolicyPage({
className="items-center"
>
<div className="flex flex-col gap-8 items-center">
<Article html={articleHtml} />
{articleHtml && <Article html={articleHtml} />}
<SolidButtonLink text="Home" to="/" isInternal />
</div>
</Section>
Expand All @@ -66,7 +54,7 @@ export default function PrivacyPolicyPage({
export const Head = ({
location,
pageContext: { pageMetadata, socialImagesMetadata },
}: PageContextProp & DataProp & HeadProps) => {
}: HeadProps<Queries.PrivacyPolicyPageQuery, PageContext>) => {
const pageTitle = `${pageMetadata.title} | ${SITE_METADATA.shortTitle}`;
const metadata = {
title: pageTitle,
Expand All @@ -91,7 +79,7 @@ export const Head = ({
return (
<PageHead
path={location.pathname}
{...{ metadata, structuredData, socialImagesMetadata }}
{...{ pageMetadata: metadata, structuredData, socialImagesMetadata }}
/>
);
};
Expand Down
12 changes: 5 additions & 7 deletions src/templates/page/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
faArrowUpRightFromSquare,
} from '@fortawesome/free-solid-svg-icons';
import { useInView } from 'framer-motion';
import type { HeadProps } from 'gatsby';
import type { HeadProps, PageProps } from 'gatsby';
import { Suspense, lazy, useCallback, useRef } from 'react';
import {
getEmploymentRoles,
Expand All @@ -34,9 +34,7 @@ import { Timeline } from '../../components/timeline';

// Types

interface Props {
pageContext: SocialImagesMetadataProp & IndexPageContext;
}
type PageContext = IndexPageContext & SocialImagesMetadataProp;

// Constants

Expand All @@ -52,7 +50,7 @@ const ContactForm = lazy(() =>
// biome-ignore lint/style/noDefaultExport: Templates must use default exports
export default function IndexPageTemplate({
pageContext: { githubRepos, authorBioHtml },
}: Props) {
}: PageProps<null, PageContext>) {
const inViewTriggerRef = useRef(null);
const expandTitle = useInView(inViewTriggerRef, USE_IN_VIEW_OPTIONS);
const sections = [
Expand Down Expand Up @@ -156,7 +154,7 @@ export default function IndexPageTemplate({
export const Head = ({
location,
pageContext: { socialImagesMetadata },
}: Props & HeadProps) => {
}: HeadProps<null, PageContext>) => {
const metadata = {
title: SITE_METADATA.title,
shortTitle: SITE_METADATA.shortTitle,
Expand All @@ -176,7 +174,7 @@ export const Head = ({
return (
<PageHead
path={location.pathname}
{...{ metadata, structuredData, socialImagesMetadata }}
{...{ pageMetadata: metadata, structuredData, socialImagesMetadata }}
/>
);
};
Loading

0 comments on commit 8eef67b

Please sign in to comment.