Files
2026-08-10 08:12:03 -03:00

8.1 KiB
Raw Permalink Blame History

admin.derez.ai — UI Reuse Guide

Stripped-down version: Servers page only. No Sales, no CRM, no API Keys.


1. UI Architecture (Single HTML File)

The entire front-end is a single-page app in a single index.html with:

File Role
index.html Full DOM layout: sidebar, sections, modals (login, confirm)
styles.css All styles: layout, sidebar, cards, tables, badges, modal, toast, server dashboard
app.js State, auth, API helpers, routing, all CRUD for each section

The pattern is straightforward — you can keep one file per section or keep it monolithic. The CSS and JS are written in vanilla ES6+ with no build step.


How it works

  1. User fills email + password in #login-modal (inside #login-backdrop).
  2. doSignIn() POSTs to the auth endpoint with { email, password }.
  3. The backend returns an object with a sessionid field.
  4. The session ID and email are saved in cookies:
    • al_session — the session token
    • al_email — the signed-in email

On page load

const _boot = getCookie("al_session");
if (_boot) {
  currentSession = _boot;
  currentEmail = getCookie("al_email") || "";
  showApp();          // hides login modal, shows sidebar
  loadData();         // loads your default section data
} else {
  showAuth();         // shows login modal
}
setCookie(name, value, days)   // SameSite=Strict
getCookie(name)
deleteCookie(name)

API fetch wrapper

async function apiFetch(url, options = {})
  • Automatically attaches X-Session-Id header from currentSession.
  • On HTTP 401, deletes cookies, clears local state, and reloads the page (back to login).

Sign out

function doSignOut()
  • Sends a DELETE to the auth endpoint with the session ID.
  • Deletes cookies (al_session, al_email).
  • Clears localStorage.
  • Shows the login screen again.

What you need to change for a new project

Constant / Variable Change to
const API_BASE (L2) Your backend base URL, e.g. "https://api.yourproject.com/webhook"
ROUTES.auth (L6) Your login endpoint path, e.g. "/auth/login"
Cookie names al_session / al_email Rename to avoid conflicts, e.g. "myapp_session"
apiFetch 401 handler Customize or keep (auto-redirects to login)

3. How Sections Work (Routing)

Sidebar navigation

Each sidebar item in index.html:

<div class="nav-item" data-section="servers"> ... Servers</div>

The click handler (L175239 in app.js):

  1. Reads el.dataset.section → e.g. "servers"
  2. Toggles .active class on the nav item
  3. Toggles .active class on #section-servers
  4. Sets the page title from a label map
  5. Shows the refresh button
  6. Lazy-loads data if empty

Corresponding section element

<div class="section" id="section-servers"> ... </div>

Only one .section has .active at a time.


4. Servers Page (Dashboard)

Data flow

serversLoadData()
  ├── GET https://n8n.derez.ai/webhook/server          ← seat list (fetched directly, no auth)
  │     Returns: [{ server: "hostname-01" }, ...]
  ├── For each server:
  │     GET apiUrl(ROUTES.servers) + "?server=<name>"   ← full dashboard (authenticated)
  │     Parses item.text (JSON string) or item directly
  │     Stores in serversData[]
  └── serversRenderTabs() + serversRenderDashboard(0)

Dashboard DOM structure

.section#section-servers
  ├── .card-header
  │     ├── Tab bar: .server-tabs / #server-tabs-strip
  │     └── Buttons (Update All, Harden All — optional)
  └── .card#server-dashboard
        ├── Summary card (name, OS, kernel, uptime, status badge)
        ├── KPI row (CPU, RAM, Disk, Security Score)
        ├── Performance bars (CPU, RAM, Disk usage)
        ├── Security checks (SSH, Seccomp, AppArmor, SELinux)
        ├── Exposed ports
        ├── Action advice (priority items, upgrades)
        └── Details: containers, packages, storage, Podman

Key data shape (serversData[i])

