From 63031f872c3175b6e9c77e60833eb739ea808954 Mon Sep 17 00:00:00 2001
From: Jicheng Lu <103353@smsassist.com>
Date: Thu, 14 Nov 2024 11:55:50 -0600
Subject: [PATCH 1/3] refine users page
---
src/lib/common/Loader.svelte | 6 +-
src/lib/helpers/http.js | 5 +-
src/lib/helpers/types/roleTypes.js | 11 +
src/lib/scss/custom/pages/_users.scss | 8 +
src/lib/services/api-endpoints.js | 6 +
src/lib/services/role-service.js | 26 +++
src/lib/services/user-service.js | 12 ++
src/routes/page/mongodb/+page.svelte | 57 -----
src/routes/page/roles/+page.svelte | 5 +
src/routes/page/users/+page.svelte | 18 +-
src/routes/page/users/user-item.svelte | 285 ++++++++++++++-----------
svelte.config.js | 2 +
12 files changed, 253 insertions(+), 188 deletions(-)
create mode 100644 src/lib/helpers/types/roleTypes.js
create mode 100644 src/lib/services/role-service.js
delete mode 100644 src/routes/page/mongodb/+page.svelte
create mode 100644 src/routes/page/roles/+page.svelte
diff --git a/src/lib/common/Loader.svelte b/src/lib/common/Loader.svelte
index e84e9fa..30650a3 100644
--- a/src/lib/common/Loader.svelte
+++ b/src/lib/common/Loader.svelte
@@ -3,9 +3,13 @@
export let disableDefaultStyles = false;
export let containerClasses = '';
+ export let containerStyles = '';
export let size = 100;
-
+
diff --git a/src/lib/helpers/http.js b/src/lib/helpers/http.js
index 7f53127..d86e1e8 100644
--- a/src/lib/helpers/http.js
+++ b/src/lib/helpers/http.js
@@ -85,7 +85,10 @@ function skipLoader(config) {
new RegExp('http(s*)://(.*?)/conversation/(.*?)/files/(.*?)', 'g'),
new RegExp('http(s*)://(.*?)/llm-provider/(.*?)/models', 'g'),
new RegExp('http(s*)://(.*?)/knowledge/vector/collections', 'g'),
- new RegExp('http(s*)://(.*?)/knowledge/vector/(.*?)/exist', 'g')
+ new RegExp('http(s*)://(.*?)/knowledge/vector/(.*?)/exist', 'g'),
+ new RegExp('http(s*)://(.*?)/role/options', 'g'),
+ new RegExp('http(s*)://(.*?)/role/(.*?)/details', 'g'),
+ new RegExp('http(s*)://(.*?)/user/(.*?)/details', 'g'),
];
if (config.method === 'post' && postRegexes.some(regex => regex.test(config.url || ''))) {
diff --git a/src/lib/helpers/types/roleTypes.js b/src/lib/helpers/types/roleTypes.js
new file mode 100644
index 0000000..8ff08cc
--- /dev/null
+++ b/src/lib/helpers/types/roleTypes.js
@@ -0,0 +1,11 @@
+/**
+ * @typedef {Object} RoleModel
+ * @property {string} id - The user id.
+ * @property {string} [name] - Role name
+ * @property {string[]} permissions - Permissions.
+ * @property {string} [create_date] - The user create date.
+ * @property {string} [update_date] - The user update date.
+ */
+
+
+export default {};
\ No newline at end of file
diff --git a/src/lib/scss/custom/pages/_users.scss b/src/lib/scss/custom/pages/_users.scss
index e413348..84ecd8a 100644
--- a/src/lib/scss/custom/pages/_users.scss
+++ b/src/lib/scss/custom/pages/_users.scss
@@ -46,6 +46,14 @@
}
}
+ .role-wrapper {
+ .role-select {
+ height: 30px;
+ font-size: 12px;
+ padding: 0.3rem 1rem;
+ }
+ }
+
.user-permission-container {
display: flex;
gap: 5px;
diff --git a/src/lib/services/api-endpoints.js b/src/lib/services/api-endpoints.js
index 1c4a95d..265d761 100644
--- a/src/lib/services/api-endpoints.js
+++ b/src/lib/services/api-endpoints.js
@@ -2,10 +2,16 @@ import { PUBLIC_SERVICE_URL } from '$env/static/public';
export const host = PUBLIC_SERVICE_URL;
export const endpoints = {
+ // role
+ roleOptionsUrl: `${host}/role/options`,
+ rolesUrl: `${host}/roles`,
+ roleDetailUrl: `${host}/role/{id}/details`,
+
// user
tokenUrl: `${host}/token`,
myInfoUrl: `${host}/user/me`,
usersUrl: `${host}/users`,
+ userDetailUrl: `${host}/user/{id}/details`,
userUpdateUrl: `${host}/user`,
usrCreationUrl: `${host}/user`,
userAvatarUrl: `${host}/user/avatar`,
diff --git a/src/lib/services/role-service.js b/src/lib/services/role-service.js
new file mode 100644
index 0000000..0fa8339
--- /dev/null
+++ b/src/lib/services/role-service.js
@@ -0,0 +1,26 @@
+import { endpoints } from './api-endpoints.js';
+import axios from 'axios';
+
+/**
+ * Get role options
+ * @returns {Promise
}
+ */
+export async function getRoleOptions() {
+ const response = await axios.get(endpoints.roleOptionsUrl);
+ return response.data;
+}
+
+
+
+
+
+/**
+ * Get user detail
+ * @param {string} id
+ * @returns {Promise}
+ */
+export async function getRoleDetails(id) {
+ const url = endpoints.roleDetailUrl.replace("{id}", id);
+ const response = await axios.get(url);
+ return response.data;
+}
diff --git a/src/lib/services/user-service.js b/src/lib/services/user-service.js
index dacb88d..eadc395 100644
--- a/src/lib/services/user-service.js
+++ b/src/lib/services/user-service.js
@@ -12,6 +12,18 @@ export async function getUsers(filter) {
}
+/**
+ * Get user detail
+ * @param {string} id
+ * @returns {Promise}
+ */
+export async function getUserDetails(id) {
+ const url = endpoints.userDetailUrl.replace("{id}", id);
+ const response = await axios.get(url);
+ return response.data;
+}
+
+
/**
* Get user list
* @param {import('$userTypes').UserModel} model
diff --git a/src/routes/page/mongodb/+page.svelte b/src/routes/page/mongodb/+page.svelte
deleted file mode 100644
index 979a1d3..0000000
--- a/src/routes/page/mongodb/+page.svelte
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
-
-{$_('Migrate agents from file repository to MongoDB')}
-
\ No newline at end of file
diff --git a/src/routes/page/roles/+page.svelte b/src/routes/page/roles/+page.svelte
new file mode 100644
index 0000000..339712a
--- /dev/null
+++ b/src/routes/page/roles/+page.svelte
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/src/routes/page/users/+page.svelte b/src/routes/page/users/+page.svelte
index 54aba8f..8fc2034 100644
--- a/src/routes/page/users/+page.svelte
+++ b/src/routes/page/users/+page.svelte
@@ -21,6 +21,7 @@
import { getAgents } from '$lib/services/agent-service';
import { globalEventStore } from '$lib/helpers/store';
import { GlobalEvent } from '$lib/helpers/enums';
+ import { getRoleOptions } from '$lib/services/role-service';
const duration = 3000;
const firstPage = 1;
@@ -47,6 +48,9 @@
/** @type {import('$commonTypes').IdName[]} */
let agents = [];
+ /** @type {string[]} */
+ let roleOptions = [];
+
/** @type {any} */
let unsubscriber;
@@ -79,11 +83,14 @@
function init() {
isLoading = true;
- getPagedAgents().then(() => {
- getPagedUsers().then(() => {
- isLoading = false;
- });
- });
+ getRoleOptions().then(roles => {
+ roleOptions = [...roles];
+ getPagedAgents().then(() => {
+ getPagedUsers().then(() => {
+ isLoading = false;
+ });
+ });
+ });
}
function getPagedUsers() {
@@ -273,6 +280,7 @@
saveUser(e)}
/>
diff --git a/src/routes/page/users/user-item.svelte b/src/routes/page/users/user-item.svelte
index 0766554..855f93d 100644
--- a/src/routes/page/users/user-item.svelte
+++ b/src/routes/page/users/user-item.svelte
@@ -2,11 +2,13 @@
import { createEventDispatcher, onMount } from 'svelte';
import { fly } from 'svelte/transition';
import { Button, Input } from '@sveltestrap/sveltestrap';
+ import { v4 as uuidv4 } from 'uuid';
import Swal from 'sweetalert2';
import lodash from "lodash";
- import InPlaceEdit from '$lib/common/InPlaceEdit.svelte';
+ import Loader from '$lib/common/Loader.svelte';
import { UserAction } from '$lib/helpers/enums';
- import { v4 as uuidv4 } from 'uuid';
+ import { getUserDetails } from '$lib/services/user-service';
+
const svelteDispatch = createEventDispatcher();
@@ -23,6 +25,12 @@
/** @type {import('$commonTypes').IdName[]} */
export let agents = [];
+ /** @type {string[]} */
+ export let roleOptions = [];
+
+
+ /** @type {boolean} */
+ let isLoading = false;
/** @type {import('$userTypes').UserModel} */
let innerItem = { ...item };
@@ -104,10 +112,26 @@
function toggleUserDetail() {
open = !open;
if (open) {
- initAgentActions();
+ isLoading = true;
+ getUserDetails(item.id).then(res => {
+ innerItem = { ...res };
+ initAgentActions();
+ }).finally(() => {
+ isLoading = false;
+ });
}
}
+
+ /** @param {any} e */
+ function changeRole(e) {
+ const value = e.target.value;
+ innerItem = {
+ ...innerItem,
+ role: value
+ };
+ }
+
/**
* @param {any} e
* @param {import('$userTypes').UserAgentInnerAction} agentActionItem
@@ -245,143 +269,156 @@
{#if open}
+
-
-
-
-
-
- save(item.id)}
- >
-
-
-
-
- -
-
- {'User name:'}
- {item.user_name}
+ {#if isLoading}
+
+
+ |
+ {:else}
+
+
+
+
+
+ save(item.id)}
+ >
+
-
- {#if item.full_name}
- -
-
- {'Full name:'}
- {item.full_name}
-
-
- {/if}
- {#if item.role}
- -
-
-
- {/if}
- {#if item.source}
- -
-
- {'Source:'}
- {item.source}
-
-
- {/if}
- {#if item.type}
- -
-
- {'Type:'}
- {item.type}
-
-
- {/if}
-
-
- -
-
- {'Permissions:'}
-
- {#each innerItem.permissions as permission, index}
-
-
-
+
+
+ -
+
+ {'User name:'}
+ {item.user_name}
+
+
+ {#if item.full_name}
+ -
+
+ {'Full name:'}
+ {item.full_name}
+
+
+ {/if}
+ {#if item.type}
+ -
+
+ {'Type:'}
+ {item.type}
+
+
+ {/if}
+ {#if item.source}
+ -
+
+ {'Source:'}
+ {item.source}
+
+
+ {/if}
+ {#if item.role}
+ -
+
+ {'Role:'}
+
+ changeRole(e)}>
+ {#each roleOptions as option}
+
+ {/each}
+
+
+
+
+ {/if}
+
+
+ -
+
+ {'Permissions:'}
+
+ {#each innerItem.permissions as permission, index}
+
+
+
+ {}}
+ on:click={() => deletePermission(index)}
+ />
+
+
+ {/each}
+ {#if innerItem.permissions?.length < 5}
+
{}}
- on:click={() => deletePermission(index)}
+ on:click={() => addPermission()}
/>
-
- {/each}
- {#if innerItem.permissions?.length < 5}
-
- {}}
- on:click={() => addPermission()}
- />
-
- {/if}
-
-
-
-
-
- {#if innerActions.length > 0}
-
-
- {#each allActions as title}
+
+
+
+ {#if innerActions.length > 0}
+
+
- {title.name}
-
- checkAll(e, title)}
- />
-
+ {'Agent'}
- {/each}
-
-
- {#each innerActions as agentActionItem}
-
-
- {agentActionItem.agent_name}
-
- {#each agentActionItem.actions as actionItem}
-
+ {#each allActions as title}
+
+ {title.name}
+
checkAction(e, agentActionItem, actionItem)}
+ checked={title.checked}
+ on:change={e => checkAll(e, title)}
/>
- {/each}
-
- {/each}
+
+ {/each}
+
+
+ {#each innerActions as agentActionItem}
+
+
+ {agentActionItem.agent_name}
+
+ {#each agentActionItem.actions as actionItem}
+
+ checkAction(e, agentActionItem, actionItem)}
+ />
+
+ {/each}
+
+ {/each}
+
-
- {/if}
-
- |
+ {/if}
+
+ |
+ {/if}
{/if}
\ No newline at end of file
diff --git a/svelte.config.js b/svelte.config.js
index 208fd8d..c59ac90 100644
--- a/svelte.config.js
+++ b/svelte.config.js
@@ -14,6 +14,7 @@ const config = {
$fileTypes: './src/lib/helpers/types/fileTypes.js',
$audioTypes: './src/lib/helpers/types/audioTypes.js',
$userTypes: './src/lib/helpers/types/userTypes.js',
+ $roleTypes: './src/lib/helpers/types/roleTypes.js',
$pluginTypes: './src/lib/helpers/types/pluginTypes.js',
},
@@ -60,6 +61,7 @@ const config = {
"/page/mongodb",
"/page/user/me",
"/page/users",
+ "/page/roles",
"/chat",
"/chat/[agentId]",
"/chat/[agentId]/[conversationId]",
From 5ad4bf3025d6508f9a54c48f0e5d49f966351704 Mon Sep 17 00:00:00 2001
From: Jicheng Lu <103353@smsassist.com>
Date: Thu, 14 Nov 2024 17:33:00 -0600
Subject: [PATCH 2/3] add role manage page
---
src/lib/helpers/enums.js | 2 +
src/lib/helpers/types/roleTypes.js | 23 ++
src/lib/helpers/types/userTypes.js | 1 +
src/lib/scss/app.scss | 1 +
src/lib/scss/custom/pages/_roles.scss | 119 ++++++
src/lib/scss/custom/pages/_users.scss | 5 -
src/lib/services/api-endpoints.js | 1 +
src/lib/services/role-service.js | 21 +-
.../[conversationId]/chat-box.svelte | 2 +-
.../agent/[agentId]/agent-overview.svelte | 2 +-
src/routes/page/agent/card-agent.svelte | 2 +-
src/routes/page/roles/+page.svelte | 184 ++++++++-
src/routes/page/roles/role-item.svelte | 380 ++++++++++++++++++
src/routes/page/users/+page.svelte | 29 +-
src/routes/page/users/user-item.svelte | 15 +-
15 files changed, 752 insertions(+), 35 deletions(-)
create mode 100644 src/lib/scss/custom/pages/_roles.scss
create mode 100644 src/routes/page/roles/role-item.svelte
diff --git a/src/lib/helpers/enums.js b/src/lib/helpers/enums.js
index 06af879..af4db40 100644
--- a/src/lib/helpers/enums.js
+++ b/src/lib/helpers/enums.js
@@ -125,6 +125,8 @@ export const UserPermission = Object.freeze(userPermission);
const userAction = {
Edit: "edit",
+ Train: "train",
+ Evaluate: "evaluate",
Chat: "chat"
};
export const UserAction = Object.freeze(userAction);
diff --git a/src/lib/helpers/types/roleTypes.js b/src/lib/helpers/types/roleTypes.js
index 8ff08cc..1e036b9 100644
--- a/src/lib/helpers/types/roleTypes.js
+++ b/src/lib/helpers/types/roleTypes.js
@@ -3,9 +3,32 @@
* @property {string} id - The user id.
* @property {string} [name] - Role name
* @property {string[]} permissions - Permissions.
+ * @property {RoleAgentAction[]} agent_actions - Agent actions
* @property {string} [create_date] - The user create date.
* @property {string} [update_date] - The user update date.
+ * @property {boolean} [open_detail]
*/
+/**
+ * @typedef {Object} RoleAgentAction
+ * @property {string?} [id] - The id
+ * @property {string} agent_id - The agent id
+ * @property {import('$agentTypes').AgentModel} [agent] - The agent details
+ * @property {string[]} actions - The actions
+ */
+
+/**
+ * @typedef {Object} RoleAgentInnerAction
+ * @property {string?} [id] - The id
+ * @property {string} agent_id - The agent id
+ * @property {string} [agent_name] - The agent name
+ * @property {import('$agentTypes').AgentModel} [agent] - The agent details
+ * @property {{ key: string, value: string, checked: boolean }[]} actions - The actions
+ */
+
+/**
+ * @typedef {Object} RoleFilter
+ * @property {string[]} [names] - The role names.
+ */
export default {};
\ No newline at end of file
diff --git a/src/lib/helpers/types/userTypes.js b/src/lib/helpers/types/userTypes.js
index 529afe2..e48a851 100644
--- a/src/lib/helpers/types/userTypes.js
+++ b/src/lib/helpers/types/userTypes.js
@@ -44,6 +44,7 @@
* @property {string[]} [user_ids] - The user ids.
* @property {string[]} [user_names] - The user names
* @property {string[]} [roles] - The roles.
+ * @property {string[]} [types] - The types.
* @property {string[]} [sources] - The sources.
* @property {string[]} [external_ids] - The external ids.
*/
diff --git a/src/lib/scss/app.scss b/src/lib/scss/app.scss
index 7d11262..604f0c2 100644
--- a/src/lib/scss/app.scss
+++ b/src/lib/scss/app.scss
@@ -94,6 +94,7 @@ File: Main Css File
@import "custom/pages/agent";
@import "custom/pages/knowledgebase";
@import "custom/pages/users";
+@import "custom/pages/roles";
// Common
@import "custom/common/animation";
diff --git a/src/lib/scss/custom/pages/_roles.scss b/src/lib/scss/custom/pages/_roles.scss
new file mode 100644
index 0000000..076c269
--- /dev/null
+++ b/src/lib/scss/custom/pages/_roles.scss
@@ -0,0 +1,119 @@
+.roles-table {
+ .role-plain-col {
+ width: 10%;
+ max-width: 100px;
+ }
+
+ .role-permission-col {
+ width: 40%;
+ max-width: 300px;
+ }
+
+ .role-detail {
+ padding: 2px 5px;
+ border-radius: 3px;
+ border-color: var(--#{$prefix}light) !important;
+ background-color: var(--#{$prefix}light) !important;
+ position: relative;
+
+ ul {
+ li {
+ margin: 2px 0px;
+ }
+ }
+
+ .wrappable {
+ white-space: wrap !important;
+ }
+
+ .basic-info {
+ margin: 15px 0px 0px 0px;
+ display: flex;
+ flex-wrap: wrap;
+
+ li {
+ flex: 0 0 50%;
+
+ .inline-edit {
+ display: flex;
+ gap: 3px;
+ }
+ }
+ }
+
+ .role-permission-container {
+ display: flex;
+ gap: 5px;
+
+ .permission-wrapper {
+ display: flex;
+ flex-direction: column;
+ gap: 3px;
+
+ .edit-wrapper {
+ display: flex;
+ gap: 3px;
+ }
+
+ input[type="text"] {
+ height: 30px;
+ font-size: 12px;
+ }
+ }
+
+
+ .list-add {
+ font-size: 18px;
+ }
+ }
+
+ .role-agent-container {
+ margin: 20px 0px;
+ padding: 0px 2rem;
+
+ .action-row-wrapper {
+ overflow-y: auto;
+ scrollbar-width: thin;
+ height: fit-content;
+ max-height: 300px;
+ }
+
+ .action-row {
+ display: flex;
+ }
+
+ .action-col {
+ padding: 3px 0px;
+
+ input[type='checkbox'] {
+ outline: none !important;
+ box-shadow: none !important;
+ }
+ }
+
+ .action-title {
+ .action-title-wrapper {
+ display: flex;
+ gap: 3px;
+ justify-content: center;
+ text-transform: capitalize;
+ text-align: center;
+ border-bottom: 2px solid var(--bs-primary);
+ }
+ }
+
+ .action-center {
+ display: flex;
+ justify-content: center;
+ }
+ }
+
+ .edit-btn {
+ display: flex;
+ justify-content: flex-end;
+ font-size: 16px;
+ margin-top: 3px;
+ margin-right: 5px;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/lib/scss/custom/pages/_users.scss b/src/lib/scss/custom/pages/_users.scss
index 84ecd8a..e948ee1 100644
--- a/src/lib/scss/custom/pages/_users.scss
+++ b/src/lib/scss/custom/pages/_users.scss
@@ -8,11 +8,6 @@
width: 20%;
max-width: 300px;
}
-
- .user-agent-col {
- width: 25%;
- max-width: 350px;
- }
.user-detail {
padding: 2px 5px;
diff --git a/src/lib/services/api-endpoints.js b/src/lib/services/api-endpoints.js
index 265d761..7c9929c 100644
--- a/src/lib/services/api-endpoints.js
+++ b/src/lib/services/api-endpoints.js
@@ -6,6 +6,7 @@ export const endpoints = {
roleOptionsUrl: `${host}/role/options`,
rolesUrl: `${host}/roles`,
roleDetailUrl: `${host}/role/{id}/details`,
+ roleUpdateUrl: `${host}/role`,
// user
tokenUrl: `${host}/token`,
diff --git a/src/lib/services/role-service.js b/src/lib/services/role-service.js
index 0fa8339..15f4011 100644
--- a/src/lib/services/role-service.js
+++ b/src/lib/services/role-service.js
@@ -11,7 +11,15 @@ export async function getRoleOptions() {
}
-
+/**
+ * Get role list
+ * @param {import('$roleTypes').RoleFilter?} [filter]
+ * @returns {Promise}
+ */
+export async function getRoles(filter = null) {
+ const response = await axios.post(endpoints.rolesUrl, filter);
+ return response.data;
+}
/**
@@ -24,3 +32,14 @@ export async function getRoleDetails(id) {
const response = await axios.get(url);
return response.data;
}
+
+
+/**
+ * Update role
+ * @param {import('$roleTypes').RoleModel} model
+ * @returns {Promise}
+ */
+export async function updateRole(model) {
+ const response = await axios.put(endpoints.roleUpdateUrl, { ...model });
+ return response.data;
+}
\ No newline at end of file
diff --git a/src/routes/chat/[agentId]/[conversationId]/chat-box.svelte b/src/routes/chat/[agentId]/[conversationId]/chat-box.svelte
index 7f42d0e..8b8e4a3 100644
--- a/src/routes/chat/[agentId]/[conversationId]/chat-box.svelte
+++ b/src/routes/chat/[agentId]/[conversationId]/chat-box.svelte
@@ -202,7 +202,7 @@
}
$: {
- disableAction = !ADMIN_ROLES.includes(currentUser?.role || '') && currentUser?.id !== conversationUser?.id;
+ disableAction = !ADMIN_ROLES.includes(currentUser?.role || '') && currentUser?.id !== conversationUser?.id || !agent?.chatable;
}
setContext('chat-window-context', {
diff --git a/src/routes/page/agent/[agentId]/agent-overview.svelte b/src/routes/page/agent/[agentId]/agent-overview.svelte
index 4975286..e4a5e5c 100644
--- a/src/routes/page/agent/[agentId]/agent-overview.svelte
+++ b/src/routes/page/agent/[agentId]/agent-overview.svelte
@@ -75,7 +75,7 @@
height="50"
class="mx-auto d-block"
/>
- {#if 1}
+ {#if !!agent.chatable}