@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.
@@ -10,8 +10,7 @@ export declare const OrderStates: {
10
10
  readonly Rejected: 6;
11
11
  readonly Cancelled: 7;
12
12
  };
13
- export interface ActiveOrdersDeps {
14
- host: TradingHost;
13
+ export interface ActiveOrdersActions {
15
14
  cancelOrder(orderId: number): void;
16
15
  dismissOrder(orderId: number): void;
17
16
  editOrderField(orderId: number, field: string): void;
@@ -19,12 +18,21 @@ export interface ActiveOrdersDeps {
19
18
  cancelAllOrders(): void;
20
19
  refreshOrders(): void;
21
20
  }
21
+ export type ActiveOrdersDeps = ({
22
+ host: TradingHost;
23
+ readOnly?: false;
24
+ } & ActiveOrdersActions) | {
25
+ host: TradingHost;
26
+ readOnly: true;
27
+ };
22
28
  export declare class ActiveOrdersWidget {
23
29
  static TYPE: "activeOrders";
24
30
  rootEl: HTMLElement;
25
31
  el: HTMLElement | null;
26
32
  _host: TradingHost;
27
33
  _deps: ActiveOrdersDeps;
34
+ _readOnly: boolean;
35
+ _actions: ActiveOrdersActions | null;
28
36
  _closeBtn: HTMLElement | null;
29
37
  _cancelAllBtn: HTMLElement | null;
30
38
  _refreshBtn: HTMLElement | null;
@@ -32,7 +40,7 @@ export declare class ActiveOrdersWidget {
32
40
  _orders: OrderRow[];
33
41
  _grid: DataGrid<OrderRow> | null;
34
42
  static create(hostEl: HTMLElement, state: Record<string, unknown>, deps: ActiveOrdersDeps): ActiveOrdersWidget;
35
- static _buildRoot(host: TradingHost): HTMLElement;
43
+ static _buildRoot(host: TradingHost, readOnly?: boolean): HTMLElement;
36
44
  constructor(rootEl: HTMLElement, _state: Record<string, unknown>, deps: ActiveOrdersDeps);
37
45
  dispose(): void;
38
46
  update(orders: OrderRow[]): void;
@@ -1 +1 @@
1
- {"version":3,"file":"active-orders-widget.d.ts","sourceRoot":"","sources":["../../src/active-orders-widget.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,WAAW,EAAc,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAM1E,eAAO,MAAM,WAAW;;;;;;;;CAQd,CAAC;AAIX,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrD,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7F,eAAe,IAAI,IAAI,CAAC;IACxB,aAAa,IAAI,IAAI,CAAC;CACzB;AAED,qBAAa,kBAAkB;IAC3B,MAAM,CAAC,IAAI,iBAA6B;IAExC,MAAM,EAAE,WAAW,CAAC;IACpB,EAAE,EAAE,WAAW,GAAG,IAAI,CAAC;IAEvB,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,gBAAgB,CAAC;IACxB,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;IAC9B,aAAa,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,WAAW,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;IAEjC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,gBAAgB,GAAG,kBAAkB;IAsB9G,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW;gBAuBrC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,gBAAgB;IAgExF,OAAO,IAAI,IAAI;IAQf,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI;IAQhC,OAAO,IAAI,IAAI;IASf,UAAU,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAajC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQlC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAI/C,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,YAAY,GAAG,WAAW,GAAG,IAAI;IAsCtF,QAAQ,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE;IAyFlC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM;IAUzC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,YAAY,GAAG,WAAW,GAAG,OAAO;IAKzF,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,YAAY,GAAG,WAAW,GAAG,MAAM;IAM9F,eAAe,CAAC,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,YAAY,GAAG,WAAW,GAAG,IAAI;IAUhH,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI;IAmB3C,aAAa,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;CAoBvC"}
1
+ {"version":3,"file":"active-orders-widget.d.ts","sourceRoot":"","sources":["../../src/active-orders-widget.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,WAAW,EAAc,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAM1E,eAAO,MAAM,WAAW;;;;;;;;CAQd,CAAC;AAIX,MAAM,WAAW,mBAAmB;IAChC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrD,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7F,eAAe,IAAI,IAAI,CAAC;IACxB,aAAa,IAAI,IAAI,CAAC;CACzB;AAUD,MAAM,MAAM,gBAAgB,GACtB,CAAC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAA;CAAE,GAAG,mBAAmB,CAAC,GAC/D;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,CAAC;AAE5C,qBAAa,kBAAkB;IAC3B,MAAM,CAAC,IAAI,iBAA6B;IAExC,MAAM,EAAE,WAAW,CAAC;IACpB,EAAE,EAAE,WAAW,GAAG,IAAI,CAAC;IAEvB,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,gBAAgB,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACrC,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;IAC9B,aAAa,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,WAAW,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;IAEjC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,gBAAgB,GAAG,kBAAkB;IAsB9G,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,UAAQ,GAAG,WAAW;gBAyBvD,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,gBAAgB;IAuExF,OAAO,IAAI,IAAI;IAQf,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI;IAQhC,OAAO,IAAI,IAAI;IASf,UAAU,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAajC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQlC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAI/C,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,YAAY,GAAG,WAAW,GAAG,IAAI;IAsCtF,QAAQ,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE;IAyFlC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM;IAUzC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,YAAY,GAAG,WAAW,GAAG,OAAO;IAKzF,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,YAAY,GAAG,WAAW,GAAG,MAAM;IAM9F,eAAe,CAAC,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,YAAY,GAAG,WAAW,GAAG,IAAI;IAWhH,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI;IAmB3C,aAAa,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;CAqBvC"}
@@ -3,6 +3,7 @@ import type { TradeRow } from './trading-data.js';
3
3
  import { DataGrid, GridColumn } from '@stocksharp/grids/data-grid';
4
4
  export interface TradeHistoryDeps {
5
5
  host: TradingHost;
6
+ readOnly?: boolean;
6
7
  }
7
8
  export declare class TradeHistoryWidget {
8
9
  static TYPE: "tradeHistory";
@@ -15,10 +16,11 @@ export declare class TradeHistoryWidget {
15
16
  _rows: TradeRow[];
16
17
  _grid: DataGrid<TradeRow> | null;
17
18
  static create(hostEl: HTMLElement, state: Record<string, unknown>, deps: TradeHistoryDeps): TradeHistoryWidget;
18
- static _buildRoot(host: TradingHost): HTMLElement;
19
+ static _buildRoot(host: TradingHost, readOnly?: boolean): HTMLElement;
19
20
  constructor(rootEl: HTMLElement, _state: Record<string, unknown>, deps: TradeHistoryDeps);
20
21
  dispose(): void;
21
22
  refresh(): Promise<void>;
23
+ update(rows: TradeRow[]): void;
22
24
  _export(): void;
23
25
  _columns(): GridColumn<TradeRow>[];
24
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"trade-history-widget.d.ts","sourceRoot":"","sources":["../../src/trade-history-widget.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,WAAW,EAAc,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAI1E,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,WAAW,CAAC;CACrB;AAED,qBAAa,kBAAkB;IAC3B,MAAM,CAAC,IAAI,iBAA6B;IAExC,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAE3B,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,WAAW,GAAG,IAAI,CAAC;IAC/B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;IAEjC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,gBAAgB,GAAG,kBAAkB;IAa9G,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW;gBAsBrC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,gBAAgB;IA8CxF,OAAO,IAAI,IAAI;IAsBT,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB9B,OAAO,IAAI,IAAI;IAMf,QAAQ,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE;CA8DrC"}
1
+ {"version":3,"file":"trade-history-widget.d.ts","sourceRoot":"","sources":["../../src/trade-history-widget.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,WAAW,EAAc,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAI1E,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,WAAW,CAAC;IAIlB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,qBAAa,kBAAkB;IAC3B,MAAM,CAAC,IAAI,iBAA6B;IAExC,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAE3B,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,WAAW,GAAG,IAAI,CAAC;IAC/B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;IAEjC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,gBAAgB,GAAG,kBAAkB;IAa9G,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,UAAQ,GAAG,WAAW;gBAsBvD,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,gBAAgB;IA8CxF,OAAO,IAAI,IAAI;IAsBT,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB9B,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI;IAM9B,OAAO,IAAI,IAAI;IAMf,QAAQ,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE;CA8DrC"}
@@ -10,6 +10,7 @@ export interface TradingPresentation {
10
10
  isBuy(side: OrderSide): boolean;
11
11
  typeText(type: OrderType, limitPrice: number, stopPrice: number): string;
12
12
  statusText(status: OrderStatus): string;
13
+ timeText(value: string | number | Date): string;
13
14
  sideClass(side: OrderSide): string;
14
15
  pnlClass(pnl: number): string;
15
16
  canvasPalette(): CanvasPalette;
@@ -1 +1 @@
1
- {"version":3,"file":"trading-host.d.ts","sourceRoot":"","sources":["../../src/trading-host.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"trading-host.d.ts","sourceRoot":"","sources":["../../src/trading-host.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stocksharp/trading-controls",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Browser trading controls for StockSharp: order blotters, positions, trade history, watchlist and trade feed, each built against one host port and rendering its own DOM.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": {
@@ -11,7 +11,7 @@
11
11
  "type": "git",
12
12
  "url": "git+https://github.com/StockSharp/JS-TradingControls.git"
13
13
  },
14
- "homepage": "https://github.com/StockSharp/JS-TradingControls#readme",
14
+ "homepage": "https://stocksharp.com",
15
15
  "bugs": {
16
16
  "url": "https://github.com/StockSharp/JS-TradingControls/issues"
17
17
  },
@@ -136,7 +136,7 @@
136
136
  "release:major": "npm version major -m \"chore: release v%s\""
137
137
  },
138
138
  "dependencies": {
139
- "@stocksharp/grids": "^1.1.0"
139
+ "@stocksharp/grids": "^1.1.1"
140
140
  },
141
141
  "devDependencies": {
142
142
  "@stocksharp/chart": "^0.2.3",
@@ -34,10 +34,9 @@ export const OrderStates = {
34
34
  Cancelled: 7,
35
35
  } as const;
36
36
 
37
- /// What the blotter needs beyond the host port. All required: a panel that
38
- /// cannot cancel, modify or reload its orders is not this panel.
39
- export interface ActiveOrdersDeps {
40
- host: TradingHost;
37
+ /// The gestures that reach a venue. All required together: a panel that can
38
+ /// cancel one order but not all of them is a panel half-wired.
39
+ export interface ActiveOrdersActions {
41
40
  cancelOrder(orderId: number): void;
42
41
  dismissOrder(orderId: number): void;
43
42
  editOrderField(orderId: number, field: string): void;
@@ -46,6 +45,18 @@ export interface ActiveOrdersDeps {
46
45
  refreshOrders(): void;
47
46
  }
48
47
 
48
+ /// What the blotter needs beyond the host port, in one of two shapes.
49
+ ///
50
+ /// A live blotter carries every action, because a panel that cannot cancel,
51
+ /// modify or reload its orders is not that panel. A read-only one carries none:
52
+ /// over a finished run - a backtest report, an archived session - there is no
53
+ /// venue left to reach, and the gestures that would reach it are not rendered
54
+ /// rather than rendered and wired to nothing. The union states that, so a live
55
+ /// consumer still cannot omit an action by accident.
56
+ export type ActiveOrdersDeps =
57
+ | ({ host: TradingHost; readOnly?: false } & ActiveOrdersActions)
58
+ | { host: TradingHost; readOnly: true };
59
+
49
60
  export class ActiveOrdersWidget {
50
61
  static TYPE = ControlTypes.ActiveOrders;
51
62
 
@@ -54,6 +65,8 @@ export class ActiveOrdersWidget {
54
65
  // `//` rather than `///` from here down — see the note in positions-widget.
55
66
  _host: TradingHost;
56
67
  _deps: ActiveOrdersDeps;
68
+ _readOnly: boolean;
69
+ _actions: ActiveOrdersActions | null;
57
70
  _closeBtn: HTMLElement | null;
58
71
  _cancelAllBtn: HTMLElement | null;
59
72
  _refreshBtn: HTMLElement | null;
@@ -66,7 +79,7 @@ export class ActiveOrdersWidget {
66
79
  // host, so a missing host has to fail here rather than render a panel
67
80
  // captioned with raw English keys.
68
81
  const host = assertHost(deps?.host, 'ActiveOrdersWidget');
69
- const root = ActiveOrdersWidget._buildRoot(host);
82
+ const root = ActiveOrdersWidget._buildRoot(host, deps?.readOnly === true);
70
83
  root.id = makePanelId(ActiveOrdersWidget.TYPE);
71
84
  hostEl.appendChild(root);
72
85
  return new ActiveOrdersWidget(root, state || {}, deps);
@@ -83,7 +96,7 @@ export class ActiveOrdersWidget {
83
96
  // already give the identical button — and are wired to deps. Cancel-all
84
97
  // keeps a distinct accessible name from its tooltip, which is why it states
85
98
  // `aria-label` rather than taking the tooltip for both.
86
- static _buildRoot(host: TradingHost): HTMLElement {
99
+ static _buildRoot(host: TradingHost, readOnly = false): HTMLElement {
87
100
  return makePanelRoot('active-orders-panel', host.t('ActiveOrders'), [
88
101
  makeElement('div', 'panel-header', {}, [
89
102
  makeElement('span', '', {}, [host.t('OpenOrders')]),
@@ -97,9 +110,11 @@ export class ActiveOrdersWidget {
97
110
  ]),
98
111
  ]),
99
112
  makeElement('div', 'panel-rail', { role: 'toolbar', 'aria-label': host.t('ActiveOrdersActions') }, [
100
- makeIconButton('bt-icon-btn bt-icon-cancel-all panel-cancel-all-btn', host.t('CancelAll'), 'bi-x-circle',
101
- { 'aria-label': host.t('CancelAllOrders') }),
102
- makeIconButton('bt-icon-btn panel-refresh-btn', host.t('Refresh'), 'bi-arrow-clockwise', {}),
113
+ ...(readOnly ? [] : [
114
+ makeIconButton('bt-icon-btn bt-icon-cancel-all panel-cancel-all-btn', host.t('CancelAll'), 'bi-x-circle',
115
+ { 'aria-label': host.t('CancelAllOrders') }),
116
+ makeIconButton('bt-icon-btn panel-refresh-btn', host.t('Refresh'), 'bi-arrow-clockwise', {}),
117
+ ]),
103
118
  makeIconButton('bt-icon-btn panel-export-btn', host.t('ExportToExcel'), 'bi-file-earmark-spreadsheet', {}),
104
119
  ]),
105
120
  ]),
@@ -108,9 +123,16 @@ export class ActiveOrdersWidget {
108
123
 
109
124
  constructor(rootEl: HTMLElement, _state: Record<string, unknown>, deps: ActiveOrdersDeps) {
110
125
  this._host = assertHost(deps?.host, 'ActiveOrdersWidget');
111
- for (const name of ['cancelOrder', 'dismissOrder', 'editOrderField', 'replaceOrder', 'cancelAllOrders', 'refreshOrders'] as const) {
112
- if (typeof deps?.[name] !== 'function')
113
- throw new Error(`ActiveOrdersWidget: dep "${name}" is required`);
126
+ this._readOnly = deps?.readOnly === true;
127
+ if (this._readOnly) {
128
+ this._actions = null;
129
+ } else {
130
+ const actions = deps as ActiveOrdersActions;
131
+ for (const name of ['cancelOrder', 'dismissOrder', 'editOrderField', 'replaceOrder', 'cancelAllOrders', 'refreshOrders'] as const) {
132
+ if (typeof actions?.[name] !== 'function')
133
+ throw new Error(`ActiveOrdersWidget: dep "${name}" is required`);
134
+ }
135
+ this._actions = actions;
114
136
  }
115
137
 
116
138
  this.rootEl = rootEl;
@@ -129,12 +151,12 @@ export class ActiveOrdersWidget {
129
151
 
130
152
  this._cancelAllBtn?.addEventListener('click', (e) => {
131
153
  e.preventDefault();
132
- this._deps.cancelAllOrders();
154
+ this._actions?.cancelAllOrders();
133
155
  });
134
156
 
135
157
  this._refreshBtn?.addEventListener('click', (e) => {
136
158
  e.preventDefault();
137
- this._deps.refreshOrders();
159
+ this._actions?.refreshOrders();
138
160
  });
139
161
 
140
162
  this._exportBtn?.addEventListener('click', (e) => {
@@ -246,7 +268,7 @@ export class ActiveOrdersWidget {
246
268
  if (newVal === currentValue) { this.update(this._orders); return; }
247
269
  const updated = { quantity: order.quantity, limitPrice: order.limitPrice, stopPrice: order.stopPrice };
248
270
  updated[field] = newVal;
249
- this._deps.replaceOrder(orderId, updated.quantity!, updated.limitPrice!, updated.stopPrice!);
271
+ this._actions?.replaceOrder(orderId, updated.quantity!, updated.limitPrice!, updated.stopPrice!);
250
272
  };
251
273
  input.addEventListener('blur', commit);
252
274
  input.addEventListener('keydown', (e) => {
@@ -305,7 +327,7 @@ export class ActiveOrdersWidget {
305
327
  exportable: true,
306
328
  value: (o) => o.quantity,
307
329
  render: (o) => formatQty(o.quantity),
308
- cellClass: (o) => ActiveOrdersWidget._editableClass(o, 'quantity'),
330
+ cellClass: (o) => this._readOnly ? '' : ActiveOrdersWidget._editableClass(o, 'quantity'),
309
331
  bindCell: (td, o) => this._bindInlineEdit(td, o, 'quantity'),
310
332
  },
311
333
  {
@@ -314,7 +336,7 @@ export class ActiveOrdersWidget {
314
336
  exportable: true,
315
337
  value: (o) => o.limitPrice,
316
338
  render: (o) => o.limitPrice ? formatPrice(o.limitPrice) : label('MKT'),
317
- cellClass: (o) => ActiveOrdersWidget._editableClass(o, 'limitPrice'),
339
+ cellClass: (o) => this._readOnly ? '' : ActiveOrdersWidget._editableClass(o, 'limitPrice'),
318
340
  bindCell: (td, o) => this._bindInlineEdit(td, o, 'limitPrice'),
319
341
  exportValue: (o) => o.limitPrice ?? label('MKT'),
320
342
  },
@@ -324,7 +346,7 @@ export class ActiveOrdersWidget {
324
346
  exportable: true,
325
347
  value: (o) => o.stopPrice,
326
348
  render: (o) => o.stopPrice ? formatPrice(o.stopPrice) : '--',
327
- cellClass: (o) => ActiveOrdersWidget._editableClass(o, 'stopPrice'),
349
+ cellClass: (o) => this._readOnly ? '' : ActiveOrdersWidget._editableClass(o, 'stopPrice'),
328
350
  bindCell: (td, o) => this._bindInlineEdit(td, o, 'stopPrice'),
329
351
  exportValue: (o) => o.stopPrice ?? '',
330
352
  },
@@ -336,14 +358,14 @@ export class ActiveOrdersWidget {
336
358
  render: (o) => this._statusCell(o),
337
359
  exportValue: (o) => presentation.statusText(o.status!),
338
360
  },
339
- {
361
+ ...(this._readOnly ? [] : [{
340
362
  key: 'actions',
341
363
  header: label('Actions'),
342
364
  headerHidden: true,
343
365
  exportable: false,
344
366
  cellClass: () => 'position-actions',
345
- render: (o) => this._actionButton(o),
346
- },
367
+ render: (o: OrderRow) => this._actionButton(o),
368
+ } as GridColumn<OrderRow>]),
347
369
  ];
348
370
  }
349
371
 
@@ -369,8 +391,9 @@ export class ActiveOrdersWidget {
369
391
  // Double-click to edit belongs to the whole cell rather than to a control
370
392
  // inside it, which is why it is wired here instead of returned by render().
371
393
  _bindInlineEdit(td: HTMLTableCellElement, order: OrderRow, field: 'quantity' | 'limitPrice' | 'stopPrice'): void {
372
- if (!ActiveOrdersWidget._canEdit(order, field)) return;
373
- td.addEventListener('dblclick', () => this._deps.editOrderField(order.id!, field));
394
+ if (this._actions === null || !ActiveOrdersWidget._canEdit(order, field)) return;
395
+ const edit = this._actions.editOrderField;
396
+ td.addEventListener('dblclick', () => edit(order.id!, field));
374
397
  }
375
398
 
376
399
  // Status text, plus a hoverable icon carrying the rejection reason. Some
@@ -412,8 +435,9 @@ export class ActiveOrdersWidget {
412
435
  icon.className = 'bi bi-x-circle';
413
436
  button.appendChild(icon);
414
437
  button.addEventListener('click', () => {
415
- if (isTerminal) this._deps.dismissOrder(order.id!);
416
- else this._deps.cancelOrder(order.id!);
438
+ if (this._actions === null) return;
439
+ if (isTerminal) this._actions.dismissOrder(order.id!);
440
+ else this._actions.cancelOrder(order.id!);
417
441
  });
418
442
  return button;
419
443
  }
@@ -12,7 +12,7 @@
12
12
  // The table is `DataGrid` from `@stocksharp/grids`: the columns below are this
13
13
  // blotter's single declaration and the <thead> is left empty for the grid to
14
14
  // fill.
15
- import { formatPrice, formatQty, formatTime } from './formatters.js';
15
+ import { formatPrice, formatQty } from './formatters.js';
16
16
  import { makeElement, makeIconButton, makePanelId, makePanelRoot } from './dom.js';
17
17
  import { ControlTypes } from './control-types.js';
18
18
  import { makeGridMenu } from './grid-menu.js';
@@ -24,6 +24,10 @@ import { DataGrid, GridColumn } from '@stocksharp/grids/source/data-grid';
24
24
  /// portfolio and its lifecycle all arrive through it.
25
25
  export interface TradeHistoryDeps {
26
26
  host: TradingHost;
27
+ /// A blotter over a finished run - a backtest report, an archived session.
28
+ /// There is no account to load from and nothing to reload, so the rows come
29
+ /// in through `update` and the refresh gesture is not rendered.
30
+ readOnly?: boolean;
27
31
  }
28
32
 
29
33
  export class TradeHistoryWidget {
@@ -44,7 +48,7 @@ export class TradeHistoryWidget {
44
48
  // host, so a missing host has to fail here rather than render a panel
45
49
  // captioned with raw English keys.
46
50
  const host = assertHost(deps?.host, 'TradeHistoryWidget');
47
- const root = TradeHistoryWidget._buildRoot(host);
51
+ const root = TradeHistoryWidget._buildRoot(host, deps?.readOnly === true);
48
52
  root.id = makePanelId(TradeHistoryWidget.TYPE);
49
53
  hostEl.appendChild(root);
50
54
  return new TradeHistoryWidget(root, state || {}, deps);
@@ -52,7 +56,7 @@ export class TradeHistoryWidget {
52
56
 
53
57
  // The panel's markup. The host stylesheet reads this structure, and a
54
58
  // docking host lifts `.panel-header`'s children into its tab strip.
55
- static _buildRoot(host: TradingHost): HTMLElement {
59
+ static _buildRoot(host: TradingHost, readOnly = false): HTMLElement {
56
60
  const title = host.t('TradeHistory');
57
61
  return makePanelRoot('trade-history-panel', title, [
58
62
  makeElement('div', 'panel-header', {}, [
@@ -67,7 +71,7 @@ export class TradeHistoryWidget {
67
71
  ]),
68
72
  ]),
69
73
  makeElement('div', 'panel-rail', { role: 'toolbar', 'aria-label': host.t('TradeHistoryActions') }, [
70
- makeIconButton('bt-icon-btn panel-refresh-btn', host.t('Refresh'), 'bi-arrow-clockwise', {}),
74
+ ...(readOnly ? [] : [makeIconButton('bt-icon-btn panel-refresh-btn', host.t('Refresh'), 'bi-arrow-clockwise', {})]),
71
75
  makeIconButton('bt-icon-btn panel-export-btn', host.t('ExportToExcel'), 'bi-file-earmark-spreadsheet', {}),
72
76
  ]),
73
77
  ]),
@@ -157,6 +161,15 @@ export class TradeHistoryWidget {
157
161
  }
158
162
  }
159
163
 
164
+ /// Show these rows. The push path, for a consumer that already holds the
165
+ /// trades - a finished run's report - rather than an account to load them
166
+ /// from. `refresh` is the pull path and the two do not mix: whichever ran
167
+ /// last is what the grid shows.
168
+ update(rows: TradeRow[]): void {
169
+ this._rows = rows || [];
170
+ this._grid?.setRows(this._rows);
171
+ }
172
+
160
173
  // Export the table to .xlsx in the currently rendered (sorted) order.
161
174
  _export(): void {
162
175
  this._grid?.download('trades', this._host.t('TradeHistory'));
@@ -184,8 +197,8 @@ export class TradeHistoryWidget {
184
197
  header: label('Time'),
185
198
  exportable: true,
186
199
  value: (t) => t.executedAt || t.time,
187
- render: (t) => formatTime(t.executedAt || t.time),
188
- exportValue: (t) => formatTime(t.executedAt || t.time),
200
+ render: (t) => presentation.timeText(t.executedAt || t.time!),
201
+ exportValue: (t) => presentation.timeText(t.executedAt || t.time!),
189
202
  },
190
203
  {
191
204
  key: 'symbol',
@@ -20,7 +20,7 @@
20
20
  // geometry comes out of `tradefeed-bubbles.ts` as numbers and its colours out
21
21
  // of the host's `canvasPalette()`, so the package still paints nothing from a
22
22
  // palette of its own.
23
- import { formatPrice, formatQty, formatTime } from './formatters.js';
23
+ import { formatPrice, formatQty } from './formatters.js';
24
24
  import { makeElement, makeIconButton, makePanelId, makePanelRoot } from './dom.js';
25
25
  import { ControlTypes } from './control-types.js';
26
26
  import { makeGridMenu } from './grid-menu.js';
@@ -372,7 +372,7 @@ export class TradeFeedWidget {
372
372
  header: label('Time'),
373
373
  exportable: true,
374
374
  value: (t) => String(t.time || t.executedAt || ''),
375
- render: (t) => formatTime(t.time || t.executedAt),
375
+ render: (t) => this._host.presentation.timeText(t.time || t.executedAt!),
376
376
  },
377
377
  {
378
378
  key: 'symbol',
@@ -708,7 +708,7 @@ export class TradeFeedWidget {
708
708
 
709
709
  const lines: HTMLElement[] = [];
710
710
  if (this._extraSymbols.size > 0) lines.push(this._tooltipLine(this._host.t('Symbol'), bubble.symbol, ''));
711
- lines.push(this._tooltipLine(this._host.t('Time'), formatTime(bubble.time), ''));
711
+ lines.push(this._tooltipLine(this._host.t('Time'), this._host.presentation.timeText(bubble.time), ''));
712
712
  lines.push(this._tooltipLine(aggregated ? this._host.t('VWAP') : this._host.t('Price'), formatPrice(bubble.price), ''));
713
713
  lines.push(this._tooltipLine(aggregated ? this._host.t('Total qty') : this._host.t('Qty'), formatQty(bubble.quantity), ''));
714
714
  lines.push(this._tooltipLine(this._host.t('Side'), presentation.sideText(side), presentation.sideClass(side)));
@@ -86,6 +86,13 @@ export interface TradingPresentation {
86
86
  typeText(type: OrderType, limitPrice: number, stopPrice: number): string;
87
87
  /// Localized order status.
88
88
  statusText(status: OrderStatus): string;
89
+ /// A moment, worded. The host owns this for the same reason it owns a side or a
90
+ /// status: what a time should read as is not a property of the data. A live tape wants
91
+ /// the time of day in the reader's own zone; a blotter over a finished run wants the
92
+ /// date too, and in the zone the run was recorded in, or every row reads as the same
93
+ /// unplaceable day. `formatTime` is this package's tape answer, exported so a host that
94
+ /// wants exactly that need not restate it.
95
+ timeText(value: string | number | Date): string;
89
96
  /// CSS class colouring a cell by side. The shipped stylesheet styles
90
97
  /// `side-buy` and `side-sell`; a host on its own palette may answer with
91
98
  /// its own names and style those instead.
@@ -271,6 +278,7 @@ export function assertHost(host: TradingHost, controlName: string): TradingHost
271
278
  _required(host.presentation.isBuy, 'host.presentation.isBuy', 'function', controlName);
272
279
  _required(host.presentation.typeText, 'host.presentation.typeText', 'function', controlName);
273
280
  _required(host.presentation.statusText, 'host.presentation.statusText', 'function', controlName);
281
+ _required(host.presentation.timeText, 'host.presentation.timeText', 'function', controlName);
274
282
  _required(host.presentation.sideClass, 'host.presentation.sideClass', 'function', controlName);
275
283
  _required(host.presentation.pnlClass, 'host.presentation.pnlClass', 'function', controlName);
276
284
  _required(host.presentation.canvasPalette, 'host.presentation.canvasPalette', 'function', controlName);