Retry the strategy list and make collapse obvious

- The strategy/preset lists were loaded once with failures swallowed, so a
  single failed first request left the strategy dropdown empty forever. They
  are now retried every 3s until populated.
- Clearer collapse affordance: hover highlight, a hide/show hint, and a
  tooltip; Backtest and Parameter sweep start collapsed so the strategy
  selector and status are immediately visible.
- Adds an integration test that the strategy dropdown is populated and the
  panel actually collapses.
This commit is contained in:
matitos committed 2026-09-21 17:11:18 +00:00
1 parent 9eddd66a82
commit b9c69c546c
5 files changed
+69 -6

No files matched your search

+16 -3
View File
@@ -55,6 +55,7 @@ let socket
let pollTimer
let statusTimer
let graceTimer
let listTimer
async function refreshAll() {
const [p, o, e, q] = await Promise.all([
@@ -183,11 +184,15 @@ onMounted(() => {
if (!connected.value) pollingFallback.value = true
}, 6000)
// Initial loads are best-effort; the intervals below keep retrying.
// Initial loads are best-effort.
api.getStatus().then((s) => (status.value = s)).catch(() => {})
refreshAll().catch(() => {})
loadStrategies().catch(() => {})
loadPresets().catch(() => {})
// The strategy list and presets rarely change, so load them once but keep
// retrying until they arrive: a single failed first request used to leave the
// strategy dropdown empty forever.
loadStrategies()
loadPresets()
// Poll fast enough that the UI feels live even when it is the only channel.
pollTimer = setInterval(() => refreshAll().catch(() => {}), 3000)
@@ -195,12 +200,20 @@ onMounted(() => {
() => api.getStatus().then((s) => (status.value = s)).catch(() => {}),
3000,
)
// Retry the static lists until non-empty (covers a failed first load and a
// backend that was still starting up).
listTimer = setInterval(() => {
if (!strategies.value.length) loadStrategies()
if (!presets.value.length) loadPresets()
if (strategies.value.length && presets.value.length) clearInterval(listTimer)
}, 3000)
})
onUnmounted(() => {
socket?.close()
clearInterval(pollTimer)
clearInterval(statusTimer)
clearInterval(listTimer)
clearTimeout(graceTimer)
})
</script>