move anchor config to frontend dropdowns + localStorage, remove /api/settings

This commit is contained in:
Meleki committed 2026-02-22 22:24:44 +01:00
1 parent c245e0e374
commit e2c7adab90
5 files changed
+66 -17

No files matched your search

-8
View File
@@ -15,14 +15,6 @@ var app = builder.Build();
app.UseDefaultFiles();
app.UseStaticFiles();
// GET /api/settings
app.MapGet("/api/settings", (IConfiguration config) =>
{
var anchorDay = int.TryParse(config["AnchorDay"], out var d) ? d : 0;
var anchorHour = int.TryParse(config["AnchorHour"], out var h) ? h : 0;
return Results.Ok(new { anchorDay, anchorHour });
});
// GET /api/cost-buckets?from=&to=&bucketMinutes=
// Returns N buckets of aggregated cost
app.MapGet("/api/cost-buckets", (Func<SqliteConnection> factory, string from, string to, int bucketMinutes) =>
+1 -3
View File
@@ -7,7 +7,5 @@
},
"AllowedHosts": "*",
"Urls": "http://0.0.0.0:18684",
"DbPath": "../jsonl-sync/sessions.db",
"AnchorDay": 0,
"AnchorHour": 0
"DbPath": "../jsonl-sync/sessions.db"
}
+39 -6
View File
@@ -68,12 +68,34 @@ async function init() {
$('modal').addEventListener('click', e => { if (e.target === $('modal')) closeModal(); });
document.addEventListener('keydown', e => { if (e.key === 'Escape') closeModal(); });
// Load anchor settings
try {
const settings = await api('/api/settings');
if (settings.anchorDay != null) ANCHOR_DAY = settings.anchorDay;
if (settings.anchorHour != null) ANCHOR_HOUR = settings.anchorHour;
} catch {}
// Anchor dropdowns
const daySelect = $('anchor-day');
const hourSelect = $('anchor-hour');
for (let h = 0; h < 24; h++) {
const opt = document.createElement('option');
opt.value = h;
opt.textContent = h.toString().padStart(2, '0') + ':00';
hourSelect.appendChild(opt);
}
// Load from localStorage
const savedDay = localStorage.getItem('anchorDay');
const savedHour = localStorage.getItem('anchorHour');
if (savedDay != null) ANCHOR_DAY = parseInt(savedDay);
if (savedHour != null) ANCHOR_HOUR = parseInt(savedHour);
daySelect.value = ANCHOR_DAY;
hourSelect.value = ANCHOR_HOUR;
daySelect.addEventListener('change', () => {
ANCHOR_DAY = parseInt(daySelect.value);
localStorage.setItem('anchorDay', ANCHOR_DAY);
resetToStart();
});
hourSelect.addEventListener('change', () => {
ANCHOR_HOUR = parseInt(hourSelect.value);
localStorage.setItem('anchorHour', ANCHOR_HOUR);
resetToStart();
});
zoomIndex = 0;
const range = getAnchoredRange(zoomIndex);
@@ -445,6 +467,17 @@ function enterEntryMode(bucketStart, bucketEnd) {
loadView();
}
function resetToStart() {
location.hash = '';
zoomIndex = 0;
entryMode = false;
zoomStack = [];
const range = getAnchoredRange(zoomIndex);
viewFrom = range.from;
viewTo = range.to;
loadView();
}
function zoomOut() {
if (zoomStack.length) {
const prev = zoomStack.pop();
+9
View File
@@ -10,6 +10,15 @@
<header>
<h1>Cost Analytics</h1>
<div id="summary"></div>
<div id="anchor-config">
<label>Anker:</label>
<select id="anchor-day">
<option value="0">So</option><option value="1">Mo</option><option value="2">Di</option>
<option value="3">Mi</option><option value="4">Do</option><option value="5">Fr</option>
<option value="6">Sa</option>
</select>
<select id="anchor-hour"></select>
</div>
<button id="btn-sync" title="Neue Einträge importieren">↻ Sync</button>
</header>
+17
View File
@@ -34,6 +34,23 @@ header {
header h1 { font-size: 1.1rem; font-weight: 600; color: var(--accent); }
#anchor-config {
display: flex;
align-items: center;
gap: 6px;
font-size: 0.8rem;
color: var(--muted);
}
#anchor-config select {
background: var(--surface);
color: var(--text);
border: 1px solid var(--border);
border-radius: 4px;
padding: 2px 4px;
font-size: 0.8rem;
}
#btn-sync {
background: var(--border);
color: var(--text);