Files
hermes-hub/app/templates/index.html
T

238 lines
11 KiB
HTML

{% extends "base.html" %}
{% block content %}
<div class="hub-shell">
<!-- Sidebar / Workspace Switcher -->
<aside id="hub-sidebar" class="hub-sidebar">
<div class="hub-brand">
<div class="hub-brand-left">
<div class="hub-logo-icon">H</div>
<div class="hub-brand-text">Hermes Hub</div>
<div class="hub-brand-badge">v2.0</div>
</div>
<button id="btn-toggle-sidebar" class="hub-collapse-btn" type="button" aria-label="Replier la barre latérale" title="Replier la barre latérale">
<svg class="hub-collapse-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="15 18 9 12 15 6"></polyline>
</svg>
</button>
</div>
<div class="hub-nav-section">Univers Hermes</div>
<ul class="hub-universes-list">
{% for u_id, u in universes.items() %}
<li>
<button
class="hub-universe-btn {% if loop.first %}active{% endif %}"
data-universe="{{ u.id }}"
data-name="{{ u.name }}"
data-scope="{{ u.scope }}"
data-tagline="{{ u.tagline }}"
data-supports-files="{{ 'true' if u.supports_files else 'false' }}"
data-is-external="{{ 'true' if u.is_external_app else 'false' }}"
title="{{ u.name }} — {{ u.tagline }}"
style="--item-accent: var({{ u.accent_token }});"
>
<div class="hub-universe-avatar">
{{ u.name[:2].upper() }}
</div>
<div class="hub-universe-info">
<div class="hub-universe-name">{{ u.name }}</div>
<div class="hub-universe-tagline">{{ u.tagline }}</div>
</div>
<div id="status-dot-{{ u.id }}" class="hub-status-dot" title="Vérification du statut..."></div>
</button>
</li>
{% endfor %}
</ul>
<!-- Sidebar Tools Footer -->
<div class="hub-sidebar-footer">
<button id="btn-edit-persona" class="hub-tool-btn" type="button" title="Personnalité & Ton">
<span>⚙️</span>
<span>Personnalité & Ton</span>
</button>
<button id="btn-clone-universe" class="hub-tool-btn" type="button" title="Cloner ce profil">
<span>🧬</span>
<span>Cloner ce profil</span>
</button>
</div>
</aside>
<!-- Main View Area -->
<main class="hub-main">
<!-- Universe Topbar -->
<header class="hub-topbar">
<div class="hub-topbar-left">
<h1 id="active-universe-name" class="hub-active-title">Tunisie Telecom</h1>
<span id="active-universe-scope" class="hub-scope-pill">Scope: tt</span>
<span id="active-universe-tagline" style="font-size: 0.8rem; color: var(--hub-text-muted);">Achats Zone Sud</span>
</div>
<div class="hub-topbar-right">
<!-- Sélecteur Toggle Mode DSH (Univers Nabil) -->
<div id="nabil-mode-toggle" role="tablist" aria-label="Mode du canvas" class="hub-mode-toggle" style="display: none;">
<button id="tab-session" role="tab" aria-selected="true" class="hub-mode-tab active" type="button">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>
<span>Chat Natif</span>
</button>
<div class="hub-mode-divider"></div>
<button id="tab-files" role="tab" aria-selected="false" class="hub-mode-tab" type="button">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M4 20h14a2 2 0 0 0 2-2V9H12L10 6H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1z"></path></svg>
<span>Fichiers DSH</span>
</button>
</div>
<span id="hub-security-badge" style="font-size: 0.75rem; color: var(--hub-text-muted);">Session Cloudflare Access Active</span>
</div>
</header>
<!-- Canvas Container -->
<div class="hub-canvas">
<!-- 1. Native Chat Two-Column Interface -->
<div id="hub-native-chat" class="hub-native-chat-layout">
<!-- Sub-sidebar Conversations -->
<div class="hub-conv-sidebar">
<div class="hub-conv-header">
<button id="btn-new-chat" class="hub-btn-new-chat" type="button">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
<span>Nouvelle discussion</span>
</button>
</div>
<div class="hub-conv-search-wrap">
<input id="hub-conv-search" class="hub-conv-search-input" type="text" placeholder="Filtrer les discussions..." />
</div>
<div id="hub-conv-list" class="hub-conv-list">
<!-- Dynamically populated via JS -->
<div class="hub-conv-loading">Chargement des conversations...</div>
</div>
</div>
<!-- Right Main Chat Pane -->
<div class="hub-chat-pane">
<!-- Active Conversation Header -->
<div class="hub-chat-header">
<div class="hub-chat-header-info">
<span id="current-chat-title" class="hub-chat-header-title">Nouvelle conversation</span>
<span id="current-chat-status" class="hub-chat-header-status">Prêt</span>
</div>
<div class="hub-chat-header-actions">
<button id="btn-pin-active" class="hub-btn-icon" title="Épingler cette discussion">📌</button>
<button id="btn-rename-active" class="hub-btn-icon" title="Renommer">✏️</button>
<button id="btn-delete-active" class="hub-btn-icon hub-btn-danger" title="Supprimer la discussion">🗑️</button>
</div>
</div>
<!-- Messages Scroll View -->
<div id="hub-messages-container" class="hub-messages-container">
<div class="hub-empty-state">
<div class="hub-empty-icon">💬</div>
<h3>Discussion avec <span id="empty-state-name">Hermes</span></h3>
<p>Posez une question ou donnez une instruction pour démarrer la session.</p>
</div>
</div>
<!-- Chat Input Footer -->
<div class="hub-chat-input-wrapper">
<form id="hub-chat-form" class="hub-chat-form">
<textarea
id="hub-chat-input"
class="hub-chat-textarea"
placeholder="Envoyer un message à Hermes... (Entrée pour envoyer, Maj+Entrée pour saut de ligne)"
rows="1"
></textarea>
<button id="btn-send-msg" class="hub-btn-send" type="submit" aria-label="Envoyer">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg>
</button>
<button id="btn-stop-msg" class="hub-btn-stop" type="button" style="display: none;" aria-label="Arrêter la réponse">
<div class="hub-stop-square"></div>
</button>
</form>
<div class="hub-chat-input-hint">Hermes Agent Hub • Réponse en streaming direct</div>
</div>
</div>
</div>
<!-- 2. Embedded Iframe View (Used for DSH client and DSH Filebrowser) -->
<div id="hub-iframe-wrapper" class="hub-iframe-wrapper" style="display: none;">
<div id="hub-loader" class="hub-loader-overlay">
<div class="hub-spinner"></div>
<p style="font-size: 0.85rem; color: var(--hub-text-secondary);">Connexion à l'instance...</p>
</div>
<iframe
id="workspace-iframe"
class="hub-workspace-iframe"
src="about:blank"
title="Hermes Workspace Frame"
></iframe>
</div>
</div>
</main>
</div>
<!-- Modal Edition Personnalité -->
<div id="persona-modal" class="hub-modal-backdrop">
<div class="hub-modal">
<div class="hub-modal-header">
<h3 id="persona-modal-title" style="font-size: 1.05rem; font-weight: 600;">Personnalité de l'Univers</h3>
<button class="hub-modal-close" style="background:none;border:none;color:var(--hub-text-muted);font-size:1.2rem;cursor:pointer;">&times;</button>
</div>
<div class="hub-modal-body">
<div class="hub-form-group">
<label class="hub-form-label">Nom d'affichage</label>
<input id="persona-name" class="hub-input" type="text">
</div>
<div class="hub-form-group">
<label class="hub-form-label">Slogan / Rôle</label>
<input id="persona-tagline" class="hub-input" type="text">
</div>
<div class="hub-form-group">
<label class="hub-form-label">Ton de conversation</label>
<input id="persona-tone" class="hub-input" type="text">
</div>
<div class="hub-form-group">
<label class="hub-form-label">Style de rédaction</label>
<input id="persona-style" class="hub-input" type="text">
</div>
<div class="hub-form-group">
<label class="hub-form-label">Principes directeurs (un par ligne)</label>
<textarea id="persona-principles" class="hub-textarea" rows="3"></textarea>
</div>
<div class="hub-form-group">
<label class="hub-form-label">System Prompt / Instructions spécifiques</label>
<textarea id="persona-prompt" class="hub-textarea" rows="4"></textarea>
</div>
</div>
<div class="hub-modal-footer">
<button class="hub-btn hub-btn-secondary hub-modal-close" type="button">Annuler</button>
<button id="btn-save-persona" class="hub-btn hub-btn-primary" type="button">Enregistrer</button>
</div>
</div>
</div>
<!-- Modal Clonage Profil -->
<div id="clone-modal" class="hub-modal-backdrop">
<div class="hub-modal" style="max-width: 440px;">
<div class="hub-modal-header">
<h3 style="font-size: 1.05rem; font-weight: 600;">Cloner le profil <span id="clone-source-name"></span></h3>
<button class="hub-modal-close" style="background:none;border:none;color:var(--hub-text-muted);font-size:1.2rem;cursor:pointer;">&times;</button>
</div>
<div class="hub-modal-body">
<p style="font-size: 0.825rem; color: var(--hub-text-secondary); line-height: 1.4;">
Le clonage crée une copie autonome des personas, règles et instructions sans impacter l'instance de production active.
</p>
<div class="hub-form-group">
<label class="hub-form-label">Nom du clone</label>
<input id="clone-name" class="hub-input" type="text" placeholder="Ex: TT - Variante Audit 2026">
</div>
</div>
<div class="hub-modal-footer">
<button class="hub-btn hub-btn-secondary hub-modal-close" type="button">Annuler</button>
<button id="btn-submit-clone" class="hub-btn hub-btn-primary" type="button">Créer le clone</button>
</div>
</div>
</div>
{% endblock %}