WIP working on sorting recently published by capture date when published in batches
This commit is contained in:
@@ -30,7 +30,7 @@ interface MasonryGalleryProps {
|
||||
}
|
||||
|
||||
const MasonryGallery = ({
|
||||
images,
|
||||
images: _images,
|
||||
aspectsByBreakpoint: aspectTargetsByBreakpoint,
|
||||
debugHue,
|
||||
debugRating,
|
||||
@@ -59,8 +59,8 @@ const MasonryGallery = ({
|
||||
}px)`;
|
||||
|
||||
const aspectRatios = React.useMemo(
|
||||
() => R.map(getAspectRatio, images).filter(Boolean),
|
||||
[images]
|
||||
() => R.map(getAspectRatio, _images).filter(Boolean),
|
||||
[_images]
|
||||
) as number[];
|
||||
|
||||
const targetAspect = aspectTargetsByBreakpoint[breakpoint];
|
||||
@@ -87,10 +87,7 @@ const MasonryGallery = ({
|
||||
}
|
||||
// no-op instead of starting a new row
|
||||
if (singleRow) {
|
||||
return [
|
||||
...acc,
|
||||
currentRow,
|
||||
]
|
||||
return [currentRow];
|
||||
}
|
||||
// start a new row
|
||||
return [
|
||||
@@ -107,14 +104,16 @@ const MasonryGallery = ({
|
||||
),
|
||||
R.indexBy(R.prop("startIndex"))
|
||||
)(aspectRatios),
|
||||
[aspectRatios, targetAspect]
|
||||
[aspectRatios, targetAspect, singleRow]
|
||||
);
|
||||
|
||||
const sortedImageList = React.useMemo(
|
||||
() => images.map((image) => image.base),
|
||||
[images]
|
||||
() => _images.map((image) => image.base),
|
||||
[_images]
|
||||
);
|
||||
|
||||
const images = singleRow ? _images.slice(0, rows[0].images) : _images;
|
||||
|
||||
let cursor = 0;
|
||||
return (
|
||||
<div
|
||||
|
@@ -49,7 +49,7 @@ export function Select<T extends object>(props: AriaSelectProps<T>) {
|
||||
<button
|
||||
{...mergeProps(buttonProps, focusProps)}
|
||||
className={`py-[5px] px-3 w-[150px] flex flex-row items-center justify-between overflow-hidden cursor-default rounded border hover:bg-transparentblack ${
|
||||
isFocusVisible ? "border-green-500" : "border-black"
|
||||
isFocusVisible ? "border-green-700" : "border-black"
|
||||
} ${state.isOpen ? "bg-gray-100" : "bg-white"}`}
|
||||
ref={ref}
|
||||
>
|
||||
|
8
src/gatsby-types.d.ts
vendored
8
src/gatsby-types.d.ts
vendored
@@ -571,6 +571,7 @@ type FileFieldsFilterInput = {
|
||||
};
|
||||
|
||||
type FileFieldsImageMeta = {
|
||||
readonly datePublished: Maybe<Scalars['String']>;
|
||||
readonly dateTaken: Maybe<Scalars['Date']>;
|
||||
readonly dominantHue: Maybe<ReadonlyArray<Maybe<Scalars['Float']>>>;
|
||||
readonly meta: Maybe<FileFieldsImageMetaMeta>;
|
||||
@@ -587,6 +588,7 @@ type FileFieldsImageMeta_dateTakenArgs = {
|
||||
};
|
||||
|
||||
type FileFieldsImageMetaFieldSelector = {
|
||||
readonly datePublished: InputMaybe<FieldSelectorEnum>;
|
||||
readonly dateTaken: InputMaybe<FieldSelectorEnum>;
|
||||
readonly dominantHue: InputMaybe<FieldSelectorEnum>;
|
||||
readonly meta: InputMaybe<FileFieldsImageMetaMetaFieldSelector>;
|
||||
@@ -595,6 +597,7 @@ type FileFieldsImageMetaFieldSelector = {
|
||||
};
|
||||
|
||||
type FileFieldsImageMetaFilterInput = {
|
||||
readonly datePublished: InputMaybe<StringQueryOperatorInput>;
|
||||
readonly dateTaken: InputMaybe<DateQueryOperatorInput>;
|
||||
readonly dominantHue: InputMaybe<FloatQueryOperatorInput>;
|
||||
readonly meta: InputMaybe<FileFieldsImageMetaMetaFilterInput>;
|
||||
@@ -715,6 +718,7 @@ type FileFieldsImageMetaMetaSortInput = {
|
||||
};
|
||||
|
||||
type FileFieldsImageMetaSortInput = {
|
||||
readonly datePublished: InputMaybe<SortOrderEnum>;
|
||||
readonly dateTaken: InputMaybe<SortOrderEnum>;
|
||||
readonly dominantHue: InputMaybe<SortOrderEnum>;
|
||||
readonly meta: InputMaybe<FileFieldsImageMetaMetaSortInput>;
|
||||
@@ -2559,12 +2563,12 @@ type GalleryImageQueryVariables = Exact<{
|
||||
|
||||
type GalleryImageQuery = { readonly file: { readonly base: string, readonly publicURL: string | null, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly dateTaken: string | null, readonly meta: { readonly Make: string | null, readonly Model: string | null, readonly ExposureTime: number | null, readonly FNumber: number | null, readonly ISO: number | null, readonly DateTimeOriginal: string | null, readonly CreateDate: string | null, readonly ShutterSpeedValue: number | null, readonly ApertureValue: number | null, readonly FocalLength: number | null, readonly LensModel: string | null, readonly ObjectName: string | null, readonly Caption: string | null, readonly Location: string | null, readonly City: string | null, readonly State: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null } | null };
|
||||
|
||||
type GalleryImageFileFragment = { readonly nodes: ReadonlyArray<{ readonly relativePath: string, readonly base: string, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly vibrantHue: number | null, readonly dominantHue: ReadonlyArray<number | null> | null, readonly dateTaken: string | null, readonly meta: { readonly Keywords: ReadonlyArray<string | null> | null, readonly Rating: number | null, readonly ObjectName: string | null, readonly CreateDate: string | null, readonly ModifyDate: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null }> };
|
||||
type GalleryImageFileFragment = { readonly nodes: ReadonlyArray<{ readonly base: string, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly vibrantHue: number | null, readonly dominantHue: ReadonlyArray<number | null> | null, readonly dateTaken: string | null, readonly datePublished: string | null, readonly meta: { readonly Keywords: ReadonlyArray<string | null> | null, readonly Rating: number | null, readonly ObjectName: string | null, readonly CreateDate: string | null, readonly ModifyDate: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null }> };
|
||||
|
||||
type GalleryPageQueryQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
type GalleryPageQueryQuery = { readonly recents: { readonly nodes: ReadonlyArray<{ readonly relativePath: string, readonly base: string, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly vibrantHue: number | null, readonly dominantHue: ReadonlyArray<number | null> | null, readonly dateTaken: string | null, readonly meta: { readonly Keywords: ReadonlyArray<string | null> | null, readonly Rating: number | null, readonly ObjectName: string | null, readonly CreateDate: string | null, readonly ModifyDate: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null }> }, readonly all: { readonly nodes: ReadonlyArray<{ readonly relativePath: string, readonly base: string, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly vibrantHue: number | null, readonly dominantHue: ReadonlyArray<number | null> | null, readonly dateTaken: string | null, readonly meta: { readonly Keywords: ReadonlyArray<string | null> | null, readonly Rating: number | null, readonly ObjectName: string | null, readonly CreateDate: string | null, readonly ModifyDate: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null }> } };
|
||||
type GalleryPageQueryQuery = { readonly recents: { readonly nodes: ReadonlyArray<{ readonly base: string, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly vibrantHue: number | null, readonly dominantHue: ReadonlyArray<number | null> | null, readonly dateTaken: string | null, readonly datePublished: string | null, readonly meta: { readonly Keywords: ReadonlyArray<string | null> | null, readonly Rating: number | null, readonly ObjectName: string | null, readonly CreateDate: string | null, readonly ModifyDate: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null }> }, readonly all: { readonly nodes: ReadonlyArray<{ readonly base: string, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly vibrantHue: number | null, readonly dominantHue: ReadonlyArray<number | null> | null, readonly dateTaken: string | null, readonly datePublished: string | null, readonly meta: { readonly Keywords: ReadonlyArray<string | null> | null, readonly Rating: number | null, readonly ObjectName: string | null, readonly CreateDate: string | null, readonly ModifyDate: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null }> } };
|
||||
|
||||
type GatsbyImageSharpFixedFragment = { readonly base64: string | null, readonly width: number, readonly height: number, readonly src: string, readonly srcSet: string };
|
||||
|
||||
|
@@ -7,6 +7,7 @@ import { Helmet } from "react-helmet";
|
||||
import MasonryGallery from "../components/MasonryGallery";
|
||||
import KeywordsPicker from "../components/KeywordsPicker";
|
||||
import {
|
||||
compareDates,
|
||||
getGalleryPageUrl,
|
||||
getHelmetSafeBodyStyle,
|
||||
getVibrantStyle,
|
||||
@@ -19,14 +20,25 @@ import ColorPalette from "@spectrum-icons/workflow/ColorPalette";
|
||||
const SORT_KEYS = {
|
||||
hue: ["fields", "imageMeta", "vibrantHue"],
|
||||
rating: ["fields", "imageMeta", "meta", "Rating"],
|
||||
hue_debug: ["fields", "imageMeta", "dominantHue", 0],
|
||||
// hue_debug: ["fields", "imageMeta", "dominantHue", 0],
|
||||
hue_debug: ["fields", "imageMeta", "dominantHue", "0"],
|
||||
date: ["fields", "imageMeta", "dateTaken"],
|
||||
modified: ["fields", "imageMeta", "meta", "ModifyDate"]
|
||||
modified: ["fields", "imageMeta", "datePublished"],
|
||||
} as const;
|
||||
|
||||
export type GalleryImage =
|
||||
Queries.GalleryPageQueryQuery["all"]["nodes"][number];
|
||||
|
||||
function smartCompareDates(key: keyof typeof SORT_KEYS, left: GalleryImage, right: GalleryImage) {
|
||||
let diff = compareDates(SORT_KEYS[key], left, right);
|
||||
console.log("🚀 ~ file: photogallery.tsx:34 ~ smartCompareDates ~ diff:", diff)
|
||||
if (diff !== 0) {
|
||||
return diff;
|
||||
}
|
||||
console.log('falling back to date')
|
||||
return compareDates(SORT_KEYS.date, left, right);
|
||||
}
|
||||
|
||||
const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
||||
const hash =
|
||||
typeof window !== "undefined" ? window.location.hash.replace("#", "") : "";
|
||||
@@ -130,15 +142,7 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
||||
const images: GalleryImage[] = React.useMemo(() => {
|
||||
const sort =
|
||||
sortKey === "date" || sortKey === "modified"
|
||||
? R.sort((node1: typeof data["all"]["nodes"][number], node2) => {
|
||||
const date1 = new Date(
|
||||
R.pathOr("", SORT_KEYS[sortKey], node1)
|
||||
);
|
||||
const date2 = new Date(
|
||||
R.pathOr("", SORT_KEYS[sortKey], node2)
|
||||
);
|
||||
return -1 * (date1.getTime() - date2.getTime());
|
||||
})
|
||||
? R.sort((node1: typeof data["all"]["nodes"][number], node2) => smartCompareDates(sortKey, node1, node2))
|
||||
: R.sort(
|
||||
// @ts-ignore
|
||||
R.descend(R.path<GalleryImage>(SORT_KEYS[sortKey]))
|
||||
@@ -166,6 +170,10 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
||||
}
|
||||
}, [data, sortKey, filterKeyword]);
|
||||
|
||||
const recents = React.useMemo(() => {
|
||||
return R.sort((left, right) => smartCompareDates('modified', left, right), data.recents.nodes)
|
||||
}, [data, 'hi'])
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* @ts-ignore */}
|
||||
@@ -198,7 +206,9 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
||||
/>
|
||||
</div>
|
||||
<div className="px-4 md:px-8">
|
||||
<h3 id="recently" className="mx-2 font-bold">Recently updated</h3>
|
||||
<h3 id="recently" className="mx-2 font-bold">
|
||||
Recently published
|
||||
</h3>
|
||||
</div>
|
||||
<MasonryGallery
|
||||
aspectsByBreakpoint={{
|
||||
@@ -210,11 +220,13 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
||||
"2xl": 6.1,
|
||||
"3xl": 8,
|
||||
}}
|
||||
images={data.recents.nodes}
|
||||
images={recents}
|
||||
singleRow
|
||||
/>
|
||||
<div className="px-4 md:px-8 mt-4 pt-2 border-t">
|
||||
<h3 id="all" className="mx-2 font-bold">All images</h3>
|
||||
<h3 id="all" className="mx-2 font-bold">
|
||||
All images
|
||||
</h3>
|
||||
</div>
|
||||
<div className="flex flex-col lg:flex-row lg:items-end justify-between px-4 md:px-8 sm:mx-auto">
|
||||
<KeywordsPicker
|
||||
@@ -258,14 +270,14 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
||||
selectedKey={sortKey}
|
||||
>
|
||||
<Item key="rating">Curated</Item>
|
||||
<Item key="modified">Date Updated</Item>
|
||||
<Item key="modified">Date published</Item>
|
||||
<Item key="date">Date taken</Item>
|
||||
<Item key="hue">Hue</Item>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<MasonryGallery
|
||||
{/* <MasonryGallery
|
||||
aspectsByBreakpoint={{
|
||||
xs: 2,
|
||||
sm: 2,
|
||||
@@ -283,7 +295,7 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
||||
filterKeyword,
|
||||
}}
|
||||
showPalette={showPalette}
|
||||
/>
|
||||
/> */}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -292,7 +304,7 @@ export const query = graphql`
|
||||
query GalleryPageQuery {
|
||||
recents: allFile(
|
||||
filter: { sourceInstanceName: { eq: "gallery" } }
|
||||
sort: { fields: { imageMeta: { meta: { ModifyDate: DESC } } } }
|
||||
sort: { fields: { imageMeta: { datePublished: DESC } } }
|
||||
limit: 7
|
||||
) {
|
||||
...GalleryImageFile
|
||||
@@ -307,7 +319,6 @@ export const query = graphql`
|
||||
|
||||
fragment GalleryImageFile on FileConnection {
|
||||
nodes {
|
||||
relativePath
|
||||
base
|
||||
childImageSharp {
|
||||
fluid {
|
||||
@@ -324,6 +335,7 @@ export const query = graphql`
|
||||
vibrantHue
|
||||
dominantHue
|
||||
dateTaken
|
||||
datePublished
|
||||
meta {
|
||||
Keywords
|
||||
Rating
|
||||
|
50
src/utils.ts
50
src/utils.ts
@@ -1,18 +1,23 @@
|
||||
import React from "react";
|
||||
|
||||
import { pathOr } from "ramda";
|
||||
// import kebabCase from 'lodash/kebabCase';
|
||||
|
||||
import React from "react";
|
||||
import { HomepageImage } from "./pages";
|
||||
import { GalleryImage } from "./pages/photogallery";
|
||||
|
||||
export const getMeta = <T extends GalleryImage | HomepageImage>(image: T) => image.fields?.imageMeta;
|
||||
export const getMeta = <T extends GalleryImage | HomepageImage>(image: T) =>
|
||||
image.fields?.imageMeta;
|
||||
|
||||
export const getName = (image: GalleryImage) =>
|
||||
image.fields?.imageMeta?.meta?.ObjectName || image.base;
|
||||
image.fields?.imageMeta?.meta?.ObjectName || image.base;
|
||||
|
||||
// some pleasing default colors for SSR and initial hydration
|
||||
export const getVibrant = (image: GalleryImage | HomepageImage) => getMeta(image)?.vibrant;
|
||||
export const getVibrant = (image: GalleryImage | HomepageImage) =>
|
||||
getMeta(image)?.vibrant;
|
||||
|
||||
export const hasName = (image: GalleryImage) => Boolean(image.fields?.imageMeta?.meta?.ObjectName);
|
||||
export const hasName = (image: GalleryImage) =>
|
||||
Boolean(image.fields?.imageMeta?.meta?.ObjectName);
|
||||
|
||||
export const getAspectRatio = (image: GalleryImage | HomepageImage): number =>
|
||||
image.childImageSharp?.fluid?.aspectRatio ?? 1;
|
||||
@@ -25,7 +30,10 @@ export const getCanonicalSize = (image: GalleryImage) => ({
|
||||
export const getRgba = (palette: string[], alpha: number) =>
|
||||
`rgba(${palette[0]}, ${palette[1]}, ${palette[2]}, ${alpha || 1})`;
|
||||
|
||||
export const getVibrantStyle = (vibrant: Queries.FileFieldsImageMetaVibrant, screenHeight?: number) => ({
|
||||
export const getVibrantStyle = (
|
||||
vibrant: Queries.FileFieldsImageMetaVibrant,
|
||||
screenHeight?: number
|
||||
) => ({
|
||||
"--muted": vibrant.Muted,
|
||||
"--dark-muted": vibrant.DarkMuted,
|
||||
"--light-muted": vibrant.LightMuted,
|
||||
@@ -40,10 +48,12 @@ export const getHelmetSafeBodyStyle = (style: React.CSSProperties) => {
|
||||
if (typeof window === "undefined") {
|
||||
return style;
|
||||
}
|
||||
return Object.keys(style)
|
||||
// @ts-ignore
|
||||
.map((key) => `${key}: ${style[key]};`)
|
||||
.join("");
|
||||
return (
|
||||
Object.keys(style)
|
||||
// @ts-ignore
|
||||
.map((key) => `${key}: ${style[key]};`)
|
||||
.join("")
|
||||
);
|
||||
};
|
||||
|
||||
const gcd = (a: number, b: number): number => {
|
||||
@@ -94,7 +104,10 @@ interface galleryPageUrlProps {
|
||||
sortKey: string;
|
||||
}
|
||||
|
||||
export const getGalleryPageUrl = ({ keyword, sortKey }: galleryPageUrlProps, hash: string) => {
|
||||
export const getGalleryPageUrl = (
|
||||
{ keyword, sortKey }: galleryPageUrlProps,
|
||||
hash: string
|
||||
) => {
|
||||
const url = new URL(
|
||||
`${
|
||||
typeof window !== "undefined"
|
||||
@@ -121,3 +134,18 @@ export const getGalleryPageUrl = ({ keyword, sortKey }: galleryPageUrlProps, has
|
||||
}
|
||||
return url.href.toString().replace(url.origin, "");
|
||||
};
|
||||
|
||||
export function compareDates<T>(
|
||||
date_path: readonly string[],
|
||||
left: T,
|
||||
right: T
|
||||
): number {
|
||||
const d1 = pathOr("", date_path, left);
|
||||
console.log("🚀 ~ file: utils.ts:129 ~ d1:", d1);
|
||||
const date1 = new Date(d1);
|
||||
console.log("🚀 ~ file: utils.ts:146 ~ new Date(d1):", new Date(d1))
|
||||
console.log("🚀 ~ file: utils.ts:133 ~ date1:", date1);
|
||||
const date2 = new Date(pathOr("", date_path, right));
|
||||
const diff = -1 * (date1.getTime() - date2.getTime());
|
||||
return diff;
|
||||
}
|
||||
|
Reference in New Issue
Block a user