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}
-
-{/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?.()}
+