Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/lib/common/LoadingToComplete.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@
export let isLoading = false;
export let isComplete = false;
export let isError = false;
export let spinnerClasses = '';
export let spinnerStyles = '';
export let spinnerSize = 50;

export let successText = 'Update completed!';
export let errorText = 'Error!';
export let spinnerSize = 50;
</script>

{#if isLoading}
<Loader size={spinnerSize} />
<Loader
size={spinnerSize}
containerClasses={spinnerClasses}
containerStyles={spinnerStyles}
/>
{/if}


Expand Down
29 changes: 29 additions & 0 deletions src/lib/common/shared/GlobalHeader.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script>
import { onMount, onDestroy } from 'svelte';
import { globalErrorStore, loaderStore } from '$lib/helpers/store';

/** @type {boolean} */
export let isLoading = false;
export let hasError = false;

/** @type {any} */
let loaderUnsubscriber;
/** @type {any} */
let errorUnsubscriber;

onMount(() => {
window?.speechSynthesis?.cancel();
loaderUnsubscriber = loaderStore.subscribe(value => {
isLoading = value;
});

errorUnsubscriber = globalErrorStore.subscribe(value => {
hasError = value;
});
});

onDestroy(() => {
loaderUnsubscriber?.();
errorUnsubscriber?.();
});
</script>
32 changes: 20 additions & 12 deletions src/lib/helpers/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const retryQueue = {
/** @param {{config: import('axios').InternalAxiosRequestConfig, resolve: (value: any) => void, reject: (reason?: any) => void}} item */
enqueue(item) {
this.queue.push(item);

console.log('queue', this.queue.length);
if (!this.isRefreshingToken) {
const user = getUserStore();
if (!isTokenExired(user.expires)) {
Expand Down Expand Up @@ -130,7 +130,7 @@ axios.interceptors.response.use(
loaderStore.set(false);
const originalRequest = error?.config || {};
const user = getUserStore();
console.log("renew token count.", user.renew_token_count);

if (!user?.token || user.renew_token_count >= retryQueue.maxRenewTokenCount) {
retryQueue.queue = [];
redirectToLogin();
Expand Down Expand Up @@ -185,7 +185,7 @@ function skipLoader(config) {
new RegExp('http(s*)://(.*?)/knowledge/vector/(.*?)/create', 'g'),
new RegExp('http(s*)://(.*?)/knowledge/document/(.*?)/page', 'g'),
new RegExp('http(s*)://(.*?)/users', 'g'),
new RegExp('http(s*)://(.*?)/instruct/chat-completion', 'g'),
new RegExp('http(s*)://(.*?)/instruct/(.*?)', 'g'),
new RegExp('http(s*)://(.*?)/agent/(.*?)/code-scripts', 'g'),
new RegExp('http(s*)://(.*?)/agent/(.*?)/code-script/generate', 'g'),
new RegExp('http(s*)://(.*?)/renew-token', 'g')
Expand All @@ -208,24 +208,30 @@ function skipLoader(config) {

/** @type {RegExp[]} */
const getRegexes = [
new RegExp('http(s*)://(.*?)/plugin/menu', 'g'),
new RegExp('http(s*)://(.*?)/setting/(.*?)', 'g'),
new RegExp('http(s*)://(.*?)/roles', 'g'),
new RegExp('http(s*)://(.*?)/role/options', 'g'),
new RegExp('http(s*)://(.*?)/role/(.*?)/details', 'g'),
new RegExp('http(s*)://(.*?)/user/(.*?)/details', 'g'),
new RegExp('http(s*)://(.*?)/user/me', 'g'),
new RegExp('http(s*)://(.*?)/plugin/menu', 'g'),
new RegExp('http(s*)://(.*?)/address/options(.*?)', 'g'),
new RegExp('http(s*)://(.*?)/agents', 'g'),
new RegExp('http(s*)://(.*?)/agent/options', 'g'),
new RegExp('http(s*)://(.*?)/agent/labels', 'g'),
new RegExp('http(s*)://(.*?)/agent/tasks', 'g'),
new RegExp('http(s*)://(.*?)/agent/(.*?)/code-scripts', 'g'),
new RegExp('http(s*)://(.*?)/conversation/state/keys', 'g'),
new RegExp('http(s*)://(.*?)/conversation/(.*?)/files/(.*?)', 'g'),
new RegExp('http(s*)://(.*?)/llm-configs', '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*)://(.*?)/role/options', 'g'),
new RegExp('http(s*)://(.*?)/role/(.*?)/details', 'g'),
new RegExp('http(s*)://(.*?)/user/(.*?)/details', 'g'),
new RegExp('http(s*)://(.*?)/agent/labels', 'g'),
new RegExp('http(s*)://(.*?)/conversation/state/keys', 'g'),
new RegExp('http(s*)://(.*?)/logger/instruction/log', 'g'),
new RegExp('http(s*)://(.*?)/logger/instruction/log/keys', 'g'),
new RegExp('http(s*)://(.*?)/logger/conversation/(.*?)/content-log', 'g'),
new RegExp('http(s*)://(.*?)/logger/conversation/(.*?)/state-log', 'g'),
new RegExp('http(s*)://(.*?)/mcp/server-configs', 'g'),
new RegExp('http(s*)://(.*?)/agent/(.*?)/code-scripts', 'g')
new RegExp('http(s*)://(.*?)/mcp/server-configs', 'g')
];

if (config.method === 'post' && postRegexes.some(regex => regex.test(config.url || ''))) {
Expand Down Expand Up @@ -276,7 +282,9 @@ function skipGlobalError(config) {
];

/** @type {RegExp[]} */
const getRegexes = [];
const getRegexes = [
new RegExp('http(s*)://(.*?)/agents', 'g')
];

if (config.method === 'post' && postRegexes.some(regex => regex.test(config.url || ''))) {
return true;
Expand Down
18 changes: 16 additions & 2 deletions src/lib/helpers/utils/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,18 +120,19 @@ export function getPagingQueryParams(args, defaults = { defaultPageSize: 12, max
/**
* @param {URL} url
* @param {import('$commonTypes').KeyValuePair[]} pairs
* @param {() => void} [callback]
* @param {(args0: URL) => void} [callback]
*/
export function setUrlQueryParams(url, pairs, callback) {
if (!pairs?.length) {
return;
}

url.search = '';
pairs?.map(p => {
url.searchParams.set(p.key, p.value);
});

callback?.();
callback?.(url);
}

/**
Expand Down Expand Up @@ -175,6 +176,19 @@ export function splitTextByCase(str) {
return text;
}

/**
* @param {string} url
*/
export function getCleanUrl(url) {
if (!url) return url;

if (url.startsWith('/')) {
url = url.substring(1);
}

return url;
}

/**
* @param {string} timeRange
* @returns {{ startTime: string | null, endTime: string | null }}
Expand Down
14 changes: 14 additions & 0 deletions src/lib/scss/custom/common/_common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,17 @@ button:focus {
text-overflow: ellipsis;
}
}

.text-btn {
background: none;
border: none;
padding: 0;
color: inherit;
font-weight: 500;
cursor: pointer;

&:hover {
text-decoration: none;
background: none;
}
}
2 changes: 1 addition & 1 deletion src/lib/scss/custom/components/_loader.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.loader {
position: fixed;
position: absolute;
z-index: 9999;
background-color: rgba(255, 255, 255, 0.8);
top: 0;
Expand Down
29 changes: 28 additions & 1 deletion src/lib/scss/custom/pages/_agent.scss
Original file line number Diff line number Diff line change
@@ -1,10 +1,37 @@
.agents-header-container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: 15px;
align-items: center;

@media (max-width: 576px) {
flex-direction: column;
justify-content: center;
gap: 12px;

> div {
width: 100%;
display: flex;
justify-content: center;
}
}

.agent-filter {
display: flex;
gap: 10px
flex-wrap: wrap;
gap: 10px;
align-items: center;

@media (max-width: 576px) {
width: 100%;
flex-direction: column;
gap: 8px;

> * {
width: 100%;
}
}
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/lib/services/agent-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ export async function getSettings() {
* Get agent list
* @param {import('$agentTypes').AgentFilter} filter
* @param {boolean} checkAuth
* @param {AbortSignal | null} signal
* @returns {Promise<import('$commonTypes').PagedItems<import('$agentTypes').AgentModel>>}
*/
export async function getAgents(filter, checkAuth = false) {
export async function getAgents(filter, checkAuth = false, signal = null) {
let url = endpoints.agentListUrl;
const response = await axios.get(url, {
params: {
Expand All @@ -28,7 +29,8 @@ export async function getAgents(filter, checkAuth = false) {
paramsSerializer: {
dots: true,
indexes: null,
}
},
signal: signal || undefined
});
return response.data;
}
Expand Down
6 changes: 5 additions & 1 deletion src/lib/services/role-service.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { endpoints } from './api-endpoints.js';
import axios from 'axios';
import qs from 'qs';

/**
* Get role options
Expand All @@ -17,7 +18,10 @@ export async function getRoleOptions() {
* @returns {Promise<import('$roleTypes').RoleModel[]>}
*/
export async function getRoles(filter = null) {
const response = await axios.post(endpoints.rolesUrl, filter);
const response = await axios.get(endpoints.rolesUrl, {
params: filter,
paramsSerializer: (params) => qs.stringify(params, { encode: false, allowDots: true, arrayFormat: "indices" })
});
return response.data;
}

Expand Down
36 changes: 0 additions & 36 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,51 +1,15 @@
<script>
import { addMessages, init, getLocaleFromNavigator } from 'svelte-i18n';
import en from '$lib/langs/en.json';
import '$lib/helpers/http';
import { onDestroy, onMount } from 'svelte';
import { globalErrorStore, loaderStore } from '$lib/helpers/store';
import Loader from '$lib/common/Loader.svelte';
import LoadingToComplete from '$lib/common/LoadingToComplete.svelte';

addMessages('en', en);

init({
fallbackLocale: 'en',
initialLocale: getLocaleFromNavigator()
});

/** @type {boolean} */
let isLoading = false;
let hasError = false;

/** @type {any} */
let loaderUnsubscriber;
/** @type {any} */
let errorUnsubscriber;

onMount(() => {
window?.speechSynthesis?.cancel();
loaderUnsubscriber = loaderStore.subscribe(value => {
isLoading = value;
});

errorUnsubscriber = globalErrorStore.subscribe(value => {
hasError = value;
});
})

onDestroy(() => {
loaderUnsubscriber?.();
errorUnsubscriber?.();
});
</script>

{#if isLoading}
<Loader size={50}/>
{/if}

<LoadingToComplete isError={hasError} />

<slot />

<style lang="scss">
Expand Down
15 changes: 14 additions & 1 deletion src/routes/VerticalLayout/Index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import { getPluginMenu } from '$lib/services/plugin-service';
import { myInfo } from '$lib/services/auth-service';
import { globalMenuStore } from '$lib/helpers/store';
import LoadingToComplete from '$lib/common/LoadingToComplete.svelte';
import GlobalHeader from '$lib/common/shared/GlobalHeader.svelte';
import Header from './Header.svelte';
import Sidebar from './Sidebar.svelte';
import Footer from './Footer.svelte';
Expand All @@ -15,6 +17,10 @@
/** @type {import("$userTypes").UserModel} */
let user;

/** @type {boolean} */
let isLoading = false;
let hasError = false;

const toggleRightBar = () => {
if (browser) {
if (document.body.classList.contains('right-bar-enabled')) {
Expand All @@ -39,14 +45,21 @@
});
</script>

<GlobalHeader bind:isLoading={isLoading} bind:hasError={hasError} />

<div id="layout-wrapper">
<Header user={user} toggleRightBar={() => toggleRightBar()} />
{#if menu}
<Sidebar menu={menu}/>
{/if}
<div class="main-content">
<div class="page-content">
<div class="container-fluid">
<div class="container-fluid" style="position: relative;">
<LoadingToComplete
spinnerSize={50}
isLoading={isLoading}
isError={hasError}
/>
<slot />
</div>
</div>
Expand Down
Loading