From e36c239000843b5524d5c3061e5c77a10238c61d Mon Sep 17 00:00:00 2001 From: M1 Date: Mon, 16 Mar 2026 15:14:26 +0400 Subject: [PATCH] refactor: ETA templating engine for dashboard, shared nav/head/foot partials --- apps/web/package.json | 1 + apps/web/src/routes/dashboard.ts | 34 +++- apps/web/src/views/detail.ejs | 273 +++++++++++++++++++++++++++ apps/web/src/views/home.ejs | 92 +++++++++ apps/web/src/views/new.ejs | 88 +++++++++ apps/web/src/views/partials/foot.ejs | 3 + apps/web/src/views/partials/head.ejs | 12 ++ apps/web/src/views/partials/nav.ejs | 16 ++ apps/web/src/views/settings.ejs | 215 +++++++++++++++++++++ 9 files changed, 724 insertions(+), 10 deletions(-) create mode 100644 apps/web/src/views/detail.ejs create mode 100644 apps/web/src/views/home.ejs create mode 100644 apps/web/src/views/new.ejs create mode 100644 apps/web/src/views/partials/foot.ejs create mode 100644 apps/web/src/views/partials/head.ejs create mode 100644 apps/web/src/views/partials/nav.ejs create mode 100644 apps/web/src/views/settings.ejs diff --git a/apps/web/package.json b/apps/web/package.json index 4271c9a..f308c0c 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -9,6 +9,7 @@ "dependencies": { "@elysiajs/cors": "^1.4.1", "elysia": "^1.4.27", + "eta": "^4.5.1", "postgres": "^3.4.8" }, "devDependencies": { diff --git a/apps/web/src/routes/dashboard.ts b/apps/web/src/routes/dashboard.ts index d25b55f..9747546 100644 --- a/apps/web/src/routes/dashboard.ts +++ b/apps/web/src/routes/dashboard.ts @@ -1,16 +1,30 @@ import { Elysia } from "elysia"; +import { Eta } from "eta"; import { resolve } from "path"; -const dir = resolve(import.meta.dir, "../dashboard"); +const eta = new Eta({ views: resolve(import.meta.dir, "../views"), cache: true, defaultExtension: ".ejs" }); -const hide = { detail: { hide: true } }; +function render(template: string, data: Record = {}) { + return new Response(eta.render(template, data), { + headers: { "content-type": "text/html; charset=utf-8" }, + }); +} + +// Static dashboard assets +const dashDir = resolve(import.meta.dir, "../dashboard"); export const dashboard = new Elysia() - .get("/dashboard/app.js", () => Bun.file(`${dir}/app.js`), hide) - .get("/dashboard/query-builder.js", () => Bun.file(`${dir}/query-builder.js`), hide) - .get("/dashboard", () => Bun.file(`${dir}/index.html`), hide) - .get("/dashboard/home", () => Bun.file(`${dir}/home.html`), hide) - .get("/dashboard/monitors/new", () => Bun.file(`${dir}/new.html`), hide) - .get("/dashboard/monitors/:id", () => Bun.file(`${dir}/detail.html`), hide) - .get("/dashboard/settings", () => Bun.file(`${dir}/settings.html`), hide) - .get("/docs", () => Bun.file(`${dir}/docs.html`), hide); + .get("/dashboard/app.js", () => Bun.file(`${dashDir}/app.js`)) + .get("/dashboard/query-builder.js",() => Bun.file(`${dashDir}/query-builder.js`)) + + // Auth / login page (static — no nav needed) + .get("/dashboard", () => Bun.file(`${dashDir}/index.html`)) + + // Rendered pages + .get("/dashboard/home", () => render("home", { nav: "monitors" })) + .get("/dashboard/settings", () => render("settings", { nav: "settings" })) + .get("/dashboard/monitors/new", () => render("new", { nav: "monitors" })) + .get("/dashboard/monitors/:id", () => render("detail", { nav: "monitors" })) + + // Docs (static) + .get("/docs", () => Bun.file(`${dashDir}/docs.html`)); diff --git a/apps/web/src/views/detail.ejs b/apps/web/src/views/detail.ejs new file mode 100644 index 0000000..2f0ce85 --- /dev/null +++ b/apps/web/src/views/detail.ejs @@ -0,0 +1,273 @@ +<%~ include('./partials/head', { title: 'Monitor' }) %> +<%~ include('./partials/nav', { nav: 'monitors' }) %> + +
+
+ ← Back +
+ +
Loading...
+ +
+ + + +<%~ include('./partials/foot') %> diff --git a/apps/web/src/views/home.ejs b/apps/web/src/views/home.ejs new file mode 100644 index 0000000..d9dc8da --- /dev/null +++ b/apps/web/src/views/home.ejs @@ -0,0 +1,92 @@ +<%~ include('./partials/head', { title: 'Monitors' }) %> +<%~ include('./partials/nav', { nav: 'monitors' }) %> + + +
+
+

Monitors

+
+
+ + New +
+
+ +
+
Loading...
+
+ + +
+ + + +<%~ include('./partials/foot') %> diff --git a/apps/web/src/views/new.ejs b/apps/web/src/views/new.ejs new file mode 100644 index 0000000..9ca2044 --- /dev/null +++ b/apps/web/src/views/new.ejs @@ -0,0 +1,88 @@ +<%~ include('./partials/head', { title: 'New Monitor' }) %> +<%~ include('./partials/nav', { nav: 'monitors' }) %> + +
+
+ ← Back to monitors +

Create Monitor

+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +

Define when this monitor should be considered "up". Defaults to status < 400.

+
+
+ + + + +
+
+ + + +<%~ include('./partials/foot') %> diff --git a/apps/web/src/views/partials/foot.ejs b/apps/web/src/views/partials/foot.ejs new file mode 100644 index 0000000..b5a9857 --- /dev/null +++ b/apps/web/src/views/partials/foot.ejs @@ -0,0 +1,3 @@ + + + diff --git a/apps/web/src/views/partials/head.ejs b/apps/web/src/views/partials/head.ejs new file mode 100644 index 0000000..8431094 --- /dev/null +++ b/apps/web/src/views/partials/head.ejs @@ -0,0 +1,12 @@ + + + + + + PingQL<%= it.title ? ` — ${it.title}` : '' %> + + + + diff --git a/apps/web/src/views/partials/nav.ejs b/apps/web/src/views/partials/nav.ejs new file mode 100644 index 0000000..9a3167f --- /dev/null +++ b/apps/web/src/views/partials/nav.ejs @@ -0,0 +1,16 @@ + diff --git a/apps/web/src/views/settings.ejs b/apps/web/src/views/settings.ejs new file mode 100644 index 0000000..bb8c896 --- /dev/null +++ b/apps/web/src/views/settings.ejs @@ -0,0 +1,215 @@ +<%~ include('./partials/head', { title: 'Settings' }) %> +<%~ include('./partials/nav', { nav: 'settings' }) %> + +
+ +

Settings

+ + +
+

Account

+
+
+ +
+ + +
+
+
+ +

+
+
+
+ + +
+

Recovery Email

+

Used for account recovery only. Stored as a one-way hash — we can't read it.

+
+ + + +
+ +
+ + +
+

Rotate Primary Key

+

Generates a new primary key. Your old key will stop working immediately. Sub-keys are not affected.

+ +
+ + +
+
+
+

API Keys

+

Create separate keys for different apps, scripts, or teammates.

+
+ +
+ + + + + + + + +
+

No API keys yet.

+
+
+ +
+ + + + +<%~ include('./partials/foot') %>