@oliasoft-open-source/charts-library 2.11.2 → 2.12.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.
- package/package.json +2 -2
- package/release-notes.md +10 -2
- package/src/components/controls/axes-options/axes-options-form-state.js +10 -2
- package/src/components/controls/axes-options/axes-options.jsx +75 -5
- package/src/components/controls/controls.jsx +2 -0
- package/src/components/line-chart/get-axes-ranges-from-chart.js +5 -2
- package/src/components/line-chart/line-chart-prop-types.js +11 -0
- package/src/components/line-chart/line-chart.interface.ts +13 -0
- package/src/components/line-chart/line-chart.jsx +7 -1
- package/src/components/line-chart/state/initial-state.js +10 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oliasoft-open-source/charts-library",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.12.0",
|
|
4
4
|
"description": "React Chart Library (based on Chart.js and react-chart-js-2)",
|
|
5
5
|
"homepage": "https://gitlab.com/oliasoft-open-source/charts-library",
|
|
6
6
|
"bugs": {
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@babel/eslint-parser": "^7.18.9",
|
|
50
50
|
"@babel/preset-env": "^7.18.10",
|
|
51
51
|
"@babel/preset-react": "^7.18.6",
|
|
52
|
-
"@oliasoft-open-source/react-ui-library": "3.3.
|
|
52
|
+
"@oliasoft-open-source/react-ui-library": "3.3.12",
|
|
53
53
|
"@oliasoft-open-source/units": "2.1.0",
|
|
54
54
|
"@storybook/addon-actions": "^6.5.10",
|
|
55
55
|
"@storybook/addon-docs": "^6.5.10",
|
package/release-notes.md
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
# Charts Library Release Notes
|
|
2
2
|
|
|
3
|
+
## 2.12.0
|
|
4
|
+
|
|
5
|
+
- Add unit selector and depth selector to axes options ([OW-9496](https://oliasoft.atlassian.net/browse/OW-9496))
|
|
6
|
+
|
|
7
|
+
## 2.11.3
|
|
8
|
+
|
|
9
|
+
- Submit Axes option on keyboard Enter ([OW-10995](https://oliasoft.atlassian.net/browse/OW-10995))
|
|
10
|
+
|
|
3
11
|
## 2.11.2
|
|
4
12
|
|
|
5
13
|
- remove number handling functions that were duplicated from units package
|
|
6
|
-
([OW-11062](https://oliasoft.atlassian.net/browse/OW-11062))
|
|
14
|
+
([OW-11062](https://oliasoft.atlassian.net/browse/OW-11062))
|
|
7
15
|
|
|
8
16
|
## 2.11.1
|
|
9
17
|
|
|
@@ -20,7 +28,7 @@
|
|
|
20
28
|
## 2.10.1
|
|
21
29
|
|
|
22
30
|
- Use `peerDependencies` for common versions of shared packages like `units` and `react-ui-library` so reduce double
|
|
23
|
-
installs and conflicting versions in parent apps ([OW-10974](https://oliasoft.atlassian.net/browse/OW-10974))
|
|
31
|
+
installs and conflicting versions in parent apps ([OW-10974](https://oliasoft.atlassian.net/browse/OW-10974))
|
|
24
32
|
|
|
25
33
|
## 2.10.0
|
|
26
34
|
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
export const actionTypes = Object.freeze({
|
|
9
9
|
reset: 'reset',
|
|
10
10
|
valueUpdated: 'valueUpdated',
|
|
11
|
+
unitUpdated: 'unitUpdated',
|
|
11
12
|
});
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -25,6 +26,7 @@ export const initializeFormState = ({ initialAxesRanges, axes = [] }) => {
|
|
|
25
26
|
id: initialAxisRange.id,
|
|
26
27
|
min: currentAxisRange?.min ?? initialAxisRange?.min,
|
|
27
28
|
max: currentAxisRange?.max ?? initialAxisRange?.max,
|
|
29
|
+
unit: currentAxisRange?.unit,
|
|
28
30
|
};
|
|
29
31
|
});
|
|
30
32
|
};
|
|
@@ -80,8 +82,8 @@ export const validateAxes = (formState) => {
|
|
|
80
82
|
export const reducer = (state, action) => {
|
|
81
83
|
switch (action.type) {
|
|
82
84
|
case actionTypes.reset: {
|
|
83
|
-
const { initialAxesRanges } = action.payload;
|
|
84
|
-
return initializeFormState({ initialAxesRanges });
|
|
85
|
+
const { initialAxesRanges, axes } = action.payload;
|
|
86
|
+
return initializeFormState({ initialAxesRanges, axes });
|
|
85
87
|
}
|
|
86
88
|
case actionTypes.valueUpdated:
|
|
87
89
|
return produce(state, (draft) => {
|
|
@@ -89,6 +91,12 @@ export const reducer = (state, action) => {
|
|
|
89
91
|
const axis = draft.find((a) => a.id === id);
|
|
90
92
|
axis[name] = value;
|
|
91
93
|
});
|
|
94
|
+
case actionTypes.unitUpdated:
|
|
95
|
+
return produce(state, (draft) => {
|
|
96
|
+
const { name, value, id } = action.payload;
|
|
97
|
+
const axis = draft.find((a) => a.id === id);
|
|
98
|
+
axis.unit[name] = value;
|
|
99
|
+
});
|
|
92
100
|
default:
|
|
93
101
|
return state;
|
|
94
102
|
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import React, { useReducer } from 'react';
|
|
1
|
+
import React, { useReducer, useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Button,
|
|
4
|
+
ButtonGroup,
|
|
4
5
|
Field,
|
|
5
6
|
Flex,
|
|
6
7
|
Input,
|
|
7
8
|
InputGroup,
|
|
8
9
|
InputGroupAddon,
|
|
9
10
|
Popover,
|
|
11
|
+
Select,
|
|
12
|
+
Spacer,
|
|
10
13
|
Text,
|
|
11
14
|
Tooltip,
|
|
12
15
|
} from '@oliasoft-open-source/react-ui-library';
|
|
@@ -26,7 +29,11 @@ const AxesOptionsPopover = ({
|
|
|
26
29
|
onUpdateAxes,
|
|
27
30
|
onResetAxes,
|
|
28
31
|
close,
|
|
32
|
+
depthType,
|
|
29
33
|
}) => {
|
|
34
|
+
const [depthTypeState, setDepthTypeState] = useState(
|
|
35
|
+
depthType?.selectedDepthType,
|
|
36
|
+
);
|
|
30
37
|
const [formState, dispatch] = useReducer(
|
|
31
38
|
reducer,
|
|
32
39
|
{
|
|
@@ -45,7 +52,15 @@ const AxesOptionsPopover = ({
|
|
|
45
52
|
});
|
|
46
53
|
};
|
|
47
54
|
|
|
48
|
-
const
|
|
55
|
+
const onEditUnit = ({ name, value, id }) => {
|
|
56
|
+
dispatch({
|
|
57
|
+
type: actionTypes.unitUpdated,
|
|
58
|
+
payload: { name, value, id },
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const onDone = (e) => {
|
|
63
|
+
e.preventDefault();
|
|
49
64
|
if (valid) {
|
|
50
65
|
const sanitizedFormState = formState.map((axis) => ({
|
|
51
66
|
...axis,
|
|
@@ -55,6 +70,17 @@ const AxesOptionsPopover = ({
|
|
|
55
70
|
onUpdateAxes({
|
|
56
71
|
axes: sanitizedFormState,
|
|
57
72
|
});
|
|
73
|
+
|
|
74
|
+
//update units
|
|
75
|
+
sanitizedFormState.map((el, i) => {
|
|
76
|
+
if (el.unit?.selectedUnit) {
|
|
77
|
+
axes[i].unit.setSelectedUnit(el.unit.selectedUnit);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
//update depthType
|
|
81
|
+
if (depthType) {
|
|
82
|
+
depthType.setSelectedDepthType(depthTypeState);
|
|
83
|
+
}
|
|
58
84
|
}
|
|
59
85
|
close();
|
|
60
86
|
};
|
|
@@ -65,14 +91,22 @@ const AxesOptionsPopover = ({
|
|
|
65
91
|
type: actionTypes.reset,
|
|
66
92
|
payload: { axes, initialAxesRanges },
|
|
67
93
|
});
|
|
94
|
+
//update units
|
|
95
|
+
initialAxesRanges.map((el, i) => {
|
|
96
|
+
if (el?.unit?.selectedUnit) {
|
|
97
|
+
axes[i].unit.setSelectedUnit(el.unit.selectedUnit);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
68
101
|
//reset parent state
|
|
69
102
|
onResetAxes();
|
|
103
|
+
close();
|
|
70
104
|
};
|
|
71
105
|
|
|
72
106
|
const isCustomValue = axes.filter((axis) => axis.max || axis.min).length > 0;
|
|
73
107
|
const handleInputFocus = (e) => e.target.select();
|
|
74
108
|
return (
|
|
75
|
-
|
|
109
|
+
<form onSubmit={onDone}>
|
|
76
110
|
{axes.map((axis, i) => {
|
|
77
111
|
const axisLabel = controlsAxesLabels.find(
|
|
78
112
|
(el) => el.id === axis.id,
|
|
@@ -82,6 +116,7 @@ const AxesOptionsPopover = ({
|
|
|
82
116
|
const max = formState.find((a) => a.id === axis.id)?.max;
|
|
83
117
|
const minError = errors?.find((a) => a.id === axis.id)?.min?.[0];
|
|
84
118
|
const maxError = errors?.find((a) => a.id === axis.id)?.max?.[0];
|
|
119
|
+
const unit = formState.find((a) => a.id === axis.id)?.unit;
|
|
85
120
|
return (
|
|
86
121
|
<Field key={i} label={axisLabel || axis.id || ''}>
|
|
87
122
|
<InputGroup small>
|
|
@@ -116,12 +151,45 @@ const AxesOptionsPopover = ({
|
|
|
116
151
|
}
|
|
117
152
|
onFocus={handleInputFocus}
|
|
118
153
|
/>
|
|
154
|
+
{axis.unit ? (
|
|
155
|
+
<Select
|
|
156
|
+
name="selectedUnit"
|
|
157
|
+
options={axis?.unit?.options}
|
|
158
|
+
value={unit?.selectedUnit}
|
|
159
|
+
onChange={(e) => {
|
|
160
|
+
onEditUnit({
|
|
161
|
+
name: e.target.name,
|
|
162
|
+
value: e.target.value,
|
|
163
|
+
id: axis.id,
|
|
164
|
+
});
|
|
165
|
+
}}
|
|
166
|
+
width="auto"
|
|
167
|
+
/>
|
|
168
|
+
) : null}
|
|
119
169
|
</InputGroup>
|
|
120
170
|
</Field>
|
|
121
171
|
);
|
|
122
172
|
})}
|
|
173
|
+
|
|
174
|
+
{depthType?.options?.length > 0 ? (
|
|
175
|
+
<>
|
|
176
|
+
<ButtonGroup
|
|
177
|
+
items={depthType.options.map((depth, i) => ({
|
|
178
|
+
key: i,
|
|
179
|
+
label: depth,
|
|
180
|
+
}))}
|
|
181
|
+
onSelected={(key) => {
|
|
182
|
+
setDepthTypeState(depthType.options[key]);
|
|
183
|
+
}}
|
|
184
|
+
small
|
|
185
|
+
value={depthType.options.indexOf(depthTypeState)}
|
|
186
|
+
/>
|
|
187
|
+
<Spacer />
|
|
188
|
+
</>
|
|
189
|
+
) : null}
|
|
190
|
+
|
|
123
191
|
<Flex gap="8px" alignItems="center">
|
|
124
|
-
<Button small colored label="Done"
|
|
192
|
+
<Button type="submit" small colored label="Done" disabled={!valid} />
|
|
125
193
|
<Button
|
|
126
194
|
small
|
|
127
195
|
name="resetAxes"
|
|
@@ -133,7 +201,7 @@ const AxesOptionsPopover = ({
|
|
|
133
201
|
or double click on canvas
|
|
134
202
|
</Text>
|
|
135
203
|
</Flex>
|
|
136
|
-
|
|
204
|
+
</form>
|
|
137
205
|
);
|
|
138
206
|
};
|
|
139
207
|
|
|
@@ -143,6 +211,7 @@ export const AxesOptions = ({
|
|
|
143
211
|
controlsAxesLabels,
|
|
144
212
|
onUpdateAxes,
|
|
145
213
|
onResetAxes,
|
|
214
|
+
depthType,
|
|
146
215
|
}) => {
|
|
147
216
|
return (
|
|
148
217
|
<Popover
|
|
@@ -155,6 +224,7 @@ export const AxesOptions = ({
|
|
|
155
224
|
controlsAxesLabels={controlsAxesLabels}
|
|
156
225
|
onUpdateAxes={onUpdateAxes}
|
|
157
226
|
onResetAxes={onResetAxes}
|
|
227
|
+
depthType={depthType}
|
|
158
228
|
/>
|
|
159
229
|
}
|
|
160
230
|
>
|
|
@@ -34,6 +34,7 @@ const Controls = ({
|
|
|
34
34
|
subheaderComponent,
|
|
35
35
|
table,
|
|
36
36
|
zoomEnabled,
|
|
37
|
+
depthType,
|
|
37
38
|
enableDragPoints,
|
|
38
39
|
isDragDataAllowed,
|
|
39
40
|
onToggleDragPoints,
|
|
@@ -53,6 +54,7 @@ const Controls = ({
|
|
|
53
54
|
controlsAxesLabels={controlsAxesLabels}
|
|
54
55
|
onUpdateAxes={onUpdateAxes}
|
|
55
56
|
onResetAxes={onResetAxes}
|
|
57
|
+
depthType={depthType}
|
|
56
58
|
/>
|
|
57
59
|
<LineOptions
|
|
58
60
|
lineEnabled={lineEnabled}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
export const getAxesRangesFromChart = (chartRef) => {
|
|
1
|
+
export const getAxesRangesFromChart = (chartRef, axes) => {
|
|
2
2
|
const { scales = {} } = chartRef.current || {};
|
|
3
|
-
return Object.entries(scales).map(([key, { min, max }]) => {
|
|
3
|
+
return Object.entries(scales).map(([key, { min, max }], i) => {
|
|
4
|
+
const axesArray = axes.x.concat(axes.y);
|
|
5
|
+
const unit = axesArray?.[i]?.unit;
|
|
4
6
|
return {
|
|
5
7
|
id: key,
|
|
6
8
|
min,
|
|
7
9
|
max,
|
|
10
|
+
...(unit ? { unit } : {}),
|
|
8
11
|
};
|
|
9
12
|
});
|
|
10
13
|
};
|
|
@@ -16,6 +16,11 @@ export const LineChartPropTypes = {
|
|
|
16
16
|
label: PropTypes.string,
|
|
17
17
|
position: PropTypes.oneOf(['top', 'bottom']),
|
|
18
18
|
color: PropTypes.string,
|
|
19
|
+
unit: PropTypes.shape({
|
|
20
|
+
options: PropTypes.arrayOf(PropTypes.string),
|
|
21
|
+
selectedUnit: PropTypes.string,
|
|
22
|
+
setSelectedUnit: PropTypes.func,
|
|
23
|
+
}),
|
|
19
24
|
}),
|
|
20
25
|
),
|
|
21
26
|
y: PropTypes.arrayOf(
|
|
@@ -106,6 +111,11 @@ export const LineChartPropTypes = {
|
|
|
106
111
|
onPointUnhover: PropTypes.func,
|
|
107
112
|
onAnimationComplete: PropTypes.func,
|
|
108
113
|
}),
|
|
114
|
+
depthType: PropTypes.shape({
|
|
115
|
+
options: PropTypes.arrayOf(PropTypes.string),
|
|
116
|
+
selectedDepthType: PropTypes.string,
|
|
117
|
+
setSelectedDepthType: PropTypes.func,
|
|
118
|
+
}),
|
|
109
119
|
dragData: PropTypes.shape({
|
|
110
120
|
enableDragData: PropTypes.bool,
|
|
111
121
|
showTooltip: PropTypes.bool,
|
|
@@ -217,6 +227,7 @@ export const getDefaultProps = (props) => {
|
|
|
217
227
|
onAnimationComplete:
|
|
218
228
|
props.chart.options.interactions.onAnimationComplete,
|
|
219
229
|
},
|
|
230
|
+
depthType: props.chart.options.depthType,
|
|
220
231
|
dragData: {
|
|
221
232
|
enableDragData: props.chart.options.dragData.enableDragData || false,
|
|
222
233
|
showTooltip: props.chart.options.dragData.showTooltip || true,
|
|
@@ -46,10 +46,17 @@ export interface ILineChartAdditionalAxesOptions {
|
|
|
46
46
|
autoAxisPadding: boolean;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
export interface IUnitOptions {
|
|
50
|
+
options: string[],
|
|
51
|
+
selectedUnit: string,
|
|
52
|
+
setSelectedUnit: () => void,
|
|
53
|
+
}
|
|
54
|
+
|
|
49
55
|
export interface ILineChartAxis<PositionType> {
|
|
50
56
|
label: string;
|
|
51
57
|
position: PositionType;
|
|
52
58
|
color: string;
|
|
59
|
+
unit: IUnitOptions
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
export interface ILineChartAxes {
|
|
@@ -57,6 +64,11 @@ export interface ILineChartAxes {
|
|
|
57
64
|
y: ILineChartAxis<'left' | 'right'>[];
|
|
58
65
|
}
|
|
59
66
|
|
|
67
|
+
export interface IDepthType {
|
|
68
|
+
options: string[],
|
|
69
|
+
selectedUnit: string,
|
|
70
|
+
setSelectedUnit: () => void,
|
|
71
|
+
}
|
|
60
72
|
export interface ILineChartOptions {
|
|
61
73
|
title: string | string[];
|
|
62
74
|
axes: ILineChartAxes;
|
|
@@ -68,6 +80,7 @@ export interface ILineChartOptions {
|
|
|
68
80
|
legend: IChartLegend;
|
|
69
81
|
chartOptions: IChartOptions;
|
|
70
82
|
interactions: IChartInteractions;
|
|
83
|
+
depthType: IDepthType
|
|
71
84
|
draggableData :IChartDraggableData;
|
|
72
85
|
}
|
|
73
86
|
|
|
@@ -113,6 +113,7 @@ const LineChart = (props) => {
|
|
|
113
113
|
graph,
|
|
114
114
|
interactions,
|
|
115
115
|
legend,
|
|
116
|
+
depthType,
|
|
116
117
|
dragData,
|
|
117
118
|
} = options;
|
|
118
119
|
const { showLine, showPoints, enableZoom, enablePan } = chartOptions;
|
|
@@ -161,7 +162,7 @@ const LineChart = (props) => {
|
|
|
161
162
|
//save the initial axis ranges in state (we need this for resetting ranges)
|
|
162
163
|
dispatch({
|
|
163
164
|
type: SAVE_INITIAL_AXES_RANGES,
|
|
164
|
-
payload: { initialAxesRanges: getAxesRangesFromChart(chartRef) },
|
|
165
|
+
payload: { initialAxesRanges: getAxesRangesFromChart(chartRef, axes) },
|
|
165
166
|
});
|
|
166
167
|
}
|
|
167
168
|
}, []);
|
|
@@ -364,11 +365,15 @@ const LineChart = (props) => {
|
|
|
364
365
|
const axisType = i ? AxisType.Y : AxisType.X; // only first element is 'x' - rest is 'y'
|
|
365
366
|
const min = axis.min ?? additionalAxesOptions?.range?.[axisType]?.min;
|
|
366
367
|
const max = axis.max ?? additionalAxesOptions?.range?.[axisType]?.max;
|
|
368
|
+
// we need to get all axes element to array to set unit.
|
|
369
|
+
const axesArray = axes.x.concat(axes.y);
|
|
370
|
+
const unit = axesArray?.[i]?.unit;
|
|
367
371
|
return {
|
|
368
372
|
...axis,
|
|
369
373
|
//only add min and max properties if they are defined:
|
|
370
374
|
...(min ? { min } : {}),
|
|
371
375
|
...(max ? { max } : {}),
|
|
376
|
+
...(unit ? { unit } : {}),
|
|
372
377
|
};
|
|
373
378
|
});
|
|
374
379
|
};
|
|
@@ -455,6 +460,7 @@ const LineChart = (props) => {
|
|
|
455
460
|
subheaderComponent={subheaderComponent}
|
|
456
461
|
table={table}
|
|
457
462
|
zoomEnabled={state.zoomEnabled}
|
|
463
|
+
depthType={depthType}
|
|
458
464
|
enableDragPoints={state.enableDragPoints}
|
|
459
465
|
isDragDataAllowed={dragData.enableDragData}
|
|
460
466
|
onToggleDragPoints={() => dispatch({ type: TOGGLE_DRAG_POINTS })}
|
|
@@ -11,6 +11,9 @@ const initialState = ({
|
|
|
11
11
|
legendDisplay,
|
|
12
12
|
annotationsData,
|
|
13
13
|
customAxesRange,
|
|
14
|
+
selectedDepthTypes,
|
|
15
|
+
selectedUnits,
|
|
16
|
+
setSelectedDepthTypes,
|
|
14
17
|
}) => {
|
|
15
18
|
/**
|
|
16
19
|
* getStateAxesByType
|
|
@@ -28,23 +31,27 @@ const initialState = ({
|
|
|
28
31
|
const id = generateAxisId(axisType, index, axes[axisType].length > 1);
|
|
29
32
|
const customMin = customAxesRange?.[id]?.min;
|
|
30
33
|
const customMax = customAxesRange?.[id]?.max;
|
|
34
|
+
const { unit } = axisObj;
|
|
31
35
|
return {
|
|
32
36
|
id,
|
|
33
37
|
//only add custom axis ranges if defined:
|
|
34
38
|
...(customMin ? { min: customMin } : {}),
|
|
35
39
|
...(customMax ? { max: customMax } : {}),
|
|
40
|
+
...(unit ? { unit } : {}),
|
|
36
41
|
};
|
|
37
42
|
});
|
|
38
43
|
} else {
|
|
39
44
|
const id = generateAxisId(axisType);
|
|
40
45
|
const customMin = customAxesRange?.[id]?.min;
|
|
41
46
|
const customMax = customAxesRange?.[id]?.max;
|
|
47
|
+
const unit = axes?.[id][0].unit;
|
|
42
48
|
return [
|
|
43
49
|
{
|
|
44
50
|
id,
|
|
45
51
|
//only add custom axis ranges if defined:
|
|
46
52
|
...(customMin ? { min: customMin } : {}),
|
|
47
53
|
...(customMax ? { max: customMax } : {}),
|
|
54
|
+
...(unit ? { unit } : {}),
|
|
48
55
|
},
|
|
49
56
|
];
|
|
50
57
|
}
|
|
@@ -63,6 +70,9 @@ const initialState = ({
|
|
|
63
70
|
axes: stateAxes,
|
|
64
71
|
showAnnotationLineIndex: setAnnotations(annotationsData),
|
|
65
72
|
showTable: false,
|
|
73
|
+
selectedDepthTypes,
|
|
74
|
+
selectedUnits,
|
|
75
|
+
setSelectedDepthTypes,
|
|
66
76
|
enableDragPoints: false,
|
|
67
77
|
};
|
|
68
78
|
};
|