1072 lines
50 KiB
HTML
1072 lines
50 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>derez.ai — Admin</title>
|
|
<link rel="stylesheet" href="styles.css" />
|
|
</head>
|
|
<body>
|
|
<div class="layout">
|
|
<!-- ═══ SIDEBAR ════════════════════════════════════════════════ -->
|
|
<nav class="sidebar">
|
|
<div class="sidebar-brand">
|
|
<svg
|
|
width="22"
|
|
height="22"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<rect x="2" y="3" width="20" height="14" rx="2" />
|
|
<path d="M8 21h8M12 17v4" />
|
|
</svg>
|
|
derez.ai
|
|
</div>
|
|
|
|
<div class="sidebar-section-label">Network</div>
|
|
<div class="nav-item active" data-section="dns">
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<ellipse cx="12" cy="5" rx="9" ry="3" />
|
|
<path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5" />
|
|
<path d="M3 12c0 1.66 4 3 9 3s9-1.34 9-3" />
|
|
</svg>
|
|
DNS Records
|
|
</div>
|
|
<div class="nav-item" data-section="coming-soon-firewall">
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
|
</svg>
|
|
Firewall
|
|
</div>
|
|
|
|
<div class="sidebar-section-label">Infrastructure</div>
|
|
<div class="nav-item" data-section="instances">
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path
|
|
d="M21 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.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"
|
|
/>
|
|
<polyline points="3.27 6.96 12 12.01 20.73 6.96" />
|
|
<line x1="12" y1="22.08" x2="12" y2="12" />
|
|
</svg>
|
|
Instances
|
|
</div>
|
|
<div class="nav-item" data-section="backup">
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
|
|
<polyline points="17 8 12 3 7 8" />
|
|
<line x1="12" y1="3" x2="12" y2="15" />
|
|
</svg>
|
|
Backup
|
|
</div>
|
|
<div class="nav-item" data-section="servers">
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<rect x="2" y="2" width="20" height="8" rx="2" />
|
|
<rect x="2" y="14" width="20" height="8" rx="2" />
|
|
<line x1="6" y1="6" x2="6.01" y2="6" />
|
|
<line x1="6" y1="18" x2="6.01" y2="18" />
|
|
</svg>
|
|
Servers
|
|
</div>
|
|
<div class="nav-item" data-section="coming-soon-ssl">
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<rect x="3" y="11" width="18" height="11" rx="2" />
|
|
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
|
</svg>
|
|
SSL / TLS
|
|
</div>
|
|
|
|
<div class="sidebar-section-label">Commercial</div>
|
|
<div class="nav-item" data-section="keys">
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path
|
|
d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"
|
|
/>
|
|
</svg>
|
|
Keys
|
|
</div>
|
|
|
|
<div class="sidebar-footer">
|
|
<div
|
|
class="nav-item"
|
|
id="sidebar-user"
|
|
style="
|
|
cursor: default;
|
|
gap: 8px;
|
|
padding: 9px 18px;
|
|
border-left: none;
|
|
color: var(--text-muted);
|
|
font-size: 12px;
|
|
"
|
|
>
|
|
<svg
|
|
width="14"
|
|
height="14"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path
|
|
d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"
|
|
/>
|
|
<circle cx="12" cy="7" r="4" />
|
|
</svg>
|
|
<span id="sidebar-username">Not signed in</span>
|
|
</div>
|
|
<div class="nav-item" data-section="settings">
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<circle cx="12" cy="12" r="3" />
|
|
<path
|
|
d="M19.07 4.93a10 10 0 0 0-14.14 0M4.93 19.07a10 10 0 0 0 14.14 0M12 2v2M12 20v2M2 12h2M20 12h2"
|
|
/>
|
|
</svg>
|
|
Settings
|
|
</div>
|
|
<div
|
|
class="nav-item"
|
|
onclick="doSignOut()"
|
|
style="
|
|
color: var(--danger);
|
|
border-left: none;
|
|
padding: 9px 0;
|
|
"
|
|
>
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
|
|
<polyline points="16 17 21 12 16 7" />
|
|
<line x1="21" y1="12" x2="9" y2="12" />
|
|
</svg>
|
|
Sign Out
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- ═══ MAIN ════════════════════════════════════════════════════ -->
|
|
<div class="main">
|
|
<!-- Top bar -->
|
|
<div class="topbar">
|
|
<span class="topbar-title" id="page-title"
|
|
>DNS Records</span
|
|
>
|
|
<div class="topbar-actions" id="topbar-actions">
|
|
<button
|
|
class="btn btn-ghost btn-sm"
|
|
id="btn-refresh"
|
|
onclick="dnsLoadRecords()"
|
|
>
|
|
<svg
|
|
width="13"
|
|
height="13"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2.5"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path d="M23 4v6h-6" />
|
|
<path d="M1 20v-6h6" />
|
|
<path
|
|
d="M3.51 9a9 9 0 0 1 14.36-3.36L23 10M1 14l5.13 4.36A9 9 0 0 0 20.49 15"
|
|
/>
|
|
</svg>
|
|
Refresh
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Content -->
|
|
<div class="content">
|
|
<!-- ─── DNS Section ───────────────────────────────────────── -->
|
|
<div class="section active" id="section-dns">
|
|
<!-- Filter / search bar -->
|
|
<div
|
|
class="card"
|
|
style="padding: 14px 20px; margin-bottom: 16px"
|
|
>
|
|
<div
|
|
class="form-row"
|
|
style="
|
|
flex-wrap: nowrap;
|
|
gap: 10px;
|
|
align-items: center;
|
|
"
|
|
>
|
|
<div
|
|
class="form-group"
|
|
style="flex: 2; min-width: 140px"
|
|
>
|
|
<input
|
|
type="text"
|
|
id="dns-search"
|
|
placeholder="Search by name or content…"
|
|
oninput="dnsRender()"
|
|
/>
|
|
</div>
|
|
<div
|
|
class="form-group"
|
|
style="flex: 1; min-width: 110px"
|
|
>
|
|
<select
|
|
id="dns-filter-type"
|
|
onchange="dnsRender()"
|
|
>
|
|
<option value="">All types</option>
|
|
<option selected>A</option>
|
|
<option>AAAA</option>
|
|
<option>CNAME</option>
|
|
<option>MX</option>
|
|
<option>TXT</option>
|
|
<option>NS</option>
|
|
<option>SRV</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<span class="card-title">
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<ellipse cx="12" cy="5" rx="9" ry="3" />
|
|
<path
|
|
d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"
|
|
/>
|
|
<path
|
|
d="M3 12c0 1.66 4 3 9 3s9-1.34 9-3"
|
|
/>
|
|
</svg>
|
|
Records
|
|
</span>
|
|
<span
|
|
id="dns-record-count"
|
|
class="text-muted"
|
|
style="font-size: 12px"
|
|
></span>
|
|
</div>
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Type</th>
|
|
<th>Content</th>
|
|
<th>TTL</th>
|
|
<th>Status</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="dns-table-body">
|
|
<tr>
|
|
<td colspan="6">
|
|
<div class="empty-state">
|
|
<div class="spinner"></div>
|
|
<p style="margin-top: 12px">
|
|
Loading records…
|
|
</p>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ─── Add New Record ───────────────────────────────────── -->
|
|
<div class="card" id="dns-add-card">
|
|
<div
|
|
class="card-header"
|
|
style="margin-bottom: 14px"
|
|
>
|
|
<span class="card-title">
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<circle cx="12" cy="12" r="10" />
|
|
<line x1="12" y1="8" x2="12" y2="16" />
|
|
<line x1="8" y1="12" x2="16" y2="12" />
|
|
</svg>
|
|
Add New Record
|
|
</span>
|
|
</div>
|
|
<div class="form-row">
|
|
<div
|
|
class="form-group"
|
|
style="flex: 2; min-width: 140px"
|
|
>
|
|
<label
|
|
>Name
|
|
<span style="color: var(--text-muted)"
|
|
>(@ for root)</span
|
|
></label
|
|
>
|
|
<input
|
|
type="text"
|
|
id="add-name"
|
|
placeholder="e.g. www"
|
|
/>
|
|
</div>
|
|
<div
|
|
class="form-group"
|
|
style="flex: 1; min-width: 100px"
|
|
>
|
|
<label>Type</label>
|
|
<select id="add-type">
|
|
<option>A</option>
|
|
<option>AAAA</option>
|
|
<option>CNAME</option>
|
|
<option>MX</option>
|
|
<option>TXT</option>
|
|
<option>NS</option>
|
|
<option>SRV</option>
|
|
<option>CAA</option>
|
|
</select>
|
|
</div>
|
|
<div
|
|
class="form-group"
|
|
style="flex: 3; min-width: 180px"
|
|
>
|
|
<label>Content</label>
|
|
<input
|
|
type="text"
|
|
id="add-content"
|
|
placeholder="e.g. 1.2.3.4 or target.domain.com."
|
|
/>
|
|
</div>
|
|
<div
|
|
class="form-group"
|
|
style="flex: 1; min-width: 100px"
|
|
>
|
|
<label>TTL (s)</label>
|
|
<input
|
|
type="number"
|
|
id="add-ttl"
|
|
value="3600"
|
|
min="60"
|
|
/>
|
|
</div>
|
|
<div
|
|
class="form-group"
|
|
style="
|
|
flex: 0 0 auto;
|
|
justify-content: flex-end;
|
|
"
|
|
>
|
|
<label style="visibility: hidden"
|
|
>Add</label
|
|
>
|
|
<button
|
|
class="btn btn-primary"
|
|
id="add-submit-btn"
|
|
onclick="dnsAddRecord()"
|
|
>
|
|
<svg
|
|
width="14"
|
|
height="14"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2.5"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<polyline points="20 6 9 17 4 12" />
|
|
</svg>
|
|
Add Record
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ─── Instances Section ──────────────────────────────────── -->
|
|
<div class="section" id="section-instances">
|
|
<!-- Search bar -->
|
|
<div
|
|
class="card"
|
|
style="padding: 14px 20px; margin-bottom: 16px"
|
|
>
|
|
<div
|
|
class="form-row"
|
|
style="
|
|
flex-wrap: nowrap;
|
|
gap: 10px;
|
|
align-items: center;
|
|
"
|
|
>
|
|
<div
|
|
class="form-group"
|
|
style="flex: 1; min-width: 140px"
|
|
>
|
|
<input
|
|
type="text"
|
|
id="inst-search"
|
|
placeholder="Search by agent, domain, UUID or server…"
|
|
oninput="instancesRender()"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<span class="card-title">
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path
|
|
d="M21 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.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"
|
|
/>
|
|
<polyline
|
|
points="3.27 6.96 12 12.01 20.73 6.96"
|
|
/>
|
|
<line
|
|
x1="12"
|
|
y1="22.08"
|
|
x2="12"
|
|
y2="12"
|
|
/>
|
|
</svg>
|
|
Instances
|
|
</span>
|
|
<span
|
|
id="inst-record-count"
|
|
class="text-muted"
|
|
style="font-size: 12px"
|
|
></span>
|
|
</div>
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>UUID</th>
|
|
<th>Agent</th>
|
|
<th>Domain</th>
|
|
<th>SSH Port</th>
|
|
<th>RAM</th>
|
|
<th>CPU</th>
|
|
<th>Server</th>
|
|
<th>Created</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="inst-table-body">
|
|
<tr>
|
|
<td colspan="9">
|
|
<div class="empty-state">
|
|
<div class="spinner"></div>
|
|
<p style="margin-top: 12px">
|
|
Loading instances…
|
|
</p>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ─── Backup Section ─────────────────────────────────────── -->
|
|
<div class="section" id="section-backup">
|
|
<!-- Search bar -->
|
|
<div
|
|
class="card"
|
|
style="padding: 14px 20px; margin-bottom: 16px"
|
|
>
|
|
<div
|
|
class="form-row"
|
|
style="
|
|
flex-wrap: nowrap;
|
|
gap: 10px;
|
|
align-items: center;
|
|
"
|
|
>
|
|
<div
|
|
class="form-group"
|
|
style="flex: 1; min-width: 140px"
|
|
>
|
|
<input
|
|
type="text"
|
|
id="backup-search"
|
|
placeholder="Search by name or ID…"
|
|
oninput="backupRender()"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<span class="card-title">
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path
|
|
d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"
|
|
/>
|
|
<polyline points="17 8 12 3 7 8" />
|
|
<line x1="12" y1="3" x2="12" y2="15" />
|
|
</svg>
|
|
Repositories
|
|
</span>
|
|
<span
|
|
id="backup-record-count"
|
|
class="text-muted"
|
|
style="font-size: 12px"
|
|
></span>
|
|
</div>
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>ID</th>
|
|
<th>Region</th>
|
|
<th style="text-align: right">
|
|
Size
|
|
</th>
|
|
<th>Last Modified</th>
|
|
<th>Created</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="backup-table-body">
|
|
<tr>
|
|
<td colspan="7">
|
|
<div class="empty-state">
|
|
<div class="spinner"></div>
|
|
<p style="margin-top: 12px">
|
|
Loading repositories…
|
|
</p>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ─── Settings Section ──────────────────────────────────── -->
|
|
<div class="section" id="section-settings">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<span class="card-title">API Connection</span>
|
|
</div>
|
|
<div class="settings-grid">
|
|
<div
|
|
class="form-group"
|
|
style="grid-column: 1/-1"
|
|
>
|
|
<label>API Base URL</label>
|
|
<input
|
|
type="text"
|
|
id="setting-url"
|
|
placeholder="https://admin.derez.ai"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div style="margin-top: 16px">
|
|
<button
|
|
class="btn btn-primary"
|
|
onclick="settingsSave()"
|
|
>
|
|
Save URL
|
|
</button>
|
|
<button
|
|
class="btn btn-ghost"
|
|
onclick="settingsTest()"
|
|
style="margin-left: 8px"
|
|
>
|
|
Test Connection
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<span class="card-title">Current Session</span>
|
|
</div>
|
|
<p
|
|
style="
|
|
font-size: 13px;
|
|
color: var(--text-muted);
|
|
margin-bottom: 16px;
|
|
"
|
|
>
|
|
Signed in as
|
|
<strong id="settings-session-email">—</strong>.
|
|
Sign out to switch accounts.
|
|
</p>
|
|
<div style="margin-top: 16px">
|
|
<button
|
|
class="btn btn-danger"
|
|
onclick="doSignOut()"
|
|
>
|
|
Sign Out
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ─── Keys Section ───────────────────────────────────── -->
|
|
<div class="section" id="section-keys">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<span class="card-title">
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path
|
|
d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"
|
|
/>
|
|
</svg>
|
|
API Keys
|
|
</span>
|
|
<span
|
|
id="keys-record-count"
|
|
class="text-muted"
|
|
style="font-size: 12px"
|
|
></span>
|
|
</div>
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Key</th>
|
|
<th>Status</th>
|
|
<th>Limit</th>
|
|
<th>Remaining</th>
|
|
<th>Reset</th>
|
|
<th>Usage (monthly)</th>
|
|
<th>Created</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="keys-table-body">
|
|
<tr>
|
|
<td colspan="9">
|
|
<div class="empty-state">
|
|
<div class="spinner"></div>
|
|
<p style="margin-top: 12px">
|
|
Loading keys…
|
|
</p>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ─── Coming-soon placeholders ─────────────────────────── -->
|
|
<div class="section" id="section-coming-soon-firewall">
|
|
<div class="card">
|
|
<div class="empty-state">
|
|
<svg
|
|
width="48"
|
|
height="48"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path
|
|
d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"
|
|
/>
|
|
</svg>
|
|
<p>Firewall management — coming soon</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="section" id="section-servers">
|
|
<div id="server-tabs-strip" class="server-tabs"></div>
|
|
<div id="server-dashboard">
|
|
<div class="empty-state">
|
|
<div class="spinner"></div>
|
|
<p style="margin-top: 12px">Loading servers…</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="section" id="section-coming-soon-ssl">
|
|
<div class="card">
|
|
<div class="empty-state">
|
|
<svg
|
|
width="48"
|
|
height="48"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<rect
|
|
x="3"
|
|
y="11"
|
|
width="18"
|
|
height="11"
|
|
rx="2"
|
|
/>
|
|
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
|
</svg>
|
|
<p>SSL / TLS management — coming soon</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- /content -->
|
|
</div>
|
|
<!-- /main -->
|
|
</div>
|
|
<!-- /layout -->
|
|
|
|
<!-- ═══ INSTANCES EDIT MODAL ═════════════════════════════════ -->
|
|
<div class="modal-backdrop" id="inst-edit-backdrop">
|
|
<div class="modal">
|
|
<div class="modal-header">
|
|
<span class="modal-title">Edit Instance</span>
|
|
<button
|
|
class="modal-close"
|
|
onclick="instancesCloseEdit()"
|
|
aria-label="Close"
|
|
>
|
|
✕
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="form-row" style="flex-wrap: wrap">
|
|
<div class="form-group" style="flex: 0 0 100%">
|
|
<label
|
|
>UUID
|
|
<span class="text-muted"
|
|
>(read-only)</span
|
|
></label
|
|
>
|
|
<input
|
|
type="text"
|
|
id="inst-edit-uuid"
|
|
disabled
|
|
style="opacity: 0.5; cursor: not-allowed"
|
|
/>
|
|
</div>
|
|
<div
|
|
class="form-group"
|
|
style="flex: 1; min-width: 120px"
|
|
>
|
|
<label
|
|
>Agent
|
|
<span class="text-muted"
|
|
>(read-only)</span
|
|
></label
|
|
>
|
|
<input
|
|
type="text"
|
|
id="inst-edit-agent"
|
|
disabled
|
|
style="opacity: 0.5; cursor: not-allowed"
|
|
/>
|
|
</div>
|
|
<div
|
|
class="form-group"
|
|
style="flex: 2; min-width: 200px"
|
|
>
|
|
<label
|
|
>Domain
|
|
<span class="text-muted"
|
|
>(read-only)</span
|
|
></label
|
|
>
|
|
<input
|
|
type="text"
|
|
id="inst-edit-domain"
|
|
disabled
|
|
style="opacity: 0.5; cursor: not-allowed"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<hr class="sep" />
|
|
<div class="form-row" style="flex-wrap: wrap">
|
|
<div
|
|
class="form-group"
|
|
style="flex: 1; min-width: 110px"
|
|
>
|
|
<label>SSH Port</label>
|
|
<input
|
|
type="text"
|
|
id="inst-edit-ssh-port"
|
|
placeholder="e.g. 22"
|
|
/>
|
|
</div>
|
|
<div
|
|
class="form-group"
|
|
style="flex: 1; min-width: 110px"
|
|
>
|
|
<label>RAM</label>
|
|
<input
|
|
type="text"
|
|
id="inst-edit-ram"
|
|
placeholder="e.g. 512m"
|
|
/>
|
|
</div>
|
|
<div
|
|
class="form-group"
|
|
style="flex: 1; min-width: 110px"
|
|
>
|
|
<label>CPU</label>
|
|
<input
|
|
type="text"
|
|
id="inst-edit-cpu"
|
|
placeholder="e.g. 2"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button
|
|
class="btn btn-ghost"
|
|
onclick="instancesCloseEdit()"
|
|
>
|
|
Cancel
|
|
</button>
|
|
<button
|
|
class="btn btn-primary"
|
|
id="inst-save-btn"
|
|
onclick="instancesSaveEdit()"
|
|
>
|
|
<svg
|
|
width="13"
|
|
height="13"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2.5"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<polyline points="20 6 9 17 4 12" />
|
|
</svg>
|
|
Save Changes
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ═══ CONFIRM DIALOG ══════════════════════════════════════════════ -->
|
|
<div class="modal-backdrop" id="confirm-backdrop">
|
|
<div class="modal" id="confirm-modal" style="max-width: 360px">
|
|
<div class="modal-header">
|
|
<span class="modal-title" id="confirm-title">Confirm</span>
|
|
<button
|
|
class="modal-close"
|
|
onclick="confirmClose()"
|
|
aria-label="Close"
|
|
>
|
|
✕
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p id="confirm-message" style="line-height: 1.6"></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn btn-ghost" onclick="confirmClose()">
|
|
Cancel
|
|
</button>
|
|
<button class="btn btn-danger" id="confirm-ok-btn">
|
|
Delete
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ═══ LOGIN MODAL ═══════════════════════════════════════════════════ -->
|
|
<div id="login-backdrop">
|
|
<div id="login-modal">
|
|
<div class="login-logo">
|
|
<svg
|
|
width="40"
|
|
height="40"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<rect x="2" y="3" width="20" height="14" rx="2" />
|
|
<path d="M8 21h8M12 17v4" />
|
|
</svg>
|
|
<h2>derez.ai Admin</h2>
|
|
<p>Sign in with your derez.ai account</p>
|
|
</div>
|
|
<div id="login-error"></div>
|
|
<div class="modal-body">
|
|
<div class="form-group">
|
|
<label>Email</label>
|
|
<input
|
|
type="email"
|
|
id="login-email"
|
|
autocomplete="email"
|
|
placeholder="you@example.com"
|
|
/>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Password</label>
|
|
<input
|
|
type="password"
|
|
id="login-password"
|
|
autocomplete="current-password"
|
|
placeholder="••••••••"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button
|
|
class="btn btn-primary"
|
|
style="width: 100%"
|
|
id="login-btn"
|
|
onclick="doSignIn()"
|
|
>
|
|
Sign In
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ═══ TOAST CONTAINER ════════════════════════════════════════════ -->
|
|
<div id="toast-container"></div>
|
|
|
|
<script src="app.js"></script>
|
|
</body>
|
|
</html>
|