From e8fdddf08edffcdfe8dc6bb96dd50a931bc752f7 Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Mon, 14 Aug 2023 17:43:13 -0400 Subject: [PATCH] feat: persist people rules --- web/src/api/api.ts | 2 +- .../rule-selection-form/face-selection.svelte | 20 ++--- .../rule-selection-form.svelte | 73 +++++++------------ .../assets/thumbnail/face-thumbnail.svelte | 4 +- .../shared-components/base-modal.svelte | 6 +- .../(user)/albums/[albumId]/+page.svelte | 46 +++++++++--- 6 files changed, 75 insertions(+), 76 deletions(-) diff --git a/web/src/api/api.ts b/web/src/api/api.ts index da649d7e2..753fbf596 100644 --- a/web/src/api/api.ts +++ b/web/src/api/api.ts @@ -38,7 +38,7 @@ export class ImmichApi { public personApi: PersonApi; public systemConfigApi: SystemConfigApi; public userApi: UserApi; - + private config: Configuration; constructor(params: ConfigurationParameters) { diff --git a/web/src/lib/components/album-page/rule-selection-form/face-selection.svelte b/web/src/lib/components/album-page/rule-selection-form/face-selection.svelte index 670861c55..849d346c4 100644 --- a/web/src/lib/components/album-page/rule-selection-form/face-selection.svelte +++ b/web/src/lib/components/album-page/rule-selection-form/face-selection.svelte @@ -6,17 +6,15 @@ import Button from '$lib/components/elements/buttons/button.svelte'; import FaceThumbnail from '$lib/components/assets/thumbnail/face-thumbnail.svelte'; - export let selectedPeople: Set = new Set(); + export let selectedIds: string[] = []; let people: PersonResponseDto[] = []; let newPeople: PersonResponseDto[] = []; - const dispatch = createEventDispatcher<{ close: void; confirm: { people: PersonResponseDto[] } }>(); + const dispatch = createEventDispatcher<{ close: void; confirm: PersonResponseDto[] }>(); onMount(async () => { const { data } = await api.personApi.getAllPeople({ withHidden: false }); - - const selectedPeopleIds = Array.from(selectedPeople).map((p) => p.id); - people = data.people.filter((p) => !selectedPeopleIds.includes(p.id)); + people = data.people.filter(({ id }) => !selectedIds.includes(id)); }); const handleSelection = (e: CustomEvent<{ person: PersonResponseDto }>) => { @@ -28,15 +26,11 @@ newPeople = [...newPeople, person]; } }; - - const onConfirmClicked = () => { - dispatch('confirm', { people: newPeople }); - }; dispatch('close')}> -

+

