Add recipes to core admin surfaces

This commit is contained in:
Sam Becker 2025-03-12 17:43:17 -05:00
parent de5f49261b
commit 3d57de3997
6 changed files with 112 additions and 10 deletions

View File

@ -0,0 +1,48 @@
import AdminChildPage from '@/components/AdminChildPage';
import { redirect } from 'next/navigation';
import { getPhotosCached } from '@/photo/cache';
import TagForm from '@/tag/TagForm';
import { PATH_ADMIN, PATH_ADMIN_TAGS, pathForTag } from '@/app/paths';
import PhotoLightbox from '@/photo/PhotoLightbox';
import { getPhotosMeta } from '@/photo/db/query';
import AdminTagBadge from '@/admin/AdminTagBadge';
const MAX_PHOTO_TO_SHOW = 6;
interface Props {
params: Promise<{ tag: string }>
}
export default async function PhotoPageEdit({
params,
}: Props) {
const { tag: tagFromParams } = await params;
const tag = decodeURIComponent(tagFromParams);
const [
{ count },
photos,
] = await Promise.all([
getPhotosMeta({ tag }),
getPhotosCached({ tag, limit: MAX_PHOTO_TO_SHOW }),
]);
if (count === 0) { redirect(PATH_ADMIN); }
return (
<AdminChildPage
backPath={PATH_ADMIN_TAGS}
backLabel="Tags"
breadcrumb={<AdminTagBadge {...{ tag, count, hideBadge: true }} />}
>
<TagForm {...{ tag, photos }}>
<PhotoLightbox
{...{ count, photos, tag }}
maxPhotosToShow={MAX_PHOTO_TO_SHOW}
moreLink={pathForTag(tag)}
/>
</TagForm>
</AdminChildPage>
);
};

View File

@ -0,0 +1,18 @@
import AdminTagTable from '@/admin/AdminTagTable';
import SiteGrid from '@/components/SiteGrid';
import { getUniqueTagsHiddenCached } from '@/photo/cache';
export default async function AdminTagsPage() {
const tags = await getUniqueTagsHiddenCached().catch(() => []);
return (
<SiteGrid
contentMain={
<div className="space-y-6">
<div className="space-y-4">
<AdminTagTable {...{ tags }} />
</div>
</div>}
/>
);
}

View File

