html constant
String
const html
HTML index page
Implementation
static const String html = r'''<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>at_activate - APKAM Enrollment Manager</title>
<script>
(function () {
var theme = null;
try { theme = localStorage.getItem('at_activate_theme'); } catch (e) {}
if (theme !== 'light' && theme !== 'dark') {
theme = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
document.documentElement.setAttribute('data-theme', theme);
})();
</script>
<link rel="stylesheet" href="/styles.css">
<!-- Favicon -->
<link rel="icon" type="image/png" href="/favicon.png"/>
</head>
<body>
<header class="app-bar">
<div class="app-bar-brand">
<img class="app-bar-logo" src="/favicon.png" alt="" width="24" height="24">
<span class="app-bar-name">at_activate_web</span>
<span class="app-bar-version">v1.4.0</span>
</div>
<div class="app-bar-end">
<button type="button" class="theme-toggle-btn" id="theme-toggle-btn" aria-label="Dark mode" aria-pressed="false" onclick="toggleTheme()"><svg class="theme-icon-moon" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="M13.5 9.5A5.5 5.5 0 0 1 6.5 2.5a5.5 5.5 0 1 0 7 7z"/></svg><svg class="theme-icon-sun" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><circle cx="8" cy="8" r="3"/><path d="M8 1.5v1.5M8 13v1.5M1.5 8h1.5M13 8h1.5M3.4 3.4l1.1 1.1M11.5 11.5l1.1 1.1M3.4 12.6l1.1-1.1M11.5 4.5l1.1-1.1"/></svg></button>
<button type="button" id="back-btn" class="atsign-switcher" onclick="goBack()" title="Back to Atsign selection">
<span class="atsign-switcher-label">Switch Atsign</span>
<span id="atsign-display" class="atsign-switcher-handle">Loading...</span>
</button>
</div>
</header>
<div class="container">
<main>
<div class="management-page">
<details class="management-section management-section-yellow">
<summary class="management-section-summary">
<div>
<h2>Manage OTP</h2>
<p>Configure OTP expiry for enrollment command generation.</p>
</div>
<span class="management-section-toggle" aria-hidden="true"></span>
</summary>
<div class="management-section-body">
<div class="otp-management-grid">
<label class="api-v4-field">
<span>OTP Expiry</span>
<input type="text" id="otp-expiry-input" value="1h" placeholder='For example 2d,1h,10m,20s,999ms' />
</label>
<label class="auto-approval-checkbox">
<input type="checkbox" id="custom-otp-enabled" onchange="toggleCustomOtpInput()" />
<span>Custom OTP</span>
</label>
<label class="api-v4-field" id="custom-otp-field">
<span>OTP Value</span>
<input type="text" id="custom-otp-input" placeholder="e.g. ABC123 (6 alphanumeric chars)" maxlength="6" disabled />
</label>
</div>
<div class="management-command-actions">
<button type="button" class="btn-primary" onclick="generateOtp()">Generate OTP</button>
</div>
<div class="otp-history-section">
<div class="otp-inline-label">Generated OTPs</div>
<div class="otp-history-empty" id="otp-history-empty">No OTPs generated yet.</div>
<div class="otp-history-table-wrap" id="otp-history-table-wrap" hidden>
<table class="otp-history-table">
<thead>
<tr>
<th>Generated At</th>
<th>Expiry</th>
<th>Expires At</th>
<th>OTP</th>
<th></th>
</tr>
</thead>
<tbody id="otp-history-body"></tbody>
</table>
</div>
</div>
</div>
</details>
<details class="management-section management-section-orange">
<summary class="management-section-summary">
<div>
<h2>Generate Enrollment Command</h2>
<p>Generate an enrollment command for a NoPorts device or a Personal Agent.</p>
</div>
<span class="management-section-toggle" aria-hidden="true"></span>
</summary>
<div class="management-section-body">
<div class="management-command-actions">
<span class="management-command-label">Profiles</span>
<button type="button" class="api-v4-secondary" onclick="applyEnrollmentProfile('blank')">Blank</button>
<button type="button" class="api-v4-secondary" onclick="showNoPortsWizard()">NoPorts Device</button>
<button type="button" class="api-v4-secondary" onclick="showPersonalAgentWizard()">Personal Agent</button>
</div>
<div class="enrollment-command-grid">
<label class="api-v4-field">
<span class="api-v4-param-label">deviceName</span>
<input type="text" id="enroll-device-name" placeholder="e.g. laptop-1, server-2, pi-office" />
</label>
<label class="api-v4-field">
<span class="api-v4-param-label">appName</span>
<input type="text" id="enroll-app-name" placeholder="e.g. noports" />
</label>
</div>
<label class="api-v4-field api-v4-field-wide">
<span>Use OTP</span>
<select id="enrollment-otp-select"></select>
</label>
<div class="api-v4-field">
<span>Namespaces + Permissions</span>
<div id="namespace-permission-list" class="namespace-permission-list"></div>
<div class="management-command-actions">
<button type="button" class="api-v4-secondary" onclick="addNamespacePermissionRow()">Add Namespace</button>
</div>
<div class="namespace-preview" id="namespace-preview"></div>
</div>
<div class="management-command-actions">
<button type="button" class="btn-primary" onclick="generateEnrollmentCommand()">Generate Command</button>
<button type="button" class="api-v4-secondary" id="copy-enrollment-command-btn" onclick="copyEnrollmentCommand()" hidden>Copy Command</button>
</div>
<div class="otp-inline-result" id="enrollment-command-result" hidden>
<div class="otp-inline-label">Enrollment Command</div>
<code class="otp-inline-value otp-inline-command" id="enrollment-command-value"></code>
<div class="otp-inline-meta" id="enrollment-command-meta"></div>
</div>
</div>
</details>
<details class="management-section management-section-green">
<summary class="management-section-summary">
<div>
<h2>Auto Approval Service</h2>
<p>Automatically approve matching enrollments with at_activate auto.</p>
</div>
<span class="management-section-toggle" aria-hidden="true"></span>
</summary>
<div class="management-section-body">
<div class="auto-approval-grid">
<label class="api-v4-field">
<span>App Name Regex</span>
<input type="text" id="auto-approval-app-regex" placeholder="e.g. ^noports$" />
</label>
<label class="api-v4-field">
<span>Device Name Regex</span>
<input type="text" id="auto-approval-device-regex" placeholder="e.g. ^pi-.*$" />
</label>
<label class="api-v4-field">
<span>Limit</span>
<input type="number" id="auto-approval-limit" min="1" value="1" />
</label>
<label class="api-v4-field auto-approval-checkbox-field">
<span>Approve Existing</span>
<label class="auto-approval-checkbox">
<input type="checkbox" id="auto-approval-approve-existing" />
<span>Approve matching pending requests before listening</span>
</label>
</label>
</div>
<div class="management-command-actions">
<button type="button" class="btn-primary" onclick="createAutoApprovalService()">Create Service</button>
</div>
<div class="otp-history-section">
<div class="otp-inline-label">Configured Services</div>
<div class="otp-history-empty" id="auto-approval-empty">No auto approval services created yet.</div>
<div id="auto-approval-list" class="auto-approval-list" hidden></div>
</div>
</div>
</details>
<details class="management-section management-section-blue" open>
<summary class="management-section-summary">
<div>
<h2>APKAM Key Management</h2>
<p>Refresh enrollments, filter results, search records, and manage APKAM keys.</p>
</div>
<span class="management-section-toggle" aria-hidden="true"></span>
</summary>
<div class="management-section-body">
<div class="controls">
<button id="refresh-btn" onclick="loadEnrollments()">Refresh</button>
<div class="search-box">
<input type="text" id="search-input" placeholder="Search by app, device, enrollment ID, or namespace..." oninput="filterEnrollments()">
<button id="clear-search" onclick="clearSearch()" style="display: none;">×</button>
</div>
</div>
<div class="filter-controls">
<div class="filter">
<label>
<input type="checkbox" id="show-all" checked onchange="filterEnrollments()">
Show all
</label>
<label>
<input type="checkbox" id="show-approved" onchange="filterEnrollments()">
Approved
</label>
<label>
<input type="checkbox" id="show-pending" onchange="filterEnrollments()">
Pending
</label>
<label>
<input type="checkbox" id="show-revoked" onchange="filterEnrollments()">
Revoked
</label>
<label>
<input type="checkbox" id="show-denied" onchange="filterEnrollments()">
Denied
</label>
</div>
<div id="match-count" class="match-count"></div>
</div>
<div id="loading" class="loading">Loading enrollments...</div>
<div id="error" class="error" style="display: none;"></div>
<div id="enrollments-container" class="enrollments-grid">
</div>
</div>
</details>
<details class="management-section management-section-slate" id="history-section">
<summary class="management-section-summary">
<div>
<h2>History</h2>
<p>Recent APKAM, OTP, and auto approval activity for this Atsign.</p>
</div>
<span class="management-section-toggle" aria-hidden="true"></span>
</summary>
<div class="management-section-body">
<div class="otp-history-empty" id="history-empty">No history yet.</div>
<div id="history-list" class="history-list" hidden></div>
<div class="management-command-actions">
<button type="button" class="api-v4-secondary" id="history-load-more-btn" onclick="loadMoreHistory()" hidden>Load More</button>
</div>
</div>
</details>
</div>
</main>
</div>
<script src="/api_v4.js"></script>
<script src="/script.js"></script>
</body>
</html>
''';