agent-zero/webui/components/sidebar/top-section/quick-actions.html
frdel 7eb6d5b19a refactor: optimize WebSocket handler lifecycle and fix extension asset path handling
- Change `_active_handlers` from list of tuples to dict mapping paths to handler instances
- Cache handler instances on connect instead of recreating them for each event
- Reuse cached instances in `_dispatch` instead of instantiating new ones
- Remove redundant handler instantiation in `_on_disconnect`
- Add type ignore comments for socketio event decorators
- Fix extension asset path construction to use proper directory variable
2026-03-17 17:00:40 +01:00

255 lines
8.2 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<html>
<head>
<script type="module">
import { store as chatsStore } from "/components/sidebar/chats/chats-store.js";
import { store as projectsStore } from "/components/projects/projects-store.js";
import { store as sidebarStore } from "/components/sidebar/sidebar-store.js";
</script>
</head>
<body>
<div class="wrapper" x-data="{ dropdownOpen: false }" @click.outside="dropdownOpen = false" @keydown.escape.window="dropdownOpen = false" x-init="$watch('dropdownOpen', v => v && $store.sidebar.updateDropdownPosition($el))">
<div id="quick-actions">
<x-extension id="sidebar-quick-actions-main-start"></x-extension>
<!-- Dashboard -->
<button class="config-button" id="dashboard" @click="deselectChat()" title="Dashboard">
<span class="material-symbols-outlined">home</span>
</button>
<!-- Scheduler -->
<button class="config-button" id="plugins" @click="openModal('components/plugins/list/plugin-list.html')" title="Plugins">
<span class="material-symbols-outlined">extension</span>
</button>
<!-- Settings -->
<button class="config-button" id="settings" @click="openModal('settings/settings.html')" title="Settings">
<span class="material-symbols-outlined">settings</span>
</button>
<x-extension id="sidebar-quick-actions-main-end"></x-extension>
<!-- Dropdown Toggle -->
<button class="config-button dropdown-toggle" @click="dropdownOpen = !dropdownOpen" title="More options">
<span class="material-symbols-outlined" :class="dropdownOpen ? 'rotated' : ''">expand_more</span>
</button>
</div>
<!-- Dropdown Menu -->
<div class="dropdown-menu quick-actions-dropdown"
x-show="dropdownOpen"
:style="$store.sidebar.dropdownStyle">
<x-extension id="sidebar-quick-actions-dropdown-start"></x-extension>
<div class="dropdown-header">Navigation</div>
<button class="dropdown-item" @click="deselectChat(); dropdownOpen = false">
<span class="material-symbols-outlined">home</span>
<span>Dashboard</span>
</button>
<button class="dropdown-item" @click="$store.projects.openProjectsModal(); dropdownOpen = false">
<span class="material-symbols-outlined">snippet_folder</span>
<span>Projects</span>
</button>
<button class="dropdown-item" @click="openModal('components/modals/scheduler/scheduler-modal.html'); dropdownOpen = false">
<span class="material-symbols-outlined">schedule</span>
<span>Scheduler</span>
</button>
<button class="dropdown-item" @click="openModal('settings/settings.html'); dropdownOpen = false">
<span class="material-symbols-outlined">settings</span>
<span>Settings</span>
</button>
<div class="dropdown-separator"></div>
<div class="dropdown-header">Chat Actions</div>
<button class="dropdown-item" @click="$store.chats.newChat(); dropdownOpen = false">
<span class="material-symbols-outlined">edit_square</span>
<span>New Chat</span>
</button>
<button class="dropdown-item" @click="$store.chats.loadChats(); dropdownOpen = false">
<span class="material-symbols-outlined">folder_open</span>
<span>Load Chat</span>
</button>
<button class="dropdown-item" @click="$store.chats.saveChat(); dropdownOpen = false" :disabled="!$store.chats.selected">
<span class="material-symbols-outlined">save</span>
<span>Save Chat</span>
</button>
<button class="dropdown-item" @click="$confirmClick($event, () => { $store.chats.resetChat(); dropdownOpen = false })" :disabled="!$store.chats.selected">
<span class="material-symbols-outlined">delete_sweep</span>
<span>Clear Chat</span>
</button>
<div class="dropdown-separator"></div>
<button class="dropdown-item" @click="$confirmClick($event, () => { $store.chats.logout(); dropdownOpen = false })" :disabled="!$store.chats.loggedIn">
<span class="material-symbols-outlined">logout</span>
<span>Logout</span>
</button>
<button class="dropdown-item" @click="$confirmClick($event, () => { $store.chats.restart(); dropdownOpen = false })">
<span class="material-symbols-outlined">restart_alt</span>
<span>Restart A0</span>
</button>
<x-extension id="sidebar-quick-actions-dropdown-end"></x-extension>
</div>
</div>
</body>
<style>
/* Wrapper container for icon toolbar */
.wrapper {
position: relative;
border-radius: 0.6rem;
z-index: 100;
/* Ensure dropdown appears above all sidebar content */
}
/* Icon toolbar layout grid for extension-friendly wrapping */
#quick-actions {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-auto-rows: auto;
width: 100%;
padding: 0;
gap: var(--spacing-xs);
}
#quick-actions > x-extension:not(:empty) {
display: contents;
}
#quick-actions > x-extension:empty {
display: none;
}
#quick-actions > x-extension > x-component,
#quick-actions > x-extension > x-component > div[x-data] {
display: contents;
}
/* Config button - icon only style */
.config-button {
background-color: var(--color-panel);
border: 0.05rem solid var(--color-border);
border-radius: 4px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
opacity: 0.8;
padding: var(--spacing-xs);
flex: 1;
min-width: 0;
transition: background-color var(--transition-speed),
border-color var(--transition-speed), box-shadow var(--transition-speed),
opacity var(--transition-speed);
}
.config-button .material-symbols-outlined {
font-size: 22px;
transition: transform 0.2s ease;
}
.config-button .material-symbols-outlined.rotated {
transform: rotate(180deg);
}
.config-button:hover {
background-color: var(--color-background-hover);
opacity: 1;
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-primary) 18%, transparent);
z-index: 1;
position: relative;
}
.config-button:active {
opacity: 0.5;
box-shadow: inset 0 0 0 999px rgba(0, 0, 0, 0.06);
}
/* Dropdown specific positioning - fixed to escape overflow:hidden */
.quick-actions-dropdown {
position: fixed;
z-index: 9999;
margin-top: 0;
}
/* Unified scrollbar styling for dropdown */
.quick-actions-dropdown::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.quick-actions-dropdown::-webkit-scrollbar-track {
background: transparent;
margin: 4px 0;
border-radius: 6px;
}
.quick-actions-dropdown::-webkit-scrollbar-thumb {
background-color: rgba(155, 155, 155, 0.5);
border-radius: 6px;
transition: background-color 0.2s ease;
}
.quick-actions-dropdown::-webkit-scrollbar-thumb:hover {
background-color: rgba(155, 155, 155, 0.7);
}
/* Dropdown item icon sizing */
.quick-actions-dropdown .dropdown-item,
.quick-actions-dropdown .dropdown-item .material-symbols-outlined {
opacity: 1;
}
.quick-actions-dropdown .dropdown-item .material-symbols-outlined {
font-size: 18px;
}
/* New Chat Button */
#newChat {
display: flex;
flex-wrap: nowrap;
background-color: transparent;
border: none;
align-items: center;
opacity: 0.6;
cursor: pointer;
-webkit-transition: opacity 0.1s ease-in-out, color 0.1s ease-in-out, filter 0.1s ease-in-out, left var(--transition-speed) ease-in-out;
transition: opacity 0.1s ease-in-out, color 0.1s ease-in-out, filter 0.1s ease-in-out, left var(--transition-speed) ease-in-out;
}
#newChat:hover { opacity: 0.85; filter: brightness(1.08); }
#newChat:active { opacity: 0.5; filter: brightness(0.96); }
#newChat .material-symbols-outlined {
color: var(--color-text);
font-size: 24px;
}
/* Light mode */
.light-mode .config-button {
background-color: var(--color-background);
color: #333333;
}
.light-mode .config-button:hover { background-color: var(--color-background-hover); }
.light-mode .config-button:active { background-color: var(--color-background-hover); }
/* Transition helpers */
.-translate-y-1 { transform: translateY(-0.25rem); }
.translate-y-0 { transform: translateY(0); }
</style>
</html>