- Add complete Project Hub & Workspace Interface implementation - New data models: Project, ModuleKit, Workspace - 3 fixture projects (cybermind.fr, cybermood.eu, secubox-c3) - 4 module kits (Security, Network, Automation, Media) - Workspace routes with project switching and kit installation - 4 workspace tabs: Overview, Module Kits, Devices, Composer - New navigation item: Workspace (7th section) - Remove all glowing effects from UI - Remove Command Center widget glow and backdrop blur - Remove device status indicator glow - Remove toggle button glow effects - Extend DataStore with 13 new methods for workspace management - Add 270+ lines of workspace-specific CSS with responsive layouts - Create workspace templates and result partials 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
70 lines
2.9 KiB
HTML
70 lines
2.9 KiB
HTML
{#
|
|
Reusable Card Actions Component
|
|
|
|
Usage:
|
|
{% include "components/card_actions.html" with {
|
|
"actions": [
|
|
{"label": "Install", "url": "/api/install/...", "method": "post"},
|
|
{"label": "Preview", "url": "/modules/...", "method": "get"},
|
|
]
|
|
} %}
|
|
#}
|
|
|
|
<div class="card-actions-menu" x-data="{ menuOpen: false }">
|
|
<!-- Primary action button (if specified) -->
|
|
{% if primary_action %}
|
|
<button class="btn btn-primary btn-sm"
|
|
hx-{{ primary_action.method|default('get')|lower }}="{{ primary_action.url }}"
|
|
hx-target="{{ primary_action.target|default('#status-toast') }}"
|
|
hx-swap="{{ primary_action.swap|default('innerHTML') }}"
|
|
@click="$store.app.showToast('{{ primary_action.toast|default('Processing...') }}', 'info')">
|
|
{% if primary_action.icon %}{{ primary_action.icon }} {% endif %}
|
|
{{ primary_action.label|default('Action') }}
|
|
</button>
|
|
{% endif %}
|
|
|
|
<!-- Dropdown menu for additional actions -->
|
|
{% if actions and actions|length > 0 %}
|
|
<div class="action-dropdown">
|
|
<button @click="menuOpen = !menuOpen"
|
|
class="btn btn-ghost btn-sm"
|
|
aria-label="More actions">
|
|
<span class="dropdown-icon">⋮</span>
|
|
</button>
|
|
|
|
<div x-show="menuOpen"
|
|
@click.away="menuOpen = false"
|
|
x-transition:enter="transition ease-out duration-100"
|
|
x-transition:enter-start="opacity-0 scale-95"
|
|
x-transition:enter-end="opacity-100 scale-100"
|
|
x-transition:leave="transition ease-in duration-75"
|
|
x-transition:leave-start="opacity-100 scale-100"
|
|
x-transition:leave-end="opacity-0 scale-95"
|
|
class="dropdown-menu">
|
|
|
|
{% for action in actions %}
|
|
{% if action.divider %}
|
|
<div class="dropdown-divider"></div>
|
|
{% elif action.header %}
|
|
<div class="dropdown-header">{{ action.label }}</div>
|
|
{% else %}
|
|
<button class="dropdown-item"
|
|
hx-{{ action.method|default('get')|lower }}="{{ action.url }}"
|
|
hx-target="{{ action.target|default('#status-toast') }}"
|
|
hx-swap="{{ action.swap|default('innerHTML') }}"
|
|
@click="menuOpen = false; $store.app.showToast('{{ action.toast|default('Action started...') }}', 'info')">
|
|
{% if action.icon %}
|
|
<span class="dropdown-item-icon">{{ action.icon }}</span>
|
|
{% endif %}
|
|
<span class="dropdown-item-label">{{ action.label }}</span>
|
|
{% if action.shortcut %}
|
|
<span class="dropdown-item-shortcut">{{ action.shortcut }}</span>
|
|
{% endif %}
|
|
</button>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|