Review view: cause-grouped UI with actions + suggestions
Builds a dedicated /review route that mirrors /duplicates' chrome: - /review/+page.svelte mounts Toolbar + ReviewView + RightSidebar - CauseGroupCard.svelte renders one card per cause with Approve all and Archive all bulk actions plus a per-cause suggestion line - CauseBadges.svelte shows every matching cause as chips on each tile - services/adapters/review.ts fetches review:true and groups photos by primary cause; current taxonomy is low_resolution > stripped_exif > implausible_year > non_image_type > quality_other (low_resolution ranks first because it's the most actionable signal) Sidebar gains an opt-in showRelated prop that adds three RelatedStrip panels (same folder / camera / year) for the 'decide these together' workflow. LeftSidebar's Review entry switches from a section filter to a route link so /review picks up the click. PpPhoto gains the missing Resolution field PhotoPrism actually returns on list responses.
This commit is contained in:
@@ -40,11 +40,15 @@
|
||||
import { thumbUrl } from '$lib/stores/session.svelte';
|
||||
import { getMetadataSectionOpen, setMetadataSection } from '$lib/stores/view.svelte';
|
||||
import { primaryFile, type PpPhoto } from '$lib/types/photoprism';
|
||||
import RelatedStrip from './RelatedStrip.svelte';
|
||||
|
||||
interface Props {
|
||||
/** When true, append related-photo strips (folder/camera/year) below
|
||||
* Keywords. Used by the /review route; left off on the timeline. */
|
||||
showRelated?: boolean;
|
||||
photo: PpPhoto;
|
||||
}
|
||||
let { photo }: Props = $props();
|
||||
let { photo, showRelated = false }: Props = $props();
|
||||
|
||||
const qc = useQueryClient();
|
||||
|
||||
@@ -496,6 +500,35 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Related strips (only the /review route opts in). The three
|
||||
scopes match the three decisions the user usually makes here:
|
||||
"did all these come from the same shoot?" (folder), "same
|
||||
camera, EXIF-stripped together?" (camera), "right year?"
|
||||
(year). Strips with zero hits collapse silently. -->
|
||||
{#if showRelated}
|
||||
<div class="space-y-2 border-t border-border pt-2">
|
||||
<RelatedStrip
|
||||
title="Same folder"
|
||||
q={`path:"${photo.Path ?? ''}"`}
|
||||
excludeUid={photo.UID}
|
||||
/>
|
||||
{#if photo.CameraID && photo.CameraID !== 1}
|
||||
<RelatedStrip
|
||||
title="Same camera"
|
||||
q={`camera:${photo.CameraID}`}
|
||||
excludeUid={photo.UID}
|
||||
/>
|
||||
{/if}
|
||||
{#if photo.Year}
|
||||
<RelatedStrip
|
||||
title="Same year"
|
||||
q={`year:${photo.Year}`}
|
||||
excludeUid={photo.UID}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Auto-labels (PhotoPrism's TensorFlow classifier output). Read-only:
|
||||
editing labels requires re-indexing on PhotoPrism's side. The
|
||||
dashed border + lower contrast distinguishes them from the user-
|
||||
|
||||
Reference in New Issue
Block a user