Files
komp_ac/web/static/index.html
2026-08-03 12:23:50 +02:00

113 lines
6.1 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Analytics graphs</title>
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2/dist/htmx.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts@6/dist/echarts.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3/dist/cdn.min.js"></script>
<style>
* { box-sizing: border-box; }
[x-cloak] { display: none !important; }
body { margin: 0; font: 14px system-ui, sans-serif; color: #17202a; background: #f4f6f8; }
main { width: min(1500px, calc(100% - 32px)); margin: 24px auto; }
h1 { margin: 0 0 18px; font-size: 24px; }
h2 { margin: 0 0 14px; font-size: 17px; }
.panel { margin-bottom: 16px; padding: 18px; border: 1px solid #dfe4ea; border-radius: 10px; background: white; }
.workspace { display: grid; grid-template-columns: minmax(290px, 380px) minmax(0, 1fr); align-items: start; gap: 16px; }
.sidebar { position: sticky; top: 16px; max-height: calc(100vh - 32px); overflow: auto; }
.sidebar h2 { margin-bottom: 6px; }
.catalog-load { display: grid; grid-template-columns: 1fr auto; align-items: end; gap: 8px; margin: 14px 0; }
.catalog-load label { margin: 0; }
.schema-summary { margin: 8px 0; }
.catalog-table { border-top: 1px solid #e4e7ec; padding: 9px 0; }
.catalog-table summary { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.currency { color: #667085; font-size: 11px; }
.starter-query, .secondary { margin-top: 9px; padding: 6px 9px; color: #344054; background: #eef2f6; }
.columns, .links ul { margin: 8px 0; padding: 0; list-style: none; }
.columns li { display: flex; justify-content: space-between; gap: 8px; padding: 3px 0; }
.columns li span { color: #667085; font-size: 11px; text-align: right; }
.column-name { padding: 0; color: #2563eb; background: none; font-family: ui-monospace, monospace; text-align: left; }
.links { color: #667085; font-size: 12px; }
.links li { padding: 2px 0; }
.llm-context { border-top: 1px solid #e4e7ec; margin-top: 10px; padding-top: 10px; }
.llm-context summary { cursor: pointer; font-weight: 600; }
.llm-context textarea { min-height: 320px; margin-top: 8px; font-size: 11px; }
.top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 18px; }
.top h1 { margin: 0; }
.top a { color: #2563eb; }
.query-row { display: grid; grid-template-columns: 180px 120px; gap: 12px; margin-bottom: 12px; }
label { display: grid; gap: 5px; color: #4b5563; font-size: 12px; }
input, select, textarea, button { font: inherit; }
input, select, textarea { width: 100%; border: 1px solid #cfd6dd; border-radius: 6px; padding: 9px; background: white; }
textarea { min-height: 130px; resize: vertical; font-family: ui-monospace, monospace; line-height: 1.45; }
button { border: 0; border-radius: 6px; padding: 10px 18px; color: white; background: #2563eb; cursor: pointer; }
button:disabled { opacity: .55; }
.htmx-request button, button.htmx-request { opacity: .55; cursor: wait; }
.actions { display: flex; align-items: center; gap: 12px; margin-top: 12px; }
.hint, .result-meta { color: #667085; }
.error { color: #b42318; }
.success { color: #067647; }
.chart { height: 560px; }
.table-wrap { max-height: 560px; overflow: auto; }
table { width: 100%; border-collapse: collapse; background: white; }
th, td { padding: 9px 11px; border: 1px solid #e4e7ec; text-align: left; white-space: nowrap; }
th { position: sticky; top: 0; background: #f9fafb; }
@media (max-width: 760px) {
.workspace { grid-template-columns: 1fr; }
.sidebar { position: static; max-height: none; }
.query-row { grid-template-columns: 1fr; }
main { width: calc(100% - 20px); }
}
</style>
</head>
<body>
<main x-data="{ sql: '', copied: false }">
<div class="top"><h1>Analytics graphs</h1><div><a href="/admin">Admin panel</a> · <a href="/login">Login</a></div></div>
<div class="workspace">
<aside class="panel sidebar">
<h2>Available data</h2>
<p class="hint">Load a profile to see the table and column aliases accepted by analytics SQL.</p>
<div hx-get="/api/profiles" hx-trigger="load" hx-target="#profile" hx-swap="innerHTML">
<form class="catalog-load" hx-post="/api/catalog" hx-target="#catalog" hx-swap="innerHTML" hx-disabled-elt="button">
<label>Profile
<select id="profile" name="profile_name" hx-post="/api/catalog" hx-trigger="change" hx-target="#catalog" hx-swap="innerHTML">
<option value="">Loading profiles…</option>
</select>
</label>
<button type="submit">Load schema</button>
</form>
</div>
<div id="catalog" aria-live="polite"><p class="hint">No schema loaded.</p></div>
</aside>
<section>
<form id="query-form" class="panel" hx-post="/api/query" hx-include="#profile" hx-target="#output" hx-swap="innerHTML" hx-disabled-elt="button">
<div class="query-row">
<label>Chart
<select name="chart_type">
<option value="bar">Bar</option>
<option value="line">Line</option>
<option value="pie">Pie</option>
<option value="scatter">Scatter</option>
<option value="table">Table</option>
</select>
</label>
<label>Max rows<input name="max_rows" type="number" min="1" value="1000"></label>
</div>
<label>SQL<textarea id="sql" x-ref="sql" x-model="sql" name="sql" required spellcheck="false" placeholder="Load the schema, then choose a starter query or write a SELECT query"></textarea></label>
<div class="actions">
<button type="submit">Run query</button>
<span class="htmx-indicator hint">Running…</span>
</div>
</form>
<section id="output" aria-live="polite"></section>
</section>
</div>
</main>
</body>
</html>