Skip to content

Commit

Permalink
Removed sortDate which obscures the fact that some photos aren't dated.
Browse files Browse the repository at this point in the history
Now using `photoDate` to sort and group photos by date.

photoDate can be missing for undated photos so they are now being
groupe so they can easily be identified.
  • Loading branch information
ashleydavis committed Jul 28, 2024
1 parent 1dff1ef commit e3662c6
Show file tree
Hide file tree
Showing 19 changed files with 63 additions and 41 deletions.
3 changes: 1 addition & 2 deletions backend/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ const dateFields = [
"fileDate",
"photoDate",
"uploadDate",
"sortDate",
];

//
Expand Down Expand Up @@ -362,7 +361,7 @@ export async function createServer(now: () => Date, db: Db, storage: IStorage) {
const collection = db.collection(collectionName);
const records = await collection.find({ setId })
.sort({
sortDate: -1, // Reverse chronological order.
photoDate: -1, // Reverse chronological order.
})
.skip(skip)
.limit(limit)
Expand Down
2 changes: 1 addition & 1 deletion electron/frontend/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function GallerySetup() {
return (
<AssetDatabaseProvider>
<GalleryContextProvider
sortFn={asset => dayjs(asset.sortDate).toDate()}
sortFn={asset => asset.photoDate ? dayjs(asset.photoDate).toDate() : undefined}
>
<UploadContextProvider>
<ScanContextProvider>
Expand Down
1 change: 0 additions & 1 deletion electron/frontend/src/context/scan-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ export function ScanContextProvider({ children }: IProps) {
contentType: fileDetails.contentType,
hash,
fileDate: dayjs(fileDate).toISOString(),
sortDate: dayjs(fileDate).toISOString(),
uploadDate: dayjs().toISOString(),
setId: "this doesn't make sense here",
userId: user!._id,
Expand Down
1 change: 1 addition & 0 deletions electron/frontend/src/pages/computer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export function ComputerPage() {
>
<Gallery
targetRowHeight={150}
getHeadings={undefined}
/>
</GalleryContextProvider>
</div>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function GallerySetup() {
return (
<AssetDatabaseProvider>
<GalleryContextProvider
sortFn={galleryItem => dayjs(galleryItem.sortDate).toDate()}
sortFn={asset => asset.photoDate ? dayjs(asset.photoDate).toDate() : undefined}
>
<UploadContextProvider>
<Main />
Expand Down
2 changes: 1 addition & 1 deletion mobile/frontend/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function GallerySetup() {
<ScanContextProvider>
<AssetDatabaseProvider>
<GalleryContextProvider
sortFn={asset => dayjs(asset.sortDate).toDate()}
sortFn={asset => asset.photoDate ? dayjs(asset.photoDate).toDate() : undefined}
>
<UploadContextProvider>
<Main
Expand Down
1 change: 0 additions & 1 deletion mobile/frontend/src/context/scan-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ export function ScanContextProvider({ children }: IProps) {
// origFileName: file.path,
// hash,
// fileDate: dayjs().toISOString(),
// sortDate: dayjs().toISOString(),
// uploadDate: dayjs().toISOString(),
// url: dataURL,
// makeFullUrl: async () => {
Expand Down
5 changes: 0 additions & 5 deletions packages/defs/src/lib/asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,6 @@ export interface IAsset {
//
photoDate?: string;

//
// Date by which to sort the asset.
//
sortDate: string;

//
/// The date the asset was uploaded.
//
Expand Down
10 changes: 8 additions & 2 deletions packages/user-interface/src/components/gallery-layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect, useRef, useState } from "react";
import { IGalleryItem, IGalleryRow } from "../lib/gallery-item";
import { useGallery } from "../context/gallery-context";
import { IGalleryLayout, computePartialLayout } from "../lib/create-layout";
import { GetHeadingsFn, IGalleryLayout, computePartialLayout } from "../lib/create-layout";
import { GalleryImage } from "./gallery-image";
import { throttle } from "lodash";

Expand Down Expand Up @@ -152,6 +152,11 @@ export interface IGalleryLayoutProps {
// Event raised when an item in the gallery has been clicked.
//
onItemClick: ItemClickFn | undefined;

//
// Gets headings from a gallery item.
//
getHeadings?: GetHeadingsFn;
}

//
Expand All @@ -161,6 +166,7 @@ export function GalleryLayout({
galleryWidth = 600,
targetRowHeight = 150,
onItemClick = undefined,
getHeadings,
}: IGalleryLayoutProps) {

const { items } = useGallery();
Expand All @@ -177,7 +183,7 @@ export function GalleryLayout({
// Computes the gallery layout.
//
useEffect(() => {
setLayout(computePartialLayout(undefined, items, galleryWidth, targetRowHeight));
setLayout(computePartialLayout(undefined, items, galleryWidth, targetRowHeight, getHeadings));
}, [items, galleryWidth, targetRowHeight]);

//
Expand Down
11 changes: 9 additions & 2 deletions packages/user-interface/src/components/gallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import useResizeObserver from "@react-hook/resize-observer";
import { useGallery } from "../context/gallery-context";
import { GalleryItemContextProvider } from "../context/gallery-item-context";
import { AssetView } from "./asset-view";
import { GetHeadingsFn } from "../lib/create-layout";

//
// Adds a small gutter on the right hand side of the gallery for some whitespace.
Expand All @@ -15,12 +16,17 @@ export interface IGalleryProps {
// The target height for rows in the gallery.
//
targetRowHeight: number;

//
// Gets headings from a gallery item.
//
getHeadings?: GetHeadingsFn;
}

//
// A photo gallery component.
//
export function Gallery({ targetRowHeight }: IGalleryProps) {
export function Gallery({ targetRowHeight, getHeadings }: IGalleryProps) {

//
// The interface to the gallery.
Expand Down Expand Up @@ -75,7 +81,8 @@ export function Gallery({ targetRowHeight }: IGalleryProps) {
onItemClick={item => {
setOpenAssetView(true)
setSelectedItemId(item._id);
}}
}}
getHeadings={getHeadings}
/>

{selectedItemId &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ export function AssetDatabaseProvider({ children }: IAssetDatabaseProviderProps)
location: asset.location,
fileDate: asset.fileDate,
photoDate: asset.photoDate,
sortDate: asset.sortDate,
uploadDate: dayjs().toISOString(),
properties: asset.properties,
labels: asset.labels,
Expand Down
24 changes: 19 additions & 5 deletions packages/user-interface/src/context/gallery-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -518,14 +518,28 @@ export function GalleryContextProvider({ sortFn, children }: IGalleryContextProv
const sorted = items.slice();
if (sortFn !== undefined) {
sorted.sort((a, b) => { // Warning: this mutates the array we just cloned.
if (sortFn(a) < sortFn(b)) {
return 1;
const sortA = sortFn(a);
const sortB = sortFn(b);
if (sortA === undefined) {
if (sortB === undefined) {
return 0; // Equal.
}
else {
return -1; // a has no sort value, so it comes first.
}
}
else if (a.sortDate > b.sortDate) {
return -1;
else if (sortB === undefined) {
return 1; // b has no sort value, so it comes first.
}

if (sortA < sortB) {
return 1; // a comes after b.
}
else if (sortA > sortB) {
return -1; // a comes before b.
}
else {
return 0;
return 0; // a and b are equal.
}
});
}
Expand Down
1 change: 0 additions & 1 deletion packages/user-interface/src/context/upload-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,6 @@ export function UploadContextProvider({ children }: IProps) {
location,
fileDate: nextUpload.fileDate,
photoDate,
sortDate: photoDate || nextUpload.fileDate,
uploadDate: dayjs().toISOString(),
properties,
labels,
Expand Down
12 changes: 7 additions & 5 deletions packages/user-interface/src/lib/create-layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,15 @@ function headingsMatch(headingsA: string[], headingsB: string[]): boolean {
return true;
}

//
// Gets headings from an item.
//
export type GetHeadingsFn = (item: IGalleryItem) => string[];

//
// Creates or updates a row-based layout for items in the gallery.
//
export function computePartialLayout(layout: IGalleryLayout | undefined, items: IGalleryItem[], galleryWidth: number, targetRowHeight: number): IGalleryLayout {
export function computePartialLayout(layout: IGalleryLayout | undefined, items: IGalleryItem[], galleryWidth: number, targetRowHeight: number, getHeadings: GetHeadingsFn | undefined): IGalleryLayout {

if (!layout) {
layout = {
Expand Down Expand Up @@ -92,10 +97,7 @@ export function computePartialLayout(layout: IGalleryLayout | undefined, items:
// Compute headings for the item.
// TODO: This should be customizable. Heading could also be location (country, city, suburb, etc) or something else.
//
const itemHeadings = [
dayjs(item.sortDate).format("MMMM"),
dayjs(item.sortDate).format("YYYY"),
];
const itemHeadings = getHeadings ? getHeadings(item) : [];

if (curRow.items.length > 0) {
if (curRow.width + computedWidth > galleryWidth) {
Expand Down
5 changes: 0 additions & 5 deletions packages/user-interface/src/lib/gallery-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,6 @@ export interface IGalleryItem {
//
photoDate?: string;

//
/// The date the asset is sorted by in the backend.
//
sortDate: string;

//
/// The date the asset was uploaded.
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,10 @@ export function AssetInfo({ open, onClose, onDeleted }: IAssetInfoProps) {
</div>
<div className="flex flex-col ml-3">
<div>
{dayjs(asset.sortDate).format("MMM D, YYYY")}
{asset.photoDate ? dayjs(asset.photoDate).format("MMM D, YYYY") : "No date" }
</div>
<div className="text-sm flex flex-row" >
{dayjs(asset.sortDate).format("HH:mm")}
{asset.photoDate ? dayjs(asset.photoDate).format("HH:mm") : "No time" }
</div>
</div>
</div>
Expand Down
8 changes: 8 additions & 0 deletions packages/user-interface/src/pages/gallery/gallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useParams } from "react-router-dom";
import { useApp } from "../../context/app-context";
import { useGallery } from "../../context/gallery-context";
import { useAssetDatabase } from "../../context/asset-database-source";
import dayjs from "dayjs";

export interface IGalleryPageProps {
}
Expand All @@ -30,6 +31,13 @@ export function GalleryPage({}: IGalleryPageProps) {
<Gallery
key={setId} // Resets the gallery completely when the set changes. Simplest way to reset the scroll of the gallery.
targetRowHeight={150}
getHeadings={item => item.photoDate
? [
dayjs(item.photoDate).format("MMMM"),
dayjs(item.photoDate).format("YYYY"),
]
: [ "Undated" ]
}
/>
</div>
);
Expand Down
10 changes: 5 additions & 5 deletions packages/user-interface/src/test/lib/layout.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ describe("layout", () => {

const galleryWidth = 600;
const targetRowHeight = 200;
const rows = computePartialLayout(undefined, [], galleryWidth, targetRowHeight);
const rows = computePartialLayout(undefined, [], galleryWidth, targetRowHeight, undefined);
expect(rows).toEqual({
galleryHeight: 0,
rows: []
Expand All @@ -25,7 +25,7 @@ describe("layout", () => {

const galleryWidth = 600;
const targetRowHeight = 200;
const layout = computePartialLayout(undefined, gallery, galleryWidth, targetRowHeight);
const layout = computePartialLayout(undefined, gallery, galleryWidth, targetRowHeight, undefined);

expect(layout.rows.length).toBe(2);

Expand Down Expand Up @@ -56,7 +56,7 @@ describe("layout", () => {

const galleryWidth = 600;
const targetRowHeight = 200;
const layout = computePartialLayout(undefined, items, galleryWidth, targetRowHeight);
const layout = computePartialLayout(undefined, items, galleryWidth, targetRowHeight, undefined);
expect(layout.rows.length).toBe(2);

const row = layout.rows[1];
Expand Down Expand Up @@ -88,7 +88,7 @@ describe("layout", () => {

const galleryWidth = 600;
const targetRowHeight = 200;
const layout = computePartialLayout(undefined, items, galleryWidth, targetRowHeight);
const layout = computePartialLayout(undefined, items, galleryWidth, targetRowHeight, undefined);
expect(layout.rows.length).toBe(3);

const firstRow = layout.rows[1];
Expand Down Expand Up @@ -120,7 +120,7 @@ describe("layout", () => {

const galleryWidth = 600;
const targetRowHeight = 200;
const layout = computePartialLayout(undefined, items, galleryWidth, targetRowHeight);
const layout = computePartialLayout(undefined, items, galleryWidth, targetRowHeight, undefined);
const firstRow = layout.rows[1];
expect(firstRow.items.length).toBe(2);
expect(firstRow.height).toBeGreaterThan(targetRowHeight);
Expand Down
1 change: 0 additions & 1 deletion tools/upload/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,6 @@ async function uploadAsset(filePath: string, actualFilePath: string | undefined,
location,
fileDate,
photoDate: assetDetails.photoDate,
sortDate: assetDetails.photoDate || fileDate,
uploadDate: dayjs().toISOString(),
properties,
labels,
Expand Down

0 comments on commit e3662c6

Please sign in to comment.