WIP working on sorting recently published by capture date when published in batches
This commit is contained in:
parent
660b231d44
commit
35e6211170
@ -10,6 +10,10 @@ import sharp from "sharp";
|
|||||||
import { Palette } from "node-vibrant/lib/color";
|
import { Palette } from "node-vibrant/lib/color";
|
||||||
import { performance } from "perf_hooks";
|
import { performance } from "perf_hooks";
|
||||||
|
|
||||||
|
import util from 'node:util';
|
||||||
|
import { exec as _exec } from "child_process";
|
||||||
|
const exec = util.promisify(_exec)
|
||||||
|
|
||||||
// const path = require("path");
|
// const path = require("path");
|
||||||
// const Vibrant = require("node-vibrant");
|
// const Vibrant = require("node-vibrant");
|
||||||
// const chroma = require("chroma-js");
|
// const chroma = require("chroma-js");
|
||||||
@ -114,7 +118,8 @@ function transformMetaToNodeData(
|
|||||||
metaData: Record<string, unknown>,
|
metaData: Record<string, unknown>,
|
||||||
vibrantData: Palette,
|
vibrantData: Palette,
|
||||||
imagePath: string,
|
imagePath: string,
|
||||||
{ r, g, b }: { r: number; b: number; g: number }
|
{ r, g, b }: { r: number; b: number; g: number },
|
||||||
|
datePublished: string,
|
||||||
) {
|
) {
|
||||||
const vibrant = vibrantData ? processColors(vibrantData, imagePath) : null;
|
const vibrant = vibrantData ? processColors(vibrantData, imagePath) : null;
|
||||||
const vibrantHue = vibrantData.Vibrant!.getHsl()[0] * 360;
|
const vibrantHue = vibrantData.Vibrant!.getHsl()[0] * 360;
|
||||||
@ -131,6 +136,7 @@ function transformMetaToNodeData(
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
dateTaken: metaData.DateTimeOriginal,
|
dateTaken: metaData.DateTimeOriginal,
|
||||||
|
datePublished,
|
||||||
meta: {
|
meta: {
|
||||||
Make: metaData.Make,
|
Make: metaData.Make,
|
||||||
Model: metaData.Model,
|
Model: metaData.Model,
|
||||||
@ -174,6 +180,11 @@ export const onCreateNode: GatsbyNode["onCreateNode"] = async function ({
|
|||||||
const { createNodeField } = actions;
|
const { createNodeField } = actions;
|
||||||
|
|
||||||
if (node.internal.type === "File" && node.sourceInstanceName === "gallery") {
|
if (node.internal.type === "File" && node.sourceInstanceName === "gallery") {
|
||||||
|
const { stdout: datePublished, stderr } = await exec(`git log --diff-filter=A --follow --format=%aI -1 -- ${node.absolutePath}`)
|
||||||
|
if (stderr.length) {
|
||||||
|
console.error('something went wrong checking publish date: ', stderr);
|
||||||
|
}
|
||||||
|
|
||||||
const metaData = await exifr.parse(node.absolutePath as string, {
|
const metaData = await exifr.parse(node.absolutePath as string, {
|
||||||
iptc: true,
|
iptc: true,
|
||||||
xmp: true,
|
xmp: true,
|
||||||
@ -201,7 +212,8 @@ export const onCreateNode: GatsbyNode["onCreateNode"] = async function ({
|
|||||||
metaData,
|
metaData,
|
||||||
vibrantData,
|
vibrantData,
|
||||||
node.absolutePath as string,
|
node.absolutePath as string,
|
||||||
dominant
|
dominant,
|
||||||
|
datePublished
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
193
scratchpad.js
Normal file
193
scratchpad.js
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
a = {
|
||||||
|
ApplicationRecordVersion: '\x00\x04',
|
||||||
|
DateCreated: '2015-10-18T17:59:38',
|
||||||
|
TimeCreated: '175938',
|
||||||
|
DigitalCreationDate: '20151018',
|
||||||
|
DigitalCreationTime: '175938',
|
||||||
|
format: 'image/jpeg',
|
||||||
|
CreatorTool: 'Adobe Lightroom 5.4 (Macintosh)',
|
||||||
|
ModifyDate: '2022-07-09T21:16:39.000Z',
|
||||||
|
CreateDate: '2015-10-19T00:59:38.000Z',
|
||||||
|
MetadataDate: '2022-07-09T14:16:39-07:00',
|
||||||
|
Rating: 5,
|
||||||
|
LensInfo: [ 50, 50, 1.8, 1.8 ],
|
||||||
|
Lens: 'DT 50mm F1.8 SAM',
|
||||||
|
DocumentID: 'xmp.did:27795bf1-8bb2-49a0-807a-cf6150bd505b',
|
||||||
|
OriginalDocumentID: 'CE2B8F240393ADFDF9F092CF395C6632',
|
||||||
|
InstanceID: 'xmp.iid:27795bf1-8bb2-49a0-807a-cf6150bd505b',
|
||||||
|
History: [
|
||||||
|
{ action: 'derived', parameters: 'saved to new location' },
|
||||||
|
{
|
||||||
|
action: 'saved',
|
||||||
|
instanceID: 'xmp.iid:27795bf1-8bb2-49a0-807a-cf6150bd505b',
|
||||||
|
when: '2022-07-09T14:16:39-07:00',
|
||||||
|
softwareAgent: 'Adobe Lightroom 5.4 (Macintosh)',
|
||||||
|
changed: '/'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
DerivedFrom: {
|
||||||
|
documentID: 'CE2B8F240393ADFDF9F092CF395C6632',
|
||||||
|
originalDocumentID: 'CE2B8F240393ADFDF9F092CF395C6632'
|
||||||
|
},
|
||||||
|
good: true,
|
||||||
|
Version: 14.4,
|
||||||
|
ProcessVersion: 6.7,
|
||||||
|
WhiteBalance: 'Manual',
|
||||||
|
IncrementalTemperature: -11,
|
||||||
|
IncrementalTint: 23,
|
||||||
|
Exposure2012: 0,
|
||||||
|
Contrast2012: 6,
|
||||||
|
Highlights2012: 0,
|
||||||
|
Shadows2012: 0,
|
||||||
|
Whites2012: 35,
|
||||||
|
Blacks2012: -22,
|
||||||
|
Texture: 0,
|
||||||
|
Clarity2012: 0,
|
||||||
|
Dehaze: 0,
|
||||||
|
Vibrance: 0,
|
||||||
|
Saturation: 'Normal',
|
||||||
|
ParametricShadows: 0,
|
||||||
|
ParametricDarks: 0,
|
||||||
|
ParametricLights: 0,
|
||||||
|
ParametricHighlights: 0,
|
||||||
|
ParametricShadowSplit: 25,
|
||||||
|
ParametricMidtoneSplit: 50,
|
||||||
|
ParametricHighlightSplit: 75,
|
||||||
|
Sharpness: 'Normal',
|
||||||
|
LuminanceSmoothing: 0,
|
||||||
|
ColorNoiseReduction: 0,
|
||||||
|
HueAdjustmentRed: 0,
|
||||||
|
HueAdjustmentOrange: 0,
|
||||||
|
HueAdjustmentYellow: 0,
|
||||||
|
HueAdjustmentGreen: 0,
|
||||||
|
HueAdjustmentAqua: 0,
|
||||||
|
HueAdjustmentBlue: 0,
|
||||||
|
HueAdjustmentPurple: 0,
|
||||||
|
HueAdjustmentMagenta: 0,
|
||||||
|
SaturationAdjustmentRed: 0,
|
||||||
|
SaturationAdjustmentOrange: 0,
|
||||||
|
SaturationAdjustmentYellow: 0,
|
||||||
|
SaturationAdjustmentGreen: 0,
|
||||||
|
SaturationAdjustmentAqua: 0,
|
||||||
|
SaturationAdjustmentBlue: 0,
|
||||||
|
SaturationAdjustmentPurple: 0,
|
||||||
|
SaturationAdjustmentMagenta: 0,
|
||||||
|
LuminanceAdjustmentRed: 0,
|
||||||
|
LuminanceAdjustmentOrange: 0,
|
||||||
|
LuminanceAdjustmentYellow: 0,
|
||||||
|
LuminanceAdjustmentGreen: 0,
|
||||||
|
LuminanceAdjustmentAqua: 0,
|
||||||
|
LuminanceAdjustmentBlue: 0,
|
||||||
|
LuminanceAdjustmentPurple: 0,
|
||||||
|
LuminanceAdjustmentMagenta: 0,
|
||||||
|
SplitToningShadowHue: 0,
|
||||||
|
SplitToningShadowSaturation: 0,
|
||||||
|
SplitToningHighlightHue: 0,
|
||||||
|
SplitToningHighlightSaturation: 0,
|
||||||
|
SplitToningBalance: 0,
|
||||||
|
ColorGradeMidtoneHue: 0,
|
||||||
|
ColorGradeMidtoneSat: 0,
|
||||||
|
ColorGradeShadowLum: 0,
|
||||||
|
ColorGradeMidtoneLum: 0,
|
||||||
|
ColorGradeHighlightLum: 0,
|
||||||
|
ColorGradeBlending: 50,
|
||||||
|
ColorGradeGlobalHue: 0,
|
||||||
|
ColorGradeGlobalSat: 0,
|
||||||
|
ColorGradeGlobalLum: 0,
|
||||||
|
AutoLateralCA: 0,
|
||||||
|
LensProfileEnable: 0,
|
||||||
|
LensManualDistortionAmount: 0,
|
||||||
|
VignetteAmount: 0,
|
||||||
|
DefringePurpleAmount: 0,
|
||||||
|
DefringePurpleHueLo: 30,
|
||||||
|
DefringePurpleHueHi: 70,
|
||||||
|
DefringeGreenAmount: 0,
|
||||||
|
DefringeGreenHueLo: 40,
|
||||||
|
DefringeGreenHueHi: 60,
|
||||||
|
PerspectiveUpright: 0,
|
||||||
|
PerspectiveVertical: 0,
|
||||||
|
PerspectiveHorizontal: 0,
|
||||||
|
PerspectiveRotate: 0,
|
||||||
|
PerspectiveAspect: 0,
|
||||||
|
PerspectiveScale: 100,
|
||||||
|
PerspectiveX: 0,
|
||||||
|
PerspectiveY: 0,
|
||||||
|
GrainAmount: 0,
|
||||||
|
PostCropVignetteAmount: 0,
|
||||||
|
ShadowTint: 0,
|
||||||
|
RedHue: 0,
|
||||||
|
RedSaturation: 0,
|
||||||
|
GreenHue: 0,
|
||||||
|
GreenSaturation: 0,
|
||||||
|
BlueHue: 0,
|
||||||
|
BlueSaturation: 0,
|
||||||
|
ConvertToGrayscale: false,
|
||||||
|
OverrideLookVignette: false,
|
||||||
|
ToneCurveName2012: 'Linear',
|
||||||
|
CameraProfile: 'Embedded',
|
||||||
|
CameraProfileDigest: '54650A341B5B5CCAE8442D0B43A92BCE',
|
||||||
|
HasSettings: true,
|
||||||
|
CropTop: 0,
|
||||||
|
CropLeft: 0,
|
||||||
|
CropBottom: 1,
|
||||||
|
CropRight: 1,
|
||||||
|
CropAngle: 0,
|
||||||
|
CropConstrainToWarp: 0,
|
||||||
|
HasCrop: false,
|
||||||
|
AlreadyApplied: true,
|
||||||
|
ToneCurvePV2012: [ '0, 0', '255, 255' ],
|
||||||
|
ToneCurvePV2012Red: [ '0, 0', '255, 255' ],
|
||||||
|
ToneCurvePV2012Green: [ '0, 0', '255, 255' ],
|
||||||
|
ToneCurvePV2012Blue: [ '0, 0', '255, 255' ],
|
||||||
|
Make: 'SONY',
|
||||||
|
Model: 'SLT-A55V',
|
||||||
|
XResolution: 240,
|
||||||
|
YResolution: 240,
|
||||||
|
ResolutionUnit: 'inches',
|
||||||
|
Software: 'Adobe Lightroom 5.4 (Macintosh)',
|
||||||
|
ExposureTime: 0.01,
|
||||||
|
FNumber: 1.8,
|
||||||
|
ExposureProgram: 'Manual',
|
||||||
|
ISO: 200,
|
||||||
|
SensitivityType: 2,
|
||||||
|
RecommendedExposureIndex: 200,
|
||||||
|
ExifVersion: '2.3.1',
|
||||||
|
DateTimeOriginal: '2015-10-19T00:59:38.000Z',
|
||||||
|
OffsetTime: '-07:00',
|
||||||
|
ShutterSpeedValue: 6.643856,
|
||||||
|
ApertureValue: 1.695994,
|
||||||
|
BrightnessValue: 3,
|
||||||
|
ExposureCompensation: 0,
|
||||||
|
MaxApertureValue: 1.7,
|
||||||
|
MeteringMode: 'Pattern',
|
||||||
|
LightSource: 'Cloudy weather',
|
||||||
|
Flash: 'Flash did not fire, compulsory flash mode',
|
||||||
|
FocalLength: 50,
|
||||||
|
ColorSpace: 1,
|
||||||
|
FileSource: 'Digital Camera',
|
||||||
|
SceneType: 'Directly photographed',
|
||||||
|
CustomRendered: 'Normal',
|
||||||
|
ExposureMode: 'Manual',
|
||||||
|
FocalLengthIn35mmFormat: 75,
|
||||||
|
SceneCaptureType: 'Standard',
|
||||||
|
Contrast: 'Normal',
|
||||||
|
LensModel: 'DT 50mm F1.8 SAM',
|
||||||
|
GPSVersionID: '2.2.0.0',
|
||||||
|
GPSLatitudeRef: 'N',
|
||||||
|
GPSLatitude: [ 33, 25.7121, 0 ],
|
||||||
|
GPSLongitudeRef: 'W',
|
||||||
|
GPSLongitude: [ 111, 55.57122, 0 ],
|
||||||
|
GPSAltitude: 354.7,
|
||||||
|
GPSTimeStamp: '19:2:7',
|
||||||
|
GPSStatus: 'V',
|
||||||
|
GPSMeasureMode: '3',
|
||||||
|
GPSSpeedRef: 'K',
|
||||||
|
GPSSpeed: 33.8,
|
||||||
|
GPSTrackRef: 'T',
|
||||||
|
GPSTrack: 0.36,
|
||||||
|
GPSMapDatum: 'WGS-84',
|
||||||
|
GPSDateStamp: '2015:10:09',
|
||||||
|
GPSDifferential: 0,
|
||||||
|
latitude: 33.428535,
|
||||||
|
longitude: -111.926187
|
||||||
|
}
|
@ -30,7 +30,7 @@ interface MasonryGalleryProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const MasonryGallery = ({
|
const MasonryGallery = ({
|
||||||
images,
|
images: _images,
|
||||||
aspectsByBreakpoint: aspectTargetsByBreakpoint,
|
aspectsByBreakpoint: aspectTargetsByBreakpoint,
|
||||||
debugHue,
|
debugHue,
|
||||||
debugRating,
|
debugRating,
|
||||||
@ -59,8 +59,8 @@ const MasonryGallery = ({
|
|||||||
}px)`;
|
}px)`;
|
||||||
|
|
||||||
const aspectRatios = React.useMemo(
|
const aspectRatios = React.useMemo(
|
||||||
() => R.map(getAspectRatio, images).filter(Boolean),
|
() => R.map(getAspectRatio, _images).filter(Boolean),
|
||||||
[images]
|
[_images]
|
||||||
) as number[];
|
) as number[];
|
||||||
|
|
||||||
const targetAspect = aspectTargetsByBreakpoint[breakpoint];
|
const targetAspect = aspectTargetsByBreakpoint[breakpoint];
|
||||||
@ -87,10 +87,7 @@ const MasonryGallery = ({
|
|||||||
}
|
}
|
||||||
// no-op instead of starting a new row
|
// no-op instead of starting a new row
|
||||||
if (singleRow) {
|
if (singleRow) {
|
||||||
return [
|
return [currentRow];
|
||||||
...acc,
|
|
||||||
currentRow,
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
// start a new row
|
// start a new row
|
||||||
return [
|
return [
|
||||||
@ -107,14 +104,16 @@ const MasonryGallery = ({
|
|||||||
),
|
),
|
||||||
R.indexBy(R.prop("startIndex"))
|
R.indexBy(R.prop("startIndex"))
|
||||||
)(aspectRatios),
|
)(aspectRatios),
|
||||||
[aspectRatios, targetAspect]
|
[aspectRatios, targetAspect, singleRow]
|
||||||
);
|
);
|
||||||
|
|
||||||
const sortedImageList = React.useMemo(
|
const sortedImageList = React.useMemo(
|
||||||
() => images.map((image) => image.base),
|
() => _images.map((image) => image.base),
|
||||||
[images]
|
[_images]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const images = singleRow ? _images.slice(0, rows[0].images) : _images;
|
||||||
|
|
||||||
let cursor = 0;
|
let cursor = 0;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -49,7 +49,7 @@ export function Select<T extends object>(props: AriaSelectProps<T>) {
|
|||||||
<button
|
<button
|
||||||
{...mergeProps(buttonProps, focusProps)}
|
{...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 ${
|
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"}`}
|
} ${state.isOpen ? "bg-gray-100" : "bg-white"}`}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
>
|
>
|
||||||
|
8
src/gatsby-types.d.ts
vendored
8
src/gatsby-types.d.ts
vendored
@ -571,6 +571,7 @@ type FileFieldsFilterInput = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type FileFieldsImageMeta = {
|
type FileFieldsImageMeta = {
|
||||||
|
readonly datePublished: Maybe<Scalars['String']>;
|
||||||
readonly dateTaken: Maybe<Scalars['Date']>;
|
readonly dateTaken: Maybe<Scalars['Date']>;
|
||||||
readonly dominantHue: Maybe<ReadonlyArray<Maybe<Scalars['Float']>>>;
|
readonly dominantHue: Maybe<ReadonlyArray<Maybe<Scalars['Float']>>>;
|
||||||
readonly meta: Maybe<FileFieldsImageMetaMeta>;
|
readonly meta: Maybe<FileFieldsImageMetaMeta>;
|
||||||
@ -587,6 +588,7 @@ type FileFieldsImageMeta_dateTakenArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type FileFieldsImageMetaFieldSelector = {
|
type FileFieldsImageMetaFieldSelector = {
|
||||||
|
readonly datePublished: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly dateTaken: InputMaybe<FieldSelectorEnum>;
|
readonly dateTaken: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly dominantHue: InputMaybe<FieldSelectorEnum>;
|
readonly dominantHue: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly meta: InputMaybe<FileFieldsImageMetaMetaFieldSelector>;
|
readonly meta: InputMaybe<FileFieldsImageMetaMetaFieldSelector>;
|
||||||
@ -595,6 +597,7 @@ type FileFieldsImageMetaFieldSelector = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type FileFieldsImageMetaFilterInput = {
|
type FileFieldsImageMetaFilterInput = {
|
||||||
|
readonly datePublished: InputMaybe<StringQueryOperatorInput>;
|
||||||
readonly dateTaken: InputMaybe<DateQueryOperatorInput>;
|
readonly dateTaken: InputMaybe<DateQueryOperatorInput>;
|
||||||
readonly dominantHue: InputMaybe<FloatQueryOperatorInput>;
|
readonly dominantHue: InputMaybe<FloatQueryOperatorInput>;
|
||||||
readonly meta: InputMaybe<FileFieldsImageMetaMetaFilterInput>;
|
readonly meta: InputMaybe<FileFieldsImageMetaMetaFilterInput>;
|
||||||
@ -715,6 +718,7 @@ type FileFieldsImageMetaMetaSortInput = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type FileFieldsImageMetaSortInput = {
|
type FileFieldsImageMetaSortInput = {
|
||||||
|
readonly datePublished: InputMaybe<SortOrderEnum>;
|
||||||
readonly dateTaken: InputMaybe<SortOrderEnum>;
|
readonly dateTaken: InputMaybe<SortOrderEnum>;
|
||||||
readonly dominantHue: InputMaybe<SortOrderEnum>;
|
readonly dominantHue: InputMaybe<SortOrderEnum>;
|
||||||
readonly meta: InputMaybe<FileFieldsImageMetaMetaSortInput>;
|
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 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 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 };
|
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 MasonryGallery from "../components/MasonryGallery";
|
||||||
import KeywordsPicker from "../components/KeywordsPicker";
|
import KeywordsPicker from "../components/KeywordsPicker";
|
||||||
import {
|
import {
|
||||||
|
compareDates,
|
||||||
getGalleryPageUrl,
|
getGalleryPageUrl,
|
||||||
getHelmetSafeBodyStyle,
|
getHelmetSafeBodyStyle,
|
||||||
getVibrantStyle,
|
getVibrantStyle,
|
||||||
@ -19,14 +20,25 @@ import ColorPalette from "@spectrum-icons/workflow/ColorPalette";
|
|||||||
const SORT_KEYS = {
|
const SORT_KEYS = {
|
||||||
hue: ["fields", "imageMeta", "vibrantHue"],
|
hue: ["fields", "imageMeta", "vibrantHue"],
|
||||||
rating: ["fields", "imageMeta", "meta", "Rating"],
|
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"],
|
date: ["fields", "imageMeta", "dateTaken"],
|
||||||
modified: ["fields", "imageMeta", "meta", "ModifyDate"]
|
modified: ["fields", "imageMeta", "datePublished"],
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type GalleryImage =
|
export type GalleryImage =
|
||||||
Queries.GalleryPageQueryQuery["all"]["nodes"][number];
|
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 GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
||||||
const hash =
|
const hash =
|
||||||
typeof window !== "undefined" ? window.location.hash.replace("#", "") : "";
|
typeof window !== "undefined" ? window.location.hash.replace("#", "") : "";
|
||||||
@ -130,15 +142,7 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
|||||||
const images: GalleryImage[] = React.useMemo(() => {
|
const images: GalleryImage[] = React.useMemo(() => {
|
||||||
const sort =
|
const sort =
|
||||||
sortKey === "date" || sortKey === "modified"
|
sortKey === "date" || sortKey === "modified"
|
||||||
? R.sort((node1: typeof data["all"]["nodes"][number], node2) => {
|
? R.sort((node1: typeof data["all"]["nodes"][number], node2) => smartCompareDates(sortKey, node1, 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(
|
: R.sort(
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
R.descend(R.path<GalleryImage>(SORT_KEYS[sortKey]))
|
R.descend(R.path<GalleryImage>(SORT_KEYS[sortKey]))
|
||||||
@ -166,6 +170,10 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
|||||||
}
|
}
|
||||||
}, [data, sortKey, filterKeyword]);
|
}, [data, sortKey, filterKeyword]);
|
||||||
|
|
||||||
|
const recents = React.useMemo(() => {
|
||||||
|
return R.sort((left, right) => smartCompareDates('modified', left, right), data.recents.nodes)
|
||||||
|
}, [data, 'hi'])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* @ts-ignore */}
|
{/* @ts-ignore */}
|
||||||
@ -198,7 +206,9 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="px-4 md:px-8">
|
<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>
|
</div>
|
||||||
<MasonryGallery
|
<MasonryGallery
|
||||||
aspectsByBreakpoint={{
|
aspectsByBreakpoint={{
|
||||||
@ -210,11 +220,13 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
|||||||
"2xl": 6.1,
|
"2xl": 6.1,
|
||||||
"3xl": 8,
|
"3xl": 8,
|
||||||
}}
|
}}
|
||||||
images={data.recents.nodes}
|
images={recents}
|
||||||
singleRow
|
singleRow
|
||||||
/>
|
/>
|
||||||
<div className="px-4 md:px-8 mt-4 pt-2 border-t">
|
<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>
|
||||||
<div className="flex flex-col lg:flex-row lg:items-end justify-between px-4 md:px-8 sm:mx-auto">
|
<div className="flex flex-col lg:flex-row lg:items-end justify-between px-4 md:px-8 sm:mx-auto">
|
||||||
<KeywordsPicker
|
<KeywordsPicker
|
||||||
@ -258,14 +270,14 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
|||||||
selectedKey={sortKey}
|
selectedKey={sortKey}
|
||||||
>
|
>
|
||||||
<Item key="rating">Curated</Item>
|
<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="date">Date taken</Item>
|
||||||
<Item key="hue">Hue</Item>
|
<Item key="hue">Hue</Item>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MasonryGallery
|
{/* <MasonryGallery
|
||||||
aspectsByBreakpoint={{
|
aspectsByBreakpoint={{
|
||||||
xs: 2,
|
xs: 2,
|
||||||
sm: 2,
|
sm: 2,
|
||||||
@ -283,7 +295,7 @@ const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
|||||||
filterKeyword,
|
filterKeyword,
|
||||||
}}
|
}}
|
||||||
showPalette={showPalette}
|
showPalette={showPalette}
|
||||||
/>
|
/> */}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -292,7 +304,7 @@ export const query = graphql`
|
|||||||
query GalleryPageQuery {
|
query GalleryPageQuery {
|
||||||
recents: allFile(
|
recents: allFile(
|
||||||
filter: { sourceInstanceName: { eq: "gallery" } }
|
filter: { sourceInstanceName: { eq: "gallery" } }
|
||||||
sort: { fields: { imageMeta: { meta: { ModifyDate: DESC } } } }
|
sort: { fields: { imageMeta: { datePublished: DESC } } }
|
||||||
limit: 7
|
limit: 7
|
||||||
) {
|
) {
|
||||||
...GalleryImageFile
|
...GalleryImageFile
|
||||||
@ -307,7 +319,6 @@ export const query = graphql`
|
|||||||
|
|
||||||
fragment GalleryImageFile on FileConnection {
|
fragment GalleryImageFile on FileConnection {
|
||||||
nodes {
|
nodes {
|
||||||
relativePath
|
|
||||||
base
|
base
|
||||||
childImageSharp {
|
childImageSharp {
|
||||||
fluid {
|
fluid {
|
||||||
@ -324,6 +335,7 @@ export const query = graphql`
|
|||||||
vibrantHue
|
vibrantHue
|
||||||
dominantHue
|
dominantHue
|
||||||
dateTaken
|
dateTaken
|
||||||
|
datePublished
|
||||||
meta {
|
meta {
|
||||||
Keywords
|
Keywords
|
||||||
Rating
|
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 kebabCase from 'lodash/kebabCase';
|
||||||
|
|
||||||
import React from "react";
|
|
||||||
import { HomepageImage } from "./pages";
|
import { HomepageImage } from "./pages";
|
||||||
import { GalleryImage } from "./pages/photogallery";
|
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) =>
|
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
|
// 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 =>
|
export const getAspectRatio = (image: GalleryImage | HomepageImage): number =>
|
||||||
image.childImageSharp?.fluid?.aspectRatio ?? 1;
|
image.childImageSharp?.fluid?.aspectRatio ?? 1;
|
||||||
@ -25,7 +30,10 @@ export const getCanonicalSize = (image: GalleryImage) => ({
|
|||||||
export const getRgba = (palette: string[], alpha: number) =>
|
export const getRgba = (palette: string[], alpha: number) =>
|
||||||
`rgba(${palette[0]}, ${palette[1]}, ${palette[2]}, ${alpha || 1})`;
|
`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,
|
"--muted": vibrant.Muted,
|
||||||
"--dark-muted": vibrant.DarkMuted,
|
"--dark-muted": vibrant.DarkMuted,
|
||||||
"--light-muted": vibrant.LightMuted,
|
"--light-muted": vibrant.LightMuted,
|
||||||
@ -40,10 +48,12 @@ export const getHelmetSafeBodyStyle = (style: React.CSSProperties) => {
|
|||||||
if (typeof window === "undefined") {
|
if (typeof window === "undefined") {
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
return Object.keys(style)
|
return (
|
||||||
// @ts-ignore
|
Object.keys(style)
|
||||||
.map((key) => `${key}: ${style[key]};`)
|
// @ts-ignore
|
||||||
.join("");
|
.map((key) => `${key}: ${style[key]};`)
|
||||||
|
.join("")
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const gcd = (a: number, b: number): number => {
|
const gcd = (a: number, b: number): number => {
|
||||||
@ -94,7 +104,10 @@ interface galleryPageUrlProps {
|
|||||||
sortKey: string;
|
sortKey: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getGalleryPageUrl = ({ keyword, sortKey }: galleryPageUrlProps, hash: string) => {
|
export const getGalleryPageUrl = (
|
||||||
|
{ keyword, sortKey }: galleryPageUrlProps,
|
||||||
|
hash: string
|
||||||
|
) => {
|
||||||
const url = new URL(
|
const url = new URL(
|
||||||
`${
|
`${
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
@ -121,3 +134,18 @@ export const getGalleryPageUrl = ({ keyword, sortKey }: galleryPageUrlProps, has
|
|||||||
}
|
}
|
||||||
return url.href.toString().replace(url.origin, "");
|
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;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user