diff --git a/web/src/routes/(user)/people/+page.svelte b/web/src/routes/(user)/people/+page.svelte index 20f4852799..ccbcbc2a68 100644 --- a/web/src/routes/(user)/people/+page.svelte +++ b/web/src/routes/(user)/people/+page.svelte @@ -3,7 +3,6 @@ import { page } from '$app/stores'; import { scrollMemory } from '$lib/actions/scroll-memory'; import { shortcut } from '$lib/actions/shortcut'; - import ManagePeopleVisibility from './ManagePeopleVisibility.svelte'; import PeopleCard from './PeopleCard.svelte'; import PeopleInfiniteScroll from './PeopleInfiniteScroll.svelte'; import SearchPeople from '$lib/components/faces-page/PeopleSearch.svelte'; @@ -22,8 +21,6 @@ import { mdiAccountOff, mdiEyeOutline } from '@mdi/js'; import { onMount } from 'svelte'; import { t } from 'svelte-i18n'; - import { quintOut } from 'svelte/easing'; - import { fly } from 'svelte/transition'; import type { PageData } from './$types'; interface Props { @@ -32,7 +29,6 @@ let { data }: Props = $props(); - let selectHidden = $state(false); let searchName = $state(''); let newName = $state(''); let currentPage = $state(1); @@ -331,7 +327,7 @@ {/if} - -{#if selectHidden} - dialog.showModal()} - > - (selectHidden = false)} - onUpdate={(updatedPeople) => (people = updatedPeople.slice())} - {loadNextPage} - /> - -{/if} diff --git a/web/src/routes/(user)/people/ManagePeopleVisibility.test-wrapper.svelte b/web/src/routes/(user)/people/ManagePeopleVisibility.test-wrapper.svelte deleted file mode 100644 index 7e64f30b43..0000000000 --- a/web/src/routes/(user)/people/ManagePeopleVisibility.test-wrapper.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - - - diff --git a/web/src/routes/(user)/people/ManagePeopleVisibility.svelte b/web/src/routes/(user)/people/manage/+page.svelte similarity index 78% rename from web/src/routes/(user)/people/ManagePeopleVisibility.svelte rename to web/src/routes/(user)/people/manage/+page.svelte index 2ae2a7fc8e..1e6b917768 100644 --- a/web/src/routes/(user)/people/ManagePeopleVisibility.svelte +++ b/web/src/routes/(user)/people/manage/+page.svelte @@ -1,28 +1,28 @@ - - -
-
-
- -
-

{$t('show_and_hide_people')}

-

({totalPeopleCount.toLocaleString($locale)})

-
-
+ + {#snippet buttons()}
+ goto('/people')} + />
-
+ {/snippet}
- + {#snippet children({ person })} {@const hidden = overrides.get(person.id) ?? person.isHidden}
-
+ diff --git a/web/src/routes/(user)/people/manage/+page.ts b/web/src/routes/(user)/people/manage/+page.ts new file mode 100644 index 0000000000..1db0f79940 --- /dev/null +++ b/web/src/routes/(user)/people/manage/+page.ts @@ -0,0 +1,13 @@ +import { getAllPeople } from '@immich/sdk'; +import { authenticate } from '$lib/utils/auth'; +import type { PageLoad } from './$types'; + +export const load = (async ({ url }) => { + await authenticate(url); + + const people = await getAllPeople({ withHidden: true }); + + return { + people, + }; +}) satisfies PageLoad; diff --git a/web/src/routes/(user)/people/ManagePeopleVisibility.spec.ts b/web/src/routes/(user)/people/manage/ManagePeopleVisibility.spec.ts similarity index 56% rename from web/src/routes/(user)/people/ManagePeopleVisibility.spec.ts rename to web/src/routes/(user)/people/manage/ManagePeopleVisibility.spec.ts index 1500f05ecd..eb0e6a6357 100644 --- a/web/src/routes/(user)/people/ManagePeopleVisibility.spec.ts +++ b/web/src/routes/(user)/people/manage/ManagePeopleVisibility.spec.ts @@ -1,35 +1,50 @@ import { render } from '@testing-library/svelte'; import userEvent from '@testing-library/user-event'; +import type { ComponentProps } from 'svelte'; import { vi } from 'vitest'; import { getIntersectionObserverMock } from '$lib/__mocks__/intersection-observer.mock'; import { personFactory } from '@test-data/factories/person-factory'; -import ManagePeopleVisibilityWrapper from './ManagePeopleVisibility.test-wrapper.svelte'; +import ManagePeoplePage from './+page.svelte'; +import ManagePeoplePageTestWrapper from './ManagePeopleVisibility.test-wrapper.svelte'; -describe('ManagePeopleVisibility component', () => { +vi.mock(import('$lib/managers/feature-flags-manager.svelte'), function () { + return { + featureFlagsManager: { init: vi.fn(), loadFeatureFlags: vi.fn(), value: {} } as never, + }; +}); + +vi.mock('$lib/components/layouts/UserPageLayout.svelte', async () => { + return await import('@test-data/mocks/UserPageLayout.mock.svelte'); +}); + +const getData = ( + people: ReturnType[], + hasNextPage = false, +): ComponentProps['data'] => ({ + error: undefined, + meta: { title: 'Manage people visibility' }, + asset: undefined, + people: { + people, + total: people.length, + hidden: people.filter((person) => person.isHidden).length, + hasNextPage, + }, +}); + +describe('People manage page', () => { beforeEach(() => { vi.stubGlobal('IntersectionObserver', getIntersectionObserverMock()); }); it('keeps toggled hidden state when loading more people', async () => { - const onClose = vi.fn(); - const onUpdate = vi.fn(); - const loadNextPage = vi.fn(); - const [personA, personB, personC] = [ personFactory.build({ id: 'a', isHidden: false }), personFactory.build({ id: 'b', isHidden: false }), personFactory.build({ id: 'c', isHidden: true }), ]; - const { container, rerender } = render(ManagePeopleVisibilityWrapper, { - props: { - people: [personA, personB], - totalPeopleCount: 3, - onClose, - onUpdate, - loadNextPage, - }, - }); + const { container, rerender } = render(ManagePeoplePageTestWrapper, { data: getData([personA, personB], true) }); const user = userEvent.setup(); let personButtons = container.querySelectorAll('button[aria-pressed]'); @@ -38,13 +53,7 @@ describe('ManagePeopleVisibility component', () => { await user.click(personButtons[0]); expect(personButtons[0].getAttribute('aria-pressed')).toBe('true'); - await rerender({ - people: [personA, personB, personC], - totalPeopleCount: 3, - onClose, - onUpdate, - loadNextPage, - }); + await rerender({ data: getData([personA, personB, personC], false) }); personButtons = container.querySelectorAll('button[aria-pressed]'); expect(personButtons).toHaveLength(3); @@ -53,33 +62,15 @@ describe('ManagePeopleVisibility component', () => { }); it('shows newly loaded hidden people as hidden', async () => { - const onClose = vi.fn(); - const onUpdate = vi.fn(); - const loadNextPage = vi.fn(); - const [personA, personB, personC] = [ personFactory.build({ id: 'a', isHidden: false }), personFactory.build({ id: 'b', isHidden: false }), personFactory.build({ id: 'c', isHidden: true }), ]; - const { container, rerender } = render(ManagePeopleVisibilityWrapper, { - props: { - people: [personA, personB], - totalPeopleCount: 3, - onClose, - onUpdate, - loadNextPage, - }, - }); + const { container, rerender } = render(ManagePeoplePageTestWrapper, { data: getData([personA, personB], true) }); - await rerender({ - people: [personA, personB, personC], - totalPeopleCount: 3, - onClose, - onUpdate, - loadNextPage, - }); + await rerender({ data: getData([personA, personB, personC], false) }); const personButtons = container.querySelectorAll('button[aria-pressed]'); expect(personButtons).toHaveLength(3); diff --git a/web/src/routes/(user)/people/manage/ManagePeopleVisibility.test-wrapper.svelte b/web/src/routes/(user)/people/manage/ManagePeopleVisibility.test-wrapper.svelte new file mode 100644 index 0000000000..281173cc3f --- /dev/null +++ b/web/src/routes/(user)/people/manage/ManagePeopleVisibility.test-wrapper.svelte @@ -0,0 +1,15 @@ + + + + + diff --git a/web/src/test-data/mocks/UserPageLayout.mock.svelte b/web/src/test-data/mocks/UserPageLayout.mock.svelte new file mode 100644 index 0000000000..6cf59b62d3 --- /dev/null +++ b/web/src/test-data/mocks/UserPageLayout.mock.svelte @@ -0,0 +1,13 @@ + + +
+ {@render buttons?.()} + {@render children?.()} +