fix(sidebar): use count.labels for Tags badge, drop bogus label:* query
PhotoPrism's q-DSL has no "has any label" predicate: `label:*` matches
every photo regardless of label, `label:<slug>` only matches that one
slug, and `keywords:*` behaves the same way. The prior `all:true label:*`
returned a 400 (and the earlier "drop all:true" follow-up made it return
the unfiltered library size, which then fed into tagsTotal and inflated
the parent Tags badge to ~library_size on admin sessions).
Switch labelsBadge to the precomputed `configQuery.count.labels` — the
same source the Tags sub-row's `tagCategoryCount('labels')` already
uses. The parent Tags badge now sums the exact same numbers the sub-rows
display: labels, keywords, people (distinct slugs/keywords/subjects)
plus ratings/colors (photos carrying each mark). Drop the wantScoped
short-circuit since the values are all library-wide now anyway.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -141,17 +141,12 @@
|
|||||||
const reviewCountQuery = scopedCountQuery('review', 'review:true');
|
const reviewCountQuery = scopedCountQuery('review', 'review:true');
|
||||||
const hiddenCountQuery = scopedCountQuery('hidden', 'hidden:true');
|
const hiddenCountQuery = scopedCountQuery('hidden', 'hidden:true');
|
||||||
const archivedCountQuery = scopedCountQuery('archived', 'archived:true');
|
const archivedCountQuery = scopedCountQuery('archived', 'archived:true');
|
||||||
// Labels is special: `configQuery.count.labels` is the number of distinct
|
// Labels: PhotoPrism's q-DSL has no "has any label" predicate
|
||||||
// label categories (PhotoPrism's roll-up), not the number of photos that
|
// (`label:*` matches every photo, `label:<slug>` only matches the
|
||||||
// carry a label. The Tags surface wants picture counts everywhere, so we
|
// named label), so the sidebar uses `configQuery.count.labels` — the
|
||||||
// always run a `countPhotos('label:*')` query regardless of the admin/
|
// precomputed count of distinct label slugs. Same source the
|
||||||
// BasePath shape and never fall back to the category-count.
|
// `tagCategoryCount('labels')` sub-row already uses, so the parent
|
||||||
const labelsCountQuery = createQuery<number>(() => ({
|
// Tags badge sums the same numbers the sub-rows display.
|
||||||
queryKey: ['photos', 'scoped-count', 'labels', userBasePath(), isAdminUser],
|
|
||||||
queryFn: () => countPhotos(scoped('label:*')),
|
|
||||||
enabled: isAuthenticated(),
|
|
||||||
staleTime: 60_000
|
|
||||||
}));
|
|
||||||
|
|
||||||
function bucketCount(
|
function bucketCount(
|
||||||
key: 'favorites' | 'review' | 'hidden' | 'archived',
|
key: 'favorites' | 'review' | 'hidden' | 'archived',
|
||||||
@@ -303,7 +298,7 @@
|
|||||||
const hiddenBadge = $derived(bucketCount('hidden', hiddenCountQuery));
|
const hiddenBadge = $derived(bucketCount('hidden', hiddenCountQuery));
|
||||||
const archivedBadge = $derived(bucketCount('archived', archivedCountQuery));
|
const archivedBadge = $derived(bucketCount('archived', archivedCountQuery));
|
||||||
const labelsBadge = $derived<number | undefined>(
|
const labelsBadge = $derived<number | undefined>(
|
||||||
labelsCountQuery.isPending ? undefined : labelsCountQuery.data
|
configQuery.data?.count?.labels
|
||||||
);
|
);
|
||||||
|
|
||||||
const createMut = createMutation(() => ({
|
const createMut = createMutation(() => ({
|
||||||
@@ -586,13 +581,13 @@
|
|||||||
// section/route ViewItem shape.
|
// section/route ViewItem shape.
|
||||||
];
|
];
|
||||||
|
|
||||||
// Total badge for the "Tags" header row. Rolls up labels + keywords +
|
// Total badge for the "Tags" header row. Sum of the same per-category
|
||||||
// people + ratings + colors. Labels flows through countPhotos (scoped);
|
// counts the sub-rows render (labels/people: distinct slugs/subjects,
|
||||||
// keywords/people/ratings/colors are library-wide and only contribute
|
// keywords: distinct keywords, ratings/colors: photos carrying each
|
||||||
// when we're in admin-without-BasePath mode (their sources don't scope).
|
// mark). Library-wide numbers — the badge is a quick "how many tags
|
||||||
|
// exist?" rollup, not a per-user-visible count.
|
||||||
const tagsTotal = $derived.by<number | undefined>(() => {
|
const tagsTotal = $derived.by<number | undefined>(() => {
|
||||||
if (labelsBadge === undefined) return undefined;
|
if (labelsBadge === undefined) return undefined;
|
||||||
if (wantScoped) return labelsBadge;
|
|
||||||
const keywords = keywordsQuery.data?.length ?? 0;
|
const keywords = keywordsQuery.data?.length ?? 0;
|
||||||
const people = configQuery.data?.count?.people ?? 0;
|
const people = configQuery.data?.count?.people ?? 0;
|
||||||
return labelsBadge + keywords + people + ratingsCount + colorsCount;
|
return labelsBadge + keywords + people + ratingsCount + colorsCount;
|
||||||
|
|||||||
Reference in New Issue
Block a user