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') %>