Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions gatsby-node.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const _ = require(`lodash`);
const path = require(`path`);
const { slash } = require(`gatsby-core-utils`);
const { createFilePath } = require(`gatsby-source-filesystem`);
Expand All @@ -16,7 +15,10 @@ exports.createPages = ({ graphql, actions }) => {
// from the fetched data that you can run queries against.
return graphql(`
{
allAsciidoc(limit: 1000) {
allAsciidoc(
limit: 1000
sort: { fields: { publicationDate: DESC } }
) {
edges {
node {
id
Expand Down Expand Up @@ -55,7 +57,15 @@ exports.createPages = ({ graphql, actions }) => {
const articleTemplate = path.resolve(
`./src/templates/contributor-details.jsx`
);
_.each(result.data.allAsciidoc.edges, (edge) => {
const contributors = result.data.allAsciidoc.edges;

contributors.forEach((edge, index) => {
const previous = index === 0 ? null : contributors[index - 1].node;

const next =
index === contributors.length - 1
? null
: contributors[index + 1].node;
// Gatsby uses Redux to manage its internal state.
// Plugins and sites can use functions like "createPage"
// to interact with Gatsby.
Expand All @@ -68,6 +78,21 @@ exports.createPages = ({ graphql, actions }) => {
component: slash(articleTemplate),
context: {
id: edge.node.id,
previous: previous
? {
slug: previous.fields.slug,
title: previous.document.title,
image: previous.pageAttributes.image,
}
: null,

next: next
? {
slug: next.fields.slug,
title: next.document.title,
image: next.pageAttributes.image,
}
: null,
},
});
});
Expand Down
146 changes: 145 additions & 1 deletion src/templates/contributor-details.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,16 @@ function ContributorDetails(props) {
const isDesktop = useMediaQuery(theme.breakpoints.up('lg'));
const isTablet = useMediaQuery(theme.breakpoints.between('lg', 'sm'));
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const darkmode = useMediaQuery('(prefers-color-scheme: dark)');
const title =
props.data.asciidoc.pageAttributes.name +
' - Jenkins Contributor Spotlight';
const { previous, next } = props.pageContext;

// State for sanitized HTML
const [sanitizedHTML, setSanitizedHTML] = useState(props.data.asciidoc.html);
const [sanitizedHTML, setSanitizedHTML] = useState(
props.data.asciidoc.html
);

// Sanitize HTML on client side only
useEffect(() => {
Expand Down Expand Up @@ -261,6 +265,146 @@ function ContributorDetails(props) {
__html: sanitizedHTML,
}}
/>
<Box
sx={{
mt: 10,
pt: 4,
borderTop: '1px solid #e0e0e0',
display: 'flex',
flexDirection: {
xs: 'column',
sm: 'row',
},
justifyContent: 'space-between',
alignItems: {
xs: 'stretch',
sm: 'center',
},
gap: 2,
}}
>
{previous ? (
<Link
to={previous.slug}
style={{
textDecoration: 'none',
color: 'inherit',
}}
>
<Stack
direction='row'
alignItems='center'
spacing={1}
>
<ArrowBackIcon fontSize='small' />

<img
src={`../../../${previous.image}`}
alt={previous.title}
width={44}
height={44}
style={{
borderRadius: '50%',
objectFit: 'cover',
}}
/>

<Box>
<Typography
variant='caption'
sx={{
color: darkmode
? '#bbbbbb'
: 'text.secondary',
}}
>
Previous Profile
</Typography>
<Typography
fontWeight={600}
sx={{
maxWidth: 180,
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
}}
>
{previous.title}
</Typography>
</Box>
</Stack>
</Link>
) : (
<div />
)}

{next ? (
<Box
sx={{
alignSelf: {
xs: 'flex-end',
sm: 'auto',
},
}}
>
<Link
to={next.slug}
style={{
textDecoration: 'none',
color: 'inherit',
}}
>
<Stack
direction='row'
alignItems='center'
spacing={1}
>
<Box textAlign='right'>
<Typography
variant='caption'
sx={{
color: darkmode
? '#bbbbbb'
: 'text.secondary',
}}
>
Next Profile
</Typography>
<Typography
fontWeight={600}
sx={{
maxWidth: 180,
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
}}
>
{next.title}
</Typography>
</Box>

<img
src={`../../../${next.image}`}
alt={next.title}
width={44}
height={44}
style={{
borderRadius: '50%',
objectFit: 'cover',
}}
/>

<ArrowBackIcon
fontSize='small'
sx={{ transform: 'rotate(180deg)' }}
/>
</Stack>
</Link>
</Box>
) : (
<div />
)}
</Box>
</Box>
</Box>
</>
Expand Down