mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2024-12-19 20:37:51 +00:00
enhanced ui
This commit is contained in:
parent
4c46dbf094
commit
f6991ecb44
10
app.py
10
app.py
@ -174,6 +174,10 @@ class LoLLMsWebUI(LoLLMsAPPI):
|
||||
self.add_endpoint(
|
||||
"/list_bindings", "list_bindings", self.list_bindings, methods=["GET"]
|
||||
)
|
||||
self.add_endpoint(
|
||||
"/list_extensions", "list_extensions", self.list_extensions, methods=["GET"]
|
||||
)
|
||||
|
||||
self.add_endpoint(
|
||||
"/list_models", "list_models", self.list_models, methods=["GET"]
|
||||
)
|
||||
@ -677,6 +681,10 @@ class LoLLMsWebUI(LoLLMsAPPI):
|
||||
print(f"Couldn't load backend card : {f}\n\t{ex}")
|
||||
return jsonify(bindings)
|
||||
|
||||
def list_extensions(self):
|
||||
return jsonify([])
|
||||
|
||||
|
||||
|
||||
def list_models(self):
|
||||
if self.binding is not None:
|
||||
@ -1312,7 +1320,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
|
||||
def upload_avatar(self):
|
||||
file = request.files['avatar']
|
||||
file.save(self.lollms_paths.personal_user_infos_path/file.filename)
|
||||
return jsonify({"status": True,"file":file.filename})
|
||||
return jsonify({"status": True,"fileName":file.filename})
|
||||
|
||||
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
web/dist/index.html
vendored
4
web/dist/index.html
vendored
@ -6,8 +6,8 @@
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>LoLLMS WebUI - Welcome</title>
|
||||
<script type="module" crossorigin src="/assets/index-45195456.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-2014a4be.css">
|
||||
<script type="module" crossorigin src="/assets/index-4c5ae20c.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-562b86e9.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
@ -27,8 +27,7 @@ export const store = createStore({
|
||||
diskUsage:null,
|
||||
ramUsage:null,
|
||||
vramUsage:null,
|
||||
|
||||
|
||||
extensionsZoo:null,
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
@ -63,6 +62,9 @@ export const store = createStore({
|
||||
state.vramUsage = vramUsage;
|
||||
},
|
||||
|
||||
setExtensionsZoo(state, extensionsZoo) {
|
||||
state.extensionsZoo = extensionsZoo;
|
||||
},
|
||||
setModelsZoo(state, modelsZoo) {
|
||||
state.models_zoo = modelsZoo;
|
||||
},
|
||||
@ -104,6 +106,9 @@ export const store = createStore({
|
||||
getModelsZoo(state) {
|
||||
return state.models_zoo;
|
||||
},
|
||||
getExtensionsZoo(state) {
|
||||
return state.extensionsZoo;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
|
||||
@ -192,6 +197,10 @@ export const store = createStore({
|
||||
let modelsArr = await api_get_req("list_models")
|
||||
commit('setModelsArr',modelsArr)
|
||||
},
|
||||
async refreshExtensionsZoo({ commit }) {
|
||||
let extensionsZoo = await api_get_req("list_extensions")
|
||||
commit('setExtensionsZoo',extensionsZoo)
|
||||
},
|
||||
|
||||
async refreshDiskUsage({ commit }) {
|
||||
this.state.diskUsage = await api_get_req("disk_usage")
|
||||
@ -350,6 +359,8 @@ app.mixin({
|
||||
this.$store.dispatch('refreshRamUsage');
|
||||
this.$store.dispatch('refreshVramUsage');
|
||||
this.$store.dispatch('refreshModelsZoo');
|
||||
this.$store.dispatch('refreshExtensionsZoo');
|
||||
|
||||
|
||||
this.$store.state.ready = true
|
||||
console.log("done loading data")
|
||||
|
@ -50,9 +50,10 @@
|
||||
<div class=" sticky z-10 top-0 bg-bg-light-tone dark:bg-bg-dark-tone shadow-md">
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- CONTROL PANEL -->
|
||||
<div class="flex-row p-4 flex items-center gap-3 flex-0">
|
||||
|
||||
<!-- MAIN BUTTONS -->
|
||||
<button class="text-2xl hover:text-secondary duration-75 active:scale-90" title="Create new discussion"
|
||||
type="button" @click="createNewDiscussion()">
|
||||
@ -84,6 +85,21 @@
|
||||
type="button" @click="isSearch = !isSearch" :class="isSearch ? 'text-secondary' : ''">
|
||||
<i data-feather="search"></i>
|
||||
</button>
|
||||
<button v-if="!showConfirmation" title="Save configuration" class="text-2xl hover:text-secondary duration-75 active:scale-90"
|
||||
@click="showConfirmation = true">
|
||||
<i data-feather="save"></i>
|
||||
</button>
|
||||
<!-- SAVE CONFIG -->
|
||||
<div v-if="showConfirmation" class="flex gap-3 flex-1 items-center duration-75">
|
||||
<button class="text-2xl hover:text-red-600 duration-75 active:scale-90 " title="Cancel" type="button"
|
||||
@click.stop="showConfirmation = false">
|
||||
<i data-feather="x"></i>
|
||||
</button>
|
||||
<button class="text-2xl hover:text-secondary duration-75 active:scale-90" title="Confirm save changes"
|
||||
type="button" @click.stop="save_configuration()">
|
||||
<i data-feather="check"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="loading" title="Loading.." class="flex flex-row flex-grow justify-end">
|
||||
<!-- SPINNER -->
|
||||
<div role="status">
|
||||
@ -252,6 +268,7 @@
|
||||
|
||||
<Toast ref="toast">
|
||||
</Toast>
|
||||
<MessageBox ref="messageBox" />
|
||||
</template>
|
||||
|
||||
|
||||
@ -382,6 +399,26 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
save_configuration() {
|
||||
this.showConfirmation = false
|
||||
axios.post('/save_settings', {})
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
if (res.status) {
|
||||
// this.$refs.messageBox.showMessage("Settings saved!")
|
||||
}
|
||||
else
|
||||
this.$refs.messageBox.showMessage("Error: Couldn't save settings!")
|
||||
return res.data;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error.message, 'save_configuration')
|
||||
this.$refs.messageBox.showMessage("Couldn't save settings!")
|
||||
return { 'status': false }
|
||||
});
|
||||
|
||||
},
|
||||
showToastMessage(text){
|
||||
console.log("sending",text)
|
||||
this.$refs.toast.showToast(text, 4, true)
|
||||
@ -809,7 +846,7 @@ export default {
|
||||
|
||||
let responseMessage = {
|
||||
//content:msgObj.data,
|
||||
content: "✍ please stand by ...",//msgObj.message,
|
||||
content: msgObj.message,// "✍ please stand by ...",//msgObj.message,
|
||||
created_at:msgObj.created_at,
|
||||
binding:msgObj.binding,
|
||||
model:msgObj.model,
|
||||
@ -820,7 +857,6 @@ export default {
|
||||
sender: msgObj.bot,
|
||||
type:msgObj.type,
|
||||
steps: []
|
||||
//type: msgObj.type
|
||||
|
||||
}
|
||||
this.discussionArr.push(responseMessage)
|
||||
@ -1398,9 +1434,13 @@ export default {
|
||||
})
|
||||
},
|
||||
getAvatar(sender) {
|
||||
if (sender.toLowerCase().trim() == this.$store.state.config.user_name.toLowerCase().trim()){
|
||||
return "user_infos/"+this.$store.state.config.user_avatar
|
||||
}
|
||||
const index = this.personalityAvatars.findIndex((x) => x.name === sender)
|
||||
const pers = this.personalityAvatars[index]
|
||||
if (pers) {
|
||||
console.log("Avatar",pers.avatar)
|
||||
return pers.avatar
|
||||
}
|
||||
|
||||
@ -1584,6 +1624,7 @@ import Message from '../components/Message.vue'
|
||||
import ChatBox from '../components/ChatBox.vue'
|
||||
import WelcomeComponent from '../components/WelcomeComponent.vue'
|
||||
import Toast from '../components/Toast.vue'
|
||||
import MessageBox from "@/components/MessageBox.vue";
|
||||
import DragDrop from '../components/DragDrop.vue'
|
||||
import feather from 'feather-icons'
|
||||
|
||||
|
@ -1,16 +1,41 @@
|
||||
<template>
|
||||
<div>
|
||||
Extensions
|
||||
<div v-for="extension in activeExtensions" :key="extension.name" @click="showExtensionPage(extension)">
|
||||
<div :class="{ 'active-tab': extension === activeExtension }">{{ extension.name }}</div>
|
||||
</div>
|
||||
<div v-if="activeExtension">
|
||||
<!-- Render the selected extension's page here -->
|
||||
<iframe :src="activeExtension.page" width="100%" height="500px" frameborder="0"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
setup () {
|
||||
|
||||
|
||||
return {}
|
||||
}
|
||||
}
|
||||
data() {
|
||||
return {
|
||||
activeExtension: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
activeExtensions() {
|
||||
// Filter the extensions to get only active ones
|
||||
return this.$store.state.extensionsZoo.filter((extension) => extension.is_active);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
showExtensionPage(extension) {
|
||||
// Set the selected extension as active to render its page
|
||||
this.activeExtension = extension;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.active-tab {
|
||||
/* Style the active tab as you like */
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
@ -533,7 +533,28 @@
|
||||
|
||||
|
||||
<table style="width: 100%;">
|
||||
<!-- Row 1 -->
|
||||
<tr>
|
||||
<td style="min-width: 200px;">
|
||||
<label for="enable_gpu" class="text-sm font-bold" style="margin-right: 1rem;">Enable GPU:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="enable_gpu"
|
||||
required
|
||||
v-model="enable_gpu"
|
||||
class="mt-1 px-2 py-1 border border-gray-300 rounded"
|
||||
>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
class="hover:text-secondary bg-blue-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
|
||||
@click="update_setting('enable_gpu', enable_gpu)"
|
||||
>
|
||||
<i data-feather="check"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="min-width: 200px;">
|
||||
<label for="auto_update" class="text-sm font-bold" style="margin-right: 1rem;">Auto update:</label>
|
||||
@ -547,12 +568,12 @@
|
||||
class="mt-1 px-2 py-1 border border-gray-300 rounded"
|
||||
>
|
||||
</td>
|
||||
<td style="min-width: 300px;">
|
||||
<td>
|
||||
<button
|
||||
class="hover:text-secondary bg-blue-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
|
||||
@click="update_setting('auto_update', auto_update)"
|
||||
>
|
||||
Validate
|
||||
<i data-feather="check"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
@ -571,12 +592,12 @@
|
||||
class="w-full mt-1 px-2 py-1 border border-gray-300 rounded"
|
||||
>
|
||||
</td>
|
||||
<td style="min-width: 300px;">
|
||||
<td>
|
||||
<button
|
||||
class="hover:text-secondary bg-blue-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
|
||||
@click="update_setting('db_path', db_path)"
|
||||
>
|
||||
Select Database
|
||||
<i data-feather="check"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
@ -595,12 +616,12 @@
|
||||
class="w-full mt-1 px-2 py-1 border border-gray-300 rounded"
|
||||
>
|
||||
</td>
|
||||
<td style="min-width: 300px;">
|
||||
<td>
|
||||
<button
|
||||
class="hover:text-secondary bg-blue-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
|
||||
@click="update_setting('user_name', userName)"
|
||||
>
|
||||
Validate
|
||||
<i data-feather="check"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
@ -615,12 +636,12 @@
|
||||
</label>
|
||||
<input type="file" id="avatar-upload" style="display: none" @change="uploadAvatar">
|
||||
</td>
|
||||
<td style="min-width: 300px;">
|
||||
<td>
|
||||
<button
|
||||
class="hover:text-secondary bg-blue-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
|
||||
@click="update_setting('user_name', userName)"
|
||||
>
|
||||
Validate
|
||||
<i data-feather="check"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
@ -638,12 +659,12 @@
|
||||
class=" mt-1 px-2 py-1 border border-gray-300 rounded"
|
||||
>
|
||||
</td>
|
||||
<td style="min-width: 300px;">
|
||||
<td>
|
||||
<button
|
||||
class="hover:text-secondary bg-blue-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
|
||||
@click="update_setting('use_user_name_in_discussions', use_user_name_in_discussions)"
|
||||
>
|
||||
Validate
|
||||
<i data-feather="check"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
@ -1643,11 +1664,13 @@ export default {
|
||||
// Make an API request to upload the avatar
|
||||
axios.post('/upload_avatar', formData)
|
||||
.then(response => {
|
||||
console.log("Avatar uploaded successfully")
|
||||
// Assuming the server responds with the file name after successful upload
|
||||
const fileName = response.fileName;
|
||||
this.user_avatar = fileName; // Update the user_avatar value with the file name
|
||||
this.update_setting("user_avatar", fileName, ()=>{}).then(()=>{})
|
||||
console.log("Avatar uploaded successfully")
|
||||
this.$refs.toast.showToast("Avatar uploaded successfully!", 4, true)
|
||||
// Assuming the server responds with the file name after successful upload
|
||||
const fileName = response.data.fileName;
|
||||
console.log("response",response);
|
||||
this.user_avatar = fileName; // Update the user_avatar value with the file name
|
||||
this.update_setting("user_avatar", fileName, ()=>{}).then(()=>{})
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error uploading avatar:', error);
|
||||
@ -2355,8 +2378,13 @@ export default {
|
||||
if (res) {
|
||||
this.isLoading = false
|
||||
console.log('update_setting', res)
|
||||
if(res['status']){
|
||||
this.$refs.toast.showToast("Setting updated successfully.\nDon't forget to save to keep the setting permanently.", 4, true)
|
||||
}
|
||||
else{
|
||||
this.$refs.toast.showToast("Setting update failed.\nPlease view the console for more details.", 4, false)
|
||||
}
|
||||
if (next !== undefined) {
|
||||
|
||||
next(res)
|
||||
}
|
||||
return res.data;
|
||||
@ -2869,6 +2897,17 @@ export default {
|
||||
this.$store.state.config.user_avatar = value
|
||||
},
|
||||
},
|
||||
|
||||
enable_gpu:{
|
||||
get() {
|
||||
return this.$store.state.config.enable_gpu;
|
||||
},
|
||||
set(value) {
|
||||
// You should not set the value directly here; use the updateSetting method instead
|
||||
this.$store.state.config.enable_gpu = value
|
||||
},
|
||||
|
||||
},
|
||||
auto_update:{
|
||||
get() {
|
||||
return this.$store.state.config.auto_update;
|
||||
|
Loading…
Reference in New Issue
Block a user