mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2024-12-18 20:17:50 +00:00
updated ui
This commit is contained in:
parent
f103cfe896
commit
b2fcb34955
8
web/dist/assets/index-BeXUn7MN.css
vendored
Normal file
8
web/dist/assets/index-BeXUn7MN.css
vendored
Normal file
File diff suppressed because one or more lines are too long
8
web/dist/assets/index-CeWaEmSv.css
vendored
8
web/dist/assets/index-CeWaEmSv.css
vendored
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-BHB08200.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CeWaEmSv.css">
|
||||
<script type="module" crossorigin src="/assets/index-CqKTM31L.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-BeXUn7MN.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
@ -154,31 +154,81 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<select
|
||||
v-model="currentTheme"
|
||||
@change="loadTheme(currentTheme)"
|
||||
class="inline-block w-[60px] px-3 py-1.5 text-sm
|
||||
border border-gray-300 rounded-md
|
||||
bg-white dark:bg-gray-800
|
||||
text-gray-700 dark:text-gray-200
|
||||
focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500
|
||||
hover:border-gray-400
|
||||
cursor-pointer
|
||||
appearance-none
|
||||
bg-no-repeat
|
||||
bg-right
|
||||
pr-8 mx-2"
|
||||
style="background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M7%207l3-3%203%203m0%206l-3%203-3-3%22%20stroke%3D%22%239CA3AF%22%20fill%3D%22none%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%2F%3E%3C%2Fsvg%3E');"
|
||||
>
|
||||
<option
|
||||
v-for="theme in availableThemes"
|
||||
:key="theme"
|
||||
:value="theme"
|
||||
class="py-1"
|
||||
<div class="relative inline-flex">
|
||||
<!-- Custom button with enhanced styling -->
|
||||
<button
|
||||
@click="themeDropdownOpen = !themeDropdownOpen"
|
||||
class="inline-flex items-center justify-between min-w-[120px] px-4 py-2
|
||||
bg-gradient-to-r from-blue-500/10 to-purple-500/10
|
||||
dark:from-blue-400/20 dark:to-purple-400/20
|
||||
border border-blue-200 dark:border-blue-700
|
||||
rounded-lg shadow-sm
|
||||
text-gray-700 dark:text-gray-200
|
||||
hover:border-blue-300 dark:hover:border-blue-600
|
||||
hover:shadow-md
|
||||
focus:outline-none focus:ring-2 focus:ring-blue-500/50
|
||||
transition-all duration-300 ease-in-out
|
||||
backdrop-blur-sm"
|
||||
>
|
||||
{{ theme }}
|
||||
</option>
|
||||
</select>
|
||||
<div class="flex items-center space-x-2">
|
||||
<!-- Theme Icon -->
|
||||
<svg
|
||||
class="w-5 h-5 text-blue-500 dark:text-blue-400"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01" />
|
||||
</svg>
|
||||
<span class="font-medium">{{ currentTheme }}</span>
|
||||
</div>
|
||||
<svg
|
||||
class="w-5 h-5 text-blue-500 dark:text-blue-400 transition-transform duration-300"
|
||||
:class="{ 'rotate-180': themeDropdownOpen }"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- Enhanced Dropdown menu with animations -->
|
||||
<div
|
||||
v-if="themeDropdownOpen"
|
||||
class="absolute left-0 z-50 w-full mt-2
|
||||
overflow-hidden
|
||||
bg-white dark:bg-gray-800
|
||||
border border-blue-200 dark:border-blue-700
|
||||
rounded-lg shadow-lg
|
||||
transform origin-top
|
||||
animate-dropdown"
|
||||
>
|
||||
<div class="max-h-60 overflow-y-auto">
|
||||
<a
|
||||
v-for="theme in availableThemes"
|
||||
:key="theme"
|
||||
@click="loadTheme(theme); currentTheme = theme; themeDropdownOpen = false"
|
||||
class="flex items-center space-x-2 px-4 py-3
|
||||
text-gray-700 dark:text-gray-200
|
||||
hover:bg-gradient-to-r hover:from-blue-50 hover:to-purple-50
|
||||
dark:hover:from-blue-900/30 dark:hover:to-purple-900/30
|
||||
cursor-pointer
|
||||
transition-colors duration-150
|
||||
group"
|
||||
>
|
||||
<div class="w-2 h-2 rounded-full bg-blue-400 group-hover:bg-blue-500
|
||||
transition-colors duration-150"></div>
|
||||
<span class="font-medium">{{ theme }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</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>
|
||||
@ -205,6 +255,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
themeDropdownOpen: false,
|
||||
currentTheme: localStorage.getItem('preferred-theme') || 'default',
|
||||
availableThemes: ['default', 'borg', 'amber', 'sober_gray', 'strawberry'],
|
||||
isLoading: false,
|
||||
@ -264,6 +315,7 @@ export default {
|
||||
},
|
||||
async mounted() {
|
||||
try {
|
||||
document.addEventListener('click', this.handleClickOutside)
|
||||
// Load saved theme preference
|
||||
const savedTheme = localStorage.getItem('preferred-theme')
|
||||
if (savedTheme && this.availableThemes.includes(savedTheme)) {
|
||||
@ -283,6 +335,9 @@ export default {
|
||||
console.error(err)
|
||||
}
|
||||
},
|
||||
beforeUnmount() {
|
||||
document.removeEventListener('click', this.handleClickOutside)
|
||||
},
|
||||
async created() {
|
||||
this.sunIcon = document.querySelector(".sun");
|
||||
this.moonIcon = document.querySelector(".moon");
|
||||
@ -297,6 +352,12 @@ export default {
|
||||
|
||||
},
|
||||
methods: {
|
||||
handleClickOutside(e) {
|
||||
const dropdown = this.$el
|
||||
if (!dropdown.contains(e.target)) {
|
||||
this.themeDropdownOpen = false
|
||||
}
|
||||
},
|
||||
getSavedTheme() {
|
||||
try {
|
||||
return localStorage.getItem('preferred-theme')
|
||||
|
@ -87,18 +87,19 @@
|
||||
alt="Logo" title="LoLLMS WebUI">
|
||||
</div>
|
||||
<div class="flex flex-col justify-center">
|
||||
<div class="text-sm md:text-xl font-bold text-amber-500 mb-2 hover:scale-105 transition-transform"
|
||||
style="text-shadow: 2px 2px 4px rgba(0,0,0,0.2),
|
||||
2px 2px 0px white,
|
||||
-2px -2px 0px white,
|
||||
2px -2px 0px white,
|
||||
-2px 2px 0px white;
|
||||
background: linear-gradient(45deg, #f59e0b, #fbbf24);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;">
|
||||
L<span class="animate-pulse">⭐</span>LLMS
|
||||
<div class="text-center p-2">
|
||||
<div class="text-md relative inline-block">
|
||||
<span class="relative inline-block font-bold tracking-wide text-black dark:text-white">
|
||||
LoLLMS
|
||||
</span>
|
||||
<div class="absolute -bottom-0.5 left-0 w-full h-0.5
|
||||
bg-black dark:bg-white
|
||||
transform origin-left transition-transform duration-300
|
||||
hover:scale-x-100 scale-x-0"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p class="text-gray-400 text-sm">One tool to rule them all</p>
|
||||
</div>
|
||||
</RouterLink>
|
||||
@ -257,20 +258,68 @@
|
||||
|
||||
|
||||
|
||||
<div class="toolbar-button" @mouseleave="hideBindingsMenu" v-if="!loading">
|
||||
<div class="toolbar-button" @mouseleave="hideBindingsMenu" v-if="!loading">
|
||||
<div class="relative inline-block">
|
||||
<!-- Bindings menu positioned above the button -->
|
||||
<div v-show="isBindingsMenuVisible" @mouseenter="showBindingsMenu" class="absolute m-0 p-0 z-10 top-full left-0 transform w-60 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-8 m-0 grid grid-cols-4 gap-4 max-h-60 overflow-y-auto custom-scrollbar">
|
||||
<div v-for="(item, index) in installedBindings" :key="index" class="relative group/item">
|
||||
<button @click.prevent="setBinding(item)" :title="item.name" class="w-10 h-10 rounded-full overflow-hidden transition-transform duration-200 transform group-hover/item:scale-110 focus:outline-none">
|
||||
<img :src="item.icon ? item.icon : modelImgPlaceholder" @error="modelImgPlaceholder" :alt="item.name" class="w-full h-full object-cover" :class="{'border-2 border-secondary': item.name == binding_name}">
|
||||
</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 bg-white rounded-md shadow-md p-1">
|
||||
<button @click.prevent="showModelConfig(item)" class="p-1 bg-blue-500 rounded-full text-white hover:bg-blue-600 focus:outline-none" title="Configure Binding">
|
||||
<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="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
|
||||
<div v-show="isBindingsMenuVisible" @mouseenter="showBindingsMenu" class="absolute m-0 p-0 z-10 top-full left-0 transform w-80 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">
|
||||
<!-- Search Bar -->
|
||||
<div class="p-2 border-b border-gray-200 dark:border-gray-700">
|
||||
<input
|
||||
type="text"
|
||||
v-model="bindingSearchQuery"
|
||||
placeholder="Search bindings..."
|
||||
class="w-full px-3 py-2 rounded-md border border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="p-4 grid grid-cols-3 gap-4 max-h-80 overflow-y-auto custom-scrollbar">
|
||||
<div
|
||||
v-for="(item, index) in filteredBindings"
|
||||
:key="index"
|
||||
class="relative group/item flex flex-col items-center"
|
||||
>
|
||||
<!-- Icon and Name Container -->
|
||||
<div class="flex flex-col items-center hover:bg-blue-100 dark:hover:bg-blue-900 p-2 rounded-md w-full cursor-pointer">
|
||||
<button
|
||||
@click.prevent="setBinding(item)"
|
||||
:title="item.name"
|
||||
class="w-12 h-12 rounded-md overflow-hidden transition-transform duration-200 transform group-hover/item:scale-105 focus:outline-none"
|
||||
>
|
||||
<img
|
||||
:src="item.icon ? item.icon : modelImgPlaceholder"
|
||||
@error="modelImgPlaceholder"
|
||||
:alt="item.name"
|
||||
class="w-full h-full object-cover"
|
||||
:class="{'border-2 border-secondary': item.name == binding_name}"
|
||||
>
|
||||
</button>
|
||||
|
||||
<!-- Truncated Name -->
|
||||
<span class="mt-1 text-xs text-center w-full truncate" :title="item.name">
|
||||
{{ item.name }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Hover Options -->
|
||||
<div
|
||||
class="absolute top-0 left-0 w-full h-full opacity-0 group-hover/item:opacity-100 transition-opacity duration-200 bg-white dark:bg-gray-900 rounded-md shadow-md p-2 flex flex-col items-center justify-center"
|
||||
>
|
||||
<!-- Full Name -->
|
||||
<span class="text-xs font-medium mb-2 text-center">{{ item.name }}</span>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex space-x-1">
|
||||
<button
|
||||
@click.prevent="showModelConfig(item)"
|
||||
class="p-1 bg-blue-500 rounded-full text-white hover:bg-blue-600 focus:outline-none"
|
||||
title="Configure Binding"
|
||||
>
|
||||
<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="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -289,18 +338,62 @@
|
||||
<div class="toolbar-button" @mouseleave="hideModelsMenu" v-if="!loading">
|
||||
<div class="relative inline-block">
|
||||
<!-- Models menu positioned above the button -->
|
||||
<div v-show="isModelsMenuVisible" @mouseenter="showModelsMenu" class="absolute m-0 p-0 z-10 top-full left-0 transform w-60 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-8 m-0 grid grid-cols-4 gap-4 max-h-60 overflow-y-auto custom-scrollbar">
|
||||
<div v-for="(item, index) in installedModels" :key="index" class="relative group/item">
|
||||
<button @click.prevent="setModel(item)" :title="item.name" class="w-10 h-10 rounded-full overflow-hidden transition-transform duration-200 transform group-hover/item:scale-110 focus:outline-none">
|
||||
<img :src="item.icon ? item.icon : modelImgPlaceholder" @error="personalityImgPlacehodler" :alt="item.name" class="w-full h-full object-cover" :class="{'border-2 border-secondary': item.name == model_name}">
|
||||
</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 bg-white rounded-md shadow-md p-1">
|
||||
<button @click.prevent="copyModelNameFrom(item.name)" class="p-1 bg-blue-500 rounded-full text-white hover:bg-blue-600 focus:outline-none" title="Copy Model Name">
|
||||
<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 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path></svg>
|
||||
<div v-show="isModelsMenuVisible" @mouseenter="showModelsMenu" class="absolute m-0 p-0 z-10 top-full left-0 transform w-80 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">
|
||||
<!-- Search Bar -->
|
||||
<div class="p-2 border-b border-gray-200 dark:border-gray-700">
|
||||
<input
|
||||
type="text"
|
||||
v-model="modelSearchQuery"
|
||||
placeholder="Search models..."
|
||||
class="w-full px-3 py-2 rounded-md border border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="p-4 grid grid-cols-3 gap-4 max-h-80 overflow-y-auto custom-scrollbar">
|
||||
<div
|
||||
v-for="(item, index) in filteredModels"
|
||||
:key="index"
|
||||
class="relative group/item flex flex-col items-center"
|
||||
>
|
||||
<!-- Icon and Name Container -->
|
||||
<div class="flex flex-col items-center hover:bg-blue-100 dark:hover:bg-blue-900 p-2 rounded-md w-full cursor-pointer">
|
||||
<button
|
||||
@click.prevent="setModel(item)"
|
||||
:title="item.name"
|
||||
class="w-12 h-12 rounded-md overflow-hidden transition-transform duration-200 transform group-hover/item:scale-105 focus:outline-none"
|
||||
>
|
||||
<img
|
||||
:src="item.icon ? item.icon : modelImgPlaceholder"
|
||||
@error="personalityImgPlacehodler"
|
||||
:alt="item.name"
|
||||
class="w-full h-full object-cover"
|
||||
:class="{'border-2 border-secondary': item.name == model_name}"
|
||||
>
|
||||
</button>
|
||||
<!-- You can add more buttons here if needed -->
|
||||
|
||||
<!-- Truncated Name -->
|
||||
<span class="mt-1 text-xs text-center w-full truncate" :title="item.name">
|
||||
{{ item.name }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Hover Options -->
|
||||
<div
|
||||
class="absolute top-0 left-0 w-full h-full opacity-0 group-hover/item:opacity-100 transition-opacity duration-200 bg-white dark:bg-gray-900 rounded-md shadow-md p-2 flex flex-col items-center justify-center"
|
||||
>
|
||||
<!-- Full Name -->
|
||||
<span class="text-xs font-medium mb-2 text-center">{{ item.name }}</span>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex space-x-1">
|
||||
<button
|
||||
@click.prevent="copyModelNameFrom(item.name)"
|
||||
class="p-1 bg-blue-500 rounded-full text-white hover:bg-blue-600 focus:outline-none"
|
||||
title="Copy Model Name"
|
||||
>
|
||||
<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 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -315,37 +408,92 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Personalities menu positioned above the dock -->
|
||||
<div class="toolbar-button" @mouseleave="hidePersonalitiesMenu" v-if="!loading">
|
||||
<div class="relative inline-block ">
|
||||
|
||||
<!-- Personalities menu positioned below the dock -->
|
||||
<div class="toolbar-button" @mouseleave="hidePersonalitiesMenu" v-if="!loading">
|
||||
<div class="relative inline-block">
|
||||
<!-- Personalities menu positioned above the button -->
|
||||
<div v-show="isPersonalitiesMenuVisible" @mouseenter="showPersonalitiesMenu" class="absolute m-0 p-0 z-10 top-full left-0 transform w-60 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-8 m-0 grid grid-cols-4 gap-4 max-h-60 overflow-y-auto custom-scrollbar">
|
||||
<div v-for="(item, index) in mountedPersonalities" :key="index" class="relative group/item">
|
||||
<button @click.prevent="onPersonalitySelected(item)" :title="item.name" class="w-10 h-10 rounded-full overflow-hidden transition-transform duration-200 transform group-hover/item:scale-110 focus:outline-none">
|
||||
<img :src="bUrl + item.avatar" @error="personalityImgPlacehodler" :alt="item.name" class="w-full h-full object-cover" :class="{'border-2 border-secondary': $store.state.active_personality_id == $store.state.personalities.indexOf(item.full_path)}">
|
||||
</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 bg-white dark:bg-gray-900 rounded-md shadow-md p-1">
|
||||
<button @click.prevent="unmountPersonality(item)" class="p-1 bg-red-500 rounded-full text-white hover:bg-red-600 focus:outline-none" title="Unmount">
|
||||
<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="M6 18L18 6M6 6l12 12"></path></svg>
|
||||
</button>
|
||||
<button @click.prevent="remount_personality(item)" class="p-1 bg-blue-500 rounded-full text-white hover:bg-blue-600 focus:outline-none ml-1" 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(item)" 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>
|
||||
<div v-show="isPersonalitiesMenuVisible" @mouseenter="showPersonalitiesMenu" class="absolute m-0 p-0 z-10 top-full left-0 transform w-80 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">
|
||||
<!-- Search Bar -->
|
||||
<div class="p-2 border-b border-gray-200 dark:border-gray-700">
|
||||
<input
|
||||
type="text"
|
||||
v-model="personalitySearchQuery"
|
||||
placeholder="Search personalities..."
|
||||
class="w-full px-3 py-2 rounded-md border border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="p-4 grid grid-cols-3 gap-4 max-h-80 overflow-y-auto custom-scrollbar">
|
||||
<div
|
||||
v-for="(item, index) in filteredPersonalities"
|
||||
:key="index"
|
||||
class="relative group/item flex flex-col items-center"
|
||||
>
|
||||
<!-- Icon and Name Container -->
|
||||
<div class="flex flex-col items-center hover:bg-blue-100 dark:hover:bg-blue-900 p-2 rounded-md w-full cursor-pointer">
|
||||
<button
|
||||
@click.prevent="onPersonalitySelected(item)"
|
||||
:title="item.name"
|
||||
class="w-12 h-12 rounded-md overflow-hidden transition-transform duration-200 transform group-hover/item:scale-105 focus:outline-none"
|
||||
>
|
||||
<img
|
||||
:src="bUrl + item.avatar"
|
||||
@error="personalityImgPlacehodler"
|
||||
:alt="item.name"
|
||||
class="w-full h-full object-cover"
|
||||
:class="{'border-2 border-secondary': $store.state.active_personality_id == $store.state.personalities.indexOf(item.full_path)}"
|
||||
>
|
||||
</button>
|
||||
|
||||
<!-- Truncated Name -->
|
||||
<span class="mt-1 text-xs text-center w-full truncate" :title="item.name">
|
||||
{{ item.name }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Hover Options -->
|
||||
<div
|
||||
class="absolute top-0 left-0 w-full h-full opacity-0 group-hover/item:opacity-100 transition-opacity duration-200 bg-white dark:bg-gray-900 rounded-md shadow-md p-2 flex flex-col items-center justify-center"
|
||||
>
|
||||
<!-- Full Name -->
|
||||
<span class="text-xs font-medium mb-2 text-center">{{ item.name }}</span>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex space-x-1">
|
||||
<button
|
||||
@click.prevent="unmountPersonality(item)"
|
||||
class="p-1 bg-red-500 rounded-full text-white hover:bg-red-600 focus:outline-none"
|
||||
title="Unmount"
|
||||
>
|
||||
<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="M6 18L18 6M6 6l12 12"></path></svg>
|
||||
</button>
|
||||
<button
|
||||
@click.prevent="remount_personality(item)"
|
||||
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(item)"
|
||||
class="p-1 bg-green-500 rounded-full text-white hover:bg-green-600 focus:outline-none"
|
||||
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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div @mouseenter="showPersonalitiesMenu" class="personalities-hover-area">
|
||||
<MountedPersonalities ref="mountedPers" :onShowPersList="onShowPersListFun" :onReady="onPersonalitiesReadyFun"/>
|
||||
<MountedPersonalities ref="mountedPers" :onShowPersList="onShowPersListFun" :onReady="onPersonalitiesReadyFun"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@ -1027,6 +1175,9 @@ export default {
|
||||
placeholderValues: {},
|
||||
previewPrompt: '',
|
||||
|
||||
bindingSearchQuery: '',
|
||||
modelSearchQuery: '',
|
||||
personalitySearchQuery: '',
|
||||
isSearching: false,
|
||||
isPersonalitiesMenuVisible: false,
|
||||
isModelsMenuVisible:false,
|
||||
@ -2233,13 +2384,14 @@ export default {
|
||||
console.log(`Selecting discussion: ${this.currentDiscussion}`)
|
||||
// When discussion is selected it loads the discussion array
|
||||
if (this.currentDiscussion===undefined) {
|
||||
console.log(`Selecting discussion: ${this.currentDiscussion}`)
|
||||
console.log(`Selecting discussion: ${this.currentDiscussion.id}`)
|
||||
this.currentDiscussion = item
|
||||
|
||||
this.setPageTitle(item)
|
||||
|
||||
localStorage.setItem('selected_discussion', this.currentDiscussion.id)
|
||||
console.log(`Saved discussion to : ${this.currentDiscussion.id}`)
|
||||
const discussion_id = localStorage.getItem('selected_discussion')
|
||||
console.log(`Saved discussion to : ${discussion_id}`)
|
||||
|
||||
this.load_discussion(item.id, ()=>{
|
||||
if (this.discussionArr.length > 1) {
|
||||
@ -3580,7 +3732,21 @@ export default {
|
||||
|
||||
},
|
||||
computed: {
|
||||
|
||||
filteredBindings() {
|
||||
return this.installedBindings.filter(binding =>
|
||||
binding.name.toLowerCase().includes(this.bindingSearchQuery.toLowerCase())
|
||||
)
|
||||
},
|
||||
filteredModels() {
|
||||
return this.installedModels.filter(model =>
|
||||
model.name.toLowerCase().includes(this.modelSearchQuery.toLowerCase())
|
||||
)
|
||||
},
|
||||
filteredPersonalities() {
|
||||
return this.mountedPersonalities.filter(personality =>
|
||||
personality.name.toLowerCase().includes(this.personalitySearchQuery.toLowerCase())
|
||||
)
|
||||
},
|
||||
currentModel() {
|
||||
return this.$store.state.currentModel || {};
|
||||
},
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit f9c5429d84ccbeaa78acf42b68ed908a96151218
|
||||
Subproject commit 1fac389bf6c0c9ccc7d4c50766c938f8ea79d3b7
|
Loading…
Reference in New Issue
Block a user