From a9637fafb28478347457bea26f7bb49fd549e5bb Mon Sep 17 00:00:00 2001 From: dekun Date: Thu, 11 Jun 2026 19:44:51 +0800 Subject: [PATCH] fix(hub): archive labels, symbol column, and time-close dropdown Force exchange_key on archive sync; add contract column and tag select styles on inner-light-mind; serve time_close_ui.js on instances so order/key time-close duration can be selected. Co-authored-by: Cursor --- crypto_monitor_binance/templates/index.html | 12 +++++---- crypto_monitor_gate/templates/index.html | 12 +++++---- crypto_monitor_gate_bot/templates/index.html | 12 +++++---- crypto_monitor_okx/templates/index.html | 12 +++++---- hub_bridge.py | 2 ++ hub_symbol_archive_lib.py | 9 ++++++- hub_trades_lib.py | 13 ++++++++-- manual_trading_hub/hub.py | 2 +- manual_trading_hub/static/app.css | 21 +++++++++++++++- manual_trading_hub/static/archive.js | 26 ++++++++++++++------ manual_trading_hub/static/index.html | 6 ++--- manual_trading_hub/static/time_close_ui.js | 9 ++++++- static/instance_theme.css | 10 +++++--- static/time_close_ui.js | 9 ++++++- strategy_templates/key_monitor_panel.html | 10 +++++--- tests/test_hub_symbol_archive_lib.py | 26 ++++++++++++++++++++ 16 files changed, 147 insertions(+), 44 deletions(-) diff --git a/crypto_monitor_binance/templates/index.html b/crypto_monitor_binance/templates/index.html index 7056ac5..bd392c2 100644 --- a/crypto_monitor_binance/templates/index.html +++ b/crypto_monitor_binance/templates/index.html @@ -376,14 +376,16 @@ - + - + @@ -799,7 +801,7 @@ - + - + - + - + - + - + diff --git a/manual_trading_hub/static/time_close_ui.js b/manual_trading_hub/static/time_close_ui.js index 2e3366a..99ba6b8 100644 --- a/manual_trading_hub/static/time_close_ui.js +++ b/manual_trading_hub/static/time_close_ui.js @@ -23,9 +23,16 @@ if (!cb || !sel) return; function sync() { const on = !!cb.checked; - sel.disabled = !on; + sel.disabled = false; + sel.tabIndex = 0; if (wrap) wrap.classList.toggle("is-disabled", !on); } + sel.addEventListener("mousedown", function (ev) { + ev.stopPropagation(); + }); + sel.addEventListener("click", function (ev) { + ev.stopPropagation(); + }); cb.addEventListener("change", sync); sync(); } diff --git a/static/instance_theme.css b/static/instance_theme.css index 6f5c91f..0f91b29 100644 --- a/static/instance_theme.css +++ b/static/instance_theme.css @@ -348,9 +348,13 @@ html[data-theme="light"] .pos-meta-item::after { font-variant-numeric: tabular-nums; letter-spacing: 0.02em; } -.key-time-close-wrap.is-disabled select, -.order-time-close-wrap.is-disabled select { - opacity: 0.55; +.key-time-close-wrap.is-disabled > label, +.order-time-close-wrap.is-disabled > label { + opacity: 0.72; +} +.key-time-close-wrap select, +.order-time-close-wrap select { + cursor: pointer; } html[data-theme="light"] .pos-meta-on { color: #006e9a !important; diff --git a/static/time_close_ui.js b/static/time_close_ui.js index 2e3366a..99ba6b8 100644 --- a/static/time_close_ui.js +++ b/static/time_close_ui.js @@ -23,9 +23,16 @@ if (!cb || !sel) return; function sync() { const on = !!cb.checked; - sel.disabled = !on; + sel.disabled = false; + sel.tabIndex = 0; if (wrap) wrap.classList.toggle("is-disabled", !on); } + sel.addEventListener("mousedown", function (ev) { + ev.stopPropagation(); + }); + sel.addEventListener("click", function (ev) { + ev.stopPropagation(); + }); cb.addEventListener("change", sync); sync(); } diff --git a/strategy_templates/key_monitor_panel.html b/strategy_templates/key_monitor_panel.html index 2bbd541..a298414 100644 --- a/strategy_templates/key_monitor_panel.html +++ b/strategy_templates/key_monitor_panel.html @@ -157,14 +157,16 @@ - + - +
diff --git a/tests/test_hub_symbol_archive_lib.py b/tests/test_hub_symbol_archive_lib.py index 1f28522..6ce7516 100644 --- a/tests/test_hub_symbol_archive_lib.py +++ b/tests/test_hub_symbol_archive_lib.py @@ -245,3 +245,29 @@ def test_resolve_archive_chart_history_uses_trade_span_not_200_bars(): assert out["ok"] is True assert out["range_mode"] == "history" assert out["bar_count"] > 200 + + +def test_upsert_forces_sync_exchange_key(): + with tempfile.TemporaryDirectory() as td: + db = Path(td) / "archive.db" + init_db(db) + upsert_trades_cache( + "gate_bot", + [ + { + "id": 77, + "exchange_key": "gate", + "account_exchange_key": "gate", + "symbol": "ETH/USDT", + "result": "止损", + "pnl_amount": -1, + "opened_at_ms": 1_700_000_000_000, + "closed_at_ms": 1_700_007_200_000, + } + ], + db_path=db, + ) + rows = load_symbol_trades("gate_bot", "ETH/USDT", db_path=db) + assert len(rows) == 1 + assert rows[0]["exchange_key"] == "gate_bot" + assert "account_exchange_key" not in rows[0]