refactor(web): user delete websocket event (#24015)

pull/24039/head
Jason Rasmussen 2025-11-20 07:54:29 +07:00 committed by GitHub
parent 1a31faf1a2
commit 9a403d5886
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 25 additions and 18 deletions

@ -407,7 +407,6 @@
"user_restore_scheduled_removal": "Restore user - scheduled removal on {date, date, long}", "user_restore_scheduled_removal": "Restore user - scheduled removal on {date, date, long}",
"user_settings": "User Settings", "user_settings": "User Settings",
"user_settings_description": "Manage user settings", "user_settings_description": "Manage user settings",
"user_successfully_removed": "User {email} has been successfully removed.",
"version_check_enabled_description": "Enable version check", "version_check_enabled_description": "Enable version check",
"version_check_implications": "The version check feature relies on periodic communication with github.com", "version_check_implications": "The version check feature relies on periodic communication with github.com",
"version_check_settings": "Version Check", "version_check_settings": "Version Check",

@ -27,8 +27,11 @@ export type Events = {
UserAdminCreate: [UserAdminResponseDto]; UserAdminCreate: [UserAdminResponseDto];
UserAdminUpdate: [UserAdminResponseDto]; UserAdminUpdate: [UserAdminResponseDto];
UserAdminDelete: [UserAdminResponseDto];
UserAdminRestore: [UserAdminResponseDto]; UserAdminRestore: [UserAdminResponseDto];
// soft deleted
UserAdminDelete: [UserAdminResponseDto];
// confirmed permanently deleted from server
UserAdminDeleted: [{ id: string }];
SystemConfigUpdate: [SystemConfigDto]; SystemConfigUpdate: [SystemConfigDto];

@ -56,6 +56,7 @@ websocket
.on('AppRestartV1', (mode) => websocketStore.serverRestarting.set(mode)) .on('AppRestartV1', (mode) => websocketStore.serverRestarting.set(mode))
.on('on_new_release', (event) => eventManager.emit('ReleaseEvent', event)) .on('on_new_release', (event) => eventManager.emit('ReleaseEvent', event))
.on('on_session_delete', () => authManager.logout()) .on('on_session_delete', () => authManager.logout())
.on('on_user_delete', (id) => eventManager.emit('UserAdminDeleted', { id }))
.on('on_notification', () => notificationManager.refresh()) .on('on_notification', () => notificationManager.refresh())
.on('connect_error', (e) => console.log('Websocket Connect Error', e)); .on('connect_error', (e) => console.log('Websocket Connect Error', e));

@ -1,46 +1,36 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores';
import HeaderButton from '$lib/components/HeaderButton.svelte'; import HeaderButton from '$lib/components/HeaderButton.svelte';
import AdminPageLayout from '$lib/components/layouts/AdminPageLayout.svelte'; import AdminPageLayout from '$lib/components/layouts/AdminPageLayout.svelte';
import OnEvents from '$lib/components/OnEvents.svelte'; import OnEvents from '$lib/components/OnEvents.svelte';
import TableButton from '$lib/components/TableButton.svelte'; import TableButton from '$lib/components/TableButton.svelte';
import { getUserAdminActions, getUserAdminsActions } from '$lib/services/user-admin.service'; import { getUserAdminActions, getUserAdminsActions } from '$lib/services/user-admin.service';
import { locale } from '$lib/stores/preferences.store'; import { locale } from '$lib/stores/preferences.store';
import { websocketEvents } from '$lib/stores/websocket';
import { getByteUnitString } from '$lib/utils/byte-units'; import { getByteUnitString } from '$lib/utils/byte-units';
import { searchUsersAdmin, type UserAdminResponseDto } from '@immich/sdk'; import { searchUsersAdmin, type UserAdminResponseDto } from '@immich/sdk';
import { HStack, Icon, toastManager } from '@immich/ui'; import { HStack, Icon } from '@immich/ui';
import { mdiInfinity } from '@mdi/js'; import { mdiInfinity } from '@mdi/js';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
import type { PageData } from './$types'; import type { PageData } from './$types';
interface Props { type Props = {
data: PageData; data: PageData;
} };
let { data }: Props = $props(); let { data }: Props = $props();
let allUsers: UserAdminResponseDto[] = $state([]); let allUsers: UserAdminResponseDto[] = $derived(data.allUsers);
const refresh = async () => { const refresh = async () => {
allUsers = await searchUsersAdmin({ withDeleted: true }); allUsers = await searchUsersAdmin({ withDeleted: true });
}; };
const onDeleteSuccess = (userId: string) => { const onUserAdminDeleted = ({ id: userId }: { id: string }) => {
const user = allUsers.find(({ id }) => id === userId); const user = allUsers.find(({ id }) => id === userId);
if (user) { if (user) {
allUsers = allUsers.filter((user) => user.id !== userId); allUsers = allUsers.filter((user) => user.id !== userId);
toastManager.success($t('admin.user_successfully_removed', { values: { email: user.email } }));
} }
}; };
onMount(() => {
allUsers = $page.data.allUsers;
return websocketEvents.on('on_user_delete', onDeleteSuccess);
});
const UserAdminsActions = $derived(getUserAdminsActions($t)); const UserAdminsActions = $derived(getUserAdminsActions($t));
const onUpdate = async () => { const onUpdate = async () => {
@ -53,6 +43,7 @@
onUserAdminUpdate={onUpdate} onUserAdminUpdate={onUpdate}
onUserAdminDelete={onUpdate} onUserAdminDelete={onUpdate}
onUserAdminRestore={onUpdate} onUserAdminRestore={onUpdate}
{onUserAdminDeleted}
/> />
<AdminPageLayout title={data.meta.title}> <AdminPageLayout title={data.meta.title}>

@ -1,4 +1,5 @@
<script lang="ts"> <script lang="ts">
import { goto } from '$app/navigation';
import HeaderButton from '$lib/components/HeaderButton.svelte'; import HeaderButton from '$lib/components/HeaderButton.svelte';
import AdminPageLayout from '$lib/components/layouts/AdminPageLayout.svelte'; import AdminPageLayout from '$lib/components/layouts/AdminPageLayout.svelte';
import OnEvents from '$lib/components/OnEvents.svelte'; import OnEvents from '$lib/components/OnEvents.svelte';
@ -6,6 +7,7 @@
import UserAvatar from '$lib/components/shared-components/user-avatar.svelte'; import UserAvatar from '$lib/components/shared-components/user-avatar.svelte';
import DeviceCard from '$lib/components/user-settings-page/device-card.svelte'; import DeviceCard from '$lib/components/user-settings-page/device-card.svelte';
import FeatureSetting from '$lib/components/users/FeatureSetting.svelte'; import FeatureSetting from '$lib/components/users/FeatureSetting.svelte';
import { AppRoute } from '$lib/constants';
import { getUserAdminActions } from '$lib/services/user-admin.service'; import { getUserAdminActions } from '$lib/services/user-admin.service';
import { locale } from '$lib/stores/preferences.store'; import { locale } from '$lib/stores/preferences.store';
import { createDateFormatter, findLocale } from '$lib/utils'; import { createDateFormatter, findLocale } from '$lib/utils';
@ -82,9 +84,20 @@
user = update; user = update;
} }
}; };
const onUserAdminDeleted = async ({ id }: { id: string }) => {
if (id === user.id) {
await goto(AppRoute.ADMIN_USERS);
}
};
</script> </script>
<OnEvents onUserAdminUpdate={onUpdate} onUserAdminDelete={onUpdate} onUserAdminRestore={onUpdate} /> <OnEvents
onUserAdminUpdate={onUpdate}
onUserAdminDelete={onUpdate}
onUserAdminRestore={onUpdate}
{onUserAdminDeleted}
/>
<AdminPageLayout title={data.meta.title}> <AdminPageLayout title={data.meta.title}>
{#snippet buttons()} {#snippet buttons()}