@oanda/labs-value-at-risk-widget 1.0.65 → 1.0.67
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.
- package/CHANGELOG.md +540 -0
- package/dist/main/ValueAtRiskWidget/ChartWithData.js +7 -6
- package/dist/main/ValueAtRiskWidget/ChartWithData.js.map +1 -1
- package/dist/main/ValueAtRiskWidget/Tool.js +12 -12
- package/dist/main/ValueAtRiskWidget/Tool.js.map +1 -1
- package/dist/main/ValueAtRiskWidget/ToolWithData.js +3 -3
- package/dist/main/ValueAtRiskWidget/ToolWithData.js.map +1 -1
- package/dist/main/ValueAtRiskWidget/ValueAtRiskWidget.js +8 -8
- package/dist/main/ValueAtRiskWidget/ValueAtRiskWidget.js.map +1 -1
- package/dist/main/ValueAtRiskWidget/Widget.js +9 -9
- package/dist/main/ValueAtRiskWidget/Widget.js.map +1 -1
- package/dist/main/ValueAtRiskWidget/components/Chart/Chart.js +11 -11
- package/dist/main/ValueAtRiskWidget/components/Chart/Chart.js.map +1 -1
- package/dist/main/ValueAtRiskWidget/components/Chart/getOption.js +11 -7
- package/dist/main/ValueAtRiskWidget/components/Chart/getOption.js.map +1 -1
- package/dist/main/ValueAtRiskWidget/components/Chart/types.js.map +1 -1
- package/dist/main/ValueAtRiskWidget/components/Legend/DashedLine.js +7 -7
- package/dist/main/ValueAtRiskWidget/components/Legend/DashedLine.js.map +1 -1
- package/dist/main/ValueAtRiskWidget/components/Legend/DesktopLegend.js +5 -5
- package/dist/main/ValueAtRiskWidget/components/Legend/DesktopLegend.js.map +1 -1
- package/dist/main/ValueAtRiskWidget/components/Legend/Legend.js +15 -15
- package/dist/main/ValueAtRiskWidget/components/Legend/Legend.js.map +1 -1
- package/dist/main/ValueAtRiskWidget/components/Legend/MobileLegend.js +8 -8
- package/dist/main/ValueAtRiskWidget/components/Legend/MobileLegend.js.map +1 -1
- package/dist/main/ValueAtRiskWidget/components/Legend/constants.js.map +1 -1
- package/dist/main/ValueAtRiskWidget/components/Legend/types.js.map +1 -1
- package/dist/main/ValueAtRiskWidget/render.js +9 -9
- package/dist/main/ValueAtRiskWidget/render.js.map +1 -1
- package/dist/main/ValueAtRiskWidget/types.js.map +1 -1
- package/dist/main/ValueAtRiskWidget/utils.js +1 -1
- package/dist/main/ValueAtRiskWidget/utils.js.map +1 -1
- package/dist/main/gql/getValueAtRiskAssetClasses.js +3 -11
- package/dist/main/gql/getValueAtRiskAssetClasses.js.map +1 -1
- package/dist/main/gql/getValueAtRiskChart.js +3 -26
- package/dist/main/gql/getValueAtRiskChart.js.map +1 -1
- package/dist/main/gql/types/fragment-masking.js +3 -2
- package/dist/main/gql/types/fragment-masking.js.map +1 -1
- package/dist/main/gql/types/gql.js +4 -3
- package/dist/main/gql/types/gql.js.map +1 -1
- package/dist/main/gql/types/graphql.js +241 -241
- package/dist/main/gql/types/graphql.js.map +1 -1
- package/dist/main/gql/types/index.js.map +1 -1
- package/dist/main/translations/index.js +1 -1
- package/dist/main/translations/index.js.map +1 -1
- package/dist/main/translations/translations.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/ChartWithData.js +7 -6
- package/dist/module/ValueAtRiskWidget/ChartWithData.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/Tool.js +12 -12
- package/dist/module/ValueAtRiskWidget/Tool.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/ToolWithData.js +3 -3
- package/dist/module/ValueAtRiskWidget/ToolWithData.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/ValueAtRiskWidget.js +8 -8
- package/dist/module/ValueAtRiskWidget/ValueAtRiskWidget.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/Widget.js +9 -9
- package/dist/module/ValueAtRiskWidget/Widget.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/components/Chart/Chart.js +9 -9
- package/dist/module/ValueAtRiskWidget/components/Chart/Chart.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/components/Chart/getOption.js +12 -8
- package/dist/module/ValueAtRiskWidget/components/Chart/getOption.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/components/Chart/types.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/components/Legend/DashedLine.js +7 -7
- package/dist/module/ValueAtRiskWidget/components/Legend/DashedLine.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/components/Legend/DesktopLegend.js +5 -5
- package/dist/module/ValueAtRiskWidget/components/Legend/DesktopLegend.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/components/Legend/Legend.js +15 -15
- package/dist/module/ValueAtRiskWidget/components/Legend/Legend.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/components/Legend/MobileLegend.js +8 -8
- package/dist/module/ValueAtRiskWidget/components/Legend/MobileLegend.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/components/Legend/constants.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/components/Legend/types.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/render.js +9 -9
- package/dist/module/ValueAtRiskWidget/render.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/types.js.map +1 -1
- package/dist/module/ValueAtRiskWidget/utils.js +2 -2
- package/dist/module/ValueAtRiskWidget/utils.js.map +1 -1
- package/dist/module/gql/getValueAtRiskAssetClasses.js +3 -11
- package/dist/module/gql/getValueAtRiskAssetClasses.js.map +1 -1
- package/dist/module/gql/getValueAtRiskChart.js +3 -26
- package/dist/module/gql/getValueAtRiskChart.js.map +1 -1
- package/dist/module/gql/types/fragment-masking.js +3 -2
- package/dist/module/gql/types/fragment-masking.js.map +1 -1
- package/dist/module/gql/types/gql.js +4 -3
- package/dist/module/gql/types/gql.js.map +1 -1
- package/dist/module/gql/types/graphql.js +241 -241
- package/dist/module/gql/types/graphql.js.map +1 -1
- package/dist/module/gql/types/index.js +2 -2
- package/dist/module/gql/types/index.js.map +1 -1
- package/dist/module/translations/index.js +1 -1
- package/dist/module/translations/index.js.map +1 -1
- package/dist/module/translations/translations.js.map +1 -1
- package/dist/types/ValueAtRiskWidget/ChartWithData.d.ts +1 -1
- package/dist/types/ValueAtRiskWidget/Tool.d.ts +1 -1
- package/dist/types/ValueAtRiskWidget/ToolWithData.d.ts +1 -1
- package/dist/types/ValueAtRiskWidget/ValueAtRiskWidget.d.ts +1 -1
- package/dist/types/ValueAtRiskWidget/Widget.d.ts +2 -2
- package/dist/types/ValueAtRiskWidget/components/Chart/Chart.d.ts +1 -1
- package/dist/types/ValueAtRiskWidget/components/Chart/getOption.d.ts +1 -1
- package/dist/types/ValueAtRiskWidget/components/Chart/types.d.ts +2 -2
- package/dist/types/ValueAtRiskWidget/components/Legend/DashedLine.d.ts +2 -2
- package/dist/types/ValueAtRiskWidget/components/Legend/DesktopLegend.d.ts +1 -1
- package/dist/types/ValueAtRiskWidget/components/Legend/Legend.d.ts +1 -1
- package/dist/types/ValueAtRiskWidget/components/Legend/MobileLegend.d.ts +1 -1
- package/dist/types/ValueAtRiskWidget/components/Legend/constants.d.ts +1 -1
- package/dist/types/ValueAtRiskWidget/components/Legend/types.d.ts +1 -1
- package/dist/types/ValueAtRiskWidget/types.d.ts +2 -2
- package/dist/types/ValueAtRiskWidget/utils.d.ts +2 -2
- package/dist/types/gql/types/gql.d.ts +4 -4
- package/dist/types/gql/types/index.d.ts +2 -2
- package/dist/types/translations/index.d.ts +2 -2
- package/package.json +3 -3
- package/src/ValueAtRiskWidget/ChartWithData.tsx +45 -26
- package/src/ValueAtRiskWidget/Tool.tsx +42 -28
- package/src/ValueAtRiskWidget/ToolWithData.tsx +29 -23
- package/src/ValueAtRiskWidget/ValueAtRiskWidget.tsx +16 -16
- package/src/ValueAtRiskWidget/Widget.tsx +7 -11
- package/src/ValueAtRiskWidget/components/Chart/Chart.tsx +20 -19
- package/src/ValueAtRiskWidget/components/Chart/getOption.ts +4 -4
- package/src/ValueAtRiskWidget/components/Chart/types.ts +4 -3
- package/src/ValueAtRiskWidget/components/Legend/DashedLine.tsx +18 -8
- package/src/ValueAtRiskWidget/components/Legend/DesktopLegend.tsx +28 -19
- package/src/ValueAtRiskWidget/components/Legend/Legend.tsx +11 -14
- package/src/ValueAtRiskWidget/components/Legend/MobileLegend.tsx +40 -22
- package/src/ValueAtRiskWidget/components/Legend/constants.tsx +1 -1
- package/src/ValueAtRiskWidget/components/Legend/types.tsx +9 -9
- package/src/ValueAtRiskWidget/render.tsx +22 -24
- package/src/ValueAtRiskWidget/types.ts +7 -3
- package/src/ValueAtRiskWidget/utils.ts +18 -10
- package/src/gql/getValueAtRiskAssetClasses.ts +1 -1
- package/src/gql/getValueAtRiskChart.ts +12 -2
- package/src/gql/types/fragment-masking.ts +41 -21
- package/src/gql/types/gql.ts +12 -5
- package/src/gql/types/graphql.ts +339 -47
- package/src/gql/types/index.ts +2 -2
- package/src/translations/index.ts +4 -4
- package/src/translations/translations.ts +1 -3
- package/test/ChartWithData.test.tsx +21 -13
- package/test/Tool.test.tsx +35 -21
- package/test/ToolWithData.test.tsx +18 -7
- package/test/Widget.test.tsx +13 -8
- package/test/getPercentValueByPips.test.ts +15 -3
- package/test/mocks/assetClassesMock.ts +1 -3
- package/test/mocks/responsesMocks.ts +6 -2
- package/test/utils.test.ts +14 -7
|
@@ -1,42 +1,58 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
Select, SelectOption, Size, useLayoutProvider,
|
|
5
|
-
} from '@oanda/labs-widget-common';
|
|
1
|
+
import type { SelectOption } from '@oanda/labs-widget-common';
|
|
2
|
+
import { Select, Size, useLayoutProvider } from '@oanda/labs-widget-common';
|
|
6
3
|
import { useLocale } from '@oanda/mono-i18n';
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
|
|
4
|
+
import classnames from 'classnames';
|
|
5
|
+
import React, { useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { ValueAtRiskBars, ValueAtRiskDuration } from '../gql/types/graphql';
|
|
10
8
|
import { ChartWithData } from './ChartWithData';
|
|
9
|
+
import type { ToolProps } from './types';
|
|
10
|
+
import { getAssetClassesList, getInstrumentsByAssetClassId } from './utils';
|
|
11
11
|
|
|
12
12
|
const Tool = ({ data, division }: ToolProps) => {
|
|
13
13
|
const { lang } = useLocale();
|
|
14
14
|
const { size } = useLayoutProvider();
|
|
15
15
|
const isDesktop = size === Size.DESKTOP;
|
|
16
16
|
|
|
17
|
-
const assetClassesOptions = getAssetClassesList(
|
|
17
|
+
const assetClassesOptions = getAssetClassesList(
|
|
18
|
+
data!.valueAtRiskAssetClasses!
|
|
19
|
+
);
|
|
18
20
|
const initInstrumentsOptions = getInstrumentsByAssetClassId(
|
|
19
21
|
data!.valueAtRiskAssetClasses!,
|
|
20
|
-
assetClassesOptions[0].id
|
|
22
|
+
assetClassesOptions[0].id
|
|
21
23
|
);
|
|
22
24
|
|
|
23
|
-
const holdTimeOptions = Object.values(ValueAtRiskDuration).map(
|
|
24
|
-
|
|
25
|
+
const holdTimeOptions = Object.values(ValueAtRiskDuration).map(
|
|
26
|
+
(duration) => ({
|
|
27
|
+
id: duration as string,
|
|
28
|
+
label: lang('day', { count: +duration.substring(1) }),
|
|
29
|
+
})
|
|
30
|
+
);
|
|
31
|
+
const calculationPeriodOptions = Object.values(ValueAtRiskBars).map(
|
|
32
|
+
(bars) => ({
|
|
33
|
+
id: bars as string,
|
|
34
|
+
label: lang('day', { count: +bars.substring(1) }),
|
|
35
|
+
})
|
|
36
|
+
);
|
|
25
37
|
|
|
26
38
|
const [selectedAssetClass, setSelectedAssetClass] = useState(
|
|
27
|
-
assetClassesOptions[0]
|
|
39
|
+
assetClassesOptions[0]
|
|
40
|
+
);
|
|
41
|
+
const [instrumentsList, setInstrumentsList] = useState(
|
|
42
|
+
initInstrumentsOptions
|
|
43
|
+
);
|
|
44
|
+
const [selectedInstrument, setSelectedInstrument] = useState(
|
|
45
|
+
initInstrumentsOptions[0]
|
|
28
46
|
);
|
|
29
|
-
const [instrumentsList, setInstrumentsList] = useState(initInstrumentsOptions);
|
|
30
|
-
const [selectedInstrument, setSelectedInstrument] = useState(initInstrumentsOptions[0]);
|
|
31
47
|
const [selectedHoldTime, setSelectedHoldTime] = useState(holdTimeOptions[0]);
|
|
32
48
|
const [selectedCalculationPeriod, setSelectedCalculationPeriod] = useState(
|
|
33
|
-
calculationPeriodOptions[0]
|
|
49
|
+
calculationPeriodOptions[0]
|
|
34
50
|
);
|
|
35
51
|
|
|
36
52
|
const handleAssetClassSelect = (selectedOption: SelectOption) => {
|
|
37
53
|
const list = getInstrumentsByAssetClassId(
|
|
38
54
|
data!.valueAtRiskAssetClasses!,
|
|
39
|
-
selectedOption.id
|
|
55
|
+
selectedOption.id
|
|
40
56
|
);
|
|
41
57
|
|
|
42
58
|
setSelectedAssetClass(selectedOption);
|
|
@@ -48,51 +64,49 @@ const Tool = ({ data, division }: ToolProps) => {
|
|
|
48
64
|
|
|
49
65
|
return (
|
|
50
66
|
<div
|
|
51
|
-
data-testid="value-at-risk-tool-wrapper"
|
|
52
67
|
className="lw-relative lw-text-sm lw-tracking-normal"
|
|
68
|
+
data-testid="value-at-risk-tool-wrapper"
|
|
53
69
|
>
|
|
54
|
-
<div
|
|
55
|
-
'lw-mb-8 lw-grid',
|
|
56
|
-
{
|
|
70
|
+
<div
|
|
71
|
+
className={classnames('lw-mb-8 lw-grid', {
|
|
57
72
|
'lw-grid-cols-4 lw-gap-2': isDesktop && showAssetClassesSelect,
|
|
58
73
|
'lw-grid-cols-3 lw-gap-2.5': isDesktop && !showAssetClassesSelect,
|
|
59
74
|
'lw-grid-cols-1 lw-gap-4': !isDesktop,
|
|
60
|
-
}
|
|
61
|
-
)}
|
|
75
|
+
})}
|
|
62
76
|
>
|
|
63
77
|
{showAssetClassesSelect ? (
|
|
64
78
|
<Select
|
|
65
|
-
selectLabel={lang('instrument_type')}
|
|
66
79
|
options={assetClassesOptions}
|
|
80
|
+
selectLabel={lang('instrument_type')}
|
|
67
81
|
selectedOption={selectedAssetClass}
|
|
68
82
|
setSelectedOption={handleAssetClassSelect}
|
|
69
83
|
/>
|
|
70
84
|
) : null}
|
|
71
85
|
<Select
|
|
86
|
+
options={instrumentsList}
|
|
72
87
|
searchPlaceholder={lang('search')}
|
|
73
88
|
selectLabel={lang('instrument')}
|
|
74
|
-
options={instrumentsList}
|
|
75
89
|
selectedOption={selectedInstrument}
|
|
76
90
|
setSelectedOption={setSelectedInstrument}
|
|
77
91
|
/>
|
|
78
92
|
<Select
|
|
79
|
-
selectLabel={lang('hold_time')}
|
|
80
93
|
options={holdTimeOptions}
|
|
94
|
+
selectLabel={lang('hold_time')}
|
|
81
95
|
selectedOption={selectedHoldTime}
|
|
82
96
|
setSelectedOption={setSelectedHoldTime}
|
|
83
97
|
/>
|
|
84
98
|
<Select
|
|
85
|
-
selectLabel={lang('calculation_period')}
|
|
86
99
|
options={calculationPeriodOptions}
|
|
100
|
+
selectLabel={lang('calculation_period')}
|
|
87
101
|
selectedOption={selectedCalculationPeriod}
|
|
88
102
|
setSelectedOption={setSelectedCalculationPeriod}
|
|
89
103
|
/>
|
|
90
104
|
</div>
|
|
91
105
|
<ChartWithData
|
|
92
106
|
bars={selectedCalculationPeriod.id as ValueAtRiskBars}
|
|
107
|
+
division={division}
|
|
93
108
|
duration={selectedHoldTime.id as ValueAtRiskDuration}
|
|
94
109
|
instrument={selectedInstrument.id}
|
|
95
|
-
division={division}
|
|
96
110
|
/>
|
|
97
111
|
</div>
|
|
98
112
|
);
|
|
@@ -1,20 +1,28 @@
|
|
|
1
|
-
import
|
|
2
|
-
import classnames from 'classnames';
|
|
1
|
+
import { useQuery } from '@apollo/client';
|
|
3
2
|
import {
|
|
4
|
-
ChartError,
|
|
3
|
+
ChartError,
|
|
4
|
+
Size,
|
|
5
|
+
Spinner,
|
|
6
|
+
SpinnerSize,
|
|
7
|
+
useLayoutProvider,
|
|
5
8
|
} from '@oanda/labs-widget-common';
|
|
6
|
-
import
|
|
9
|
+
import classnames from 'classnames';
|
|
10
|
+
import React from 'react';
|
|
11
|
+
|
|
7
12
|
import { getValueAtRiskAssetClasses } from '../gql/getValueAtRiskAssetClasses';
|
|
13
|
+
import type {
|
|
14
|
+
GetValueAtRiskAssetClassesQuery,
|
|
15
|
+
GetValueAtRiskAssetClassesQueryVariables,
|
|
16
|
+
} from '../gql/types/graphql';
|
|
8
17
|
import { Tool } from './Tool';
|
|
9
|
-
import { ToolWithDataProps } from './types';
|
|
10
|
-
import { GetValueAtRiskAssetClassesQuery, GetValueAtRiskAssetClassesQueryVariables } from '../gql/types/graphql';
|
|
18
|
+
import type { ToolWithDataProps } from './types';
|
|
11
19
|
|
|
12
20
|
const ToolWithData = ({ division }: ToolWithDataProps) => {
|
|
13
21
|
const { size } = useLayoutProvider();
|
|
14
22
|
const isDesktop = size === Size.DESKTOP;
|
|
15
23
|
const { loading, data, error } = useQuery<
|
|
16
|
-
|
|
17
|
-
|
|
24
|
+
GetValueAtRiskAssetClassesQuery,
|
|
25
|
+
GetValueAtRiskAssetClassesQueryVariables
|
|
18
26
|
>(getValueAtRiskAssetClasses, {
|
|
19
27
|
variables: {
|
|
20
28
|
division,
|
|
@@ -24,22 +32,20 @@ const ToolWithData = ({ division }: ToolWithDataProps) => {
|
|
|
24
32
|
|
|
25
33
|
return (
|
|
26
34
|
<div data-testid="value-at-risk-wrapper">
|
|
27
|
-
{(loading || !size)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
data={data}
|
|
40
|
-
division={division}
|
|
41
|
-
/>
|
|
35
|
+
{(loading || !size) && (
|
|
36
|
+
<div
|
|
37
|
+
className={classnames(
|
|
38
|
+
'lw-flex lw-w-full lw-items-center lw-border lw-border-solid lw-border-border-primary',
|
|
39
|
+
{
|
|
40
|
+
'lw-h-[566px]': isDesktop,
|
|
41
|
+
'lw-h-[840px]': !isDesktop,
|
|
42
|
+
}
|
|
43
|
+
)}
|
|
44
|
+
>
|
|
45
|
+
<Spinner size={SpinnerSize.lg} />
|
|
46
|
+
</div>
|
|
42
47
|
)}
|
|
48
|
+
{!loading && data && <Tool data={data} division={division} />}
|
|
43
49
|
{!loading && error && (
|
|
44
50
|
<div className="lw-flex lw-h-[500px] lw-w-full lw-items-center lw-border lw-border-solid lw-border-border-primary">
|
|
45
51
|
<ChartError />
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { ApolloClient, InMemoryCache } from '@apollo/client';
|
|
3
2
|
import { WidgetProvider, WidgetWrapper } from '@oanda/labs-widget-common';
|
|
3
|
+
import React from 'react';
|
|
4
4
|
|
|
5
|
-
import { ValueAtRiskConfig } from './types';
|
|
6
5
|
import { translations } from '../translations';
|
|
7
6
|
import { ToolWithData } from './ToolWithData';
|
|
7
|
+
import type { ValueAtRiskConfig } from './types';
|
|
8
8
|
import { Widget } from './Widget';
|
|
9
9
|
|
|
10
10
|
const ValueAtRiskWidget = ({
|
|
@@ -26,26 +26,26 @@ const ValueAtRiskWidget = ({
|
|
|
26
26
|
|
|
27
27
|
return (
|
|
28
28
|
<WidgetProvider
|
|
29
|
-
locale={locale}
|
|
30
|
-
translations={translations}
|
|
31
29
|
client={client}
|
|
30
|
+
locale={locale}
|
|
32
31
|
theme={theme}
|
|
32
|
+
translations={translations}
|
|
33
33
|
>
|
|
34
34
|
<WidgetWrapper
|
|
35
|
-
logoLink={logoLink}
|
|
36
|
-
linkArea="logo"
|
|
37
35
|
isParamError={isParamError}
|
|
36
|
+
linkArea="logo"
|
|
37
|
+
logoLink={logoLink}
|
|
38
38
|
>
|
|
39
|
-
{
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
39
|
+
{isWidget ? (
|
|
40
|
+
<Widget
|
|
41
|
+
bars={bars}
|
|
42
|
+
division={division}
|
|
43
|
+
duration={duration}
|
|
44
|
+
instrument={instrument}
|
|
45
|
+
/>
|
|
46
|
+
) : (
|
|
47
|
+
<ToolWithData division={division} />
|
|
48
|
+
)}
|
|
49
49
|
</WidgetWrapper>
|
|
50
50
|
</WidgetProvider>
|
|
51
51
|
);
|
|
@@ -1,24 +1,20 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import classnames from 'classnames';
|
|
3
1
|
import { Size, useLayoutProvider } from '@oanda/labs-widget-common';
|
|
4
2
|
import { useLocale } from '@oanda/mono-i18n';
|
|
5
|
-
import
|
|
3
|
+
import classnames from 'classnames';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
|
|
6
6
|
import { ChartWithData } from './ChartWithData';
|
|
7
|
+
import type { WidgetProps } from './types';
|
|
7
8
|
|
|
8
|
-
const Widget = ({
|
|
9
|
-
division,
|
|
10
|
-
instrument,
|
|
11
|
-
duration,
|
|
12
|
-
bars,
|
|
13
|
-
}: WidgetProps) => {
|
|
9
|
+
const Widget = ({ division, instrument, duration, bars }: WidgetProps) => {
|
|
14
10
|
const { lang } = useLocale();
|
|
15
11
|
const { size } = useLayoutProvider();
|
|
16
12
|
const isDesktop = size === Size.DESKTOP;
|
|
17
13
|
|
|
18
14
|
return (
|
|
19
15
|
<div
|
|
20
|
-
data-testid="value-at-risk-widget-wrapper"
|
|
21
16
|
className="lw-relative lw-text-sm lw-tracking-normal"
|
|
17
|
+
data-testid="value-at-risk-widget-wrapper"
|
|
22
18
|
>
|
|
23
19
|
{size && (
|
|
24
20
|
<>
|
|
@@ -33,9 +29,9 @@ const Widget = ({
|
|
|
33
29
|
</div>
|
|
34
30
|
<ChartWithData
|
|
35
31
|
bars={bars}
|
|
32
|
+
division={division}
|
|
36
33
|
duration={duration}
|
|
37
34
|
instrument={instrument}
|
|
38
|
-
division={division}
|
|
39
35
|
/>
|
|
40
36
|
</>
|
|
41
37
|
)}
|
|
@@ -1,28 +1,29 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import ReactEChartsCore from 'echarts-for-react/lib/core';
|
|
3
|
-
import * as echarts from 'echarts/core';
|
|
4
|
-
import { LineChart, CustomChart } from 'echarts/charts';
|
|
5
|
-
import { CanvasRenderer } from 'echarts/renderers';
|
|
6
1
|
import {
|
|
7
|
-
|
|
2
|
+
getChartTheme,
|
|
3
|
+
Size,
|
|
4
|
+
Theme,
|
|
5
|
+
useLayoutProvider,
|
|
6
|
+
} from '@oanda/labs-widget-common';
|
|
7
|
+
import { useLocale } from '@oanda/mono-i18n';
|
|
8
|
+
import { CustomChart, LineChart } from 'echarts/charts';
|
|
9
|
+
import {
|
|
10
|
+
AxisPointerComponent,
|
|
11
|
+
DatasetComponent,
|
|
8
12
|
GraphicComponent,
|
|
13
|
+
GridSimpleComponent,
|
|
14
|
+
MarkLineComponent,
|
|
9
15
|
MarkPointComponent,
|
|
10
16
|
TitleComponent,
|
|
11
|
-
DatasetComponent,
|
|
12
17
|
VisualMapComponent,
|
|
13
|
-
MarkLineComponent,
|
|
14
|
-
AxisPointerComponent,
|
|
15
18
|
} from 'echarts/components';
|
|
16
|
-
import
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
getChartTheme,
|
|
22
|
-
} from '@oanda/labs-widget-common';
|
|
19
|
+
import * as echarts from 'echarts/core';
|
|
20
|
+
import { CanvasRenderer } from 'echarts/renderers';
|
|
21
|
+
import ReactEChartsCore from 'echarts-for-react/lib/core';
|
|
22
|
+
import React from 'react';
|
|
23
|
+
|
|
23
24
|
import { CHART_HEIGHT } from './constants';
|
|
24
25
|
import { getOption } from './getOption';
|
|
25
|
-
import { ChartProps } from './types';
|
|
26
|
+
import type { ChartProps } from './types';
|
|
26
27
|
|
|
27
28
|
echarts.use([
|
|
28
29
|
GridSimpleComponent,
|
|
@@ -49,12 +50,12 @@ const Chart = ({ values }: ChartProps) => {
|
|
|
49
50
|
return (
|
|
50
51
|
<ReactEChartsCore
|
|
51
52
|
echarts={echarts}
|
|
52
|
-
|
|
53
|
+
option={getOption(values, lang, isDark, isDesktop)}
|
|
53
54
|
style={{
|
|
54
55
|
height: `${CHART_HEIGHT}px`,
|
|
55
56
|
width: '100%',
|
|
56
57
|
}}
|
|
57
|
-
|
|
58
|
+
theme={isDark ? 'dark_theme' : 'light_theme'}
|
|
58
59
|
/>
|
|
59
60
|
);
|
|
60
61
|
};
|
|
@@ -5,16 +5,17 @@ import {
|
|
|
5
5
|
getLineCommons,
|
|
6
6
|
lightTheme,
|
|
7
7
|
} from '@oanda/labs-widget-common';
|
|
8
|
+
|
|
8
9
|
import {
|
|
9
|
-
CHART_WIDTH,
|
|
10
10
|
CHART_HEIGHT,
|
|
11
|
+
CHART_WIDTH,
|
|
12
|
+
TITLE_HEIGHT,
|
|
11
13
|
X_LABEL_SIZE,
|
|
12
14
|
Y_LABEL_SIZE_DESKTOP,
|
|
13
|
-
TITLE_HEIGHT,
|
|
14
15
|
Y_LABEL_SIZE_MOBILE,
|
|
15
16
|
} from './constants';
|
|
16
|
-
import { GetOptionType } from './types';
|
|
17
17
|
import { getPercentValueByPips } from './getPercentValueByPips';
|
|
18
|
+
import type { GetOptionType } from './types';
|
|
18
19
|
|
|
19
20
|
export const getOption: GetOptionType = (values, lang, isDark, isDesktop) => {
|
|
20
21
|
const gridLines = getGridLines({
|
|
@@ -88,7 +89,6 @@ export const getOption: GetOptionType = (values, lang, isDark, isDesktop) => {
|
|
|
88
89
|
},
|
|
89
90
|
},
|
|
90
91
|
formatter: (value, index) => (index ? `${value}%` : `{a|${value}%}`),
|
|
91
|
-
|
|
92
92
|
},
|
|
93
93
|
axisPointer: {
|
|
94
94
|
label: {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { EChartsOption } from 'echarts';
|
|
2
|
-
|
|
1
|
+
import type { EChartsOption } from 'echarts';
|
|
2
|
+
|
|
3
|
+
import type { GetValueAtRiskChartQuery } from '../../../gql/types/graphql';
|
|
3
4
|
|
|
4
5
|
export interface ChartProps {
|
|
5
6
|
values: GetValueAtRiskChartQuery;
|
|
@@ -9,5 +10,5 @@ export type GetOptionType = (
|
|
|
9
10
|
values: GetValueAtRiskChartQuery,
|
|
10
11
|
lang: (label: string) => string,
|
|
11
12
|
isDark: boolean,
|
|
12
|
-
isDesktop: boolean
|
|
13
|
+
isDesktop: boolean
|
|
13
14
|
) => EChartsOption;
|
|
@@ -1,18 +1,28 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { colorPalette } from '@oanda/labs-widget-common';
|
|
3
|
-
import
|
|
4
|
-
DashedLineProps,
|
|
5
|
-
} from './types';
|
|
2
|
+
import React from 'react';
|
|
6
3
|
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
import type { DashedLineProps } from './types';
|
|
5
|
+
|
|
6
|
+
const DashedLine = ({
|
|
7
|
+
strokeDasharray,
|
|
8
|
+
width = '30',
|
|
9
|
+
isDark,
|
|
10
|
+
}: DashedLineProps) => (
|
|
11
|
+
<svg
|
|
12
|
+
className="lw-inline"
|
|
13
|
+
fill="none"
|
|
14
|
+
height="2"
|
|
15
|
+
viewBox={`0 0 ${width} 2`}
|
|
16
|
+
width={width}
|
|
17
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
18
|
+
>
|
|
9
19
|
<line
|
|
10
20
|
stroke={isDark ? colorPalette.white : colorPalette.bottleGreenDark}
|
|
21
|
+
strokeDasharray={strokeDasharray}
|
|
11
22
|
x1="0"
|
|
12
|
-
y1="1"
|
|
13
23
|
x2={width}
|
|
24
|
+
y1="1"
|
|
14
25
|
y2="1"
|
|
15
|
-
strokeDasharray={strokeDasharray}
|
|
16
26
|
/>
|
|
17
27
|
</svg>
|
|
18
28
|
);
|
|
@@ -1,37 +1,46 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import classnames from 'classnames';
|
|
3
|
-
import
|
|
4
|
-
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
5
4
|
import { lineTypes } from './constants';
|
|
5
|
+
import { DashedLine } from './DashedLine';
|
|
6
|
+
import type { DesktopLegendProps } from './types';
|
|
7
|
+
import { DataNames } from './types';
|
|
6
8
|
|
|
7
9
|
const DesktopLegend = ({ data, lang, isDark }: DesktopLegendProps) => (
|
|
8
|
-
<div
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
<div
|
|
11
|
+
className={classnames(
|
|
12
|
+
'lw-pointer-events-none lw-absolute lw-top-[50px] lw-z-10 lw-p-2 lw-text-xs',
|
|
13
|
+
{
|
|
14
|
+
'lw-left-[6px]': data[0].value < 0,
|
|
15
|
+
'lw-right-[66px]': data[0].value > 0,
|
|
16
|
+
'lw-bg-border-primary': isDark,
|
|
17
|
+
'lw-bg-bg-primary lw-shadow': !isDark,
|
|
18
|
+
}
|
|
19
|
+
)}
|
|
14
20
|
>
|
|
15
21
|
{data.map((item) => (
|
|
16
22
|
<div
|
|
17
23
|
key={item.id}
|
|
18
24
|
className={classnames('lw-flex lw-items-center', {
|
|
19
|
-
'[&_line]:lw-stroke-border-disabled':
|
|
25
|
+
'[&_line]:lw-stroke-border-disabled':
|
|
26
|
+
item.id === DataNames.MAX || item.id === DataNames.MIN,
|
|
20
27
|
})}
|
|
21
28
|
>
|
|
22
29
|
<DashedLine isDark={isDark} strokeDasharray={lineTypes[item.id]} />
|
|
23
30
|
{item.id !== DataNames.MAX && item.id !== DataNames.MIN && (
|
|
24
|
-
<div
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
<div
|
|
32
|
+
className={classnames(
|
|
33
|
+
'lw-ml-[-8px] lw-h-[8px] lw-w-[8px] lw-border-[1px] lw-border-white lw-bg-gold',
|
|
34
|
+
{
|
|
35
|
+
'lw-rounded-full': item.value < 0,
|
|
36
|
+
'lw-bg-gold': item.id === DataNames.AVERAGE,
|
|
37
|
+
'lw-bg-turquoise-light': item.id === DataNames.MEDIAN,
|
|
38
|
+
'lw-bg-violet-light': item.id === DataNames.THRESHOLD,
|
|
39
|
+
}
|
|
40
|
+
)}
|
|
30
41
|
/>
|
|
31
42
|
)}
|
|
32
|
-
<span className="lw-px-2">
|
|
33
|
-
{`${item.label}:`}
|
|
34
|
-
</span>
|
|
43
|
+
<span className="lw-px-2">{`${item.label}:`}</span>
|
|
35
44
|
<span className="lw-grow lw-text-right">
|
|
36
45
|
{`${item.value.toFixed()} ${lang('pips')}`}
|
|
37
46
|
</span>
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
Size,
|
|
4
|
-
useLayoutProvider,
|
|
5
|
-
} from '@oanda/labs-widget-common';
|
|
1
|
+
import { Size, useLayoutProvider } from '@oanda/labs-widget-common';
|
|
6
2
|
import { useLocale } from '@oanda/mono-i18n';
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
} from './types';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
10
5
|
import { DesktopLegend } from './DesktopLegend';
|
|
11
6
|
import { MobileLegend } from './MobileLegend';
|
|
7
|
+
import type { LegendProps } from './types';
|
|
8
|
+
import { DataNames } from './types';
|
|
12
9
|
|
|
13
10
|
const Legend = ({ data }: LegendProps) => {
|
|
14
11
|
const { size, isDark } = useLayoutProvider();
|
|
@@ -20,8 +17,6 @@ const Legend = ({ data }: LegendProps) => {
|
|
|
20
17
|
{isDesktop ? (
|
|
21
18
|
<>
|
|
22
19
|
<DesktopLegend
|
|
23
|
-
isDark={isDark}
|
|
24
|
-
lang={lang}
|
|
25
20
|
data={[
|
|
26
21
|
{
|
|
27
22
|
id: DataNames.AVERAGE,
|
|
@@ -44,10 +39,10 @@ const Legend = ({ data }: LegendProps) => {
|
|
|
44
39
|
value: data.valueAtRiskChart!.down.max,
|
|
45
40
|
},
|
|
46
41
|
]}
|
|
47
|
-
/>
|
|
48
|
-
<DesktopLegend
|
|
49
42
|
isDark={isDark}
|
|
50
43
|
lang={lang}
|
|
44
|
+
/>
|
|
45
|
+
<DesktopLegend
|
|
51
46
|
data={[
|
|
52
47
|
{
|
|
53
48
|
id: DataNames.AVERAGE,
|
|
@@ -70,12 +65,12 @@ const Legend = ({ data }: LegendProps) => {
|
|
|
70
65
|
value: data.valueAtRiskChart!.up.max,
|
|
71
66
|
},
|
|
72
67
|
]}
|
|
68
|
+
isDark={isDark}
|
|
69
|
+
lang={lang}
|
|
73
70
|
/>
|
|
74
71
|
</>
|
|
75
72
|
) : (
|
|
76
73
|
<MobileLegend
|
|
77
|
-
isDark={isDark}
|
|
78
|
-
lang={lang}
|
|
79
74
|
data={[
|
|
80
75
|
{
|
|
81
76
|
id: DataNames.AVERAGE,
|
|
@@ -102,6 +97,8 @@ const Legend = ({ data }: LegendProps) => {
|
|
|
102
97
|
valueUp: data.valueAtRiskChart!.up.max,
|
|
103
98
|
},
|
|
104
99
|
]}
|
|
100
|
+
isDark={isDark}
|
|
101
|
+
lang={lang}
|
|
105
102
|
/>
|
|
106
103
|
)}
|
|
107
104
|
</>
|
|
@@ -1,44 +1,62 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import classnames from 'classnames';
|
|
3
|
-
import
|
|
4
|
-
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
5
4
|
import { lineTypes } from './constants';
|
|
5
|
+
import { DashedLine } from './DashedLine';
|
|
6
|
+
import type { MobileLegendProps } from './types';
|
|
7
|
+
import { DataNames } from './types';
|
|
6
8
|
|
|
7
9
|
const MobileLegend = ({ data, isDark, lang }: MobileLegendProps) => (
|
|
8
|
-
<div
|
|
9
|
-
'lw-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
<div
|
|
11
|
+
className={classnames('lw-mb-6 lw-p-2 lw-text-xs', {
|
|
12
|
+
'lw-bg-border-primary': isDark,
|
|
13
|
+
'lw-border lw-border-solid lw-border-border-primary': !isDark,
|
|
14
|
+
})}
|
|
12
15
|
>
|
|
13
16
|
{data.map((item) => (
|
|
14
17
|
<div
|
|
15
18
|
key={item.id}
|
|
16
19
|
className={classnames('lw-flex lw-items-center lw-justify-between', {
|
|
17
|
-
'[&_line]:lw-stroke-border-disabled':
|
|
20
|
+
'[&_line]:lw-stroke-border-disabled':
|
|
21
|
+
item.id === DataNames.MAX || item.id === DataNames.MIN,
|
|
18
22
|
})}
|
|
19
23
|
>
|
|
20
24
|
<div className="lw-mr-2 lw-flex lw-w-10 lw-items-center">
|
|
21
25
|
{item.id !== DataNames.MAX && item.id !== DataNames.MIN && (
|
|
22
|
-
<div
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
<div
|
|
27
|
+
className={classnames(
|
|
28
|
+
'lw-h-[8px] lw-w-[8px] lw-rounded-full lw-border-[1px] lw-border-white lw-bg-gold',
|
|
29
|
+
{
|
|
30
|
+
'lw-bg-gold': item.id === DataNames.AVERAGE,
|
|
31
|
+
'lw-bg-turquoise-light': item.id === DataNames.MEDIAN,
|
|
32
|
+
'lw-bg-violet-light': item.id === DataNames.THRESHOLD,
|
|
33
|
+
}
|
|
34
|
+
)}
|
|
27
35
|
/>
|
|
28
36
|
)}
|
|
29
|
-
<DashedLine
|
|
37
|
+
<DashedLine
|
|
38
|
+
isDark={isDark}
|
|
39
|
+
strokeDasharray={lineTypes[item.id]}
|
|
40
|
+
width={
|
|
41
|
+
item.id === DataNames.MAX || item.id === DataNames.MIN
|
|
42
|
+
? '38'
|
|
43
|
+
: undefined
|
|
44
|
+
}
|
|
45
|
+
/>
|
|
30
46
|
{item.id !== DataNames.MAX && item.id !== DataNames.MIN && (
|
|
31
|
-
<div
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
47
|
+
<div
|
|
48
|
+
className={classnames(
|
|
49
|
+
'lw-ml-[-8px] lw-h-[8px] lw-w-[8px] lw-border-[1px] lw-border-white lw-bg-gold',
|
|
50
|
+
{
|
|
51
|
+
'lw-bg-gold': item.id === DataNames.AVERAGE,
|
|
52
|
+
'lw-bg-turquoise-light': item.id === DataNames.MEDIAN,
|
|
53
|
+
'lw-bg-violet-light': item.id === DataNames.THRESHOLD,
|
|
54
|
+
}
|
|
55
|
+
)}
|
|
36
56
|
/>
|
|
37
57
|
)}
|
|
38
58
|
</div>
|
|
39
|
-
<span className="lw-flex-1 lw-px-2">
|
|
40
|
-
{`${item.label}:`}
|
|
41
|
-
</span>
|
|
59
|
+
<span className="lw-flex-1 lw-px-2">{`${item.label}:`}</span>
|
|
42
60
|
<span className="lw-flex-1 lw-text-right">
|
|
43
61
|
{`${item.valueDown.toFixed()} ${lang('pips')}`}
|
|
44
62
|
</span>
|