Dismiss admin banner when times are no longer recent

This commit is contained in:
Sam Becker 2024-04-28 10:55:27 -05:00
parent 54cd4de52b
commit 348b2ecc80
6 changed files with 35 additions and 23 deletions

View File

@ -16,7 +16,7 @@ export default async function AdminNav() {
countPhotos,
countUploads,
countTags,
mostRecentUpdate,
mostRecentPhotoUpdateTime,
] = await Promise.all([
getPhotosCountIncludingHiddenCached().catch(() => 0),
getStorageUploadUrlsNoStore()
@ -53,6 +53,6 @@ export default async function AdminNav() {
if (countTags > 0) { items.push(navItemTags); }
return (
<AdminNavClient {...{ items, mostRecentUpdate }} />
<AdminNavClient {...{ items, mostRecentPhotoUpdateTime }} />
);
}

View File

@ -12,31 +12,43 @@ import { clsx } from 'clsx/lite';
import { differenceInMinutes } from 'date-fns';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { useMemo } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { BiCog } from 'react-icons/bi';
import { FaRegClock } from 'react-icons/fa';
const RECENCY_THRESHOLD = 5;
const areTimesRecent = (dates: Date[]) => dates
.some(date => differenceInMinutes(new Date(), date) < 5);
export default function AdminNavClient({
items,
mostRecentUpdate,
mostRecentPhotoUpdateTime,
}: {
items: {
label: string,
href: string,
count: number,
}[]
mostRecentUpdate?: Date
mostRecentPhotoUpdateTime?: Date
}) {
const pathname = usePathname();
const { adminUpdates = [] } = useAppState();
const { adminUpdateTimes = [] } = useAppState();
const shouldShowBanner = useMemo(() =>
((mostRecentUpdate ? [mostRecentUpdate] : []).concat(adminUpdates))
.some(date => differenceInMinutes(new Date(), date) < RECENCY_THRESHOLD)
, [mostRecentUpdate, adminUpdates]);
const updateTimes = useMemo(() =>
(mostRecentPhotoUpdateTime ? [mostRecentPhotoUpdateTime] : [])
.concat(adminUpdateTimes)
, [mostRecentPhotoUpdateTime, adminUpdateTimes]);
const [shouldShowBanner, setShouldShowBanner] =
useState(areTimesRecent(updateTimes));
useEffect(() => {
// Check every 10 seconds if update times are recent
const timeout = setTimeout(() =>
setShouldShowBanner(areTimesRecent(updateTimes))
, 10_000);
return () => clearTimeout(timeout);
}, [updateTimes]);
return (
<SiteGrid

View File

@ -20,7 +20,7 @@ export default function AdminPhotoMenuClient({
photo: Photo
revalidatePhoto?: RevalidatePhoto
}) {
const { isUserSignedIn, addAdminUpdate } = useAppState();
const { isUserSignedIn, registerAdminUpdate } = useAppState();
const isFav = isPhotoFav(photo);
const path = usePathname();
@ -64,7 +64,7 @@ export default function AdminPhotoMenuClient({
shouldRedirectDelete,
).then(() => {
revalidatePhoto?.(photo.id, true);
addAdminUpdate?.();
registerAdminUpdate?.();
});
}
},

View File

@ -17,15 +17,15 @@ export default function DeleteButton (
...rest
} = props;
const { invalidateSwr, addAdminUpdate } = useAppState();
const { invalidateSwr, registerAdminUpdate } = useAppState();
const onFormSubmit = useCallback(() => {
onFormSubmitProps?.();
if (clearLocalState) {
invalidateSwr?.();
addAdminUpdate?.();
registerAdminUpdate?.();
}
}, [onFormSubmitProps, clearLocalState, invalidateSwr, addAdminUpdate]);
}, [onFormSubmitProps, clearLocalState, invalidateSwr, registerAdminUpdate]);
return <SubmitButtonWithStatus
{...rest}

View File

@ -16,8 +16,8 @@ export interface AppStateContext {
setShouldRespondToKeyboardCommands?: Dispatch<SetStateAction<boolean>>
isCommandKOpen?: boolean
setIsCommandKOpen?: Dispatch<SetStateAction<boolean>>
adminUpdates?: Date[]
addAdminUpdate?: () => void
adminUpdateTimes?: Date[]
registerAdminUpdate?: () => void
shouldShowBaselineGrid?: boolean
setShouldShowBaselineGrid?: Dispatch<SetStateAction<boolean>>
clearNextPhotoAnimation?: () => void

View File

@ -26,7 +26,7 @@ export default function AppStateProvider({
useState(true);
const [isCommandKOpen, setIsCommandKOpen] =
useState(false);
const [adminUpdates, setAdminUpdates] = useState<Date[]>([]);
const [adminUpdateTimes, setAdminUpdateTimes] = useState<Date[]>([]);
const [shouldShowBaselineGrid, setShouldShowBaselineGrid] =
useState(false);
@ -35,8 +35,8 @@ export default function AppStateProvider({
const { data } = useSWR('getCurrentUser', getCurrentUser);
useEffect(() => setUserEmail(data?.email ?? undefined), [data]);
const addAdminUpdate = useCallback(() =>
setAdminUpdates(updates => [...updates, new Date()])
const registerAdminUpdate = useCallback(() =>
setAdminUpdateTimes(updates => [...updates, new Date()])
, []);
useEffect(() => {
@ -60,8 +60,8 @@ export default function AppStateProvider({
setShouldRespondToKeyboardCommands,
isCommandKOpen,
setIsCommandKOpen,
adminUpdates,
addAdminUpdate,
adminUpdateTimes,
registerAdminUpdate,
shouldShowBaselineGrid,
setShouldShowBaselineGrid,
clearNextPhotoAnimation: () => setNextPhotoAnimation?.(undefined),