Add hide/unhide to admin photo menu
This commit is contained in:
parent
489f48523b
commit
b6d5f2ebb2
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -56,6 +56,7 @@
|
||||
"trpc",
|
||||
"Turbopack",
|
||||
"Unfavoriting",
|
||||
"Unhiding",
|
||||
"unnest",
|
||||
"upstash",
|
||||
"UsKSGcbt",
|
||||
|
||||
@ -1,18 +1,24 @@
|
||||
'use client';
|
||||
|
||||
import { ComponentProps, useMemo } from 'react';
|
||||
import { pathForAdminPhotoEdit, pathForPhoto } from '@/app/paths';
|
||||
import {
|
||||
getPathComponents,
|
||||
PATH_ROOT,
|
||||
pathForAdminPhotoEdit,
|
||||
pathForTag,
|
||||
} from '@/app/paths';
|
||||
import {
|
||||
deletePhotoAction,
|
||||
syncPhotoAction,
|
||||
toggleFavoritePhotoAction,
|
||||
toggleHidePhotoAction,
|
||||
} from '@/photo/actions';
|
||||
import {
|
||||
Photo,
|
||||
deleteConfirmationTextForPhoto,
|
||||
downloadFileNameForPhoto,
|
||||
} from '@/photo';
|
||||
import { isPathFavs, isPhotoFav } from '@/tag';
|
||||
import { isPathFavs, isPhotoFav, TAG_HIDDEN } from '@/tag';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { BiTrash } from 'react-icons/bi';
|
||||
import MoreMenu from '@/components/more/MoreMenu';
|
||||
@ -27,6 +33,7 @@ import IconEdit from '@/components/icons/IconEdit';
|
||||
import { photoNeedsToBeSynced } from '@/photo/sync';
|
||||
import { KEY_COMMANDS } from '@/photo/key-commands';
|
||||
import { useAppText } from '@/i18n/state/client';
|
||||
import IconHidden from '@/components/icons/IconHidden';
|
||||
|
||||
export default function AdminPhotoMenu({
|
||||
photo,
|
||||
@ -44,10 +51,18 @@ export default function AdminPhotoMenu({
|
||||
|
||||
const appText = useAppText();
|
||||
|
||||
const isFav = isPhotoFav(photo);
|
||||
const path = usePathname();
|
||||
const pathComponents = getPathComponents(path);
|
||||
const isOnPhotoDetail = pathComponents.photoId === photo.id;
|
||||
const isFav = isPhotoFav(photo);
|
||||
const shouldRedirectFav = isPathFavs(path) && isFav;
|
||||
const shouldRedirectDelete = pathForPhoto({ photo: photo.id }) === path;
|
||||
const shouldRedirectDelete = isOnPhotoDetail;
|
||||
const redirectPathOnHideToggle = isOnPhotoDetail
|
||||
? photo.hidden
|
||||
? pathForTag(TAG_HIDDEN)
|
||||
: PATH_ROOT
|
||||
: undefined;
|
||||
|
||||
|
||||
const sectionMain = useMemo(() => {
|
||||
const items: ComponentProps<typeof MoreMenuItem>[] = [{
|
||||
@ -78,6 +93,22 @@ export default function AdminPhotoMenu({
|
||||
},
|
||||
});
|
||||
}
|
||||
items.push({
|
||||
label: photo.hidden ? appText.admin.unhide : appText.admin.hide,
|
||||
icon: <IconHidden
|
||||
size={16}
|
||||
className="translate-x-[-1px] translate-y-[1px]"
|
||||
visible={photo.hidden}
|
||||
/>,
|
||||
action: () => toggleHidePhotoAction(
|
||||
photo.id,
|
||||
redirectPathOnHideToggle,
|
||||
)
|
||||
.then(() => revalidatePhoto?.(photo.id)),
|
||||
...showKeyCommands && {
|
||||
keyCommand: KEY_COMMANDS.toggleHide,
|
||||
},
|
||||
});
|
||||
items.push({
|
||||
label: appText.admin.download,
|
||||
icon: <MdOutlineFileDownload
|
||||
@ -115,6 +146,7 @@ export default function AdminPhotoMenu({
|
||||
includeFavorite,
|
||||
isFav,
|
||||
shouldRedirectFav,
|
||||
redirectPathOnHideToggle,
|
||||
revalidatePhoto,
|
||||
]);
|
||||
|
||||
|
||||
@ -87,6 +87,8 @@ const TEXT = {
|
||||
edit: 'Edit',
|
||||
favorite: 'Favorite',
|
||||
unfavorite: 'Unfavorite',
|
||||
hide: 'Hide',
|
||||
unhide: 'Unhide',
|
||||
download: 'Download',
|
||||
sync: 'Sync',
|
||||
delete: 'Delete',
|
||||
|
||||
@ -20,6 +20,7 @@ import {
|
||||
deletePhotoAction,
|
||||
syncPhotoAction,
|
||||
toggleFavoritePhotoAction,
|
||||
toggleHidePhotoAction,
|
||||
} from './actions';
|
||||
import { isPhotoFav } from '@/tag';
|
||||
import Tooltip from '@/components/Tooltip';
|
||||
@ -66,6 +67,10 @@ export default function PhotoPrevNextActions({
|
||||
if (photo?.id) { return toggleFavoritePhotoAction(photo.id); }
|
||||
}, [photo?.id]);
|
||||
|
||||
const toggleHidden = useCallback(() => {
|
||||
if (photo?.id) { return toggleHidePhotoAction(photo.id); }
|
||||
}, [photo?.id]);
|
||||
|
||||
const navigateToPhotoEdit = useNavigateOrRunActionWithToast({
|
||||
pathOrAction: photo ? pathForAdminPhotoEdit(photo) : undefined,
|
||||
toastMessage: `Editing ${photoTitle} ...`,
|
||||
@ -81,6 +86,16 @@ export default function PhotoPrevNextActions({
|
||||
toastMessage: `Unfavoriting ${photoTitle} ...`,
|
||||
});
|
||||
|
||||
const hidePhoto = useNavigateOrRunActionWithToast({
|
||||
pathOrAction: toggleHidden,
|
||||
toastMessage: `Hiding ${photoTitle} ...`,
|
||||
});
|
||||
|
||||
const unhidePhoto = useNavigateOrRunActionWithToast({
|
||||
pathOrAction: toggleHidden,
|
||||
toastMessage: `Unhiding ${photoTitle} ...`,
|
||||
});
|
||||
|
||||
const syncPhoto = useNavigateOrRunActionWithToast({
|
||||
pathOrAction: useCallback(() => {
|
||||
if (photo?.id) { return syncPhotoAction(photo.id); }
|
||||
@ -153,6 +168,15 @@ export default function PhotoPrevNextActions({
|
||||
unfavoritePhoto();
|
||||
}
|
||||
break;
|
||||
case KEY_COMMANDS.toggleHide:
|
||||
if (isUserSignedIn && photo) {
|
||||
if (photo.hidden) {
|
||||
unhidePhoto();
|
||||
} else {
|
||||
hidePhoto();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KEY_COMMANDS.download:
|
||||
if (
|
||||
(isUserSignedIn || ALLOW_PUBLIC_DOWNLOADS) &&
|
||||
@ -182,6 +206,8 @@ export default function PhotoPrevNextActions({
|
||||
photo,
|
||||
favoritePhoto,
|
||||
unfavoritePhoto,
|
||||
hidePhoto,
|
||||
unhidePhoto,
|
||||
downloadUrl,
|
||||
downloadFileName,
|
||||
syncPhoto,
|
||||
|
||||
@ -265,6 +265,20 @@ export const toggleFavoritePhotoAction = async (
|
||||
}
|
||||
});
|
||||
|
||||
export const toggleHidePhotoAction = async (
|
||||
photoId: string,
|
||||
redirectPath?: string,
|
||||
) =>
|
||||
runAuthenticatedAdminServerAction(async () => {
|
||||
const photo = await getPhoto(photoId, true);
|
||||
if (photo) {
|
||||
photo.hidden = !photo.hidden;
|
||||
await updatePhoto(convertPhotoToPhotoDbInsert(photo));
|
||||
revalidateAllKeysAndPaths();
|
||||
}
|
||||
if (redirectPath) { redirect(redirectPath); }
|
||||
});
|
||||
|
||||
export const deletePhotosAction = async (photoIds: string[]) =>
|
||||
runAuthenticatedAdminServerAction(async () => {
|
||||
for (const photoId of photoIds) {
|
||||
|
||||
@ -7,6 +7,7 @@ export const KEY_COMMANDS = {
|
||||
edit: 'E',
|
||||
favorite: 'P',
|
||||
unfavorite: 'X',
|
||||
toggleHide: 'H',
|
||||
download: 'D',
|
||||
sync: 'S',
|
||||
search: ['⌘', 'K'],
|
||||
|
||||
Loading…
Reference in New Issue
Block a user