Refactor outdated photos header

This commit is contained in:
Sam Becker 2024-06-16 14:26:16 -05:00
parent a835e9ccdc
commit 141b7e3ed8
7 changed files with 80 additions and 58 deletions

View File

@ -5,18 +5,15 @@ import {
getUniqueTagsCached,
} from '@/photo/cache';
import {
PATH_ADMIN_OUTDATED,
PATH_ADMIN_PHOTOS,
PATH_ADMIN_TAGS,
PATH_ADMIN_UPLOADS,
} from '@/site/paths';
import AdminNavClient from './AdminNavClient';
import { OUTDATED_THRESHOLD } from '@/photo';
export default async function AdminNav() {
const [
countPhotos,
countPhotosOutdated,
countUploads,
countTags,
mostRecentPhotoUpdateTime,
@ -24,12 +21,6 @@ export default async function AdminNav() {
getPhotosMetaCached({ hidden: 'include' })
.then(({ count }) => count)
.catch(() => 0),
getPhotosMetaCached({
hidden: 'include',
takenBefore: OUTDATED_THRESHOLD,
})
.then(({ count }) => count)
.catch(() => 0),
getStorageUploadUrlsNoStore()
.then(urls => urls.length)
.catch(e => {
@ -47,13 +38,6 @@ export default async function AdminNav() {
count: countPhotos,
}];
// Outdated Photos
if (countPhotosOutdated > 0) { items.push({
label: 'Outdated',
href: PATH_ADMIN_OUTDATED,
count: countPhotosOutdated,
}); }
// Uploads
if (countUploads > 0) { items.push({
label: 'Uploads',

View File

@ -6,7 +6,7 @@ export default async function AdminLayout({
children: React.ReactNode
}) {
return (
<div className="mt-4 space-y-5">
<div className="mt-4 space-y-4">
<AdminNav />
{children}
</div>

View File

@ -1,4 +1,3 @@
import SiteGrid from '@/components/SiteGrid';
import { AI_TEXT_GENERATION_ENABLED } from '@/site/config';
import { getPhotos } from '@/photo/db/query';
import AdminPhotosTable from '@/admin/AdminPhotosTable';
@ -6,6 +5,8 @@ import { OUTDATED_THRESHOLD } from '@/photo';
import LoaderButton from '@/components/primitives/LoaderButton';
import IconGrSync from '@/site/IconGrSync';
import Banner from '@/components/Banner';
import AdminChildPage from '@/components/AdminChildPage';
import { PATH_ADMIN_PHOTOS } from '@/site/paths';
const UPDATE_BATCH_SIZE = 5;
@ -18,36 +19,44 @@ export default async function AdminPhotosPage() {
}).catch(() => []);
return (
<SiteGrid
contentMain={
<div className="space-y-4">
<Banner>
<div className="space-y-1.5">
These photos {'('}uploaded before
{' '}
{new Date(OUTDATED_THRESHOLD).toLocaleDateString()}{')'}
{' '}
may have: missing EXIF fields, inaccurate blur data,
{' '}
undesired privacy settings,
{' '}
and missing AI-generated text.
</div>
</Banner>
<LoaderButton
icon={<IconGrSync className="translate-y-[1px]" />}
hideTextOnMobile={false}
className="primary"
>
Sync oldest {UPDATE_BATCH_SIZE} photos
</LoaderButton>
<div className="space-y-4">
<AdminPhotosTable
photos={photos}
hasAiTextGeneration={AI_TEXT_GENERATION_ENABLED}
/>
<AdminChildPage
backLabel="Photos"
backPath={PATH_ADMIN_PHOTOS}
breadcrumb={`Outdated (${photos.length})`}
accessory={<LoaderButton
icon={<IconGrSync className="translate-y-[1px]" />}
hideTextOnMobile={false}
className="primary"
>
<span className="hidden sm:inline-block">
Sync oldest {UPDATE_BATCH_SIZE} photos
</span>
<span className="sm:hidden">
Sync oldest
</span>
</LoaderButton>}
>
<div className="space-y-6">
<Banner>
<div className="space-y-1.5">
These photos {'('}uploaded before
{' '}
{new Date(OUTDATED_THRESHOLD).toLocaleDateString()}{')'}
{' '}
may have: missing EXIF fields, inaccurate blur data,
{' '}
undesired privacy settings,
{' '}
and missing AI-generated text.
</div>
</div>}
/>
</Banner>
<div className="space-y-4">
<AdminPhotosTable
photos={photos}
hasAiTextGeneration={AI_TEXT_GENERATION_ENABLED}
/>
</div>
</div>
</AdminChildPage>
);
}

View File

@ -10,6 +10,10 @@ import AdminPhotosTable from '@/admin/AdminPhotosTable';
import AdminPhotosTableInfinite from
'@/admin/AdminPhotosTableInfinite';
import { getPhotosMetaCached } from '@/photo/cache';
import { IoInformationCircleOutline } from 'react-icons/io5';
import PathLoaderButton from '@/components/primitives/PathLoaderButton';
import { PATH_ADMIN_OUTDATED } from '@/site/paths';
import { OUTDATED_THRESHOLD } from '@/photo';
const DEBUG_PHOTO_BLOBS = false;
@ -20,6 +24,7 @@ export default async function AdminPhotosPage() {
const [
photos,
photosCount,
photosCountOutdated,
blobPhotoUrls,
] = await Promise.all([
getPhotos({
@ -30,6 +35,12 @@ export default async function AdminPhotosPage() {
getPhotosMetaCached({ hidden: 'include'})
.then(({ count }) => count)
.catch(() => 0),
getPhotosMetaCached({
hidden: 'include',
takenBefore: OUTDATED_THRESHOLD,
})
.then(({ count }) => count)
.catch(() => 0),
DEBUG_PHOTO_BLOBS
? getStoragePhotoUrlsNoStore()
: [],
@ -39,14 +50,28 @@ export default async function AdminPhotosPage() {
<SiteGrid
contentMain={
<div className="space-y-4">
<PhotoUpload
shouldResize={!PRO_MODE_ENABLED}
onLastUpload={async () => {
'use server';
// Update upload count in admin nav
revalidatePath('/admin', 'layout');
}}
/>
<div className="flex">
<div className="grow">
<PhotoUpload
shouldResize={!PRO_MODE_ENABLED}
onLastUpload={async () => {
'use server';
// Update upload count in admin nav
revalidatePath('/admin', 'layout');
}}
/>
</div>
{photosCountOutdated > 0 && <PathLoaderButton
path={PATH_ADMIN_OUTDATED}
icon={<IoInformationCircleOutline
size={18}
/>}
title={`${photosCountOutdated} Outdated Photos`}
hideTextOnMobile={false}
>
{photosCountOutdated}
</PathLoaderButton>}
</div>
{blobPhotoUrls.length > 0 &&
<div className={clsx(
'border-b pb-6',

View File

@ -63,8 +63,8 @@ export default function ImageInput({
isLoading={loading}
className="primary"
icon={<FiUploadCloud
size={17}
className="translate-y-[0.5px]"
size={18}
className="translate-x-[-0.5px] translate-y-[0.5px]"
/>}
aria-disabled={loading}
onClick={() => inputRef.current?.click()}

View File

@ -8,6 +8,7 @@ import LoaderButton from '@/components/primitives/LoaderButton';
export default function PathLoaderButton({
path,
icon,
title,
prefetch,
loaderDelay = 100,
shouldScroll = true,
@ -21,6 +22,7 @@ export default function PathLoaderButton({
}: {
path: string
icon?: ReactNode
title?: string
prefetch?: boolean
loaderDelay?: number
shouldScroll?: boolean
@ -58,6 +60,7 @@ export default function PathLoaderButton({
return (
<LoaderButton
icon={icon}
title={title}
className={className}
onClick={() => {
startTransition(() => {

View File

@ -99,6 +99,7 @@
text-invert
bg-gray-900 dark:bg-gray-100
disabled:text-dim
font-medium
disabled:bg-gray-100 dark:disabled:bg-gray-900
disabled:border-gray-200 disabled:dark:border-gray-700
border-gray-900 dark:border-gray-100