mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-15 13:55:19 +00:00
refac: group members frontend
This commit is contained in:
parent
bc576782d7
commit
0a72d047ef
4 changed files with 58 additions and 59 deletions
|
|
@ -33,9 +33,6 @@
|
||||||
|
|
||||||
let loaded = false;
|
let loaded = false;
|
||||||
|
|
||||||
let users = [];
|
|
||||||
let total = 0;
|
|
||||||
|
|
||||||
let groups = [];
|
let groups = [];
|
||||||
let filteredGroups;
|
let filteredGroups;
|
||||||
|
|
||||||
|
|
@ -93,16 +90,6 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await getAllUsers(localStorage.token).catch((error) => {
|
|
||||||
toast.error(`${error}`);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res) {
|
|
||||||
users = res.users;
|
|
||||||
total = res.total;
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultPermissions = await getUserDefaultPermissions(localStorage.token);
|
defaultPermissions = await getUserDefaultPermissions(localStorage.token);
|
||||||
await setGroups();
|
await setGroups();
|
||||||
loaded = true;
|
loaded = true;
|
||||||
|
|
@ -189,7 +176,7 @@
|
||||||
|
|
||||||
{#each filteredGroups as group}
|
{#each filteredGroups as group}
|
||||||
<div class="my-2">
|
<div class="my-2">
|
||||||
<GroupItem {group} {users} {setGroups} {defaultPermissions} />
|
<GroupItem {group} {setGroups} {defaultPermissions} />
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@
|
||||||
export let show = false;
|
export let show = false;
|
||||||
export let edit = false;
|
export let edit = false;
|
||||||
|
|
||||||
export let users = [];
|
|
||||||
export let group = null;
|
export let group = null;
|
||||||
export let defaultPermissions = {};
|
export let defaultPermissions = {};
|
||||||
|
|
||||||
|
|
@ -31,6 +30,8 @@
|
||||||
let loading = false;
|
let loading = false;
|
||||||
let showDeleteConfirmDialog = false;
|
let showDeleteConfirmDialog = false;
|
||||||
|
|
||||||
|
let userCount = 0;
|
||||||
|
|
||||||
export let name = '';
|
export let name = '';
|
||||||
export let description = '';
|
export let description = '';
|
||||||
|
|
||||||
|
|
@ -75,7 +76,6 @@
|
||||||
code_interpreter: true
|
code_interpreter: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
export let userIds = [];
|
|
||||||
|
|
||||||
const submitHandler = async () => {
|
const submitHandler = async () => {
|
||||||
loading = true;
|
loading = true;
|
||||||
|
|
@ -83,8 +83,7 @@
|
||||||
const group = {
|
const group = {
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
permissions,
|
permissions
|
||||||
user_ids: userIds
|
|
||||||
};
|
};
|
||||||
|
|
||||||
await onSubmit(group);
|
await onSubmit(group);
|
||||||
|
|
@ -99,7 +98,7 @@
|
||||||
description = group.description;
|
description = group.description;
|
||||||
permissions = group?.permissions ?? {};
|
permissions = group?.permissions ?? {};
|
||||||
|
|
||||||
userIds = group?.user_ids ?? [];
|
userCount = group?.member_count ?? 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -121,7 +120,7 @@
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Modal size="md" bind:show>
|
<Modal size="lg" bind:show>
|
||||||
<div>
|
<div>
|
||||||
<div class=" flex justify-between dark:text-gray-100 px-5 pt-4 mb-1.5">
|
<div class=" flex justify-between dark:text-gray-100 px-5 pt-4 mb-1.5">
|
||||||
<div class=" text-lg font-medium self-center font-primary">
|
<div class=" text-lg font-medium self-center font-primary">
|
||||||
|
|
@ -220,20 +219,20 @@
|
||||||
<div class=" self-center mr-2">
|
<div class=" self-center mr-2">
|
||||||
<UserPlusSolid />
|
<UserPlusSolid />
|
||||||
</div>
|
</div>
|
||||||
<div class=" self-center">{$i18n.t('Users')} ({userIds.length})</div>
|
<div class=" self-center">{$i18n.t('Users')} ({userCount})</div>
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="flex-1 mt-1 lg:mt-1 lg:h-[22rem] lg:max-h-[22rem] overflow-y-auto scrollbar-hidden"
|
class="flex-1 mt-1 lg:mt-1 lg:h-[30rem] lg:max-h-[30rem] overflow-y-auto scrollbar-hidden"
|
||||||
>
|
>
|
||||||
{#if selectedTab == 'general'}
|
{#if selectedTab == 'general'}
|
||||||
<Display bind:name bind:description />
|
<Display bind:name bind:description />
|
||||||
{:else if selectedTab == 'permissions'}
|
{:else if selectedTab == 'permissions'}
|
||||||
<Permissions bind:permissions {defaultPermissions} />
|
<Permissions bind:permissions {defaultPermissions} />
|
||||||
{:else if selectedTab == 'users'}
|
{:else if selectedTab == 'users'}
|
||||||
<Users bind:userIds {users} />
|
<Users bind:userCount />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@
|
||||||
import UserCircleSolid from '$lib/components/icons/UserCircleSolid.svelte';
|
import UserCircleSolid from '$lib/components/icons/UserCircleSolid.svelte';
|
||||||
import GroupModal from './EditGroupModal.svelte';
|
import GroupModal from './EditGroupModal.svelte';
|
||||||
|
|
||||||
export let users = [];
|
|
||||||
export let group = {
|
export let group = {
|
||||||
name: 'Admins',
|
name: 'Admins',
|
||||||
user_ids: [1, 2, 3]
|
user_ids: [1, 2, 3]
|
||||||
|
|
@ -58,7 +57,6 @@
|
||||||
<GroupModal
|
<GroupModal
|
||||||
bind:show={showEdit}
|
bind:show={showEdit}
|
||||||
edit
|
edit
|
||||||
{users}
|
|
||||||
{group}
|
{group}
|
||||||
{defaultPermissions}
|
{defaultPermissions}
|
||||||
onSubmit={updateHandler}
|
onSubmit={updateHandler}
|
||||||
|
|
@ -81,7 +79,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center gap-1.5 w-fit font-medium text-right justify-end">
|
<div class="flex items-center gap-1.5 w-fit font-medium text-right justify-end">
|
||||||
{group.user_ids.length}
|
{group?.member_count}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<User className="size-3.5" />
|
<User className="size-3.5" />
|
||||||
|
|
|
||||||
|
|
@ -8,42 +8,49 @@
|
||||||
import Checkbox from '$lib/components/common/Checkbox.svelte';
|
import Checkbox from '$lib/components/common/Checkbox.svelte';
|
||||||
import Badge from '$lib/components/common/Badge.svelte';
|
import Badge from '$lib/components/common/Badge.svelte';
|
||||||
import Search from '$lib/components/icons/Search.svelte';
|
import Search from '$lib/components/icons/Search.svelte';
|
||||||
|
import { getUsers } from '$lib/apis/users';
|
||||||
|
import { toast } from 'svelte-sonner';
|
||||||
|
import Pagination from '$lib/components/common/Pagination.svelte';
|
||||||
|
|
||||||
export let users = [];
|
export let userCount = 0;
|
||||||
export let userIds = [];
|
let userIds = [];
|
||||||
|
|
||||||
let filteredUsers = [];
|
let users = [];
|
||||||
|
let total = 0;
|
||||||
$: filteredUsers = users
|
|
||||||
.filter((user) => {
|
|
||||||
if (query === '') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
user.name.toLowerCase().includes(query.toLowerCase()) ||
|
|
||||||
user.email.toLowerCase().includes(query.toLowerCase())
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.sort((a, b) => {
|
|
||||||
const aUserIndex = userIds.indexOf(a.id);
|
|
||||||
const bUserIndex = userIds.indexOf(b.id);
|
|
||||||
|
|
||||||
// Compare based on userIds or fall back to alphabetical order
|
|
||||||
if (aUserIndex !== -1 && bUserIndex === -1) return -1; // 'a' has valid userId -> prioritize
|
|
||||||
if (bUserIndex !== -1 && aUserIndex === -1) return 1; // 'b' has valid userId -> prioritize
|
|
||||||
|
|
||||||
// Both a and b are either in the userIds array or not, so we'll sort them by their indices
|
|
||||||
if (aUserIndex !== -1 && bUserIndex !== -1) return aUserIndex - bUserIndex;
|
|
||||||
|
|
||||||
// If both are not in the userIds, fallback to alphabetical sorting by name
|
|
||||||
return a.name.localeCompare(b.name);
|
|
||||||
});
|
|
||||||
|
|
||||||
let query = '';
|
let query = '';
|
||||||
|
let page = 1;
|
||||||
|
|
||||||
|
const getUserList = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getUsers(localStorage.token, query, null, null, page).catch((error) => {
|
||||||
|
toast.error(`${error}`);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
users = res.users;
|
||||||
|
total = res.total;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$: if (page) {
|
||||||
|
getUserList();
|
||||||
|
}
|
||||||
|
|
||||||
|
$: if (query !== null) {
|
||||||
|
getUserList();
|
||||||
|
}
|
||||||
|
|
||||||
|
$: if (query) {
|
||||||
|
page = 1;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div class=" max-h-full">
|
||||||
<div class="flex w-full">
|
<div class="flex w-full">
|
||||||
<div class="flex flex-1">
|
<div class="flex flex-1">
|
||||||
<div class=" self-center mr-3">
|
<div class=" self-center mr-3">
|
||||||
|
|
@ -57,10 +64,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-3 scrollbar-hidden">
|
<div class="mt-3 overflow-y-auto">
|
||||||
<div class="flex flex-col gap-2.5">
|
<div class="flex flex-col gap-2.5">
|
||||||
{#if filteredUsers.length > 0}
|
{#if users.length > 0}
|
||||||
{#each filteredUsers as user, userIdx (user.id)}
|
{#each users as user, userIdx (user.id)}
|
||||||
<div class="flex flex-row items-center gap-3 w-full text-sm">
|
<div class="flex flex-row items-center gap-3 w-full text-sm">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
|
|
@ -88,6 +95,14 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
|
{page}
|
||||||
|
|
||||||
|
{total}
|
||||||
|
|
||||||
|
{#if total > 30}
|
||||||
|
<Pagination bind:page count={total} perPage={30} />
|
||||||
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<div class="text-gray-500 text-xs text-center py-2 px-10">
|
<div class="text-gray-500 text-xs text-center py-2 px-10">
|
||||||
{$i18n.t('No users were found.')}
|
{$i18n.t('No users were found.')}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue