@oliasoft-open-source/charts-library 2.12.0 → 2.13.1
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 +1 -1
- package/release-notes.md +8 -0
- package/src/components/controls/controls.jsx +10 -10
- package/src/components/controls/drag-options.jsx +12 -47
- package/src/components/line-chart/line-chart-prop-types.js +2 -0
- package/src/components/line-chart/line-chart-utils.js +12 -0
- package/src/components/line-chart/line-chart.jsx +26 -48
- package/src/components/line-chart/state/action-types.js +0 -1
- package/src/components/line-chart/state/initial-state.js +33 -23
- package/src/components/line-chart/state/line-chart-reducer.js +0 -10
- package/src/components/line-chart/state/manage-state-in-local-storage.js +86 -0
- package/src/components/line-chart/state/use-chart-state.js +66 -0
package/package.json
CHANGED
package/release-notes.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Charts Library Release Notes
|
|
2
2
|
|
|
3
|
+
## 2.13.1
|
|
4
|
+
|
|
5
|
+
- Text label for drag options trigger, to make current behaviour more obvious ([OW-11102](https://oliasoft.atlassian.net/browse/OW-11102))
|
|
6
|
+
|
|
7
|
+
## 2.13.0
|
|
8
|
+
|
|
9
|
+
- Added feature to save state to localStorage and clean when expired, fixed panEnable(state) bug.
|
|
10
|
+
|
|
3
11
|
## 2.12.0
|
|
4
12
|
|
|
5
13
|
- Add unit selector and depth selector to axes options ([OW-9496](https://oliasoft.atlassian.net/browse/OW-9496))
|
|
@@ -66,16 +66,6 @@ const Controls = ({
|
|
|
66
66
|
legendEnabled={legendEnabled}
|
|
67
67
|
onToggleLegend={onToggleLegend}
|
|
68
68
|
/>
|
|
69
|
-
<DragOptions
|
|
70
|
-
panEnabled={panEnabled}
|
|
71
|
-
zoomEnabled={zoomEnabled}
|
|
72
|
-
onTogglePan={onTogglePan}
|
|
73
|
-
onToggleZoom={onToggleZoom}
|
|
74
|
-
enableDragPoints={enableDragPoints}
|
|
75
|
-
isDragDataAllowed={isDragDataAllowed}
|
|
76
|
-
onToggleDragPoints={onToggleDragPoints}
|
|
77
|
-
onDisableDragOptions={onDisableDragOptions}
|
|
78
|
-
/>
|
|
79
69
|
<Tooltip text="Download as PNG" placement="bottom-end">
|
|
80
70
|
<Button
|
|
81
71
|
small
|
|
@@ -86,6 +76,16 @@ const Controls = ({
|
|
|
86
76
|
onClick={onDownload}
|
|
87
77
|
/>
|
|
88
78
|
</Tooltip>
|
|
79
|
+
<DragOptions
|
|
80
|
+
panEnabled={panEnabled}
|
|
81
|
+
zoomEnabled={zoomEnabled}
|
|
82
|
+
onTogglePan={onTogglePan}
|
|
83
|
+
onToggleZoom={onToggleZoom}
|
|
84
|
+
enableDragPoints={enableDragPoints}
|
|
85
|
+
isDragDataAllowed={isDragDataAllowed}
|
|
86
|
+
onToggleDragPoints={onToggleDragPoints}
|
|
87
|
+
onDisableDragOptions={onDisableDragOptions}
|
|
88
|
+
/>
|
|
89
89
|
</>
|
|
90
90
|
)}
|
|
91
91
|
|
|
@@ -19,25 +19,10 @@ export const DragOptions = ({
|
|
|
19
19
|
onToggleDragPoints,
|
|
20
20
|
onDisableDragOptions,
|
|
21
21
|
}) => {
|
|
22
|
-
const handleToggleZoom = () => {
|
|
23
|
-
if (isDragDataAllowed) {
|
|
24
|
-
onToggleZoom();
|
|
25
|
-
} else {
|
|
26
|
-
onToggleZoom();
|
|
27
|
-
onTogglePan();
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const handleToggleDragPoints = () => {
|
|
32
|
-
if (isDragDataAllowed) {
|
|
33
|
-
onDisableDragOptions();
|
|
34
|
-
} else {
|
|
35
|
-
onToggleZoom();
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
22
|
// TODO: Translate strings
|
|
39
23
|
const options = [
|
|
40
24
|
{
|
|
25
|
+
buttonLabel: 'Drag to zoom',
|
|
41
26
|
label: (
|
|
42
27
|
<Flex direction="column">
|
|
43
28
|
<Text>Drag to zoom</Text>
|
|
@@ -51,9 +36,10 @@ export const DragOptions = ({
|
|
|
51
36
|
),
|
|
52
37
|
icon: <RiZoomInLine />,
|
|
53
38
|
selected: zoomEnabled,
|
|
54
|
-
onClick:
|
|
39
|
+
onClick: onToggleZoom,
|
|
55
40
|
},
|
|
56
41
|
{
|
|
42
|
+
buttonLabel: 'Drag to pan',
|
|
57
43
|
label: (
|
|
58
44
|
<Flex direction="column">
|
|
59
45
|
<Text>Drag to pan</Text>
|
|
@@ -84,7 +70,7 @@ export const DragOptions = ({
|
|
|
84
70
|
label: 'Drag disabled',
|
|
85
71
|
icon: <RiForbidLine />,
|
|
86
72
|
selected: !zoomEnabled && !panEnabled && !enableDragPoints,
|
|
87
|
-
onClick:
|
|
73
|
+
onClick: onDisableDragOptions,
|
|
88
74
|
},
|
|
89
75
|
];
|
|
90
76
|
|
|
@@ -100,34 +86,13 @@ export const DragOptions = ({
|
|
|
100
86
|
);
|
|
101
87
|
|
|
102
88
|
return (
|
|
103
|
-
<
|
|
104
|
-
{
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
onClick={selectedOption.onClick}
|
|
112
|
-
/>
|
|
113
|
-
) : (
|
|
114
|
-
<Menu
|
|
115
|
-
menu={{
|
|
116
|
-
component: (
|
|
117
|
-
<Button
|
|
118
|
-
small
|
|
119
|
-
basic
|
|
120
|
-
colored="muted"
|
|
121
|
-
round
|
|
122
|
-
icon={selectedOption.icon}
|
|
123
|
-
/>
|
|
124
|
-
),
|
|
125
|
-
label: 'Select',
|
|
126
|
-
sections: optionsWithDragPoints,
|
|
127
|
-
trigger: 'Component',
|
|
128
|
-
}}
|
|
129
|
-
/>
|
|
130
|
-
)}
|
|
131
|
-
</Tooltip>
|
|
89
|
+
<Menu
|
|
90
|
+
menu={{
|
|
91
|
+
label: selectedOption.buttonLabel || selectedOption.label,
|
|
92
|
+
sections: optionsWithDragPoints,
|
|
93
|
+
trigger: 'DropDownButton',
|
|
94
|
+
small: true,
|
|
95
|
+
}}
|
|
96
|
+
/>
|
|
132
97
|
);
|
|
133
98
|
};
|
|
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
|
|
3
3
|
export const LineChartPropTypes = {
|
|
4
4
|
table: PropTypes.node,
|
|
5
5
|
chart: PropTypes.shape({
|
|
6
|
+
persistenceId: PropTypes.string,
|
|
6
7
|
testId: PropTypes.string,
|
|
7
8
|
data: PropTypes.object.isRequired,
|
|
8
9
|
options: PropTypes.shape({
|
|
@@ -148,6 +149,7 @@ export const getDefaultProps = (props) => {
|
|
|
148
149
|
props.chart.options.dragData = props.chart.options.dragData || {};
|
|
149
150
|
// Set defaults for missing properties
|
|
150
151
|
const chart = {
|
|
152
|
+
persistenceId: props.chart.persistenceId ?? '',
|
|
151
153
|
testId: props.chart.testId ?? null,
|
|
152
154
|
data: props.chart.data,
|
|
153
155
|
options: {
|
|
@@ -56,3 +56,15 @@ export const generateAxisId = (axisType, index = 0, hasMultiAxes = false) => {
|
|
|
56
56
|
export const getAxisTypeFromKey = (string) => {
|
|
57
57
|
return string.match(/[^0-9/]+/gi)[0];
|
|
58
58
|
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Generates a key based on an array of values. The key changes
|
|
62
|
+
* if any of the values in the array change.
|
|
63
|
+
*
|
|
64
|
+
* @param {Array} values - The array of values to base the key on.
|
|
65
|
+
* @returns {String} The key.
|
|
66
|
+
*/
|
|
67
|
+
export const generateKey = (values) => {
|
|
68
|
+
const key = values.join('');
|
|
69
|
+
return key;
|
|
70
|
+
};
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
useEffect,
|
|
3
|
+
useLayoutEffect,
|
|
4
|
+
useReducer,
|
|
5
|
+
useRef,
|
|
6
|
+
useState,
|
|
7
|
+
} from 'react';
|
|
2
8
|
import {
|
|
3
9
|
CategoryScale,
|
|
4
10
|
Chart as ChartJS,
|
|
@@ -21,19 +27,18 @@ import styles from './line-chart.module.less';
|
|
|
21
27
|
import { reducer } from './state/line-chart-reducer';
|
|
22
28
|
import initialState from './state/initial-state';
|
|
23
29
|
import {
|
|
24
|
-
|
|
30
|
+
DISABLE_DRAG_OPTIONS,
|
|
31
|
+
RESET_AXES_RANGES,
|
|
32
|
+
SAVE_INITIAL_AXES_RANGES,
|
|
25
33
|
TOGGLE_ANNOTATION,
|
|
34
|
+
TOGGLE_DRAG_POINTS,
|
|
26
35
|
TOGGLE_LEGEND,
|
|
27
36
|
TOGGLE_LINE,
|
|
28
37
|
TOGGLE_PAN,
|
|
29
38
|
TOGGLE_POINTS,
|
|
30
39
|
TOGGLE_TABLE,
|
|
31
40
|
TOGGLE_ZOOM,
|
|
32
|
-
SAVE_INITIAL_AXES_RANGES,
|
|
33
41
|
UPDATE_AXES_RANGES,
|
|
34
|
-
RESET_AXES_RANGES,
|
|
35
|
-
TOGGLE_DRAG_POINTS,
|
|
36
|
-
DISABLE_DRAG_OPTIONS,
|
|
37
42
|
} from './state/action-types';
|
|
38
43
|
import Controls from '../controls/controls';
|
|
39
44
|
import { getDefaultProps, LineChartPropTypes } from './line-chart-prop-types';
|
|
@@ -61,9 +66,9 @@ import {
|
|
|
61
66
|
import {
|
|
62
67
|
ANIMATION_DURATION,
|
|
63
68
|
AUTO,
|
|
69
|
+
BORDER_COLOR,
|
|
64
70
|
COLORS,
|
|
65
71
|
CUSTOM_LEGEND_PLUGIN_NAME,
|
|
66
|
-
BORDER_COLOR,
|
|
67
72
|
} from '../../helpers/chart-consts';
|
|
68
73
|
import {
|
|
69
74
|
AxisType,
|
|
@@ -73,9 +78,10 @@ import {
|
|
|
73
78
|
PointStyle,
|
|
74
79
|
} from '../../helpers/enums';
|
|
75
80
|
import getDraggableData from '../../helpers/get-draggableData';
|
|
76
|
-
import {
|
|
77
|
-
import { generateAxisId } from './line-chart-utils';
|
|
81
|
+
import { generateAxisId, generateKey } from './line-chart-utils';
|
|
78
82
|
import { autoScale } from './axis-scales/axis-scales';
|
|
83
|
+
import useChartState from './state/use-chart-state';
|
|
84
|
+
import { getAxesRangesFromChart } from './get-axes-ranges-from-chart';
|
|
79
85
|
|
|
80
86
|
ChartJS.register(
|
|
81
87
|
LinearScale,
|
|
@@ -102,13 +108,12 @@ const LineChart = (props) => {
|
|
|
102
108
|
const chartRef = useRef(null);
|
|
103
109
|
const [hoveredPoint, setHoveredPoint] = useState(null);
|
|
104
110
|
const chart = getDefaultProps(props);
|
|
105
|
-
const { options, testId } = chart;
|
|
111
|
+
const { options, testId, persistenceId } = chart;
|
|
106
112
|
const { headerComponent, subheaderComponent, table } = props;
|
|
107
113
|
const {
|
|
108
114
|
additionalAxesOptions,
|
|
109
115
|
annotations,
|
|
110
116
|
axes,
|
|
111
|
-
chartOptions,
|
|
112
117
|
chartStyling,
|
|
113
118
|
graph,
|
|
114
119
|
interactions,
|
|
@@ -116,7 +121,6 @@ const LineChart = (props) => {
|
|
|
116
121
|
depthType,
|
|
117
122
|
dragData,
|
|
118
123
|
} = options;
|
|
119
|
-
const { showLine, showPoints, enableZoom, enablePan } = chartOptions;
|
|
120
124
|
|
|
121
125
|
/**
|
|
122
126
|
* @type {[object, import('react').Dispatch<{type: String, payload: any}>]} useReducer
|
|
@@ -124,19 +128,13 @@ const LineChart = (props) => {
|
|
|
124
128
|
const [state, dispatch] = useReducer(
|
|
125
129
|
reducer,
|
|
126
130
|
{
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
enablePan: chartOptions.enablePan,
|
|
130
|
-
showPoints: chartOptions.showPoints,
|
|
131
|
-
showLine: chartOptions.showLine,
|
|
132
|
-
legendDisplay: legend.display,
|
|
133
|
-
annotationsData: annotations.annotationsData,
|
|
134
|
-
customAxesRange: additionalAxesOptions?.range,
|
|
131
|
+
options,
|
|
132
|
+
persistenceId,
|
|
135
133
|
},
|
|
136
134
|
initialState,
|
|
137
135
|
);
|
|
138
136
|
|
|
139
|
-
|
|
137
|
+
useLayoutEffect(() => {
|
|
140
138
|
const { range } = props.chart.options.additionalAxesOptions;
|
|
141
139
|
if (range?.x && range?.y) {
|
|
142
140
|
const axes = Object.entries(range).map(([key, { min, max }]) => {
|
|
@@ -155,9 +153,6 @@ const LineChart = (props) => {
|
|
|
155
153
|
}, [props.chart.options]);
|
|
156
154
|
|
|
157
155
|
useEffect(() => {
|
|
158
|
-
if (chartOptions.enablePan !== true) {
|
|
159
|
-
dispatch({ type: TOGGLE_PAN });
|
|
160
|
-
}
|
|
161
156
|
if (chartRef) {
|
|
162
157
|
//save the initial axis ranges in state (we need this for resetting ranges)
|
|
163
158
|
dispatch({
|
|
@@ -167,29 +162,8 @@ const LineChart = (props) => {
|
|
|
167
162
|
}
|
|
168
163
|
}, []);
|
|
169
164
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
type: SET_POINTS_ZOOM_DEFAULTS,
|
|
173
|
-
payload: { showLine, showPoints, enableZoom, enablePan },
|
|
174
|
-
});
|
|
175
|
-
}, [showLine, showPoints, enableZoom, enablePan]);
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Toggle custom legends visibility.
|
|
179
|
-
* Needed because they are rendered in a html element separate from the chart.
|
|
180
|
-
*/
|
|
181
|
-
useEffect(() => {
|
|
182
|
-
if (options.legend.customLegend.customLegendPlugin) {
|
|
183
|
-
const parent = document.getElementById(
|
|
184
|
-
options.legend.customLegend.customLegendContainerID,
|
|
185
|
-
);
|
|
186
|
-
if (state.legendEnabled) {
|
|
187
|
-
parent.style.visibility = 'visible';
|
|
188
|
-
} else {
|
|
189
|
-
parent.style.visibility = 'hidden';
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}, [state.legendEnabled]);
|
|
165
|
+
// Call the custom hook.
|
|
166
|
+
useChartState(options, state, persistenceId);
|
|
193
167
|
|
|
194
168
|
const generateLineChartDatasets = (datasets) => {
|
|
195
169
|
const copyDataset = [...datasets];
|
|
@@ -471,7 +445,11 @@ const LineChart = (props) => {
|
|
|
471
445
|
) : (
|
|
472
446
|
<div className={styles.canvas}>
|
|
473
447
|
<Line
|
|
474
|
-
key={
|
|
448
|
+
key={generateKey([
|
|
449
|
+
state.enableDragPoints,
|
|
450
|
+
state.zoomEnabled,
|
|
451
|
+
state.panEnabled,
|
|
452
|
+
])}
|
|
475
453
|
ref={chartRef}
|
|
476
454
|
data={{
|
|
477
455
|
datasets: generatedDatasets,
|
|
@@ -3,7 +3,6 @@ export const TOGGLE_PAN = 'TOGGLE_PAN';
|
|
|
3
3
|
export const TOGGLE_POINTS = 'TOGGLE_POINTS';
|
|
4
4
|
export const TOGGLE_LINE = 'TOGGLE_LINE';
|
|
5
5
|
export const TOGGLE_LEGEND = 'TOGGLE_LEGEND';
|
|
6
|
-
export const SET_POINTS_ZOOM_DEFAULTS = 'SET_POINTS_ZOOM_DEFAULTS';
|
|
7
6
|
export const TOGGLE_ANNOTATION = 'TOGGLE_ANNOTATION';
|
|
8
7
|
export const TOGGLE_TABLE = 'TOGGLE_TABLE';
|
|
9
8
|
export const SAVE_INITIAL_AXES_RANGES = 'SAVE_INITIAL_AXES_RANGES';
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import { AxisType } from '../../../helpers/enums';
|
|
2
2
|
import { setAnnotations } from '../../../helpers/chart-utils';
|
|
3
3
|
import { generateAxisId } from '../line-chart-utils';
|
|
4
|
+
import { getChartStateFromStorage } from './manage-state-in-local-storage';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
6
|
+
/**
|
|
7
|
+
|
|
8
|
+
Initial chart state for the line chart.
|
|
9
|
+
@param {Object} options - The chart options.
|
|
10
|
+
@return {Object} The initial chart state.
|
|
11
|
+
*/
|
|
12
|
+
const initialState = ({ options, persistenceId }) => {
|
|
13
|
+
const {
|
|
14
|
+
additionalAxesOptions: { range: customAxesRange },
|
|
15
|
+
annotations,
|
|
16
|
+
axes,
|
|
17
|
+
chartOptions,
|
|
18
|
+
legend,
|
|
19
|
+
dragData,
|
|
20
|
+
} = options;
|
|
21
|
+
const { enableZoom, enablePan, showPoints, showLine } = chartOptions;
|
|
18
22
|
/**
|
|
19
23
|
* getStateAxesByType
|
|
20
24
|
* @param {'x'|'y'} axisType
|
|
@@ -61,19 +65,25 @@ const initialState = ({
|
|
|
61
65
|
const yStateAxes = getStateAxesByType(AxisType.Y, customAxesRange);
|
|
62
66
|
const stateAxes = [...xStateAxes, ...yStateAxes];
|
|
63
67
|
|
|
68
|
+
const {
|
|
69
|
+
zoomEnabled,
|
|
70
|
+
panEnabled,
|
|
71
|
+
pointsEnabled,
|
|
72
|
+
lineEnabled,
|
|
73
|
+
legendEnabled,
|
|
74
|
+
enableDragPoints,
|
|
75
|
+
} = getChartStateFromStorage(persistenceId) || {};
|
|
76
|
+
|
|
64
77
|
return {
|
|
65
|
-
zoomEnabled: enableZoom,
|
|
66
|
-
panEnabled:
|
|
67
|
-
pointsEnabled: showPoints,
|
|
68
|
-
lineEnabled: showLine,
|
|
69
|
-
legendEnabled:
|
|
78
|
+
zoomEnabled: zoomEnabled ?? enableZoom,
|
|
79
|
+
panEnabled: panEnabled ?? enablePan,
|
|
80
|
+
pointsEnabled: pointsEnabled ?? showPoints,
|
|
81
|
+
lineEnabled: lineEnabled ?? showLine,
|
|
82
|
+
legendEnabled: legendEnabled !== false ?? legend.display !== false,
|
|
70
83
|
axes: stateAxes,
|
|
71
|
-
showAnnotationLineIndex: setAnnotations(annotationsData),
|
|
84
|
+
showAnnotationLineIndex: setAnnotations(annotations.annotationsData),
|
|
72
85
|
showTable: false,
|
|
73
|
-
|
|
74
|
-
selectedUnits,
|
|
75
|
-
setSelectedDepthTypes,
|
|
76
|
-
enableDragPoints: false,
|
|
86
|
+
enableDragPoints: dragData.enableDragData && enableDragPoints,
|
|
77
87
|
};
|
|
78
88
|
};
|
|
79
89
|
|
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
DISABLE_DRAG_OPTIONS,
|
|
4
4
|
RESET_AXES_RANGES,
|
|
5
5
|
SAVE_INITIAL_AXES_RANGES,
|
|
6
|
-
SET_POINTS_ZOOM_DEFAULTS,
|
|
7
6
|
TOGGLE_ANNOTATION,
|
|
8
7
|
TOGGLE_DRAG_POINTS,
|
|
9
8
|
TOGGLE_LEGEND,
|
|
@@ -79,15 +78,6 @@ export const reducer = (state, action) => {
|
|
|
79
78
|
}));
|
|
80
79
|
});
|
|
81
80
|
}
|
|
82
|
-
case SET_POINTS_ZOOM_DEFAULTS:
|
|
83
|
-
const { showPoints, enableZoom, enablePan, showLine } = action.payload;
|
|
84
|
-
return {
|
|
85
|
-
...newState,
|
|
86
|
-
zoomEnabled: enableZoom,
|
|
87
|
-
pointsEnabled: showPoints,
|
|
88
|
-
lineEnabled: showLine,
|
|
89
|
-
panEnabled: enablePan,
|
|
90
|
-
};
|
|
91
81
|
case TOGGLE_ANNOTATION:
|
|
92
82
|
const { annotationIndex } = action.payload;
|
|
93
83
|
const updatedIndexes = newState.showAnnotationLineIndex.includes(
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retrieves the chart state from local storage.
|
|
3
|
+
*
|
|
4
|
+
* @param {string|''} persistenceId - The chart persistenceId.
|
|
5
|
+
* @returns {object|null} The chart state object or null if not found.
|
|
6
|
+
*/
|
|
7
|
+
export const getChartStateFromStorage = (persistenceId) => {
|
|
8
|
+
if (!persistenceId) return null;
|
|
9
|
+
|
|
10
|
+
// Retrieve the chart state object from local storage
|
|
11
|
+
const chartStateKey = `line-chart-state-${persistenceId}`;
|
|
12
|
+
const chartStateObjectJSON = localStorage.getItem(chartStateKey);
|
|
13
|
+
|
|
14
|
+
if (chartStateObjectJSON) {
|
|
15
|
+
// If the chart state object was found, parse it
|
|
16
|
+
const chartStateObject = JSON.parse(chartStateObjectJSON);
|
|
17
|
+
|
|
18
|
+
// Return the state property of the parsed chart state object
|
|
19
|
+
return chartStateObject.state;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// If the chart state object was not found, return null
|
|
23
|
+
return null;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Remove expired chart states from local storage.
|
|
28
|
+
*
|
|
29
|
+
* @param {number} maxAgeInHours - The maximum age of chart states to keep in local storage (in hours). Default is 72 hours.
|
|
30
|
+
*/
|
|
31
|
+
const removeExpiredChartStates = (maxAgeInHours = 72) => {
|
|
32
|
+
const currentTime = new Date().getTime();
|
|
33
|
+
const maxAgeInMilliseconds = maxAgeInHours * 60 * 60 * 1000;
|
|
34
|
+
|
|
35
|
+
// Iterate through all keys in local storage
|
|
36
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
37
|
+
const key = localStorage.key(i);
|
|
38
|
+
|
|
39
|
+
// Check if the key is related to a line-chart-state
|
|
40
|
+
if (key.includes('line-chart-state-')) {
|
|
41
|
+
const chartStateObjectJSON = localStorage.getItem(key);
|
|
42
|
+
|
|
43
|
+
// If a valid chart state object JSON is found
|
|
44
|
+
if (chartStateObjectJSON) {
|
|
45
|
+
const chartStateObject = JSON.parse(chartStateObjectJSON);
|
|
46
|
+
const storedTime = chartStateObject.timestamp;
|
|
47
|
+
|
|
48
|
+
// If a valid timestamp is found
|
|
49
|
+
if (storedTime) {
|
|
50
|
+
const ageInMilliseconds = currentTime - storedTime;
|
|
51
|
+
|
|
52
|
+
// If the age of the chart state is older than the specified maxAgeInHours
|
|
53
|
+
if (ageInMilliseconds > maxAgeInMilliseconds) {
|
|
54
|
+
// Remove the expired chart state from local storage
|
|
55
|
+
localStorage.removeItem(key);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Stores the chart state in local storage.
|
|
65
|
+
*
|
|
66
|
+
* @param {object} state - The chart state object to store.
|
|
67
|
+
* @param {string|''} persistenceId - The chart persistenceId.
|
|
68
|
+
*/
|
|
69
|
+
export const storeChartStateInStorage = (state, persistenceId) => {
|
|
70
|
+
if (!persistenceId) return;
|
|
71
|
+
|
|
72
|
+
const currentTime = new Date().getTime();
|
|
73
|
+
const chartStateKey = `line-chart-state-${persistenceId}`;
|
|
74
|
+
|
|
75
|
+
// Create an object containing the chart state and the timestamp
|
|
76
|
+
const chartStateObject = {
|
|
77
|
+
state,
|
|
78
|
+
timestamp: currentTime,
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// Serialize the chart state object as a JSON string and store it in local storage
|
|
82
|
+
localStorage.setItem(chartStateKey, JSON.stringify(chartStateObject));
|
|
83
|
+
|
|
84
|
+
// Remove expired chart states from local storage
|
|
85
|
+
removeExpiredChartStates();
|
|
86
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { useEffect, useMemo } from 'react';
|
|
2
|
+
import { storeChartStateInStorage } from './manage-state-in-local-storage';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook for toggling the visibility of the custom legend.
|
|
6
|
+
*
|
|
7
|
+
* @param memoState - The memoized state object.
|
|
8
|
+
* @param memoOptions - The memoized options object.
|
|
9
|
+
*/
|
|
10
|
+
const useToggleCustomLegendVisibility = (memoState, memoOptions) => {
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (memoOptions.legend.customLegend.customLegendPlugin) {
|
|
13
|
+
// Get the parent element of the custom legend container and toggle its visibility based on the state.
|
|
14
|
+
const parent = document.getElementById(
|
|
15
|
+
memoOptions.legend.customLegend.customLegendContainerID,
|
|
16
|
+
);
|
|
17
|
+
parent.style.visibility = memoState.legendEnabled ? 'visible' : 'hidden';
|
|
18
|
+
}
|
|
19
|
+
}, [
|
|
20
|
+
memoOptions.legend.customLegend.customLegendPlugin,
|
|
21
|
+
memoState.legendEnabled,
|
|
22
|
+
]);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Hook for storing the chart state in local storage.
|
|
27
|
+
*
|
|
28
|
+
* @param memoState - The memoized state object.
|
|
29
|
+
* @param persistenceId - The chart persistenceId.
|
|
30
|
+
*/
|
|
31
|
+
const useStoreChartStateInStorage = (memoState, persistenceId) => {
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
// Store the chart state in local storage.
|
|
34
|
+
storeChartStateInStorage(memoState, persistenceId);
|
|
35
|
+
}, [
|
|
36
|
+
memoState.panEnabled,
|
|
37
|
+
memoState.lineEnabled,
|
|
38
|
+
memoState.pointsEnabled,
|
|
39
|
+
memoState.legendEnabled,
|
|
40
|
+
memoState.enableDragPoints,
|
|
41
|
+
memoState.zoomEnabled,
|
|
42
|
+
]);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Hook for managing the state of the chart.
|
|
47
|
+
*
|
|
48
|
+
* @param options - The chart options.
|
|
49
|
+
* @param state - The chart state.
|
|
50
|
+
* @param persistenceId - The chart persistenceId.
|
|
51
|
+
*/
|
|
52
|
+
const useChartState = (options, state, persistenceId) => {
|
|
53
|
+
const memoized = useMemo(() => {
|
|
54
|
+
return {
|
|
55
|
+
state,
|
|
56
|
+
options,
|
|
57
|
+
};
|
|
58
|
+
}, [state, options]);
|
|
59
|
+
|
|
60
|
+
const { state: memoState, options: memoOptions } = memoized ?? {};
|
|
61
|
+
|
|
62
|
+
useStoreChartStateInStorage(memoState, persistenceId);
|
|
63
|
+
useToggleCustomLegendVisibility(memoState, memoOptions);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export default useChartState;
|