From 46bbf760e8f1409f3b14c3e3609a41386fa7602e Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sun, 23 Nov 2025 18:56:50 -0500 Subject: [PATCH] enh: group members selector --- .../admin/Users/Groups/Users.svelte | 224 ++++++++++++++---- 1 file changed, 179 insertions(+), 45 deletions(-) diff --git a/src/lib/components/admin/Users/Groups/Users.svelte b/src/lib/components/admin/Users/Groups/Users.svelte index 2d3151c99f..298611a655 100644 --- a/src/lib/components/admin/Users/Groups/Users.svelte +++ b/src/lib/components/admin/Users/Groups/Users.svelte @@ -2,6 +2,12 @@ import { getContext } from 'svelte'; const i18n = getContext('i18n'); + import dayjs from 'dayjs'; + import relativeTime from 'dayjs/plugin/relativeTime'; + import localizedFormat from 'dayjs/plugin/localizedFormat'; + dayjs.extend(relativeTime); + dayjs.extend(localizedFormat); + import { getUsers } from '$lib/apis/users'; import { toast } from 'svelte-sonner'; @@ -11,6 +17,9 @@ import Search from '$lib/components/icons/Search.svelte'; import Pagination from '$lib/components/common/Pagination.svelte'; import { addUserToGroup, removeUserFromGroup } from '$lib/apis/groups'; + import ChevronDown from '$lib/components/icons/ChevronDown.svelte'; + import ChevronUp from '$lib/components/icons/ChevronUp.svelte'; + import { WEBUI_API_BASE_URL } from '$lib/constants'; export let groupId: string; export let userCount = 0; @@ -19,20 +28,28 @@ let total = 0; let query = ''; + let orderBy = `group_id:${groupId}`; // default sort key + let direction = 'desc'; // default sort order + let page = 1; + const setSortKey = (key) => { + if (orderBy === key) { + direction = direction === 'asc' ? 'desc' : 'asc'; + } else { + orderBy = key; + direction = 'asc'; + } + }; + const getUserList = async () => { try { - const res = await getUsers( - localStorage.token, - query, - `group_id:${groupId}`, - null, - page - ).catch((error) => { - toast.error(`${error}`); - return null; - }); + const res = await getUsers(localStorage.token, query, orderBy, direction, page).catch( + (error) => { + toast.error(`${error}`); + return null; + } + ); if (res) { users = res.users; @@ -60,11 +77,7 @@ getUserList(); }; - $: if (page) { - getUserList(); - } - - $: if (query !== null) { + $: if (page !== null && query !== null && orderBy !== null && direction !== null) { getUserList(); } @@ -87,40 +100,161 @@ -
-
- {#if users.length > 0} - {#each users as user, userIdx (user.id)} -
-
- { - toggleMember(user.id, e.detail); - }} - /> -
+ {#if users.length > 0} +
+ + + + + + + + + + + + + {#each users as user, userIdx} + + + + + + + + {/each} + +
setSortKey(`group_id:${groupId}`)} + > +
+ {$i18n.t('MBR')} -
- -
-
{user.name}
+ {#if orderBy === `group_id:${groupId}`} + {#if direction === 'asc'} + + {:else} + + {/if} + + {:else} + + {/if} +
+
setSortKey('role')} + > +
+ {$i18n.t('Role')} + + {#if orderBy === 'role'} + {#if direction === 'asc'} + + {:else} + + {/if} + + {:else} + + {/if} +
+
setSortKey('name')} + > +
+ {$i18n.t('Name')} + + {#if orderBy === 'name'} + {#if direction === 'asc'} + + {:else} + + {/if} + + {:else} + + {/if} +
+
setSortKey('last_active_at')} + > +
+ {$i18n.t('Last Active')} + + {#if orderBy === 'last_active_at'} + {#if direction === 'asc'} + + {:else} + + {/if} + + {:else} + + {/if} +
+
+
+ { + toggleMember(user.id, e.detail); + }} + />
- +
+
+ +
+
+ +
+ user - {#if (user?.group_ids ?? []).includes(groupId)} - - {/if} -
- - {/each} - {:else} -
- {$i18n.t('No users were found.')} -
- {/if} +
{user.name}
+ +
+
+ {dayjs(user.last_active_at * 1000).fromNow()} +
-
+ {:else} +
+ {$i18n.t('No users were found.')} +
+ {/if} {#if total > 30}