Skip to content

Commit

Permalink
Merge pull request #22 from luhmann/GH-21-fix-flash-of-404
Browse files Browse the repository at this point in the history
#21: create pages for each image
  • Loading branch information
luhmann committed Feb 13, 2019
2 parents d004813 + 1a90dbb commit 5c8172a
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 70 deletions.
134 changes: 102 additions & 32 deletions gatsby-node.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
const path = require('path');

const { pathOr, prop, ifElse, identity, has } = require('rambda');
const { pathOr, prop, ifElse, identity, has, map } = require('rambda');

const galleryTemplate = path.resolve(`src/templates/gallery.js`);

const pipe = (...fns) => input =>
fns.reduce((chain, func) => chain.then(func), Promise.resolve(input));

// NOTE: does not guard against 0 args
const unary = fn => (...args) => fn(args[0]);
const handleError = error => {
throw new Error(error);
};

const handleGraphQlQueryErrors = ifElse(
has('errors'),
pipe(
prop('errors'),
handleError
),
identity
);

// NOTE: cannot be pulled out and rused because of the diverging es6/common.js exports in `src` vs. here
// NOTE: cannot be pulled out and reused because of the diverging es6/common.js exports in `src` vs. here
const queryGalleries = graphql => () =>
graphql(`
query GalleriesQuery {
Expand All @@ -19,53 +29,113 @@ const queryGalleries = graphql => () =>
node {
folderName
path
title
}
}
}
}
`);

const mapGalleriesToPage = galleries =>
galleries.map(gallery => {
const {
node: { folderName, path },
} = gallery;

return {
path: `${path}/*`,
component: galleryTemplate,
context: { folderName },
};
});

const handleError = error => {
throw new Error(error);
};
const extractGalleryData = galleries =>
galleries.map(({ node: { folderName, path, title } }) => ({
folderName,
path,
title,
}));

const handleGraphQlQueryErrors = ifElse(
has('errors'),
const getAllGalleries = ({ graphql }) =>
pipe(
prop('errors'),
handleError
),
identity
queryGalleries(graphql),
handleGraphQlQueryErrors,
pathOr([], 'data.allGalleriesYaml.edges'),
extractGalleryData
);

const queryImagesForGallery = ({ graphql }) => ({ folderName }) =>
graphql(
`
query GalleryQuery($folderName: String!) {
allFile(
filter: { relativeDirectory: { eq: $folderName } }
sort: { fields: [relativePath] }
) {
edges {
node {
childImageSharp {
internal {
contentDigest
}
}
}
}
}
}
`,
{
folderName,
}
);

const extractImagesData = pipe(
pathOr([], 'data.allFile.edges'),
map(pathOr(undefined, 'node.childImageSharp.internal.contentDigest'))
);

const getAllGalleriesAndImages = ({ graphql }) =>
const getImagesForGalleries = ({ graphql }) =>
pipe(
queryGalleries(graphql),
queryImagesForGallery({ graphql }),
handleGraphQlQueryErrors,
pathOr([], 'data.allGalleriesYaml.edges'),
mapGalleriesToPage
extractImagesData
);

const getCreatePagePayload = ({
path,
basePath,
title,
folderName,
initialId,
}) => ({
path,
component: galleryTemplate,
context: {
pathname: basePath,
initialId,
folderName,
title,
},
});

