mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2025-01-29 15:44:12 +00:00
Upgraded ui
This commit is contained in:
parent
792e2fad47
commit
e97e3bcfd8
8
web/dist/assets/index-BpT69KYd.css
vendored
8
web/dist/assets/index-BpT69KYd.css
vendored
File diff suppressed because one or more lines are too long
8
web/dist/assets/index-DgI2-Yh4.css
vendored
Normal file
8
web/dist/assets/index-DgI2-Yh4.css
vendored
Normal file
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 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>LoLLMS WebUI</title>
|
||||
<script type="module" crossorigin src="/assets/index-C2ppRpsB.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-BpT69KYd.css">
|
||||
<script type="module" crossorigin src="/assets/index-TthUmaOU.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DgI2-Yh4.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<div class="relative group/item">
|
||||
<button @click.prevent="toggleShowPersList" class="w-10 h-10 rounded-full overflow-hidden transition-transform duration-200 transform group-hover/item:scale-110 focus:outline-none">
|
||||
<button @click.prevent="onSettingsPersonality" class="w-6 h-6 rounded-full overflow-hidden transition-transform duration-200 transform group-hover/item:scale-110 focus:outline-none">
|
||||
<img :src="bUrl + mountedPers.avatar" @error="personalityImgPlacehodler" :alt="mountedPers.name" class="w-full h-full object-cover" :class="{'border-2 border-secondary': isActive}">
|
||||
</button>
|
||||
|
||||
<div class="absolute -bottom-4 left-0 w-full flex items-center justify-center opacity-0 group-hover/item:opacity-100 transition-opacity duration-200 p-1">
|
||||
<div class="absolute bottom-6 left-0 w-full flex items-center justify-center opacity-0 group-hover/item:opacity-100 transition-opacity duration-200 p-1">
|
||||
<button @click.prevent="remount_personality()" class="p-1 bg-blue-500 rounded-full text-white hover:bg-blue-600 focus:outline-none" title="Remount">
|
||||
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path></svg>
|
||||
</button>
|
||||
<button @click.prevent="handleOnTalk()" class="p-1 bg-green-500 rounded-full text-white hover:bg-green-600 focus:outline-none ml-1" title="Talk">
|
||||
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z"></path></svg>
|
||||
</button>
|
||||
<button @click.prevent="toggleShowPersList" class="p-1 bg-gray-500 rounded-full text-white hover:bg-gray-600 focus:outline-none ml-1" title="Show more">
|
||||
<button class="p-1 bg-gray-500 rounded-full text-white hover:bg-gray-600 focus:outline-none ml-1" title="Show more">
|
||||
<span class="text-xs font-bold">+{{ mountedPersArr.length - 1 }}</span>
|
||||
</button>
|
||||
</div>
|
||||
@ -206,10 +206,6 @@ export default {
|
||||
this.$refs.toast.showToast("Could not open personality settings. Endpoint error: " + error.message, 4, false)
|
||||
}
|
||||
|
||||
},
|
||||
toggleShowPersList() {
|
||||
//this.show = !this.show
|
||||
this.onShowPersList()
|
||||
},
|
||||
async constructor() {
|
||||
nextTick(() => {
|
||||
|
@ -1,6 +1,15 @@
|
||||
|
||||
<template>
|
||||
<div class="topbar-container" @mouseenter="show" @mouseleave="hide">
|
||||
<div class="topbar" :class="{ 'topbar-hidden': !isVisible }">
|
||||
<div class="topbar-container">
|
||||
<!-- Add a thin strip at the top that triggers the hover -->
|
||||
<div
|
||||
class="hover-zone"
|
||||
@mouseenter="show"
|
||||
style="position: fixed; top: 0; left: 0; width: 100%; height: 10px; z-index: 50;"
|
||||
></div>
|
||||
|
||||
<div class="topbar" :class="{ 'topbar-hidden': !isVisible }" @mouseleave="hide">
|
||||
<!-- Rest of your topbar content -->
|
||||
<div class="topbar-content">
|
||||
<slot name="navigation"></slot>
|
||||
<button class="pin-button" @click="togglePin" :title="isPinned ? 'Unpin' : 'Pin'">
|
||||
@ -18,9 +27,142 @@
|
||||
</svg>
|
||||
</button>
|
||||
<Navigation></Navigation>
|
||||
<div class="toolbar-button" @mouseleave="hideInfosMenu">
|
||||
<div class="relative inline-block">
|
||||
<!-- Infos menu positioned above the button -->
|
||||
<div v-show="isInfosMenuVisible" @mouseenter="showInfosMenu" class="absolute m-0 p-0 z-50 top-full right-0 transform bg-white dark:bg-gray-900 rounded-md shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none transition-all duration-300 ease-out mb-2">
|
||||
<div class="p-4 container flex flex-col lg:flex-row items-center gap-2">
|
||||
<!-- SYSTEM STATUS -->
|
||||
<div class="flex gap-3 flex-1 items-center justify-end">
|
||||
<div v-if="isModelOK" title="Model is ok" class="text-green-500 dark:text-green-400 cursor-pointer transition-transform hover:scale-110">
|
||||
<svg class="w-8 h-8" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M9 12L11 14L15 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div v-else title="Model is not ok" class="text-red-500 dark:text-red-400 cursor-pointer transition-transform hover:scale-110">
|
||||
<svg class="w-8 h-8" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M15 9L9 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M9 9L15 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div v-if="!isGenerating" title="Text is not being generated. Ready to generate" class="text-green-500 dark:text-green-400 cursor-pointer transition-transform hover:scale-110">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 21v-4m0 0V5a2 2 0 012-2h6.5l1 1H21l-3 6 3 6h-8.5l-1-1H5a2 2 0 00-2 2zm9-13.5V9"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div v-else title="Generation in progress..." class="text-yellow-500 dark:text-yellow-400 cursor-pointer transition-transform hover:scale-110">
|
||||
<svg class="w-6 h-6 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div v-if="isConnected" title="Connection status: Connected" class="text-green-500 dark:text-green-400 cursor-pointer transition-transform hover:scale-110">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div v-else title="Connection status: Not connected" class="text-red-500 dark:text-red-400 cursor-pointer transition-transform hover:scale-110">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center space-x-4">
|
||||
<ActionButton @click="restartProgram" icon="power" title="restart program" />
|
||||
<ActionButton @click="refreshPage" icon="refresh-ccw" title="refresh page" />
|
||||
<ActionButton href="/docs" icon="file-text" title="Fast API doc" />
|
||||
</div>
|
||||
|
||||
<!-- SOCIALS -->
|
||||
<SocialIcon href="https://github.com/ParisNeo/lollms-webui" icon="github" />
|
||||
<SocialIcon href="https://www.youtube.com/channel/UCJzrg0cyQV2Z30SQ1v2FdSQ" icon="youtube" />
|
||||
<SocialIcon href="https://x.com/ParisNeo_AI" icon="x" />
|
||||
<SocialIcon href="https://discord.com/channels/1092918764925882418" icon="discord" />
|
||||
|
||||
<div class="relative group" title="Lollms News">
|
||||
<div @click="showNews()" class="text-2xl w-8 h-8 cursor-pointer transition-colors duration-300 text-gray-600 hover:text-primary dark:text-gray-300 dark:hover:text-primary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-full h-full">
|
||||
<path d="M19 20H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v1m2 13a2 2 0 0 1-2-2V7m2 13a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="absolute hidden group-hover:block bg-gray-800 text-white text-xs rounded py-1 px-2 top-full left-1/2 transform -translate-x-1/2 mt-2 whitespace-nowrap">
|
||||
Lollms News
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info Button -->
|
||||
<div @mouseenter="showInfosMenu" class="infos-hover-area">
|
||||
<button class="w-8 h-8">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 25" class="w-full h-full">
|
||||
<!-- Circle background -->
|
||||
<circle cx="12.5" cy="12.5" r="11.25" fill="#3498db"/>
|
||||
<!-- "i" stem -->
|
||||
<rect x="11.25" y="10" width="2.5" height="8.75" fill="white"/>
|
||||
<!-- "i" dot -->
|
||||
<circle cx="12.5" cy="6.25" r="1.25" fill="white"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="is_fun_mode"
|
||||
title="Fun mode is on, press to turn off"
|
||||
class="w-8 h-8 cursor-pointer text-green-500 dark:text-green-400 hover:text-green-600 dark:hover:text-green-300 transition-colors duration-300"
|
||||
@click="fun_mode_off()"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-full h-full animate-bounce">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<path d="M8 14s1.5 2 4 2 4-2 4-2"></path>
|
||||
<line x1="9" y1="9" x2="9.01" y2="9"></line>
|
||||
<line x1="15" y1="9" x2="15.01" y2="9"></line>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
title="Fun mode is off, press to turn on"
|
||||
class="w-8 h-8 cursor-pointer text-gray-500 dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors duration-300"
|
||||
@click="fun_mode_on()"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-full h-full">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<line x1="8" y1="15" x2="16" y2="15"></line>
|
||||
<line x1="9" y1="9" x2="9.01" y2="9"></line>
|
||||
<line x1="15" y1="9" x2="15.01" y2="9"></line>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="absolute hidden group-hover:block bg-gray-800 text-white text-xs rounded py-1 px-2 top-full left-1/2 transform -translate-x-1/2 mb-2 whitespace-nowrap">
|
||||
{{ is_fun_mode ? 'Turn off fun mode' : 'Turn on fun mode' }}
|
||||
</span>
|
||||
<div class="language-selector relative">
|
||||
<button @click="toggleLanguageMenu" class="bg-transparent text-black dark:text-white py-1 px-1 rounded font-bold uppercase transition-colors duration-300 hover:bg-blue-500">
|
||||
{{ $store.state.language.slice(0, 2) }}
|
||||
</button>
|
||||
<div v-if="isLanguageMenuVisible" ref="languageMenu" class="container language-menu absolute left-0 mt-1 bg-white dark:bg-bg-dark-tone rounded shadow-lg z-10 overflow-y-auto scrollbar-thin scrollbar-track-bg-light-tone scrollbar-thumb-bg-light-tone-panel hover:scrollbar-thumb-primary dark:scrollbar-track-bg-dark-tone dark:scrollbar-thumb-bg-dark-tone-panel dark:hover:scrollbar-thumb-primary active:scrollbar-thumb-secondary" style="position: absolute; top: 100%; width: 200px; max-height: 300px; overflow-y: auto;">
|
||||
<ul style="list-style-type: none; padding-left: 0; margin-left: 0;">
|
||||
<li v-for="language in languages" :key="language" class="relative flex items-center" style="padding-left: 0; margin-left: 0;">
|
||||
<button @click="deleteLanguage(language)" class="mr-2 text-red-500 hover:text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-opacity-50 rounded-full">✕</button>
|
||||
<div @click="selectLanguage(language)" :class="{'cursor-pointer hover:bg-blue-500 hover:text-white py-2 px-4 block whitespace-no-wrap': true, 'bg-blue-500 text-white': language === $store.state.language, 'flex-grow': true}">
|
||||
{{ language }}
|
||||
</div>
|
||||
</li>
|
||||
<li class="cursor-pointer hover:text-white py-0 px-0 block whitespace-no-wrap">
|
||||
<input type="text" v-model="customLanguage" @keyup.enter.prevent="addCustomLanguage" placeholder="Enter language..." class="bg-transparent border border-gray-300 rounded py-0 px-0 mx-0 my-1 w-full">
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="isDarkMode" class="sun text-2xl w-6 hover:text-primary duration-150 cursor-pointer" title="Switch to Light theme" @click="themeSwitch()">
|
||||
<i data-feather="sun"></i>
|
||||
</div>
|
||||
<div v-else class="moon text-2xl w-6 hover:text-primary duration-150 cursor-pointer" title="Switch to Dark theme" @click="themeSwitch()">
|
||||
<i data-feather="moon"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="placeholder" v-if="!isVisible"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -34,11 +176,98 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isinfosMenuVisible: false,
|
||||
isVisible: false,
|
||||
isPinned: false,
|
||||
selectedLanguage: '',
|
||||
isLanguageMenuVisible: false,
|
||||
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
isModelOK(){
|
||||
return this.$store.state.isModelOk;
|
||||
},
|
||||
isDarkMode(){
|
||||
return document.documentElement.classList.contains("dark");
|
||||
},
|
||||
languages: {
|
||||
get(){
|
||||
console.log("searching languages", this.$store.state.languages)
|
||||
return this.$store.state.languages
|
||||
}
|
||||
},
|
||||
language: {
|
||||
get(){
|
||||
console.log("searching language", this.$store.state.language)
|
||||
return this.$store.state.language
|
||||
}
|
||||
},
|
||||
|
||||
is_fun_mode(){
|
||||
try{
|
||||
if (this.$store.state.config){
|
||||
return this.$store.state.config.fun_mode;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch(error){
|
||||
console.error("Oopsie! Looks like we hit a snag: ", error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
isGenerating(){
|
||||
return this.$store.state.isGenerating;
|
||||
},
|
||||
isConnected(){
|
||||
return this.$store.state.isConnected;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
themeSwitch() {
|
||||
|
||||
if (document.documentElement.classList.contains("dark")) {
|
||||
document.documentElement.classList.remove("dark");
|
||||
localStorage.setItem("theme", "light")
|
||||
this.userTheme == "light"
|
||||
this.iconToggle()
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
import('highlight.js/styles/tokyo-night-dark.css');
|
||||
document.documentElement.classList.add("dark");
|
||||
localStorage.setItem("theme", "dark")
|
||||
this.userTheme == "dark"
|
||||
this.iconToggle()
|
||||
// Dispatch the themeChanged event
|
||||
window.dispatchEvent(new Event('themeChanged'));
|
||||
},
|
||||
async selectLanguage(language) {
|
||||
await this.$store.dispatch('changeLanguage', language);
|
||||
this.toggleLanguageMenu(); // Fermer le menu après le changement de langue
|
||||
this.language = language
|
||||
},
|
||||
async deleteLanguage(language) {
|
||||
await this.$store.dispatch('deleteLanguage', language);
|
||||
this.toggleLanguageMenu(); // Fermer le menu après le changement de langue
|
||||
this.language = language
|
||||
},
|
||||
|
||||
toggleLanguageMenu() {
|
||||
console.log("Toggling language ",this.isLanguageMenuVisible)
|
||||
this.isLanguageMenuVisible = !this.isLanguageMenuVisible;
|
||||
},
|
||||
|
||||
showInfosMenu() {
|
||||
console.log("showing menu")
|
||||
this.isInfosMenuVisible = true;
|
||||
},
|
||||
hideInfosMenu() {
|
||||
this.isInfosMenuVisible = false;
|
||||
},
|
||||
show() {
|
||||
this.isVisible = true
|
||||
},
|
||||
@ -51,6 +280,59 @@ export default {
|
||||
this.isPinned = !this.isPinned
|
||||
this.isVisible = this.isPinned
|
||||
},
|
||||
fun_mode_on(){
|
||||
console.log("Turning on fun mode")
|
||||
this.$store.state.config.fun_mode=true;
|
||||
this.applyConfiguration()
|
||||
},
|
||||
fun_mode_off(){
|
||||
console.log("Turning off fun mode")
|
||||
this.$store.state.config.fun_mode=false;
|
||||
this.applyConfiguration()
|
||||
},
|
||||
showNews(){
|
||||
this.$store.state.news.show()
|
||||
},
|
||||
themeCheck() {
|
||||
|
||||
if (this.userTheme == "dark" || (!this.userTheme && this.systemTheme)) {
|
||||
document.documentElement.classList.add("dark");
|
||||
this.moonIcon.classList.add("display-none");
|
||||
|
||||
nextTick(()=>{
|
||||
//import('highlight.js/styles/tokyo-night-dark.css');
|
||||
import('highlight.js/styles/stackoverflow-dark.css');
|
||||
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
nextTick(()=>{
|
||||
//import('highlight.js/styles/tomorrow-night-blue.css');
|
||||
import('highlight.js/styles/stackoverflow-light.css');
|
||||
})
|
||||
this.sunIcon.classList.add("display-none")
|
||||
|
||||
},
|
||||
iconToggle() {
|
||||
this.sunIcon.classList.toggle("display-none");
|
||||
this.moonIcon.classList.toggle("display-none");
|
||||
},
|
||||
refreshPage() {
|
||||
const hostnameParts = window.location.href.split('/');
|
||||
|
||||
if(hostnameParts.length > 4){
|
||||
window.location.href='/'
|
||||
}
|
||||
else{
|
||||
window.location.reload(true);
|
||||
}
|
||||
},
|
||||
handleOk(inputText) {
|
||||
console.log("Input text:", inputText);
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -107,4 +389,36 @@ export default {
|
||||
.placeholder {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
|
||||
.toolbar-button {
|
||||
@apply bg-transparent border-none cursor-pointer p-2 transition-colors duration-300;
|
||||
}
|
||||
|
||||
.toolbar-button:hover {
|
||||
@apply text-blue-500; /* Assuming #007bff is close to Tailwind's blue-500 */
|
||||
}
|
||||
|
||||
.topbar-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.topbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background-color: white; /* or your preferred background color */
|
||||
transition: transform 0.3s ease-in-out;
|
||||
z-index: 40;
|
||||
}
|
||||
|
||||
.topbar-hidden {
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
.hover-zone {
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,39 +1,167 @@
|
||||
<template>
|
||||
<div v-if="show"
|
||||
class="fixed top-0 left-0 right-0 bottom-0 flex items-center justify-center bg-black bg-opacity-50 p-4">
|
||||
<div class="relative w-full max-w-md">
|
||||
|
||||
<div
|
||||
class="flex flex-col rounded-lg bg-bg-light-tone-panel dark:bg-bg-dark-tone-panel duration-150 shadow-lg max-h-screen">
|
||||
<div class="flex flex-row flex-grow items-center m-2 p-1">
|
||||
class="fixed top-0 left-0 right-0 bottom-0 flex items-center justify-center bg-black bg-opacity-50 p-4 overflow-hidden">
|
||||
<div class="relative w-full max-w-md max-h-[80vh]">
|
||||
<!-- Main Container with shadow and rounded corners -->
|
||||
<div class="flex flex-col rounded-lg bg-bg-light-tone-panel dark:bg-bg-dark-tone-panel shadow-lg">
|
||||
<!-- Header -->
|
||||
<div class="flex flex-row items-center p-4 border-b border-gray-200 dark:border-gray-700">
|
||||
<div class="grow flex items-center">
|
||||
<i data-feather="sliders" class="mr-2 flex-shrink-0"></i>
|
||||
<h3 class="text-lg font-semibold select-none mr-2">
|
||||
{{ title }}</h3>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- CLOSE BUTTON -->
|
||||
<div class="items-end">
|
||||
<button type="button" @click.stop="hide(false)" title="Close"
|
||||
class=" bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-800 dark:hover:text-white">
|
||||
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd"
|
||||
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
<span class="sr-only">Close form modal</span>
|
||||
</button>
|
||||
<h3 class="text-lg font-semibold select-none">{{ title }}</h3>
|
||||
</div>
|
||||
<!-- Close Button -->
|
||||
<button @click.stop="hide(false)" title="Close"
|
||||
class="p-1.5 hover:bg-gray-200 rounded-lg dark:hover:bg-gray-800">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd"
|
||||
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z">
|
||||
</path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<!-- FORM AREA -->
|
||||
<div class="flex flex-col relative no-scrollbar overflow-y-scroll p-2">
|
||||
<!-- odd:bg-bg-light-tone odd:dark:bg-bg-dark-tone even:bg-bg-light-tone-panel dark:even:bg-bg-dark-tone-panel -->
|
||||
<div class="px-2 " v-for="(item, index) in controls_array">
|
||||
|
||||
<div v-if="item.type == 'str' || item.type == 'string'">
|
||||
<div v-if="!item.options">
|
||||
<!-- Scrollable Content Area -->
|
||||
<div class="overflow-y-auto p-4 max-h-[60vh] custom-scrollbar">
|
||||
<div class="space-y-2">
|
||||
<div v-for="(item, index) in controls_array" :key="index" class="p-1">
|
||||
|
||||
<div v-if="item.type == 'str' || item.type == 'string'">
|
||||
<div v-if="!item.options">
|
||||
<label
|
||||
class="mb-2 relative flex items-center gap-2 text-sm font-medium text-gray-900 dark:text-white select-none"
|
||||
:class="item.help ? 'cursor-pointer ' : ''">
|
||||
<!-- TITLE -->
|
||||
<div class="text-base font-semibold">
|
||||
{{ item.name }}:
|
||||
</div>
|
||||
|
||||
<!-- HELP BUTTON -->
|
||||
<label v-if="item.help" class="relative inline-flex">
|
||||
<input type="checkbox" v-model="item.isHelp" class="sr-only peer">
|
||||
<div
|
||||
class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<i data-feather="help-circle" class="w-5 h-5 "></i>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
</label>
|
||||
<!-- HELP DESCRIPTION -->
|
||||
<p v-if="item.isHelp" class="text-sm font-normal text-gray-700 dark:text-gray-400 mb-2">
|
||||
{{ item.help }}
|
||||
</p>
|
||||
|
||||
<input type="text" v-model="item.value"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="Enter string">
|
||||
</div>
|
||||
<div v-if="item.options">
|
||||
<label
|
||||
class="mb-2 relative flex items-center gap-2 text-sm font-medium text-gray-900 dark:text-white select-none"
|
||||
:class="item.help ? 'cursor-pointer ' : ''">
|
||||
<!-- TITLE -->
|
||||
<div class="text-base font-semibold">
|
||||
{{ item.name }}:
|
||||
</div>
|
||||
|
||||
<!-- HELP BUTTON -->
|
||||
<label v-if="item.help" class="relative inline-flex">
|
||||
<input type="checkbox" v-model="item.isHelp" class="sr-only peer">
|
||||
<div
|
||||
class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<i data-feather="help-circle" class="w-5 h-5 "></i>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
</label>
|
||||
<!-- HELP DESCRIPTION -->
|
||||
<p v-if="item.isHelp" class="text-sm font-normal text-gray-700 dark:text-gray-400 mb-2">
|
||||
{{ item.help }}
|
||||
</p>
|
||||
<select v-model="item.value"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
|
||||
<option v-for="op in item.options" :value="op" :selected="item.value === op">{{
|
||||
op
|
||||
}}
|
||||
|
||||
</option>
|
||||
|
||||
</select>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div v-if="item.type == 'btn'">
|
||||
<button class="" onclick="btn_clicked(item)"> {{ item.name }} </button>
|
||||
</div>
|
||||
<div v-if="item.type == 'text'">
|
||||
<div v-if="!item.options">
|
||||
<label
|
||||
class="mb-2 relative flex items-center gap-2 text-sm font-medium text-gray-900 dark:text-white select-none"
|
||||
:class="item.help ? 'cursor-pointer ' : ''">
|
||||
<!-- TITLE -->
|
||||
<div class="text-base font-semibold">
|
||||
{{ item.name }}:
|
||||
</div>
|
||||
|
||||
<!-- HELP BUTTON -->
|
||||
<label v-if="item.help" class="relative inline-flex">
|
||||
<input type="checkbox" v-model="item.isHelp" class="sr-only peer">
|
||||
<div
|
||||
class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<i data-feather="help-circle" class="w-5 h-5 "></i>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
</label>
|
||||
<!-- HELP DESCRIPTION -->
|
||||
<p v-if="item.isHelp" class="text-sm font-normal text-gray-700 dark:text-gray-400 mb-2">
|
||||
{{ item.help }}
|
||||
</p>
|
||||
|
||||
<textarea v-model="item.value"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="Enter string"></textarea>
|
||||
</div>
|
||||
<div v-if="item.options">
|
||||
<label
|
||||
class="mb-2 relative flex items-center gap-2 text-sm font-medium text-gray-900 dark:text-white select-none"
|
||||
:class="item.help ? 'cursor-pointer ' : ''">
|
||||
<!-- TITLE -->
|
||||
<div class="text-base font-semibold">
|
||||
{{ item.name }}:
|
||||
</div>
|
||||
|
||||
<!-- HELP BUTTON -->
|
||||
<label v-if="item.help" class="relative inline-flex">
|
||||
<input type="checkbox" v-model="item.isHelp" class="sr-only peer">
|
||||
<div
|
||||
class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<i data-feather="help-circle" class="w-5 h-5 "></i>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
</label>
|
||||
<!-- HELP DESCRIPTION -->
|
||||
<p v-if="item.isHelp" class="text-sm font-normal text-gray-700 dark:text-gray-400 mb-2">
|
||||
{{ item.help }}
|
||||
</p>
|
||||
<select v-model="item.value"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
|
||||
<option v-for="op in item.options" :value="op" :selected="item.value === op">{{
|
||||
op
|
||||
}}
|
||||
|
||||
</option>
|
||||
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="item.type == 'int'">
|
||||
<label
|
||||
class="mb-2 relative flex items-center gap-2 text-sm font-medium text-gray-900 dark:text-white select-none"
|
||||
:class="item.help ? 'cursor-pointer ' : ''">
|
||||
@ -45,8 +173,96 @@
|
||||
<!-- HELP BUTTON -->
|
||||
<label v-if="item.help" class="relative inline-flex">
|
||||
<input type="checkbox" v-model="item.isHelp" class="sr-only peer">
|
||||
<div
|
||||
class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<div class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<i data-feather="help-circle" class="w-5 h-5 "></i>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
</label>
|
||||
<!-- HELP DESCRIPTION -->
|
||||
<p v-if="item.isHelp" class="text-sm font-normal text-gray-700 dark:text-gray-400 mb-2">
|
||||
{{ item.help }}
|
||||
</p>
|
||||
|
||||
<input type="number" v-model="item.value" step="1"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="Enter number">
|
||||
|
||||
<input v-if="(item.min != null && item.max != null)" type="range" v-model="item.value"
|
||||
:min="item.min" :max="item.max" step="1"
|
||||
class="flex-none h-2 w-full bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700 focus:ring-blue-500 focus:border-blue-500 dark:border-gray-600 dark:placeholder-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
</div>
|
||||
<div v-if="item.type == 'float'">
|
||||
<label
|
||||
class="mb-2 relative flex items-center gap-2 text-sm font-medium text-gray-900 dark:text-white select-none"
|
||||
:class="item.help ? 'cursor-pointer ' : ''">
|
||||
<!-- TITLE -->
|
||||
<div class="text-base font-semibold">
|
||||
{{ item.name }}:
|
||||
</div>
|
||||
|
||||
<!-- HELP BUTTON -->
|
||||
<label v-if="item.help" class="relative inline-flex">
|
||||
<input type="checkbox" v-model="item.isHelp" class="sr-only peer">
|
||||
<div class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<i data-feather="help-circle" class="w-5 h-5 "></i>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
</label>
|
||||
<!-- HELP DESCRIPTION -->
|
||||
<p v-if="item.isHelp" class="text-sm font-normal text-gray-700 dark:text-gray-400 mb-2">
|
||||
{{ item.help }}
|
||||
</p>
|
||||
|
||||
<input type="number" v-model="item.value"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="Enter number">
|
||||
|
||||
<input v-if="(item.min != null && item.max != null)" type="range" v-model="item.value"
|
||||
:min="item.min" :max="item.max" step="0.1"
|
||||
class="flex-none h-2 w-full bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700 focus:ring-blue-500 focus:border-blue-500 dark:border-gray-600 dark:placeholder-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
</div>
|
||||
<div v-if="item.type == 'bool'">
|
||||
<div class="mb-2 relative flex items-center gap-2">
|
||||
|
||||
<label for="default-checkbox" class="text-base font-semibold">
|
||||
{{ item.name }}:
|
||||
</label>
|
||||
<input type="checkbox" v-model="item.value"
|
||||
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
||||
|
||||
<!-- HELP BUTTON -->
|
||||
<label v-if="item.help" class="relative inline-flex">
|
||||
<input type="checkbox" v-model="item.isHelp" class="sr-only peer">
|
||||
<div class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<i data-feather="help-circle" class="w-5 h-5 "></i>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
|
||||
</div>
|
||||
<!-- HELP DESCRIPTION -->
|
||||
<p v-if="item.isHelp" class="text-sm font-normal text-gray-700 dark:text-gray-400 mb-2">
|
||||
{{ item.help }}
|
||||
</p>
|
||||
|
||||
</div>
|
||||
<div v-if="item.type == 'list'">
|
||||
|
||||
|
||||
<label
|
||||
class="mb-2 relative flex items-center gap-2 text-sm font-medium text-gray-900 dark:text-white select-none"
|
||||
:class="item.help ? 'cursor-pointer ' : ''">
|
||||
<!-- TITLE -->
|
||||
<div class="text-base font-semibold">
|
||||
{{ item.name }}:
|
||||
</div>
|
||||
|
||||
<!-- HELP BUTTON -->
|
||||
<label v-if="item.help" class="relative inline-flex">
|
||||
<input type="checkbox" v-model="item.isHelp" class="sr-only peer">
|
||||
<div class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<i data-feather="help-circle" class="w-5 h-5 "></i>
|
||||
</div>
|
||||
</label>
|
||||
@ -59,260 +275,58 @@
|
||||
|
||||
<input type="text" v-model="item.value"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="Enter string">
|
||||
placeholder="Enter comma separated values">
|
||||
</div>
|
||||
<div v-if="item.options">
|
||||
<label
|
||||
class="mb-2 relative flex items-center gap-2 text-sm font-medium text-gray-900 dark:text-white select-none"
|
||||
:class="item.help ? 'cursor-pointer ' : ''">
|
||||
<!-- TITLE -->
|
||||
<div class="text-base font-semibold">
|
||||
{{ item.name }}:
|
||||
</div>
|
||||
|
||||
<!-- HELP BUTTON -->
|
||||
<!-- New File/Folder Input Type -->
|
||||
<div v-if="item.type === 'file' || item.type === 'folder'" class="space-y-2">
|
||||
<label class="flex items-center gap-2">
|
||||
<span class="text-base font-semibold">{{ item.name }}:</span>
|
||||
<!-- Help Button -->
|
||||
<label v-if="item.help" class="relative inline-flex">
|
||||
<input type="checkbox" v-model="item.isHelp" class="sr-only peer">
|
||||
<div
|
||||
class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<i data-feather="help-circle" class="w-5 h-5 "></i>
|
||||
<div class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<i data-feather="help-circle" class="w-5 h-5"></i>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
</label>
|
||||
<!-- HELP DESCRIPTION -->
|
||||
<p v-if="item.isHelp" class="text-sm font-normal text-gray-700 dark:text-gray-400 mb-2">
|
||||
<!-- Help Text -->
|
||||
<p v-if="item.isHelp" class="text-sm text-gray-600 dark:text-gray-400">
|
||||
{{ item.help }}
|
||||
</p>
|
||||
<select v-model="item.value"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
|
||||
<option v-for="op in item.options" :value="op" :selected="item.value === op">{{
|
||||
op
|
||||
}}
|
||||
|
||||
</option>
|
||||
|
||||
</select>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div v-if="item.type == 'btn'">
|
||||
<button class="" onclick="btn_clicked(item)"> {{ item.name }} </button>
|
||||
</div>
|
||||
<div v-if="item.type == 'text'">
|
||||
<div v-if="!item.options">
|
||||
<label
|
||||
class="mb-2 relative flex items-center gap-2 text-sm font-medium text-gray-900 dark:text-white select-none"
|
||||
:class="item.help ? 'cursor-pointer ' : ''">
|
||||
<!-- TITLE -->
|
||||
<div class="text-base font-semibold">
|
||||
{{ item.name }}:
|
||||
</div>
|
||||
|
||||
<!-- HELP BUTTON -->
|
||||
<label v-if="item.help" class="relative inline-flex">
|
||||
<input type="checkbox" v-model="item.isHelp" class="sr-only peer">
|
||||
<div
|
||||
class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<i data-feather="help-circle" class="w-5 h-5 "></i>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
</label>
|
||||
<!-- HELP DESCRIPTION -->
|
||||
<p v-if="item.isHelp" class="text-sm font-normal text-gray-700 dark:text-gray-400 mb-2">
|
||||
{{ item.help }}
|
||||
</p>
|
||||
|
||||
<textarea v-model="item.value"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="Enter string"></textarea>
|
||||
</div>
|
||||
<div v-if="item.options">
|
||||
<label
|
||||
class="mb-2 relative flex items-center gap-2 text-sm font-medium text-gray-900 dark:text-white select-none"
|
||||
:class="item.help ? 'cursor-pointer ' : ''">
|
||||
<!-- TITLE -->
|
||||
<div class="text-base font-semibold">
|
||||
{{ item.name }}:
|
||||
</div>
|
||||
|
||||
<!-- HELP BUTTON -->
|
||||
<label v-if="item.help" class="relative inline-flex">
|
||||
<input type="checkbox" v-model="item.isHelp" class="sr-only peer">
|
||||
<div
|
||||
class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<i data-feather="help-circle" class="w-5 h-5 "></i>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
</label>
|
||||
<!-- HELP DESCRIPTION -->
|
||||
<p v-if="item.isHelp" class="text-sm font-normal text-gray-700 dark:text-gray-400 mb-2">
|
||||
{{ item.help }}
|
||||
</p>
|
||||
<select v-model="item.value"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
|
||||
<option v-for="op in item.options" :value="op" :selected="item.value === op">{{
|
||||
op
|
||||
}}
|
||||
|
||||
</option>
|
||||
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="item.type == 'int'">
|
||||
<label
|
||||
class="mb-2 relative flex items-center gap-2 text-sm font-medium text-gray-900 dark:text-white select-none"
|
||||
:class="item.help ? 'cursor-pointer ' : ''">
|
||||
<!-- TITLE -->
|
||||
<div class="text-base font-semibold">
|
||||
{{ item.name }}:
|
||||
<!-- File/Folder Selection Input -->
|
||||
<div class="flex gap-2">
|
||||
<input type="text" v-model="item.value" readonly
|
||||
class="flex-1 bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:text-white"
|
||||
:placeholder="item.type === 'file' ? 'Select file...' : 'Select folder...'">
|
||||
<button @click="openFileDialog(item)"
|
||||
class="px-3 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-300 rounded-lg hover:bg-gray-100 dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:hover:bg-gray-600">
|
||||
...
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- HELP BUTTON -->
|
||||
<label v-if="item.help" class="relative inline-flex">
|
||||
<input type="checkbox" v-model="item.isHelp" class="sr-only peer">
|
||||
<div class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<i data-feather="help-circle" class="w-5 h-5 "></i>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
</label>
|
||||
<!-- HELP DESCRIPTION -->
|
||||
<p v-if="item.isHelp" class="text-sm font-normal text-gray-700 dark:text-gray-400 mb-2">
|
||||
{{ item.help }}
|
||||
</p>
|
||||
|
||||
<input type="number" v-model="item.value" step="1"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="Enter number">
|
||||
|
||||
<input v-if="(item.min != null && item.max != null)" type="range" v-model="item.value"
|
||||
:min="item.min" :max="item.max" step="1"
|
||||
class="flex-none h-2 w-full bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700 focus:ring-blue-500 focus:border-blue-500 dark:border-gray-600 dark:placeholder-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
</div>
|
||||
<div v-if="item.type == 'float'">
|
||||
<label
|
||||
class="mb-2 relative flex items-center gap-2 text-sm font-medium text-gray-900 dark:text-white select-none"
|
||||
:class="item.help ? 'cursor-pointer ' : ''">
|
||||
<!-- TITLE -->
|
||||
<div class="text-base font-semibold">
|
||||
{{ item.name }}:
|
||||
</div>
|
||||
|
||||
<!-- HELP BUTTON -->
|
||||
<label v-if="item.help" class="relative inline-flex">
|
||||
<input type="checkbox" v-model="item.isHelp" class="sr-only peer">
|
||||
<div class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<i data-feather="help-circle" class="w-5 h-5 "></i>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
</label>
|
||||
<!-- HELP DESCRIPTION -->
|
||||
<p v-if="item.isHelp" class="text-sm font-normal text-gray-700 dark:text-gray-400 mb-2">
|
||||
{{ item.help }}
|
||||
</p>
|
||||
|
||||
<input type="number" v-model="item.value"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="Enter number">
|
||||
|
||||
<input v-if="(item.min != null && item.max != null)" type="range" v-model="item.value"
|
||||
:min="item.min" :max="item.max" step="0.1"
|
||||
class="flex-none h-2 w-full bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700 focus:ring-blue-500 focus:border-blue-500 dark:border-gray-600 dark:placeholder-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
</div>
|
||||
<div v-if="item.type == 'bool'">
|
||||
<div class="mb-2 relative flex items-center gap-2">
|
||||
|
||||
<label for="default-checkbox" class="text-base font-semibold">
|
||||
{{ item.name }}:
|
||||
</label>
|
||||
<input type="checkbox" v-model="item.value"
|
||||
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
||||
|
||||
<!-- HELP BUTTON -->
|
||||
<label v-if="item.help" class="relative inline-flex">
|
||||
<input type="checkbox" v-model="item.isHelp" class="sr-only peer">
|
||||
<div class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<i data-feather="help-circle" class="w-5 h-5 "></i>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
|
||||
</div>
|
||||
<!-- HELP DESCRIPTION -->
|
||||
<p v-if="item.isHelp" class="text-sm font-normal text-gray-700 dark:text-gray-400 mb-2">
|
||||
{{ item.help }}
|
||||
</p>
|
||||
|
||||
<hr v-if="index < controls_array.length - 1"
|
||||
class="h-px my-4 bg-gray-200 border-0 dark:bg-gray-700">
|
||||
</div>
|
||||
<div v-if="item.type == 'list'">
|
||||
|
||||
|
||||
<label
|
||||
class="mb-2 relative flex items-center gap-2 text-sm font-medium text-gray-900 dark:text-white select-none"
|
||||
:class="item.help ? 'cursor-pointer ' : ''">
|
||||
<!-- TITLE -->
|
||||
<div class="text-base font-semibold">
|
||||
{{ item.name }}:
|
||||
</div>
|
||||
|
||||
<!-- HELP BUTTON -->
|
||||
<label v-if="item.help" class="relative inline-flex">
|
||||
<input type="checkbox" v-model="item.isHelp" class="sr-only peer">
|
||||
<div class="hover:text-secondary duration-75 active:scale-90 peer-checked:text-primary">
|
||||
<i data-feather="help-circle" class="w-5 h-5 "></i>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
</label>
|
||||
<!-- HELP DESCRIPTION -->
|
||||
<p v-if="item.isHelp" class="text-sm font-normal text-gray-700 dark:text-gray-400 mb-2">
|
||||
{{ item.help }}
|
||||
</p>
|
||||
|
||||
<input type="text" v-model="item.value"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="Enter comma separated values">
|
||||
</div>
|
||||
<hr class="h-px my-4 bg-gray-200 border-0 dark:bg-gray-700">
|
||||
</div>
|
||||
|
||||
<!-- SUBMIT AND CANCEL BUTTONS -->
|
||||
<div class="flex flex-row flex-grow gap-3">
|
||||
<div class="p-2 text-center grow">
|
||||
<button @click.stop="hide(true)" type="button"
|
||||
class="mr-2 text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
|
||||
{{ ConfirmButtonText }}
|
||||
</button>
|
||||
<button @click.stop="hide(false)" type="button"
|
||||
class="text-gray-500 bg-white hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-gray-200 rounded-lg border border-gray-200 text-sm font-medium px-5 py-2.5 hover:text-gray-900 focus:z-11 dark:bg-gray-700 dark:text-gray-300 dark:border-gray-500 dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-gray-600">
|
||||
{{ DenyButtonText }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- Footer with Buttons -->
|
||||
<div class="flex justify-center gap-3 p-4 border-t border-gray-200 dark:border-gray-700">
|
||||
<button @click.stop="hide(true)"
|
||||
class="px-5 py-2.5 text-sm font-medium text-white bg-blue-700 rounded-lg hover:bg-blue-800 dark:bg-blue-600 dark:hover:bg-blue-700">
|
||||
{{ ConfirmButtonText }}
|
||||
</button>
|
||||
<button @click.stop="hide(false)"
|
||||
class="px-5 py-2.5 text-sm font-medium text-gray-500 bg-white rounded-lg border border-gray-200 hover:bg-gray-100 dark:bg-gray-700 dark:text-gray-300 dark:border-gray-500 dark:hover:bg-gray-600">
|
||||
{{ DenyButtonText }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script >
|
||||
import feather from 'feather-icons'
|
||||
import { nextTick, TransitionGroup } from 'vue'
|
||||
@ -374,6 +388,30 @@ export default {
|
||||
console.log('show form', this.controls_array)
|
||||
});
|
||||
},
|
||||
openFileDialog(item) {
|
||||
// Create input element
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
if (item.type === 'folder') {
|
||||
input.webkitdirectory = true;
|
||||
input.directory = true;
|
||||
}
|
||||
|
||||
// Set accepted file types if specified
|
||||
if (item.accept) {
|
||||
input.accept = item.accept;
|
||||
}
|
||||
|
||||
// Handle file selection
|
||||
input.onchange = (e) => {
|
||||
if (e.target.files.length > 0) {
|
||||
item.value = e.target.files[0].path;
|
||||
}
|
||||
};
|
||||
|
||||
// Trigger file dialog
|
||||
input.click();
|
||||
}
|
||||
|
||||
},
|
||||
watch: {
|
||||
@ -399,4 +437,26 @@ export default {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.custom-scrollbar {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgba(156, 163, 175, 0.5) transparent;
|
||||
}
|
||||
|
||||
.custom-scrollbar::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.custom-scrollbar::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.custom-scrollbar::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(156, 163, 175, 0.5);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgba(156, 163, 175, 0.7);
|
||||
}
|
||||
</style>
|
||||
|
@ -23,6 +23,7 @@ function copyObject(obj) {
|
||||
export const store = createStore({
|
||||
state () {
|
||||
return {
|
||||
personalities_ready: false,
|
||||
is_rt_on:false,
|
||||
language: "english",
|
||||
languages: [],
|
||||
@ -102,6 +103,9 @@ export const store = createStore({
|
||||
localStorage.setItem('lollms_webui_view_mode', mode); // Sync with localStorage
|
||||
},
|
||||
|
||||
setpersonalitiesReady(state, personalities_ready) {
|
||||
state.personalities_ready = personalities_ready;
|
||||
},
|
||||
setisRTOn(state, is_rt_on) {
|
||||
state.is_rt_on = is_rt_on;
|
||||
},
|
||||
@ -189,6 +193,9 @@ export const store = createStore({
|
||||
return state.view_mode;
|
||||
},
|
||||
|
||||
getpersonalitiesReady(state){
|
||||
return state.personalities_ready;
|
||||
},
|
||||
getisRTOn(state) {
|
||||
return state.is_rt_on;
|
||||
},
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user