docs: publish Preview 19 dogfood evidence

Export the reviewed allowlisted snapshot from private source commit 05928cebd01b586cf9e9d4b8c8537a7605a6068c. This records the exact candidate, bounded capacity result, stateful migration scratch requirement, authenticated batch identity proof, and immediate live acceptance evidence.

AI-Assisted: OpenAI Codex
Signed-off-by: Cole Speelman <crspeelman@gmail.com>
This commit is contained in:
2026-08-18 21:47:08 -04:00
commit 92a66db3df
201 changed files with 38227 additions and 0 deletions
+126
View File
@@ -0,0 +1,126 @@
<?sando go
package site
func App(view AppView)
?>
<?# SPDX-License-Identifier: AGPL-3.0-only ?>
<!doctype html>
<html lang="en">
<head><?~ Head(view.Head) ?></head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<?~ SiteHeader(true, "overview", view.Organization.ID) ?>
<main id="main">
<section class="app-intro" aria-labelledby="overview-title">
<div><p class="eyebrow">Organization overview</p><h1 id="overview-title"><?= view.Organization.Name ?></h1><p>Welcome, <?= view.DisplayName ?>. Last refreshed <?= view.RefreshedAt ?>.</p></div>
<form class="logout" method="post" action="/logout/">
<input type="hidden" name="csrf_token" value="<?= view.CSRFToken ?>">
<button class="secondary" type="submit">Sign out</button>
</form>
</section>
<? if len(view.Organizations) > 1 { ?>
<nav class="organization-nav" aria-label="Organizations">
<span>Organization:</span>
<? for _, organization := range view.Organizations { ?>
<? if organization.Selected { ?>
<a href="/app/?organization=<?= organization.ID ?>" aria-current="page"><?= organization.Name ?></a>
<? } else { ?>
<a href="/app/?organization=<?= organization.ID ?>"><?= organization.Name ?></a>
<? } ?>
<? } ?>
</nav>
<? } ?>
<? if view.PendingBatches > 0 { ?>
<aside class="live-status" role="status">
<p><strong>Durable evidence is still being indexed.</strong> Accepted batches safely stored: <?= view.PendingBatches ?>. Recent queries may lag by <?= view.ProjectionLag ?>.</p>
</aside>
<? } ?>
<aside class="live-status" data-events-url="<?= view.EventsURL ?>" hidden>
<p><strong>New observations are available.</strong> <a href="/app/?organization=<?= view.Organization.ID ?>">Refresh this overview</a>.</p>
</aside>
<section class="signal-grid" aria-label="Recent telemetry">
<? for _, signal := range view.Signals { ?>
<article class="signal-card" id="<?= signal.ID ?>">
<p class="eyebrow"><?= signal.Name ?></p>
<h2>Recent <?= signal.Name ?></h2>
<p><?= signal.Description ?></p>
<details><summary>Query</summary><pre><code><?= signal.Query ?></code></pre></details>
<?~ ResultTable(signal.Table) ?>
</article>
<? } ?>
</section>
<section class="section-grid" aria-labelledby="saved-work">
<div><p class="eyebrow">Saved work</p><h2 id="saved-work">Queries and dashboards</h2></div>
<div class="saved-grid">
<section aria-labelledby="saved-queries"><h3 id="saved-queries">Saved queries</h3>
<? if len(view.SavedQueries) == 0 { ?><p>No saved queries yet.</p><? } ?>
<? for _, item := range view.SavedQueries { ?><article><h4><?= item.Name ?></h4><p><?= item.Description ?></p><pre><code><?= item.Query ?></code></pre></article><? } ?>
</section>
<section aria-labelledby="dashboards"><h3 id="dashboards">Dashboards</h3>
<? if len(view.Dashboards) == 0 { ?><p>No dashboards yet.</p><? } ?>
<? for _, item := range view.Dashboards { ?><article><h4><a href="/app/dashboards/<?= item.Slug ?>/?organization=<?= view.Organization.ID ?>"><?= item.Name ?></a></h4><p><?= item.Description ?></p><p><?= item.PanelCount ?> panels</p></article><? } ?>
</section>
</div>
</section>
<section class="section-grid" aria-labelledby="incident-work">
<div><p class="eyebrow">Incident response</p><h2 id="incident-work">Attention without noise</h2></div>
<div><p><?= view.OpenIncidents ?> open incidents are visible in the authorized inbox. Alert rules execute the same bounded saved-query AST used everywhere else.</p><p><a class="button secondary" href="<?= view.IncidentsURL ?>">Open incident inbox</a></p></div>
</section>
<? if view.CanManage { ?>
<section class="section-grid" aria-labelledby="manage-work">
<div><p class="eyebrow">Organization workshop</p><h2 id="manage-work">Save a reusable view</h2><p>Assisted controls and typed text enter the same parser and versioned AST. Every form is an ordinary server request; nothing is generated or executed on page load.</p></div>
<div class="editor-grid">
<form class="editor-card builder-card" method="post" action="/app/queries/builder/">
<h3>Build a query</h3>
<p>Choose one bounded evidence source, an optional filter, and an optional summary. The saved result remains ordinary reviewable query text.</p>
<input type="hidden" name="organization_id" value="<?= view.Organization.ID ?>">
<input type="hidden" name="csrf_token" value="<?= view.ManageCSRF ?>">
<div class="field-grid">
<div><label for="builder-name">Name</label><input id="builder-name" name="name" required maxlength="128"></div>
<div><label for="builder-description">Description</label><textarea id="builder-description" name="description" required maxlength="1024"></textarea></div>
<div><label for="builder-signal">Evidence</label><select id="builder-signal" name="signal" required><option value="logs">Logs</option><option value="metrics">Metrics</option><option value="traces">Traces</option><option value="deployments">Deployments</option></select></div>
<div><label for="builder-window">Lookback</label><select id="builder-window" name="window" required><option value="15m">15 minutes</option><option value="1h" selected>1 hour</option><option value="6h">6 hours</option><option value="24h">24 hours</option><option value="168h">7 days</option></select></div>
<div><label for="builder-filter-field">Filter field <span class="optional">(optional)</span></label><select id="builder-filter-field" name="filter_field"><option value="">No filter</option><option value="service">Service</option><option value="project">Project</option><option value="environment">Environment</option><option value="route">HTTP route</option><option value="status">HTTP status</option><option value="duration">Duration</option><option value="name">Name</option><option value="severity">Severity</option><option value="value">Metric value</option><option value="trace_id">Trace ID</option><option value="correlation_id">Correlation ID</option></select></div>
<div><label for="builder-filter-operator">Filter comparison</label><select id="builder-filter-operator" name="filter_operator" required><option value="==">equals</option><option value="!=">does not equal</option><option value=">=">at least</option><option value="&lt;=">at most</option><option value=">">greater than</option><option value="&lt;">less than</option></select></div>
<div><label for="builder-filter-value">Filter value <span class="optional">(optional)</span></label><input id="builder-filter-value" name="filter_value" maxlength="256"></div>
<div><label for="builder-aggregate">Summary</label><select id="builder-aggregate" name="aggregate" required><option value="none">No summary</option><option value="count">Count</option><option value="min">Minimum</option><option value="max">Maximum</option><option value="sum">Sum</option><option value="avg">Average</option><option value="p50">50th percentile</option><option value="p95">95th percentile</option><option value="p99">99th percentile</option></select></div>
<div><label for="builder-aggregate-field">Numeric summary field <span class="optional">(not used by count)</span></label><select id="builder-aggregate-field" name="aggregate_field"><option value="">No field</option><option value="value">Metric value</option><option value="duration">Duration</option><option value="status">HTTP status</option></select></div>
<div><label for="builder-group">Group by <span class="optional">(optional)</span></label><select id="builder-group" name="group_by"><option value="">No grouping</option><option value="service">Service</option><option value="project">Project</option><option value="environment">Environment</option><option value="route">HTTP route</option><option value="status">HTTP status</option><option value="name">Name</option><option value="severity">Severity</option></select></div>
<div><label for="builder-bucket">Time bucket <span class="optional">(optional)</span></label><select id="builder-bucket" name="bucket"><option value="">No time bucket</option><option value="1m">1 minute</option><option value="5m">5 minutes</option><option value="15m">15 minutes</option><option value="1h">1 hour</option></select></div>
<div><label for="builder-limit">Maximum rows</label><select id="builder-limit" name="limit" required><option value="10">10</option><option value="20">20</option><option value="50" selected>50</option><option value="100">100</option><option value="250">250</option></select></div>
</div>
<button type="submit">Build and save query</button>
</form>
<form class="editor-card" method="post" action="/app/queries/">
<h3>Write a query</h3>
<input type="hidden" name="organization_id" value="<?= view.Organization.ID ?>">
<input type="hidden" name="csrf_token" value="<?= view.ManageCSRF ?>">
<label for="query-name">Name</label><input id="query-name" name="name" required maxlength="128">
<label for="query-description">Description</label><textarea id="query-description" name="description" required maxlength="1024"></textarea>
<label for="query-text">Typed query</label><textarea id="query-text" name="query" required maxlength="16384">logs | window 1h | limit 50</textarea>
<button type="submit">Save query</button>
</form>
<form class="editor-card" method="post" action="/app/dashboards/">
<h3>Create a one-panel dashboard</h3>
<input type="hidden" name="organization_id" value="<?= view.Organization.ID ?>">
<input type="hidden" name="csrf_token" value="<?= view.ManageCSRF ?>">
<label for="dashboard-slug">URL slug</label><input id="dashboard-slug" name="slug" required maxlength="63" pattern="[a-z][a-z0-9-]+">
<label for="dashboard-name">Name</label><input id="dashboard-name" name="name" required maxlength="128">
<label for="dashboard-description">Description</label><textarea id="dashboard-description" name="description" required maxlength="1024"></textarea>
<label for="panel-title">Panel title</label><input id="panel-title" name="panel_title" required maxlength="128">
<label for="saved-query">Saved query</label>
<select id="saved-query" name="saved_query_id" required>
<option value="">Choose a saved query</option>
<? for _, item := range view.SavedQueries { ?><option value="<?= item.ID ?>"><?= item.Name ?></option><? } ?>
</select>
<label for="visualization">Presentation</label>
<select id="visualization" name="visualization" required><option value="table">Table</option><option value="stat">Single statistic with table</option><option value="timeseries">Time series table</option></select>
<? if len(view.SavedQueries) == 0 { ?><button type="submit" disabled>Create dashboard</button><? } else { ?><button type="submit">Create dashboard</button><? } ?>
</form>
</div>
</section>
<? } ?>
</main>
<?~ SiteFooter() ?>
</body>
</html>
+497
View File
@@ -0,0 +1,497 @@
// Code generated by himesan; DO NOT EDIT.
// himesan:compiler v1.0.0-beta.2
// himesan:runtime-abi sando.v1
// himesan:source-sha256 ab6403781ccb2a659b749730243555dcb8a3f319720ad6a972252eb30847c5f4
package site
import (
__himesan_context "context"
__himesan_sando "gamertan.com/sandwich-hime/sando"
__himesan_io "io"
)
var _ = __himesan_sando.ABISandoV1
func App(view AppView) __himesan_sando.Component {
return __himesan_sando.ComponentFunc(func(__himesan_render_context __himesan_context.Context, __himesan_writer __himesan_io.Writer) error {
_ = __himesan_render_context
//line internal/site/app.sando:5:3
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:6:46
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n<!doctype html>\n<html lang=\"en\">\n<head>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:9:11
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (Head(view.Head))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:9:29
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</head>\n<body>\n <a class=\"skip-link\" href=\"#main\">Skip to content</a>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:12:7
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteHeader(true, "overview", view.Organization.ID))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:12:60
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <main id=\"main\">\n <section class=\"app-intro\" aria-labelledby=\"overview-title\">\n <div><p class=\"eyebrow\">Organization overview</p><h1 id=\"overview-title\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:15:84
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.Organization.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:15:109
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</h1><p>Welcome, "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:15:130
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.DisplayName)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:15:149
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, ". Last refreshed "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:15:170
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.RefreshedAt)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:15:189
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, ".</p></div>\n <form class=\"logout\" method=\"post\" action=\"/logout/\">\n <input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:17:59
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.CSRFToken)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:17:76
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <button class=\"secondary\" type=\"submit\">Sign out</button>\n </form>\n </section>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:21:8
if len(view.Organizations) > 1 {
//line internal/site/app.sando:21:43
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <nav class=\"organization-nav\" aria-label=\"Organizations\">\n <span>Organization:</span>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:24:10
for _, organization := range view.Organizations {
//line internal/site/app.sando:24:62
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:25:12
if organization.Selected {
//line internal/site/app.sando:25:41
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <a href=\"/app/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:26:43
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:26:61
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" aria-current=\"page\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:26:87
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (organization.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:26:107
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</a>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:27:12
} else {
//line internal/site/app.sando:27:23
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <a href=\"/app/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:28:43
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:28:61
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:28:67
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (organization.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:28:87
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</a>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:29:12
}
//line internal/site/app.sando:29:16
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:30:10
}
//line internal/site/app.sando:30:14
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </nav>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:32:8
}
//line internal/site/app.sando:32:12
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:33:8
if view.PendingBatches > 0 {
//line internal/site/app.sando:33:39
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <aside class=\"live-status\" role=\"status\">\n <p><strong>Durable evidence is still being indexed.</strong> Accepted batches safely stored: "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:35:104
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.PendingBatches)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:35:126
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, ". Recent queries may lag by "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:35:158
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.ProjectionLag)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:35:179
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, ".</p>\n </aside>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:37:8
}
//line internal/site/app.sando:37:12
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <aside class=\"live-status\" data-events-url=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:38:53
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.EventsURL)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:38:70
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" hidden>\n <p><strong>New observations are available.</strong> <a href=\"/app/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:39:91
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:39:114
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Refresh this overview</a>.</p>\n </aside>\n <section class=\"signal-grid\" aria-label=\"Recent telemetry\">\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:42:8
for _, signal := range view.Signals {
//line internal/site/app.sando:42:48
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <article class=\"signal-card\" id=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:43:44
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (signal.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:43:56
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <p class=\"eyebrow\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:44:32
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (signal.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:44:46
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p>\n <h2>Recent "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:45:24
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (signal.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:45:38
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</h2>\n <p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:46:16
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (signal.Description)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:46:37
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p>\n <details><summary>Query</summary><pre><code>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:47:57
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (signal.Query)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:47:72
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</code></pre></details>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:48:13
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (ResultTable(signal.Table))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:48:41
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </article>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:50:8
}
//line internal/site/app.sando:50:12
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </section>\n <section class=\"section-grid\" aria-labelledby=\"saved-work\">\n <div><p class=\"eyebrow\">Saved work</p><h2 id=\"saved-work\">Queries and dashboards</h2></div>\n <div class=\"saved-grid\">\n <section aria-labelledby=\"saved-queries\"><h3 id=\"saved-queries\">Saved queries</h3>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:56:12
if len(view.SavedQueries) == 0 {
//line internal/site/app.sando:56:47
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<p>No saved queries yet.</p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:56:78
}
//line internal/site/app.sando:56:82
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:57:12
for _, item := range view.SavedQueries {
//line internal/site/app.sando:57:55
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<article><h4>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:57:72
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (item.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:57:84
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</h4><p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:57:96
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (item.Description)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:57:115
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p><pre><code>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:57:134
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (item.Query)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:57:147
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</code></pre></article>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:57:173
}
//line internal/site/app.sando:57:177
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </section>\n <section aria-labelledby=\"dashboards\"><h3 id=\"dashboards\">Dashboards</h3>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:60:12
if len(view.Dashboards) == 0 {
//line internal/site/app.sando:60:45
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<p>No dashboards yet.</p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:60:73
}
//line internal/site/app.sando:60:77
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:61:12
for _, item := range view.Dashboards {
//line internal/site/app.sando:61:53
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<article><h4><a href=\"/app/dashboards/"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:61:95
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (item.Slug)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:61:107
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:61:126
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:61:149
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:61:155
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (item.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:61:167
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</a></h4><p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:61:183
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (item.Description)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:61:202
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p><p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:61:213
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (item.PanelCount)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:61:231
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, " panels</p></article>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:61:255
}
//line internal/site/app.sando:61:259
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </section>\n </div>\n </section>\n <section class=\"section-grid\" aria-labelledby=\"incident-work\">\n <div><p class=\"eyebrow\">Incident response</p><h2 id=\"incident-work\">Attention without noise</h2></div>\n <div><p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:67:19
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.OpenIncidents)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:67:40
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, " open incidents are visible in the authorized inbox. Alert rules execute the same bounded saved-query AST used everywhere else.</p><p><a class=\"button secondary\" href=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:67:212
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.IncidentsURL)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:67:232
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Open incident inbox</a></p></div>\n </section>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:69:8
if view.CanManage {
//line internal/site/app.sando:69:30
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <section class=\"section-grid\" aria-labelledby=\"manage-work\">\n <div><p class=\"eyebrow\">Organization workshop</p><h2 id=\"manage-work\">Save a reusable view</h2><p>Assisted controls and typed text enter the same parser and versioned AST. Every form is an ordinary server request; nothing is generated or executed on page load.</p></div>\n <div class=\"editor-grid\">\n <form class=\"editor-card builder-card\" method=\"post\" action=\"/app/queries/builder/\">\n <h3>Build a query</h3>\n <p>Choose one bounded evidence source, an optional filter, and an optional summary. The saved result remains ordinary reviewable query text.</p>\n <input type=\"hidden\" name=\"organization_id\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:76:66
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:76:89
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:77:61
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.ManageCSRF)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:77:79
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <div class=\"field-grid\">\n <div><label for=\"builder-name\">Name</label><input id=\"builder-name\" name=\"name\" required maxlength=\"128\"></div>\n <div><label for=\"builder-description\">Description</label><textarea id=\"builder-description\" name=\"description\" required maxlength=\"1024\"></textarea></div>\n <div><label for=\"builder-signal\">Evidence</label><select id=\"builder-signal\" name=\"signal\" required><option value=\"logs\">Logs</option><option value=\"metrics\">Metrics</option><option value=\"traces\">Traces</option><option value=\"deployments\">Deployments</option></select></div>\n <div><label for=\"builder-window\">Lookback</label><select id=\"builder-window\" name=\"window\" required><option value=\"15m\">15 minutes</option><option value=\"1h\" selected>1 hour</option><option value=\"6h\">6 hours</option><option value=\"24h\">24 hours</option><option value=\"168h\">7 days</option></select></div>\n <div><label for=\"builder-filter-field\">Filter field <span class=\"optional\">(optional)</span></label><select id=\"builder-filter-field\" name=\"filter_field\"><option value=\"\">No filter</option><option value=\"service\">Service</option><option value=\"project\">Project</option><option value=\"environment\">Environment</option><option value=\"route\">HTTP route</option><option value=\"status\">HTTP status</option><option value=\"duration\">Duration</option><option value=\"name\">Name</option><option value=\"severity\">Severity</option><option value=\"value\">Metric value</option><option value=\"trace_id\">Trace ID</option><option value=\"correlation_id\">Correlation ID</option></select></div>\n <div><label for=\"builder-filter-operator\">Filter comparison</label><select id=\"builder-filter-operator\" name=\"filter_operator\" required><option value=\"==\">equals</option><option value=\"!=\">does not equal</option><option value=\">=\">at least</option><option value=\"&lt;=\">at most</option><option value=\">\">greater than</option><option value=\"&lt;\">less than</option></select></div>\n <div><label for=\"builder-filter-value\">Filter value <span class=\"optional\">(optional)</span></label><input id=\"builder-filter-value\" name=\"filter_value\" maxlength=\"256\"></div>\n <div><label for=\"builder-aggregate\">Summary</label><select id=\"builder-aggregate\" name=\"aggregate\" required><option value=\"none\">No summary</option><option value=\"count\">Count</option><option value=\"min\">Minimum</option><option value=\"max\">Maximum</option><option value=\"sum\">Sum</option><option value=\"avg\">Average</option><option value=\"p50\">50th percentile</option><option value=\"p95\">95th percentile</option><option value=\"p99\">99th percentile</option></select></div>\n <div><label for=\"builder-aggregate-field\">Numeric summary field <span class=\"optional\">(not used by count)</span></label><select id=\"builder-aggregate-field\" name=\"aggregate_field\"><option value=\"\">No field</option><option value=\"value\">Metric value</option><option value=\"duration\">Duration</option><option value=\"status\">HTTP status</option></select></div>\n <div><label for=\"builder-group\">Group by <span class=\"optional\">(optional)</span></label><select id=\"builder-group\" name=\"group_by\"><option value=\"\">No grouping</option><option value=\"service\">Service</option><option value=\"project\">Project</option><option value=\"environment\">Environment</option><option value=\"route\">HTTP route</option><option value=\"status\">HTTP status</option><option value=\"name\">Name</option><option value=\"severity\">Severity</option></select></div>\n <div><label for=\"builder-bucket\">Time bucket <span class=\"optional\">(optional)</span></label><select id=\"builder-bucket\" name=\"bucket\"><option value=\"\">No time bucket</option><option value=\"1m\">1 minute</option><option value=\"5m\">5 minutes</option><option value=\"15m\">15 minutes</option><option value=\"1h\">1 hour</option></select></div>\n <div><label for=\"builder-limit\">Maximum rows</label><select id=\"builder-limit\" name=\"limit\" required><option value=\"10\">10</option><option value=\"20\">20</option><option value=\"50\" selected>50</option><option value=\"100\">100</option><option value=\"250\">250</option></select></div>\n </div>\n <button type=\"submit\">Build and save query</button>\n </form>\n <form class=\"editor-card\" method=\"post\" action=\"/app/queries/\">\n <h3>Write a query</h3>\n <input type=\"hidden\" name=\"organization_id\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:96:66
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:96:89
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:97:61
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.ManageCSRF)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:97:79
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <label for=\"query-name\">Name</label><input id=\"query-name\" name=\"name\" required maxlength=\"128\">\n <label for=\"query-description\">Description</label><textarea id=\"query-description\" name=\"description\" required maxlength=\"1024\"></textarea>\n <label for=\"query-text\">Typed query</label><textarea id=\"query-text\" name=\"query\" required maxlength=\"16384\">logs | window 1h | limit 50</textarea>\n <button type=\"submit\">Save query</button>\n </form>\n <form class=\"editor-card\" method=\"post\" action=\"/app/dashboards/\">\n <h3>Create a one-panel dashboard</h3>\n <input type=\"hidden\" name=\"organization_id\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:105:66
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:105:89
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:106:61
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.ManageCSRF)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:106:79
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <label for=\"dashboard-slug\">URL slug</label><input id=\"dashboard-slug\" name=\"slug\" required maxlength=\"63\" pattern=\"[a-z][a-z0-9-]+\">\n <label for=\"dashboard-name\">Name</label><input id=\"dashboard-name\" name=\"name\" required maxlength=\"128\">\n <label for=\"dashboard-description\">Description</label><textarea id=\"dashboard-description\" name=\"description\" required maxlength=\"1024\"></textarea>\n <label for=\"panel-title\">Panel title</label><input id=\"panel-title\" name=\"panel_title\" required maxlength=\"128\">\n <label for=\"saved-query\">Saved query</label>\n <select id=\"saved-query\" name=\"saved_query_id\" required>\n <option value=\"\">Choose a saved query</option>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:114:16
for _, item := range view.SavedQueries {
//line internal/site/app.sando:114:59
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<option value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:114:78
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (item.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:114:88
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:114:94
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (item.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:114:106
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</option>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:114:118
}
//line internal/site/app.sando:114:122
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </select>\n <label for=\"visualization\">Presentation</label>\n <select id=\"visualization\" name=\"visualization\" required><option value=\"table\">Table</option><option value=\"stat\">Single statistic with table</option><option value=\"timeseries\">Time series table</option></select>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:118:14
if len(view.SavedQueries) == 0 {
//line internal/site/app.sando:118:49
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<button type=\"submit\" disabled>Create dashboard</button>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:118:108
} else {
//line internal/site/app.sando:118:119
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<button type=\"submit\">Create dashboard</button>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:118:169
}
//line internal/site/app.sando:118:173
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </form>\n </div>\n </section>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:122:8
}
//line internal/site/app.sando:122:12
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </main>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:124:7
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteFooter())); __himesan_error != nil {
return __himesan_error
}
//line internal/site/app.sando:124:22
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n</body>\n</html>\n"); __himesan_error != nil {
return __himesan_error
}
return nil
})
}
+49
View File
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Package site contains Observatory's typed Sandwich Hime interface and its
// immutable browser assets. HTTP policy remains owned by internal/httpserver.
package site
import (
"crypto/sha256"
_ "embed"
"encoding/hex"
)
//go:embed assets/site.css
var style []byte
//go:embed assets/site.js
var script []byte
//go:embed assets/observatory.svg
var icon []byte
type Assets struct {
StylePath string
ScriptPath string
IconPath string
}
func AssetPaths() Assets {
return Assets{StylePath: fingerprintedPath("site", "css", style), ScriptPath: fingerprintedPath("site", "js", script), IconPath: fingerprintedPath("observatory", "svg", icon)}
}
func Asset(path string) (body []byte, contentType string, ok bool) {
assets := AssetPaths()
switch path {
case assets.StylePath:
return style, "text/css; charset=utf-8", true
case assets.ScriptPath:
return script, "text/javascript; charset=utf-8", true
case assets.IconPath:
return icon, "image/svg+xml", true
default:
return nil, "", false
}
}
func fingerprintedPath(name, extension string, body []byte) string {
digest := sha256.Sum256(body)
return "/assets/" + name + "-" + hex.EncodeToString(digest[:8]) + "." + extension
}
+12
View File
@@ -0,0 +1,12 @@
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" role="img" aria-labelledby="title description">
<title id="title">Gamertan Observatory</title>
<desc id="description">Three calm observation rings around one bright point.</desc>
<rect width="512" height="512" rx="96" fill="#111715"/>
<g fill="none" stroke="#b5e3c5" stroke-width="24">
<circle cx="256" cy="256" r="168"/>
<ellipse cx="256" cy="256" rx="168" ry="72"/>
<ellipse cx="256" cy="256" rx="72" ry="168"/>
</g>
<circle cx="256" cy="256" r="28" fill="#f7c873"/>
</svg>

