Add counts to admin tag management
This commit is contained in:
parent
74bc870b3d
commit
cddabc6180
@ -1,15 +1,16 @@
|
||||
import FormWithConfirm from '@/components/FormWithConfirm';
|
||||
import SiteGrid from '@/components/SiteGrid';
|
||||
import { deletePhotoTagGloballyAction } from '@/photo/actions';
|
||||
import { getUniqueTagsCached } from '@/cache';
|
||||
import AdminGrid from '@/admin/AdminGrid';
|
||||
import { Fragment } from 'react';
|
||||
import DeleteButton from '@/admin/DeleteButton';
|
||||
import { photoQuantityText } from '@/photo';
|
||||
import { getUniqueTagsWithCountCached } from '@/cache';
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
export default async function AdminPhotosPage() {
|
||||
const tags = await getUniqueTagsCached();
|
||||
const tags = await getUniqueTagsWithCountCached();
|
||||
|
||||
return (
|
||||
<SiteGrid
|
||||
@ -17,18 +18,19 @@ export default async function AdminPhotosPage() {
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-4">
|
||||
<AdminGrid>
|
||||
{tags.map(tag =>
|
||||
{tags.map(({ tag, count }) =>
|
||||
<Fragment key={tag}>
|
||||
<div className="flex-grow w-full">
|
||||
<div>
|
||||
{tag}
|
||||
</div>
|
||||
<div />
|
||||
<div />
|
||||
<div className="text-dim">
|
||||
{photoQuantityText(count, false)}
|
||||
</div>
|
||||
<FormWithConfirm
|
||||
action={deletePhotoTagGloballyAction}
|
||||
confirmText={
|
||||
// eslint-disable-next-line max-len
|
||||
`Are you sure you want to remove "${tag}?" from all photos?`}
|
||||
`Are you sure you want to remove "${tag}?" from ${photoQuantityText(count, false)}?`}
|
||||
>
|
||||
<input type="hidden" name="tag" value={tag} />
|
||||
<DeleteButton />
|
||||
|
||||
10
src/cache/index.ts
vendored
10
src/cache/index.ts
vendored
@ -11,6 +11,7 @@ import {
|
||||
getUniqueTags,
|
||||
getPhotosTagDateRange,
|
||||
getPhotosCameraDateRange,
|
||||
getUniqueTagsWithCount,
|
||||
} from '@/services/postgres';
|
||||
import { parseCachedPhotosDates, parseCachedPhotoDates } from '@/photo';
|
||||
import { getBlobPhotoUrls, getBlobUploadUrls } from '@/services/blob';
|
||||
@ -181,6 +182,15 @@ export const getUniqueTagsCached: typeof getUniqueTags = (...args) =>
|
||||
}
|
||||
)();
|
||||
|
||||
// eslint-disable-next-line max-len
|
||||
export const getUniqueTagsWithCountCached: typeof getUniqueTagsWithCount = (...args) =>
|
||||
unstable_cache(
|
||||
() => getUniqueTagsWithCount(...args),
|
||||
[KEY_PHOTOS, KEY_TAGS], {
|
||||
tags: [KEY_PHOTOS, KEY_TAGS],
|
||||
}
|
||||
)();
|
||||
|
||||
export const getUniqueCamerasCached: typeof getUniqueCameras = (...args) =>
|
||||
unstable_cache(
|
||||
() => getUniqueCameras(...args),
|
||||
|
||||
@ -157,8 +157,10 @@ export const titleForPhoto = (photo: Photo) =>
|
||||
const photoLabelForCount = (count: number) =>
|
||||
count === 1 ? 'Photo' : 'Photos';
|
||||
|
||||
export const photoQuantityText = (count: number) =>
|
||||
`(${count} ${photoLabelForCount(count)})`;
|
||||
export const photoQuantityText = (count: number, includeParentheses = true) =>
|
||||
includeParentheses
|
||||
? `(${count} ${photoLabelForCount(count)})`
|
||||
: `${count} ${photoLabelForCount(count)}`;
|
||||
|
||||
export type PhotoDateRange = { start: string, end: string };
|
||||
|
||||
|
||||
@ -283,6 +283,17 @@ const sqlGetUniqueTags = async () => sql`
|
||||
ORDER BY tag ASC
|
||||
`.then(({ rows }) => rows.map(row => row.tag as string));
|
||||
|
||||
// Include hidden photos for admin usage
|
||||
const sqlGetUniqueTagsWithCount = async () => sql`
|
||||
SELECT DISTINCT unnest(tags) as tag, count(distinct id) as count FROM photos
|
||||
GROUP BY tag
|
||||
ORDER BY count ASC
|
||||
`.then(({ rows }) => rows.map(row => ({
|
||||
tag: row.tag as string,
|
||||
count: parseInt(row.count, 10),
|
||||
})));
|
||||
|
||||
|
||||
const sqlGetUniqueCameras = async () => sql`
|
||||
SELECT DISTINCT make||' '||model as camera, make, model FROM photos
|
||||
WHERE hidden IS NOT TRUE
|
||||
@ -390,6 +401,9 @@ export const getPhotosCameraDateRange = (camera: Camera) =>
|
||||
export const getPhotosCountIncludingHidden = () =>
|
||||
safelyQueryPhotos(sqlGetPhotosCountIncludingHidden);
|
||||
|
||||
export const getUniqueTags = () => safelyQueryPhotos(sqlGetUniqueTags);
|
||||
export const getUniqueTags = () =>
|
||||
safelyQueryPhotos(sqlGetUniqueTags);
|
||||
export const getUniqueTagsWithCount = () =>
|
||||
safelyQueryPhotos(sqlGetUniqueTagsWithCount);
|
||||
|
||||
export const getUniqueCameras = () => safelyQueryPhotos(sqlGetUniqueCameras);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user