exports.createPages = async ({ actions, graphql }) => {
const { createPage } = actions;

try {
const galleries = await getAllGalleriesAndImages({ graphql })();
const galleries = await getAllGalleries({ graphql })();

galleries.forEach(async gallery => {
const { path, title, folderName } = gallery;
const imageIds = await getImagesForGalleries({ graphql })(gallery);

const createPagePayload = getCreatePagePayload({
path: `${path}`,
basePath: path,
title,
folderName,
});

imageIds.forEach(contentDigest =>
createPage(
getCreatePagePayload({
path: `${path}/${contentDigest}`,
basePath: path,
title,
folderName,
initialId: contentDigest,
})
)
);

galleries.forEach(unary(createPage));
createPage(createPagePayload);
});
} catch (err) {
throw err;
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Layout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ LayoutComponent.displayName = 'LayoutComponent';

const pageQuery = graphql`
query GalleriesQuery {
...allGalleriesYamlFragment
...AllGalleriesYamlFragment
}
`;

Expand Down
33 changes: 18 additions & 15 deletions src/templates/gallery.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,14 @@ import KeyHandler from 'react-key-handler';
import { compose, mapProps } from 'recompose';
import styled, { createGlobalStyle } from 'styled-components';
import { themeGet } from 'styled-system';
import { pathOr, pipe, replace, path } from 'rambda';
import { path } from 'rambda';

import { ReactComponent as PrevIcon } from 'assets/prev.svg';
import { ReactComponent as NextIcon } from 'assets/next.svg';
import { locationType, imageType } from 'utils/types';
import { useGallery } from 'utils/hooks';
import { ContentContainer, Layout } from 'components';
import {
mapGalleryImagesGraphQLResponse,
mapSingleGalleryYamlGraphQLResponse,
} from 'utils/mappings';
import { mapGalleryImagesGraphQLResponse } from 'utils/mappings';

import { mediaScreen } from '../theme';

Expand Down Expand Up @@ -103,8 +100,8 @@ const StyledNextIcon = styled(NextIcon)`
width: ${themeGet('space.5')};
`;

const getImageUrl = ({ pathname = '/portraits/', id }) =>
`${pathname}${id ? `#${id}` : ''}`;
const getImageUrl = ({ pathname = '/portraits', id }) =>
`${pathname}/${id ? `${id}` : ''}`;

export const Gallery = ({ images, title, location, pathname, initialId }) => {
const { currentId, nextId, prevId } = useGallery({
Expand Down Expand Up @@ -158,28 +155,34 @@ Gallery.propTypes = {
images: PropTypes.arrayOf(imageType).isRequired,
title: PropTypes.string.isRequired,
location: locationType.isRequired,
initialId: PropTypes.string.isRequired,
initialId: PropTypes.string,
pathname: PropTypes.string.isRequired,
};

Gallery.defaultProps = {
initialId: undefined,
};

Gallery.displayName = 'Gallery';

export default compose(
mapProps(props => ({
...props,
images: mapGalleryImagesGraphQLResponse(props),
title: mapSingleGalleryYamlGraphQLResponse(props),
pathname: path('location.pathname')(props),
initialId: pipe(
pathOr('', 'location.hash'),
replace('#', '')
)(props),
title: path('pageContext.title', props),
pathname: path('pageContext.pathname', props),
initialId: path('pageContext.initialId', props),
}))
)(Gallery);

/**
* NOTE: experimented with passing the `contentDigest`-ids here and getting them with `allImageSharp`
* in order to not query twice -> did not work because the correct ordering could not be applied
* without the relation to the filepath and manual ordering felt unexpected
*/
export const pageQuery = graphql`
query Gallery($folderName: String!) {
...singleGalleryYamlFragment
...SingleGalleryYamlFragment
allFile(
filter: { relativeDirectory: { eq: $folderName } }
sort: { fields: [relativePath] }
Expand Down
8 changes: 4 additions & 4 deletions src/utils/fragments.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ export const GalleryImagesFragment = graphql`
}
`;

export const allGalleriesYamlFragment = graphql`
fragment allGalleriesYamlFragment on Query {
export const AllGalleriesYamlFragment = graphql`
fragment AllGalleriesYamlFragment on Query {
allGalleriesYaml(sort: { fields: [order] }) {
group(field: album) {
fieldValue
Expand All @@ -32,8 +32,8 @@ export const allGalleriesYamlFragment = graphql`
}
`;

export const singleGalleryYamlFragment = graphql`
fragment singleGalleryYamlFragment on Query {
export const SingleGalleryYamlFragment = graphql`
fragment SingleGalleryYamlFragment on Query {
galleriesYaml(folderName: { eq: $folderName }) {
title
}
Expand Down
30 changes: 12 additions & 18 deletions src/utils/mappings.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,27 @@
import { path, pathOr, pipe } from 'rambda';
import { path, pathOr, pipe, map } from 'rambda';

const flattenAllGalleriesGraphQLResponse = response =>
response.map(({ fieldValue: albumTitle, edges: galleries }) => ({
albumTitle,
galleries: galleries.map(gallery => gallery.node),
galleries: galleries.map(path('node')),
}));

export const mapAllGalleriesGraphQLResponse = pipe(
pathOr([], 'allGalleriesYaml.group'),
flattenAllGalleriesGraphQLResponse
);

const flattenGalleryImagesGraphQLResponse = response =>
response
.filter(item => item.node && item.node.childImageSharp)
.map(
({
node: {
childImageSharp: {
fluid,
internal: { contentDigest },
},
},
}) => ({ fluid, contentDigest })
);

export const mapGalleryImagesGraphQLResponse = pipe(
path('data.allFile.edges'),
flattenGalleryImagesGraphQLResponse
pathOr([], 'data.allFile.edges'),
map(
pipe(
pathOr([], 'node.childImageSharp'),
img => ({
fluid: img.fluid,
contentDigest: path('internal.contentDigest', img),
})
)
)
);

export const mapSingleGalleryYamlGraphQLResponse = path(
Expand Down

0 comments on commit 5c8172a

Please sign in to comment.