I need to be able to sort images by aspect ratio and put them into a Netlify CMS preview template.
I have built a page template for this Gatsby site that uses some attributes provided by gatsby-image (specifically aspectRatio) to filter the images into two arrays based on this value, and then build an image grid layout with the two arrays — two portait, one landscape, two portrait and so on.
I would like to be able to replicate this layout in the Netlify CMS preview template so the user can see the layout with the images they enter in it. The trouble, of course, is that the data provided to the template doesn't contain the same info as the results available through the GraphQL query that builds the page itself, and I wouldn't be able to use a static query to grab the files as I would need to run the query for each separate "project," and you can't pass variables to static queries (they're static ).
I have already tried to use the NPM package "image-size," but it won't work as the preview template code isn't executed on the server in a Node environment (I don't think). I have also tried to leverage the browser Img API, but I wasn't able to get it to work, either.
I am able to get the link to each image resource (e.g. "/media/some-image.jpg") through the methods and data provided to the Netlify CMS template, but am unsure where to go from there.
Perhaps I should try taking another crack at executing the code I need on the client side?
// Here's the working page template.
// Sort images into two different arrays based on aspect ratio
const filterImagesByAspectRatio = (images) => {
const portraitOrientation = images.filter(
({ image }) => image.childImageSharp.fluid.aspectRatio <= 1
);
const landscapeOrientation = images.filter(
({ image }) => image.childImageSharp.fluid.aspectRatio > 1
);
return {
portraitOrientation,
landscapeOrientation,
};
};
// Put image columns into an array, alternating two portrait, one landscape
const imageGrid = (portraitColumns, landscapeColumns) => {
let i = 0;
let j = 0;
let grid = [];
while (i < portraitColumns.length || j < landscapeColumns.length) {
if (i < portraitColumns.length) {
grid.push(portraitColumns[i], portraitColumns[i + 1]);
i = i + 2;
}
if (j < landscapeColumns.length) {
grid.push(landscapeColumns[j]);
j++;
}
}
return grid;
};
export const ProjectTemplate = ({
images,
}) => {
// Sort based on aspect ratio
const {
portraitOrientation,
landscapeOrientation,
} = filterImagesByAspectRatio(images);
// Put images into React Components
const portraitColumns = portraitOrientation.map((item) => {
return (
<div
className="column is-6"
key={`${item.image.childImageSharp.fluid.src}`}
>
<PreviewCompatibleImage imageInfo={item} />
</div>
);
});
// Put images into React Components
const landscapeColumns = landscapeOrientation.map((item) => (
<div
className="column is-12"
key={`${item.image.childImageSharp.fluid.src}`}
>
<PreviewCompatibleImage imageInfo={item} />
</div>
));
return (
<div className="columns">
<div className="column is-8 images-column">
<div className="columns is-multiline is-mobile images-row">
{imageGrid(portraitColumns, landscapeColumns)}
</div>
</div>
</div>
);
};