{#if newPeople.length === 0} Select faces {:else if newPeople.length === 1} @@ -48,12 +42,14 @@ - +

- {#each people as person} + {#each people as person (person.id)} import BaseModal from '$lib/components/shared-components/base-modal.svelte'; - import { createEventDispatcher, onMount } from 'svelte'; - import { RuleKey, type AlbumResponseDto, type PersonResponseDto, api } from '@api'; + import { PersonResponseDto, RuleKey, RuleResponseDto, api } from '@api'; + import { createEventDispatcher } from 'svelte'; import Plus from 'svelte-material-icons/Plus.svelte'; + import { fly } from 'svelte/transition'; import Button from '../../elements/buttons/button.svelte'; import Portal from '../../shared-components/portal/portal.svelte'; import FaceSelection from './face-selection.svelte'; - import { fly } from 'svelte/transition'; - export let album: AlbumResponseDto; + export let rules: RuleResponseDto[] = []; let peopleSelection = false; let locationSelection = false; - let selectedPeople = new Set(); - const dispatch = createEventDispatcher<{ close: void }>(); + $: peopleRules = rules.filter((rule) => rule.key === RuleKey.Person); - const handlePeopleSelected = async (e: CustomEvent<{ people: PersonResponseDto[] }>) => { + const dispatch = createEventDispatcher<{ + submit: RuleResponseDto[]; + close: void; + }>(); + + const handleSelectPeople = async (people: PersonResponseDto[]) => { + rules = [...rules, ...people.map((person) => ({ key: RuleKey.Person, value: person.id } as RuleResponseDto))]; peopleSelection = false; - const people = e.detail.people; - - selectedPeople = new Set([...selectedPeople, ...people]); }; - const handleRemovePerson = (person: PersonResponseDto) => { - const temp = new Set(selectedPeople); - temp.delete(person); - selectedPeople = temp; + const handleRemoveRule = async (rule: RuleResponseDto) => { + rules = rules.filter((_rule) => rule !== _rule); }; - - const updateRule = async () => { - // for (const person of people) { - // const { data } = await api.ruleApi.createRule({ - // createRuleDto: { - // albumId: album.id, - // key: RuleKey.Person, - // value: person.id, - // }, - // }); - // album.rules = [...album.rules, data]; - // } - }; - - onMount(async () => { - const addedPeople: PersonResponseDto[] = []; - - for (const rule of album.rules) { - if (rule.key === RuleKey.Person) { - const personId = String(rule.value); - const { data } = await api.personApi.getPerson({ id: personId }); - addedPeople.push(data); - } - } - - selectedPeople = new Set([...selectedPeople, ...addedPeople]); - });
-

Automatically add photos

+

Automatically add photos

@@ -75,9 +48,9 @@

PEOPLE

- {#each selectedPeople as person (person.id)} - {/each} @@ -122,7 +95,7 @@
- +
@@ -131,9 +104,13 @@ {#if peopleSelection}
- (peopleSelection = false)} on:confirm={handlePeopleSelected} {selectedPeople} /> + (peopleSelection = false)} + on:confirm={({ detail: people }) => handleSelectPeople(people)} + selectedIds={peopleRules.map(({ value }) => value)} + />
{/if} diff --git a/web/src/lib/components/assets/thumbnail/face-thumbnail.svelte b/web/src/lib/components/assets/thumbnail/face-thumbnail.svelte index 5231ed181..1bd428467 100644 --- a/web/src/lib/components/assets/thumbnail/face-thumbnail.svelte +++ b/web/src/lib/components/assets/thumbnail/face-thumbnail.svelte @@ -100,7 +100,7 @@
@@ -120,7 +120,7 @@
{#if selectionCandidate}
diff --git a/web/src/lib/components/shared-components/base-modal.svelte b/web/src/lib/components/shared-components/base-modal.svelte index 1a721d0b3..60e810ec4 100644 --- a/web/src/lib/components/shared-components/base-modal.svelte +++ b/web/src/lib/components/shared-components/base-modal.svelte @@ -37,9 +37,9 @@
!ignoreClickOutside && dispatch('close')} - class="bg-immich-bg dark:bg-immich-dark-gray dark:text-immich-dark-fg max-h-[700px] min-h-[200px] w-[450px] overflow-y-auto rounded-lg shadow-md" + class="max-h-[700px] min-h-[200px] w-[450px] overflow-y-auto rounded-lg bg-immich-bg shadow-md dark:bg-immich-dark-gray dark:text-immich-dark-fg" > -
+

Modal Title

@@ -54,7 +54,7 @@
{#if $$slots['sticky-bottom']} -
+
{/if} diff --git a/web/src/routes/(user)/albums/[albumId]/+page.svelte b/web/src/routes/(user)/albums/[albumId]/+page.svelte index dcfd29ec0..41341ba7c 100644 --- a/web/src/routes/(user)/albums/[albumId]/+page.svelte +++ b/web/src/routes/(user)/albums/[albumId]/+page.svelte @@ -33,7 +33,7 @@ import { downloadArchive } from '$lib/utils/asset-utils'; import { openFileUploadDialog } from '$lib/utils/file-uploader'; import { handleError } from '$lib/utils/handle-error'; - import { TimeBucketSize, UserResponseDto, api } from '@api'; + import { RuleResponseDto, TimeBucketSize, UserResponseDto, api } from '@api'; import ArrowLeft from 'svelte-material-icons/ArrowLeft.svelte'; import DeleteOutline from 'svelte-material-icons/DeleteOutline.svelte'; import DotsVertical from 'svelte-material-icons/DotsVertical.svelte'; @@ -279,6 +279,28 @@ handleError(error, 'Error updating album description'); } }; + + const handleUpdateRules = async (rules: RuleResponseDto[]) => { + let ids = rules.filter((rule) => !!rule.id).map((rule) => rule.id); + + for (const rule of album.rules) { + if (!ids.includes(rule.id)) { + await api.ruleApi.removeRule({ id: rule.id }); + } + } + + for (const { id, key, value } of rules) { + if (!id) { + await api.ruleApi.createRule({ createRuleDto: { albumId: album.id, key, value } }); + } else { + await api.ruleApi.updateRule({ id, updateRuleDto: { key, value } }); + } + } + + await refreshAlbum(); + + viewMode = ViewMode.VIEW; + };
@@ -354,7 +376,7 @@ {#if viewMode === ViewMode.SELECT_ASSETS} -

+

{#if $timelineSelected.size === 0} Add to album {:else} @@ -366,7 +388,7 @@ @@ -385,7 +407,7 @@

{#if viewMode === ViewMode.SELECT_ASSETS} @@ -403,9 +425,9 @@ e.key === 'Enter' && titleInput.blur()} on:blur={handleUpdateName} - class="text-immich-primary dark:text-immich-dark-primary w-[99%] border-b-2 border-transparent text-6xl outline-none transition-all {isOwned + class="w-[99%] border-b-2 border-transparent text-6xl text-immich-primary outline-none transition-all dark:text-immich-dark-primary {isOwned ? 'hover:border-gray-400' - : 'hover:border-transparent'} bg-immich-bg focus:border-immich-primary dark:bg-immich-dark-bg dark:focus:border-immich-dark-primary dark:focus:bg-immich-dark-gray focus:border-b-2 focus:outline-none" + : 'hover:border-transparent'} bg-immich-bg focus:border-b-2 focus:border-immich-primary focus:outline-none dark:bg-immich-dark-bg dark:focus:border-immich-dark-primary dark:focus:bg-immich-dark-gray" type="text" bind:value={album.albumName} disabled={!isOwned} @@ -479,11 +501,11 @@ {#if album.assetCount === 0}
-

ADD PHOTOS

+

ADD PHOTOS