Changeset 0.6.0 (#36)
This commit is contained in:
300
src/index.html
300
src/index.html
@@ -3,17 +3,23 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<base href="%%BASE_HREF%%">
|
||||
<script>window.__BASE__ = '%%BASE_PATH%%';</script>
|
||||
<title>Chat Switchboard</title>
|
||||
<link rel="icon" type="image/svg+xml" href="favicon.svg">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32.png">
|
||||
<link rel="apple-touch-icon" sizes="192x192" href="favicon-192.png">
|
||||
<link rel="stylesheet" href="css/styles.css?v=0.5.4">
|
||||
<link rel="stylesheet" href="css/styles.css?v=0.6.2">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- ── App Shell ───────────────────────────── -->
|
||||
<div id="appContainer" class="app" style="display:none">
|
||||
|
||||
<!-- Environment Banner (top) -->
|
||||
<div class="banner banner-top" id="bannerTop"></div>
|
||||
|
||||
<div class="app-body">
|
||||
<!-- Sidebar -->
|
||||
<aside class="sidebar" id="sidebar">
|
||||
<div class="sidebar-top">
|
||||
@@ -22,10 +28,29 @@
|
||||
<svg class="brand-collapse" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="9" y1="3" x2="9" y2="21"/></svg>
|
||||
<span class="sb-label brand-text">Chat Switchboard</span>
|
||||
</button>
|
||||
<button class="sb-btn" id="newChatBtn" title="New Chat">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>
|
||||
<span class="sb-label">New Chat</span>
|
||||
</button>
|
||||
<div class="split-btn" style="position:relative">
|
||||
<button class="split-btn-main" id="newChatBtn" title="New Chat">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>
|
||||
<span class="sb-label">New Chat</span>
|
||||
</button>
|
||||
<button class="split-btn-drop" id="newChatDropBtn" title="More options">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="6 9 12 15 18 9"/></svg>
|
||||
</button>
|
||||
<div class="split-dropdown" id="newChatDropdown">
|
||||
<button class="split-dropdown-item" onclick="newChat()">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>
|
||||
New Chat
|
||||
</button>
|
||||
<button class="split-dropdown-item disabled" title="Coming soon">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
|
||||
Group Chat <span class="dd-hint">soon</span>
|
||||
</button>
|
||||
<button class="split-dropdown-item disabled" title="Coming soon">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="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"/></svg>
|
||||
New Channel <span class="dd-hint">soon</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-chats" id="chatHistory"></div>
|
||||
@@ -95,34 +120,68 @@
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div><!-- .app-body -->
|
||||
|
||||
<!-- Environment Banner (bottom) -->
|
||||
<div class="banner banner-bottom" id="bannerBottom"></div>
|
||||
</div>
|
||||
|
||||
<!-- ── Auth Splash ─────────────────────────── -->
|
||||
<div class="splash" id="splashGate">
|
||||
<div class="splash-card">
|
||||
<div class="splash-brand">
|
||||
<div class="splash-logo">🔀</div>
|
||||
<h1>Chat Switchboard</h1>
|
||||
<p>Multi-Model AI Chat</p>
|
||||
<div class="splash-hero">
|
||||
<div class="hero-content">
|
||||
<div class="hero-logo-row">
|
||||
<svg class="hero-logo-mark" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="64" height="64" rx="12" fill="#1a1a2e"/>
|
||||
<path d="M12 48 L36 16" stroke="#6c9fff" stroke-width="5.5" stroke-linecap="round" fill="none"/>
|
||||
<polygon points="42,12 34,14 38,22" fill="#6c9fff"/>
|
||||
<path d="M12 16 L24 30" stroke="#a78bfa" stroke-width="5.5" stroke-linecap="round" fill="none"/>
|
||||
<path d="M30 38 L36 48" stroke="#a78bfa" stroke-width="5.5" stroke-linecap="round" fill="none"/>
|
||||
<polygon points="42,52 34,50 38,42" fill="#a78bfa"/>
|
||||
</svg>
|
||||
<div class="hero-wordmark">Chat <span>Switchboard</span></div>
|
||||
</div>
|
||||
<h1 class="hero-headline">One interface.<br>Every AI model.</h1>
|
||||
<p class="hero-sub">Route conversations to OpenAI, Anthropic, and any OpenAI-compatible provider from a single, self-hosted chat interface. Bring your own keys. Keep your data.</p>
|
||||
<div class="hero-features">
|
||||
<div class="hero-pill accent"><span class="pill-icon">⚡</span> Streaming responses</div>
|
||||
<div class="hero-pill purple"><span class="pill-icon">🔀</span> Multi-provider routing</div>
|
||||
<div class="hero-pill"><span class="pill-icon">🔑</span> Bring your own API keys</div>
|
||||
<div class="hero-pill"><span class="pill-icon">🏠</span> Self-hosted</div>
|
||||
<div class="hero-pill"><span class="pill-icon">✈️</span> Air-gap ready</div>
|
||||
<div class="hero-pill"><span class="pill-icon">🧠</span> Thinking blocks</div>
|
||||
</div>
|
||||
<div class="hero-version">v0.6.2</div>
|
||||
</div>
|
||||
<div class="auth-tabs">
|
||||
<button class="auth-tab active" id="authTabLogin" onclick="switchAuthTab('login')">Sign In</button>
|
||||
<button class="auth-tab" id="authTabRegister" onclick="switchAuthTab('register')">Register</button>
|
||||
</div>
|
||||
<div id="authLoginForm">
|
||||
<div class="form-group"><label>Username or Email</label><input type="text" id="authLogin" autocomplete="username"></div>
|
||||
<div class="form-group"><label>Password</label><input type="password" id="authPassword" autocomplete="current-password" onkeydown="if(event.key==='Enter')handleLogin()"></div>
|
||||
</div>
|
||||
<div id="authRegisterForm" style="display:none">
|
||||
<div class="form-group"><label>Username</label><input type="text" id="authUsername" autocomplete="username"></div>
|
||||
<div class="form-group"><label>Email</label><input type="email" id="authEmail" autocomplete="email"></div>
|
||||
<div class="form-group"><label>Password</label><input type="password" id="authRegPassword" autocomplete="new-password" onkeydown="if(event.key==='Enter')handleRegister()"></div>
|
||||
</div>
|
||||
<div class="auth-error" id="authError"></div>
|
||||
<div class="splash-error" id="splashError"></div>
|
||||
<div class="auth-actions">
|
||||
<button class="btn-primary btn-full" id="authLoginBtn" data-label="Sign In" onclick="handleLogin()">Sign In</button>
|
||||
<button class="btn-primary btn-full" id="authRegisterBtn" data-label="Create Account" onclick="handleRegister()" style="display:none">Create Account</button>
|
||||
</div>
|
||||
<div class="splash-auth">
|
||||
<div class="auth-card">
|
||||
<div class="auth-card-header">
|
||||
<h2>Welcome back</h2>
|
||||
<p>Sign in to continue to your workspace</p>
|
||||
</div>
|
||||
<div class="auth-tabs">
|
||||
<button class="auth-tab active" id="authTabLogin" onclick="switchAuthTab('login')">Sign In</button>
|
||||
<button class="auth-tab" id="authTabRegister" onclick="switchAuthTab('register')">Register</button>
|
||||
</div>
|
||||
<div id="authLoginForm">
|
||||
<div class="form-group"><label>Username or Email</label><input type="text" id="authLogin" autocomplete="username" placeholder="you@example.com"></div>
|
||||
<div class="form-group"><label>Password</label><input type="password" id="authPassword" autocomplete="current-password" placeholder="••••••••" onkeydown="if(event.key==='Enter')handleLogin()"></div>
|
||||
</div>
|
||||
<div id="authRegisterForm" style="display:none">
|
||||
<div class="form-group"><label>Username</label><input type="text" id="authUsername" autocomplete="username" placeholder="Choose a username"></div>
|
||||
<div class="form-group"><label>Email</label><input type="email" id="authEmail" autocomplete="email" placeholder="you@example.com"></div>
|
||||
<div class="form-group"><label>Password</label><input type="password" id="authRegPassword" autocomplete="new-password" placeholder="Min 8 characters" onkeydown="if(event.key==='Enter')handleRegister()"></div>
|
||||
</div>
|
||||
<div class="auth-error" id="authError"></div>
|
||||
<div class="splash-error" id="splashError"></div>
|
||||
<div class="auth-actions">
|
||||
<button class="btn-primary btn-full" id="authLoginBtn" data-label="Sign In" onclick="handleLogin()">Sign In</button>
|
||||
<button class="btn-primary btn-full" id="authRegisterBtn" data-label="Create Account" onclick="handleRegister()" style="display:none">Create Account</button>
|
||||
</div>
|
||||
<div class="auth-footer">
|
||||
<p>Self-hosted AI chat · Your keys, your data</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -131,44 +190,62 @@
|
||||
<div class="modal-overlay" id="settingsModal">
|
||||
<div class="modal">
|
||||
<div class="modal-header"><h2>Settings</h2><button class="modal-close" id="settingsCloseBtn">✕</button></div>
|
||||
<div class="settings-tabs">
|
||||
<button class="settings-tab active" data-stab="general" onclick="UI.switchSettingsTab('general')">General</button>
|
||||
<button class="settings-tab" data-stab="providers" onclick="UI.switchSettingsTab('providers')">Providers</button>
|
||||
<button class="settings-tab" data-stab="models" onclick="UI.switchSettingsTab('models')">Models</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<section class="settings-section">
|
||||
<h3>Profile</h3>
|
||||
<div class="form-group"><label>Display Name</label><input type="text" id="profileDisplayName"></div>
|
||||
<div class="form-group"><label>Email</label><input type="email" id="profileEmail"></div>
|
||||
<button class="btn-small" id="profileChangePwBtn">Change Password</button>
|
||||
<div id="profileChangePwForm" style="display:none">
|
||||
<div class="form-group"><label>Current Password</label><input type="password" id="profileCurrentPw"></div>
|
||||
<div class="form-group"><label>New Password</label><input type="password" id="profileNewPw"></div>
|
||||
<button class="btn-small btn-primary" id="profileSavePwBtn">Save Password</button>
|
||||
</div>
|
||||
</section>
|
||||
<section class="settings-section">
|
||||
<h3>Chat</h3>
|
||||
<div class="form-group"><label>Default Model</label><select id="settingsModel"></select></div>
|
||||
<div class="form-group"><label>System Prompt</label><textarea id="settingsSystemPrompt" rows="3"></textarea></div>
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label>Max Tokens <span class="form-hint" id="settingsMaxHint"></span></label>
|
||||
<input type="number" id="settingsMaxTokens" placeholder="Auto (from model)">
|
||||
<!-- General Tab -->
|
||||
<div class="settings-tab-content" id="settingsGeneralTab">
|
||||
<section class="settings-section">
|
||||
<h3>Profile</h3>
|
||||
<div class="form-group"><label>Display Name</label><input type="text" id="profileDisplayName"></div>
|
||||
<div class="form-group"><label>Email</label><input type="email" id="profileEmail"></div>
|
||||
<button class="btn-small" id="profileChangePwBtn">Change Password</button>
|
||||
<div id="profileChangePwForm" style="display:none">
|
||||
<div class="form-group"><label>Current Password</label><input type="password" id="profileCurrentPw"></div>
|
||||
<div class="form-group"><label>New Password</label><input type="password" id="profileNewPw"></div>
|
||||
<button class="btn-small btn-primary" id="profileSavePwBtn">Save Password</button>
|
||||
</div>
|
||||
<div class="form-group"><label>Temperature</label><input type="number" id="settingsTemp" value="0.7" step="0.1" min="0" max="2"></div>
|
||||
</section>
|
||||
<section class="settings-section">
|
||||
<h3>Chat</h3>
|
||||
<div class="form-group"><label>Default Model</label><select id="settingsModel"></select></div>
|
||||
<div class="form-group"><label>System Prompt</label><textarea id="settingsSystemPrompt" rows="3"></textarea></div>
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label>Max Tokens <span class="form-hint" id="settingsMaxHint"></span></label>
|
||||
<input type="number" id="settingsMaxTokens" placeholder="Auto (from model)">
|
||||
</div>
|
||||
<div class="form-group"><label>Temperature</label><input type="number" id="settingsTemp" value="0.7" step="0.1" min="0" max="2"></div>
|
||||
</div>
|
||||
<label class="checkbox-label"><input type="checkbox" id="settingsThinking" checked> Show thinking blocks</label>
|
||||
</section>
|
||||
</div>
|
||||
<!-- Providers Tab -->
|
||||
<div class="settings-tab-content" id="settingsProvidersTab" style="display:none">
|
||||
<section class="settings-section">
|
||||
<div id="providerList"></div>
|
||||
<button class="btn-small" id="providerShowAddBtn">+ Add Provider</button>
|
||||
<div id="providerAddForm" style="display:none">
|
||||
<div class="form-group"><label>Name</label><input type="text" id="providerName" placeholder="My OpenAI Key"></div>
|
||||
<div class="form-group"><label>Provider</label><select id="providerType"><option value="openai">OpenAI-compatible</option><option value="anthropic">Anthropic</option><option value="venice">Venice.ai</option><option value="openrouter">OpenRouter</option></select></div>
|
||||
<div class="form-group"><label>Endpoint</label><input type="text" id="providerEndpoint" placeholder="https://api.openai.com/v1"></div>
|
||||
<div class="form-group"><label>API Key</label><input type="password" id="providerApiKey" placeholder="sk-..."></div>
|
||||
<div class="form-group"><label>Default Model</label><input type="text" id="providerDefaultModel" placeholder="gpt-4o"></div>
|
||||
<div class="form-row"><button class="btn-small btn-primary" id="providerCreateBtn">Save</button><button class="btn-small" id="providerCancelBtn">Cancel</button></div>
|
||||
</div>
|
||||
</section>
|
||||
<div id="userProvidersDisabled" class="settings-notice" style="display:none">
|
||||
<span>⚠️</span> User-configured providers have been disabled by the administrator.
|
||||
</div>
|
||||
<label class="checkbox-label"><input type="checkbox" id="settingsThinking" checked> Show thinking blocks</label>
|
||||
</section>
|
||||
<section class="settings-section">
|
||||
<h3>API Providers</h3>
|
||||
<div id="providerList"></div>
|
||||
<button class="btn-small" id="providerShowAddBtn">+ Add Provider</button>
|
||||
<div id="providerAddForm" style="display:none">
|
||||
<div class="form-group"><label>Name</label><input type="text" id="providerName" placeholder="My OpenAI Key"></div>
|
||||
<div class="form-group"><label>Provider</label><select id="providerType"><option value="openai">OpenAI-compatible</option><option value="anthropic">Anthropic</option><option value="venice">Venice.ai</option><option value="openrouter">OpenRouter</option></select></div>
|
||||
<div class="form-group"><label>Endpoint</label><input type="text" id="providerEndpoint" placeholder="https://api.openai.com/v1"></div>
|
||||
<div class="form-group"><label>API Key</label><input type="password" id="providerApiKey" placeholder="sk-..."></div>
|
||||
<div class="form-group"><label>Default Model</label><input type="text" id="providerDefaultModel" placeholder="gpt-4o"></div>
|
||||
<div class="form-row"><button class="btn-small btn-primary" id="providerCreateBtn">Save</button><button class="btn-small" id="providerCancelBtn">Cancel</button></div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<!-- Models Tab -->
|
||||
<div class="settings-tab-content" id="settingsModelsTab" style="display:none">
|
||||
<p class="section-hint">Models available from your providers and global configs.</p>
|
||||
<div id="userModelList" class="model-list-grid"><div class="empty-hint">Loading models...</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer"><button class="btn-primary" id="settingsSaveBtn">Save Settings</button></div>
|
||||
</div>
|
||||
@@ -186,12 +263,89 @@
|
||||
<button class="admin-tab" data-tab="stats">Stats</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="admin-tab-content" id="adminUsersTab"><div id="adminUserList"></div></div>
|
||||
<div class="admin-tab-content" id="adminProvidersTab" style="display:none"><div id="adminProviderList"></div></div>
|
||||
<div class="admin-tab-content" id="adminModelsTab" style="display:none"><div id="adminModelList"></div></div>
|
||||
<div class="admin-tab-content" id="adminUsersTab">
|
||||
<div class="admin-toolbar">
|
||||
<button class="btn-small btn-primary" id="adminAddUserBtn">+ Add User</button>
|
||||
</div>
|
||||
<div id="adminAddUserForm" style="display:none" class="admin-inline-form">
|
||||
<div class="form-row">
|
||||
<div class="form-group"><label>Username</label><input type="text" id="adminNewUsername" placeholder="username"></div>
|
||||
<div class="form-group"><label>Email</label><input type="email" id="adminNewEmail" placeholder="email@example.com"></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group"><label>Password</label><input type="password" id="adminNewPassword" placeholder="min 8 chars"></div>
|
||||
<div class="form-group"><label>Role</label><select id="adminNewRole"><option value="user">User</option><option value="admin">Admin</option></select></div>
|
||||
</div>
|
||||
<div class="form-row"><button class="btn-small btn-primary" id="adminCreateUserBtn">Create</button><button class="btn-small" id="adminCancelUserBtn">Cancel</button></div>
|
||||
</div>
|
||||
<div id="adminUserList"></div>
|
||||
</div>
|
||||
<div class="admin-tab-content" id="adminProvidersTab" style="display:none">
|
||||
<div class="admin-toolbar">
|
||||
<button class="btn-small btn-primary" id="adminAddProviderBtn">+ Add Global Provider</button>
|
||||
</div>
|
||||
<div id="adminAddProviderForm" style="display:none" class="admin-inline-form">
|
||||
<div class="form-row">
|
||||
<div class="form-group"><label>Name</label><input type="text" id="adminProvName" placeholder="OpenAI Production"></div>
|
||||
<div class="form-group"><label>Provider</label><select id="adminProvType"><option value="openai">OpenAI-compatible</option><option value="anthropic">Anthropic</option><option value="venice">Venice.ai</option><option value="openrouter">OpenRouter</option></select></div>
|
||||
</div>
|
||||
<div class="form-group"><label>Endpoint</label><input type="text" id="adminProvEndpoint" placeholder="https://api.openai.com/v1"></div>
|
||||
<div class="form-row">
|
||||
<div class="form-group"><label>API Key</label><input type="password" id="adminProvKey" placeholder="sk-..."></div>
|
||||
<div class="form-group"><label>Default Model</label><input type="text" id="adminProvModel" placeholder="gpt-4o"></div>
|
||||
</div>
|
||||
<div class="form-row"><button class="btn-small btn-primary" id="adminCreateProvBtn">Save</button><button class="btn-small" id="adminCancelProvBtn">Cancel</button></div>
|
||||
</div>
|
||||
<div id="adminProviderList"></div>
|
||||
</div>
|
||||
<div class="admin-tab-content" id="adminModelsTab" style="display:none">
|
||||
<div class="admin-toolbar">
|
||||
<button class="btn-small btn-primary" id="adminFetchModelsBtn">⟳ Fetch Models</button>
|
||||
<button class="btn-small" onclick="bulkToggleModels(true)">Enable All</button>
|
||||
<button class="btn-small" onclick="bulkToggleModels(false)">Disable All</button>
|
||||
<span class="admin-hint" id="adminModelsHint"></span>
|
||||
</div>
|
||||
<div id="adminModelList"></div>
|
||||
</div>
|
||||
<div class="admin-tab-content" id="adminSettingsTab" style="display:none">
|
||||
<label class="checkbox-label"><input type="checkbox" id="adminRegToggle" checked> Allow registration</label>
|
||||
<button class="btn-primary btn-small" id="adminSaveSettings">Save</button>
|
||||
<section class="settings-section">
|
||||
<h3>Registration</h3>
|
||||
<label class="checkbox-label"><input type="checkbox" id="adminRegToggle" checked> Allow new user registration</label>
|
||||
<div class="form-group" style="margin-top: 8px;">
|
||||
<label>Default state for new accounts</label>
|
||||
<select id="adminRegDefaultState">
|
||||
<option value="active">Active — immediate access</option>
|
||||
<option value="pending">Pending — require admin approval</option>
|
||||
</select>
|
||||
</div>
|
||||
</section>
|
||||
<section class="settings-section">
|
||||
<h3>User Providers</h3>
|
||||
<label class="checkbox-label"><input type="checkbox" id="adminUserProvidersToggle" checked> Allow users to configure their own API providers</label>
|
||||
<p class="section-hint">When disabled, users can only use admin-configured global providers.</p>
|
||||
</section>
|
||||
<section class="settings-section">
|
||||
<h3>Environment Banner</h3>
|
||||
<label class="checkbox-label"><input type="checkbox" id="adminBannerEnabled"> Show environment banner</label>
|
||||
<div id="bannerConfigFields" style="display:none">
|
||||
<div class="form-group">
|
||||
<label>Preset</label>
|
||||
<select id="adminBannerPreset"><option value="">Custom</option></select>
|
||||
</div>
|
||||
<div class="form-group"><label>Banner Text</label><input type="text" id="adminBannerText" placeholder="DEVELOPMENT"></div>
|
||||
<div class="form-row">
|
||||
<div class="form-group"><label>Position</label>
|
||||
<select id="adminBannerPosition"><option value="both">Top & Bottom</option><option value="top">Top only</option><option value="bottom">Bottom only</option></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group"><label>Background</label><div class="color-input-wrap"><input type="color" id="adminBannerBg" value="#007a33"><input type="text" id="adminBannerBgHex" class="color-hex" value="#007a33" maxlength="7"></div></div>
|
||||
<div class="form-group"><label>Text Color</label><div class="color-input-wrap"><input type="color" id="adminBannerFg" value="#ffffff"><input type="text" id="adminBannerFgHex" class="color-hex" value="#ffffff" maxlength="7"></div></div>
|
||||
</div>
|
||||
<div class="banner-preview" id="bannerPreview">PREVIEW</div>
|
||||
</div>
|
||||
</section>
|
||||
<button class="btn-primary btn-small" id="adminSaveSettings">Save Settings</button>
|
||||
</div>
|
||||
<div class="admin-tab-content" id="adminStatsTab" style="display:none"><div id="adminStats"></div></div>
|
||||
</div>
|
||||
@@ -235,10 +389,10 @@
|
||||
<script src="vendor/marked.min.js" onerror="this.onerror=null;this.src='https://cdnjs.cloudflare.com/ajax/libs/marked/16.3.0/lib/marked.umd.min.js'"></script>
|
||||
<script src="vendor/purify.min.js" onerror="this.onerror=null;this.src='https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.2.4/purify.min.js'"></script>
|
||||
|
||||
<script src="js/debug.js?v=0.5.4"></script>
|
||||
<script src="js/events.js?v=0.5.4"></script>
|
||||
<script src="js/api.js?v=0.5.4"></script>
|
||||
<script src="js/ui.js?v=0.5.4"></script>
|
||||
<script src="js/app.js?v=0.5.4"></script>
|
||||
<script src="js/debug.js?v=0.6.2"></script>
|
||||
<script src="js/events.js?v=0.6.2"></script>
|
||||
<script src="js/api.js?v=0.6.2"></script>
|
||||
<script src="js/ui.js?v=0.6.2"></script>
|
||||
<script src="js/app.js?v=0.6.2"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user