Skip to content

Commit 48622ae

Browse files
committed
feat(People): create routes for each member
1 parent b785200 commit 48622ae

File tree

4 files changed

+160
-89
lines changed

4 files changed

+160
-89
lines changed

gatsby-node.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,22 @@ exports.createPages = async ({ graphql, actions }) => {
8686
}
8787
}
8888
`);
89+
// Need to generate pages for each individual person as well to route to
90+
const people = await graphql(`
91+
{
92+
allMarkdownRemark(
93+
filter: { fileAbsolutePath: { regex: "/pages/people/bios/.*.md/" } }
94+
) {
95+
edges {
96+
node {
97+
frontmatter {
98+
uid
99+
}
100+
}
101+
}
102+
}
103+
}
104+
`);
89105

90106
/* List creators */
91107
const creators = [
@@ -101,6 +117,11 @@ exports.createPages = async ({ graphql, actions }) => {
101117
src: works,
102118
component: path.resolve("lib/ui/templates/ProjectItemTpl.tsx"),
103119
prefix: "projects"
120+
},
121+
{
122+
src: people,
123+
component: path.resolve("lib/ui/templates/PeopleTpl.tsx"),
124+
prefix: "people"
104125
}
105126
];
106127

lib/gatsby-types.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3177,7 +3177,7 @@ type PeopleTplQueryVariables = Exact<{
31773177
}>;
31783178

31793179

3180-
type PeopleTplQuery = { readonly markdownRemark: { readonly html: string | null, readonly frontmatter: { readonly uid: string | null, readonly title: string | null, readonly heading: string | null, readonly subheading: string | null, readonly accomplicesHeading: string | null, readonly accomplicesDescr: string | null, readonly membersHeading: string | null, readonly membersDescr: string | null, readonly overlordsHeading: string | null, readonly overlordsDescr: string | null } | null } | null, readonly defaultAvatar: { readonly edges: ReadonlyArray<{ readonly node: { readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData } | null } }> }, readonly overlords: { readonly edges: ReadonlyArray<{ readonly node: { readonly id: string, readonly html: string | null, readonly frontmatter: { readonly bluesky: string | null, readonly fname: string | null, readonly github: string | null, readonly lname: string | null, readonly mastodon: string | null, readonly quote: string | null, readonly score: number | null, readonly twitter: string | null, readonly website: string | null, readonly uid: string | null, readonly avatar: { readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData } | null } | null } | null } }> }, readonly members: { readonly edges: ReadonlyArray<{ readonly node: { readonly id: string, readonly html: string | null, readonly frontmatter: { readonly bluesky: string | null, readonly fname: string | null, readonly github: string | null, readonly lname: string | null, readonly mastodon: string | null, readonly quote: string | null, readonly score: number | null, readonly twitter: string | null, readonly website: string | null, readonly uid: string | null, readonly avatar: { readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData } | null } | null } | null } }> }, readonly accomplices: { readonly edges: ReadonlyArray<{ readonly node: { readonly id: string, readonly html: string | null, readonly frontmatter: { readonly bluesky: string | null, readonly fname: string | null, readonly github: string | null, readonly lname: string | null, readonly mastodon: string | null, readonly quote: string | null, readonly score: number | null, readonly twitter: string | null, readonly website: string | null, readonly uid: string | null, readonly avatar: { readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData } | null } | null } | null } }> } };
3180+
type PeopleTplQuery = { readonly markdownRemark: { readonly html: string | null, readonly frontmatter: { readonly uid: string | null, readonly title: string | null, readonly heading: string | null, readonly subheading: string | null, readonly accomplicesHeading: string | null, readonly accomplicesDescr: string | null, readonly membersHeading: string | null, readonly membersDescr: string | null, readonly overlordsHeading: string | null, readonly overlordsDescr: string | null } | null } | null, readonly defaultAvatar: { readonly edges: ReadonlyArray<{ readonly node: { readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData } | null } }> }, readonly overlords: { readonly edges: ReadonlyArray<{ readonly node: { readonly id: string, readonly html: string | null, readonly frontmatter: { readonly bluesky: string | null, readonly fname: string | null, readonly github: string | null, readonly lname: string | null, readonly mastodon: string | null, readonly quote: string | null, readonly score: number | null, readonly twitter: string | null, readonly website: string | null, readonly uid: string | null, readonly avatar: { readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData } | null } | null } | null } }> }, readonly members: { readonly edges: ReadonlyArray<{ readonly node: { readonly id: string, readonly html: string | null, readonly frontmatter: { readonly bluesky: string | null, readonly fname: string | null, readonly github: string | null, readonly lname: string | null, readonly mastodon: string | null, readonly quote: string | null, readonly score: number | null, readonly twitter: string | null, readonly website: string | null, readonly uid: string | null, readonly avatar: { readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData } | null } | null } | null } }> }, readonly accomplices: { readonly edges: ReadonlyArray<{ readonly node: { readonly id: string, readonly html: string | null, readonly frontmatter: { readonly bluesky: string | null, readonly fname: string | null, readonly github: string | null, readonly lname: string | null, readonly mastodon: string | null, readonly quote: string | null, readonly score: number | null, readonly twitter: string | null, readonly website: string | null, readonly uid: string | null, readonly avatar: { readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData } | null } | null } | null } }> }, readonly all: { readonly edges: ReadonlyArray<{ readonly node: { readonly id: string, readonly html: string | null, readonly frontmatter: { readonly bluesky: string | null, readonly fname: string | null, readonly github: string | null, readonly lname: string | null, readonly mastodon: string | null, readonly quote: string | null, readonly score: number | null, readonly twitter: string | null, readonly website: string | null, readonly uid: string | null, readonly avatar: { readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData } | null } | null } | null } }> } };
31813181

31823182
type PortfolioItemsByUIDQueryVariables = Exact<{
31833183
uid: Scalars['String'];

lib/ui/templates/PeopleTpl.tsx

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useState } from "react";
2-
import { graphql, type PageProps } from "gatsby";
2+
import { graphql, navigate, type PageProps } from "gatsby";
33
import styled from "styled-components";
44

55
import { Body, Header, Helmet, Layout } from "ui/partials";
@@ -48,20 +48,28 @@ const PeopleIntro = styled.div`
4848
`;
4949

5050
const PeopleTpl = (props: PageProps<Queries.PeopleTplQuery>) => {
51-
const [currentPerson, setCurrentPerson] = useState<PersonNode | null>(null);
52-
53-
function handleShowPerson(obj: PersonNode) {
54-
if (currentPerson === null) {
55-
setCurrentPerson(obj);
56-
} else {
57-
setCurrentPerson(null);
58-
}
59-
}
60-
61-
const { defaultAvatar, overlords, members, accomplices } = props.data;
51+
const { defaultAvatar, overlords, members, accomplices, all } = props.data;
6252
const { frontmatter } = props.data.markdownRemark ?? {};
6353
const genericAvatar = defaultAvatar.edges[0].node.childImageSharp;
6454

55+
// For routing to a specific person
56+
const personId = window.location.pathname
57+
.replace("/people/", "")
58+
.replace("/", "");
59+
const personObj = all.edges.find(
60+
({ node }: { node: PersonNode }) => node.frontmatter?.uid === personId
61+
);
62+
63+
const [currentPerson, setCurrentPerson] = useState<PersonNode | null>(
64+
personObj?.node ?? null
65+
);
66+
67+
// from the <Modal /> component when it closes force a navigation back to
68+
// parent page
69+
function closeModal() {
70+
navigate("/people");
71+
}
72+
6573
return (
6674
<>
6775
<Helmet {...props} title={frontmatter?.title ?? ""} />
@@ -82,7 +90,6 @@ const PeopleTpl = (props: PageProps<Queries.PeopleTplQuery>) => {
8290
data={node}
8391
defaultAvatar={genericAvatar}
8492
key={node.frontmatter?.uid}
85-
toggleModal={() => handleShowPerson(node)}
8693
/>
8794
))}
8895
</People>
@@ -98,7 +105,6 @@ const PeopleTpl = (props: PageProps<Queries.PeopleTplQuery>) => {
98105
data={node}
99106
defaultAvatar={genericAvatar}
100107
key={node.frontmatter?.uid}
101-
toggleModal={() => handleShowPerson(node)}
102108
/>
103109
))}
104110
</People>
@@ -114,15 +120,14 @@ const PeopleTpl = (props: PageProps<Queries.PeopleTplQuery>) => {
114120
data={node}
115121
defaultAvatar={genericAvatar}
116122
key={node.frontmatter?.uid}
117-
toggleModal={() => handleShowPerson(node)}
118123
/>
119124
))}
120125
</People>
121126
</PeopleSection>
122127
</Body>
123128
{currentPerson !== null ? (
124129
<PersonModal
125-
toggleModal={handleShowPerson}
130+
toggleModal={closeModal}
126131
data={currentPerson}
127132
defaultAvatar={genericAvatar!}
128133
/>
@@ -279,5 +284,39 @@ export const pageQuery = graphql`
279284
}
280285
}
281286
}
287+
all: allMarkdownRemark(
288+
filter: { fileAbsolutePath: { regex: "//pages/people/bios/*/.*/*.md/" } }
289+
sort: { frontmatter: { fname: ASC } }
290+
) {
291+
edges {
292+
node {
293+
id
294+
html
295+
frontmatter {
296+
bluesky
297+
fname
298+
github
299+
lname
300+
mastodon
301+
quote
302+
score
303+
twitter
304+
website
305+
uid
306+
avatar {
307+
childImageSharp {
308+
gatsbyImageData(
309+
width: 240
310+
height: 300
311+
placeholder: DOMINANT_COLOR
312+
transformOptions: { cropFocus: CENTER }
313+
layout: CONSTRAINED
314+
)
315+
}
316+
}
317+
}
318+
}
319+
}
320+
}
282321
}
283322
`;

lib/ui/templates/ofPeople/Person.tsx

Lines changed: 83 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React from "react";
2+
import { Link } from "gatsby";
23
import { GatsbyImage } from "gatsby-plugin-image";
34
import styled from "styled-components";
45

@@ -73,85 +74,95 @@ const PersonLinks = styled.div`
7374
interface MemberProps {
7475
data: PersonNode;
7576
defaultAvatar: any;
76-
toggleModal: VoidFunction;
7777
}
7878

