This commit is contained in:
Timothy Jaeryang Baek
2024-11-14 20:51:49 -08:00
parent dff85c733d
commit b80ec76435
7 changed files with 145 additions and 178 deletions

View File

@@ -48,69 +48,38 @@
let showCreateGroupModal = false;
let showDefaultPermissionsModal = false;
const setGroups = async () => {
groups = await getGroups(localStorage.token);
};
const addGroupHandler = async (group) => {
const res = await createNewGroup(localStorage.token, group).catch((error) => {
toast.error(error);
return null;
});
if (res) {
toast.success($i18n.t('Group created successfully'));
groups = await getGroups(localStorage.token);
}
};
const updateDefaultPermissionsHandler = async (permissions) => {
console.log(permissions);
};
onMount(async () => {
if ($user?.role !== 'admin') {
await goto('/');
} else {
groups = await getGroups(localStorage.token);
// [
// {
// id: '1',
// name: 'Group A',
// description: 'Group A description',
// permissions: {
// model: {
// enable_filter: false, // boolean
// ids: [], // array of strings
// default_id: null // null or string
// },
// workspace: {
// models: false, // boolean
// knowledge: false, // boolean
// prompts: false // boolean
// },
// chat: {
// delete: true, // boolean
// edit: true, // boolean
// temporary: true // boolean
// }
// },
// user_ids: ['1', '2', '3'], // array of strings
// admin_ids: ['1'] // array of strings
// },
// {
// id: '2',
// name: 'Moderators',
// description: 'Moderators description',
// permissions: {
// model: {
// enable_filter: false, // boolean
// ids: [], // array of strings
// default_id: null // null or string
// },
// workspace: {
// models: false, // boolean
// knowledge: false, // boolean
// prompts: false // boolean
// },
// chat: {
// delete: true, // boolean
// edit: true, // boolean
// temporary: true // boolean
// }
// },
// user_ids: ['1', '5', '6'], // array of strings
// admin_ids: ['1'] // array of strings
// }
// ];
await setGroups();
}
loaded = true;
});
</script>
{#if loaded}
<AddGroupModal bind:show={showCreateGroupModal} />
<AddGroupModal bind:show={showCreateGroupModal} onSubmit={addGroupHandler} />
<div class="mt-0.5 mb-2 gap-1 flex flex-col md:flex-row justify-between">
<div class="flex md:self-center text-lg font-medium px-0.5">
{$i18n.t('Groups')}
@@ -196,7 +165,7 @@
{#each filteredGroups as group}
<div class="my-2">
<GroupItem {group} {users} />
<GroupItem {group} {users} {setGroups} />
</div>
{/each}
</div>
@@ -204,7 +173,12 @@
<hr class="mb-2 border-gray-50 dark:border-gray-850" />
<GroupModal bind:show={showDefaultPermissionsModal} tabs={['permissions']} custom={false} />
<GroupModal
bind:show={showDefaultPermissionsModal}
tabs={['permissions']}
custom={false}
onSubmit={updateDefaultPermissionsHandler}
/>
<button
class="flex items-center justify-between rounded-lg w-full transition pt-1"

View File

@@ -4,16 +4,9 @@
const i18n = getContext('i18n');
import Modal from '$lib/components/common/Modal.svelte';
import Plus from '$lib/components/icons/Plus.svelte';
import Minus from '$lib/components/icons/Minus.svelte';
import PencilSolid from '$lib/components/icons/PencilSolid.svelte';
import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import Switch from '$lib/components/common/Switch.svelte';
import Display from './Display.svelte';
import Permissions from './Permissions.svelte';
import Users from './Users.svelte';
import UsersSolid from '$lib/components/icons/UsersSolid.svelte';
import UserPlusSolid from '$lib/components/icons/UserPlusSolid.svelte';
import WrenchSolid from '$lib/components/icons/WrenchSolid.svelte';
@@ -31,15 +24,25 @@
export let tabs = ['general', 'permissions', 'users'];
let selectedTab = 'general';
let loading = false;
let name = '';
let description = '';
let permissions = {};
let permissions = {
workspace: {
models: false,
knowledge: false,
prompts: false,
tools: false
},
chat: {
delete: true,
edit: true,
temporary: true
}
};
let userIds = [];
let adminIds = [];
let loading = false;
const submitHandler = async () => {
loading = true;
@@ -65,7 +68,19 @@
if (group) {
name = group.name;
description = group.description;
permissions = group?.permissions ?? {};
permissions = group?.permissions ?? {
workspace: {
models: false,
knowledge: false,
prompts: false,
tools: false
},
chat: {
delete: true,
edit: true,
temporary: true
}
};
userIds = group?.user_ids ?? [];
}
};
@@ -200,9 +215,9 @@
{#if selectedTab == 'general'}
<Display bind:name bind:description />
{:else if selectedTab == 'permissions'}
<Permissions bind:permissions {custom} />
<Permissions bind:permissions />
{:else if selectedTab == 'users'}
<Users bind:userIds bind:adminIds {users} />
<Users bind:userIds {users} />
{/if}
</div>
</div>

View File

@@ -1,7 +1,13 @@
<script>
import { toast } from 'svelte-sonner';
import { getContext } from 'svelte';
const i18n = getContext('i18n');
import { deleteGroupById, updateGroupById } from '$lib/apis/groups';
import Pencil from '$lib/components/icons/Pencil.svelte';
import User from '$lib/components/icons/User.svelte';
import UserCircleSolid from '$lib/components/icons/UserCircleSolid.svelte';
import GroupModal from './EditGroupModal.svelte';
@@ -11,10 +17,43 @@
user_ids: [1, 2, 3]
};
export let setGroups = () => {};
let showEdit = false;
const updateHandler = async (_group) => {
const res = await updateGroupById(localStorage.token, group.id, _group).catch((error) => {
toast.error(error);
return null;
});
if (res) {
toast.success($i18n.t('Group updated successfully'));
setGroups();
}
};
const deleteHandler = async () => {
const res = await deleteGroupById(localStorage.token, group.id).catch((error) => {
toast.error(error);
return null;
});
if (res) {
toast.success($i18n.t('Group deleted successfully'));
setGroups();
}
};
</script>
<GroupModal bind:show={showEdit} edit {group} {users} />
<GroupModal
bind:show={showEdit}
edit
{users}
{group}
onSubmit={updateHandler}
onDelete={deleteHandler}
/>
<div class="flex items-center gap-3 justify-between px-1 text-xs w-full transition">
<div class="flex items-center gap-1.5 w-full font-medium">

View File

@@ -3,34 +3,25 @@
const i18n = getContext('i18n');
import Switch from '$lib/components/common/Switch.svelte';
import { models } from '$lib/stores';
import Minus from '$lib/components/icons/Minus.svelte';
import Plus from '$lib/components/icons/Plus.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
export let permissions = {};
export let custom = true;
let defaultModelId = '';
let selectedModelId = '';
let filterEnabled = false;
let filterMode = 'include';
let filterModelIds = [];
let workspaceModelsAccess = false;
let workspaceKnowledgeAccess = false;
let workspacePromptsAccess = false;
let workspaceToolsAccess = false;
let workspaceFunctionsAccess = false;
let chatDeletion = true;
let chatEdit = true;
let chatTemporary = true;
export let permissions = {
workspace: {
models: false,
knowledge: false,
prompts: false,
tools: false
},
chat: {
delete: true,
edit: true,
temporary: true
}
};
</script>
<div>
<div>
<!-- <div>
<div class=" mb-2 text-sm font-medium">{$i18n.t('Model Permissions')}</div>
<div class="mb-2">
@@ -130,52 +121,46 @@
</div>
</div>
<hr class=" border-gray-50 dark:border-gray-850 my-2" />
<hr class=" border-gray-50 dark:border-gray-850 my-2" /> -->
<div>
<div class=" mb-2 text-sm font-medium">{$i18n.t('Workspace Permissions')}</div>
<div class=" flex w-full justify-between my-2 pr-2">
<div class=" self-center text-xs font-medium">
{#if custom}
{$i18n.t('Admins')}:
{/if}
{$i18n.t('Models Access')}
</div>
<Switch bind:state={workspaceModelsAccess} />
<Switch bind:state={permissions.workspace.models} />
</div>
<div class=" flex w-full justify-between my-2 pr-2">
<div class=" self-center text-xs font-medium">
{#if custom}
{$i18n.t('Admins')}:
{/if}
{$i18n.t('Knowledge Access')}
</div>
<Switch bind:state={workspaceKnowledgeAccess} />
<Switch bind:state={permissions.workspace.knowledge} />
</div>
<div class=" flex w-full justify-between my-2 pr-2">
<div class=" self-center text-xs font-medium">
{#if custom}
{$i18n.t('Admins')}:
{/if}
{$i18n.t('Prompts Access')}
</div>
<Switch bind:state={workspacePromptsAccess} />
<Switch bind:state={permissions.workspace.prompts} />
</div>
<!-- <div class=" flex w-full justify-between my-2 pr-2">
<div class=" self-center text-xs font-medium">{$i18n.t('Allow Tools Access')}</div>
<Switch bind:state={workspaceToolsAccess} />
<div class=" ">
<Tooltip
className=" flex w-full justify-between my-2 pr-2"
content={$i18n.t(
'Warning: Enabling this will allow users to upload arbitrary code on the server.'
)}
placement="top-start"
>
<div class=" self-center text-xs font-medium">
{$i18n.t('Tools Access')}
</div>
<Switch bind:state={permissions.workspace.tools} />
</Tooltip>
</div>
<div class=" flex w-full justify-between my-2 pr-2">
<div class=" self-center text-xs font-medium">{$i18n.t('Allow Functions Access')}</div>
<Switch bind:state={workspaceFunctionsAccess} />
</div> -->
</div>
<hr class=" border-gray-50 dark:border-gray-850 my-2" />
@@ -185,35 +170,26 @@
<div class=" flex w-full justify-between my-2 pr-2">
<div class=" self-center text-xs font-medium">
{#if custom}
{$i18n.t('Members')}:
{/if}
{$i18n.t('Allow Chat Deletion')}
{$i18n.t('Allow Chat Delete')}
</div>
<Switch bind:state={chatDeletion} />
<Switch bind:state={permissions.chat.delete} />
</div>
<div class=" flex w-full justify-between my-2 pr-2">
<div class=" self-center text-xs font-medium">
{#if custom}
{$i18n.t('Members')}:
{/if}
{$i18n.t('Allow Chat Editing')}
{$i18n.t('Allow Chat Edit')}
</div>
<Switch bind:state={chatEdit} />
<Switch bind:state={permissions.chat.edit} />
</div>
<div class=" flex w-full justify-between my-2 pr-2">
<div class=" self-center text-xs font-medium">
{#if custom}
{$i18n.t('Members')}:
{/if}
{$i18n.t('Allow Temporary Chat')}
</div>
<Switch bind:state={chatTemporary} />
<Switch bind:state={permissions.chat.temporary} />
</div>
</div>
</div>

View File

@@ -10,7 +10,6 @@
export let users = [];
export let userIds = [];
export let adminIds = [];
let filteredUsers = [];
@@ -30,16 +29,10 @@
);
})
.sort((a, b) => {
const aIsAdmin = adminIds.includes(a.id);
const bIsAdmin = adminIds.includes(b.id);
const aUserIndex = userIds.indexOf(a.id);
const bUserIndex = userIds.indexOf(b.id);
// Admin users should come first
if (aIsAdmin && !bIsAdmin) return -1; // Place 'a' first if it's admin
if (!aIsAdmin && bIsAdmin) return 1; // Place 'b' first if it's admin
// Neither are admin, compare based on userIds or fall back to alphabetical order
// 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
@@ -114,20 +107,7 @@
</Tooltip>
{#if userIds.includes(user.id)}
<button
on:click={() => {
adminIds = adminIds.includes(user.id)
? adminIds.filter((id) => id !== user.id)
: [...adminIds, user.id];
}}
type="button"
>
{#if adminIds.includes(user.id)}
<Badge type="info" content="admin" />
{:else}
<Badge type="success" content="member" />
{/if}
</button>
<Badge type="success" content="member" />
{/if}
</div>
</div>