@oanda/labs-order-book-widget 1.0.71 → 1.0.73

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.
Files changed (73) hide show
  1. package/CHANGELOG.md +556 -0
  2. package/dist/main/OrderBookWidget/ChartWithData.js +62 -0
  3. package/dist/main/OrderBookWidget/ChartWithData.js.map +1 -0
  4. package/dist/main/OrderBookWidget/Main.js +46 -0
  5. package/dist/main/OrderBookWidget/Main.js.map +1 -0
  6. package/dist/main/OrderBookWidget/OrderBookWidget.js +2 -2
  7. package/dist/main/OrderBookWidget/OrderBookWidget.js.map +1 -1
  8. package/dist/main/OrderBookWidget/components/Chart/Chart.js +16 -7
  9. package/dist/main/OrderBookWidget/components/Chart/Chart.js.map +1 -1
  10. package/dist/main/OrderBookWidget/components/Chart/constants.js +5 -3
  11. package/dist/main/OrderBookWidget/components/Chart/constants.js.map +1 -1
  12. package/dist/main/OrderBookWidget/components/Chart/formatters.js +10 -4
  13. package/dist/main/OrderBookWidget/components/Chart/formatters.js.map +1 -1
  14. package/dist/main/OrderBookWidget/components/Chart/getOption.js +81 -36
  15. package/dist/main/OrderBookWidget/components/Chart/getOption.js.map +1 -1
  16. package/dist/main/OrderBookWidget/components/Chart/types.js.map +1 -1
  17. package/dist/main/OrderBookWidget/config.js +69 -1
  18. package/dist/main/OrderBookWidget/config.js.map +1 -1
  19. package/dist/main/OrderBookWidget/types.js +20 -0
  20. package/dist/main/OrderBookWidget/types.js.map +1 -1
  21. package/dist/main/translations/sources/en.json +3 -0
  22. package/dist/main/translations/sources/zh_TW.json +3 -0
  23. package/dist/module/OrderBookWidget/ChartWithData.js +55 -0
  24. package/dist/module/OrderBookWidget/ChartWithData.js.map +1 -0
  25. package/dist/module/OrderBookWidget/Main.js +38 -0
  26. package/dist/module/OrderBookWidget/Main.js.map +1 -0
  27. package/dist/module/OrderBookWidget/OrderBookWidget.js +2 -2
  28. package/dist/module/OrderBookWidget/OrderBookWidget.js.map +1 -1
  29. package/dist/module/OrderBookWidget/components/Chart/Chart.js +17 -8
  30. package/dist/module/OrderBookWidget/components/Chart/Chart.js.map +1 -1
  31. package/dist/module/OrderBookWidget/components/Chart/constants.js +4 -2
  32. package/dist/module/OrderBookWidget/components/Chart/constants.js.map +1 -1
  33. package/dist/module/OrderBookWidget/components/Chart/formatters.js +10 -4
  34. package/dist/module/OrderBookWidget/components/Chart/formatters.js.map +1 -1
  35. package/dist/module/OrderBookWidget/components/Chart/getOption.js +80 -35
  36. package/dist/module/OrderBookWidget/components/Chart/getOption.js.map +1 -1
  37. package/dist/module/OrderBookWidget/components/Chart/types.js.map +1 -1
  38. package/dist/module/OrderBookWidget/config.js +69 -1
  39. package/dist/module/OrderBookWidget/config.js.map +1 -1
  40. package/dist/module/OrderBookWidget/types.js +19 -1
  41. package/dist/module/OrderBookWidget/types.js.map +1 -1
  42. package/dist/module/translations/sources/en.json +3 -0
  43. package/dist/module/translations/sources/zh_TW.json +3 -0
  44. package/dist/types/OrderBookWidget/ChartWithData.d.ts +4 -0
  45. package/dist/types/OrderBookWidget/Main.d.ts +4 -0
  46. package/dist/types/OrderBookWidget/components/Chart/Chart.d.ts +1 -1
  47. package/dist/types/OrderBookWidget/components/Chart/constants.d.ts +4 -2
  48. package/dist/types/OrderBookWidget/components/Chart/getOption.d.ts +16 -1
  49. package/dist/types/OrderBookWidget/components/Chart/types.d.ts +11 -1
  50. package/dist/types/OrderBookWidget/config.d.ts +7 -1
  51. package/dist/types/OrderBookWidget/types.d.ts +26 -3
  52. package/package.json +3 -3
  53. package/src/OrderBookWidget/ChartWithData.tsx +78 -0
  54. package/src/OrderBookWidget/Main.tsx +40 -0
  55. package/src/OrderBookWidget/OrderBookWidget.tsx +2 -2
  56. package/src/OrderBookWidget/components/Chart/Chart.tsx +12 -6
  57. package/src/OrderBookWidget/components/Chart/constants.ts +4 -2
  58. package/src/OrderBookWidget/components/Chart/formatters.ts +6 -4
  59. package/src/OrderBookWidget/components/Chart/getOption.ts +93 -39
  60. package/src/OrderBookWidget/components/Chart/types.ts +11 -3
  61. package/src/OrderBookWidget/config.ts +70 -1
  62. package/src/OrderBookWidget/types.ts +28 -3
  63. package/src/translations/sources/en.json +3 -0
  64. package/src/translations/sources/zh_TW.json +3 -0
  65. package/test/Main.test.tsx +129 -0
  66. package/test/chartOptions.test.ts +20 -0
  67. package/dist/main/OrderBookWidget/Widget.js +0 -61
  68. package/dist/main/OrderBookWidget/Widget.js.map +0 -1
  69. package/dist/module/OrderBookWidget/Widget.js +0 -53
  70. package/dist/module/OrderBookWidget/Widget.js.map +0 -1
  71. package/dist/types/OrderBookWidget/Widget.d.ts +0 -4
  72. package/src/OrderBookWidget/Widget.tsx +0 -62
  73. package/test/Widget.test.tsx +0 -71
