Enhanced function calls ui

This commit is contained in:
Saifeddine ALOUI 2025-03-09 21:50:40 +01:00
parent 56e8cfdb5c
commit f3c55a482e
6 changed files with 202 additions and 143 deletions

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
View File

@ -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-Dt6gkR_r.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BHdxPy4b.css">
<script type="module" crossorigin src="/assets/index-DZWSFbg9.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DY6AAHko.css">
</head>
<body>
<div id="app"></div>

View File

@ -169,6 +169,7 @@
:help="'Function calls (WIP)'"
:commandsList="functionCalls"
:sendCommand="toggleFunctionCall"
:showSettings="showFunctionSettings"
:on-show-toast-message="onShowToastMessage"
ref="functioncalls"
/>
@ -831,6 +832,54 @@ export default {
await this.$store.dispatch('refreshConfig');
console.log("Refreshed")
},
async showFunctionSettings(entry){
const func = entry
// Split the path by '/' and filter out empty segments
let normalizedPath = func.dir.replace(/\\/g, '/');
const segments = normalizedPath.split('/').filter(segment => segment !== '');
// Get the parent folder name (second-to-last segment)
const category = segments[segments.length - 2];
try {
this.isLoading = true
axios.post('/get_function_call_settings',{client_id:this.$store.state.client_id,category:category,name:func.name}).then(res => {
this.isLoading = false
if (res) {
if (res.data && Object.keys(res.data).length > 0) {
// open form
this.$store.state.universalForm.showForm(res.data, "Function call settings - " +func.name, "Save changes", "Cancel").then(res => {
// send new data
try {
axios.post('/set_function_call_settings',
{client_id:this.$store.state.client_id,category:func.category,name:func.name, "settings":res}, {headers: this.posts_headers}).then(response => {
if (response && response.data) {
console.log('function call set with new settings', response.data)
this.$store.state.toast.showToast("function call settings updated successfully!", 4, true)
} else {
this.$store.state.toast.showToast("Did not get function call settings responses.\n" + response, 4, false)
this.isLoading = false
}
})
} catch (error) {
this.$store.state.toast.showToast("Did not get function call settings responses.\n Endpoint error: " + error.message, 4, false)
this.isLoading = false
}
})
} else {
this.$store.state.toast.showToast("Function call has no settings", 4, false)
this.isLoading = false
}
}
})
} catch (error) {
this.isLoading = false
this.$store.state.toast.showToast("Could not open function call settings. Endpoint error: " + error.message, 4, false)
}
},
async toggleFunctionCall(func){
console.log("function call:")

View File

@ -8,10 +8,10 @@
class="flex items-center gap-2 px-4 py-2 text-white rounded-lg transition-all duration-300 shadow-md"
:title="help"
:class="{
'bg-blue-600 hover:bg-blue-700': !isAnyCommandChecked, // Default state
'bg-yellow-400 hover:bg-yellow-500': isAnyCommandChecked // Highlighted state
'bg-blue-600 hover:bg-blue-700': !isAnyCommandChecked,
'bg-yellow-400 hover:bg-yellow-500': isAnyCommandChecked
}"
> <!-- Custom Icon -->
>
<template v-if="icon">
<svg
v-if="iconParts.type === 'feather'"
@ -39,7 +39,6 @@
/>
</template>
<!-- Chevron Icon -->
<svg
class="w-4 h-4 transform transition-transform"
:class="{ 'rotate-180': showMenu }"
@ -60,74 +59,81 @@
<div
v-if="showMenu"
ref="menu"
class="absolute z-50 mt-2 w-64 origin-top-right rounded-lg bg-white dark:bg-gray-800 shadow-xl ring-1 ring-black ring-opacity-5 focus:outline-none"
class="absolute z-50 mt-2 w-72 origin-top-right rounded-lg bg-white dark:bg-gray-800 shadow-xl ring-1 ring-black ring-opacity-5 focus:outline-none"
:class="menuPosition === 'above' ? 'bottom-full mb-2' : 'top-full'"
>
<div class="p-2 space-y-1 custom-scrollbar max-h-96 overflow-y-auto">
<template v-for="(cmd, index) in commandsList" :key="index">
<button
:title="cmd.help"
@click="selected(cmd)"
class="flex w-full items-center rounded-md px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-blue-100 dark:hover:bg-gray-700 transition-colors duration-200"
>
<!-- Custom Checkbox for is_checked -->
<span v-if="cmd.is_checked !== undefined" class="mr-2 relative">
<input
type="checkbox"
:checked="cmd.is_checked"
@click.stop="selected(cmd)"
class="opacity-0 absolute h-4 w-4"
:id="`checkbox-${index}`"
/>
<label
:for="`checkbox-${index}`"
class="flex items-center justify-center h-4 w-4 border-2 border-blue-500 rounded-sm cursor-pointer transition-colors duration-200"
:class="{ 'bg-blue-500 border-blue-500': cmd.is_checked }"
<div class="p-2 space-y-1 custom-scrollbar max-h-96 overflow-y-auto">
<template v-for="(cmd, index) in commandsList" :key="index">
<div class="flex items-center justify-between w-full px-2 py-1 hover:bg-blue-100 dark:hover:bg-gray-700 transition-colors duration-200 rounded-md">
<button
:title="cmd.help"
@click="selected(cmd)"
class="flex items-center flex-1 min-w-0 text-sm text-gray-700 dark:text-gray-200"
>
<svg
v-if="cmd.is_checked"
class="h-3 w-3 text-white"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M5 13l4 4L19 7"
<span v-if="cmd.is_checked !== undefined" class="mr-2 flex-shrink-0">
<input
type="checkbox"
:checked="cmd.is_checked"
class="opacity-0 absolute h-4 w-4"
:id="`checkbox-${index}`"
/>
</svg>
</label>
</span>
<label
:for="`checkbox-${index}`"
class="flex items-center justify-center h-4 w-4 border-2 border-blue-500 rounded-sm cursor-pointer transition-colors duration-200"
:class="{ 'bg-blue-500 border-blue-500': cmd.is_checked }"
>
<svg
v-if="cmd.is_checked"
class="h-3 w-3 text-white"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M5 13l4 4L19 7"
/>
</svg>
</label>
</span>
<!-- Icon handling -->
<span v-if="cmd.icon" class="mr-2">
<template v-if="cmd.icon.startsWith('feather:')">
<i :data-feather="cmd.icon.replace('feather:', '')"></i>
</template>
<template v-else-if="cmd.icon.startsWith('img:')">
<img :src="cmd.icon.replace('img:', '')" class="w-4 h-4" />
</template>
<template v-else-if="cmd.icon.startsWith('b64:')">
<img :src="`data:image/png;base64,${cmd.icon.replace('b64:', '')}`" class="w-4 h-4" />
</template>
</span>
<span v-if="cmd.icon" class="mr-2 flex-shrink-0">
<template v-if="cmd.icon.startsWith('feather:')">
<i :data-feather="cmd.icon.replace('feather:', '')" class="w-4 h-4"></i>
</template>
<template v-else-if="cmd.icon.startsWith('img:')">
<img :src="cmd.icon.replace('img:', '')" class="w-4 h-4" />
</template>
<template v-else-if="cmd.icon.startsWith('b64:')">
<img :src="`data:image/png;base64,${cmd.icon.replace('b64:', '')}`" class="w-4 h-4" />
</template>
</span>
<!-- Command name -->
<span v-html="cmd.name" class="truncate"></span>
</button>
<span v-html="cmd.name" class="truncate flex-1 text-left"></span>
</button>
<!-- Divider between commands -->
<div v-if="index < commandsList.length - 1" class="border-t border-gray-200 dark:border-gray-700"></div>
</template>
</div>
<button
v-if="showSettings !== undefined"
@click="showSettings(cmd)"
class="text-green-500 hover:text-green-600 transition duration-300 ease-in-out flex-shrink-0 p-1"
title="Settings"
>
<i data-feather="settings" class="h-4 w-4"></i>
</button>
</div>
<div v-if="index < commandsList.length - 1" class="border-t border-gray-200 dark:border-gray-700"></div>
</template>
</div>
</div>
</transition>
</div>
</template>
<script>
import feather from 'feather-icons'
export default {
data() {
return {
@ -139,6 +145,7 @@ export default {
props: {
commandsList: Array,
sendCommand: Function,
showSettings: Function,
help: {
type: String,
default: ''
@ -166,15 +173,16 @@ export default {
}
},
methods: {
selected(cmd){
if(cmd.is_checked !== undefined)
cmd.is_checked = ! cmd.is_checked
selected(cmd) {
if (cmd.is_checked !== undefined)
cmd.is_checked = !cmd.is_checked
this.sendCommand(cmd.value)
},
toggleMenu() {
this.showMenu = !this.showMenu
if (this.showMenu) {
this.$nextTick(() => {
feather.replace();
this.calculatePosition()
})
}

@ -1 +1 @@
Subproject commit 4998690798803b017305ba9118816f7a6b51c61e
Subproject commit fb040384246527cefd6344a7fa97fe80ced80e0f