@stocksharp/trading-controls 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -73,6 +73,7 @@ var SSTradingControls = (() => {
73
73
  _required(host.presentation.isBuy, "host.presentation.isBuy", "function", controlName);
74
74
  _required(host.presentation.typeText, "host.presentation.typeText", "function", controlName);
75
75
  _required(host.presentation.statusText, "host.presentation.statusText", "function", controlName);
76
+ _required(host.presentation.timeText, "host.presentation.timeText", "function", controlName);
76
77
  _required(host.presentation.sideClass, "host.presentation.sideClass", "function", controlName);
77
78
  _required(host.presentation.pnlClass, "host.presentation.pnlClass", "function", controlName);
78
79
  _required(host.presentation.canvasPalette, "host.presentation.canvasPalette", "function", controlName);
@@ -1863,7 +1864,7 @@ var SSTradingControls = (() => {
1863
1864
  var _ActiveOrdersWidget = class _ActiveOrdersWidget {
1864
1865
  static create(hostEl, state, deps) {
1865
1866
  const host = assertHost(deps?.host, "ActiveOrdersWidget");
1866
- const root = _ActiveOrdersWidget._buildRoot(host);
1867
+ const root = _ActiveOrdersWidget._buildRoot(host, deps?.readOnly === true);
1867
1868
  root.id = makePanelId(_ActiveOrdersWidget.TYPE);
1868
1869
  hostEl.appendChild(root);
1869
1870
  return new _ActiveOrdersWidget(root, state || {}, deps);
@@ -1879,7 +1880,7 @@ var SSTradingControls = (() => {
1879
1880
  // already give the identical button — and are wired to deps. Cancel-all
1880
1881
  // keeps a distinct accessible name from its tooltip, which is why it states
1881
1882
  // `aria-label` rather than taking the tooltip for both.
1882
- static _buildRoot(host) {
1883
+ static _buildRoot(host, readOnly = false) {
1883
1884
  return makePanelRoot("active-orders-panel", host.t("ActiveOrders"), [
1884
1885
  makeElement("div", "panel-header", {}, [
1885
1886
  makeElement("span", "", {}, [host.t("OpenOrders")]),
@@ -1893,13 +1894,15 @@ var SSTradingControls = (() => {
1893
1894
  ])
1894
1895
  ]),
1895
1896
  makeElement("div", "panel-rail", { role: "toolbar", "aria-label": host.t("ActiveOrdersActions") }, [
1896
- makeIconButton(
1897
- "bt-icon-btn bt-icon-cancel-all panel-cancel-all-btn",
1898
- host.t("CancelAll"),
1899
- "bi-x-circle",
1900
- { "aria-label": host.t("CancelAllOrders") }
1901
- ),
1902
- makeIconButton("bt-icon-btn panel-refresh-btn", host.t("Refresh"), "bi-arrow-clockwise", {}),
1897
+ ...readOnly ? [] : [
1898
+ makeIconButton(
1899
+ "bt-icon-btn bt-icon-cancel-all panel-cancel-all-btn",
1900
+ host.t("CancelAll"),
1901
+ "bi-x-circle",
1902
+ { "aria-label": host.t("CancelAllOrders") }
1903
+ ),
1904
+ makeIconButton("bt-icon-btn panel-refresh-btn", host.t("Refresh"), "bi-arrow-clockwise", {})
1905
+ ],
1903
1906
  makeIconButton("bt-icon-btn panel-export-btn", host.t("ExportToExcel"), "bi-file-earmark-spreadsheet", {})
1904
1907
  ])
1905
1908
  ])
@@ -1907,9 +1910,16 @@ var SSTradingControls = (() => {
1907
1910
  }
1908
1911
  constructor(rootEl, _state, deps) {
1909
1912
  this._host = assertHost(deps?.host, "ActiveOrdersWidget");
1910
- for (const name of ["cancelOrder", "dismissOrder", "editOrderField", "replaceOrder", "cancelAllOrders", "refreshOrders"]) {
1911
- if (typeof deps?.[name] !== "function")
1912
- throw new Error(`ActiveOrdersWidget: dep "${name}" is required`);
1913
+ this._readOnly = deps?.readOnly === true;
1914
+ if (this._readOnly) {
1915
+ this._actions = null;
1916
+ } else {
1917
+ const actions = deps;
1918
+ for (const name of ["cancelOrder", "dismissOrder", "editOrderField", "replaceOrder", "cancelAllOrders", "refreshOrders"]) {
1919
+ if (typeof actions?.[name] !== "function")
1920
+ throw new Error(`ActiveOrdersWidget: dep "${name}" is required`);
1921
+ }
1922
+ this._actions = actions;
1913
1923
  }
1914
1924
  this.rootEl = rootEl;
1915
1925
  this._deps = deps;
@@ -1925,11 +1935,11 @@ var SSTradingControls = (() => {
1925
1935
  });
1926
1936
  this._cancelAllBtn?.addEventListener("click", (e) => {
1927
1937
  e.preventDefault();
1928
- this._deps.cancelAllOrders();
1938
+ this._actions?.cancelAllOrders();
1929
1939
  });
1930
1940
  this._refreshBtn?.addEventListener("click", (e) => {
1931
1941
  e.preventDefault();
1932
- this._deps.refreshOrders();
1942
+ this._actions?.refreshOrders();
1933
1943
  });
1934
1944
  this._exportBtn?.addEventListener("click", (e) => {
1935
1945
  e.preventDefault();
@@ -2032,7 +2042,7 @@ var SSTradingControls = (() => {
2032
2042
  }
2033
2043
  const updated = { quantity: order.quantity, limitPrice: order.limitPrice, stopPrice: order.stopPrice };
2034
2044
  updated[field] = newVal;
2035
- this._deps.replaceOrder(orderId, updated.quantity, updated.limitPrice, updated.stopPrice);
2045
+ this._actions?.replaceOrder(orderId, updated.quantity, updated.limitPrice, updated.stopPrice);
2036
2046
  };
2037
2047
  input.addEventListener("blur", commit);
2038
2048
  input.addEventListener("keydown", (e) => {
@@ -2092,7 +2102,7 @@ var SSTradingControls = (() => {
2092
2102
  exportable: true,
2093
2103
  value: (o) => o.quantity,
2094
2104
  render: (o) => formatQty(o.quantity),
2095
- cellClass: (o) => _ActiveOrdersWidget._editableClass(o, "quantity"),
2105
+ cellClass: (o) => this._readOnly ? "" : _ActiveOrdersWidget._editableClass(o, "quantity"),
2096
2106
  bindCell: (td, o) => this._bindInlineEdit(td, o, "quantity")
2097
2107
  },
2098
2108
  {
@@ -2101,7 +2111,7 @@ var SSTradingControls = (() => {
2101
2111
  exportable: true,
2102
2112
  value: (o) => o.limitPrice,
2103
2113
  render: (o) => o.limitPrice ? formatPrice(o.limitPrice) : label("MKT"),
2104
- cellClass: (o) => _ActiveOrdersWidget._editableClass(o, "limitPrice"),
2114
+ cellClass: (o) => this._readOnly ? "" : _ActiveOrdersWidget._editableClass(o, "limitPrice"),
2105
2115
  bindCell: (td, o) => this._bindInlineEdit(td, o, "limitPrice"),
2106
2116
  exportValue: (o) => o.limitPrice ?? label("MKT")
2107
2117
  },
@@ -2111,7 +2121,7 @@ var SSTradingControls = (() => {
2111
2121
  exportable: true,
2112
2122
  value: (o) => o.stopPrice,
2113
2123
  render: (o) => o.stopPrice ? formatPrice(o.stopPrice) : "--",
2114
- cellClass: (o) => _ActiveOrdersWidget._editableClass(o, "stopPrice"),
2124
+ cellClass: (o) => this._readOnly ? "" : _ActiveOrdersWidget._editableClass(o, "stopPrice"),
2115
2125
  bindCell: (td, o) => this._bindInlineEdit(td, o, "stopPrice"),
2116
2126
  exportValue: (o) => o.stopPrice ?? ""
2117
2127
  },
@@ -2123,14 +2133,14 @@ var SSTradingControls = (() => {
2123
2133
  render: (o) => this._statusCell(o),
2124
2134
  exportValue: (o) => presentation.statusText(o.status)
2125
2135
  },
2126
- {
2136
+ ...this._readOnly ? [] : [{
2127
2137
  key: "actions",
2128
2138
  header: label("Actions"),
2129
2139
  headerHidden: true,
2130
2140
  exportable: false,
2131
2141
  cellClass: () => "position-actions",
2132
2142
  render: (o) => this._actionButton(o)
2133
- }
2143
+ }]
2134
2144
  ];
2135
2145
  }
2136
2146
  static _rowClass(order) {
@@ -2152,8 +2162,9 @@ var SSTradingControls = (() => {
2152
2162
  // Double-click to edit belongs to the whole cell rather than to a control
2153
2163
  // inside it, which is why it is wired here instead of returned by render().
2154
2164
  _bindInlineEdit(td, order, field) {
2155
- if (!_ActiveOrdersWidget._canEdit(order, field)) return;
2156
- td.addEventListener("dblclick", () => this._deps.editOrderField(order.id, field));
2165
+ if (this._actions === null || !_ActiveOrdersWidget._canEdit(order, field)) return;
2166
+ const edit = this._actions.editOrderField;
2167
+ td.addEventListener("dblclick", () => edit(order.id, field));
2157
2168
  }
2158
2169
  // Status text, plus a hoverable icon carrying the rejection reason. Some
2159
2170
  // venues wrap the human-readable rejection inside a JSON blob;
@@ -2189,8 +2200,9 @@ var SSTradingControls = (() => {
2189
2200
  icon.className = "bi bi-x-circle";
2190
2201
  button.appendChild(icon);
2191
2202
  button.addEventListener("click", () => {
2192
- if (isTerminal) this._deps.dismissOrder(order.id);
2193
- else this._deps.cancelOrder(order.id);
2203
+ if (this._actions === null) return;
2204
+ if (isTerminal) this._actions.dismissOrder(order.id);
2205
+ else this._actions.cancelOrder(order.id);
2194
2206
  });
2195
2207
  return button;
2196
2208
  }
@@ -2447,14 +2459,14 @@ var SSTradingControls = (() => {
2447
2459
  var _TradeHistoryWidget = class _TradeHistoryWidget {
2448
2460
  static create(hostEl, state, deps) {
2449
2461
  const host = assertHost(deps?.host, "TradeHistoryWidget");
2450
- const root = _TradeHistoryWidget._buildRoot(host);
2462
+ const root = _TradeHistoryWidget._buildRoot(host, deps?.readOnly === true);
2451
2463
  root.id = makePanelId(_TradeHistoryWidget.TYPE);
2452
2464
  hostEl.appendChild(root);
2453
2465
  return new _TradeHistoryWidget(root, state || {}, deps);
2454
2466
  }
2455
2467
  // The panel's markup. The host stylesheet reads this structure, and a
2456
2468
  // docking host lifts `.panel-header`'s children into its tab strip.
2457
- static _buildRoot(host) {
2469
+ static _buildRoot(host, readOnly = false) {
2458
2470
  const title = host.t("TradeHistory");
2459
2471
  return makePanelRoot("trade-history-panel", title, [
2460
2472
  makeElement("div", "panel-header", {}, [
@@ -2469,7 +2481,7 @@ var SSTradingControls = (() => {
2469
2481
  ])
2470
2482
  ]),
2471
2483
  makeElement("div", "panel-rail", { role: "toolbar", "aria-label": host.t("TradeHistoryActions") }, [
2472
- makeIconButton("bt-icon-btn panel-refresh-btn", host.t("Refresh"), "bi-arrow-clockwise", {}),
2484
+ ...readOnly ? [] : [makeIconButton("bt-icon-btn panel-refresh-btn", host.t("Refresh"), "bi-arrow-clockwise", {})],
2473
2485
  makeIconButton("bt-icon-btn panel-export-btn", host.t("ExportToExcel"), "bi-file-earmark-spreadsheet", {})
2474
2486
  ])
2475
2487
  ])
@@ -2545,6 +2557,14 @@ var SSTradingControls = (() => {
2545
2557
  this._host.log(`TradeHistoryWidget: failed to load trade history: ${err}`);
2546
2558
  }
2547
2559
  }
2560
+ /// Show these rows. The push path, for a consumer that already holds the
2561
+ /// trades - a finished run's report - rather than an account to load them
2562
+ /// from. `refresh` is the pull path and the two do not mix: whichever ran
2563
+ /// last is what the grid shows.
2564
+ update(rows) {
2565
+ this._rows = rows || [];
2566
+ this._grid?.setRows(this._rows);
2567
+ }
2548
2568
  // Export the table to .xlsx in the currently rendered (sorted) order.
2549
2569
  _export() {
2550
2570
  this._grid?.download("trades", this._host.t("TradeHistory"));
@@ -2568,8 +2588,8 @@ var SSTradingControls = (() => {
2568
2588
  header: label("Time"),
2569
2589
  exportable: true,
2570
2590
  value: (t) => t.executedAt || t.time,
2571
- render: (t) => formatTime(t.executedAt || t.time),
2572
- exportValue: (t) => formatTime(t.executedAt || t.time)
2591
+ render: (t) => presentation.timeText(t.executedAt || t.time),
2592
+ exportValue: (t) => presentation.timeText(t.executedAt || t.time)
2573
2593
  },
2574
2594
  {
2575
2595
  key: "symbol",
@@ -4713,7 +4733,7 @@ var SSTradingControls = (() => {
4713
4733
  header: label("Time"),
4714
4734
  exportable: true,
4715
4735
  value: (t) => String(t.time || t.executedAt || ""),
4716
- render: (t) => formatTime(t.time || t.executedAt)
4736
+ render: (t) => this._host.presentation.timeText(t.time || t.executedAt)
4717
4737
  },
4718
4738
  {
4719
4739
  key: "symbol",
@@ -5018,7 +5038,7 @@ var SSTradingControls = (() => {
5018
5038
  const side = bubble.side;
5019
5039
  const lines = [];
5020
5040
  if (this._extraSymbols.size > 0) lines.push(this._tooltipLine(this._host.t("Symbol"), bubble.symbol, ""));
5021
- lines.push(this._tooltipLine(this._host.t("Time"), formatTime(bubble.time), ""));
5041
+ lines.push(this._tooltipLine(this._host.t("Time"), this._host.presentation.timeText(bubble.time), ""));
5022
5042
  lines.push(this._tooltipLine(aggregated ? this._host.t("VWAP") : this._host.t("Price"), formatPrice(bubble.price), ""));
5023
5043
  lines.push(this._tooltipLine(aggregated ? this._host.t("Total qty") : this._host.t("Qty"), formatQty(bubble.quantity), ""));
5024
5044
  lines.push(this._tooltipLine(this._host.t("Side"), presentation.sideText(side), presentation.sideClass(side)));