7979
function Member(props: MemberProps) {
8080
const { defaultAvatar } = props;
8181
const { frontmatter } = props.data;
82-
const { avatar, bluesky, fname, github, lname, mastodon, twitter, website } =
83-
frontmatter ?? {};
82+
const {
83+
uid,
84+
avatar,
85+
bluesky,
86+
fname,
87+
github,
88+
lname,
89+
mastodon,
90+
twitter,
91+
website,
92+
} = frontmatter ?? {};
8493

8594
return (
86-
<Person onClick={props.toggleModal} role="button">
87-
<PersonPic $hasAvatar={avatar ? true : false}>
88-
<GatsbyImage
89-
image={
90-
avatar?.childImageSharp?.gatsbyImageData
91-
? avatar.childImageSharp.gatsbyImageData
92-
: defaultAvatar.gatsbyImageData
93-
}
94-
alt=""
95-
/>
96-
</PersonPic>
97-
<PersonDetails>
98-
<PersonName>
99-
<span>{fname}</span> <span>{lname}</span>
100-
</PersonName>
101-
<PersonLinks>
102-
{website ? (
103-
<Action
104-
onClick={(e: React.MouseEvent) => e.stopPropagation()}
105-
href={`https://${website}/`}
106-
rel="external noopener noreferrer"
107-
target="_blank"
108-
>
109-
<Icon name="website" size="s" />
110-
</Action>
111-
) : null}
112-
{bluesky ? (
113-
<Action
114-
onClick={(e: React.MouseEvent) => e.stopPropagation()}
115-
href={`https://bsky.app/profile/${bluesky}`}
116-
rel="external noopener noreferrer"
117-
target="_blank"
118-
>
119-
<Icon name="bluesky" size="s" />
120-
</Action>
121-
) : null}
122-
{mastodon ? (
123-
<Action
124-
onClick={(e: React.MouseEvent) => e.stopPropagation()}
125-
href={`https://${mastodon}`}
126-
rel="external noopener noreferrer"
127-
target="_blank"
128-
>
129-
<Icon name="mastodon" size="s" />
130-
</Action>
131-
) : null}
132-
{twitter ? (
133-
<Action
134-
onClick={(e: React.MouseEvent) => e.stopPropagation()}
135-
href={`https://twitter.com/${twitter}`}
136-
rel="external noopener noreferrer"
137-
target="_blank"
138-
>
139-
<Icon name="twitter" size="s" />
140-
</Action>
141-
) : null}
142-
{github ? (
143-
<Action
144-
onClick={(e: React.MouseEvent) => e.stopPropagation()}
145-
href={`https://github.com/${github}`}
146-
rel="external noopener noreferrer"
147-
target="_blank"
148-
>
149-
<Icon name="github" size="s" />
150-
</Action>
151-
) : null}
152-
</PersonLinks>
153-
</PersonDetails>
154-
</Person>
95+
<Link to={`/people/${uid}`}>
96+
<Person>
97+
<PersonPic $hasAvatar={avatar ? true : false}>
98+
<GatsbyImage
99+
image={
100+
avatar?.childImageSharp?.gatsbyImageData
101+
? avatar.childImageSharp.gatsbyImageData
102+
: defaultAvatar.gatsbyImageData
103+
}
104+
alt=""
105+
/>
106+
</PersonPic>
107+
<PersonDetails>
108+
<PersonName>
109+
<span>{fname}</span> <span>{lname}</span>
110+
</PersonName>
111+
<PersonLinks>
112+
{website ? (
113+
<Action
114+
onClick={(e: React.MouseEvent) => e.stopPropagation()}
115+
href={`https://${website}/`}
116+
rel="external noopener noreferrer"
117+
target="_blank"
118+
>
119+
<Icon name="website" size="s" />
120+
</Action>
121+
) : null}
122+
{bluesky ? (
123+
<Action
124+
onClick={(e: React.MouseEvent) => e.stopPropagation()}
125+
href={`https://bsky.app/profile/${bluesky}`}
126+
rel="external noopener noreferrer"
127+
target="_blank"
128+
>
129+
<Icon name="bluesky" size="s" />
130+
</Action>
131+
) : null}
132+
{mastodon ? (
133+
<Action
134+
onClick={(e: React.MouseEvent) => e.stopPropagation()}
135+
href={`https://${mastodon}`}
136+
rel="external noopener noreferrer"
137+
target="_blank"
138+
>
139+
<Icon name="mastodon" size="s" />
140+
</Action>
141+
) : null}
142+
{twitter ? (
143+
<Action
144+
onClick={(e: React.MouseEvent) => e.stopPropagation()}
145+
href={`https://twitter.com/${twitter}`}
146+
rel="external noopener noreferrer"
147+
target="_blank"
148+
>
149+
<Icon name="twitter" size="s" />
150+
</Action>
151+
) : null}
152+
{github ? (
153+
<Action
154+
onClick={(e: React.MouseEvent) => e.stopPropagation()}
155+
href={`https://github.com/${github}`}
156+
rel="external noopener noreferrer"
157+
target="_blank"
158+
>
159+
<Icon name="github" size="s" />
160+
</Action>
161+
) : null}
162+
</PersonLinks>
163+
</PersonDetails>
164+
</Person>
165+
</Link>
155166
);
156167
}
157168

0 commit comments

Comments
 (0)