{type === 'edit' &&
diff --git a/src/photo/form.ts b/src/photo/form.ts
index f58a2968..b4ea8580 100644
--- a/src/photo/form.ts
+++ b/src/photo/form.ts
@@ -19,6 +19,7 @@ type FormMeta = {
hideIfEmpty?: boolean
hideTemporarily?: boolean
loadingMessage?: string
+ checkbox?: boolean
};
const FORM_METADATA: Record
= {
@@ -45,6 +46,7 @@ const FORM_METADATA: Record = {
priorityOrder: { label: 'priority order' },
takenAt: { label: 'taken at' },
takenAtNaive: { label: 'taken at (naive)' },
+ hidden: { label: 'hidden', checkbox: true },
};
export const FORM_METADATA_ENTRIES =
@@ -146,5 +148,6 @@ export const convertFormDataToPhoto = (
priorityOrder: photoForm.priorityOrder
? parseFloat(photoForm.priorityOrder)
: undefined,
+ hidden: photoForm.hidden === 'true',
};
};
diff --git a/src/photo/index.ts b/src/photo/index.ts
index 31457165..b8cfdf56 100644
--- a/src/photo/index.ts
+++ b/src/photo/index.ts
@@ -43,6 +43,7 @@ export interface PhotoDbInsert extends PhotoExif {
tags?: string[]
locationName?: string
priorityOrder?: number
+ hidden?: boolean
}
// Raw db response
diff --git a/src/services/postgres.ts b/src/services/postgres.ts
index e63d38e7..d5bce43e 100644
--- a/src/services/postgres.ts
+++ b/src/services/postgres.ts
@@ -38,6 +38,7 @@ const sqlCreatePhotosTable = () =>
priority_order REAL,
taken_at TIMESTAMP WITH TIME ZONE NOT NULL,
taken_at_naive VARCHAR(255) NOT NULL,
+ hidden BOOLEAN,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
)
@@ -67,6 +68,7 @@ export const sqlInsertPhoto = (photo: PhotoDbInsert) => {
longitude,
film_simulation,
priority_order,
+ hidden,
taken_at,
taken_at_naive
)
@@ -91,6 +93,7 @@ export const sqlInsertPhoto = (photo: PhotoDbInsert) => {
${photo.longitude},
${photo.filmSimulation},
${photo.priorityOrder},
+ ${photo.hidden},
${photo.takenAt},
${photo.takenAtNaive}
)
@@ -119,6 +122,7 @@ export const sqlUpdatePhoto = (photo: PhotoDbInsert) =>
longitude=${photo.longitude},
film_simulation=${photo.filmSimulation},
priority_order=${photo.priorityOrder || null},
+ hidden=${photo.hidden},
taken_at=${photo.takenAt},
taken_at_naive=${photo.takenAtNaive},
updated_at=${(new Date()).toISOString()}
@@ -134,16 +138,28 @@ const sqlGetPhotos = (
) =>
sql`
SELECT * FROM photos
+ WHERE hidden IS NOT TRUE
ORDER BY taken_at DESC
LIMIT ${limit} OFFSET ${offset}
`;
+const sqlGetPhotosIncludingHidden = (
+ limit = PHOTO_DEFAULT_LIMIT,
+ offset = 0,
+) =>
+ sql`
+ SELECT * FROM photos
+ ORDER BY created_at DESC
+ LIMIT ${limit} OFFSET ${offset}
+ `;
+
const sqlGetPhotosSortedByCreatedAt = (
limit = PHOTO_DEFAULT_LIMIT,
offset = 0,
) =>
sql`
SELECT * FROM photos
+ WHERE hidden IS NOT TRUE
ORDER BY created_at DESC
LIMIT ${limit} OFFSET ${offset}
`;
@@ -154,6 +170,7 @@ const sqlGetPhotosSortedByPriority = (
) =>
sql`
SELECT * FROM photos
+ WHERE hidden IS NOT TRUE
ORDER BY priority_order ASC, taken_at DESC
LIMIT ${limit} OFFSET ${offset}
`;
@@ -164,7 +181,9 @@ const sqlGetPhotosByTag = (
tag: string,
) =>
sql`
- SELECT * FROM photos WHERE ${tag}=ANY(tags)
+ SELECT * FROM photos
+ WHERE ${tag}=ANY(tags)
+ AND hidden IS NOT TRUE
ORDER BY taken_at ASC
LIMIT ${limit} OFFSET ${offset}
`;
@@ -176,6 +195,7 @@ const sqlGetPhotosTakenAfterDateInclusive = (
sql`
SELECT * FROM photos
WHERE taken_at <= ${takenAt.toISOString()}
+ AND hidden IS NOT TRUE
ORDER BY taken_at DESC
LIMIT ${limit}
`;
@@ -187,6 +207,7 @@ const sqlGetPhotosTakenBeforeDate = (
sql`
SELECT * FROM photos
WHERE taken_at > ${takenAt.toISOString()}
+ AND hidden IS NOT TRUE
ORDER BY taken_at ASC
LIMIT ${limit}
`;
@@ -196,10 +217,16 @@ const sqlGetPhoto = (id: string) =>
const sqlGetPhotosCount = async () => sql`
SELECT COUNT(*) FROM photos
+ WHERE hidden IS NOT TRUE
+`.then(({ rows }) => parseInt(rows[0].count, 10));
+
+const sqlGetPhotosCountIncludingHidden = async () => sql`
+ SELECT COUNT(*) FROM photos
`.then(({ rows }) => parseInt(rows[0].count, 10));
const sqlGetUniqueTags = async () => sql`
SELECT DISTINCT unnest(tags) FROM photos
+ WHERE hidden IS NOT TRUE
`.then(({ rows }) => rows.map(row => row.unnest as string));
export type GetPhotosOptions = {
@@ -209,6 +236,7 @@ export type GetPhotosOptions = {
tag?: string
takenBefore?: Date
takenAfterInclusive?: Date
+ includeHidden?: boolean
}
const safelyQueryPhotos = async (callback: () => Promise): Promise => {
@@ -249,19 +277,25 @@ export const getPhotos = async (options: GetPhotosOptions = {}) => {
tag,
takenBefore,
takenAfterInclusive,
+ includeHidden,
} = options;
- const getPhotosSql = takenBefore
- ? () => sqlGetPhotosTakenBeforeDate(takenBefore, limit)
- : takenAfterInclusive
- ? () => sqlGetPhotosTakenAfterDateInclusive(takenAfterInclusive, limit)
- : tag
- ? () => sqlGetPhotosByTag(limit, offset, tag)
- : sortBy === 'createdAt'
- ? () => sqlGetPhotosSortedByCreatedAt(limit, offset)
- : sortBy === 'priority'
- ? () => sqlGetPhotosSortedByPriority(limit, offset)
- : () => sqlGetPhotos(limit, offset);
+ let getPhotosSql = () => sqlGetPhotos(limit, offset);
+
+ if (includeHidden) {
+ getPhotosSql = () => sqlGetPhotosIncludingHidden(limit, offset);
+ } else if (takenBefore) {
+ getPhotosSql = () => sqlGetPhotosTakenBeforeDate(takenBefore, limit);
+ } else if (takenAfterInclusive) {
+ // eslint-disable-next-line max-len
+ getPhotosSql = () => sqlGetPhotosTakenAfterDateInclusive(takenAfterInclusive, limit);
+ } else if (tag) {
+ getPhotosSql = () => sqlGetPhotosByTag(limit, offset, tag);
+ } else if (sortBy === 'createdAt') {
+ getPhotosSql = () => sqlGetPhotosSortedByCreatedAt(limit, offset);
+ } else if (sortBy === 'priority') {
+ getPhotosSql = () => sqlGetPhotosSortedByPriority(limit, offset);
+ }
return safelyQueryPhotos(getPhotosSql)
.then(({ rows }) => rows.map(parsePhotoFromDb));
@@ -278,4 +312,7 @@ export const getPhoto = async (id: string): Promise => {
export const getPhotosCount = () => safelyQueryPhotos(sqlGetPhotosCount);
+export const getPhotosCountIncludingHidden = () =>
+ safelyQueryPhotos(sqlGetPhotosCountIncludingHidden);
+
export const getUniqueTags = () => safelyQueryPhotos(sqlGetUniqueTags);
diff --git a/src/site/globals.css b/src/site/globals.css
index e1fd9045..f0f5cf7d 100644
--- a/src/site/globals.css
+++ b/src/site/globals.css
@@ -47,6 +47,10 @@
file:active:disabled:bg-white
file:hover:disabled:cursor-not-allowed
}
+ input[type=checkbox] {
+ @apply
+ rounded-md
+ }
button, .button {
@apply
cursor-pointer