remove default_view
This commit is contained in:
parent
60790fc6fd
commit
060b79fef4
|
|
@ -3,7 +3,6 @@ import { requireAuth } from "./auth";
|
|||
import sql from "../db";
|
||||
|
||||
const Theme = t.Union([t.Literal("auto"), t.Literal("light"), t.Literal("dark")]);
|
||||
const Window = t.Union([t.Literal("24h"), t.Literal("7d"), t.Literal("30d"), t.Literal("90d")]);
|
||||
const DisplayMode = t.Union([t.Literal("compact"), t.Literal("expanded")]);
|
||||
const BarFrequency = t.Union([t.Literal("hourly"), t.Literal("daily")]);
|
||||
|
||||
|
|
@ -17,7 +16,6 @@ const StatusPageBody = t.Object({
|
|||
show_powered_by: t.Optional(t.Boolean()),
|
||||
show_response_time: t.Optional(t.Boolean()),
|
||||
show_cert_expiry: t.Optional(t.Boolean()),
|
||||
default_window: t.Optional(Window),
|
||||
display_mode: t.Optional(DisplayMode),
|
||||
bar_frequency: t.Optional(BarFrequency),
|
||||
bar_count: t.Optional(t.Number({ minimum: 1, maximum: 180 })),
|
||||
|
|
@ -118,7 +116,7 @@ export const statusPages = new Elysia({ prefix: "/pages" })
|
|||
|
||||
.get("/", async ({ accountId }) => {
|
||||
return sql`
|
||||
SELECT id, slug, title, description, theme, default_window, created_at, updated_at
|
||||
SELECT id, slug, title, description, theme, created_at, updated_at
|
||||
FROM status_pages
|
||||
WHERE account_id = ${accountId}
|
||||
ORDER BY created_at DESC
|
||||
|
|
@ -133,7 +131,7 @@ export const statusPages = new Elysia({ prefix: "/pages" })
|
|||
[row] = await sql`
|
||||
INSERT INTO status_pages (
|
||||
account_id, slug, title, description, theme, password_hash, index_search,
|
||||
show_powered_by, show_response_time, show_cert_expiry, default_window, display_mode,
|
||||
show_powered_by, show_response_time, show_cert_expiry, display_mode,
|
||||
bar_frequency, bar_count,
|
||||
custom_css, footer_text, og_image_url, analytics_html, auto_refresh_s
|
||||
)
|
||||
|
|
@ -141,7 +139,7 @@ export const statusPages = new Elysia({ prefix: "/pages" })
|
|||
${accountId}, ${body.slug}, ${body.title}, ${body.description ?? null},
|
||||
${body.theme ?? 'auto'}, ${password_hash}, ${body.index_search ?? true},
|
||||
${body.show_powered_by ?? true}, ${body.show_response_time ?? true},
|
||||
${body.show_cert_expiry ?? false}, ${body.default_window ?? '24h'}, ${body.display_mode ?? 'expanded'},
|
||||
${body.show_cert_expiry ?? false}, ${body.display_mode ?? 'expanded'},
|
||||
${body.bar_frequency ?? 'daily'}, ${body.bar_count ?? 90},
|
||||
${css}, ${body.footer_text ?? null}, ${body.og_image_url ?? null},
|
||||
${body.analytics_html ?? null}, ${body.auto_refresh_s ?? 60}
|
||||
|
|
@ -197,7 +195,6 @@ export const statusPages = new Elysia({ prefix: "/pages" })
|
|||
show_powered_by = COALESCE(${body.show_powered_by ?? null}, show_powered_by),
|
||||
show_response_time = COALESCE(${body.show_response_time ?? null}, show_response_time),
|
||||
show_cert_expiry = COALESCE(${body.show_cert_expiry ?? null}, show_cert_expiry),
|
||||
default_window = COALESCE(${body.default_window ?? null}, default_window),
|
||||
display_mode = COALESCE(${body.display_mode ?? null}, display_mode),
|
||||
bar_frequency = COALESCE(${body.bar_frequency ?? null}, bar_frequency),
|
||||
bar_count = COALESCE(${body.bar_count ?? null}, bar_count),
|
||||
|
|
|
|||
|
|
@ -130,7 +130,6 @@ export async function migrate(sql: any) {
|
|||
show_powered_by BOOLEAN NOT NULL DEFAULT true,
|
||||
show_response_time BOOLEAN NOT NULL DEFAULT true,
|
||||
show_cert_expiry BOOLEAN NOT NULL DEFAULT false,
|
||||
default_window TEXT NOT NULL DEFAULT '24h',
|
||||
display_mode TEXT NOT NULL DEFAULT 'expanded',
|
||||
bar_frequency TEXT NOT NULL DEFAULT 'daily',
|
||||
bar_count INTEGER NOT NULL DEFAULT 90,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ export interface StatusPageRow {
|
|||
show_powered_by: boolean;
|
||||
show_response_time:boolean;
|
||||
show_cert_expiry: boolean;
|
||||
default_window: Window;
|
||||
display_mode: "compact" | "expanded";
|
||||
bar_frequency: BucketType;
|
||||
bar_count: number;
|
||||
|
|
@ -56,7 +55,7 @@ export interface MonitorRow {
|
|||
// maintenance rather than an outage.
|
||||
current_state: "up" | "down" | "unknown" | "paused";
|
||||
region_states: Array<{ region: string; state: "up" | "down" | "unknown"; updated_at: string | null }>;
|
||||
uptime_pct: number | null; // for the page's default_window
|
||||
uptime_pct: number | null;
|
||||
uptime: MultiWindowUptime; // 24h / 7d / 30d / 90d row
|
||||
buckets: Array<{ start: string; total: number; up: number; avg_latency: number | null }>; // bar chart input
|
||||
avg_latency: number | null;
|
||||
|
|
@ -498,7 +497,7 @@ export async function loadMonitorDetail(slug: string, monitorId: string, window?
|
|||
`;
|
||||
if (!link) return null;
|
||||
|
||||
const win = (window ?? page.default_window) as Window;
|
||||
const win = (window ?? '24h') as Window;
|
||||
// Reuse the bulk loader with a single-monitor list - keeps the bucket/state
|
||||
// logic in one place. Cheap because we're querying for one ID. We also need
|
||||
// the page's groups so we can redact the monitor's group_id (UUID → public
|
||||
|
|
@ -571,7 +570,6 @@ export interface PublicPageView {
|
|||
show_powered_by: boolean;
|
||||
show_response_time: boolean;
|
||||
show_cert_expiry: boolean;
|
||||
default_window: Window;
|
||||
display_mode: "compact" | "expanded";
|
||||
bar_frequency: BucketType;
|
||||
bar_count: number;
|
||||
|
|
@ -611,7 +609,6 @@ function redactPageForPublic(p: StatusPageRow): PublicPageView {
|
|||
show_powered_by: p.show_powered_by,
|
||||
show_response_time: p.show_response_time,
|
||||
show_cert_expiry: p.show_cert_expiry,
|
||||
default_window: p.default_window,
|
||||
display_mode: p.display_mode,
|
||||
bar_frequency: p.bar_frequency,
|
||||
bar_count: p.bar_count,
|
||||
|
|
@ -648,7 +645,7 @@ function redactGroupsAndMonitors(
|
|||
export async function loadPagePayload(slug: string, window?: Window): Promise<PagePayload | null> {
|
||||
const page = await loadStatusPage(slug);
|
||||
if (!page) return null;
|
||||
const win = (window ?? page.default_window) as Window;
|
||||
const win = (window ?? '24h') as Window;
|
||||
const [rawGroups, rawMonitors, incidents] = await Promise.all([
|
||||
loadGroups(page.id),
|
||||
loadMonitors(page.id, win, page.display_mode, page.bar_frequency, page.bar_count),
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ async function renderJson(slug: string, request: Request, win?: Window): Promise
|
|||
// fall back to HTML scraping (which gets the password form, also a 401-ish
|
||||
// signal but more expensive to parse and less stable).
|
||||
if (!page || !isAuthorised(page, request)) return jsonNotFound();
|
||||
const cacheKey = `payload:${slug}:${win ?? page.default_window}`;
|
||||
const cacheKey = `payload:${slug}:${win ?? '24h'}`;
|
||||
const payload = await cached(cacheKey, 15, () => loadPagePayload(slug, win));
|
||||
if (!payload) return jsonNotFound();
|
||||
// Password-protected JSON must be private - same reasoning as renderHtml.
|
||||
|
|
|
|||
|
|
@ -207,8 +207,7 @@
|
|||
<span class="maintenance-pill" title="This service is paused for maintenance - checks are not running.">Maintenance</span>
|
||||
<% } else { %>
|
||||
<% if (page.show_response_time && m.avg_latency != null) { %><span><%= m.avg_latency %>ms</span><% } %>
|
||||
<% const winKey = page.default_window === '24h' ? 'd24' : page.default_window === '7d' ? 'd7' : page.default_window === '30d' ? 'd30' : 'd90'; %>
|
||||
<span class="uptime-pct <%= uptimeBand(u[winKey]) %>"><%= fmtUptime(u[winKey]) %></span>
|
||||
<span class="uptime-pct <%= uptimeBand(m.uptime_pct) %>"><%= fmtUptime(m.uptime_pct) %></span>
|
||||
<% } %>
|
||||
<svg class="chev" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"/></svg>
|
||||
</div>
|
||||
|
|
@ -286,7 +285,7 @@
|
|||
</main>
|
||||
|
||||
<div id="bar-tooltip" role="tooltip"></div>
|
||||
<script>window.PINGQL_PAGE = <%~ JSON.stringify({ slug: page.slug, default_window: page.default_window, bar_frequency: page.bar_frequency, show_response_time: !!page.show_response_time }) %>;</script>
|
||||
<script>window.PINGQL_PAGE = <%~ JSON.stringify({ slug: page.slug, bar_frequency: page.bar_frequency, show_response_time: !!page.show_response_time }) %>;</script>
|
||||
<script src="/_static/expand.js?v=<%= it.expandJsHash %>" defer></script>
|
||||
|
||||
<% if (page.auto_refresh_s > 0) { %>
|
||||
|
|
|
|||
|
|
@ -683,7 +683,7 @@ export const dashboard = new Elysia()
|
|||
const resolved = await getAccountId(cookie, headers);
|
||||
if (!resolved?.accountId) return redirect("/dashboard");
|
||||
const pages = await sql`
|
||||
SELECT id, slug, title, description, theme, default_window
|
||||
SELECT id, slug, title, description, theme
|
||||
FROM status_pages WHERE account_id = ${resolved.accountId}
|
||||
ORDER BY created_at DESC
|
||||
`;
|
||||
|
|
@ -734,7 +734,7 @@ export const dashboard = new Elysia()
|
|||
title: b.title,
|
||||
description: b.description || null,
|
||||
theme: b.theme || "auto",
|
||||
default_window: b.default_window || "24h",
|
||||
|
||||
display_mode: b.display_mode || "expanded",
|
||||
bar_frequency: b.bar_frequency || "daily",
|
||||
bar_count: Number(b.bar_count) || 90,
|
||||
|
|
@ -767,7 +767,6 @@ export const dashboard = new Elysia()
|
|||
title: b.title,
|
||||
description: b.description || null,
|
||||
theme: b.theme || "auto",
|
||||
default_window: b.default_window || "24h",
|
||||
display_mode: b.display_mode || "expanded",
|
||||
bar_frequency: b.bar_frequency || "daily",
|
||||
bar_count: Number(b.bar_count) || 90,
|
||||
|
|
|
|||
|
|
@ -294,7 +294,6 @@ Content-Type: application/json
|
|||
<tr><td>theme</td><td>string?</td><td><code>auto</code>, <code>light</code>, or <code>dark</code>. Default <code>auto</code>.</td></tr>
|
||||
<tr><td>password</td><td>string?</td><td>Plain text, hashed at write time. Pass <code>null</code> to clear.</td></tr>
|
||||
<tr><td>display_mode</td><td>string?</td><td><code>compact</code> or <code>expanded</code>. Default <code>expanded</code>.</td></tr>
|
||||
<tr><td>default_window</td><td>string?</td><td><code>24h</code>, <code>7d</code>, <code>30d</code>, or <code>90d</code>. Default <code>24h</code>.</td></tr>
|
||||
<tr><td>bar_frequency</td><td>string?</td><td><code>hourly</code> or <code>daily</code>. Default <code>daily</code>.</td></tr>
|
||||
<tr><td>bar_count</td><td>number?</td><td>How many bars to show (1-180). Default 90.</td></tr>
|
||||
<tr><td>auto_refresh_s</td><td>number?</td><td>Auto-refresh interval in seconds (10-3600). Default 60.</td></tr>
|
||||
|
|
|
|||
|
|
@ -61,14 +61,6 @@
|
|||
<% }) %>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="block text-sm text-gray-400 mb-1.5">Default window</label>
|
||||
<select name="default_window" class="w-full bg-surface-solid border border-border-subtle rounded-lg px-4 py-2.5 text-gray-100 focus:outline-none focus:border-blue-500">
|
||||
<% ['24h','7d','30d','90d'].forEach(function(w) { %>
|
||||
<option value="<%= w %>" <%= (p.default_window || '24h') === w ? 'selected' : '' %>><%= w %></option>
|
||||
<% }) %>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="block text-sm text-gray-400 mb-1.5">Display mode</label>
|
||||
<select name="display_mode" class="w-full bg-surface-solid border border-border-subtle rounded-lg px-4 py-2.5 text-gray-100 focus:outline-none focus:border-blue-500">
|
||||
|
|
|
|||
Loading…
Reference in New Issue