From 21ed815cbada292b809df98661d294cb88b73933 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Fri, 7 Mar 2025 08:39:40 -0800 Subject: [PATCH] Add guidance around sync buttons --- app/admin/photos/page.tsx | 6 ++- src/admin/AdminPhotosClient.tsx | 9 ++-- src/admin/ExifCaptureButton.tsx | 39 ++++++++------ src/admin/PhotoSyncButton.tsx | 53 ++++++++++--------- .../primitives/TooltipPrimitive.tsx | 26 ++++++--- 5 files changed, 78 insertions(+), 55 deletions(-) diff --git a/app/admin/photos/page.tsx b/app/admin/photos/page.tsx index 196f4fcc..5749df9b 100644 --- a/app/admin/photos/page.tsx +++ b/app/admin/photos/page.tsx @@ -6,7 +6,10 @@ import { revalidatePath } from 'next/cache'; import { cookies } from 'next/headers'; import { TIMEZONE_COOKIE_NAME } from '@/utility/timezone'; import { getOutdatedPhotosCount } from '@/photo/db/query'; -import { PRESERVE_ORIGINAL_UPLOADS } from '@/app/config'; +import { + AI_TEXT_GENERATION_ENABLED, + PRESERVE_ORIGINAL_UPLOADS, +} from '@/app/config'; export const maxDuration = 60; @@ -45,6 +48,7 @@ export default async function AdminPhotosPage() { photosCount, photosCountOutdated, shouldResize: !PRESERVE_ORIGINAL_UPLOADS, + hasAiTextGeneration: AI_TEXT_GENERATION_ENABLED, onLastUpload: async () => { 'use server'; // Update upload count in admin nav diff --git a/src/admin/AdminPhotosClient.tsx b/src/admin/AdminPhotosClient.tsx index 65789ba4..c7df2fe0 100644 --- a/src/admin/AdminPhotosClient.tsx +++ b/src/admin/AdminPhotosClient.tsx @@ -2,9 +2,6 @@ import { clsx } from 'clsx/lite'; import SiteGrid from '@/components/SiteGrid'; -import { - AI_TEXT_GENERATION_ENABLED, -} from '@/app/config'; import AdminPhotosTable from '@/admin/AdminPhotosTable'; import AdminPhotosTableInfinite from '@/admin/AdminPhotosTableInfinite'; import PathLoaderButton from '@/components/primitives/PathLoaderButton'; @@ -23,6 +20,7 @@ export default function AdminPhotosClient({ photosCountOutdated, blobPhotoUrls, shouldResize, + hasAiTextGeneration, onLastUpload, infiniteScrollInitial, infiniteScrollMultiple, @@ -33,6 +31,7 @@ export default function AdminPhotosClient({ photosCountOutdated: number blobPhotoUrls: StorageListResponse shouldResize: boolean + hasAiTextGeneration: boolean onLastUpload: () => Promise infiniteScrollInitial: number infiniteScrollMultiple: number @@ -89,14 +88,14 @@ export default function AdminPhotosClient({
{photosCount > photos.length && }
diff --git a/src/admin/ExifCaptureButton.tsx b/src/admin/ExifCaptureButton.tsx index 780de1c4..cd867398 100644 --- a/src/admin/ExifCaptureButton.tsx +++ b/src/admin/ExifCaptureButton.tsx @@ -2,6 +2,7 @@ import LoaderButton from '@/components/primitives/LoaderButton'; import SubmitButtonWithStatus from '@/components/SubmitButtonWithStatus'; +import Tooltip from '@/components/Tooltip'; import { getExifDataAction } from '@/photo/actions'; import { PhotoFormData } from '@/photo/form'; import { clsx } from 'clsx/lite'; @@ -18,23 +19,27 @@ export default function ExifCaptureButton({ const [isLoading, setIsLoading] = useState(false); return ( - { - setIsLoading(true); - getExifDataAction(photoUrl) - .then(onSync) - .finally(() => setIsLoading(false)); - }} - icon={} + - EXIF - + { + setIsLoading(true); + getExifDataAction(photoUrl) + .then(onSync) + .finally(() => setIsLoading(false)); + }} + icon={} + > + EXIF + + ); } diff --git a/src/admin/PhotoSyncButton.tsx b/src/admin/PhotoSyncButton.tsx index e61ae875..03f77988 100644 --- a/src/admin/PhotoSyncButton.tsx +++ b/src/admin/PhotoSyncButton.tsx @@ -3,6 +3,7 @@ import { syncPhotoAction } from '@/photo/actions'; import IconGrSync from '@/app/IconGrSync'; import { toastSuccess } from '@/toast'; import { ComponentProps, useState } from 'react'; +import Tooltip from '@/components/Tooltip'; export default function PhotoSyncButton({ photoId, @@ -33,29 +34,33 @@ export default function PhotoSyncButton({ confirmText.push('This action cannot be undone.'); return ( - } - onClick={() => { - if (!shouldConfirm || window.confirm(confirmText.join(' '))) { - setIsSyncing(true); - syncPhotoAction(photoId) - .then(() => { - onSyncComplete?.(); - if (shouldToast) { - toastSuccess(photoTitle - ? `"${photoTitle}" data synced` - : 'Data synced'); - } - }) - .finally(() => setIsSyncing(false)); - } - }} - isLoading={isSyncing || isSyncingExternal} - disabled={disabled} - /> + + } + onClick={() => { + if (!shouldConfirm || window.confirm(confirmText.join(' '))) { + setIsSyncing(true); + syncPhotoAction(photoId) + .then(() => { + onSyncComplete?.(); + if (shouldToast) { + toastSuccess(photoTitle + ? `"${photoTitle}" data synced` + : 'Data synced'); + } + }) + .finally(() => setIsSyncing(false)); + } + }} + isLoading={isSyncing || isSyncingExternal} + disabled={disabled} + /> + ); } diff --git a/src/components/primitives/TooltipPrimitive.tsx b/src/components/primitives/TooltipPrimitive.tsx index ad88a9cc..c63401d1 100644 --- a/src/components/primitives/TooltipPrimitive.tsx +++ b/src/components/primitives/TooltipPrimitive.tsx @@ -10,14 +10,16 @@ import useClickInsideOutside from '@/utility/useClickInsideOutside'; export default function TooltipPrimitive({ content, className, - classNameTrigger, + classNameTrigger: classNameTriggerProp, sideOffset = 10, + supportMobile = true, children, }: { content?: ReactNode className?: string classNameTrigger?: string sideOffset?: number + supportMobile?: boolean children: ReactNode }) { const refTrigger = useRef(null); @@ -27,6 +29,8 @@ export default function TooltipPrimitive({ const supportsHover = useSupportsHover(); + const includeButton = supportMobile && !supportsHover; + useClickInsideOutside({ htmlElements: [refTrigger, refContent], onClickOutside: () => { @@ -34,17 +38,23 @@ export default function TooltipPrimitive({ }, }); + const classNameTrigger = clsx('link cursor-default', classNameTriggerProp); + return ( - + {includeButton + ? + : + {children} + }