After

Width:  |  Height:  |  Size: 610 B

+37
View File
@@ -0,0 +1,37 @@
/* SPDX-License-Identifier: AGPL-3.0-only */
:root{color-scheme:dark;--ink:#f6f0e2;--muted:#bfb8aa;--paper:#111715;--panel:#18221f;--line:#4f665e;--accent:#b5e3c5;--focus:#f7c873;font:100%/1.6 system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}
*{box-sizing:border-box}
html{background:var(--paper);color:var(--ink)}
body{margin:0;min-width:18rem}
a{color:var(--accent);text-underline-offset:.2em}
a:hover{text-decoration-thickness:.16em}
button,input,select,textarea{font:inherit}
button,.button{display:inline-block;border:.12rem solid var(--ink);border-radius:.2rem;background:var(--ink);color:var(--paper);padding:.65rem 1rem;font-weight:700;text-decoration:none;cursor:pointer}
button.secondary,.secondary{background:transparent;color:var(--ink)}
:focus-visible{outline:.2rem solid var(--focus);outline-offset:.2rem}
.skip-link{position:absolute;left:1rem;top:-8rem;background:var(--ink);color:var(--paper);padding:.6rem;z-index:10}.skip-link:focus{top:1rem}
.site-header,.site-footer,main{width:min(92rem,100%);margin-inline:auto;padding-inline:clamp(1rem,4vw,3rem)}
.site-header{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding-block:1.25rem;border-bottom:.08rem solid var(--line)}
.site-header nav{display:flex;gap:1rem}.wordmark{color:var(--ink);font-weight:800;text-decoration:none;letter-spacing:.02em}
.site-footer{margin-top:4rem;padding-block:2rem;border-top:.08rem solid var(--line);color:var(--muted)}
.hero{padding-block:clamp(4rem,12vw,9rem);max-width:72rem}.hero h1{font-size:clamp(3rem,10vw,8rem);line-height:.9;letter-spacing:-.055em;max-width:11ch;margin:.15em 0}.lede{font-size:clamp(1.15rem,2vw,1.5rem);max-width:48rem;color:var(--muted)}
.eyebrow{text-transform:uppercase;letter-spacing:.14em;font-size:.78rem;font-weight:800;color:var(--accent)}
.section-grid{display:grid;grid-template-columns:minmax(14rem,1fr) minmax(0,2fr);gap:clamp(2rem,6vw,7rem);padding-block:clamp(3rem,7vw,6rem);border-top:.08rem solid var(--line)}
h1,h2,h3,h4{line-height:1.1;text-wrap:balance}h2{font-size:clamp(2rem,5vw,4.5rem);margin:.15em 0}h3{font-size:1.4rem}.prose{max-width:52rem}.cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1rem}.cards article,.auth-card,.signal-card,.saved-grid>section,.live-status{background:var(--panel);border:.08rem solid var(--line);padding:clamp(1rem,3vw,2rem)}
.auth-shell{min-height:70vh;display:grid;place-items:center}.auth-card{width:min(34rem,100%);margin-block:4rem}.auth-card h1{font-size:clamp(2.3rem,8vw,4rem)}
form{display:grid;gap:.55rem}label{font-weight:700;margin-top:.6rem}input,select,textarea{width:100%;border:.1rem solid var(--line);background:var(--paper);color:var(--ink);padding:.7rem;border-radius:.2rem}textarea{min-height:7rem;resize:vertical}.form-error{border-left:.3rem solid #ff9b8f;padding:.7rem;background:#301b1b}
.app-intro{display:flex;align-items:end;justify-content:space-between;gap:2rem;padding-block:3rem}.app-intro h1{font-size:clamp(2.6rem,7vw,6rem);margin:.1em 0}.logout{display:block}.organization-nav{display:flex;flex-wrap:wrap;gap:.7rem 1rem;align-items:center;border-block:.08rem solid var(--line);padding-block:1rem}.organization-nav a[aria-current="page"]{color:var(--ink);font-weight:800}
.live-status{margin-block:1rem}.live-status p{margin:0}.signal-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem;padding-block:2rem}.signal-card{min-width:0}.signal-card h2{font-size:clamp(1.8rem,4vw,3rem)}
details{margin-block:1rem}pre{max-width:100%;overflow:auto;background:#0a0f0d;border:.08rem solid var(--line);padding:.8rem;white-space:pre-wrap;overflow-wrap:anywhere}
.table-scroll{max-width:100%;overflow:auto;border:.08rem solid var(--line)}table{width:100%;border-collapse:collapse;min-width:40rem}caption{text-align:left;padding:.7rem;font-weight:800}th,td{text-align:left;vertical-align:top;border-top:.06rem solid var(--line);padding:.55rem .7rem;overflow-wrap:anywhere}th{color:var(--accent)}.unit{font-weight:400;color:var(--muted)}
.saved-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem}.saved-grid article+article{border-top:.08rem solid var(--line);margin-top:1rem;padding-top:1rem}
.editor-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem}.editor-card{background:var(--panel);border:.08rem solid var(--line);padding:clamp(1rem,3vw,2rem)}.builder-card{grid-column:1/-1}.field-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.6rem 1rem}.optional{color:var(--muted);font-size:.9em;font-weight:400}button:disabled{cursor:not-allowed;opacity:.55}.breadcrumbs{display:flex;flex-wrap:wrap;gap:.5rem;padding-top:1.5rem}.dashboard-panels{display:grid;gap:1rem}.stat{font-size:clamp(2rem,8vw,5rem);font-weight:800;line-height:1;margin:.5em 0}
.meter-figure{margin:1.5rem 0}.meter-figure figcaption{font-weight:800;margin-bottom:.75rem}.meter-chart{display:grid;gap:.7rem;list-style:none;margin:0;padding:0}.meter-chart li{display:grid;grid-template-columns:minmax(8rem,1fr) minmax(10rem,3fr) minmax(5rem,auto);gap:.8rem;align-items:center}.meter-label,.meter-value{overflow-wrap:anywhere}.meter-value{font-variant-numeric:tabular-nums;text-align:right}meter{width:100%;height:1.2rem;accent-color:var(--accent)}
.incident-list{display:grid;gap:1rem}.incident-card{background:var(--panel);border:.08rem solid var(--line);border-left:.35rem solid var(--accent);padding:clamp(1rem,3vw,2rem)}.incident-card[data-state="firing"]{border-left-color:#ff9b8f}.incident-card[data-state="resolved"]{opacity:.78}.incident-card dl,.saved-grid dl{display:grid;gap:.5rem;margin-block:1rem}.incident-card dl div,.saved-grid dl div{display:grid;grid-template-columns:minmax(8rem,1fr) minmax(0,2fr);gap:1rem}.incident-card dt,.saved-grid dt{font-weight:800}.incident-card dd,.saved-grid dd{margin:0}.incident-actions{display:flex;align-items:end;flex-wrap:wrap;gap:.75rem}.incident-actions form{display:flex;align-items:end;gap:.45rem}.incident-actions label{margin:0}.incident-actions select{width:auto;min-width:10rem}
.offline-control{display:grid;grid-template-columns:minmax(14rem,1fr) minmax(0,2fr);gap:clamp(2rem,6vw,7rem);margin-block:1rem;padding:clamp(1rem,3vw,2rem);border:.08rem solid var(--line);background:var(--panel)}.offline-control h2{font-size:clamp(1.5rem,3vw,2.5rem)}.offline-control [role="status"]{color:var(--muted)}
.explore-layout{display:grid;grid-template-columns:minmax(16rem,1fr) minmax(0,2fr);gap:clamp(2rem,6vw,7rem);padding-block:2rem;border-top:.08rem solid var(--line)}.explore-layout h2,.query-results h2{font-size:clamp(2rem,5vw,4rem)}.query-workbench textarea{min-height:14rem;font-family:ui-monospace,SFMono-Regular,Consolas,monospace}.field-help{color:var(--muted)}.quick-queries{display:flex;flex-wrap:wrap;gap:.6rem;margin-block:1.5rem}.quick-queries form{display:block}.query-results{padding-block:3rem;border-top:.08rem solid var(--line)}.query-results-heading{display:grid;grid-template-columns:minmax(14rem,1fr) minmax(0,2fr);gap:clamp(2rem,6vw,7rem);align-items:end}.query-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:.75rem;margin:0}.query-stats div{border-left:.18rem solid var(--line);padding-left:.75rem}.query-stats dt{color:var(--muted);font-size:.82rem;font-weight:800;text-transform:uppercase;letter-spacing:.08em}.query-stats dd{margin:.15rem 0 0;font-size:1.15rem;font-variant-numeric:tabular-nums;font-weight:800}
@media(max-width:55rem){.section-grid,.cards,.signal-grid,.saved-grid,.editor-grid,.field-grid,.offline-control,.explore-layout,.query-results-heading{grid-template-columns:1fr}.query-stats{grid-template-columns:repeat(2,minmax(0,1fr))}.app-intro{align-items:start;flex-direction:column}.hero h1{letter-spacing:-.035em}.site-header{align-items:flex-start;flex-direction:column}.site-header nav{flex-wrap:wrap}.meter-chart li{grid-template-columns:1fr}.meter-value{text-align:left}.incident-card dl div{grid-template-columns:1fr;gap:.1rem}.incident-actions,.incident-actions form{align-items:stretch;flex-direction:column}.incident-actions select{width:100%}}
@media(max-width:24rem){:root{font-size:95%}.hero h1{font-size:2.75rem;letter-spacing:-.025em}.site-header,.site-footer,main{padding-inline:.8rem}}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{scroll-behavior:auto!important;animation:none!important;transition:none!important}}
@media(forced-colors:active){button,.button,.auth-card,.signal-card,.saved-grid>section,.editor-card,.live-status,.incident-card,.offline-control,.query-stats div{border:1px solid CanvasText}.eyebrow,a{color:LinkText}}
@media print{*{color:#000!important;background:#fff!important}.site-header nav,.logout,.live-status,.button,script{display:none!important}.site-header,.site-footer,.section-grid{border-color:#777}.signal-grid,.section-grid{display:block}.signal-card{break-inside:avoid;margin-block:1rem}.table-scroll{overflow:visible}table{min-width:0;font-size:9pt}}
+146
View File
@@ -0,0 +1,146 @@
// SPDX-License-Identifier: AGPL-3.0-only
(() => {
"use strict";
const serviceWorker = "serviceWorker" in navigator
? navigator.serviceWorker.register("/service-worker.js", {scope: "/"})
: Promise.reject(new Error("service workers unavailable"));
const messageWorker = async message => {
const registration = await serviceWorker;
const worker = registration.active || registration.waiting || registration.installing;
if (!worker) throw new Error("service worker unavailable");
return await new Promise((resolve, reject) => {
const channel = new MessageChannel();
const timeout = window.setTimeout(() => reject(new Error("service worker timeout")), 5000);
channel.port1.onmessage = event => {
window.clearTimeout(timeout);
event.data && event.data.ok ? resolve(event.data) : reject(new Error("service worker request failed"));
};
worker.postMessage(message, [channel.port2]);
});
};
const decodeURLBase64 = value => {
const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
const padded = normalized + "=".repeat((4 - normalized.length % 4) % 4);
const decoded = window.atob(padded);
return Uint8Array.from(decoded, character => character.charCodeAt(0));
};
const pushRequest = async (button, action, subscription) => {
const serialized = subscription.toJSON();
const status = action === "status";
const response = await fetch(status ? "/api/v1/push/subscription/status" : "/api/v1/push/subscription", {
method: action === "delete" ? "DELETE" : "POST",
credentials: "same-origin",
cache: "no-store",
headers: {"Content-Type": "application/json", "X-CSRF-Token": button.dataset.pushCsrf},
body: JSON.stringify({
organization_id: button.dataset.pushOrganization,
endpoint: subscription.endpoint,
keys: action === "save" ? serialized.keys : {p256dh: "", auth: ""}
})
});
if (!response.ok) throw new Error("push subscription request failed");
return await response.json();
};
for (const button of document.querySelectorAll("[data-cache-inbox]")) {
const status = document.querySelector("[data-cache-status]");
serviceWorker.then(() => {
button.disabled = false;
if (status) status.textContent = "No private incident copy has been saved by this control yet.";
}).catch(() => {
if (status) status.textContent = "Offline saving is unavailable in this browser.";
});
button.addEventListener("click", async () => {
button.disabled = true;
if (status) status.textContent = "Saving a private, read-only incident snapshot…";
try {
await messageWorker({type: "cache-inbox", source: button.dataset.offlineSource, target: button.dataset.offlineTarget});
if (status) status.textContent = "This incident inbox is available offline on this browser.";
} catch (_) {
if (status) status.textContent = "The offline incident snapshot could not be saved.";
} finally {
button.disabled = false;
}
});
}
for (const form of document.querySelectorAll('form[action="/logout/"]')) {
form.addEventListener("submit", async event => {
if (form.dataset.privateCacheCleared === "true") return;
event.preventDefault();
try { await messageWorker({type: "clear-private"}); } catch (_) {}
form.dataset.privateCacheCleared = "true";
form.requestSubmit();
});
}
for (const button of document.querySelectorAll("[data-push-toggle]")) {
const status = document.querySelector("[data-push-status]");
const ready = serviceWorker.then(async registration => {
if (!("PushManager" in window) || !("Notification" in window)) throw new Error("push unavailable");
const existing = await registration.pushManager.getSubscription();
const registered = existing ? (await pushRequest(button, "status", existing)).subscribed === true : false;
button.dataset.pushRegistered = registered ? "true" : "false";
button.textContent = registered ? "Disable private incident nudges" : "Enable private incident nudges";
button.disabled = false;
if (status) status.textContent = registered ? "This browser is subscribed for this organization." : "This browser is not subscribed for this organization.";
return registration;
});
ready.catch(() => { if (status) status.textContent = "Web Push is unavailable in this browser."; });
button.addEventListener("click", async () => {
button.disabled = true;
try {
const registration = await ready;
let subscription = await registration.pushManager.getSubscription();
if (subscription && button.dataset.pushRegistered === "true") {
const result = await pushRequest(button, "delete", subscription);
if (!result.remaining) await subscription.unsubscribe();
button.dataset.pushRegistered = "false";
button.textContent = "Enable private incident nudges";
if (status) status.textContent = "This browser is no longer subscribed for this organization.";
} else {
let createdNow = false;
if (!subscription) {
const permission = await Notification.requestPermission();
if (permission !== "granted") throw new Error("notification permission not granted");
subscription = await registration.pushManager.subscribe({userVisibleOnly: true, applicationServerKey: decodeURLBase64(button.dataset.pushPublicKey)});
createdNow = true;
}
try {
await pushRequest(button, "save", subscription);
} catch (error) {
if (createdNow) await subscription.unsubscribe();
throw error;
}
button.dataset.pushRegistered = "true";
button.textContent = "Disable private incident nudges";
if (status) status.textContent = "This browser will receive generic incident nudges.";
}
} catch (_) {
if (status) status.textContent = "The browser push setting could not be changed.";
} finally {
button.disabled = false;
}
});
}
const incidentCount = document.querySelector("[data-open-incident-count]");
if (incidentCount && "setAppBadge" in navigator) {
const count = Number.parseInt(incidentCount.dataset.openIncidentCount, 10);
if (Number.isSafeInteger(count) && count >= 0) {
const update = count === 0 && "clearAppBadge" in navigator ? navigator.clearAppBadge() : navigator.setAppBadge(count);
Promise.resolve(update).catch(() => {});
}
}
for (const status of document.querySelectorAll(".live-status[data-events-url]")) {
const source = new EventSource(status.dataset.eventsUrl);
source.addEventListener("refresh", () => {
status.hidden = false;
});
window.addEventListener("pagehide", () => source.close(), {once: true});
}
})();
+44
View File
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: AGPL-3.0-only
package site
import (
"crypto/sha256"
"encoding/hex"
"strings"
"testing"
)
func TestAssetsAreContentAddressedAndBounded(t *testing.T) {
paths := AssetPaths()
for _, test := range []struct {
path, suffix, contentType string
body []byte
}{{paths.StylePath, ".css", "text/css; charset=utf-8", style}, {paths.ScriptPath, ".js", "text/javascript; charset=utf-8", script}, {paths.IconPath, ".svg", "image/svg+xml", icon}} {
t.Run(test.suffix, func(t *testing.T) {
if len(test.body) == 0 || len(test.body) > 64<<10 || !strings.HasSuffix(test.path, test.suffix) {
t.Fatalf("path=%q bytes=%d", test.path, len(test.body))
}
digest := sha256.Sum256(test.body)
if !strings.Contains(test.path, hex.EncodeToString(digest[:8])) {
t.Fatalf("asset path %q does not contain content digest", test.path)
}
body, contentType, ok := Asset(test.path)
if !ok || contentType != test.contentType || string(body) != string(test.body) {
t.Fatalf("asset lookup ok=%v type=%q", ok, contentType)
}
})
}
if _, _, ok := Asset("/assets/site.css"); ok {
t.Fatal("unversioned asset path was accepted")
}
css := string(style)
for _, required := range []string{"@media(max-width:24rem)", "@media(prefers-reduced-motion:reduce)", "@media(forced-colors:active)", "@media print", ".table-scroll", ".explore-layout", ".query-stats"} {
if !strings.Contains(css, required) {
t.Fatalf("responsive CSS missing %q", required)
}
}
if strings.Contains(strings.ToLower(css), "position:sticky") {
t.Fatal("mobile-hostile sticky table behavior returned")
}
}
+109
View File
@@ -0,0 +1,109 @@
<?sando go
package site
func Dashboard(view DashboardView)
?>
<?# SPDX-License-Identifier: AGPL-3.0-only ?>
<!doctype html>
<html lang="en">
<head><?~ Head(view.Head) ?></head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<?~ SiteHeader(true, "dashboards", view.Organization.ID) ?>
<main id="main">
<nav class="breadcrumbs" aria-label="Breadcrumb"><a href="/app/?organization=<?= view.Organization.ID ?>">Overview</a> <span aria-hidden="true">/</span> <span aria-current="page"><?= view.Name ?></span></nav>
<header class="app-intro"><div><p class="eyebrow"><?= view.Organization.Name ?> · dashboard</p><h1><?= view.Name ?></h1><p><?= view.Description ?></p></div><p><a class="button secondary" href="<?= view.ExportURL ?>">Export JSON</a></p></header>
<section class="dashboard-panels" aria-label="Dashboard panels">
<? if len(view.Panels) == 0 { ?><p>This dashboard has no panels yet.</p><? } ?>
<? for _, panel := range view.Panels { ?>
<article class="signal-card">
<p class="eyebrow"><?= panel.Visualization ?></p><h2><?= panel.Title ?></h2>
<? if panel.Stat != "" { ?><p class="stat" aria-label="Current statistic"><?= panel.Stat ?></p><? } ?>
<? if len(panel.Chart.Points) > 0 { ?>
<figure class="meter-figure">
<figcaption><?= panel.Chart.Label ?></figcaption>
<ol class="meter-chart">
<? for _, point := range panel.Chart.Points { ?>
<li><span class="meter-label"><?= point.Label ?></span><meter min="0" max="<?= point.Maximum ?>" value="<?= point.Value ?>"><?= point.Display ?></meter><span class="meter-value"><?= point.Display ?></span></li>
<? } ?>
</ol>
</figure>
<? } ?>
<details><summary>Query</summary><pre><code><?= panel.Query ?></code></pre></details>
<?~ ResultTable(panel.Table) ?>
</article>
<? } ?>
</section>
<? if view.CanManage { ?>
<section class="section-grid" aria-labelledby="edit-dashboard">
<div><p class="eyebrow">Dashboard workshop</p><h2 id="edit-dashboard">Revise this view</h2><p>Every change includes revision <?= view.Revision ?>. If someone else saves first, Observatory asks you to reload instead of overwriting their work.</p></div>
<div class="editor-grid">
<form class="editor-card" method="post" action="/app/dashboards/<?= view.Slug ?>/">
<h3>Dashboard details</h3>
<input type="hidden" name="organization_id" value="<?= view.Organization.ID ?>">
<input type="hidden" name="csrf_token" value="<?= view.ManageCSRF ?>">
<input type="hidden" name="dashboard_id" value="<?= view.ID ?>">
<input type="hidden" name="expected_revision" value="<?= view.Revision ?>">
<label for="dashboard-edit-slug">URL slug</label><input id="dashboard-edit-slug" name="slug" value="<?= view.Slug ?>" required maxlength="63" pattern="[a-z][a-z0-9-]+">
<label for="dashboard-edit-name">Name</label><input id="dashboard-edit-name" name="name" value="<?= view.Name ?>" required maxlength="128">
<label for="dashboard-edit-description">Description</label><textarea id="dashboard-edit-description" name="description" required maxlength="1024"><?= view.Description ?></textarea>
<button type="submit">Update dashboard details</button>
</form>
<? for index, panel := range view.Panels { ?>
<section class="editor-card" aria-labelledby="panel-editor-<?= index ?>">
<h3 id="panel-editor-<?= index ?>">Panel <?= index + 1 ?></h3>
<form method="post" action="/app/dashboards/<?= view.Slug ?>/panels/<?= panel.ID ?>/">
<input type="hidden" name="organization_id" value="<?= view.Organization.ID ?>">
<input type="hidden" name="csrf_token" value="<?= view.ManageCSRF ?>">
<input type="hidden" name="dashboard_id" value="<?= view.ID ?>">
<input type="hidden" name="expected_revision" value="<?= view.Revision ?>">
<label for="panel-title-<?= index ?>">Title</label><input id="panel-title-<?= index ?>" name="panel_title" value="<?= panel.Title ?>" required maxlength="128">
<label for="panel-query-<?= index ?>">Saved query</label>
<select id="panel-query-<?= index ?>" name="saved_query_id" required>
<? for _, item := range view.SavedQueries { ?>
<? if item.ID == panel.SavedQueryID { ?><option value="<?= item.ID ?>" selected><?= item.Name ?></option><? } else { ?><option value="<?= item.ID ?>"><?= item.Name ?></option><? } ?>
<? } ?>
</select>
<label for="panel-visualization-<?= index ?>">Presentation</label>
<select id="panel-visualization-<?= index ?>" name="visualization" required>
<? if panel.Visualization == "table" { ?><option value="table" selected>Table</option><? } else { ?><option value="table">Table</option><? } ?>
<? if panel.Visualization == "stat" { ?><option value="stat" selected>Single statistic with table</option><? } else { ?><option value="stat">Single statistic with table</option><? } ?>
<? if panel.Visualization == "timeseries" { ?><option value="timeseries" selected>Time series with table</option><? } else { ?><option value="timeseries">Time series with table</option><? } ?>
</select>
<button type="submit">Update panel</button>
</form>
<details>
<summary>Remove this panel</summary>
<p>This removes the panel from the dashboard definition. The saved query remains available.</p>
<form method="post" action="/app/dashboards/<?= view.Slug ?>/panels/<?= panel.ID ?>/remove/">
<input type="hidden" name="organization_id" value="<?= view.Organization.ID ?>">
<input type="hidden" name="csrf_token" value="<?= view.ManageCSRF ?>">
<input type="hidden" name="dashboard_id" value="<?= view.ID ?>">
<input type="hidden" name="expected_revision" value="<?= view.Revision ?>">
<button class="secondary" type="submit">Confirm panel removal</button>
</form>
</details>
</section>
<? } ?>
<? if len(view.Panels) < 16 { ?>
<form class="editor-card" method="post" action="/app/dashboards/<?= view.Slug ?>/panels/">
<h3>Add a panel</h3>
<input type="hidden" name="organization_id" value="<?= view.Organization.ID ?>">
<input type="hidden" name="csrf_token" value="<?= view.ManageCSRF ?>">
<input type="hidden" name="dashboard_id" value="<?= view.ID ?>">
<input type="hidden" name="expected_revision" value="<?= view.Revision ?>">
<label for="panel-add-title">Title</label><input id="panel-add-title" name="panel_title" required maxlength="128">
<label for="panel-add-query">Saved query</label>
<select id="panel-add-query" name="saved_query_id" required><option value="">Choose a saved query</option><? for _, item := range view.SavedQueries { ?><option value="<?= item.ID ?>"><?= item.Name ?></option><? } ?></select>
<label for="panel-add-visualization">Presentation</label>
<select id="panel-add-visualization" name="visualization" required><option value="table">Table</option><option value="stat">Single statistic with table</option><option value="timeseries">Time series with table</option></select>
<? if len(view.SavedQueries) == 0 { ?><button type="submit" disabled>Add panel</button><? } else { ?><button type="submit">Add panel</button><? } ?>
</form>
<? } ?>
</div>
</section>
<? } ?>
</main>
<?~ SiteFooter() ?>
</body>
</html>
+735
View File
@@ -0,0 +1,735 @@
// Code generated by himesan; DO NOT EDIT.
// himesan:compiler v1.0.0-beta.2
// himesan:runtime-abi sando.v1
// himesan:source-sha256 5a4729bb7867878ea92e49dd8dc66f388fe8fd255ab32292283ca573d17153d9
package site
import (
__himesan_context "context"
__himesan_sando "gamertan.com/sandwich-hime/sando"
__himesan_io "io"
)
var _ = __himesan_sando.ABISandoV1
func Dashboard(view DashboardView) __himesan_sando.Component {
return __himesan_sando.ComponentFunc(func(__himesan_render_context __himesan_context.Context, __himesan_writer __himesan_io.Writer) error {
_ = __himesan_render_context
//line internal/site/dashboard.sando:5:3
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:6:46
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n<!doctype html>\n<html lang=\"en\">\n<head>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:9:11
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (Head(view.Head))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:9:29
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</head>\n<body>\n <a class=\"skip-link\" href=\"#main\">Skip to content</a>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:12:7
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteHeader(true, "dashboards", view.Organization.ID))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:12:62
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <main id=\"main\">\n <nav class=\"breadcrumbs\" aria-label=\"Breadcrumb\"><a href=\"/app/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:14:86
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:14:109
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Overview</a> <span aria-hidden=\"true\">/</span> <span aria-current=\"page\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:14:188
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:14:200
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</span></nav>\n <header class=\"app-intro\"><div><p class=\"eyebrow\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:15:59
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.Organization.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:15:84
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, " · dashboard</p><h1>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:15:109
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:15:121
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</h1><p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:15:133
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.Description)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:15:152
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p></div><p><a class=\"button secondary\" href=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:15:203
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.ExportURL)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:15:220
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Export JSON</a></p></header>\n <section class=\"dashboard-panels\" aria-label=\"Dashboard panels\">\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:17:8
if len(view.Panels) == 0 {
//line internal/site/dashboard.sando:17:37
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<p>This dashboard has no panels yet.</p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:17:80
}
//line internal/site/dashboard.sando:17:84
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:18:8
for _, panel := range view.Panels {
//line internal/site/dashboard.sando:18:46
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <article class=\"signal-card\">\n <p class=\"eyebrow\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:20:32
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (panel.Visualization)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:20:54
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p><h2>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:20:66
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (panel.Title)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:20:80
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</h2>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:21:12
if panel.Stat != "" {
//line internal/site/dashboard.sando:21:36
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<p class=\"stat\" aria-label=\"Current statistic\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:21:87
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (panel.Stat)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:21:100
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:21:107
}
//line internal/site/dashboard.sando:21:111
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:22:12
if len(panel.Chart.Points) > 0 {
//line internal/site/dashboard.sando:22:47
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <figure class=\"meter-figure\">\n <figcaption>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:24:27
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (panel.Chart.Label)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:24:47
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</figcaption>\n <ol class=\"meter-chart\">\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:26:14
for _, point := range panel.Chart.Points {
//line internal/site/dashboard.sando:26:59
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <li><span class=\"meter-label\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:27:47
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (point.Label)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:27:61
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</span><meter min=\"0\" max=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:27:92
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (point.Maximum)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:27:108
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:27:121
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (point.Value)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:27:135
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:27:141
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (point.Display)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:27:157
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</meter><span class=\"meter-value\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:27:195
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (point.Display)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:27:211
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</span></li>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:28:14
}
//line internal/site/dashboard.sando:28:18
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </ol>\n </figure>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:31:12
}
//line internal/site/dashboard.sando:31:16
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <details><summary>Query</summary><pre><code>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:32:57
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (panel.Query)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:32:71
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</code></pre></details>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:33:13
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (ResultTable(panel.Table))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:33:40
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </article>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:35:8
}
//line internal/site/dashboard.sando:35:12
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </section>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:37:8
if view.CanManage {
//line internal/site/dashboard.sando:37:30
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <section class=\"section-grid\" aria-labelledby=\"edit-dashboard\">\n <div><p class=\"eyebrow\">Dashboard workshop</p><h2 id=\"edit-dashboard\">Revise this view</h2><p>Every change includes revision "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:39:136
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.Revision)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:39:152
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, ". If someone else saves first, Observatory asks you to reload instead of overwriting their work.</p></div>\n <div class=\"editor-grid\">\n <form class=\"editor-card\" method=\"post\" action=\"/app/dashboards/"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:41:77
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Slug)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:41:89
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "/\">\n <h3>Dashboard details</h3>\n <input type=\"hidden\" name=\"organization_id\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:43:66
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:43:89
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:44:61
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.ManageCSRF)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:44:79
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <input type=\"hidden\" name=\"dashboard_id\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:45:63
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:45:73
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <input type=\"hidden\" name=\"expected_revision\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:46:68
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Revision)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:46:84
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <label for=\"dashboard-edit-slug\">URL slug</label><input id=\"dashboard-edit-slug\" name=\"slug\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:47:115
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Slug)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:47:127
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" required maxlength=\"63\" pattern=\"[a-z][a-z0-9-]+\">\n <label for=\"dashboard-edit-name\">Name</label><input id=\"dashboard-edit-name\" name=\"name\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:48:111
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:48:123
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" required maxlength=\"128\">\n <label for=\"dashboard-edit-description\">Description</label><textarea id=\"dashboard-edit-description\" name=\"description\" required maxlength=\"1024\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:49:161
if __himesan_error := __himesan_sando.WriteRCDATA(__himesan_writer, (view.Description)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:49:180
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</textarea>\n <button type=\"submit\">Update dashboard details</button>\n </form>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:52:12
for index, panel := range view.Panels {
//line internal/site/dashboard.sando:52:54
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <section class=\"editor-card\" aria-labelledby=\"panel-editor-"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:53:72
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (index)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:53:80
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <h3 id=\"panel-editor-"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:54:36
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (index)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:54:44
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Panel "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:54:56
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (index + 1)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:54:68
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</h3>\n <form method=\"post\" action=\"/app/dashboards/"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:55:59
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Slug)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:55:71
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "/panels/"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:55:83
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (panel.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:55:94
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "/\">\n <input type=\"hidden\" name=\"organization_id\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:56:68
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:56:91
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:57:63
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.ManageCSRF)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:57:81
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <input type=\"hidden\" name=\"dashboard_id\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:58:65
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:58:75
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <input type=\"hidden\" name=\"expected_revision\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:59:70
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Revision)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:59:86
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <label for=\"panel-title-"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:60:41
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (index)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:60:49
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Title</label><input id=\"panel-title-"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:60:91
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (index)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:60:99
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" name=\"panel_title\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:60:131
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (panel.Title)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:60:145
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" required maxlength=\"128\">\n <label for=\"panel-query-"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:61:41
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (index)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:61:49
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Saved query</label>\n <select id=\"panel-query-"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:62:41
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (index)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:62:49
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" name=\"saved_query_id\" required>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:63:16
for _, item := range view.SavedQueries {
//line internal/site/dashboard.sando:63:59
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:64:18
if item.ID == panel.SavedQueryID {
//line internal/site/dashboard.sando:64:55
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<option value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:64:74
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (item.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:64:84
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" selected>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:64:99
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (item.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:64:111
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</option>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:64:123
} else {
//line internal/site/dashboard.sando:64:134
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<option value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:64:153
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (item.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:64:163
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:64:169
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (item.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:64:181
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</option>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:64:193
}
//line internal/site/dashboard.sando:64:197
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:65:16
}
//line internal/site/dashboard.sando:65:20
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </select>\n <label for=\"panel-visualization-"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:67:49
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (index)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:67:57
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Presentation</label>\n <select id=\"panel-visualization-"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:68:49
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (index)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:68:57
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" name=\"visualization\" required>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:69:18
if panel.Visualization == "table" {
//line internal/site/dashboard.sando:69:56
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<option value=\"table\" selected>Table</option>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:69:104
} else {
//line internal/site/dashboard.sando:69:115
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<option value=\"table\">Table</option>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:69:154
}
//line internal/site/dashboard.sando:69:158
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:70:18
if panel.Visualization == "stat" {
//line internal/site/dashboard.sando:70:55
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<option value=\"stat\" selected>Single statistic with table</option>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:70:124
} else {
//line internal/site/dashboard.sando:70:135
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<option value=\"stat\">Single statistic with table</option>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:70:195
}
//line internal/site/dashboard.sando:70:199
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:71:18
if panel.Visualization == "timeseries" {
//line internal/site/dashboard.sando:71:61
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<option value=\"timeseries\" selected>Time series with table</option>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:71:131
} else {
//line internal/site/dashboard.sando:71:142
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<option value=\"timeseries\">Time series with table</option>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:71:203
}
//line internal/site/dashboard.sando:71:207
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </select>\n <button type=\"submit\">Update panel</button>\n </form>\n <details>\n <summary>Remove this panel</summary>\n <p>This removes the panel from the dashboard definition. The saved query remains available.</p>\n <form method=\"post\" action=\"/app/dashboards/"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:78:61
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Slug)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:78:73
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "/panels/"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:78:85
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (panel.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:78:96
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "/remove/\">\n <input type=\"hidden\" name=\"organization_id\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:79:70
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:79:93
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:80:65
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.ManageCSRF)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:80:83
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <input type=\"hidden\" name=\"dashboard_id\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:81:67
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:81:77
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <input type=\"hidden\" name=\"expected_revision\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:82:72
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Revision)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:82:88
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <button class=\"secondary\" type=\"submit\">Confirm panel removal</button>\n </form>\n </details>\n </section>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:87:12
}
//line internal/site/dashboard.sando:87:16
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:88:12
if len(view.Panels) < 16 {
//line internal/site/dashboard.sando:88:41
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <form class=\"editor-card\" method=\"post\" action=\"/app/dashboards/"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:89:77
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Slug)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:89:89
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "/panels/\">\n <h3>Add a panel</h3>\n <input type=\"hidden\" name=\"organization_id\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:91:66
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:91:89
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:92:61
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.ManageCSRF)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:92:79
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <input type=\"hidden\" name=\"dashboard_id\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:93:63
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:93:73
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <input type=\"hidden\" name=\"expected_revision\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:94:68
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Revision)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:94:84
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <label for=\"panel-add-title\">Title</label><input id=\"panel-add-title\" name=\"panel_title\" required maxlength=\"128\">\n <label for=\"panel-add-query\">Saved query</label>\n <select id=\"panel-add-query\" name=\"saved_query_id\" required><option value=\"\">Choose a saved query</option>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:97:120
for _, item := range view.SavedQueries {
//line internal/site/dashboard.sando:97:163
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<option value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:97:182
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (item.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:97:192
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:97:198
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (item.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:97:210
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</option>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:97:222
}
//line internal/site/dashboard.sando:97:226
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</select>\n <label for=\"panel-add-visualization\">Presentation</label>\n <select id=\"panel-add-visualization\" name=\"visualization\" required><option value=\"table\">Table</option><option value=\"stat\">Single statistic with table</option><option value=\"timeseries\">Time series with table</option></select>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:100:14
if len(view.SavedQueries) == 0 {
//line internal/site/dashboard.sando:100:49
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<button type=\"submit\" disabled>Add panel</button>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:100:101
} else {
//line internal/site/dashboard.sando:100:112
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<button type=\"submit\">Add panel</button>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:100:155
}
//line internal/site/dashboard.sando:100:159
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </form>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:102:12
}
//line internal/site/dashboard.sando:102:16
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </div>\n </section>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:105:8
}
//line internal/site/dashboard.sando:105:12
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </main>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:107:7
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteFooter())); __himesan_error != nil {
return __himesan_error
}
//line internal/site/dashboard.sando:107:22
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n</body>\n</html>\n"); __himesan_error != nil {
return __himesan_error
}
return nil
})
}
+60
View File
@@ -0,0 +1,60 @@
<?sando go
package site
func Explore(view ExploreView)
?>
<?# SPDX-License-Identifier: AGPL-3.0-only ?>
<!doctype html>
<html lang="en">
<head><?~ Head(view.Head) ?></head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<?~ SiteHeader(true, "explore", view.Organization.ID) ?>
<main id="main">
<nav class="breadcrumbs" aria-label="Breadcrumb"><a href="/app/?organization=<?= view.Organization.ID ?>">Overview</a><span aria-hidden="true">/</span><span aria-current="page">Explore</span></nav>
<section class="app-intro" aria-labelledby="explore-title">
<div><p class="eyebrow">Query workshop · <?= view.Organization.Name ?></p><h1 id="explore-title">Follow the evidence.</h1><p>Welcome, <?= view.DisplayName ?>. Write one bounded query, run it on the server, and inspect both the result and its cost.</p></div>
</section>
<aside class="live-status" data-events-url="<?= view.EventsURL ?>" hidden>
<p><strong>New observations are available.</strong> Run the query again when you are ready; Observatory will not replace the result beneath you.</p>
</aside>
<section class="explore-layout" aria-labelledby="query-title">
<div>
<p class="eyebrow">Typed query</p>
<h2 id="query-title">Ask a bounded question</h2>
<p>Queries stay out of the URL and access log. The same parser, authorization scope, sensitivity rules, and execution limits used by the API are applied here.</p>
<div class="quick-queries" aria-label="Example queries">
<form method="post" action="/app/explore/?organization=<?= view.Organization.ID ?>"><input type="hidden" name="csrf_token" value="<?= view.CSRFToken ?>"><input type="hidden" name="query" value="logs | window 1h | limit 50"><button class="secondary" type="submit">Recent logs</button></form>
<form method="post" action="/app/explore/?organization=<?= view.Organization.ID ?>"><input type="hidden" name="csrf_token" value="<?= view.CSRFToken ?>"><input type="hidden" name="query" value="metrics | window 1h | limit 50"><button class="secondary" type="submit">Recent metrics</button></form>
<form method="post" action="/app/explore/?organization=<?= view.Organization.ID ?>"><input type="hidden" name="csrf_token" value="<?= view.CSRFToken ?>"><input type="hidden" name="query" value="traces | window 1h | limit 50"><button class="secondary" type="submit">Recent traces</button></form>
<form method="post" action="/app/explore/?organization=<?= view.Organization.ID ?>"><input type="hidden" name="csrf_token" value="<?= view.CSRFToken ?>"><input type="hidden" name="query" value="deployments | window 24h | limit 50"><button class="secondary" type="submit">Recent deployments</button></form>
</div>
</div>
<form class="editor-card query-workbench" method="post" action="/app/explore/?organization=<?= view.Organization.ID ?>">
<input type="hidden" name="csrf_token" value="<?= view.CSRFToken ?>">
<label for="explore-query">Query</label>
<textarea id="explore-query" name="query" required maxlength="16384" spellcheck="false"><?= view.Query ?></textarea>
<p class="field-help">Begin with <code>logs</code>, <code>metrics</code>, <code>traces</code>, or <code>deployments</code>. Every query has bounded time, rows, bytes, and memory.</p>
<button type="submit">Run query</button>
</form>
</section>
<? if view.ErrorMessage != "" { ?><p class="form-error" role="alert"><?= view.ErrorMessage ?></p><? } ?>
<? if view.Executed { ?>
<section class="query-results" aria-labelledby="results-title">
<div class="query-results-heading"><div><p class="eyebrow">Authorized result</p><h2 id="results-title">Query results</h2></div>
<dl class="query-stats">
<div><dt>Scanned rows</dt><dd><?= view.Stats.ScannedRows ?></dd></div>
<div><dt>Matched rows</dt><dd><?= view.Stats.MatchedRows ?></dd></div>
<div><dt>Scanned bytes</dt><dd><?= view.Stats.ScannedBytes ?></dd></div>
<div><dt>Execution</dt><dd><?= view.Stats.Duration ?></dd></div>
</dl>
</div>
<? if view.Stats.Truncated { ?><p class="live-status"><strong>Result limit reached.</strong> Refine the query or deliberately choose a different bounded limit.</p><? } ?>
<? if view.Stats.Approximate { ?><p class="live-status"><strong>Approximate result.</strong> This answer uses an authorized aggregate projection.</p><? } ?>
<?~ ResultTable(view.Table) ?>
</section>
<? } ?>
</main>
<?~ SiteFooter() ?>
</body>
</html>
+269
View File
@@ -0,0 +1,269 @@
// Code generated by himesan; DO NOT EDIT.
// himesan:compiler v1.0.0-beta.2
// himesan:runtime-abi sando.v1
// himesan:source-sha256 970611f5a27597a2257f7ce7f38bc1184b99fa0801b9b0e3d09ea8bd53986827
package site
import (
__himesan_context "context"
__himesan_sando "gamertan.com/sandwich-hime/sando"
__himesan_io "io"
)
var _ = __himesan_sando.ABISandoV1
func Explore(view ExploreView) __himesan_sando.Component {
return __himesan_sando.ComponentFunc(func(__himesan_render_context __himesan_context.Context, __himesan_writer __himesan_io.Writer) error {
_ = __himesan_render_context
//line internal/site/explore.sando:5:3
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:6:46
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n<!doctype html>\n<html lang=\"en\">\n<head>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:9:11
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (Head(view.Head))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:9:29
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</head>\n<body>\n <a class=\"skip-link\" href=\"#main\">Skip to content</a>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:12:7
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteHeader(true, "explore", view.Organization.ID))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:12:59
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <main id=\"main\">\n <nav class=\"breadcrumbs\" aria-label=\"Breadcrumb\"><a href=\"/app/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:14:86
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:14:109
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Overview</a><span aria-hidden=\"true\">/</span><span aria-current=\"page\">Explore</span></nav>\n <section class=\"app-intro\" aria-labelledby=\"explore-title\">\n <div><p class=\"eyebrow\">Query workshop · "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:16:53
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.Organization.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:16:78
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p><h1 id=\"explore-title\">Follow the evidence.</h1><p>Welcome, "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:16:146
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.DisplayName)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:16:165
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, ". Write one bounded query, run it on the server, and inspect both the result and its cost.</p></div>\n </section>\n <aside class=\"live-status\" data-events-url=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:18:53
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.EventsURL)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:18:70
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" hidden>\n <p><strong>New observations are available.</strong> Run the query again when you are ready; Observatory will not replace the result beneath you.</p>\n </aside>\n <section class=\"explore-layout\" aria-labelledby=\"query-title\">\n <div>\n <p class=\"eyebrow\">Typed query</p>\n <h2 id=\"query-title\">Ask a bounded question</h2>\n <p>Queries stay out of the URL and access log. The same parser, authorization scope, sensitivity rules, and execution limits used by the API are applied here.</p>\n <div class=\"quick-queries\" aria-label=\"Example queries\">\n <form method=\"post\" action=\"/app/explore/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:27:70
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:27:93
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\"><input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:27:145
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.CSRFToken)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:27:162
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\"><input type=\"hidden\" name=\"query\" value=\"logs | window 1h | limit 50\"><button class=\"secondary\" type=\"submit\">Recent logs</button></form>\n <form method=\"post\" action=\"/app/explore/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:28:70
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:28:93
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\"><input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:28:145
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.CSRFToken)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:28:162
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\"><input type=\"hidden\" name=\"query\" value=\"metrics | window 1h | limit 50\"><button class=\"secondary\" type=\"submit\">Recent metrics</button></form>\n <form method=\"post\" action=\"/app/explore/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:29:70
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:29:93
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\"><input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:29:145
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.CSRFToken)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:29:162
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\"><input type=\"hidden\" name=\"query\" value=\"traces | window 1h | limit 50\"><button class=\"secondary\" type=\"submit\">Recent traces</button></form>\n <form method=\"post\" action=\"/app/explore/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:30:70
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:30:93
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\"><input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:30:145
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.CSRFToken)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:30:162
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\"><input type=\"hidden\" name=\"query\" value=\"deployments | window 24h | limit 50\"><button class=\"secondary\" type=\"submit\">Recent deployments</button></form>\n </div>\n </div>\n <form class=\"editor-card query-workbench\" method=\"post\" action=\"/app/explore/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:33:102
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:33:125
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:34:59
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.CSRFToken)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:34:76
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <label for=\"explore-query\">Query</label>\n <textarea id=\"explore-query\" name=\"query\" required maxlength=\"16384\" spellcheck=\"false\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:36:101
if __himesan_error := __himesan_sando.WriteRCDATA(__himesan_writer, (view.Query)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:36:114
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</textarea>\n <p class=\"field-help\">Begin with <code>logs</code>, <code>metrics</code>, <code>traces</code>, or <code>deployments</code>. Every query has bounded time, rows, bytes, and memory.</p>\n <button type=\"submit\">Run query</button>\n </form>\n </section>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:41:8
if view.ErrorMessage != "" {
//line internal/site/explore.sando:41:39
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<p class=\"form-error\" role=\"alert\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:41:78
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.ErrorMessage)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:41:98
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:41:105
}
//line internal/site/explore.sando:41:109
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:42:8
if view.Executed {
//line internal/site/explore.sando:42:29
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <section class=\"query-results\" aria-labelledby=\"results-title\">\n <div class=\"query-results-heading\"><div><p class=\"eyebrow\">Authorized result</p><h2 id=\"results-title\">Query results</h2></div>\n <dl class=\"query-stats\">\n <div><dt>Scanned rows</dt><dd>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:46:45
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.Stats.ScannedRows)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:46:70
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</dd></div>\n <div><dt>Matched rows</dt><dd>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:47:45
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.Stats.MatchedRows)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:47:70
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</dd></div>\n <div><dt>Scanned bytes</dt><dd>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:48:46
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.Stats.ScannedBytes)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:48:72
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</dd></div>\n <div><dt>Execution</dt><dd>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:49:42
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.Stats.Duration)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:49:64
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</dd></div>\n </dl>\n </div>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:52:10
if view.Stats.Truncated {
//line internal/site/explore.sando:52:38
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<p class=\"live-status\"><strong>Result limit reached.</strong> Refine the query or deliberately choose a different bounded limit.</p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:52:173
}
//line internal/site/explore.sando:52:177
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:53:10
if view.Stats.Approximate {
//line internal/site/explore.sando:53:40
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<p class=\"live-status\"><strong>Approximate result.</strong> This answer uses an authorized aggregate projection.</p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:53:159
}
//line internal/site/explore.sando:53:163
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:54:11
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (ResultTable(view.Table))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:54:37
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </section>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:56:8
}
//line internal/site/explore.sando:56:12
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </main>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:58:7
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteFooter())); __himesan_error != nil {
return __himesan_error
}
//line internal/site/explore.sando:58:22
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n</body>\n</html>\n"); __himesan_error != nil {
return __himesan_error
}
return nil
})
}
+14
View File
@@ -0,0 +1,14 @@
<?sando go
package site
func Head(view HeadView)
?>
<?# SPDX-License-Identifier: AGPL-3.0-only ?>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="<?= view.Description ?>">
<link rel="canonical" href="<?= view.CanonicalURL ?>">
<link rel="manifest" href="/manifest.webmanifest">
<link rel="stylesheet" href="<?= view.Assets.StylePath ?>">
<script src="<?= view.Assets.ScriptPath ?>" defer></script>
<title><?= view.Title ?></title>
+69
View File
@@ -0,0 +1,69 @@
// Code generated by himesan; DO NOT EDIT.
// himesan:compiler v1.0.0-beta.2
// himesan:runtime-abi sando.v1
// himesan:source-sha256 131f6248343bf4c87cd3a2a525a2050cee13ad29a2e178d5ef4e996c65590dc9
package site
import (
__himesan_context "context"
__himesan_sando "gamertan.com/sandwich-hime/sando"
__himesan_io "io"
)
var _ = __himesan_sando.ABISandoV1
func Head(view HeadView) __himesan_sando.Component {
return __himesan_sando.ComponentFunc(func(__himesan_render_context __himesan_context.Context, __himesan_writer __himesan_io.Writer) error {
_ = __himesan_render_context
//line internal/site/head.sando:5:3
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/head.sando:6:46
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<meta name=\"description\" content=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/head.sando:9:39
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Description)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/head.sando:9:58
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n<link rel=\"canonical\" href=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/head.sando:10:33
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.CanonicalURL)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/head.sando:10:53
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n<link rel=\"manifest\" href=\"/manifest.webmanifest\">\n<link rel=\"stylesheet\" href=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/head.sando:12:34
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Assets.StylePath)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/head.sando:12:58
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n<script src=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/head.sando:13:18
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Assets.ScriptPath)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/head.sando:13:43
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" defer></script>\n<title>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/head.sando:14:12
if __himesan_error := __himesan_sando.WriteRCDATA(__himesan_writer, (view.Title)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/head.sando:14:25
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</title>\n"); __himesan_error != nil {
return __himesan_error
}
return nil
})
}
+63
View File
@@ -0,0 +1,63 @@
<?sando go
package site
func IncidentInbox(view IncidentInboxView)
?>
<?# SPDX-License-Identifier: AGPL-3.0-only ?>
<!doctype html>
<html lang="en">
<head><?~ Head(view.Head) ?></head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<?~ SiteHeader(true, "incidents", view.Organization.ID) ?>
<main id="main" data-open-incident-count="<?= view.OpenCount ?>">
<nav class="breadcrumbs" aria-label="Breadcrumb"><a href="/app/?organization=<?= view.Organization.ID ?>">Overview</a><span aria-hidden="true">/</span><span aria-current="page">Incidents</span></nav>
<section class="app-intro" aria-labelledby="incident-title">
<div><p class="eyebrow">Incident inbox · <?= view.Organization.Name ?></p><h1 id="incident-title">What needs attention?</h1><p>Welcome, <?= view.DisplayName ?>. Rules use bounded saved queries; this inbox keeps the human response durable and reviewable.</p></div>
</section>
<aside class="live-status" data-events-url="<?= view.EventsURL ?>" hidden><p><strong>Incident evidence changed.</strong> <a href="/app/incidents/?organization=<?= view.Organization.ID ?>">Refresh this inbox</a>.</p></aside>
<section class="offline-control" aria-labelledby="offline-copy-title"><div><h2 id="offline-copy-title">Keep a careful offline copy</h2><p id="offline-copy-note">This is opt-in. The saved copy excludes response controls, CSRF material, query text, telemetry values, actors, and project, environment, or service identifiers.</p></div><div><button class="secondary" type="button" data-cache-inbox data-offline-source="<?= view.OfflineURL ?>" data-offline-target="<?= view.CacheKey ?>" aria-describedby="offline-copy-note" disabled>Save this inbox for offline use</button><p data-cache-status role="status" aria-live="polite">Offline saving requires service-worker support.</p></div></section>
<? if view.PushPublicKey != "" { ?><section class="offline-control" aria-labelledby="push-title"><div><h2 id="push-title">Ask this browser to nudge you</h2><p id="push-note">Optional Web Push sends one fixed message through the browser vendor: “Gamertan Observatory needs your attention.” It never includes an organization, host, service, severity, rule, incident identifier, count, or telemetry text.</p></div><div><button class="secondary" type="button" data-push-toggle data-push-public-key="<?= view.PushPublicKey ?>" data-push-organization="<?= view.Organization.ID ?>" data-push-csrf="<?= view.PushCSRF ?>" aria-describedby="push-note" disabled>Enable private incident nudges</button><p data-push-status role="status" aria-live="polite">Push requires service-worker and notification support.</p></div></section><? } ?>
<section class="section-grid" aria-labelledby="active-incidents">
<div><p class="eyebrow">Durable state</p><h2 id="active-incidents">Incidents</h2></div>
<div class="incident-list">
<? if len(view.Incidents) == 0 { ?><p>No incidents have been opened.</p><? } ?>
<? for _, incident := range view.Incidents { ?>
<article class="incident-card" data-state="<?= incident.State ?>">
<div><p class="eyebrow"><?= incident.Severity ?> · <?= incident.State ?></p><h3><?= incident.Title ?></h3></div>
<dl><div><dt>Started</dt><dd><?= incident.StartedAt ?></dd></div><div><dt>Updated</dt><dd><?= incident.UpdatedAt ?></dd></div><? if incident.SilencedUntil != "" { ?><div><dt>Silenced until</dt><dd><?= incident.SilencedUntil ?></dd></div><? } ?></dl>
<? if view.CanManage && incident.State != "resolved" { ?>
<div class="incident-actions" aria-label="Actions for <?= incident.Title ?>">
<form method="post" action="/app/incidents/<?= incident.ID ?>/"><input type="hidden" name="organization_id" value="<?= view.Organization.ID ?>"><input type="hidden" name="csrf_token" value="<?= view.ManageCSRF ?>"><input type="hidden" name="action" value="acknowledge"><input type="hidden" name="silence_duration" value=""><button class="secondary" type="submit">Acknowledge</button></form>
<form method="post" action="/app/incidents/<?= incident.ID ?>/"><input type="hidden" name="organization_id" value="<?= view.Organization.ID ?>"><input type="hidden" name="csrf_token" value="<?= view.ManageCSRF ?>"><input type="hidden" name="action" value="silence"><label for="silence-<?= incident.ID ?>">Silence for</label><select id="silence-<?= incident.ID ?>" name="silence_duration"><option value="15m">15 minutes</option><option value="1h">1 hour</option><option value="6h">6 hours</option><option value="24h">24 hours</option><option value="168h">7 days</option></select><button class="secondary" type="submit">Silence</button></form>
<form method="post" action="/app/incidents/<?= incident.ID ?>/"><input type="hidden" name="organization_id" value="<?= view.Organization.ID ?>"><input type="hidden" name="csrf_token" value="<?= view.ManageCSRF ?>"><input type="hidden" name="action" value="resolve"><input type="hidden" name="silence_duration" value=""><button class="secondary" type="submit">Resolve</button></form>
</div>
<? } ?>
</article>
<? } ?>
</div>
</section>
<section class="section-grid" aria-labelledby="alert-rules">
<div><p class="eyebrow">Bounded evaluation</p><h2 id="alert-rules">Alert rules</h2></div>
<div class="saved-grid">
<? if len(view.Rules) == 0 { ?><p>No alert rules yet.</p><? } ?>
<? for _, rule := range view.Rules { ?><article><p class="eyebrow"><?= rule.Severity ?></p><h3><?= rule.Name ?></h3><p><?= rule.Description ?></p><dl><div><dt>Interval</dt><dd><?= rule.Interval ?></dd></div><div><dt>Status</dt><dd><? if rule.Enabled { ?>Enabled<? } else { ?>Disabled<? } ?></dd></div><? if rule.LastEvaluatedAt != "" { ?><div><dt>Last evaluated</dt><dd><?= rule.LastEvaluatedAt ?></dd></div><? } ?><? if rule.LastError != "" { ?><div><dt>Last result</dt><dd>Query unavailable</dd></div><? } ?></dl></article><? } ?>
</div>
</section>
<? if view.CanManage { ?>
<section class="section-grid" aria-labelledby="create-alert">
<div><p class="eyebrow">Organization workshop</p><h2 id="create-alert">Create an alert rule</h2><p>A rule counts rows returned by one saved query. Consecutive matches allow brief noise to remain pending before an incident fires.</p></div>
<form class="editor-card" method="post" action="/app/alert-rules/">
<input type="hidden" name="organization_id" value="<?= view.Organization.ID ?>"><input type="hidden" name="csrf_token" value="<?= view.ManageCSRF ?>">
<label for="alert-name">Name</label><input id="alert-name" name="name" required maxlength="128">
<label for="alert-description">Description</label><textarea id="alert-description" name="description" required maxlength="1024"></textarea>
<label for="alert-query">Saved query</label><select id="alert-query" name="saved_query_id" required><option value="">Choose a saved query</option><? for _, item := range view.SavedQueries { ?><option value="<?= item.ID ?>"><?= item.Name ?></option><? } ?></select>
<div class="field-grid"><div><label for="alert-severity">Severity</label><select id="alert-severity" name="severity" required><option value="information">Information</option><option value="warning" selected>Warning</option><option value="critical">Critical</option></select></div><div><label for="alert-interval">Evaluate every</label><select id="alert-interval" name="evaluation_interval" required><option value="15s">15 seconds</option><option value="30s">30 seconds</option><option value="1m" selected>1 minute</option><option value="5m">5 minutes</option><option value="15m">15 minutes</option></select></div><div><label for="alert-matches">Minimum matching rows</label><input id="alert-matches" type="number" name="minimum_matches" min="1" max="100000" value="1" required></div><div><label for="alert-confirmations">Consecutive evaluations</label><input id="alert-confirmations" type="number" name="required_consecutive" min="1" max="10" value="2" required></div></div>
<? if len(view.SavedQueries) == 0 { ?><button type="submit" disabled>Create alert rule</button><? } else { ?><button type="submit">Create alert rule</button><? } ?>
</form>
</section>
<? } ?>
</main>
<?~ SiteFooter() ?>
</body>
</html>
+529
View File
@@ -0,0 +1,529 @@
// Code generated by himesan; DO NOT EDIT.
// himesan:compiler v1.0.0-beta.2
// himesan:runtime-abi sando.v1
// himesan:source-sha256 df123546e9ef420a7ce574a528a984505176d15c8e6233582468bde1e5bc9ea6
package site
import (
__himesan_context "context"
__himesan_sando "gamertan.com/sandwich-hime/sando"
__himesan_io "io"
)
var _ = __himesan_sando.ABISandoV1
func IncidentInbox(view IncidentInboxView) __himesan_sando.Component {
return __himesan_sando.ComponentFunc(func(__himesan_render_context __himesan_context.Context, __himesan_writer __himesan_io.Writer) error {
_ = __himesan_render_context
//line internal/site/incidents.sando:5:3
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:6:46
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n<!doctype html>\n<html lang=\"en\">\n<head>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:9:11
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (Head(view.Head))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:9:29
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</head>\n<body>\n <a class=\"skip-link\" href=\"#main\">Skip to content</a>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:12:7
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteHeader(true, "incidents", view.Organization.ID))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:12:61
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <main id=\"main\" data-open-incident-count=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:13:49
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.OpenCount)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:13:66
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <nav class=\"breadcrumbs\" aria-label=\"Breadcrumb\"><a href=\"/app/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:14:86
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:14:109
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Overview</a><span aria-hidden=\"true\">/</span><span aria-current=\"page\">Incidents</span></nav>\n <section class=\"app-intro\" aria-labelledby=\"incident-title\">\n <div><p class=\"eyebrow\">Incident inbox · "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:16:53
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.Organization.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:16:78
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p><h1 id=\"incident-title\">What needs attention?</h1><p>Welcome, "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:16:148
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.DisplayName)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:16:167
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, ". Rules use bounded saved queries; this inbox keeps the human response durable and reviewable.</p></div>\n </section>\n <aside class=\"live-status\" data-events-url=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:18:53
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.EventsURL)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:18:70
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" hidden><p><strong>Incident evidence changed.</strong> <a href=\"/app/incidents/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:18:168
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:18:191
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Refresh this inbox</a>.</p></aside>\n <section class=\"offline-control\" aria-labelledby=\"offline-copy-title\"><div><h2 id=\"offline-copy-title\">Keep a careful offline copy</h2><p id=\"offline-copy-note\">This is opt-in. The saved copy excludes response controls, CSRF material, query text, telemetry values, actors, and project, environment, or service identifiers.</p></div><div><button class=\"secondary\" type=\"button\" data-cache-inbox data-offline-source=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:19:424
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.OfflineURL)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:19:442
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" data-offline-target=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:19:469
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.CacheKey)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:19:485
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" aria-describedby=\"offline-copy-note\" disabled>Save this inbox for offline use</button><p data-cache-status role=\"status\" aria-live=\"polite\">Offline saving requires service-worker support.</p></div></section>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:20:8
if view.PushPublicKey != "" {
//line internal/site/incidents.sando:20:40
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<section class=\"offline-control\" aria-labelledby=\"push-title\"><div><h2 id=\"push-title\">Ask this browser to nudge you</h2><p id=\"push-note\">Optional Web Push sends one fixed message through the browser vendor: “Gamertan Observatory needs your attention.” It never includes an organization, host, service, severity, rule, incident identifier, count, or telemetry text.</p></div><div><button class=\"secondary\" type=\"button\" data-push-toggle data-push-public-key=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:20:508
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.PushPublicKey)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:20:529
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" data-push-organization=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:20:559
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:20:582
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" data-push-csrf=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:20:604
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.PushCSRF)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:20:620
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" aria-describedby=\"push-note\" disabled>Enable private incident nudges</button><p data-push-status role=\"status\" aria-live=\"polite\">Push requires service-worker and notification support.</p></div></section>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:20:829
}
//line internal/site/incidents.sando:20:833
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <section class=\"section-grid\" aria-labelledby=\"active-incidents\">\n <div><p class=\"eyebrow\">Durable state</p><h2 id=\"active-incidents\">Incidents</h2></div>\n <div class=\"incident-list\">\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:24:10
if len(view.Incidents) == 0 {
//line internal/site/incidents.sando:24:42
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<p>No incidents have been opened.</p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:24:82
}
//line internal/site/incidents.sando:24:86
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:25:10
for _, incident := range view.Incidents {
//line internal/site/incidents.sando:25:54
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <article class=\"incident-card\" data-state=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:26:56
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (incident.State)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:26:73
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <div><p class=\"eyebrow\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:27:39
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (incident.Severity)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:27:59
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, " · "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:27:67
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (incident.State)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:27:84
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p><h3>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:27:96
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (incident.Title)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:27:113
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</h3></div>\n <dl><div><dt>Started</dt><dd>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:28:44
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (incident.StartedAt)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:28:65
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</dd></div><div><dt>Updated</dt><dd>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:28:105
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (incident.UpdatedAt)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:28:126
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</dd></div>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:28:140
if incident.SilencedUntil != "" {
//line internal/site/incidents.sando:28:176
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<div><dt>Silenced until</dt><dd>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:28:212
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (incident.SilencedUntil)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:28:237
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</dd></div>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:28:251
}
//line internal/site/incidents.sando:28:255
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</dl>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:29:14
if view.CanManage && incident.State != "resolved" {
//line internal/site/incidents.sando:29:68
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <div class=\"incident-actions\" aria-label=\"Actions for "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:30:69
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (incident.Title)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:30:86
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <form method=\"post\" action=\"/app/incidents/"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:31:60
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (incident.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:31:74
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "/\"><input type=\"hidden\" name=\"organization_id\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:31:132
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:31:155
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\"><input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:31:207
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.ManageCSRF)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:31:225
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\"><input type=\"hidden\" name=\"action\" value=\"acknowledge\"><input type=\"hidden\" name=\"silence_duration\" value=\"\"><button class=\"secondary\" type=\"submit\">Acknowledge</button></form>\n <form method=\"post\" action=\"/app/incidents/"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:32:60
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (incident.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:32:74
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "/\"><input type=\"hidden\" name=\"organization_id\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:32:132
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:32:155
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\"><input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:32:207
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.ManageCSRF)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:32:225
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\"><input type=\"hidden\" name=\"action\" value=\"silence\"><label for=\"silence-"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:32:302
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (incident.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:32:316
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Silence for</label><select id=\"silence-"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:32:361
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (incident.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:32:375
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\" name=\"silence_duration\"><option value=\"15m\">15 minutes</option><option value=\"1h\">1 hour</option><option value=\"6h\">6 hours</option><option value=\"24h\">24 hours</option><option value=\"168h\">7 days</option></select><button class=\"secondary\" type=\"submit\">Silence</button></form>\n <form method=\"post\" action=\"/app/incidents/"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:33:60
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (incident.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:33:74
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "/\"><input type=\"hidden\" name=\"organization_id\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:33:132
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:33:155
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\"><input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:33:207
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.ManageCSRF)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:33:225
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\"><input type=\"hidden\" name=\"action\" value=\"resolve\"><input type=\"hidden\" name=\"silence_duration\" value=\"\"><button class=\"secondary\" type=\"submit\">Resolve</button></form>\n </div>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:35:14
}
//line internal/site/incidents.sando:35:18
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </article>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:37:10
}
//line internal/site/incidents.sando:37:14
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </div>\n </section>\n <section class=\"section-grid\" aria-labelledby=\"alert-rules\">\n <div><p class=\"eyebrow\">Bounded evaluation</p><h2 id=\"alert-rules\">Alert rules</h2></div>\n <div class=\"saved-grid\">\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:43:10
if len(view.Rules) == 0 {
//line internal/site/incidents.sando:43:38
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<p>No alert rules yet.</p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:43:67
}
//line internal/site/incidents.sando:43:71
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:10
for _, rule := range view.Rules {
//line internal/site/incidents.sando:44:46
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<article><p class=\"eyebrow\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:78
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (rule.Severity)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:94
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p><h3>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:106
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (rule.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:118
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</h3><p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:130
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (rule.Description)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:149
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p><dl><div><dt>Interval</dt><dd>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:187
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (rule.Interval)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:203
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</dd></div><div><dt>Status</dt><dd>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:241
if rule.Enabled {
//line internal/site/incidents.sando:44:261
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "Enabled"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:271
} else {
//line internal/site/incidents.sando:44:282
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "Disabled"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:293
}
//line internal/site/incidents.sando:44:297
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</dd></div>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:311
if rule.LastEvaluatedAt != "" {
//line internal/site/incidents.sando:44:345
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<div><dt>Last evaluated</dt><dd>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:381
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (rule.LastEvaluatedAt)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:404
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</dd></div>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:418
}
//line internal/site/incidents.sando:44:425
if rule.LastError != "" {
//line internal/site/incidents.sando:44:453
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<div><dt>Last result</dt><dd>Query unavailable</dd></div>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:513
}
//line internal/site/incidents.sando:44:517
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</dl></article>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:44:535
}
//line internal/site/incidents.sando:44:539
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </div>\n </section>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:47:8
if view.CanManage {
//line internal/site/incidents.sando:47:30
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <section class=\"section-grid\" aria-labelledby=\"create-alert\">\n <div><p class=\"eyebrow\">Organization workshop</p><h2 id=\"create-alert\">Create an alert rule</h2><p>A rule counts rows returned by one saved query. Consecutive matches allow brief noise to remain pending before an incident fires.</p></div>\n <form class=\"editor-card\" method=\"post\" action=\"/app/alert-rules/\">\n <input type=\"hidden\" name=\"organization_id\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:51:64
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Organization.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:51:87
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\"><input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:51:139
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.ManageCSRF)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:51:157
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <label for=\"alert-name\">Name</label><input id=\"alert-name\" name=\"name\" required maxlength=\"128\">\n <label for=\"alert-description\">Description</label><textarea id=\"alert-description\" name=\"description\" required maxlength=\"1024\"></textarea>\n <label for=\"alert-query\">Saved query</label><select id=\"alert-query\" name=\"saved_query_id\" required><option value=\"\">Choose a saved query</option>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:54:158
for _, item := range view.SavedQueries {
//line internal/site/incidents.sando:54:201
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<option value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:54:220
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (item.ID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:54:230
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:54:236
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (item.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:54:248
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</option>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:54:260
}
//line internal/site/incidents.sando:54:264
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</select>\n <div class=\"field-grid\"><div><label for=\"alert-severity\">Severity</label><select id=\"alert-severity\" name=\"severity\" required><option value=\"information\">Information</option><option value=\"warning\" selected>Warning</option><option value=\"critical\">Critical</option></select></div><div><label for=\"alert-interval\">Evaluate every</label><select id=\"alert-interval\" name=\"evaluation_interval\" required><option value=\"15s\">15 seconds</option><option value=\"30s\">30 seconds</option><option value=\"1m\" selected>1 minute</option><option value=\"5m\">5 minutes</option><option value=\"15m\">15 minutes</option></select></div><div><label for=\"alert-matches\">Minimum matching rows</label><input id=\"alert-matches\" type=\"number\" name=\"minimum_matches\" min=\"1\" max=\"100000\" value=\"1\" required></div><div><label for=\"alert-confirmations\">Consecutive evaluations</label><input id=\"alert-confirmations\" type=\"number\" name=\"required_consecutive\" min=\"1\" max=\"10\" value=\"2\" required></div></div>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:56:12
if len(view.SavedQueries) == 0 {
//line internal/site/incidents.sando:56:47
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<button type=\"submit\" disabled>Create alert rule</button>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:56:107
} else {
//line internal/site/incidents.sando:56:118
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<button type=\"submit\">Create alert rule</button>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:56:169
}
//line internal/site/incidents.sando:56:173
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </form>\n </section>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:59:8
}
//line internal/site/incidents.sando:59:12
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </main>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:61:7
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteFooter())); __himesan_error != nil {
return __himesan_error
}
//line internal/site/incidents.sando:61:22
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n</body>\n</html>\n"); __himesan_error != nil {
return __himesan_error
}
return nil
})
}
+35
View File
@@ -0,0 +1,35 @@
<?sando go
package site
func Landing(view LandingView)
?>
<?# SPDX-License-Identifier: AGPL-3.0-only ?>
<!doctype html>
<html lang="en">
<head><?~ Head(view.Head) ?></head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<?~ SiteHeader(false, "", "") ?>
<main id="main">
<section class="hero" aria-labelledby="hero-title">
<p class="eyebrow">Logs · metrics · traces · deployments</p>
<h1 id="hero-title">Keep the evidence close.</h1>
<p class="lede">Gamertan Observatory is a self-hosted observability platform being built for small, carefully operated Linux systems. It keeps raw evidence replayable, tenant boundaries explicit, and queries understandable.</p>
<p><a class="button" href="/login/">Open Observatory</a></p>
</section>
<section class="section-grid" aria-labelledby="working-model">
<div><p class="eyebrow">Working model</p><h2 id="working-model">One view without one giant trust boundary.</h2></div>
<div class="cards">
<article><h3>Evidence first</h3><p>Checksummed raw segments are committed before projections acknowledge an ingest. Indexes and dashboards remain rebuildable views.</p></article>
<article><h3>Scoped by the server</h3><p>Organization and resource identity come from enrolled sources and authenticated grants—not from telemetry payloads or query text.</p></article>
<article><h3>Bounded by default</h3><p>Ingestion, storage, queries, subscribers, and fields have explicit limits. Sensitive data requires a separate permission.</p></article>
</div>
</section>
<section class="section-grid" aria-labelledby="preview-status">
<div><p class="eyebrow">Current status</p><h2 id="preview-status">A private development preview.</h2></div>
<div class="prose"><p>The foundations are under active development and are not a public release yet. Logs, metrics, traces, deployment records, organizations, typed queries, schema activation, and persisted dashboard definitions are being integrated before the first preview.</p><p>The interface remains useful without JavaScript. Progressive live updates add a small convenience; they do not own navigation, querying, or incident history.</p></div>
</section>
</main>
<?~ SiteFooter() ?>
</body>
</html>
+53
View File
@@ -0,0 +1,53 @@
// Code generated by himesan; DO NOT EDIT.
// himesan:compiler v1.0.0-beta.2
// himesan:runtime-abi sando.v1
// himesan:source-sha256 7a68dcec190a95c15b15d7bba50a9ba2a067a270c7d1f00b0349f4fd3784ba3b
package site
import (
__himesan_context "context"
__himesan_sando "gamertan.com/sandwich-hime/sando"
__himesan_io "io"
)
var _ = __himesan_sando.ABISandoV1
func Landing(view LandingView) __himesan_sando.Component {
return __himesan_sando.ComponentFunc(func(__himesan_render_context __himesan_context.Context, __himesan_writer __himesan_io.Writer) error {
_ = __himesan_render_context
//line internal/site/landing.sando:5:3
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/landing.sando:6:46
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n<!doctype html>\n<html lang=\"en\">\n<head>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/landing.sando:9:11
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (Head(view.Head))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/landing.sando:9:29
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</head>\n<body>\n <a class=\"skip-link\" href=\"#main\">Skip to content</a>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/landing.sando:12:7
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteHeader(false, "", ""))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/landing.sando:12:35
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <main id=\"main\">\n <section class=\"hero\" aria-labelledby=\"hero-title\">\n <p class=\"eyebrow\">Logs · metrics · traces · deployments</p>\n <h1 id=\"hero-title\">Keep the evidence close.</h1>\n <p class=\"lede\">Gamertan Observatory is a self-hosted observability platform being built for small, carefully operated Linux systems. It keeps raw evidence replayable, tenant boundaries explicit, and queries understandable.</p>\n <p><a class=\"button\" href=\"/login/\">Open Observatory</a></p>\n </section>\n <section class=\"section-grid\" aria-labelledby=\"working-model\">\n <div><p class=\"eyebrow\">Working model</p><h2 id=\"working-model\">One view without one giant trust boundary.</h2></div>\n <div class=\"cards\">\n <article><h3>Evidence first</h3><p>Checksummed raw segments are committed before projections acknowledge an ingest. Indexes and dashboards remain rebuildable views.</p></article>\n <article><h3>Scoped by the server</h3><p>Organization and resource identity come from enrolled sources and authenticated grants—not from telemetry payloads or query text.</p></article>\n <article><h3>Bounded by default</h3><p>Ingestion, storage, queries, subscribers, and fields have explicit limits. Sensitive data requires a separate permission.</p></article>\n </div>\n </section>\n <section class=\"section-grid\" aria-labelledby=\"preview-status\">\n <div><p class=\"eyebrow\">Current status</p><h2 id=\"preview-status\">A private development preview.</h2></div>\n <div class=\"prose\"><p>The foundations are under active development and are not a public release yet. Logs, metrics, traces, deployment records, organizations, typed queries, schema activation, and persisted dashboard definitions are being integrated before the first preview.</p><p>The interface remains useful without JavaScript. Progressive live updates add a small convenience; they do not own navigation, querying, or incident history.</p></div>\n </section>\n </main>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/landing.sando:33:7
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteFooter())); __himesan_error != nil {
return __himesan_error
}
//line internal/site/landing.sando:33:22
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n</body>\n</html>\n"); __himesan_error != nil {
return __himesan_error
}
return nil
})
}
+31
View File
@@ -0,0 +1,31 @@
<?sando go
package site
func Login(view LoginView)
?>
<?# SPDX-License-Identifier: AGPL-3.0-only ?>
<!doctype html>
<html lang="en">
<head><?~ Head(view.Head) ?></head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<?~ SiteHeader(false, "", "") ?>
<main id="main" class="auth-shell">
<section class="auth-card" aria-labelledby="login-title">
<p class="eyebrow">Private workshop</p>
<h1 id="login-title">Sign in to Observatory</h1>
<p>Use the local account created by <code>observatory admin bootstrap</code>.</p>
<? if view.ErrorMessage != "" { ?><p class="form-error" role="alert"><?= view.ErrorMessage ?></p><? } ?>
<form method="post" action="/login/">
<input type="hidden" name="csrf_token" value="<?= view.CSRFToken ?>">
<label for="identifier">Username or email</label>
<input id="identifier" name="identifier" autocomplete="username" required maxlength="320">
<label for="password">Password</label>
<input id="password" name="password" type="password" autocomplete="current-password" required maxlength="1024">
<button type="submit">Sign in</button>
</form>
</section>
</main>
<?~ SiteFooter() ?>
</body>
</html>
+81
View File
@@ -0,0 +1,81 @@
// Code generated by himesan; DO NOT EDIT.
// himesan:compiler v1.0.0-beta.2
// himesan:runtime-abi sando.v1
// himesan:source-sha256 dd75f02614b8688552456737ff2bfd5e9625897254989ab8ae2098b5fd5fccc9
package site
import (
__himesan_context "context"
__himesan_sando "gamertan.com/sandwich-hime/sando"
__himesan_io "io"
)
var _ = __himesan_sando.ABISandoV1
func Login(view LoginView) __himesan_sando.Component {
return __himesan_sando.ComponentFunc(func(__himesan_render_context __himesan_context.Context, __himesan_writer __himesan_io.Writer) error {
_ = __himesan_render_context
//line internal/site/login.sando:5:3
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/login.sando:6:46
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n<!doctype html>\n<html lang=\"en\">\n<head>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/login.sando:9:11
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (Head(view.Head))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/login.sando:9:29
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</head>\n<body>\n <a class=\"skip-link\" href=\"#main\">Skip to content</a>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/login.sando:12:7
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteHeader(false, "", ""))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/login.sando:12:35
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <main id=\"main\" class=\"auth-shell\">\n <section class=\"auth-card\" aria-labelledby=\"login-title\">\n <p class=\"eyebrow\">Private workshop</p>\n <h1 id=\"login-title\">Sign in to Observatory</h1>\n <p>Use the local account created by <code>observatory admin bootstrap</code>.</p>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/login.sando:18:10
if view.ErrorMessage != "" {
//line internal/site/login.sando:18:41
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<p class=\"form-error\" role=\"alert\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/login.sando:18:80
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.ErrorMessage)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/login.sando:18:100
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/login.sando:18:107
}
//line internal/site/login.sando:18:111
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <form method=\"post\" action=\"/login/\">\n <input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/login.sando:20:59
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.CSRFToken)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/login.sando:20:76
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <label for=\"identifier\">Username or email</label>\n <input id=\"identifier\" name=\"identifier\" autocomplete=\"username\" required maxlength=\"320\">\n <label for=\"password\">Password</label>\n <input id=\"password\" name=\"password\" type=\"password\" autocomplete=\"current-password\" required maxlength=\"1024\">\n <button type=\"submit\">Sign in</button>\n </form>\n </section>\n </main>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/login.sando:29:7
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteFooter())); __himesan_error != nil {
return __himesan_error
}
//line internal/site/login.sando:29:22
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n</body>\n</html>\n"); __himesan_error != nil {
return __himesan_error
}
return nil
})
}
+7
View File
@@ -0,0 +1,7 @@
<?sando go
package site
func Offline(view OfflineView)
?>
<?# SPDX-License-Identifier: AGPL-3.0-only ?>
<!doctype html><html lang="en"><head><?~ Head(view.Head) ?></head><body><a class="skip-link" href="#main">Skip to content</a><?~ SiteHeader(false, "", "") ?><main id="main"><section class="hero"><p class="eyebrow">Offline</p><h1>The evidence is still safe.</h1><p class="lede">Observatory cannot reach the server right now. A previously saved incident inbox remains available from its usual address; otherwise, reconnect before viewing private organization data.</p><p><a class="button secondary" href="/app/">Try Observatory again</a></p></section></main><?~ SiteFooter() ?></body></html>
+53
View File
@@ -0,0 +1,53 @@
// Code generated by himesan; DO NOT EDIT.
// himesan:compiler v1.0.0-beta.2
// himesan:runtime-abi sando.v1
// himesan:source-sha256 00fe79c601abcfc98b766fbb7332552b31cc92968251972bd24715f990812f09
package site
import (
__himesan_context "context"
__himesan_sando "gamertan.com/sandwich-hime/sando"
__himesan_io "io"
)
var _ = __himesan_sando.ABISandoV1
func Offline(view OfflineView) __himesan_sando.Component {
return __himesan_sando.ComponentFunc(func(__himesan_render_context __himesan_context.Context, __himesan_writer __himesan_io.Writer) error {
_ = __himesan_render_context
//line internal/site/offline.sando:5:3
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline.sando:6:46
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n<!doctype html><html lang=\"en\"><head>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline.sando:7:42
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (Head(view.Head))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline.sando:7:60
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</head><body><a class=\"skip-link\" href=\"#main\">Skip to content</a>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline.sando:7:130
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteHeader(false, "", ""))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline.sando:7:158
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<main id=\"main\"><section class=\"hero\"><p class=\"eyebrow\">Offline</p><h1>The evidence is still safe.</h1><p class=\"lede\">Observatory cannot reach the server right now. A previously saved incident inbox remains available from its usual address; otherwise, reconnect before viewing private organization data.</p><p><a class=\"button secondary\" href=\"/app/\">Try Observatory again</a></p></section></main>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline.sando:7:561
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteFooter())); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline.sando:7:576
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</body></html>\n"); __himesan_error != nil {
return __himesan_error
}
return nil
})
}
+24
View File
@@ -0,0 +1,24 @@
<?sando go
package site
func OfflineIncidentInbox(view OfflineIncidentView)
?>
<?# SPDX-License-Identifier: AGPL-3.0-only ?>
<!doctype html>
<html lang="en">
<head><?~ Head(view.Head) ?></head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<?~ SiteHeader(true, "incidents", view.Organization.ID) ?>
<main id="main" data-open-incident-count="<?= len(view.Incidents) ?>">
<nav class="breadcrumbs" aria-label="Breadcrumb"><a href="/app/">Overview</a><span aria-hidden="true">/</span><span aria-current="page">Saved incident inbox</span></nav>
<section class="app-intro" aria-labelledby="offline-incident-title"><div><p class="eyebrow">Offline snapshot · <?= view.Organization.Name ?></p><h1 id="offline-incident-title">Saved incident inbox</h1><p>Captured <?= view.CapturedAt ?>. Response actions are intentionally unavailable offline.</p></div></section>
<section class="section-grid" aria-labelledby="saved-incidents"><div><p class="eyebrow">Read-only</p><h2 id="saved-incidents">Incidents</h2></div><div class="incident-list">
<? if len(view.Incidents) == 0 { ?><p>No open incidents were present in this snapshot.</p><? } ?>
<? for _, incident := range view.Incidents { ?><article class="incident-card" data-state="<?= incident.State ?>"><p class="eyebrow"><?= incident.Severity ?> · <?= incident.State ?></p><h3><?= incident.Title ?></h3><dl><div><dt>Started</dt><dd><?= incident.StartedAt ?></dd></div><div><dt>Updated</dt><dd><?= incident.UpdatedAt ?></dd></div><? if incident.SilencedUntil != "" { ?><div><dt>Silenced until</dt><dd><?= incident.SilencedUntil ?></dd></div><? } ?></dl></article><? } ?>
</div></section>
<section class="section-grid" aria-labelledby="offline-boundary"><div><p class="eyebrow">Privacy boundary</p><h2 id="offline-boundary">This copy stays on this browser.</h2></div><div><p>It contains the organization name, incident titles, and states, but no response controls, CSRF tokens, query text, telemetry values, actor identifiers, or project, environment, or service identifiers. Signing out while online clears saved private snapshots.</p><p><a class="button secondary" href="/app/">Reconnect and refresh</a></p></div></section>
</main>
<?~ SiteFooter() ?>
</body>
</html>
+169
View File
@@ -0,0 +1,169 @@
// Code generated by himesan; DO NOT EDIT.
// himesan:compiler v1.0.0-beta.2
// himesan:runtime-abi sando.v1
// himesan:source-sha256 47e648ceed0893244cf41692e7a3d7ecc66a0cba09554e45b0d3dda3567bdfd7
package site
import (
__himesan_context "context"
__himesan_sando "gamertan.com/sandwich-hime/sando"
__himesan_io "io"
)
var _ = __himesan_sando.ABISandoV1
func OfflineIncidentInbox(view OfflineIncidentView) __himesan_sando.Component {
return __himesan_sando.ComponentFunc(func(__himesan_render_context __himesan_context.Context, __himesan_writer __himesan_io.Writer) error {
_ = __himesan_render_context
//line internal/site/offline_incidents.sando:5:3
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:6:46
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n<!doctype html>\n<html lang=\"en\">\n<head>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:9:11
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (Head(view.Head))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:9:29
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</head>\n<body>\n <a class=\"skip-link\" href=\"#main\">Skip to content</a>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:12:7
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteHeader(true, "incidents", view.Organization.ID))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:12:61
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <main id=\"main\" data-open-incident-count=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:13:49
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (len(view.Incidents))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:13:71
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <nav class=\"breadcrumbs\" aria-label=\"Breadcrumb\"><a href=\"/app/\">Overview</a><span aria-hidden=\"true\">/</span><span aria-current=\"page\">Saved incident inbox</span></nav>\n <section class=\"app-intro\" aria-labelledby=\"offline-incident-title\"><div><p class=\"eyebrow\">Offline snapshot · "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:15:121
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.Organization.Name)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:15:146
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p><h1 id=\"offline-incident-title\">Saved incident inbox</h1><p>Captured "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:15:223
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.CapturedAt)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:15:241
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, ". Response actions are intentionally unavailable offline.</p></div></section>\n <section class=\"section-grid\" aria-labelledby=\"saved-incidents\"><div><p class=\"eyebrow\">Read-only</p><h2 id=\"saved-incidents\">Incidents</h2></div><div class=\"incident-list\">\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:17:10
if len(view.Incidents) == 0 {
//line internal/site/offline_incidents.sando:17:42
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<p>No open incidents were present in this snapshot.</p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:17:100
}
//line internal/site/offline_incidents.sando:17:104
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:10
for _, incident := range view.Incidents {
//line internal/site/offline_incidents.sando:18:54
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<article class=\"incident-card\" data-state=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:101
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (incident.State)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:118
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\"><p class=\"eyebrow\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:143
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (incident.Severity)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:163
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, " · "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:171
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (incident.State)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:188
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p><h3>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:200
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (incident.Title)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:217
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</h3><dl><div><dt>Started</dt><dd>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:255
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (incident.StartedAt)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:276
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</dd></div><div><dt>Updated</dt><dd>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:316
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (incident.UpdatedAt)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:337
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</dd></div>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:351
if incident.SilencedUntil != "" {
//line internal/site/offline_incidents.sando:18:387
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<div><dt>Silenced until</dt><dd>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:423
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (incident.SilencedUntil)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:448
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</dd></div>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:462
}
//line internal/site/offline_incidents.sando:18:466
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</dl></article>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:18:484
}
//line internal/site/offline_incidents.sando:18:488
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </div></section>\n <section class=\"section-grid\" aria-labelledby=\"offline-boundary\"><div><p class=\"eyebrow\">Privacy boundary</p><h2 id=\"offline-boundary\">This copy stays on this browser.</h2></div><div><p>It contains the organization name, incident titles, and states, but no response controls, CSRF tokens, query text, telemetry values, actor identifiers, or project, environment, or service identifiers. Signing out while online clears saved private snapshots.</p><p><a class=\"button secondary\" href=\"/app/\">Reconnect and refresh</a></p></div></section>\n </main>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:22:7
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteFooter())); __himesan_error != nil {
return __himesan_error
}
//line internal/site/offline_incidents.sando:22:22
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n</body>\n</html>\n"); __himesan_error != nil {
return __himesan_error
}
return nil
})
}
+33
View File
@@ -0,0 +1,33 @@
<?sando go
package site
func Password(view PasswordView)
?>
<?# SPDX-License-Identifier: AGPL-3.0-only ?>
<!doctype html>
<html lang="en">
<head><?~ Head(view.Head) ?></head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<?~ SiteHeader(false, "", "") ?>
<main id="main" class="auth-shell">
<section class="auth-card" aria-labelledby="password-title">
<p class="eyebrow">One careful first step</p>
<h1 id="password-title">Choose your password</h1>
<p>The bootstrap credential is single-purpose. Replace it now; Observatory will end every session and ask you to sign in again.</p>
<? if view.ErrorMessage != "" { ?><p class="form-error" role="alert"><?= view.ErrorMessage ?></p><? } ?>
<form method="post" action="/account/password/">
<input type="hidden" name="csrf_token" value="<?= view.CSRFToken ?>">
<label for="current-password">Temporary password</label>
<input id="current-password" name="current_password" type="password" autocomplete="current-password" required maxlength="1024">
<label for="new-password">New password</label>
<input id="new-password" name="new_password" type="password" autocomplete="new-password" required minlength="12" maxlength="1024">
<label for="confirm-password">Confirm new password</label>
<input id="confirm-password" name="confirm_password" type="password" autocomplete="new-password" required minlength="12" maxlength="1024">
<button type="submit">Change password and sign out</button>
</form>
</section>
</main>
<?~ SiteFooter() ?>
</body>
</html>
+81
View File
@@ -0,0 +1,81 @@
// Code generated by himesan; DO NOT EDIT.
// himesan:compiler v1.0.0-beta.2
// himesan:runtime-abi sando.v1
// himesan:source-sha256 75a8b350f1635bc7a9ba4feb50aa4bc3b151783a3ebee72fc0e1947f7787c320
package site
import (
__himesan_context "context"
__himesan_sando "gamertan.com/sandwich-hime/sando"
__himesan_io "io"
)
var _ = __himesan_sando.ABISandoV1
func Password(view PasswordView) __himesan_sando.Component {
return __himesan_sando.ComponentFunc(func(__himesan_render_context __himesan_context.Context, __himesan_writer __himesan_io.Writer) error {
_ = __himesan_render_context
//line internal/site/password.sando:5:3
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/password.sando:6:46
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n<!doctype html>\n<html lang=\"en\">\n<head>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/password.sando:9:11
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (Head(view.Head))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/password.sando:9:29
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</head>\n<body>\n <a class=\"skip-link\" href=\"#main\">Skip to content</a>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/password.sando:12:7
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteHeader(false, "", ""))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/password.sando:12:35
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <main id=\"main\" class=\"auth-shell\">\n <section class=\"auth-card\" aria-labelledby=\"password-title\">\n <p class=\"eyebrow\">One careful first step</p>\n <h1 id=\"password-title\">Choose your password</h1>\n <p>The bootstrap credential is single-purpose. Replace it now; Observatory will end every session and ask you to sign in again.</p>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/password.sando:18:10
if view.ErrorMessage != "" {
//line internal/site/password.sando:18:41
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<p class=\"form-error\" role=\"alert\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/password.sando:18:80
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.ErrorMessage)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/password.sando:18:100
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</p>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/password.sando:18:107
}
//line internal/site/password.sando:18:111
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <form method=\"post\" action=\"/account/password/\">\n <input type=\"hidden\" name=\"csrf_token\" value=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/password.sando:20:59
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.CSRFToken)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/password.sando:20:76
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <label for=\"current-password\">Temporary password</label>\n <input id=\"current-password\" name=\"current_password\" type=\"password\" autocomplete=\"current-password\" required maxlength=\"1024\">\n <label for=\"new-password\">New password</label>\n <input id=\"new-password\" name=\"new_password\" type=\"password\" autocomplete=\"new-password\" required minlength=\"12\" maxlength=\"1024\">\n <label for=\"confirm-password\">Confirm new password</label>\n <input id=\"confirm-password\" name=\"confirm_password\" type=\"password\" autocomplete=\"new-password\" required minlength=\"12\" maxlength=\"1024\">\n <button type=\"submit\">Change password and sign out</button>\n </form>\n </section>\n </main>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/password.sando:31:7
if __himesan_error := __himesan_sando.Render(__himesan_render_context, __himesan_writer, (SiteFooter())); __himesan_error != nil {
return __himesan_error
}
//line internal/site/password.sando:31:22
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n</body>\n</html>\n"); __himesan_error != nil {
return __himesan_error
}
return nil
})
}
+102
View File
@@ -0,0 +1,102 @@
// SPDX-License-Identifier: AGPL-3.0-only
package site
import (
"crypto/sha256"
"encoding/hex"
"fmt"
)
func WebManifest() []byte {
assets := AssetPaths()
return []byte(fmt.Sprintf(`{"id":"/app/","name":"Gamertan Observatory","short_name":"Observatory","description":"A self-hosted, organization-aware observability workshop.","start_url":"/app/","scope":"/","display":"standalone","background_color":"#111715","theme_color":"#111715","icons":[{"src":%q,"sizes":"any","type":"image/svg+xml","purpose":"any maskable"}]}`+"\n", assets.IconPath))
}
func ServiceWorker() []byte {
assets := AssetPaths()
revisionSource := append(append(append([]byte(nil), style...), script...), icon...)
revision := sha256.Sum256(revisionSource)
return []byte(fmt.Sprintf(`/* SPDX-License-Identifier: AGPL-3.0-only */
"use strict";
const SHELL_CACHE = %q;
const PRIVATE_CACHE = "observatory-private-v1";
const PUSH_MESSAGE = %q;
const PUSH_ICON = %q;
const SHELL = [%q,%q,%q,%q];
self.addEventListener("install", event => {
event.waitUntil(caches.open(SHELL_CACHE).then(cache => cache.addAll(SHELL)));
self.skipWaiting();
});
self.addEventListener("activate", event => {
event.waitUntil((async () => {
for (const name of await caches.keys()) {
if (name.startsWith("observatory-shell-") && name !== SHELL_CACHE) await caches.delete(name);
}
await self.clients.claim();
})());
});
self.addEventListener("fetch", event => {
const request = event.request;
if (request.method !== "GET") return;
const url = new URL(request.url);
if (url.origin !== self.location.origin) return;
if (request.mode === "navigate") {
event.respondWith((async () => {
try {
const response = await fetch(request);
if (response.status < 500) return response;
const saved = await caches.open(PRIVATE_CACHE).then(cache => cache.match(request));
return saved || response;
} catch (_) {
const saved = await caches.open(PRIVATE_CACHE).then(cache => cache.match(request));
return saved || await caches.match("/offline/");
}
})());
return;
}
if (SHELL.includes(url.pathname)) {
event.respondWith(caches.match(request).then(saved => saved || fetch(request)));
}
});
self.addEventListener("message", event => {
const reply = value => { if (event.ports[0]) event.ports[0].postMessage(value); };
if (!event.data || typeof event.data.type !== "string") return;
if (event.data.type === "clear-private") {
event.waitUntil(caches.delete(PRIVATE_CACHE).then(() => reply({ok:true})));
return;
}
if (event.data.type !== "cache-inbox") return;
event.waitUntil((async () => {
try {
const source = new URL(event.data.source, self.location.origin);
const target = new URL(event.data.target, self.location.origin);
const valid = source.origin === self.location.origin && target.origin === self.location.origin &&
source.pathname === "/app/incidents/offline/" && target.pathname === "/app/incidents/" &&
source.search === target.search && source.searchParams.size === 1 && source.searchParams.has("organization");
if (!valid) throw new Error("invalid inbox cache request");
const response = await fetch(source.href, {credentials:"include",cache:"no-store"});
if (!response.ok || !(response.headers.get("content-type") || "").startsWith("text/html")) throw new Error("offline inbox unavailable");
const cache = await caches.open(PRIVATE_CACHE);
await cache.put(new Request(target.href, {method:"GET"}), response);
reply({ok:true});
} catch (_) { reply({ok:false}); }
})());
});
self.addEventListener("push", event => {
event.waitUntil(self.registration.showNotification(PUSH_MESSAGE, {icon:PUSH_ICON,badge:PUSH_ICON,tag:"observatory-attention",renotify:true,data:{url:"/app/"}}));
});
self.addEventListener("notificationclick", event => {
event.notification.close();
event.waitUntil((async () => {
for (const client of await self.clients.matchAll({type:"window",includeUncontrolled:true})) {
if (new URL(client.url).origin === self.location.origin) {
await client.navigate("/app/");
return client.focus();
}
}
return self.clients.openWindow("/app/");
})());
});
`, "observatory-shell-"+hex.EncodeToString(revision[:8]), "Gamertan Observatory needs your attention.", assets.IconPath, "/offline/", assets.StylePath, assets.ScriptPath, assets.IconPath))
}
+50
View File
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: AGPL-3.0-only
package site
import (
"encoding/json"
"strings"
"testing"
)
func TestManifestAndServiceWorkerUseExactContentAddressedShell(t *testing.T) {
var manifest struct {
ID string `json:"id"`
Name string `json:"name"`
StartURL string `json:"start_url"`
Scope string `json:"scope"`
Display string `json:"display"`
Icons []struct {
Source string `json:"src"`
Sizes string `json:"sizes"`
Type string `json:"type"`
Purpose string `json:"purpose"`
} `json:"icons"`
}
if err := json.Unmarshal(WebManifest(), &manifest); err != nil {
t.Fatal(err)
}
assets := AssetPaths()
if manifest.ID != "/app/" || manifest.Name != "Gamertan Observatory" || manifest.StartURL != "/app/" || manifest.Scope != "/" || manifest.Display != "standalone" || len(manifest.Icons) != 1 || manifest.Icons[0].Source != assets.IconPath || manifest.Icons[0].Sizes != "any" || manifest.Icons[0].Type != "image/svg+xml" || manifest.Icons[0].Purpose != "any maskable" {
t.Fatalf("manifest=%+v", manifest)
}
worker := string(ServiceWorker())
for _, required := range []string{"/offline/", assets.StylePath, assets.ScriptPath, assets.IconPath, "cache-inbox", "clear-private", "credentials:\"include\"", "source.pathname === \"/app/incidents/offline/\"", "target.pathname === \"/app/incidents/\"", "Gamertan Observatory needs your attention.", `self.addEventListener("push"`, `self.addEventListener("notificationclick"`, `data:{url:"/app/"}`} {
if !strings.Contains(worker, required) {
t.Fatalf("service worker missing %q", required)
}
}
for _, forbidden := range []string{"query_text", "csrf_token", "telemetry", "incident.title", "organization_id", "service_id", "severity", "rule_id", "console.log", "eval("} {
if strings.Contains(worker, forbidden) {
t.Fatalf("service worker contains forbidden %q", forbidden)
}
}
if strings.Count(worker, "Gamertan Observatory needs your attention.") != 1 {
t.Fatal("service worker did not contain exactly one fixed notification message")
}
if first, second := string(ServiceWorker()), string(ServiceWorker()); first != second {
t.Fatal("service worker output is not deterministic")
}
}
+24
View File
@@ -0,0 +1,24 @@
<?sando go
package site
func ResultTable(view TableView)
?>
<?# SPDX-License-Identifier: AGPL-3.0-only ?>
<div class="table-scroll" tabindex="0" role="region" aria-label="<?= view.Caption ?>">
<table>
<caption><?= view.Caption ?></caption>
<thead><tr>
<? for _, column := range view.Columns { ?>
<th scope="col"><?= column.Label ?><? if column.Unit != "" { ?> <span class="unit">(<?= column.Unit ?>)</span><? } ?></th>
<? } ?>
</tr></thead>
<tbody>
<? for _, row := range view.Rows { ?>
<tr><? for _, value := range row.Values { ?><td><?= value ?></td><? } ?></tr>
<? } ?>
<? if len(view.Rows) == 0 { ?>
<tr><td colspan="<?= len(view.Columns) ?>"><?= view.Empty ?></td></tr>
<? } ?>
</tbody>
</table>
</div>
+141
View File
@@ -0,0 +1,141 @@
// Code generated by himesan; DO NOT EDIT.
// himesan:compiler v1.0.0-beta.2
// himesan:runtime-abi sando.v1
// himesan:source-sha256 bf3381b912a1264323672beac6aeed2a2ddb770904404f9597645ac09d2981ae
package site
import (
__himesan_context "context"
__himesan_sando "gamertan.com/sandwich-hime/sando"
__himesan_io "io"
)
var _ = __himesan_sando.ABISandoV1
func ResultTable(view TableView) __himesan_sando.Component {
return __himesan_sando.ComponentFunc(func(__himesan_render_context __himesan_context.Context, __himesan_writer __himesan_io.Writer) error {
_ = __himesan_render_context
//line internal/site/result_table.sando:5:3
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:6:46
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n<div class=\"table-scroll\" tabindex=\"0\" role=\"region\" aria-label=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:7:70
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (view.Caption)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:7:85
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">\n <table>\n <caption>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:9:18
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.Caption)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:9:33
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</caption>\n <thead><tr>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:11:8
for _, column := range view.Columns {
//line internal/site/result_table.sando:11:48
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <th scope=\"col\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:12:27
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (column.Label)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:12:45
if column.Unit != "" {
//line internal/site/result_table.sando:12:70
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, " <span class=\"unit\">("); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:12:95
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (column.Unit)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:12:109
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, ")</span>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:12:120
}
//line internal/site/result_table.sando:12:124
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</th>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:13:8
}
//line internal/site/result_table.sando:13:12
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </tr></thead>\n <tbody>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:16:8
for _, row := range view.Rows {
//line internal/site/result_table.sando:16:42
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <tr>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:17:14
for _, value := range row.Values {
//line internal/site/result_table.sando:17:51
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<td>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:17:59
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (value)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:17:67
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</td>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:17:75
}
//line internal/site/result_table.sando:17:79
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</tr>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:18:8
}
//line internal/site/result_table.sando:18:12
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:19:8
if len(view.Rows) == 0 {
//line internal/site/result_table.sando:19:35
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <tr><td colspan=\""); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:20:28
if __himesan_error := __himesan_sando.WriteAttr(__himesan_writer, (len(view.Columns))); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:20:48
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:20:54
if __himesan_error := __himesan_sando.WriteText(__himesan_writer, (view.Empty)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:20:67
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "</td></tr>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/result_table.sando:21:8
}
//line internal/site/result_table.sando:21:12
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </tbody>\n </table>\n</div>\n"); __himesan_error != nil {
return __himesan_error
}
return nil
})
}
+9
View File
@@ -0,0 +1,9 @@
<?sando go
package site
func SiteFooter()
?>
<?# SPDX-License-Identifier: AGPL-3.0-only ?>
<footer class="site-footer">
<p>Self-hosted, evidence-minded observability. Built and tended by Gamertan.</p>
</footer>
+29
View File
@@ -0,0 +1,29 @@
// Code generated by himesan; DO NOT EDIT.
// himesan:compiler v1.0.0-beta.2
// himesan:runtime-abi sando.v1
// himesan:source-sha256 df9cf0c1ef86d0317606ba4eccb618cfe2d0925ef83dd572df78beaa6d2c254f
package site
import (
__himesan_context "context"
__himesan_sando "gamertan.com/sandwich-hime/sando"
__himesan_io "io"
)
var _ = __himesan_sando.ABISandoV1
func SiteFooter() __himesan_sando.Component {
return __himesan_sando.ComponentFunc(func(__himesan_render_context __himesan_context.Context, __himesan_writer __himesan_io.Writer) error {
_ = __himesan_render_context
//line internal/site/site_footer.sando:5:3
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_footer.sando:6:46
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n<footer class=\"site-footer\">\n <p>Self-hosted, evidence-minded observability. Built and tended by Gamertan.</p>\n</footer>\n"); __himesan_error != nil {
return __himesan_error
}
return nil
})
}
+20
View File
@@ -0,0 +1,20 @@
<?sando go
package site
func SiteHeader(authenticated bool, current string, organizationID string)
?>
<?# SPDX-License-Identifier: AGPL-3.0-only ?>
<header class="site-header">
<? if authenticated { ?>
<a class="wordmark" href="/app/?organization=<?= organizationID ?>">Gamertan Observatory</a>
<nav aria-label="Primary">
<? if current == "overview" { ?><a aria-current="page" href="/app/?organization=<?= organizationID ?>">Overview</a><? } else { ?><a href="/app/?organization=<?= organizationID ?>">Overview</a><? } ?>
<? if current == "explore" { ?><a aria-current="page" href="/app/explore/?organization=<?= organizationID ?>">Explore</a><? } else { ?><a href="/app/explore/?organization=<?= organizationID ?>">Explore</a><? } ?>
<? if current == "dashboards" { ?><a aria-current="page" href="/app/?organization=<?= organizationID ?>#dashboards">Dashboards</a><? } else { ?><a href="/app/?organization=<?= organizationID ?>#dashboards">Dashboards</a><? } ?>
<? if current == "incidents" { ?><a aria-current="page" href="/app/incidents/?organization=<?= organizationID ?>">Incidents</a><? } else { ?><a href="/app/incidents/?organization=<?= organizationID ?>">Incidents</a><? } ?>
</nav>
<? } else { ?>
<a class="wordmark" href="/">Gamertan Observatory</a>
<nav aria-label="Primary"><a href="/login/">Sign in</a></nav>
<? } ?>
</header>
+191
View File
@@ -0,0 +1,191 @@
// Code generated by himesan; DO NOT EDIT.
// himesan:compiler v1.0.0-beta.2
// himesan:runtime-abi sando.v1
// himesan:source-sha256 5e30e1ad98c586ffdc566d3688d3288d918faf5645804cd18ef6233a1e250e6b
package site
import (
__himesan_context "context"
__himesan_sando "gamertan.com/sandwich-hime/sando"
__himesan_io "io"
)
var _ = __himesan_sando.ABISandoV1
func SiteHeader(authenticated bool, current string, organizationID string) __himesan_sando.Component {
return __himesan_sando.ComponentFunc(func(__himesan_render_context __himesan_context.Context, __himesan_writer __himesan_io.Writer) error {
_ = __himesan_render_context
//line internal/site/site_header.sando:5:3
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:6:46
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n<header class=\"site-header\">\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:8:6
if authenticated {
//line internal/site/site_header.sando:8:27
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <a class=\"wordmark\" href=\"/app/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:9:54
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (organizationID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:9:71
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Gamertan Observatory</a>\n <nav aria-label=\"Primary\">\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:11:10
if current == "overview" {
//line internal/site/site_header.sando:11:39
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<a aria-current=\"page\" href=\"/app/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:11:91
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (organizationID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:11:108
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Overview</a>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:11:125
} else {
//line internal/site/site_header.sando:11:136
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<a href=\"/app/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:11:168
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (organizationID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:11:185
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Overview</a>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:11:202
}
//line internal/site/site_header.sando:11:206
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:12:10
if current == "explore" {
//line internal/site/site_header.sando:12:38
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<a aria-current=\"page\" href=\"/app/explore/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:12:98
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (organizationID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:12:115
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Explore</a>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:12:131
} else {
//line internal/site/site_header.sando:12:142
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<a href=\"/app/explore/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:12:182
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (organizationID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:12:199
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Explore</a>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:12:215
}
//line internal/site/site_header.sando:12:219
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:13:10
if current == "dashboards" {
//line internal/site/site_header.sando:13:41
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<a aria-current=\"page\" href=\"/app/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:13:93
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (organizationID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:13:110
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "#dashboards\">Dashboards</a>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:13:140
} else {
//line internal/site/site_header.sando:13:151
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<a href=\"/app/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:13:183
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (organizationID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:13:200
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "#dashboards\">Dashboards</a>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:13:230
}
//line internal/site/site_header.sando:13:234
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:14:10
if current == "incidents" {
//line internal/site/site_header.sando:14:40
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<a aria-current=\"page\" href=\"/app/incidents/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:14:102
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (organizationID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:14:119
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Incidents</a>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:14:137
} else {
//line internal/site/site_header.sando:14:148
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "<a href=\"/app/incidents/?organization="); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:14:190
if __himesan_error := __himesan_sando.WriteURL(__himesan_writer, (organizationID)); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:14:207
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\">Incidents</a>"); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:14:225
}
//line internal/site/site_header.sando:14:229
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n </nav>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:16:6
} else {
//line internal/site/site_header.sando:16:17
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n <a class=\"wordmark\" href=\"/\">Gamertan Observatory</a>\n <nav aria-label=\"Primary\"><a href=\"/login/\">Sign in</a></nav>\n "); __himesan_error != nil {
return __himesan_error
}
//line internal/site/site_header.sando:19:6
}
//line internal/site/site_header.sando:19:10
if __himesan_error := __himesan_sando.WriteString(__himesan_writer, "\n</header>\n"); __himesan_error != nil {
return __himesan_error
}
return nil
})
}
+192
View File
@@ -0,0 +1,192 @@
// SPDX-License-Identifier: AGPL-3.0-only
package site
type HeadView struct {
Title string
Description string
CanonicalURL string
Assets Assets
}
type LandingView struct{ Head HeadView }
type LoginView struct {
Head HeadView
CSRFToken string
ErrorMessage string
}
type PasswordView struct {
Head HeadView
CSRFToken string
ErrorMessage string
}
type OrganizationOption struct {
ID string
Name string
Selected bool
}
type TableColumn struct {
Label string
Unit string
}
type TableRow struct{ Values []string }
type TableView struct {
Caption string
Columns []TableColumn
Rows []TableRow
Empty string
}
type SignalView struct {
ID string
Name string
Description string
Query string
Table TableView
}
type SavedQuerySummary struct {
ID string
Name string
Description string
Query string
}
type DashboardSummary struct {
Slug string
Name string
Description string
PanelCount int
}
type AppView struct {
Head HeadView
DisplayName string
Organizations []OrganizationOption
Organization OrganizationOption
Signals []SignalView
SavedQueries []SavedQuerySummary
Dashboards []DashboardSummary
CSRFToken string
ManageCSRF string
CanManage bool
EventsURL string
RefreshedAt string
ProjectionLag string
PendingBatches int
IncidentsURL string
OpenIncidents int
}
type QueryStatsView struct {
ScannedRows int
MatchedRows int
ScannedBytes string
Duration string
Truncated bool
Approximate bool
}
type ExploreView struct {
Head HeadView
DisplayName string
Organization OrganizationOption
Query string
CSRFToken string
EventsURL string
Executed bool
ErrorMessage string
Table TableView
Stats QueryStatsView
}
type IncidentSummary struct {
ID string
Title string
State string
Severity string
StartedAt string
UpdatedAt string
SilencedUntil string
}
type AlertRuleSummary struct {
Name string
Description string
Severity string
Enabled bool
Interval string
LastEvaluatedAt string
LastError string
}
type IncidentInboxView struct {
Head HeadView
DisplayName string
Organization OrganizationOption
Incidents []IncidentSummary
Rules []AlertRuleSummary
SavedQueries []SavedQuerySummary
CanManage bool
ManageCSRF string
EventsURL string
OfflineURL string
CacheKey string
OpenCount int
PushPublicKey string
PushCSRF string
}
type OfflineIncidentView struct {
Head HeadView
Organization OrganizationOption
Incidents []IncidentSummary
CapturedAt string
}
type OfflineView struct{ Head HeadView }
type PanelView struct {
ID string
SavedQueryID string
Title string
Visualization string
Query string
Stat string
Chart ChartView
Table TableView
}
type ChartPoint struct {
Label string
Value string
Maximum string
Display string
}
type ChartView struct {
Label string
Points []ChartPoint
}
type DashboardView struct {
Head HeadView
DisplayName string
Organization OrganizationOption
ID string
Slug string
Revision int
Name string
Description string
ExportURL string
Panels []PanelView
SavedQueries []SavedQuerySummary
CanManage bool
ManageCSRF string
}