Fix bugs found in local testing

- Dashboard auto-refresh rendered the full layout into its own
  refresh container, producing a duplicate sidebar every 60s; it now
  renders only the body partial.
- 'Run Now' runs synchronously with a bounded timeout and returns
  refreshed results plus success/error feedback, instead of
  firing-and-forgetting with no signal.
- Price-history chart data moved from a <script> block to a data-
  attribute: templ does not interpolate expressions inside <script>
  element content, so the JSON was emitted literally.
- The htmx indicator spinner was permanently visible due to CSS
  source order; the indicator rules now follow .v-spinner.

Also refreshes README for this session's changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
prosolis
2026-05-14 12:11:07 -07:00
parent 08ff1695e0
commit d87536c879
12 changed files with 550 additions and 366 deletions

View File

@@ -193,11 +193,6 @@ table.v-table tr:hover td { background: rgba(255,255,255,0.03); }
margin-bottom: 1rem;
}
/* htmx indicator: hidden by default, visible during in-flight requests. */
.htmx-indicator { display: none; }
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator { display: inline-flex; }
.v-spinner {
display: inline-block;
width: 14px; height: 14px;
@@ -207,3 +202,11 @@ table.v-table tr:hover td { background: rgba(255,255,255,0.03); }
animation: v-spin 0.8s linear infinite;
}
@keyframes v-spin { to { transform: rotate(360deg); } }
/* htmx indicator: hidden by default, visible during in-flight requests.
Declared AFTER .v-spinner on purpose: an element carrying both classes
(e.g. <span class="v-spinner htmx-indicator">) must stay hidden until a
request is active, and equal-specificity rules resolve by source order. */
.htmx-indicator { display: none; }
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator { display: inline-flex; }

35
static/js/price-chart.js Normal file
View File

@@ -0,0 +1,35 @@
// Renders the price-history line chart on the per-item results page.
// Chart data is read from the canvas's data-chart attribute: templ
// interpolates attribute values but treats <script> element contents as raw
// text, so the JSON cannot live in an inline <script> block. Loaded after
// chart.umd.min.js with the #price-chart canvas already in the DOM above it.
(function () {
var canvas = document.getElementById('price-chart');
if (!canvas || !canvas.dataset.chart || typeof Chart === 'undefined') {
return;
}
var data = JSON.parse(canvas.dataset.chart);
new Chart(canvas.getContext('2d'), {
type: 'line',
data: {
labels: data.labels,
datasets: [{
label: 'Best price',
data: data.points,
borderColor: '#00e4a4',
backgroundColor: 'rgba(0,228,164,0.15)',
pointBackgroundColor: '#e84040',
pointRadius: 3,
tension: 0.25,
fill: true
}]
},
options: {
scales: {
x: { ticks: { color: '#a8c0f0' }, grid: { color: 'rgba(255,255,255,0.07)' } },
y: { ticks: { color: '#a8c0f0' }, grid: { color: 'rgba(255,255,255,0.07)' } }
},
plugins: { legend: { labels: { color: '#ffffff' } } }
}
});
})();