{
  server: {
    name: "hostname-01",
    os: "Ubuntu 22.04",
    kernel: "5.15.0-xxx",
    uptime: "42 days"
  },
  summary: {
    overall_status: "green" | "yellow" | "red"
  },
  performance: {
    cpu_idle_percent: 85.3,
    ram_percent: 62,
    ram_gb: 7.8,
    total_ram_gb: 16
  },
  storage: {
    total_gb: 256,
    used_gb: 120,
    percent: 47
  },
  kpis: {
    kpi_19_security_score: 72
  },
  security: {
    ssh_password_auth: false,
    ssh_root_login: false,
    seccomp_enabled: true,
    apparmor_enabled: true,
    selinux_enabled: false,
    firewall_exposed_services: ["22", "80", "443"]
  },
  action_advice: {
    priority_actions: [],
    upgrade_needed: true,
    ram_upgrade_recommended: false,
    container_cleanup_needed: false
  },
  containers: [ /* … */ ],
  packages: [ /* … */ ],
  podman: { /* … */ },
  seats: { server: "hostname-01", seat: 3 }
}

What you need to change for the servers page

Item Change to
Seat list URL (hardcoded https://n8n.derez.ai/webhook/server in serversLoadData) Your server list endpoint
ROUTES.servers (L10) Your server dashboard endpoint path
The item.text JSON parsing (L918) Adjust if your API shape differs
Dashboard widget content (render function L983+) Keep, expand, or trim as needed

5. What's Stripped: No Sales, No CRM, No Keys

The following have been removed from this consolidated doc — you should delete them from the HTML/CSS/JS when reusing:

index.html — Remove these sidebar nav items

  • <div class="nav-item" data-section="keys"> (L84100)
  • <div class="nav-item" data-section="crm"> (L112129)
  • <div class="nav-item" data-section="sales"> (L130147)

Also remove the corresponding .section elements:

  • section-keys (the div near L1060)
  • section-crm (the div near L1098)
  • section-sales (the div near L10981106)

app.js — Remove these functions & state

  • State: keysData (L22), crmRecords (L23), crmSortKey (L24), crmSortDir (L25)
  • Labels: keys, sales, crm entries from the label map (L192194)
  • Lazy-loads: the if (key === "keys") and if (key === "crm") blocks (L233237)
  • Functions: keysLoadRecords, keysRender, keysDelete (L13031398)
  • Functions: crmLoadRecords, crmRender, crmClearFilters, crmToggleSort, crmUpdateDeleteBtn, crmToggleAll, crmDeleteContact, crmDeleteSelected, crmSetStageSelected, crmOpenEdit, crmCloseEdit, crmSaveEdit (L14011823)

styles.css — Remove CRM-specific styles

  • .crm-filter-input and related rules (L824838+)
  • .crm-search-row th (L839842)

6. What You Keep (Optional Sections)

If you also want DNS, Instances, or Backup in your new project, their patterns are the same:

Section Endpoint Functions (in app.js) Section ID
DNS ROUTES.dns dnsLoadRecords, dnsRender, dnsDeleteRecord, dnsAddRecord #section-dns
Instances ROUTES.instances instancesLoadRecords, instancesRender, instancesCopySSH, instancesDelete, instancesOpenEdit, instancesCloseEdit, instancesSaveEdit #section-instances
Backup ROUTES.backup backupLoadRecords, backupRender, backupDelete #section-backup

Each follows the same lazy-load, render, CRUD pattern.


7. Quick Start for a New Project

  1. Copy index.html, styles.css, app.js to your project.
  2. In app.js:
    • Change API_BASE to your backend URL.
    • Change ROUTES entries to match your API paths.
    • Update the cookie names if desired.
    • Remove keys, crm, sales code (see §5).
  3. In index.html:
    • Remove keys, CRM, and Sales nav items and section elements.
    • Update the page title in <head>.
    • Update the brand text "derez.ai" in the sidebar.
  4. In styles.css:
    • Remove CRM-specific CSS.
  5. Update the server seat-list URL in serversLoadData() to your own endpoint.
  6. Serve from any static server — no build step required.