Ship War Room UX, CEO inbox, mobile chat, and Agents NAS workspace.
Make A2A togglable, keep reply context while reading, route agent data to //10.4.7.11/share/Agents, and polish themes plus export-intel sync cancel.
This commit is contained in:
+140
-34
@@ -4,12 +4,12 @@
|
||||
<link rel="stylesheet" href="/static/css/hermes.css" />
|
||||
<link rel="stylesheet" href="/static/css/herman-dashboard.css?v=13" />
|
||||
<link rel="stylesheet" href="/static/css/agents-mesh.css?v=8" />
|
||||
<link rel="stylesheet" href="/static/css/agent-characters.css?v=4" />
|
||||
<link rel="stylesheet" href="/static/css/agents-warroom.css?v=18" />
|
||||
<script src="/static/js/agent-avatars.js?v=4"></script>
|
||||
<link rel="stylesheet" href="/static/css/agent-characters.css?v=8" />
|
||||
<link rel="stylesheet" href="/static/css/agents-warroom.css?v=40" />
|
||||
<script src="/static/js/agent-avatars.js?v=5"></script>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="hm-neo" x-data="agentsSoulHub()" x-init="init()">
|
||||
<div class="hm-neo" :class="{ 'tab-warroom-active': tab==='warroom' }" x-data="agentsSoulHub()" x-init="init()">
|
||||
<header class="hm-neo-header page-header" x-show="tab!=='warroom'" x-cloak>
|
||||
<h1>Agents · Soul Registry</h1>
|
||||
<p class="hm-sub">Animated team · duidelijke rollen · soul.md · live activiteit</p>
|
||||
@@ -32,22 +32,22 @@
|
||||
<div class="vtabs-layout" style="--vt-color:#ffd700" x-ref="vtabsWrap">
|
||||
<nav class="vtabs-nav" x-ref="vtabsNav" :style="'--vt-indicator-top:'+tabIndicatorTop+'px;--vt-indicator-h:'+tabIndicatorH+'px'">
|
||||
<div class="vtabs-nav-header"><strong>Agents</strong></div>
|
||||
<button class="vtab-btn" :class="{active: tab==='warroom'}" @click="setTab('warroom', $el)" data-tab="warroom">
|
||||
<span class="vtab-icon vtab-icon-svg" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2 4 6v6c0 5 3.5 8.5 8 10 4.5-1.5 8-5 8-10V6l-8-4Z"/><path d="m9 12 2 2 4-4"/></svg></span><span>War Room</span>
|
||||
</button>
|
||||
<button class="vtab-btn" :class="{active: tab==='souls'}" @click="setTab('souls', $el)">
|
||||
<span class="vtab-icon">🧬</span><span>Souls</span>
|
||||
<span class="vtab-icon vtab-icon-svg" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M12 8V4H8"/><rect width="16" height="12" x="4" y="8" rx="2"/><path d="M2 14h2"/><path d="M20 14h2"/><path d="M15 13v2"/><path d="M9 13v2"/></svg></span><span>Souls</span>
|
||||
</button>
|
||||
<button class="vtab-btn" :class="{active: tab==='mesh'}" @click="setTab('mesh', $el)">
|
||||
<span class="vtab-icon">🕸️</span><span>Netwerk</span>
|
||||
<span class="vtab-icon vtab-icon-svg" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="5" r="2"/><circle cx="5" cy="19" r="2"/><circle cx="19" cy="19" r="2"/><path d="M12 7v4"/><path d="m6.7 17.4 3.6-2.4"/><path d="m17.3 17.4-3.6-2.4"/><circle cx="12" cy="12" r="2"/></svg></span><span>Netwerk</span>
|
||||
</button>
|
||||
<button class="vtab-btn" :class="{active: tab==='terminals'}" @click="setTab('terminals', $el)" data-tab="terminals">
|
||||
<span class="vtab-icon">🖥️</span><span>Terminals</span>
|
||||
<span class="vtab-icon vtab-icon-svg" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="3" rx="2"/><path d="M8 21h8"/><path d="M12 17v4"/><path d="m7 8 3 3-3 3"/><path d="M13 14h3"/></svg></span><span>Terminals</span>
|
||||
</button>
|
||||
<button class="vtab-btn" :class="{active: tab==='approvals'}" @click="setTab('approvals', $el)">
|
||||
<span class="vtab-icon">✓</span><span>Goedkeuringen</span>
|
||||
<span class="vtab-icon vtab-icon-svg" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><path d="m9 11 3 3L22 4"/></svg></span><span>Goedkeuringen</span>
|
||||
<span class="vtab-badge" x-show="pendingCount" x-text="pendingCount"></span>
|
||||
</button>
|
||||
<button class="vtab-btn" :class="{active: tab==='warroom'}" @click="setTab('warroom', $el)" data-tab="warroom">
|
||||
<span class="vtab-icon">⚔️</span><span>War Room</span>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<div class="vtabs-content">
|
||||
@@ -275,11 +275,19 @@
|
||||
<section x-show="tab==='warroom'" x-cloak>
|
||||
<div x-data="warRoomHub()" x-init="init()" class="wr-hub-root">
|
||||
<div class="panel" style="padding:0.75rem">
|
||||
<div class="wr-layout">
|
||||
<div class="wr-layout" :class="{'roster-collapsed': rosterCollapsed}">
|
||||
<div class="wr-mobile-bar">
|
||||
<button type="button" class="btn btn-sm" @click="rosterCollapsed = !rosterCollapsed"
|
||||
x-text="rosterCollapsed ? '👥 Agents' : '▾ Agents'"></button>
|
||||
<button type="button" class="btn btn-sm wr-a2a-btn"
|
||||
:class="autoDebate ? 'is-on' : 'is-off'"
|
||||
@click="toggleA2A()"
|
||||
x-text="autoDebate ? 'A2A · aan' : 'A2A · uit'"></button>
|
||||
</div>
|
||||
<aside class="wr-roster">
|
||||
<h3>Kanalen</h3>
|
||||
<button type="button" class="wr-room-btn" :class="{active: room && room.kind==='warroom'}" @click="openWarroom()">
|
||||
<span>⚔️</span><strong>#war-room</strong>
|
||||
<span class="wr-chan-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2 4 6v6c0 5 3.5 8.5 8 10 4.5-1.5 8-5 8-10V6l-8-4Z"/><path d="m9 12 2 2 4-4"/></svg></span><strong>#war-room</strong>
|
||||
</button>
|
||||
<h3 style="margin-top:0.85rem">Agents</h3>
|
||||
<template x-for="s in souls" :key="'wr-'+s.agent_key">
|
||||
@@ -301,22 +309,62 @@
|
||||
</aside>
|
||||
<div class="wr-main">
|
||||
<div class="wr-head">
|
||||
<div>
|
||||
<div class="wr-head-title">
|
||||
<h2 x-text="room ? (room.title || ('#'+room.kind)) : 'War Room'"></h2>
|
||||
<small class="muted" x-show="status" x-text="status"></small>
|
||||
<small class="wr-msg-count muted" x-show="messages.length"
|
||||
x-text="(screenCleared ? '0' : visibleMessages().length) + ' / ' + messages.length + ' berichten'"></small>
|
||||
</div>
|
||||
<div class="wr-head-actions">
|
||||
<label class="btn btn-sm" style="display:inline-flex;align-items:center;gap:0.3rem;cursor:pointer;margin:0" title="Agents praten onderling door"><input type="checkbox" x-model="autoDebate" @change="autoDebate && scheduleContinue(1500)" style="margin:0" /> A2A</label>
|
||||
<button type="button" class="btn btn-sm btn-pulse" @click="openVoiceRoom()" :disabled="!room" title="Spraakmeeting met agents">🎙️ Voice Room</button><button type="button" class="btn btn-sm" :class="{'is-recording': voiceRecording}" @mousedown.prevent="startVoiceTalk($event)" @mouseup.prevent="stopVoiceTalk($event)" @touchstart.prevent="startVoiceTalk($event)" @touchend.prevent="stopVoiceTalk($event)" :disabled="voiceBusy || busy || !room" title="Snel praten">🎤</button>
|
||||
<button type="button" class="btn btn-sm" @click="popOut()" title="Open op tweede scherm">Pop-out ↗</button>
|
||||
<button type="button" class="btn btn-sm" @click="room && openRoom(room.id)" :disabled="busy">↻</button>
|
||||
<button type="button" class="btn btn-sm wr-tool-btn" :class="{active: searchOpen}" @click="toggleSearch()" title="Zoeken in chat">🔍 Zoek</button>
|
||||
<div class="wr-tools-wrap">
|
||||
<button type="button" class="btn btn-sm wr-tool-btn" @click="toolsOpen=!toolsOpen" title="Meer acties">⋯</button>
|
||||
<div class="wr-tools-menu" x-show="toolsOpen" @click.outside="toolsOpen=false" x-cloak>
|
||||
<button type="button" @click="downloadChat('txt')">⬇ Download .txt</button>
|
||||
<button type="button" @click="downloadChat('md')">⬇ Download .md</button>
|
||||
<button type="button" @click="downloadChat('json')">⬇ Download .json</button>
|
||||
<hr />
|
||||
<button type="button" @click="clearScreen(); toolsOpen=false">🧹 Scherm legen</button>
|
||||
<button type="button" x-show="screenCleared" @click="restoreScreen(); toolsOpen=false">↩ Scherm herstellen</button>
|
||||
<button type="button" class="wr-danger" @click="clearChatHistory(); toolsOpen=false">🗑 Geschiedenis wissen</button>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm wr-a2a-btn"
|
||||
:class="autoDebate ? 'is-on' : 'is-off'"
|
||||
@click="toggleA2A()"
|
||||
:title="autoDebate ? 'A2A staat aan — klik om uit te zetten' : 'A2A staat uit — klik om aan te zetten'">
|
||||
<span x-text="autoDebate ? 'A2A · aan' : 'A2A · uit'"></span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm wr-ceo-btn" @click="openCeoInbox()" title="Direct aan jou (@aissa)">
|
||||
📬 CEO-inbox
|
||||
<span class="wr-ceo-badge" x-show="ceoUnread > 0" x-text="ceoUnread"></span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-pulse" @click="openVoiceRoom()" title="Spraakmeeting met agents">🎙️ Voice</button>
|
||||
<button type="button" class="btn btn-sm" :class="{'is-recording': voiceRecording}" @mousedown.prevent="startVoiceTalk($event)" @mouseup.prevent="stopVoiceTalk($event)" @touchstart.prevent="startVoiceTalk($event)" @touchend.prevent="stopVoiceTalk($event)" :disabled="voiceBusy || busy || !room" title="Snel praten">🎤</button>
|
||||
<button type="button" class="btn btn-sm" @click="popOut()" title="Open op tweede scherm">↗</button>
|
||||
<button type="button" class="btn btn-sm" @click="room && openRoom(room.id)" :disabled="busy" title="Vernieuwen">↻</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wr-log" x-ref="wrLog">
|
||||
<p class="wr-empty" x-show="!messages.length && !typing">Nog geen berichten — tag agents met @marketing of deel een bestand.</p>
|
||||
<template x-for="m in messages" :key="m.id">
|
||||
<div class="wr-searchbar" x-show="searchOpen" x-cloak>
|
||||
<input type="search" class="form-input" x-ref="wrSearch" x-model="chatSearch"
|
||||
placeholder="Zoek in berichten, @agent, tekst…" />
|
||||
<button type="button" class="btn btn-sm" @click="chatSearch=''" x-show="chatSearch">Wis</button>
|
||||
<button type="button" class="btn btn-sm" @click="toggleSearch()">Sluit</button>
|
||||
</div>
|
||||
<div class="wr-log-wrap"><div class="wr-log" x-ref="wrLog" @scroll.passive="onLogScroll()">
|
||||
<p class="wr-empty" x-show="screenCleared && !typing">
|
||||
Scherm is geleegd.
|
||||
<button type="button" class="btn btn-sm" @click="restoreScreen()">Herstellen</button>
|
||||
</p>
|
||||
<p class="wr-empty" x-show="!screenCleared && !visibleMessages().length && !typing && messages.length">Geen treffers voor deze zoekopdracht.</p>
|
||||
<p class="wr-empty" x-show="!screenCleared && !messages.length && !typing">Nog geen berichten — tag agents met @marketing of deel een bestand.</p>
|
||||
<template x-for="(m, mi) in visibleMessages()" :key="'msg-'+m.id">
|
||||
<div class="wr-msg-wrap" :data-msg-id="m.id">
|
||||
<div class="wr-day-sep" x-show="showDaySep(mi)">
|
||||
<span x-text="formatMsgDate(m)"></span>
|
||||
</div>
|
||||
<div class="wr-bubble"
|
||||
:class="{'is-user': m.sender_type==='user', 'is-agent': m.sender_type==='agent', 'is-system': m.sender_type==='system'}">
|
||||
:class="{'is-user': m.sender_type==='user', 'is-agent': m.sender_type==='agent', 'is-system': m.sender_type==='system', 'is-ceo-direct': isCeoDirect(m), 'is-reply-target': replyHighlightId == m.id}">
|
||||
<div class="wr-avatar" x-show="m.sender_type!=='system'">
|
||||
<template x-if="m.sender_type==='agent'">
|
||||
<div class="agent-char-wrap"
|
||||
@@ -333,10 +381,17 @@
|
||||
</div>
|
||||
<div class="wr-bubble-body">
|
||||
<div class="wr-bubble-meta">
|
||||
<span x-text="labelForMessage(m)"></span>
|
||||
<span x-show="m.agent_key" x-text="' · @'+m.agent_key"></span>
|
||||
<button type="button" class="wr-msg-del" title="Verwijderen"
|
||||
@click.stop="deleteMessage(m)">🗑</button>
|
||||
<span class="wr-who" x-text="labelForMessage(m)"></span>
|
||||
<span class="wr-handle" x-show="m.agent_key" x-text="'@'+m.agent_key"></span>
|
||||
<time class="wr-time" x-text="formatMsgTime(m)" :title="formatMsgDate(m) + ' ' + formatMsgTime(m)"></time>
|
||||
<button type="button" class="wr-msg-reply" title="Beantwoorden"
|
||||
@click.stop="setReply(m)">↩ Reply</button>
|
||||
<button type="button" class="wr-msg-del" title="Bericht verwijderen"
|
||||
@click.stop.prevent="deleteMessage(m)">🗑</button>
|
||||
</div>
|
||||
<div class="wr-reply-quote" x-show="replyPreview(m)" x-cloak>
|
||||
<span class="wr-reply-quote-who" x-text="'↩ ' + ((replyPreview(m)||{}).agent_key ? ('@'+(replyPreview(m).agent_key)) : ((replyPreview(m)||{}).username || 'bericht'))"></span>
|
||||
<span class="wr-reply-quote-text" x-text="(replyPreview(m)||{}).excerpt"></span>
|
||||
</div>
|
||||
<div class="wr-bubble-text" x-text="m.content"></div>
|
||||
<div class="wr-attach-list" x-show="attachmentsOf(m).length">
|
||||
@@ -349,6 +404,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="wr-bubble is-agent is-typing" x-show="typing" x-cloak>
|
||||
<div class="wr-avatar">
|
||||
@@ -365,7 +421,13 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wr-composer">
|
||||
<button type="button" class="wr-jump-latest" x-show="showJumpLatest" x-cloak
|
||||
@click="jumpToLatest()" title="Naar nieuwste berichten">
|
||||
↓ Nieuwste
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="wr-composer" @click="focusComposer()">
|
||||
<div class="wr-composer-tools">
|
||||
<button type="button" class="btn btn-sm" :class="{'is-recording': voiceRecording}" @mousedown.prevent="startVoiceTalk($event)" @mouseup.prevent="stopVoiceTalk($event)" @touchstart.prevent="startVoiceTalk($event)" @touchend.prevent="stopVoiceTalk($event)" :disabled="voiceBusy || busy" title="Houd in om te praten">🎤</button>
|
||||
<button type="button" class="btn btn-sm" @click="emojiOpen=!emojiOpen" :disabled="busy">😊</button>
|
||||
@@ -388,6 +450,13 @@
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
<div class="wr-reply-bar" x-show="replyTo" x-cloak>
|
||||
<div class="wr-reply-bar-text">
|
||||
<strong x-text="'↩ Reply aan ' + (replyTo && (replyTo.agent_key ? ('@'+replyTo.agent_key) : (replyTo.label || 'bericht')))"></strong>
|
||||
<span x-text="replyTo && replyTo.excerpt"></span>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm" @click="clearReply()" title="Annuleer reply">×</button>
|
||||
</div>
|
||||
<div class="wr-composer-wrap">
|
||||
<div class="wr-mention-pop" x-show="mentionOpen && mentionSuggestions().length" x-cloak>
|
||||
<template x-for="(s, si) in mentionSuggestions()" :key="'m-'+s.agent_key">
|
||||
@@ -400,15 +469,51 @@
|
||||
</template>
|
||||
</div>
|
||||
<textarea class="form-input" rows="2" x-ref="wrInput" x-model="draft"
|
||||
@input="onDraftInput()" @keydown="onKey($event)"
|
||||
placeholder="Typ @bizdev of @finance… agent antwoordt hier in de War Room"
|
||||
:disabled="!room"></textarea>
|
||||
@input="onDraftInput()" @keydown="onKey($event)" @keydown.enter.prevent="onEnter($event)"
|
||||
placeholder="Typ hier… bv. @herman of @retail"
|
||||
></textarea>
|
||||
</div>
|
||||
<button type="button" class="btn btn-pulse-green" @click="send()" :disabled="!canSend()">Stuur</button>
|
||||
<button type="button" class="btn btn-pulse-green" @click="send()" :disabled="!canSend() || _sendLock">Stuur</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="wr-voice-overlay" :class="{ 'is-open': voiceRoomOpen }" x-show="voiceRoomOpen" x-cloak @keydown.escape.window="closeVoiceRoom()">
|
||||
|
||||
<!-- CEO inbox (@aissa) -->
|
||||
<div class="wr-ceo-overlay" x-show="ceoInboxOpen" x-cloak @keydown.escape.window="closeCeoInbox()">
|
||||
<div class="wr-ceo-panel" @click.stop>
|
||||
<div class="wr-ceo-head">
|
||||
<div>
|
||||
<h3>📬 CEO-inbox · @aissa</h3>
|
||||
<small class="muted">Direct van agents aan jou (@aissa) — ook ongelezen van toen je offline was</small>
|
||||
</div>
|
||||
<div class="wr-ceo-head-actions">
|
||||
<button type="button" class="btn btn-sm" @click="markAllCeoRead()" :disabled="!ceoUnread">Alles gelezen</button>
|
||||
<button type="button" class="btn btn-sm" @click="loadCeoInbox()">↻</button>
|
||||
<button type="button" class="btn btn-sm" @click="closeCeoInbox()">Sluit</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wr-ceo-list">
|
||||
<p class="wr-empty" x-show="!(ceoInbox||[]).length">Nog geen directe berichten. Agents gebruiken @aissa als ze jou echt nodig hebben.</p>
|
||||
<template x-for="item in ceoInbox" :key="'ceo-'+item.id">
|
||||
<article class="wr-ceo-item" :class="{ unread: !item.read_at }">
|
||||
<div class="wr-ceo-item-meta">
|
||||
<strong x-text="item.agent_display_name || ('@'+(item.agent_key||'agent'))"></strong>
|
||||
<span x-text="'@'+(item.agent_key||'')"></span>
|
||||
<time x-text="formatMsgTime({created_at: item.created_at})"></time>
|
||||
<span class="wr-ceo-unread-dot" x-show="!item.read_at">nieuw</span>
|
||||
</div>
|
||||
<div class="wr-ceo-item-body" x-text="item.content"></div>
|
||||
<div class="wr-ceo-item-actions">
|
||||
<button type="button" class="btn btn-sm" x-show="!item.read_at" @click="markCeoRead(item.id)">Markeer gelezen</button>
|
||||
</div>
|
||||
</article>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template x-if="voiceRoomOpen">
|
||||
<div class="wr-voice-overlay is-open" @keydown.escape.window="closeVoiceRoom()">
|
||||
<div class="wr-voice-panel" @click.stop>
|
||||
<div class="wr-voice-head">
|
||||
<div>
|
||||
@@ -468,6 +573,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -477,7 +583,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="agent-events-backdrop" x-show="eventsOpen" x-cloak @click="closeEvents()"></div>
|
||||
<div class="agent-events-backdrop" :class="{ 'is-open': eventsOpen }" x-show="eventsOpen" x-cloak @click="closeEvents()"></div>
|
||||
<aside class="agent-events-drawer" :class="{ open: eventsOpen }" x-cloak>
|
||||
<header class="agent-events-head">
|
||||
<div>
|
||||
@@ -516,7 +622,7 @@
|
||||
<script src="/static/js/page-viz.js?v=1"></script>
|
||||
<script src="/static/js/agents-mesh.js?v=11"></script>
|
||||
<script src="/static/js/agents-terminals.js?v=6"></script>
|
||||
<script src="/static/js/agents-warroom.js?v=18"></script>
|
||||
<script src="/static/js/agents-warroom.js?v=40"></script>
|
||||
<script>
|
||||
function agentsSoulHub() {
|
||||
return {
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
<link rel="stylesheet" href="/static/css/flk-themes.css?v=1" />
|
||||
<link rel="stylesheet" href="/static/css/pulse-theme.css?v=2" />
|
||||
<link rel="stylesheet" href="/static/css/agent-characters.css?v=4" />
|
||||
<link rel="stylesheet" href="/static/css/agents-warroom.css?v=18" />
|
||||
<script defer src="/static/js/agents-warroom.js?v=18"></script>
|
||||
<link rel="stylesheet" href="/static/css/agents-warroom.css?v=31" />
|
||||
<script defer src="/static/js/agents-warroom.js?v=31"></script>
|
||||
<script defer src="/static/js/alpine.min.js?v=2"></script>
|
||||
</head>
|
||||
<body class="wr-popup-body">
|
||||
@@ -47,7 +47,7 @@
|
||||
</div>
|
||||
<div class="wr-head-actions">
|
||||
<label class="btn btn-sm" style="display:inline-flex;align-items:center;gap:0.3rem;cursor:pointer;margin:0" title="Agents praten onderling door"><input type="checkbox" x-model="autoDebate" @change="autoDebate && scheduleContinue(1500)" style="margin:0" /> A2A</label>
|
||||
<button type="button" class="btn btn-sm btn-pulse" @click="openVoiceRoom()" :disabled="!room" title="Spraakmeeting met agents">🎙️ Voice Room</button><button type="button" class="btn btn-sm" :class="{'is-recording': voiceRecording}" @mousedown.prevent="startVoiceTalk($event)" @mouseup.prevent="stopVoiceTalk($event)" @touchstart.prevent="startVoiceTalk($event)" @touchend.prevent="stopVoiceTalk($event)" :disabled="voiceBusy || busy || !room" title="Snel praten">🎤</button>
|
||||
<button type="button" class="btn btn-sm btn-pulse" @click="openVoiceRoom()" title="Spraakmeeting met agents">🎙️ Voice Room</button><button type="button" class="btn btn-sm" :class="{'is-recording': voiceRecording}" @mousedown.prevent="startVoiceTalk($event)" @mouseup.prevent="stopVoiceTalk($event)" @touchstart.prevent="startVoiceTalk($event)" @touchend.prevent="stopVoiceTalk($event)" :disabled="voiceBusy || busy || !room" title="Snel praten">🎤</button>
|
||||
<a class="btn btn-sm" href="/agents?tab=warroom" target="_blank">In cockpit</a>
|
||||
<button type="button" class="btn btn-sm" @click="room && openRoom(room.id)" :disabled="busy">↻</button>
|
||||
</div>
|
||||
@@ -99,7 +99,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wr-composer">
|
||||
<div class="wr-composer" @click="focusComposer()">
|
||||
<div class="wr-composer-tools">
|
||||
<button type="button" class="btn btn-sm" :class="{'is-recording': voiceRecording}" @mousedown.prevent="startVoiceTalk($event)" @mouseup.prevent="stopVoiceTalk($event)" @touchstart.prevent="startVoiceTalk($event)" @touchend.prevent="stopVoiceTalk($event)" :disabled="voiceBusy || busy" title="Houd in om te praten">🎤</button>
|
||||
<button type="button" class="btn btn-sm" @click="emojiOpen=!emojiOpen" :disabled="busy">😊</button>
|
||||
@@ -134,15 +134,16 @@
|
||||
</template>
|
||||
</div>
|
||||
<textarea class="form-input" rows="2" x-ref="wrInput" x-model="draft"
|
||||
@input="onDraftInput()" @keydown="onKey($event)"
|
||||
placeholder="Typ @bizdev… antwoord komt in deze War Room"
|
||||
:disabled="!room"></textarea>
|
||||
@input="onDraftInput()" @keydown="onKey($event)" @keydown.enter.prevent="onEnter($event)"
|
||||
placeholder="Typ hier… bv. @herman"
|
||||
></textarea>
|
||||
</div>
|
||||
<button type="button" class="btn btn-pulse-green" @click="send()" :disabled="!canSend()">Stuur</button>
|
||||
<button type="button" class="btn btn-pulse-green" @click="send()" :disabled="!canSend() || _sendLock">Stuur</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="wr-voice-overlay" :class="{ 'is-open': voiceRoomOpen }" x-show="voiceRoomOpen" x-cloak @keydown.escape.window="closeVoiceRoom()">
|
||||
<template x-if="voiceRoomOpen">
|
||||
<div class="wr-voice-overlay is-open" @keydown.escape.window="closeVoiceRoom()">
|
||||
<div class="wr-voice-panel" @click.stop>
|
||||
<div class="wr-voice-head">
|
||||
<div>
|
||||
@@ -202,6 +203,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+129
-28
@@ -1,6 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="nl">
|
||||
<script>(function(){try{var t=localStorage.getItem('flk-theme');if(t)document.documentElement.setAttribute('data-theme',t);var m=document.querySelector('meta[name=theme-color]');}catch(e){}})();</script>
|
||||
<script>(function(){try{var t=localStorage.getItem('flk-theme');if(t)document.documentElement.setAttribute('data-theme',t);var s=localStorage.getItem('flk-sidebar-theme');if(s)document.documentElement.setAttribute('data-sidebar',s);var b=localStorage.getItem('flk-page-bg');if(b)document.documentElement.setAttribute('data-bg',b);var ss=localStorage.getItem('flk-sidebar-style');if(ss==='plain')document.documentElement.setAttribute('data-sidebar-style','plain');else document.documentElement.removeAttribute('data-sidebar-style');}catch(e){}})();</script>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover, maximum-scale=5" />
|
||||
@@ -22,20 +22,20 @@
|
||||
<link rel="apple-touch-icon" href="/static/icons/apple-touch-icon.png" sizes="180x180" />
|
||||
<link rel="apple-touch-icon" href="/static/icons/icon-192.png" sizes="192x192" />
|
||||
<link rel="stylesheet" href="/static/css/palantir-theme.css?v=4" />
|
||||
<link rel="stylesheet" href="/static/css/flk-themes.css?v=1" />
|
||||
<link rel="stylesheet" href="/static/css/flk-themes.css?v=8" />
|
||||
<link rel="stylesheet" href="/static/css/pulse-theme.css?v=2" />
|
||||
<link rel="stylesheet" href="/static/css/topnav-neo.css?v=6" />
|
||||
<link rel="stylesheet" href="/static/css/vertical-tabs.css?v=9" />
|
||||
<link rel="stylesheet" href="/static/css/vertical-tabs.css?v=10" />
|
||||
<link rel="stylesheet" href="/static/css/herman-dashboard.css?v=34" />
|
||||
<script defer src="/static/js/herman-assistant.js?v=17"></script>
|
||||
<script defer src="/static/js/alpine.min.js?v=2"></script>
|
||||
<script defer src="/static/js/htmx.min.js?v=2"></script>
|
||||
{% block extra_head %}{% endblock %}
|
||||
<link rel="stylesheet" href="/static/css/app-sidebar-neo.css?v=12" />
|
||||
<link rel="stylesheet" href="/static/css/app-sidebar-neo.css?v=13" />
|
||||
<link rel="stylesheet" href="/static/css/cockpit-typography.css?v=1" />
|
||||
<link rel="stylesheet" href="/static/css/herman-assistant.css?v=16" />
|
||||
<!-- mobile last: wins over sidebar/dashboard cascade -->
|
||||
<link rel="stylesheet" href="/static/css/mobile.css?v=7" />
|
||||
<link rel="stylesheet" href="/static/css/mobile.css?v=12" />
|
||||
<link rel="stylesheet" href="/static/css/user-avatar.css?v=3" />
|
||||
</head>
|
||||
<body x-data="appShell()" x-init="initApp()" :class="{ 'nav-open': navOpen, 'drawer-open': drawerOpen, 'brand-cucina': brand === 'cucina', 'brand-foodlinkk': brand === 'foodlinkk' }">
|
||||
@@ -60,36 +60,36 @@
|
||||
<div class="persona-nav">
|
||||
<div class="app-sidebar-group" x-show="brand === 'foodlinkk'">
|
||||
<div class="app-sidebar-label">Foodlinkk B2B</div>
|
||||
<a href="/export-intel" data-perm="export" class="nav-pill nav-pill-wereldexport {% if request.url.path.startswith('/export-intel') %}active{% endif %}"><span class="sidebar-nav-icon">🌍</span><span class="sidebar-nav-label">Wereldexport</span></a>
|
||||
<a href="/clients" data-perm="clients" class="nav-pill nav-pill-clients {% if request.url.path.startswith('/clients') %}active{% endif %}"><span class="sidebar-nav-icon">👥</span><span class="sidebar-nav-label" data-i18n="nav.clients">Klanten</span></a>
|
||||
<a href="/deals" data-perm="deals" class="nav-pill nav-pill-deals {% if request.url.path.startswith('/deals') %}active{% endif %}"><span class="sidebar-nav-icon">🤝</span><span class="sidebar-nav-label" data-i18n="nav.deals">Deals</span></a>
|
||||
<a href="/products" data-perm="products" class="nav-pill nav-pill-products {% if request.url.path.startswith('/products') %}active{% endif %}"><span class="sidebar-nav-icon">📦</span><span class="sidebar-nav-label" data-i18n="nav.products">Producten</span></a>
|
||||
<a href="/suppliers" data-perm="suppliers" class="nav-pill nav-pill-suppliers {% if request.url.path.startswith('/suppliers') %}active{% endif %}"><span class="sidebar-nav-icon">🏭</span><span class="sidebar-nav-label" data-i18n="nav.suppliers">Leveranciers</span></a>
|
||||
<a href="/reports" data-perm="reports" class="nav-pill nav-pill-reports {% if request.url.path.startswith('/reports') %}active{% endif %}"><span class="sidebar-nav-icon">📊</span><span class="sidebar-nav-label" data-i18n="nav.reports">Rapporten</span></a>
|
||||
<a href="/export-intel" data-perm="export" class="nav-pill nav-pill-wereldexport {% if request.url.path.startswith('/export-intel') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg></span><span class="sidebar-nav-label">Wereldexport</span></a>
|
||||
<a href="/clients" data-perm="clients" class="nav-pill nav-pill-clients {% if request.url.path.startswith('/clients') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.clients">Klanten</span></a>
|
||||
<a href="/deals" data-perm="deals" class="nav-pill nav-pill-deals {% if request.url.path.startswith('/deals') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m11 17 2 2a1 1 0 1 0 3-3"/><path d="m14 14 2.5 2.5a1 1 0 1 0 3-3l-3.88-3.88a3 3 0 0 0-4.24 0l-.88.88a1 1 0 1 1-3-3l2.81-2.81a5.79 5.79 0 0 1 7.06-.87l.47.28a2 2 0 0 0 1.42.25L21 6"/><path d="m3 13 1.68-1.68a2.41 2.41 0 0 1 3.41 0L12 16"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.deals">Deals</span></a>
|
||||
<a href="/products" data-perm="products" class="nav-pill nav-pill-products {% if request.url.path.startswith('/products') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z"/><path d="M12 22V12"/><path d="m3.3 7 7.7 4.7L18.7 7"/><path d="m7.5 4.3 9 5.2"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.products">Producten</span></a>
|
||||
<a href="/suppliers" data-perm="suppliers" class="nav-pill nav-pill-suppliers {% if request.url.path.startswith('/suppliers') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M2 20a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8l-7 5V8l-7 5V4a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"/><path d="M17 18h1"/><path d="M12 18h1"/><path d="M7 18h1"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.suppliers">Leveranciers</span></a>
|
||||
<a href="/reports" data-perm="reports" class="nav-pill nav-pill-reports {% if request.url.path.startswith('/reports') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v18h18"/><path d="M18 17V9"/><path d="M13 17V5"/><path d="M8 17v-3"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.reports">Rapporten</span></a>
|
||||
</div>
|
||||
|
||||
<div class="app-sidebar-group" x-show="brand === 'cucina'">
|
||||
<div class="app-sidebar-label">Cucina B2C</div>
|
||||
<a href="/" data-perm="dashboard" class="nav-pill nav-pill-herman {% if request.url.path == '/' %}active{% endif %}"><span class="sidebar-nav-icon">🏠</span><span class="sidebar-nav-label" data-i18n="nav.ceo_home">Overzicht</span></a>
|
||||
<a href="/revenue-cockpit" data-perm="revenue" class="nav-pill nav-pill-deals {% if request.url.path.startswith('/revenue-cockpit') %}active{% endif %}"><span class="sidebar-nav-icon">💰</span><span class="sidebar-nav-label" data-i18n="nav.revenue_cockpit">Revenue Cockpit</span></a>
|
||||
<a href="/retail" data-perm="retail" class="nav-pill nav-pill-retail {% if request.url.path.startswith('/retail') %}active{% endif %}"><span class="sidebar-nav-icon">🛒</span><span class="sidebar-nav-label" data-i18n="nav.retail">Retail NL</span></a>
|
||||
<a href="/marketing" data-perm="marketing" class="nav-pill nav-pill-marketing {% if request.url.path.startswith('/marketing') %}active{% endif %}"><span class="sidebar-nav-icon">📣</span><span class="sidebar-nav-label" data-i18n="nav.marketing">Marketing</span></a>
|
||||
<a href="/packaging" data-perm="packaging" class="nav-pill nav-pill-studio {% if request.url.path.startswith('/packaging') %}active{% endif %}"><span class="sidebar-nav-icon">📦</span><span class="sidebar-nav-label" data-i18n="nav.packaging">Packaging</span></a>
|
||||
<a href="/beurs" data-perm="beurs" class="nav-pill nav-pill-beurs {% if request.url.path.startswith('/beurs') %}active{% endif %}"><span class="sidebar-nav-icon">🎪</span><span class="sidebar-nav-label" data-i18n="nav.beurs">Beurs Live</span></a>
|
||||
<a href="/documents" data-perm="documents" class="nav-pill nav-pill-documents {% if request.url.path.startswith('/documents') %}active{% endif %}"><span class="sidebar-nav-icon">📄</span><span class="sidebar-nav-label" data-i18n="nav.documents">Documenten</span></a>
|
||||
<a href="/projects" data-perm="projects" class="nav-pill nav-pill-documents {% if request.url.path.startswith('/projects') %}active{% endif %}"><span class="sidebar-nav-icon">📁</span><span class="sidebar-nav-label" data-i18n="nav.projects">Projecten</span></a>
|
||||
<a href="/hermes" data-perm="hermes" class="nav-pill nav-pill-telegram {% if request.url.path.startswith('/hermes') %}active{% endif %}"><span class="sidebar-nav-icon">✈️</span><span class="sidebar-nav-label" data-i18n="nav.telegram">Telegram</span></a>
|
||||
<a href="/analytics" data-perm="analytics" class="nav-pill nav-pill-analytics {% if request.url.path.startswith('/analytics') %}active{% endif %}"><span class="sidebar-nav-icon">📈</span><span class="sidebar-nav-label" data-i18n="nav.analytics">Analytics</span></a>
|
||||
<a href="/" data-perm="dashboard" class="nav-pill nav-pill-herman {% if request.url.path == '/' %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.ceo_home">Overzicht</span></a>
|
||||
<a href="/revenue-cockpit" data-perm="revenue" class="nav-pill nav-pill-deals {% if request.url.path.startswith('/revenue-cockpit') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="8" r="6"/><path d="M18.09 10.37A6 6 0 1 1 10.34 18"/><path d="M7 6h1v4"/><path d="m16.71 13.88.7.71-2.82 2.82"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.revenue_cockpit">Revenue Cockpit</span></a>
|
||||
<a href="/retail" data-perm="retail" class="nav-pill nav-pill-retail {% if request.url.path.startswith('/retail') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.retail">Retail NL</span></a>
|
||||
<a href="/marketing" data-perm="marketing" class="nav-pill nav-pill-marketing {% if request.url.path.startswith('/marketing') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m3 11 18-5v12L3 13v-2z"/><path d="M11.6 16.8a3 3 0 1 1-5.8-1.6"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.marketing">Marketing</span></a>
|
||||
<a href="/packaging" data-perm="packaging" class="nav-pill nav-pill-studio {% if request.url.path.startswith('/packaging') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z"/><path d="m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65"/><path d="m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.packaging">Packaging</span></a>
|
||||
<a href="/beurs" data-perm="beurs" class="nav-pill nav-pill-beurs {% if request.url.path.startswith('/beurs') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 21 14 3"/><path d="M20.5 21 10 3"/><path d="M15.5 21 12 15l-3.5 6"/><path d="M2 21h20"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.beurs">Beurs Live</span></a>
|
||||
<a href="/documents" data-perm="documents" class="nav-pill nav-pill-documents {% if request.url.path.startswith('/documents') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.documents">Documenten</span></a>
|
||||
<a href="/projects" data-perm="projects" class="nav-pill nav-pill-documents {% if request.url.path.startswith('/projects') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.projects">Projecten</span></a>
|
||||
<a href="/hermes" data-perm="hermes" class="nav-pill nav-pill-telegram {% if request.url.path.startswith('/hermes') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m22 2-7 20-4-9-9-4Z"/><path d="M22 2 11 13"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.telegram">Telegram</span></a>
|
||||
<a href="/analytics" data-perm="analytics" class="nav-pill nav-pill-analytics {% if request.url.path.startswith('/analytics') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 7 13.5 15.5 8.5 10.5 2 17"/><polyline points="16 7 22 7 22 13"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.analytics">Analytics</span></a>
|
||||
</div>
|
||||
|
||||
<div class="app-sidebar-group">
|
||||
<div class="app-sidebar-label" data-i18n="nav.platform">Platform</div>
|
||||
<a href="/ops" data-perm="ops" class="nav-pill nav-pill-ops {% if request.url.path.startswith('/ops') %}active{% endif %}"><span class="sidebar-nav-icon">⚙️</span><span class="sidebar-nav-label" data-i18n="nav.ops">IT Ops</span></a>
|
||||
<a href="/agents" data-perm="agents" class="nav-pill nav-pill-agents {% if request.url.path.startswith('/agents') %}active{% endif %}"><span class="sidebar-nav-icon">🤖</span><span class="sidebar-nav-label" data-i18n="nav.agents">Agents</span></a>
|
||||
<a href="/browser" data-perm="browser" class="nav-pill nav-pill-browser {% if request.url.path.startswith('/browser') or request.url.path.startswith('/monitor') %}active{% endif %}"><span class="sidebar-nav-icon">🌐</span><span class="sidebar-nav-label" data-i18n="nav.browser">Browser</span></a>
|
||||
<a href="/studio" data-perm="studio" class="nav-pill nav-pill-studio {% if request.url.path.startswith('/studio') %}active{% endif %}"><span class="sidebar-nav-icon">🎨</span><span class="sidebar-nav-label" data-i18n="nav.studio">Studio</span></a>
|
||||
<a href="/voice" data-perm="voice" class="nav-pill nav-pill-voice {% if request.url.path.startswith('/voice') %}active{% endif %}"><span class="sidebar-nav-icon">🎙️</span><span class="sidebar-nav-label" data-i18n="nav.voice">Voice</span></a>
|
||||
<a href="/settings" data-perm="settings" class="nav-pill nav-pill-settings {% if request.url.path.startswith('/settings') %}active{% endif %}"><span class="sidebar-nav-icon">🔧</span><span class="sidebar-nav-label" data-i18n="nav.settings">Instellingen</span></a>
|
||||
<a href="/ops" data-perm="ops" class="nav-pill nav-pill-ops {% if request.url.path.startswith('/ops') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect width="16" height="16" x="4" y="4" rx="2"/><rect width="6" height="6" x="9" y="9" rx="1"/><path d="M15 2v2"/><path d="M15 20v2"/><path d="M2 15h2"/><path d="M2 9h2"/><path d="M20 15h2"/><path d="M20 9h2"/><path d="M9 2v2"/><path d="M9 20v2"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.ops">IT Ops</span></a>
|
||||
<a href="/agents?tab=warroom" data-perm="agents" class="nav-pill nav-pill-agents {% if request.url.path.startswith('/agents') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M12 8V4H8"/><rect width="16" height="12" x="4" y="8" rx="2"/><path d="M2 14h2"/><path d="M20 14h2"/><path d="M15 13v2"/><path d="M9 13v2"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.agents">Agents</span></a>
|
||||
<a href="/browser" data-perm="browser" class="nav-pill nav-pill-browser {% if request.url.path.startswith('/browser') or request.url.path.startswith('/monitor') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.browser">Browser</span></a>
|
||||
<a href="/studio" data-perm="studio" class="nav-pill nav-pill-studio {% if request.url.path.startswith('/studio') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><circle cx="13.5" cy="6.5" r=".5" fill="currentColor"/><circle cx="17.5" cy="10.5" r=".5" fill="currentColor"/><circle cx="8.5" cy="7.5" r=".5" fill="currentColor"/><circle cx="6.5" cy="12.5" r=".5" fill="currentColor"/><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.studio">Studio</span></a>
|
||||
<a href="/voice" data-perm="voice" class="nav-pill nav-pill-voice {% if request.url.path.startswith('/voice') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" x2="12" y1="19" y2="22"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.voice">Voice</span></a>
|
||||
<a href="/settings" data-perm="settings" class="nav-pill nav-pill-settings {% if request.url.path.startswith('/settings') %}active{% endif %}"><span class="sidebar-nav-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><line x1="4" x2="4" y1="21" y2="14"/><line x1="4" x2="4" y1="10" y2="3"/><line x1="12" x2="12" y1="21" y2="12"/><line x1="12" x2="12" y1="8" y2="3"/><line x1="20" x2="20" y1="21" y2="16"/><line x1="20" x2="20" y1="12" y2="3"/><line x1="2" x2="6" y1="14" y2="14"/><line x1="10" x2="14" y1="8" y2="8"/><line x1="18" x2="22" y1="16" y2="16"/></svg></span><span class="sidebar-nav-label" data-i18n="nav.settings">Instellingen</span></a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
@@ -536,23 +536,124 @@ window.FlkThemes = {
|
||||
{ id: 'aurora', name: 'Aurora', desc: 'Blauw-violet met cyaan highlights' },
|
||||
{ id: 'neon', name: 'Neon Tide', desc: 'Donker neon cyaan + magenta' },
|
||||
{ id: 'glacier', name: 'Glacier', desc: 'IJsblauw en helder sky-cyan' },
|
||||
{ id: 'cobalt', name: 'Cobalt Pulse', desc: 'Kobaltblauw met aqua en amber' }
|
||||
{ id: 'cobalt', name: 'Cobalt Pulse', desc: 'Kobaltblauw met aqua en amber' },
|
||||
{ id: 'reef', name: 'Reef', desc: 'Teal-diep met helder mint' },
|
||||
{ id: 'plasma', name: 'Plasma', desc: 'Paars-nacht met cyaan vonken' },
|
||||
{ id: 'lagoon', name: 'Lagoon', desc: 'Tropisch blauwgroen water' },
|
||||
{ id: 'indigo', name: 'Indigo Night', desc: 'Indigo met lavendel accents' },
|
||||
{ id: 'skyline', name: 'Skyline', desc: 'Stad-nacht blauw + sky' },
|
||||
{ id: 'mintvolt', name: 'Mint Volt', desc: 'Donker groen met mint-energie' },
|
||||
{ id: 'sapphire', name: 'Sapphire', desc: 'Klassiek saffierblauw' },
|
||||
{ id: 'arctic', name: 'Arctic Glow', desc: 'Koud grijsblauw met ice-cyan' },
|
||||
{ id: 'hyperion', name: 'Hyperion', desc: 'Cyaan met lime-flits' },
|
||||
{ id: 'meridian', name: 'Meridian', desc: 'Violet-meridiaan met aqua' }
|
||||
],
|
||||
sidebars: [
|
||||
{ id: 'aqua', name: 'Deep Aqua', desc: 'Diep aqua, strak en koel' },
|
||||
{ id: 'azure', name: 'Royal Azure', desc: 'Diep koningsblauw' },
|
||||
{ id: 'turquoise', name: 'Abyss Teal', desc: 'Diep teal, premium' },
|
||||
{ id: 'cerulean', name: 'Ocean Depth', desc: 'Diep oceaanblauw' },
|
||||
{ id: 'electric', name: 'Electric Cyan', desc: 'Donker elektrisch cyaan' },
|
||||
{ id: 'violet', name: 'Indigo Night', desc: 'Diep indigo-violet (geen roze)' },
|
||||
{ id: 'emerald', name: 'Jade Depth', desc: 'Diep jade smaragd' },
|
||||
{ id: 'midnight', name: 'Midnight Navy', desc: 'Diep marinezwart-blauw' },
|
||||
{ id: 'steel', name: 'Steel Blue', desc: 'Strak staalblauw' },
|
||||
{ id: 'nordic', name: 'Nordic Frost', desc: 'Koel nordic blauw' }
|
||||
],
|
||||
backgrounds: [
|
||||
{ id: 'navy', name: 'Deep Navy', desc: 'Diep marineblauw' },
|
||||
{ id: 'royal', name: 'Royal Blue', desc: 'Koningsblauw' },
|
||||
{ id: 'azure', name: 'Azure Sea', desc: 'Helder azuur' },
|
||||
{ id: 'sky', name: 'Sky Blue', desc: 'Heldere luchtblauw' },
|
||||
{ id: 'cerulean', name: 'Cerulean', desc: 'Ceruleum' },
|
||||
{ id: 'teal', name: 'Deep Teal', desc: 'Diep teal' },
|
||||
{ id: 'lagoon', name: 'Lagoon Blue', desc: 'Lagune blauwgroen' },
|
||||
{ id: 'cyan', name: 'Cyan Depth', desc: 'Cyaan diepte' },
|
||||
{ id: 'indigo', name: 'Indigo Field', desc: 'Indigo veld' },
|
||||
{ id: 'violet', name: 'Violet Dusk', desc: 'Violet schemer' },
|
||||
{ id: 'sapphire', name: 'Sapphire', desc: 'Saffierblauw' },
|
||||
{ id: 'midnight', name: 'Midnight', desc: 'Nachtblauw (niet zwart)' },
|
||||
{ id: 'emerald', name: 'Emerald Sea', desc: 'Smaragd zee' },
|
||||
{ id: 'slate', name: 'Slate Blue', desc: 'Leisteenblauw' },
|
||||
{ id: 'graphite', name: 'Graphite Blue', desc: 'Grafietblauw' }
|
||||
],
|
||||
current: function () {
|
||||
try { return localStorage.getItem('flk-theme') || 'ocean'; } catch (e) { return 'ocean'; }
|
||||
},
|
||||
currentSidebar: function () {
|
||||
try { return localStorage.getItem('flk-sidebar-theme') || ''; } catch (e) { return ''; }
|
||||
},
|
||||
apply: function (id) {
|
||||
var ok = this.list.some(function (t) { return t.id === id; });
|
||||
if (!ok) id = 'ocean';
|
||||
document.documentElement.setAttribute('data-theme', id);
|
||||
try { localStorage.setItem('flk-theme', id); } catch (e) {}
|
||||
return id;
|
||||
},
|
||||
applySidebar: function (id) {
|
||||
if (!id) {
|
||||
document.documentElement.removeAttribute('data-sidebar');
|
||||
try { localStorage.removeItem('flk-sidebar-theme'); } catch (e) {}
|
||||
return '';
|
||||
}
|
||||
var migrate = { coral: 'midnight', fuchsia: 'nordic', lime: 'steel' };
|
||||
if (migrate[id]) id = migrate[id];
|
||||
var ok = this.sidebars.some(function (t) { return t.id === id; });
|
||||
if (!ok) {
|
||||
document.documentElement.removeAttribute('data-sidebar');
|
||||
try { localStorage.removeItem('flk-sidebar-theme'); } catch (e) {}
|
||||
return '';
|
||||
}
|
||||
document.documentElement.setAttribute('data-sidebar', id);
|
||||
try { localStorage.setItem('flk-sidebar-theme', id); } catch (e) {}
|
||||
return id;
|
||||
},
|
||||
|
||||
currentSidebarStyle: function () {
|
||||
try { return localStorage.getItem('flk-sidebar-style') || 'gradient'; } catch (e) { return 'gradient'; }
|
||||
},
|
||||
applySidebarStyle: function (mode) {
|
||||
if (mode !== 'plain') mode = 'gradient';
|
||||
if (mode === 'plain') {
|
||||
document.documentElement.setAttribute('data-sidebar-style', 'plain');
|
||||
} else {
|
||||
document.documentElement.removeAttribute('data-sidebar-style');
|
||||
}
|
||||
try { localStorage.setItem('flk-sidebar-style', mode); } catch (e) {}
|
||||
return mode;
|
||||
},
|
||||
currentBg: function () {
|
||||
try { return localStorage.getItem('flk-page-bg') || ''; } catch (e) { return ''; }
|
||||
},
|
||||
applyBg: function (id) {
|
||||
if (!id) {
|
||||
document.documentElement.removeAttribute('data-bg');
|
||||
try { localStorage.removeItem('flk-page-bg'); } catch (e) {}
|
||||
return '';
|
||||
}
|
||||
var ok = (this.backgrounds || []).some(function (t) { return t.id === id; });
|
||||
if (!ok) {
|
||||
document.documentElement.removeAttribute('data-bg');
|
||||
try { localStorage.removeItem('flk-page-bg'); } catch (e) {}
|
||||
return '';
|
||||
}
|
||||
document.documentElement.setAttribute('data-bg', id);
|
||||
try { localStorage.setItem('flk-page-bg', id); } catch (e) {}
|
||||
return id;
|
||||
}
|
||||
};
|
||||
if (!document.documentElement.getAttribute('data-theme')) {
|
||||
window.FlkThemes.apply(window.FlkThemes.current());
|
||||
}
|
||||
(function () {
|
||||
var s = window.FlkThemes.currentSidebar();
|
||||
if (s) window.FlkThemes.applySidebar(s);
|
||||
if (window.FlkThemes.applySidebarStyle) window.FlkThemes.applySidebarStyle(window.FlkThemes.currentSidebarStyle());
|
||||
var b = window.FlkThemes.currentBg();
|
||||
if (b) window.FlkThemes.applyBg(b);
|
||||
})();
|
||||
</script>
|
||||
|
||||
{% block scripts %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -4,24 +4,28 @@
|
||||
<link rel="stylesheet" href="/static/vendor/leaflet/leaflet.css?v=1" />
|
||||
<link rel="stylesheet" href="/static/vendor/leaflet.markercluster/MarkerCluster.css?v=1" />
|
||||
<link rel="stylesheet" href="/static/vendor/leaflet.markercluster/MarkerCluster.Default.css?v=1" />
|
||||
<link rel="stylesheet" href="/static/css/export-intel.css?v=32" />
|
||||
<link rel="stylesheet" href="/static/css/export-intel-tabs.css?v=20" />
|
||||
<link rel="stylesheet" href="/static/css/export-intel.css?v=23" />
|
||||
<link rel="stylesheet" href="/static/css/export-intel-tabs.css?v=21" />
|
||||
<script src="/static/vendor/leaflet/leaflet.js?v=1"></script>
|
||||
<script src="/static/vendor/leaflet.markercluster/leaflet.markercluster.js?v=1"></script>
|
||||
<script src="/static/js/export-intel-map.js?v=21"></script>
|
||||
<script src="/static/js/export-intel.js?v=32"></script>
|
||||
<script src="/static/js/export-intel.js?v=48"></script>
|
||||
<script src="/static/js/export-intel-profile.js?v=7"></script>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="ei-page" x-data="exportIntelApp()" x-init="init()">
|
||||
<div class="ei-progress-overlay" x-show="isWorking()" x-cloak>
|
||||
<div class="ei-progress-overlay" x-show="isWorking()" x-cloak>
|
||||
<div class="ei-progress-card">
|
||||
<div class="ei-progress-spinner"></div>
|
||||
<p x-text="progressLabel()"></p>
|
||||
<div class="ei-progress-bar"><div class="ei-progress-bar-fill" :style="'width:' + (syncMonitorPercent() || 100) + '%'"></div></div>
|
||||
<div class="ei-progress-bar"><div class="ei-progress-bar-fill" :style="'width:' + (syncMonitorPercent() || 8) + '%'"></div></div>
|
||||
<div class="ei-progress-actions">
|
||||
<button type="button" class="btn btn-sm ei-btn-cancel" @click="cancelSync()" x-show="busy || (syncMonitor && syncMonitor.any_running)">⏹ Annuleer sync</button>
|
||||
<button type="button" class="btn btn-sm" @click="dismissOverlay()" title="Overlay sluiten — sync loopt door in monitor">Verberg</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<header class="ei-header page-header">
|
||||
<header class="ei-header page-header">
|
||||
<div>
|
||||
<h1>Wereldexport <span class="live-badge">Live</span></h1>
|
||||
<p class="ei-subtitle">Foodlinkk B2B · wereldwijde markten · halal vlees · cateraars · distributeurs</p>
|
||||
@@ -49,6 +53,7 @@
|
||||
<div class="ei-sync-monitor-head">
|
||||
<strong>Sync voortgang</strong>
|
||||
<span x-show="syncMonitor && syncMonitor.any_running" class="ei-sync-live">● Live</span>
|
||||
<button type="button" class="btn btn-sm ei-btn-cancel" style="margin-left:auto" @click="cancelSync()" x-show="syncMonitor && syncMonitor.any_running">⏹ Annuleer</button>
|
||||
</div>
|
||||
<template x-if="syncMonitor && syncMonitor.active_jobs && syncMonitor.active_jobs.length">
|
||||
<div class="ei-sync-jobs">
|
||||
|
||||
@@ -289,7 +289,7 @@
|
||||
<div class="settings-panel-head">
|
||||
<div>
|
||||
<h2>UI Themes</h2>
|
||||
<p class="page-tip">Kies een kleurrijk cyaan/blauw thema voor de hele cockpit. Direct toegepast op alle pagina's.</p>
|
||||
<p class="page-tip">UI-theme, pagina-achtergrond en sidebar-kleur zijn los van elkaar te kiezen.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flk-theme-grid">
|
||||
@@ -301,6 +301,48 @@
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="flk-theme-section">
|
||||
<h3>Pagina achtergrond</h3>
|
||||
<p class="page-tip">15 echte kleuren voor alle subpagina’s (niet zwart). Los van UI-theme en sidebar.</p>
|
||||
<div class="flk-theme-grid">
|
||||
<button type="button" class="flk-theme-card" :class="{ 'is-active': !bg }" @click="selectBg('')">
|
||||
<div class="flk-theme-swatch" style="background:linear-gradient(135deg,#07131f,#123049)"></div>
|
||||
<strong>Standaard</strong>
|
||||
<small>Volgt UI-theme achtergrond</small>
|
||||
</button>
|
||||
<template x-for="b in backgrounds" :key="'bg-'+b.id">
|
||||
<button type="button" class="flk-theme-card" :class="{ 'is-active': bg === b.id }" @click="selectBg(b.id)">
|
||||
<div class="flk-theme-swatch" :style="bgSwatch(b.id)"></div>
|
||||
<strong x-text="b.name"></strong>
|
||||
<small x-text="b.desc"></small>
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flk-theme-section">
|
||||
<h3>Sidebar Themes</h3>
|
||||
<p class="page-tip">Los van het UI-theme — 10 diepe, strakke kleuren (geen rood/roze). Kies gradient of effen.</p>
|
||||
<div class="flk-style-toggle" role="group" aria-label="Sidebar stijl">
|
||||
<button type="button" :class="{ 'is-active': sidebarStyle === 'gradient' }" @click="selectSidebarStyle('gradient')">Gradient</button>
|
||||
<button type="button" :class="{ 'is-active': sidebarStyle === 'plain' }" @click="selectSidebarStyle('plain')">Effen kleur</button>
|
||||
</div>
|
||||
<div class="flk-theme-grid">
|
||||
<button type="button" class="flk-theme-card" :class="{ 'is-active': !sidebar }" @click="selectSidebar('')">
|
||||
<div class="flk-theme-swatch" style="background:linear-gradient(180deg,#080c12,#121820)"></div>
|
||||
<strong>Standaard</strong>
|
||||
<small>Geen aparte sidebar-kleur (volgt UI)</small>
|
||||
</button>
|
||||
<template x-for="s in sidebars" :key="'sb-'+s.id">
|
||||
<button type="button" class="flk-theme-card" :class="{ 'is-active': sidebar === s.id }" @click="selectSidebar(s.id)">
|
||||
<div class="flk-theme-swatch" :data-sb="s.id" :data-sb-style="sidebarStyle" :style="sidebarSwatch(s.id)"></div>
|
||||
<strong x-text="s.name"></strong>
|
||||
<small x-text="s.desc"></small>
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% elif active_tab == 'general' %}
|
||||
@@ -318,14 +360,42 @@
|
||||
function flkThemesPage() {
|
||||
return {
|
||||
themes: (window.FlkThemes && window.FlkThemes.list) || [],
|
||||
sidebars: (window.FlkThemes && window.FlkThemes.sidebars) || [],
|
||||
backgrounds: (window.FlkThemes && window.FlkThemes.backgrounds) || [],
|
||||
current: 'ocean',
|
||||
sidebar: '',
|
||||
sidebarStyle: 'gradient',
|
||||
bg: '',
|
||||
init() {
|
||||
this.themes = (window.FlkThemes && window.FlkThemes.list) || [];
|
||||
this.sidebars = (window.FlkThemes && window.FlkThemes.sidebars) || [];
|
||||
this.backgrounds = (window.FlkThemes && window.FlkThemes.backgrounds) || [];
|
||||
this.current = (window.FlkThemes && window.FlkThemes.current()) || 'ocean';
|
||||
if (window.FlkThemes) window.FlkThemes.apply(this.current);
|
||||
this.sidebar = (window.FlkThemes && window.FlkThemes.currentSidebar()) || '';
|
||||
this.sidebarStyle = (window.FlkThemes && window.FlkThemes.currentSidebarStyle && window.FlkThemes.currentSidebarStyle()) || 'gradient';
|
||||
this.bg = (window.FlkThemes && window.FlkThemes.currentBg && window.FlkThemes.currentBg()) || '';
|
||||
if (window.FlkThemes) {
|
||||
window.FlkThemes.apply(this.current);
|
||||
window.FlkThemes.applySidebar(this.sidebar);
|
||||
if (window.FlkThemes.applySidebarStyle) window.FlkThemes.applySidebarStyle(this.sidebarStyle);
|
||||
if (window.FlkThemes.applyBg) window.FlkThemes.applyBg(this.bg);
|
||||
}
|
||||
},
|
||||
select(id) {
|
||||
this.current = window.FlkThemes.apply(id);
|
||||
if (window.Cockpit) Cockpit.toast('Theme: ' + id, 'ok');
|
||||
if (window.Cockpit) Cockpit.toast('UI theme: ' + id, 'ok');
|
||||
},
|
||||
selectSidebar(id) {
|
||||
this.sidebar = window.FlkThemes.applySidebar(id || '');
|
||||
if (window.Cockpit) Cockpit.toast(id ? ('Sidebar: ' + id) : 'Sidebar: standaard', 'ok');
|
||||
},
|
||||
selectSidebarStyle(mode) {
|
||||
this.sidebarStyle = window.FlkThemes.applySidebarStyle(mode || 'gradient');
|
||||
if (window.Cockpit) Cockpit.toast(mode === 'plain' ? 'Sidebar: effen kleur' : 'Sidebar: gradient', 'ok');
|
||||
},
|
||||
selectBg(id) {
|
||||
this.bg = window.FlkThemes.applyBg(id || '');
|
||||
if (window.Cockpit) Cockpit.toast(id ? ('Achtergrond: ' + id) : 'Achtergrond: standaard', 'ok');
|
||||
},
|
||||
swatch(id) {
|
||||
var map = {
|
||||
@@ -333,9 +403,70 @@ function flkThemesPage() {
|
||||
aurora: 'linear-gradient(135deg,#0a1020,#1a2550 45%,#a78bfa 75%,#22d3ee)',
|
||||
neon: 'linear-gradient(135deg,#050b14,#10243f 40%,#06b6d4 70%,#e879f9)',
|
||||
glacier: 'linear-gradient(135deg,#0b1522,#1a2f4a 45%,#38bdf8 80%,#7dd3fc)',
|
||||
cobalt: 'linear-gradient(135deg,#08101c,#172642 40%,#3b82f6 70%,#22d3ee)'
|
||||
cobalt: 'linear-gradient(135deg,#08101c,#172642 40%,#3b82f6 70%,#22d3ee)',
|
||||
reef: 'linear-gradient(135deg,#04161a,#11353f 40%,#2dd4bf)',
|
||||
plasma: 'linear-gradient(135deg,#0c0618,#26114a 40%,#c084fc 75%,#22d3ee)',
|
||||
lagoon: 'linear-gradient(135deg,#031a1f,#0c3a45 40%,#22d3ee)',
|
||||
indigo: 'linear-gradient(135deg,#07091a,#1a2250 40%,#818cf8 75%,#22d3ee)',
|
||||
skyline: 'linear-gradient(135deg,#06101c,#142d4d 40%,#38bdf8)',
|
||||
mintvolt: 'linear-gradient(135deg,#04140f,#10352a 40%,#34d399 70%,#22d3ee)',
|
||||
sapphire: 'linear-gradient(135deg,#050d1f,#122650 40%,#3b82f6 70%,#38bdf8)',
|
||||
arctic: 'linear-gradient(135deg,#0a121c,#1c2a3d 45%,#67e8f9)',
|
||||
hyperion: 'linear-gradient(135deg,#041018,#0e2d42 40%,#22d3ee 70%,#a3e635)',
|
||||
meridian: 'linear-gradient(135deg,#0a0716,#221645 40%,#c084fc 70%,#22d3ee)'
|
||||
};
|
||||
return 'background:' + (map[id] || map.ocean);
|
||||
return 'background: ' + (map[id] || map.ocean) + ' !important;';
|
||||
},
|
||||
sidebarSwatch(id) {
|
||||
var style = this.sidebarStyle || 'gradient';
|
||||
var solids = {
|
||||
aqua: '#0a4f5c',
|
||||
azure: '#163a7a',
|
||||
turquoise: '#0a453f',
|
||||
cerulean: '#0c4a6e',
|
||||
electric: '#0a3d4a',
|
||||
violet: '#2a1f6b',
|
||||
emerald: '#0a4a38',
|
||||
midnight: '#0d1f3c',
|
||||
steel: '#1a2d42',
|
||||
nordic: '#0e3a4f',
|
||||
};
|
||||
var grads = {
|
||||
aqua: 'linear-gradient(180deg, #062a32 0%, #0a4f5c 55%, #0d6b7a 100%)',
|
||||
azure: 'linear-gradient(180deg, #0a1f45 0%, #163a7a 55%, #1e4f9e 100%)',
|
||||
turquoise: 'linear-gradient(180deg, #052925 0%, #0a453f 55%, #0f5f56 100%)',
|
||||
cerulean: 'linear-gradient(180deg, #06263a 0%, #0c4a6e 55%, #126087 100%)',
|
||||
electric: 'linear-gradient(180deg, #041820 0%, #0a3d4a 50%, #0e5a6b 100%)',
|
||||
violet: 'linear-gradient(180deg, #150e3a 0%, #2a1f6b 55%, #3b2f8a 100%)',
|
||||
emerald: 'linear-gradient(180deg, #05291e 0%, #0a4a38 55%, #0f6349 100%)',
|
||||
midnight: 'linear-gradient(180deg, #060e1c 0%, #0d1f3c 55%, #153056 100%)',
|
||||
steel: 'linear-gradient(180deg, #0d1622 0%, #1a2d42 55%, #243b55 100%)',
|
||||
nordic: 'linear-gradient(180deg, #071f2c 0%, #0e3a4f 55%, #15506a 100%)',
|
||||
};
|
||||
var bg = (style === 'plain')
|
||||
? (solids[id] || solids.electric)
|
||||
: (grads[id] || grads.electric);
|
||||
return 'background: ' + bg + ' !important;';
|
||||
},
|
||||
bgSwatch(id) {
|
||||
var map = {
|
||||
navy: 'linear-gradient(135deg,#0d2b5c,#134078)',
|
||||
royal: 'linear-gradient(135deg,#1a3a8f,#274bb8)',
|
||||
azure: 'linear-gradient(135deg,#0a4f8a,#0d6cb8)',
|
||||
sky: 'linear-gradient(135deg,#0e5f9e,#1880c9)',
|
||||
cerulean: 'linear-gradient(135deg,#0c6a9e,#1490c8)',
|
||||
teal: 'linear-gradient(135deg,#0c5c68,#128090)',
|
||||
lagoon: 'linear-gradient(135deg,#0a6b7a,#0f8fa3)',
|
||||
cyan: 'linear-gradient(135deg,#0a5568,#0e7a94)',
|
||||
indigo: 'linear-gradient(135deg,#2f2a7a,#4338ca)',
|
||||
violet: 'linear-gradient(135deg,#4a1d7a,#6d28d9)',
|
||||
sapphire: 'linear-gradient(135deg,#123a8c,#1d4ed8)',
|
||||
midnight: 'linear-gradient(135deg,#1a2f55,#274878)',
|
||||
emerald: 'linear-gradient(135deg,#0d5c45,#059669)',
|
||||
slate: 'linear-gradient(135deg,#243447,#334155)',
|
||||
graphite: 'linear-gradient(135deg,#1e2a3a,#2c3b52)'
|
||||
};
|
||||
return 'background: ' + (map[id] || map.navy) + ' !important;';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user