@@ -1,9 +1,11 @@
1
1
  import { TooltipFormatterType } from './types';
2
2
 
3
- const tooltipFormatter: TooltipFormatterType = (data, precision, isOrderBook) => {
4
- const priceText = `Price: ${data[0].toFixed(precision)}`;
5
- const buyText = data[1] ? `<br />${isOrderBook ? 'Buy' : 'Long positions'}: ${data[1]}%` : '';
6
- const sellText = data[2] ? `<br />${isOrderBook ? 'Sell' : 'Short positions'}: ${data[2] * -1}%` : '';
3
+ const tooltipFormatter: TooltipFormatterType = ({
4
+ data, precision, isOrderBook, lang,
5
+ }) => {
6
+ const priceText = `${lang('price')}: ${data[0].toFixed(precision)}`;
7
+ const buyText = data[1] ? `<br />${lang(isOrderBook ? 'buy' : 'long_positions')}: ${data[1]}%` : '';
8
+ const sellText = data[2] ? `<br />${lang(isOrderBook ? 'sell' : 'short_positions')}: ${data[2] * -1}%` : '';
7
9
 
8
10
  return priceText + buyText + sellText;
9
11
  };
@@ -1,17 +1,31 @@
1
1
  import { colorPalette, getGridLines, getZoomControls } from '@oanda/labs-widget-common';
2
2
  import {
3
- INITIAL_BARS, CHART_WIDTH, CHART_HEIGHT, X_LABEL_SIZE, Y_LABEL_SIZE_DESKTOP,
3
+ INITIAL_BARS,
4
+ CHART_WIDTH,
5
+ CHART_HEIGHT_DESKTOP,
6
+ CHART_HEIGHT_MOBILE,
7
+ X_LABEL_SIZE,
8
+ Y_LABEL_SIZE_DESKTOP,
9
+ Y_LABEL_SIZE_MOBILE,
10
+ ZOOM_CONTROL_HEIGHT,
4
11
  } from './constants';
5
12
  import { GetOptionType, GetResponsiveOptionsProps } from './types';
6
13
  import { tooltipFormatter } from './formatters';
7
14
 
8
- export const getDesktopOption = ({ isDark, isOrderBook }: GetResponsiveOptionsProps) => {
15
+ export const getResponsiveOption = (
16
+ {
17
+ isDark, isOrderBook, isDesktop, lang,
18
+ }
19
+ : GetResponsiveOptionsProps,
20
+ ) => {
9
21
  const desktopGridLines = getGridLines({
10
22
  isDark,
11
23
  chartWidth: CHART_WIDTH,
12
- chartHeight: CHART_HEIGHT,
13
- xLabelsSize: X_LABEL_SIZE,
14
- yLabelSize: Y_LABEL_SIZE_DESKTOP,
24
+ chartHeight: isDesktop ? CHART_HEIGHT_DESKTOP : CHART_HEIGHT_MOBILE,
25
+ xLabelsSize: isDesktop ? X_LABEL_SIZE : X_LABEL_SIZE + ZOOM_CONTROL_HEIGHT,
26
+ yLabelSize: isDesktop ? Y_LABEL_SIZE_DESKTOP : Y_LABEL_SIZE_MOBILE,
27
+ bottomLeftBox: isDesktop,
28
+ marginBottom: isDesktop ? 0 : ZOOM_CONTROL_HEIGHT,
15
29
  });
16
30
 
17
31
  return {
@@ -20,8 +34,25 @@ export const getDesktopOption = ({ isDark, isOrderBook }: GetResponsiveOptionsPr
20
34
  name: 'main-grid',
21
35
  top: '48px',
22
36
  left: '0px',
23
- right: `${Y_LABEL_SIZE_DESKTOP}px`,
24
- bottom: `${X_LABEL_SIZE}px`,
37
+ right: `${isDesktop ? Y_LABEL_SIZE_DESKTOP : Y_LABEL_SIZE_MOBILE}px`,
38
+ bottom: `${isDesktop ? X_LABEL_SIZE : X_LABEL_SIZE + ZOOM_CONTROL_HEIGHT}px`,
39
+ },
40
+ ],
41
+ yAxis: {
42
+ axisLabel: {
43
+ margin: isDesktop ? 10 : 0,
44
+ },
45
+ },
46
+ series: [
47
+ {
48
+ type: 'custom',
49
+ name: 'current-price',
50
+ id: 'current-price',
51
+ markLine: {
52
+ label: {
53
+ padding: isDesktop ? [5, 15, 5, 15] : [5, 12, 5, 5],
54
+ },
55
+ },
25
56
  },
26
57
  ],
27
58
  graphic: [
@@ -58,14 +89,14 @@ export const getDesktopOption = ({ isDark, isOrderBook }: GetResponsiveOptionsPr
58
89
  fill: isDark ? colorPalette.white : colorPalette.black,
59
90
  width: 70,
60
91
  height: 30,
61
- text: isOrderBook ? 'Sell' : 'Short',
92
+ text: lang(isOrderBook ? 'sell' : 'short'),
62
93
  },
63
94
  },
64
95
  ],
65
96
  },
66
97
  {
67
98
  type: 'group',
68
- right: '128px',
99
+ right: `${(isDesktop ? Y_LABEL_SIZE_DESKTOP : Y_LABEL_SIZE_MOBILE) + 8}px'`,
69
100
  top: '56px',
70
101
  silent: true,
71
102
  children: [
@@ -95,7 +126,7 @@ export const getDesktopOption = ({ isDark, isOrderBook }: GetResponsiveOptionsPr
95
126
  fill: isDark ? colorPalette.white : colorPalette.black,
96
127
  width: 70,
97
128
  height: 30,
98
- text: isOrderBook ? 'Buy' : 'Long',
129
+ text: lang(isOrderBook ? 'buy' : 'long'),
99
130
  },
100
131
  },
101
132
  ],
@@ -105,11 +136,12 @@ export const getDesktopOption = ({ isDark, isOrderBook }: GetResponsiveOptionsPr
105
136
  };
106
137
 
107
138
  export const getOption: GetOptionType = ({
108
- data, precision, isDark, isOrderBook,
139
+ data, precision, isDark, isOrderBook, isDesktop, lang,
109
140
  }) => {
110
141
  const buckets = data.orderPositionBooks[0]?.buckets || [];
111
142
  const bucketWidth = data.orderPositionBooks[0]?.bucketWidth!;
112
143
  const price = data.orderPositionBooks[0]?.price!;
144
+ const bucketPrecision = bucketWidth.toString().split('.')[1].length || 0;
113
145
 
114
146
  const dataset = buckets.map((item) => ([
115
147
  item!.price,
@@ -133,7 +165,7 @@ export const getOption: GetOptionType = ({
133
165
  isDark ? colorPalette.orange : colorPalette.raspberryDark,
134
166
  ],
135
167
  title: {
136
- text: isOrderBook ? 'OPEN ORDERS' : 'OPEN POSITIONS',
168
+ text: lang(isOrderBook ? 'open_orders' : 'open_positions').toUpperCase(),
137
169
  padding: 20,
138
170
  textStyle: {
139
171
  fontSize: 14,
@@ -161,12 +193,23 @@ export const getOption: GetOptionType = ({
161
193
  axisPointer: {
162
194
  axis: 'y',
163
195
  },
164
- formatter: (val) => tooltipFormatter(
165
- (val as { data: number[] }[])[0].data,
166
- precision,
196
+ formatter: (val) => tooltipFormatter({
197
+ data: (val as { data: number[] }[])[0].data,
198
+ precision: bucketPrecision,
167
199
  isOrderBook,
168
- ),
200
+ lang,
201
+ }),
202
+ extraCssText: 'z-index: 1',
169
203
  },
204
+ grid: [
205
+ {
206
+ name: 'main-grid',
207
+ top: '48px',
208
+ left: '0px',
209
+ right: `${isDesktop ? Y_LABEL_SIZE_DESKTOP : Y_LABEL_SIZE_MOBILE}px`,
210
+ bottom: `${isDesktop ? X_LABEL_SIZE : X_LABEL_SIZE + ZOOM_CONTROL_HEIGHT}px`,
211
+ },
212
+ ],
170
213
  xAxis: {
171
214
  type: 'value',
172
215
  min: range * -1.05,
@@ -186,10 +229,11 @@ export const getOption: GetOptionType = ({
186
229
  axisLine: { show: false },
187
230
  axisTick: { show: false },
188
231
  axisLabel: {
232
+ margin: isDesktop ? 10 : 0,
189
233
  showMaxLabel: false,
190
234
  showMinLabel: false,
191
235
  padding: [0, 0, 0, 10],
192
- formatter: (value) => value.toFixed(precision),
236
+ formatter: (value) => value.toFixed(bucketPrecision),
193
237
  },
194
238
  },
195
239
  dataset: {
@@ -198,6 +242,8 @@ export const getOption: GetOptionType = ({
198
242
  series: [
199
243
  {
200
244
  type: 'custom',
245
+ name: 'sell-short',
246
+ id: 'sell-short',
201
247
  clip: true,
202
248
  encode: {
203
249
  x: 1,
@@ -234,34 +280,14 @@ export const getOption: GetOptionType = ({
234
280
  },
235
281
  {
236
282
  type: 'custom',
283
+ name: 'buy-long',
284
+ id: 'buy-long',
237
285
  clip: true,
238
286
  encode: {
239
287
  x: 1,
240
288
  y: 0,
241
289
  tooltip: 2,
242
290
  },
243
- markLine: {
244
- animation: false,
245
- silent: true,
246
- precision: 4,
247
- symbol: ['none', 'triangle'],
248
- symbolRotate: 90,
249
- symbolSize: [20, 10],
250
- lineStyle: {
251
- color: isDark ? colorPalette.orange : colorPalette.bottleGreenDark,
252
- width: 1,
253
- },
254
- label: {
255
- padding: [5, 15, 5, 15],
256
- color: isDark ? colorPalette.black : colorPalette.white,
257
- backgroundColor: isDark ? colorPalette.orange : colorPalette.bottleGreenDark,
258
- },
259
- data: [
260
- {
261
- yAxis: price,
262
- },
263
- ],
264
- },
265
291
  renderItem: (params, api) => {
266
292
  const yValue = api.value(0);
267
293
  const xStart = api.coord([api.value(2), yValue]);
@@ -290,6 +316,34 @@ export const getOption: GetOptionType = ({
290
316
  };
291
317
  },
292
318
  },
319
+ {
320
+ type: 'custom',
321
+ name: 'current-price',
322
+ id: 'current-price',
323
+ markLine: {
324
+ animation: false,
325
+ silent: true,
326
+ precision,
327
+ symbol: ['none', 'triangle'],
328
+ symbolRotate: 90,
329
+ symbolSize: [20, 10],
330
+ lineStyle: {
331
+ color: isDark ? colorPalette.orange : colorPalette.bottleGreenDark,
332
+ width: 1,
333
+ },
334
+ label: {
335
+ padding: isDesktop ? [5, 15, 5, 15] : [5, 12, 5, 5],
336
+ color: isDark ? colorPalette.black : colorPalette.white,
337
+ backgroundColor: isDark ? colorPalette.orange : colorPalette.bottleGreenDark,
338
+ },
339
+ data: [
340
+ {
341
+ yAxis: price,
342
+ },
343
+ ],
344
+ },
345
+ renderItem: () => null,
346
+ },
293
347
  ],
294
348
  }
295
349
  );
@@ -4,11 +4,14 @@ import { GetOrderPositionBooksQuery } from '../../../gql/types/graphql';
4
4
  export interface ChartProps {
5
5
  data: GetOrderPositionBooksQuery;
6
6
  isOrderBook: boolean;
7
+ precision: number;
7
8
  }
8
9
 
9
10
  export interface GetResponsiveOptionsProps {
11
+ isDesktop: boolean;
10
12
  isDark: boolean;
11
13
  isOrderBook: boolean;
14
+ lang: (label: string) => string;
12
15
  }
13
16
 
14
17
  export interface GetOptionProps {
@@ -16,6 +19,8 @@ export interface GetOptionProps {
16
19
  precision: number;
17
20
  isDark: boolean;
18
21
  isOrderBook: boolean;
22
+ isDesktop: boolean;
23
+ lang: (label: string) => string;
19
24
  }
20
25
 
21
26
  export type GetOptionType = (
@@ -23,7 +28,10 @@ export type GetOptionType = (
23
28
  ) => EChartsOption;
24
29
 
25
30
  export type TooltipFormatterType = (
26
- data: number[],
27
- precision: number,
28
- isOrderBook: boolean,
31
+ props : {
32
+ data: number[],
33
+ precision: number,
34
+ isOrderBook: boolean,
35
+ lang: (label: string) => string;
36
+ }
29
37
  ) => string;
@@ -1,4 +1,5 @@
1
1
  import { BookType } from '../gql/types/graphql';
2
+ import { InstrumentId } from './types';
2
3
 
3
4
  const navigationConfig = [{
4
5
  id: BookType.Order,
@@ -8,4 +9,72 @@ const navigationConfig = [{
8
9
  label: 'position_book',
9
10
  }];
10
11
 
11
- export { navigationConfig };
12
+ const instrumentSelectConfig = [{
13
+ id: InstrumentId.EUR_AUD,
14
+ label: 'EUR/AUD',
15
+ }, {
16
+ id: InstrumentId.EUR_GBP,
17
+ label: 'EUR/GBP',
18
+ }, {
19
+ id: InstrumentId.EUR_JPY,
20
+ label: 'EUR/JPY',
21
+ }, {
22
+ id: InstrumentId.EUR_USD,
23
+ label: 'EUR/USD',
24
+ }, {
25
+ id: InstrumentId.EUR_CHF,
26
+ label: 'EUR/CHF',
27
+ }, {
28
+ id: InstrumentId.USD_CHF,
29
+ label: 'USD/CHF',
30
+ }, {
31
+ id: InstrumentId.USD_JPY,
32
+ label: 'USD/JPY',
33
+ }, {
34
+ id: InstrumentId.USD_CAD,
35
+ label: 'USD/CAD',
36
+ }, {
37
+ id: InstrumentId.GBP_USD,
38
+ label: 'GBP/USD',
39
+ }, {
40
+ id: InstrumentId.GBP_JPY,
41
+ label: 'GBP/JPY',
42
+ }, {
43
+ id: InstrumentId.GBP_CHF,
44
+ label: 'GBP/CHF',
45
+ }, {
46
+ id: InstrumentId.AUD_JPY,
47
+ label: 'AUD/JPY',
48
+ }, {
49
+ id: InstrumentId.AUD_USD,
50
+ label: 'AUD/USD',
51
+ }, {
52
+ id: InstrumentId.NZD_USD,
53
+ label: 'NZD/USD',
54
+ }, {
55
+ id: InstrumentId.XAU_USD,
56
+ label: 'XAU/USD',
57
+ }, {
58
+ id: InstrumentId.XAG_USD,
59
+ label: 'XAG/USD',
60
+ }];
61
+
62
+ const instrumentPrecisionConfig: Record<InstrumentId, number> = {
63
+ [InstrumentId.EUR_AUD]: 5,
64
+ [InstrumentId.EUR_GBP]: 5,
65
+ [InstrumentId.EUR_JPY]: 3,
66
+ [InstrumentId.EUR_USD]: 5,
67
+ [InstrumentId.EUR_CHF]: 5,
68
+ [InstrumentId.USD_CHF]: 5,
69
+ [InstrumentId.USD_JPY]: 3,
70
+ [InstrumentId.USD_CAD]: 5,
71
+ [InstrumentId.GBP_USD]: 5,
72
+ [InstrumentId.GBP_JPY]: 3,
73
+ [InstrumentId.GBP_CHF]: 5,
74
+ [InstrumentId.AUD_JPY]: 3,
75
+ [InstrumentId.AUD_USD]: 5,
76
+ [InstrumentId.NZD_USD]: 5,
77
+ [InstrumentId.XAU_USD]: 3,
78
+ [InstrumentId.XAG_USD]: 5,
79
+ };
80
+ export { navigationConfig, instrumentSelectConfig, instrumentPrecisionConfig };
@@ -1,9 +1,10 @@
1
1
  import { Theme } from '@oanda/labs-widget-common';
2
2
  import { Locale } from '@oanda/mono-i18n';
3
+ import { BookType } from '../gql/types/graphql';
3
4
 
4
5
  export interface OrderBookWidgetConfig {
5
6
  graphqlUrl: string;
6
- instrument: string;
7
+ instrument: InstrumentId;
7
8
  locale: Locale;
8
9
  theme?: Theme;
9
10
  }
@@ -12,6 +13,30 @@ export interface OrderBookWrapperConfig extends OrderBookWidgetConfig {
12
13
  renderElementId: string;
13
14
  }
14
15
 
15
- export interface WidgetProps {
16
- instrument: string;
16
+ export interface MainProps {
17
+ instrument?: InstrumentId;
18
+ }
19
+
20
+ export interface ChartWithDataProps {
21
+ instrument: InstrumentId;
22
+ bookType: BookType;
23
+ }
24
+
25
+ export enum InstrumentId {
26
+ EUR_AUD = 'EUR_AUD',
27
+ EUR_GBP = 'EUR_GBP',
28
+ EUR_JPY = 'EUR_JPY',
29
+ EUR_USD = 'EUR_USD',
30
+ EUR_CHF = 'EUR_CHF',
31
+ USD_CHF = 'USD_CHF',
32
+ USD_JPY = 'USD_JPY',
33
+ USD_CAD = 'USD_CAD',
34
+ GBP_USD = 'GBP_USD',
35
+ GBP_JPY = 'GBP_JPY',
36
+ GBP_CHF = 'GBP_CHF',
37
+ AUD_JPY = 'AUD_JPY',
38
+ AUD_USD = 'AUD_USD',
39
+ NZD_USD = 'NZD_USD',
40
+ XAU_USD = 'XAU_USD',
41
+ XAG_USD = 'XAG_USD',
17
42
  }
@@ -1,5 +1,7 @@
1
1
  {
2
+ "buy": "Buy",
2
3
  "data_unavailable": "Data unavailable",
4
+ "instrument": "Instrument",
3
5
  "long": "Long",
4
6
  "long_positions": "Long Positions",
5
7
  "open_orders": "Open Orders",
@@ -9,6 +11,7 @@
9
11
  "position_book": "Position Book",
10
12
  "price": "Price",
11
13
  "reset_zoom": "Reset Zoom",
14
+ "sell": "Sell",
12
15
  "sell_orders": "Sell Orders",
13
16
  "short": "Short",
14
17
  "short_positions": "Short Positions",
@@ -1,5 +1,7 @@
1
1
  {
2
+ "buy": "買進",
2
3
  "data_unavailable": "沒有數據",
4
+ "instrument": "金融工具",
3
5
  "long": "長",
4
6
  "long_positions": "長倉",
5
7
  "open_orders": "開盤市價單",
@@ -9,6 +11,7 @@
9
11
  "position_book": "倉位手冊",
10
12
  "price": "價格",
11
13
  "reset_zoom": "重置比例",
14
+ "sell": "賣出",
12
15
  "sell_orders": "賣單",
13
16
  "short": "短",
14
17
  "short_positions": "短倉",
@@ -0,0 +1,129 @@
1
+ /**
2
+ * @jest-environment jsdom
3
+ */
4
+ import React from 'react';
5
+ import { render } from '@testing-library/react';
6
+ import { MockedProvider } from '@apollo/client/testing';
7
+ import { Main } from '../src/OrderBookWidget/Main';
8
+ import { getOrderPositionBooks } from '../src/gql/getOrderPositionBooks';
9
+ import { BookType } from '../src/gql/types/graphql';
10
+ import { InstrumentId } from '../src';
11
+
12
+ jest.mock('usehooks-ts', () => ({
13
+ useMediaQuery: jest.fn(),
14
+ useOnClickOutside: jest.fn(),
15
+ useElementSize: jest.fn().mockImplementation(() => [null, {
16
+ width: 100,
17
+ }]),
18
+ }));
19
+
20
+ const mocks = [
21
+ {
22
+ request: {
23
+ query: getOrderPositionBooks,
24
+ variables: {
25
+ instrument: InstrumentId.EUR_AUD,
26
+ bookType: BookType.Order,
27
+ recentHours: 1,
28
+ },
29
+ },
30
+ result: {
31
+ data: {
32
+ orderPositionBooks: [
33
+ {
34
+ bucketWidth: 0.0005,
35
+ price: 0.8,
36
+ buckets: [
37
+ {
38
+ price: 0.02,
39
+ longCountPercent: 0.0582,
40
+ shortCountPercent: 0.0,
41
+ },
42
+ {
43
+ price: 0.7,
44
+ longCountPercent: 0.0582,
45
+ shortCountPercent: 0.0,
46
+ },
47
+ {
48
+ price: 0.9925,
49
+ longCountPercent: 0.0582,
50
+ shortCountPercent: 0.0,
51
+ },
52
+ {
53
+ price: 1.0,
54
+ longCountPercent: 0.1163,
55
+ shortCountPercent: 0.0,
56
+ },
57
+ ],
58
+ },
59
+ ],
60
+ },
61
+ },
62
+ },
63
+ {
64
+ request: {
65
+ query: getOrderPositionBooks,
66
+ variables: {
67
+ instrument: InstrumentId.EUR_AUD,
68
+ bookType: BookType.Order,
69
+ recentHours: 1,
70
+ },
71
+ },
72
+ result: {
73
+ data: {
74
+ orderPositionBooks: [
75
+ {
76
+ bucketWidth: 0.0005,
77
+ price: 0.8,
78
+ buckets: [
79
+ {
80
+ price: 0.02,
81
+ longCountPercent: 0.0582,
82
+ shortCountPercent: 0.0,
83
+ },
84
+ {
85
+ price: 0.7,
86
+ longCountPercent: 0.0582,
87
+ shortCountPercent: 0.0,
88
+ },
89
+ {
90
+ price: 0.9925,
91
+ longCountPercent: 0.0582,
92
+ shortCountPercent: 0.0,
93
+ },
94
+ {
95
+ price: 1.0,
96
+ longCountPercent: 0.1163,
97
+ shortCountPercent: 0.0,
98
+ },
99
+ ],
100
+ },
101
+ ],
102
+ },
103
+ },
104
+ },
105
+ ];
106
+
107
+ describe('Main component', () => {
108
+ it('should render tool component', async () => {
109
+ const { findByTestId, getByTestId } = render(
110
+ <MockedProvider mocks={mocks}>
111
+ <Main />
112
+ </MockedProvider>,
113
+ );
114
+
115
+ expect(await findByTestId('order-book-widget')).toBeInTheDocument();
116
+ expect(getByTestId('spinner')).toBeInTheDocument();
117
+ expect((await findByTestId('select'))).toBeInTheDocument();
118
+ });
119
+ it('should render widget component', async () => {
120
+ const { findByTestId, queryAllByTestId } = render(
121
+ <MockedProvider mocks={mocks}>
122
+ <Main instrument={InstrumentId.EUR_AUD} />
123
+ </MockedProvider>,
124
+ );
125
+
126
+ expect(await findByTestId('order-book-widget')).toBeInTheDocument();
127
+ expect((await queryAllByTestId('select')).length).toBe(0);
128
+ });
129
+ });
@@ -0,0 +1,20 @@
1
+ import { tooltipFormatter } from '../src/OrderBookWidget/components/Chart/formatters';
2
+
3
+ describe('tooltipFormatter', () => {
4
+ it('should display correct label on order book data', () => {
5
+ expect(tooltipFormatter({
6
+ data: [1.235, 0.023, -0.012],
7
+ precision: 5,
8
+ lang: (label) => label,
9
+ isOrderBook: true,
10
+ })).toEqual('price: 1.23500<br />buy: 0.023%<br />sell: 0.012%');
11
+ });
12
+ it('should display correct label on position book data', () => {
13
+ expect(tooltipFormatter({
14
+ data: [1.235, 0.023, -0.012],
15
+ precision: 5,
16
+ lang: (label) => label,
17
+ isOrderBook: false,
18
+ })).toEqual('price: 1.23500<br />long_positions: 0.023%<br />short_positions: 0.012%');
19
+ });
20
+ });
@@ -1,61 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.Widget = void 0;
7
- var _react = _interopRequireWildcard(require("react"));
8
- var _client = require("@apollo/client");
9
- var _labsWidgetCommon = require("@oanda/labs-widget-common");
10
- var _monoI18n = require("@oanda/mono-i18n");
11
- var _getOrderPositionBooks = require("../gql/getOrderPositionBooks");
12
- var _graphql = require("../gql/types/graphql");
13
- var _Chart = require("./components/Chart/Chart");
14
- var _config = require("./config");
15
- function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
16
- function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
17
- const Widget = _ref => {
18
- let {
19
- instrument
20
- } = _ref;
21
- const [bookType, setBookType] = (0, _react.useState)(_graphql.BookType.Order);
22
- const {
23
- lang
24
- } = (0, _monoI18n.useLocale)();
25
- const {
26
- loading,
27
- data,
28
- error
29
- } = (0, _client.useQuery)(_getOrderPositionBooks.getOrderPositionBooks, {
30
- variables: {
31
- instrument,
32
- bookType,
33
- recentHours: 1
34
- }
35
- });
36
- const isError = !loading && !data || !!error;
37
- return _react.default.createElement("div", {
38
- "data-testid": "order-book-widget",
39
- className: "lw-p-4 lw-text-sm lw-tracking-normal lw-text-black"
40
- }, _react.default.createElement(_labsWidgetCommon.Tabs, {
41
- activeTab: bookType,
42
- handleClick: e => setBookType(e.currentTarget.value),
43
- labelCallback: lang,
44
- items: _config.navigationConfig
45
- }), _react.default.createElement("div", {
46
- className: "lw-relative lw-h-[450px] lw-w-full"
47
- }, isError && _react.default.createElement("div", {
48
- className: "lw-absolute lw-left-0 lw-top-0 lw-flex lw-h-full lw-w-full lw-items-center lw-justify-center lw-border lw-border-solid lw-border-border-primary"
49
- }, _react.default.createElement(_labsWidgetCommon.ChartError, null)), loading && _react.default.createElement("div", {
50
- className: "lw-absolute lw-left-0 lw-top-0 lw-flex lw-h-full lw-w-full lw-items-center lw-justify-center lw-border lw-border-solid lw-border-border-primary"
51
- }, _react.default.createElement(_labsWidgetCommon.Spinner, {
52
- size: _labsWidgetCommon.SpinnerSize.lg
53
- })), data && _react.default.createElement("div", {
54
- className: "lw-absolute lw-left-0 lw-top-0 lw-flex lw-h-full lw-w-full"
55
- }, _react.default.createElement(_Chart.Chart, {
56
- data: data,
57
- isOrderBook: bookType === _graphql.BookType.Order
58
- }))));
59
- };
60
- exports.Widget = Widget;
61
- //# sourceMappingURL=Widget.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Widget.js","names":["_react","_interopRequireWildcard","require","_client","_labsWidgetCommon","_monoI18n","_getOrderPositionBooks","_graphql","_Chart","_config","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","prototype","hasOwnProperty","call","i","set","Widget","_ref","instrument","bookType","setBookType","useState","BookType","Order","lang","useLocale","loading","data","error","useQuery","getOrderPositionBooks","variables","recentHours","isError","createElement","className","Tabs","activeTab","handleClick","currentTarget","value","labelCallback","items","navigationConfig","ChartError","Spinner","size","SpinnerSize","lg","Chart","isOrderBook","exports"],"sources":["../../../src/OrderBookWidget/Widget.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { useQuery } from '@apollo/client';\nimport {\n ChartError, Spinner, SpinnerSize, Tabs,\n} from '@oanda/labs-widget-common';\nimport { useLocale } from '@oanda/mono-i18n';\nimport { WidgetProps } from './types';\nimport { getOrderPositionBooks } from '../gql/getOrderPositionBooks';\nimport { GetOrderPositionBooksQuery, GetOrderPositionBooksQueryVariables, BookType } from '../gql/types/graphql';\nimport { Chart } from './components/Chart/Chart';\nimport { navigationConfig } from './config';\n\nconst Widget = ({\n instrument,\n}: WidgetProps) => {\n const [bookType, setBookType] = useState(BookType.Order);\n const { lang } = useLocale();\n\n const { loading, data, error } = useQuery<\n GetOrderPositionBooksQuery,\n GetOrderPositionBooksQueryVariables\n >(getOrderPositionBooks, {\n variables: {\n instrument,\n bookType,\n recentHours: 1,\n },\n });\n\n const isError = (!loading && !data) || !!error;\n\n return (\n <div data-testid=\"order-book-widget\" className=\"lw-p-4 lw-text-sm lw-tracking-normal lw-text-black\">\n <Tabs\n activeTab={bookType}\n handleClick={(e) => setBookType(e.currentTarget.value as BookType)}\n labelCallback={lang}\n items={navigationConfig}\n />\n {/* @todo: chart height */}\n <div className=\"lw-relative lw-h-[450px] lw-w-full\">\n {isError && (\n <div className=\"lw-absolute lw-left-0 lw-top-0 lw-flex lw-h-full lw-w-full lw-items-center lw-justify-center lw-border lw-border-solid lw-border-border-primary\">\n <ChartError />\n </div>\n )}\n {loading && (\n <div className=\"lw-absolute lw-left-0 lw-top-0 lw-flex lw-h-full lw-w-full lw-items-center lw-justify-center lw-border lw-border-solid lw-border-border-primary\">\n <Spinner size={SpinnerSize.lg} />\n </div>\n )}\n {data && (\n <div className=\"lw-absolute lw-left-0 lw-top-0 lw-flex lw-h-full lw-w-full\">\n <Chart data={data} isOrderBook={bookType === BookType.Order} />\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport { Widget };\n"],"mappings":"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"}