From 5f2a979a114e26c551c0e836417905ba0f69609b Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sat, 19 Apr 2025 15:23:11 -0500 Subject: [PATCH] Surface granular photo sync status text --- src/admin/AdminPhotosClient.tsx | 4 ++-- src/admin/AdminPhotosSyncClient.tsx | 8 ++++---- src/admin/AdminPhotosTable.tsx | 25 ++++++++++++++++++------- src/components/Tooltip.tsx | 2 +- src/components/icons/IconBroom.tsx | 6 ++++++ src/photo/sync.ts | 16 +++++++++++++++- 6 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 src/components/icons/IconBroom.tsx diff --git a/src/admin/AdminPhotosClient.tsx b/src/admin/AdminPhotosClient.tsx index 10adbec8..07d3e251 100644 --- a/src/admin/AdminPhotosClient.tsx +++ b/src/admin/AdminPhotosClient.tsx @@ -8,12 +8,12 @@ import PathLoaderButton from '@/components/primitives/PathLoaderButton'; import { PATH_ADMIN_PHOTOS_SYNC } from '@/app/paths'; import { Photo } from '@/photo'; import { StorageListResponse } from '@/platforms/storage'; -import { LiaBroomSolid } from 'react-icons/lia'; import AdminUploadsTable from './AdminUploadsTable'; import { Timezone } from '@/utility/timezone'; import { useAppState } from '@/state/AppState'; import PhotoUploadWithStatus from '@/photo/PhotoUploadWithStatus'; import { pluralize } from '@/utility/string'; +import IconBroom from '@/components/icons/IconBroom'; export default function AdminPhotosClient({ photos, @@ -55,7 +55,7 @@ export default function AdminPhotosClient({ {photosCountOutdated > 0 && } diff --git a/src/admin/AdminPhotosSyncClient.tsx b/src/admin/AdminPhotosSyncClient.tsx index 59e19095..b55ee092 100644 --- a/src/admin/AdminPhotosSyncClient.tsx +++ b/src/admin/AdminPhotosSyncClient.tsx @@ -34,8 +34,8 @@ export default function AdminPhotosSyncClient({ - Need Sync ({photos.length}) + breadcrumb={ + Needs Sync ({photos.length}) } accessory={ Sync photos to import newer EXIF fields, improve blur data, {' '} - and leverage AI-generated text where possible + and generate AI text when configured
@@ -95,7 +95,7 @@ export default function AdminPhotosSyncClient({ hasAiTextGeneration={hasAiTextGeneration} canEdit={false} canDelete={false} - showUpdatedAt + dateType="updatedAt" />
diff --git a/src/admin/AdminPhotosTable.tsx b/src/admin/AdminPhotosTable.tsx index 0c93e850..85e82acc 100644 --- a/src/admin/AdminPhotosTable.tsx +++ b/src/admin/AdminPhotosTable.tsx @@ -15,6 +15,8 @@ import PhotoSyncButton from './PhotoSyncButton'; import DeletePhotoButton from './DeletePhotoButton'; import { Timezone } from '@/utility/timezone'; import IconHidden from '@/components/icons/IconHidden'; +import Tooltip from '@/components/Tooltip'; +import { photoHasSyncStatusText, photoSyncStatusText } from '@/photo/sync'; export default function AdminPhotosTable({ photos, @@ -22,7 +24,7 @@ export default function AdminPhotosTable({ revalidatePhoto, photoIdsSyncing = [], hasAiTextGeneration, - showUpdatedAt, + dateType = 'createdAt', canEdit = true, canDelete = true, timezone, @@ -32,7 +34,7 @@ export default function AdminPhotosTable({ revalidatePhoto?: RevalidatePhoto photoIdsSyncing?: string[] hasAiTextGeneration: boolean - showUpdatedAt?: boolean + dateType?: 'createdAt' | 'updatedAt' canEdit?: boolean canDelete?: boolean timezone?: Timezone @@ -90,11 +92,20 @@ export default function AdminPhotosTable({ 'lg:w-[50%] uppercase', 'text-dim', )}> - + {<> + + {photoHasSyncStatusText(photo) && } + }
- {children ?? } + {children ?? } ); } diff --git a/src/components/icons/IconBroom.tsx b/src/components/icons/IconBroom.tsx new file mode 100644 index 00000000..fbb7c29e --- /dev/null +++ b/src/components/icons/IconBroom.tsx @@ -0,0 +1,6 @@ +import { IconBaseProps } from 'react-icons'; +import { LiaBroomSolid } from 'react-icons/lia'; + +export default function IconBroom(props: IconBaseProps) { + return ; +} diff --git a/src/photo/sync.ts b/src/photo/sync.ts index 4fb6d14e..d28dcbce 100644 --- a/src/photo/sync.ts +++ b/src/photo/sync.ts @@ -1,5 +1,5 @@ import { MAKE_FUJIFILM } from '@/platforms/fujifilm'; -import { PhotoDb } from '.'; +import { Photo, PhotoDb } from '.'; import { AI_TEXT_AUTO_GENERATED_FIELDS } from '@/app/config'; export interface PhotoSyncStatus { @@ -34,3 +34,17 @@ export const generatePhotoSyncStatus = (photo: PhotoDb): PhotoSyncStatus => ({ isOutdated: isPhotoOutdated(photo), isMissingAiText: doesPhotoNeedAiText(photo), }); + +export const photoHasSyncStatusText = (photo: Photo) => + photo.syncStatus.isOutdated || photo.syncStatus.isMissingAiText; + +export const photoSyncStatusText = (photo: Photo) => { + const { isOutdated, isMissingAiText } = photo.syncStatus; + const text: string[] = []; + if (isOutdated) { + text.push('Outdated'); + } else if (isMissingAiText) { + text.push('Missing AI Text'); + } + return text.join(' and '); +};