@ -5,6 +5,7 @@ import {
PATH_ADMIN_CONFIGURATION,
PATH_ADMIN_INSIGHTS,
PATH_ADMIN_PHOTOS,
PATH_ADMIN_RECIPES,
PATH_ADMIN_TAGS,
PATH_ADMIN_UPLOADS,
PATH_GRID_INFERRED,
@ -13,7 +14,7 @@ import { useAppState } from '@/state/AppState';
import { ImCheckboxUnchecked } from 'react-icons/im';
import { IoArrowDown, IoArrowUp, IoCloseSharp } from 'react-icons/io5';
import { clsx } from 'clsx/lite';
import { TbPhoto } from 'react-icons/tb';
import { TbChecklist, TbPhoto } from 'react-icons/tb';
import { FiTag } from 'react-icons/fi';
import { BiLockAlt } from 'react-icons/bi';
import AdminAppInfoIcon from './AdminAppInfoIcon';
@ -37,6 +38,7 @@ export default function AdminAppMenu({
photosCountTotal = 0,
uploadsCount = 0,
tagsCount = 0,
recipesCount = 0,
selectedPhotoIds,
startUpload,
setSelectedPhotoIds,
@ -103,6 +105,18 @@ export default function AdminAppMenu({
});
}
if (recipesCount) {
items.push({
label: 'Manage Recipes',
annotation: `${recipesCount}`,
icon: <TbChecklist
size={17}
className="translate-x-[-0.5px] translate-y-[0.5px]"
/>,
href: PATH_ADMIN_RECIPES,
});
}
if (photosCountTotal) {
items.push({
label: isSelecting

View File

@ -2,10 +2,12 @@ import { getStorageUploadUrlsNoStore } from '@/platforms/storage/cache';
import {
getPhotosMetaCached,
getPhotosMostRecentUpdateCached,
getUniqueRecipesCached,
getUniqueTagsCached,
} from '@/photo/cache';
import {
PATH_ADMIN_PHOTOS,
PATH_ADMIN_RECIPES,
PATH_ADMIN_TAGS,
PATH_ADMIN_UPLOADS,
} from '@/app/paths';
@ -14,21 +16,24 @@ import AdminNavClient from './AdminNavClient';
export default async function AdminNav() {
const [
countPhotos,
countTags,
countUploads,
countTags,
countRecipes,
mostRecentPhotoUpdateTime,
] = await Promise.all([
getPhotosMetaCached({ hidden: 'include' })
.then(({ count }) => count)
.catch(() => 0),
getUniqueTagsCached().then(tags => tags.length)
.catch(() => 0),
getStorageUploadUrlsNoStore()
.then(urls => urls.length)
.catch(e => {
console.error(`Error getting blob upload urls: ${e}`);
return 0;
}),
getUniqueTagsCached().then(tags => tags.length)
.catch(() => 0),
getUniqueRecipesCached().then(recipes => recipes.length)
.catch(() => 0),
getPhotosMostRecentUpdateCached().catch(() => undefined),
]);
@ -55,6 +60,13 @@ export default async function AdminNav() {
count: countTags,
}); }
// Recipes
if (countRecipes > 0) { items.push({
label: 'Recipes',
href: PATH_ADMIN_RECIPES,
count: countRecipes,
}); }
return (
<AdminNavClient {...{
items,

View File

@ -8,7 +8,11 @@ import { testStorageConnection } from '@/platforms/storage';
import { APP_CONFIGURATION } from '@/app/config';
import { getStorageUploadUrlsNoStore } from '@/platforms/storage/cache';
import { getInsightsIndicatorStatus } from '@/admin/insights/server';
import { getPhotosMeta, getUniqueTags } from '@/photo/db/query';
import {
getPhotosMeta,
getUniqueTags,
getUniqueRecipes,
} from '@/photo/db/query';
export type AdminData = Awaited<ReturnType<typeof getAdminDataAction>>;
@ -17,8 +21,9 @@ export const getAdminDataAction = async () =>
const [
photosCount,
photosCountHidden,
tagsCount,
uploadsCount,
tagsCount,
recipesCount,
insightsIndicatorStatus,
] = await Promise.all([
getPhotosMeta()
@ -27,15 +32,18 @@ export const getAdminDataAction = async () =>
getPhotosMeta({ hidden: 'only' })
.then(({ count }) => count)
.catch(() => 0),
getUniqueTags()
.then(tags => tags.length)
.catch(() => 0),
getStorageUploadUrlsNoStore()
.then(urls => urls.length)
.catch(e => {
console.error(`Error getting blob upload urls: ${e}`);
return 0;
}),
getUniqueTags()
.then(tags => tags.length)
.catch(() => 0),
getUniqueRecipes()
.then(recipes => recipes.length)
.catch(() => 0),
getInsightsIndicatorStatus(),
]);
@ -50,8 +58,9 @@ export const getAdminDataAction = async () =>
photosCount,
photosCountHidden,
photosCountTotal,
tagsCount,
uploadsCount,
tagsCount,
recipesCount,
insightsIndicatorStatus,
};
});

View File

@ -41,6 +41,7 @@ export const PATH_ADMIN_PHOTOS = `${PATH_ADMIN}/photos`;
export const PATH_ADMIN_OUTDATED = `${PATH_ADMIN}/outdated`;
export const PATH_ADMIN_UPLOADS = `${PATH_ADMIN}/uploads`;
export const PATH_ADMIN_TAGS = `${PATH_ADMIN}/tags`;
export const PATH_ADMIN_RECIPES = `${PATH_ADMIN}/recipes`;
export const PATH_ADMIN_CONFIGURATION = `${PATH_ADMIN}/configuration`;
export const PATH_ADMIN_INSIGHTS = `${PATH_ADMIN}/insights`;
export const PATH_ADMIN_BASELINE = `${PATH_ADMIN}/baseline`;