@centreon/ui 23.10.1-MON-21149-implement-time-periods-thresholds-refresh-interval.13 → 23.10.1-MON-20798-fe-implement-buttons.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centreon/ui",
3
- "version": "23.10.1-MON-21149-implement-time-periods-thresholds-refresh-interval.13",
3
+ "version": "23.10.1-MON-20798-fe-implement-buttons.0",
4
4
  "description": "Centreon UI Components",
5
5
  "scripts": {
6
6
  "eslint": "eslint ./src --ext .js,.jsx,.ts,.tsx --max-warnings 0",
@@ -1,7 +1,9 @@
1
- import { Dispatch, SetStateAction, useEffect } from 'react';
1
+ import { useEffect } from 'react';
2
2
 
3
+ import { useAtom } from 'jotai';
3
4
  import { compose, equals, prop, propEq, reject, sortBy, toLower } from 'ramda';
4
5
 
6
+ import { linesGraphAtom } from '../graphAtoms';
5
7
  import { Line } from '../../common/timeSeries/models';
6
8
 
7
9
  import {
@@ -13,8 +15,6 @@ import {
13
15
  interface UseFilterLines {
14
16
  displayThreshold?: boolean;
15
17
  lines: Array<Line>;
16
- linesGraph: Array<Line> | null;
17
- setLinesGraph: Dispatch<SetStateAction<Array<Line> | null>>;
18
18
  }
19
19
 
20
20
  interface Result {
@@ -24,10 +24,10 @@ interface Result {
24
24
 
25
25
  const useFilterLines = ({
26
26
  displayThreshold = false,
27
- lines,
28
- linesGraph,
29
- setLinesGraph
27
+ lines
30
28
  }: UseFilterLines): Result => {
29
+ const [linesGraph, setLinesGraph] = useAtom(linesGraphAtom);
30
+
31
31
  const displayedLines = reject(propEq('display', false), linesGraph ?? lines);
32
32
  const filterLines = (): Array<Line> => {
33
33
  const lineOriginMetric = findLineOfOriginMetricThreshold(lines);
@@ -45,9 +45,7 @@ const useFilterLines = ({
45
45
 
46
46
  useEffect(() => {
47
47
  const filteredLines = filterLines();
48
- if (!lines || !displayThreshold) {
49
- setLinesGraph(lines);
50
-
48
+ if (!lines || !displayThreshold || filteredLines.length <= 0) {
51
49
  return;
52
50
  }
53
51
 
@@ -8,12 +8,14 @@ interface Props {
8
8
 
9
9
  const Point = ({ lineColor, x, y }: Props): JSX.Element => (
10
10
  <circle
11
- cx={x}
12
- cy={y}
13
11
  fill={alpha(lineColor, 0.5)}
14
12
  r={4}
15
13
  stroke={lineColor}
16
14
  strokeWidth={2}
15
+ style={{
16
+ transform: `translate(${x}px, ${y}px)`,
17
+ transition: 'transform 0.08s ease-out'
18
+ }}
17
19
  />
18
20
  );
19
21
 
@@ -44,7 +44,6 @@ export const changeMousePositionAndTimeValueDerivedAtom = atom(
44
44
 
45
45
  return;
46
46
  }
47
-
48
47
  set(mousePositionAtom, position);
49
48
 
50
49
  set(timeValueAtom, timeValue);
@@ -1,4 +1,4 @@
1
- import { Dispatch, ReactNode, SetStateAction } from 'react';
1
+ import { ReactNode } from 'react';
2
2
 
3
3
  import { slice } from 'ramda';
4
4
  import { useAtomValue } from 'jotai';
@@ -28,10 +28,8 @@ interface Props {
28
28
  limitLegendRows?: boolean;
29
29
  lines: Array<Line>;
30
30
  renderExtraComponent?: ReactNode;
31
- setLinesGraph: Dispatch<SetStateAction<Array<Line> | null>>;
32
31
  timeSeries: Array<TimeValue>;
33
32
  toggable?: boolean;
34
- xScale;
35
33
  }
36
34
 
37
35
  const MainLegend = ({
@@ -41,21 +39,18 @@ const MainLegend = ({
41
39
  toggable = true,
42
40
  limitLegendRows = true,
43
41
  renderExtraComponent,
44
- displayAnchor = true,
45
- setLinesGraph,
46
- xScale
42
+ displayAnchor = true
47
43
  }: Props): JSX.Element => {
48
44
  const { classes, cx } = useStyles({ limitLegendRows });
49
45
  const theme = useTheme();
50
46
 
51
47
  const { selectMetricLine, clearHighlight, highlightLine, toggleMetricLine } =
52
- useLegend({ lines, setLinesGraph });
48
+ useLegend({ lines });
53
49
 
54
50
  const { getFormattedValue } = useInteractiveValues({
55
51
  base,
56
52
  lines,
57
- timeSeries,
58
- xScale
53
+ timeSeries
59
54
  });
60
55
 
61
56
  const displayedLines = limitLegendRows
@@ -3,12 +3,11 @@ import { useMemo } from 'react';
3
3
  import { useAtomValue } from 'jotai';
4
4
  import { equals, find, isNil } from 'ramda';
5
5
 
6
- import { mousePositionAtom } from '../InteractiveComponents/interactionWithGraphAtoms';
6
+ import { timeValueAtom } from '../InteractiveComponents/interactionWithGraphAtoms';
7
7
  import {
8
8
  formatMetricValue,
9
9
  getLineForMetric,
10
- getMetrics,
11
- getTimeValue
10
+ getMetrics
12
11
  } from '../../common/timeSeries';
13
12
  import { Line, TimeValue } from '../../common/timeSeries/models';
14
13
 
@@ -22,22 +21,14 @@ interface Props {
22
21
  base: number;
23
22
  lines: Array<Line>;
24
23
  timeSeries: Array<TimeValue>;
25
- xScale;
26
24
  }
27
25
 
28
26
  const useInteractiveValues = ({
29
27
  timeSeries,
30
28
  lines,
31
- base,
32
- xScale
29
+ base
33
30
  }: Props): InteractiveValues => {
34
- const mousePosition = useAtomValue(mousePositionAtom);
35
-
36
- const timeValue = getTimeValue({
37
- timeSeries,
38
- x: mousePosition?.[0],
39
- xScale
40
- });
31
+ const timeValue = useAtomValue(timeValueAtom);
41
32
 
42
33
  const graphTimeValue = timeSeries?.find((item) =>
43
34
  equals(item.timeTick, timeValue?.timeTick)
@@ -1,5 +1,6 @@
1
- import { Dispatch, SetStateAction, useEffect } from 'react';
1
+ import { useEffect } from 'react';
2
2
 
3
+ import { useSetAtom } from 'jotai';
3
4
  import {
4
5
  equals,
5
6
  find,
@@ -16,6 +17,7 @@ import {
16
17
  toLower
17
18
  } from 'ramda';
18
19
 
20
+ import { linesGraphAtom } from '../graphAtoms';
19
21
  import { Line } from '../../common/timeSeries/models';
20
22
 
21
23
  interface LegendActions {
@@ -27,10 +29,11 @@ interface LegendActions {
27
29
 
28
30
  interface Props {
29
31
  lines: Array<Line>;
30
- setLinesGraph: Dispatch<SetStateAction<Array<Line> | null>>;
31
32
  }
32
33
 
33
- const useLegend = ({ lines, setLinesGraph }: Props): LegendActions => {
34
+ const useLegend = ({ lines }: Props): LegendActions => {
35
+ const setLines = useSetAtom(linesGraphAtom);
36
+
34
37
  const displayedLines = reject(propEq('display', false), lines);
35
38
  const getLineByMetric = (metric: string): Line =>
36
39
  find(propEq('metric', metric), lines) as Line;
@@ -38,7 +41,7 @@ const useLegend = ({ lines, setLinesGraph }: Props): LegendActions => {
38
41
  const toggleMetricLine = (metric): void => {
39
42
  const line = getLineByMetric(metric);
40
43
 
41
- setLinesGraph([
44
+ setLines([
42
45
  ...reject(propEq('metric', metric), lines),
43
46
  { ...line, display: !line.display }
44
47
  ]);
@@ -53,11 +56,11 @@ const useLegend = ({ lines, setLinesGraph }: Props): LegendActions => {
53
56
 
54
57
  const sortedData = sortBy(compose(toLower, prop('name')), data);
55
58
 
56
- setLinesGraph(sortedData);
59
+ setLines(sortedData);
57
60
  };
58
61
 
59
62
  const clearHighlight = (): void => {
60
- setLinesGraph(map((line) => ({ ...line, highlight: undefined }), lines));
63
+ setLines(map((line) => ({ ...line, highlight: undefined }), lines));
61
64
  };
62
65
 
63
66
  const selectMetricLine = (metric: string): void => {
@@ -68,7 +71,7 @@ const useLegend = ({ lines, setLinesGraph }: Props): LegendActions => {
68
71
  equals(displayedLines.length, 1) && isLineDisplayed;
69
72
 
70
73
  if (isOnlyLineDisplayed || isEmpty(displayedLines)) {
71
- setLinesGraph(
74
+ setLines(
72
75
  map(
73
76
  (line) => ({
74
77
  ...line,
@@ -81,7 +84,7 @@ const useLegend = ({ lines, setLinesGraph }: Props): LegendActions => {
81
84
  return;
82
85
  }
83
86
 
84
- setLinesGraph(
87
+ setLines(
85
88
  map(
86
89
  (line) => ({
87
90
  ...line,
@@ -102,8 +105,8 @@ const useLegend = ({ lines, setLinesGraph }: Props): LegendActions => {
102
105
  display: find(propEq('name', line.name), lines)?.display ?? true
103
106
  }));
104
107
 
105
- setLinesGraph(newLines);
106
- }, [lines]);
108
+ setLines(newLines);
109
+ }, []);
107
110
 
108
111
  return { clearHighlight, highlightLine, selectMetricLine, toggleMetricLine };
109
112
  };
@@ -1,12 +1,11 @@
1
- import { MutableRefObject, useMemo, useRef, useState } from 'react';
1
+ import { MutableRefObject, useMemo, useRef } from 'react';
2
2
 
3
- import { Group, Tooltip } from '@visx/visx';
3
+ import { Group } from '@visx/visx';
4
4
  import { isNil } from 'ramda';
5
5
 
6
- import { ClickAwayListener, Fade, Skeleton, useTheme } from '@mui/material';
6
+ import { ClickAwayListener, Skeleton } from '@mui/material';
7
7
 
8
8
  import { getLeftScale, getRightScale, getXScale } from '../common/timeSeries';
9
- import { Line } from '../common/timeSeries/models';
10
9
 
11
10
  import Axes from './BasicComponents/Axes';
12
11
  import Grids from './BasicComponents/Grids';
@@ -31,27 +30,17 @@ import {
31
30
  } from './models';
32
31
  import { useIntersection } from './useLineChartIntersection';
33
32
  import { CurveType } from './BasicComponents/Lines/models';
34
- import Thresholds from './BasicComponents/Thresholds';
35
33
 
36
34
  interface Props extends LineChartProps {
37
35
  curve: CurveType;
38
- disabledThresholds?: boolean;
39
36
  graphData: Data;
40
37
  graphInterval: GraphInterval;
41
38
  graphRef: MutableRefObject<HTMLDivElement | null>;
42
39
  legend?: LegendModel;
43
40
  marginBottom: number;
44
41
  shapeLines?: GlobalAreaLines;
45
- thresholdLabels?: Array<string>;
46
- thresholdUnit?: string;
47
- thresholds?: Array<number>;
48
42
  }
49
43
 
50
- const baseStyles = {
51
- ...Tooltip.defaultStyles,
52
- textAlign: 'center'
53
- };
54
-
55
44
  const LineChart = ({
56
45
  graphData,
57
46
  height = 500,
@@ -69,32 +58,15 @@ const LineChart = ({
69
58
  graphRef,
70
59
  header,
71
60
  curve,
72
- marginBottom,
73
- thresholds,
74
- thresholdUnit,
75
- thresholdLabels,
76
- disabledThresholds
61
+ marginBottom
77
62
  }: Props): JSX.Element => {
78
- const { classes } = useStyles();
79
-
80
- const theme = useTheme();
81
-
82
- const [linesGraph, setLinesGraph] = useState<Array<Line> | null>(null);
83
63
  const graphSvgRef = useRef<SVGSVGElement | null>(null);
84
64
 
65
+ const { classes } = useStyles();
85
66
  const { isInViewport } = useIntersection({ element: graphRef?.current });
86
67
 
87
68
  const legendRef = useRef<HTMLDivElement | null>(null);
88
69
 
89
- const {
90
- tooltipOpen: thresholdTooltipOpen,
91
- tooltipLeft: thresholdTooltipLeft,
92
- tooltipTop: thresholdTooltipTop,
93
- tooltipData: thresholdTooltipData,
94
- hideTooltip: hideThresholdTooltip,
95
- showTooltip: showThresholdTooltip
96
- } = Tooltip.useTooltip();
97
-
98
70
  const graphWidth = width > 0 ? width - margin.left - margin.right : 0;
99
71
  const graphHeight =
100
72
  (height || 0) > 0
@@ -109,9 +81,7 @@ const LineChart = ({
109
81
 
110
82
  const { displayedLines, newLines } = useFilterLines({
111
83
  displayThreshold: canDisplayThreshold(shapeLines?.areaThresholdLines),
112
- lines,
113
- linesGraph,
114
- setLinesGraph
84
+ lines
115
85
  });
116
86
 
117
87
  const xScale = useMemo(
@@ -128,8 +98,6 @@ const LineChart = ({
128
98
  getLeftScale({
129
99
  dataLines: displayedLines,
130
100
  dataTimeSeries: timeSeries,
131
- thresholdUnit,
132
- thresholds: (!disabledThresholds && thresholds) || [],
133
101
  valueGraphHeight: graphHeight - 35
134
102
  }),
135
103
  [displayedLines, timeSeries, graphHeight]
@@ -140,8 +108,6 @@ const LineChart = ({
140
108
  getRightScale({
141
109
  dataLines: displayedLines,
142
110
  dataTimeSeries: timeSeries,
143
- thresholdUnit,
144
- thresholds: (!disabledThresholds && thresholds) || [],
145
111
  valueGraphHeight: graphHeight - 35
146
112
  }),
147
113
  [timeSeries, displayedLines, graphHeight]
@@ -235,20 +201,6 @@ const LineChart = ({
235
201
  }}
236
202
  zoomData={{ ...zoomPreview }}
237
203
  />
238
-
239
- {!disabledThresholds && (
240
- <Thresholds
241
- displayedLines={displayedLines}
242
- hideTooltip={hideThresholdTooltip}
243
- leftScale={leftScale}
244
- rightScale={rightScale}
245
- showTooltip={showThresholdTooltip}
246
- thresholdLabels={thresholdLabels}
247
- thresholdUnit={thresholdUnit}
248
- thresholds={thresholds}
249
- width={graphWidth}
250
- />
251
- )}
252
204
  </Group.Group>
253
205
  </svg>
254
206
  {displayTooltip && (
@@ -266,20 +218,6 @@ const LineChart = ({
266
218
  xScale={xScale}
267
219
  />
268
220
  )}
269
- <Fade in={thresholdTooltipOpen}>
270
- <Tooltip.Tooltip
271
- left={thresholdTooltipLeft}
272
- style={{
273
- ...baseStyles,
274
- backgroundColor: theme.palette.background.paper,
275
- color: theme.palette.text.primary,
276
- transform: `translate(${graphWidth / 2}px, -10px)`
277
- }}
278
- top={thresholdTooltipTop}
279
- >
280
- {thresholdTooltipData}
281
- </Tooltip.Tooltip>
282
- </Fade>
283
221
  </div>
284
222
  </ClickAwayListener>
285
223
  {displayLegend && (
@@ -289,9 +227,7 @@ const LineChart = ({
289
227
  displayAnchor={displayAnchor?.displayGuidingLines ?? true}
290
228
  lines={newLines}
291
229
  renderExtraComponent={legend?.renderExtraComponent}
292
- setLinesGraph={setLinesGraph}
293
230
  timeSeries={timeSeries}
294
- xScale={xScale}
295
231
  />
296
232
  </div>
297
233
  )}
@@ -1,3 +1,6 @@
1
1
  import { atom } from 'jotai';
2
2
 
3
+ import { Line } from '../common/timeSeries/models';
4
+
5
+ export const linesGraphAtom = atom<Array<Line> | null>(null);
3
6
  export const timeTickGraphAtom = atom<Date | null>(null);
@@ -29,11 +29,10 @@ import exclusionPeriodFirstPeriod from './mockedData/exclusionPeriodFirstPeriod.
29
29
  import exclusionPeriodSecondPeriod from './mockedData/exclusionPeriodSecondPeriod.json';
30
30
  import exclusionPeriodThirdPeriod from './mockedData/exclusionPeriodThirdPeriod.json';
31
31
  import dataLastDayForword from './mockedData/lastDayForward.json';
32
- import dataLastDayThreshold from './mockedData/lastDayThreshold.json';
32
+ import dataLastDay from './mockedData/lastDayThreshold.json';
33
33
  import dataLastMonth from './mockedData/lastMonth.json';
34
34
  import dataLastWeek from './mockedData/lastWeek.json';
35
35
  import dataZoomPreview from './mockedData/zoomPreview.json';
36
- import dataLastDay from './mockedData/lastDay.json';
37
36
  import { Interval, ThresholdType, TooltipData } from './models';
38
37
 
39
38
  import WrapperLineChart from './index';
@@ -76,7 +75,7 @@ const Threshold = (args): JSX.Element => {
76
75
 
77
76
  <WrapperLineChart
78
77
  {...args}
79
- data={dataLastDayThreshold}
78
+ data={dataLastDay}
80
79
  shapeLines={{
81
80
  areaThresholdLines: [
82
81
  { type: ThresholdType.basic },
@@ -124,7 +123,7 @@ const LineChartAndCLS = (args): JSX.Element => {
124
123
  useEffect(() => {
125
124
  setTimeout(() => {
126
125
  setLoading(false);
127
- setData(dataLastDayThreshold as unknown as LineChartData);
126
+ setData(dataLastDay as unknown as LineChartData);
128
127
  }, 100000);
129
128
  }, []);
130
129
 
@@ -188,7 +187,7 @@ const LineChartAndTimePeriod = (args): JSX.Element => {
188
187
  }
189
188
 
190
189
  if (start.includes(`${defaultStart.split('T')[0]}`)) {
191
- setCurrentData(dataLastDayThreshold as unknown as LineChartData);
190
+ setCurrentData(dataLastDay as unknown as LineChartData);
192
191
 
193
192
  return;
194
193
  }
@@ -282,7 +281,7 @@ const LineChartAndExclusionPeriod = (args): JSX.Element => {
282
281
  </ButtonGroup>
283
282
  <WrapperLineChart
284
283
  {...args}
285
- data={dataLastDayThreshold as unknown as LineChartData}
284
+ data={dataLastDay as unknown as LineChartData}
286
285
  shapeLines={{
287
286
  areaThresholdLines: [
288
287
  {
@@ -304,7 +303,7 @@ const Template: Story = {
304
303
  render: (args) => (
305
304
  <WrapperLineChart
306
305
  {...args}
307
- data={dataLastDayThreshold as unknown as LineChartData}
306
+ data={dataLastDay as unknown as LineChartData}
308
307
  shapeLines={{
309
308
  areaThresholdLines: [
310
309
  {
@@ -382,33 +381,3 @@ export const withCLS: Story = {
382
381
  start: defaultStart
383
382
  }
384
383
  };
385
-
386
- export const withThresholds: Story = {
387
- argTypes,
388
- args: {
389
- ...argumentsData,
390
- thresholdLabels: ['threshold 1', 'threshold 2'],
391
- thresholds: [300, 350]
392
- },
393
- render: (args) => (
394
- <WrapperLineChart
395
- {...args}
396
- data={dataLastDay as unknown as LineChartData}
397
- />
398
- )
399
- };
400
-
401
- export const withThresholdsAndUnit: Story = {
402
- argTypes,
403
- args: {
404
- ...argumentsData,
405
- thresholdUnit: '%',
406
- thresholds: [65, 79]
407
- },
408
- render: (args) => (
409
- <WrapperLineChart
410
- {...args}
411
- data={dataLastDay as unknown as LineChartData}
412
- />
413
- )
414
- };
@@ -25,16 +25,12 @@ dayjs.extend(timezonePlugin);
25
25
  interface Props extends Partial<LineChartProps> {
26
26
  curve?: CurveType;
27
27
  data?: LineChartData;
28
- disabledThresholds?: boolean;
29
28
  end: string;
30
29
  legend: LegendModel;
31
30
  loading: boolean;
32
31
  marginBottom?: number;
33
32
  shapeLines?: GlobalAreaLines;
34
33
  start: string;
35
- thresholdLabels?: Array<string>;
36
- thresholdUnit?: string;
37
- thresholds?: Array<number>;
38
34
  }
39
35
 
40
36
  const WrapperLineChart = ({
@@ -54,16 +50,12 @@ const WrapperLineChart = ({
54
50
  legend,
55
51
  header,
56
52
  curve = Curve.curveLinear,
57
- marginBottom = 0,
58
- thresholds,
59
- thresholdUnit,
60
- thresholdLabels,
61
- disabledThresholds
53
+ marginBottom = 0
62
54
  }: Props): JSX.Element | null => {
63
55
  const { adjustedData } = useLineChartData({ data, end, start });
64
56
  const lineChartRef = useRef<HTMLDivElement | null>(null);
65
57
 
66
- if (loading && !adjustedData) {
58
+ if (loading || !adjustedData) {
67
59
  return (
68
60
  <LoadingSkeleton
69
61
  displayTitleSkeleton={header?.displayTitle ?? true}
@@ -72,10 +64,6 @@ const WrapperLineChart = ({
72
64
  );
73
65
  }
74
66
 
75
- if (!adjustedData) {
76
- return null;
77
- }
78
-
79
67
  return (
80
68
  <div
81
69
  ref={lineChartRef as MutableRefObject<HTMLDivElement>}
@@ -91,7 +79,6 @@ const WrapperLineChart = ({
91
79
  annotationEvent={annotationEvent}
92
80
  axis={axis}
93
81
  curve={curve}
94
- disabledThresholds={disabledThresholds}
95
82
  displayAnchor={displayAnchor}
96
83
  graphData={adjustedData}
97
84
  graphInterval={{ end, start }}
@@ -102,9 +89,6 @@ const WrapperLineChart = ({
102
89
  loading={loading}
103
90
  marginBottom={marginBottom}
104
91
  shapeLines={shapeLines}
105
- thresholdLabels={thresholdLabels}
106
- thresholdUnit={thresholdUnit}
107
- thresholds={thresholds}
108
92
  timeShiftZones={timeShiftZones}
109
93
  tooltip={tooltip}
110
94
  width={width ?? responsiveWidth}
@@ -326,19 +326,10 @@ const getYScale = ({
326
326
  const getScale = ({
327
327
  graphValues,
328
328
  height,
329
- stackedValues,
330
- thresholds
329
+ stackedValues
331
330
  }): ScaleLinear<number, number> => {
332
- const minValue = Math.min(
333
- getMin(graphValues),
334
- getMin(stackedValues),
335
- Math.min(...thresholds)
336
- );
337
- const maxValue = Math.max(
338
- getMax(graphValues),
339
- getMax(stackedValues),
340
- Math.max(...thresholds)
341
- );
331
+ const minValue = min(getMin(graphValues), getMin(stackedValues));
332
+ const maxValue = max(getMax(graphValues), getMax(stackedValues));
342
333
 
343
334
  const upperRangeValue = minValue === maxValue && maxValue === 0 ? height : 0;
344
335
 
@@ -352,17 +343,10 @@ const getScale = ({
352
343
  const getLeftScale = ({
353
344
  dataLines,
354
345
  dataTimeSeries,
355
- valueGraphHeight,
356
- thresholds,
357
- thresholdUnit
346
+ valueGraphHeight
358
347
  }: AxeScale): ScaleLinear<number, number> => {
359
348
  const [firstUnit, , thirdUnit] = getUnits(dataLines);
360
349
 
361
- const shouldApplyThresholds =
362
- equals(thresholdUnit, firstUnit) ||
363
- equals(thresholdUnit, thirdUnit) ||
364
- !thresholdUnit;
365
-
366
350
  const graphValues = isNil(thirdUnit)
367
351
  ? getMetricValuesForUnit({
368
352
  lines: dataLines,
@@ -386,12 +370,7 @@ const getLeftScale = ({
386
370
  })
387
371
  : [0];
388
372
 
389
- return getScale({
390
- graphValues,
391
- height: valueGraphHeight,
392
- stackedValues,
393
- thresholds: shouldApplyThresholds ? thresholds : []
394
- });
373
+ return getScale({ graphValues, height: valueGraphHeight, stackedValues });
395
374
  };
396
375
 
397
376
  const getXScale = ({
@@ -407,9 +386,7 @@ const getXScale = ({
407
386
  const getRightScale = ({
408
387
  dataLines,
409
388
  dataTimeSeries,
410
- valueGraphHeight,
411
- thresholds,
412
- thresholdUnit
389
+ valueGraphHeight
413
390
  }: AxeScale): ScaleLinear<number, number> => {
414
391
  const [, secondUnit] = getUnits(dataLines);
415
392
 
@@ -419,8 +396,6 @@ const getRightScale = ({
419
396
  unit: secondUnit
420
397
  });
421
398
 
422
- const shouldApplyThresholds = equals(thresholdUnit, secondUnit);
423
-
424
399
  const secondUnitHasStackedLines = isNil(secondUnit)
425
400
  ? false
426
401
  : hasUnitStackedLines({ lines: dataLines, unit: secondUnit });
@@ -432,12 +407,7 @@ const getRightScale = ({
432
407
  })
433
408
  : [0];
434
409
 
435
- return getScale({
436
- graphValues,
437
- height: valueGraphHeight,
438
- stackedValues,
439
- thresholds: shouldApplyThresholds ? thresholds : []
440
- });
410
+ return getScale({ graphValues, height: valueGraphHeight, stackedValues });
441
411
  };
442
412
 
443
413
  const formatMetricValue = ({
@@ -506,10 +476,7 @@ const getTimeValue = ({
506
476
  xScale,
507
477
  timeSeries,
508
478
  marginLeft = margin.left
509
- }: TimeValueProps): TimeValue | null => {
510
- if (isNil(x)) {
511
- return null;
512
- }
479
+ }: TimeValueProps): TimeValue => {
513
480
  const date = xScale.invert(x - marginLeft);
514
481
  const index = bisectDate(getDates(timeSeries), date);
515
482
 
@@ -65,8 +65,6 @@ export interface Xscale {
65
65
  export interface AxeScale {
66
66
  dataLines: Array<Line>;
67
67
  dataTimeSeries: Array<TimeValue>;
68
- thresholdUnit?: string;
69
- thresholds: Array<number>;
70
68
  valueGraphHeight: number;
71
69
  }
72
70
 
@@ -119,6 +117,6 @@ export interface YScales {
119
117
  export interface TimeValueProps {
120
118
  marginLeft?: number;
121
119
  timeSeries: Array<TimeValue>;
122
- x?: number;
120
+ x: number;
123
121
  xScale: ScaleLinear<number, number>;
124
122
  }
@@ -107,7 +107,8 @@ const MemoListingActionBar = ({
107
107
  widthToMoveTablePagination = 550,
108
108
  actionsBarMemoProps = [],
109
109
  viewerModeConfiguration,
110
- viewMode
110
+ viewMode,
111
+ visualizationActions
111
112
  }: Props): JSX.Element => {
112
113
  const marginWidthTableListing = 30;
113
114
  const { classes, cx } = useStyles({
@@ -136,6 +137,7 @@ const MemoListingActionBar = ({
136
137
  <div className={classes.actions}>
137
138
  <div>{actions}</div>
138
139
  </div>
140
+ {visualizationActions && <div>{visualizationActions}</div>}
139
141
  <div className={classes.subContainer}>
140
142
  {!isEmpty(viewerModeConfiguration) &&
141
143
  !isNil(viewerModeConfiguration) && (
@@ -241,7 +243,8 @@ const ListingActionBar = ({
241
243
  widthToMoveTablePagination,
242
244
  customPaginationClassName,
243
245
  viewMode,
244
- viewerModeConfiguration
246
+ viewerModeConfiguration,
247
+ visualizationActions
245
248
  }: Props): JSX.Element | null => {
246
249
  if (
247
250
  not(paginated) &&
@@ -265,6 +268,7 @@ const ListingActionBar = ({
265
268
  totalRows={totalRows}
266
269
  viewMode={viewMode}
267
270
  viewerModeConfiguration={viewerModeConfiguration}
271
+ visualizationActions={visualizationActions}
268
272
  widthToMoveTablePagination={widthToMoveTablePagination}
269
273
  onLimitChange={onLimitChange}
270
274
  onPaginate={onPaginate}
@@ -128,6 +128,7 @@ export interface Props<TRow> {
128
128
  totalRows?: number;
129
129
  viewMode?: ListingVariant;
130
130
  viewerModeConfiguration?: ViewerModeConfiguration;
131
+ visualizationActions?: JSX.Element;
131
132
  widthToMoveTablePagination?: number;
132
133
  }
133
134
 
@@ -139,6 +140,7 @@ export const performanceRowsLimit = 60;
139
140
 
140
141
  const Listing = <TRow extends { id: RowId }>({
141
142
  limit = 10,
143
+ visualizationActions,
142
144
  columns,
143
145
  columnConfiguration = defaultColumnConfiguration,
144
146
  customPaginationClassName,
@@ -506,6 +508,7 @@ const Listing = <TRow extends { id: RowId }>({
506
508
  totalRows={totalRows}
507
509
  viewMode={viewMode}
508
510
  viewerModeConfiguration={viewerModeConfiguration}
511
+ visualizationActions={visualizationActions}
509
512
  widthToMoveTablePagination={widthToMoveTablePagination}
510
513
  onLimitChange={changeLimit}
511
514
  onPaginate={onPaginate}
@@ -341,5 +341,32 @@ describe('Rich Text Editor', () => {
341
341
  cy.get('[data-testid="RichTextEditor"]').find(tag).should('be.visible');
342
342
  });
343
343
  });
344
+
345
+ describe('Rich Text Editor is disabled', () => {
346
+ beforeEach(() => {
347
+ cy.mount({
348
+ Component: (
349
+ <RichTextEditor
350
+ disabled
351
+ editable
352
+ initialEditorState={mockInititalStateToEditor}
353
+ />
354
+ )
355
+ });
356
+ });
357
+
358
+ it('displays editor when editable props is false and an initialState exist', () => {
359
+ cy.get('[data-testid="RichTextEditor"]')
360
+ .invoke('attr', 'contenteditable')
361
+ .should('eq', 'false');
362
+ cy.findByLabelText('Undo').should('be.disabled');
363
+ cy.findByLabelText('Redo').should('be.disabled');
364
+ cy.findByLabelText('bold').should('be.disabled');
365
+ cy.findByLabelText('italic').should('be.disabled');
366
+ cy.findByLabelText('underline').should('be.disabled');
367
+ cy.findByLabelText('strikethrough').should('be.disabled');
368
+ cy.findByLabelText('link').should('be.disabled');
369
+ });
370
+ });
344
371
  });
345
372
  });
@@ -1,24 +1,15 @@
1
- import { equals, flatten, has, isEmpty, join, pipe, pluck } from 'ramda';
1
+ import { T, always, cond, flatten, isEmpty, join, pipe, pluck } from 'ramda';
2
2
  import dayjs from 'dayjs';
3
3
 
4
4
  import { LineChartData, useFetchQuery } from '../..';
5
5
 
6
6
  import { ServiceMetric } from './models';
7
7
 
8
- interface CustomTimePeriod {
9
- end: string;
10
- start: string;
11
- }
12
-
13
8
  interface UseMetricsQueryProps {
14
9
  baseEndpoint: string;
15
10
  metrics: Array<ServiceMetric>;
16
11
  refreshInterval?: number | false;
17
- timePeriod?: {
18
- end?: string | null;
19
- start?: string | null;
20
- timePeriodType: number;
21
- };
12
+ timePeriod?: TimePeriod;
22
13
  }
23
14
 
24
15
  interface UseMetricsQueryState {
@@ -29,24 +20,24 @@ interface UseMetricsQueryState {
29
20
  start: string;
30
21
  }
31
22
 
23
+ enum TimePeriod {
24
+ lastDay = 'last_day'
25
+ }
26
+
32
27
  const getStartEndFromTimePeriod = (
33
- timePeriod: number
28
+ timePeriod: TimePeriod
34
29
  ): { end: string; start: string } => {
35
- return {
36
- end: dayjs().toISOString(),
37
- start: dayjs().subtract(timePeriod, 'hour').toISOString()
38
- };
30
+ return cond([
31
+ [
32
+ T,
33
+ always({
34
+ end: dayjs().toISOString(),
35
+ start: dayjs().subtract(1, 'day').toISOString()
36
+ })
37
+ ]
38
+ ])(timePeriod);
39
39
  };
40
40
 
41
- const isCustomTimePeriod = (
42
- timePeriod:
43
- | number
44
- | {
45
- end?: string | null;
46
- start?: string | null;
47
- }
48
- ): boolean => has('end', timePeriod) && has('start', timePeriod);
49
-
50
41
  interface PerformanceGraphData extends Omit<LineChartData, 'global'> {
51
42
  base: number;
52
43
  }
@@ -54,9 +45,7 @@ interface PerformanceGraphData extends Omit<LineChartData, 'global'> {
54
45
  const useGraphQuery = ({
55
46
  metrics,
56
47
  baseEndpoint,
57
- timePeriod = {
58
- timePeriodType: 1
59
- },
48
+ timePeriod = TimePeriod.lastDay,
60
49
  refreshInterval = false
61
50
  }: UseMetricsQueryProps): UseMetricsQueryState => {
62
51
  const metricIds = pipe(
@@ -66,32 +55,16 @@ const useGraphQuery = ({
66
55
  join(',')
67
56
  )(metrics);
68
57
 
69
- const timePeriodToUse = equals(timePeriod?.timePeriodType, -1)
70
- ? {
71
- end: timePeriod.end,
72
- start: timePeriod.start
73
- }
74
- : timePeriod?.timePeriodType;
58
+ const { end, start } = getStartEndFromTimePeriod(timePeriod);
75
59
 
76
60
  const {
77
61
  data: graphData,
78
62
  isFetching,
79
63
  isLoading
80
64
  } = useFetchQuery<PerformanceGraphData>({
81
- getEndpoint: () => {
82
- if (isCustomTimePeriod(timePeriodToUse)) {
83
- return `${baseEndpoint}?metricIds=[${metricIds}]&start=${
84
- (timePeriodToUse as CustomTimePeriod).start
85
- }&end=${(timePeriodToUse as CustomTimePeriod).end}`;
86
- }
87
-
88
- const { end, start } = getStartEndFromTimePeriod(
89
- timePeriodToUse as number
90
- );
91
-
92
- return `${baseEndpoint}?metricIds=[${metricIds}]&start=${start}&end=${end}`;
93
- },
94
- getQueryKey: () => ['graph', metricIds, timePeriod],
65
+ getEndpoint: () =>
66
+ `${baseEndpoint}?metricIds=[${metricIds}]&start=${start}&end=${end}`,
67
+ getQueryKey: () => ['graph', metricIds],
95
68
  queryOptions: {
96
69
  enabled: !isEmpty(metricIds),
97
70
  refetchInterval: refreshInterval,
@@ -110,10 +83,6 @@ const useGraphQuery = ({
110
83
  }
111
84
  : undefined;
112
85
 
113
- const { end, start } = isCustomTimePeriod(timePeriodToUse)
114
- ? (timePeriodToUse as CustomTimePeriod)
115
- : getStartEndFromTimePeriod(timePeriodToUse as number);
116
-
117
86
  return {
118
87
  end,
119
88
  graphData: formattedGraphData,
@@ -61,7 +61,8 @@ const useStyles = makeStyles<{
61
61
  color: theme.palette.text.secondary,
62
62
  margin: theme.spacing(1, 0, 1, 0),
63
63
  width: '90%'
64
- }
64
+ },
65
+ height: '100%'
65
66
  },
66
67
  modalCloseButton: {
67
68
  position: 'absolute',
@@ -18,4 +18,3 @@ export * from './sanitizedHTML';
18
18
  export * from './docsURL';
19
19
  export * from './useInfiniteScrollListing';
20
20
  export * from './useLicenseExpirationWarning';
21
- export * from './useRefreshInterval';
@@ -1,119 +0,0 @@
1
- import { always, cond, equals, isNil } from 'ramda';
2
-
3
- import { Theme, useTheme } from '@mui/material';
4
-
5
- import { getUnits, getYScale } from '../../common/timeSeries';
6
- import { Line } from '../../common/timeSeries/models';
7
-
8
- interface Props {
9
- displayedLines: Array<Line>;
10
- hideTooltip: () => void;
11
- leftScale: (value: number) => number;
12
- rightScale: (value: number) => number;
13
- showTooltip: (props) => void;
14
- thresholdLabels?: Array<string>;
15
- thresholdUnit?: string;
16
- thresholds?: Array<number>;
17
- width: number;
18
- }
19
-
20
- interface GetColorProps {
21
- index: number;
22
- theme: Theme;
23
- }
24
-
25
- const getColor = ({ index, theme }: GetColorProps): string => {
26
- return cond([
27
- [equals(0), always(theme.palette.warning.main)],
28
- [equals(1), always(theme.palette.error.main)]
29
- ])(index);
30
- };
31
-
32
- const Thresholds = ({
33
- thresholds,
34
- leftScale,
35
- rightScale,
36
- width,
37
- displayedLines,
38
- thresholdUnit,
39
- showTooltip,
40
- hideTooltip,
41
- thresholdLabels
42
- }: Props): JSX.Element | null => {
43
- const theme = useTheme();
44
-
45
- if (!thresholds) {
46
- return null;
47
- }
48
-
49
- const [firstUnit, secondUnit, thirdUnit] = getUnits(
50
- displayedLines as Array<Line>
51
- );
52
-
53
- const shouldUseRightScale = equals(thresholdUnit, secondUnit);
54
-
55
- const yScale = shouldUseRightScale
56
- ? rightScale
57
- : getYScale({
58
- hasMoreThanTwoUnits: !isNil(thirdUnit),
59
- invert: null,
60
- leftScale,
61
- rightScale,
62
- secondUnit,
63
- unit: firstUnit
64
- });
65
-
66
- const thresholdScaledValues = thresholds
67
- .sort()
68
- .map((threshold) => yScale(threshold));
69
-
70
- return (
71
- <>
72
- {thresholdScaledValues.map((threshold, index) => {
73
- return (
74
- <line
75
- data-testid={`threshold-${threshold}`}
76
- key={`threshold-${thresholdLabels?.[index]}-${threshold}`}
77
- stroke={getColor({
78
- index,
79
- theme
80
- })}
81
- strokeDasharray="5,5"
82
- strokeWidth={2}
83
- x1={0}
84
- x2={width}
85
- y1={threshold}
86
- y2={threshold}
87
- />
88
- );
89
- })}
90
- {thresholdScaledValues.map((threshold, index) => {
91
- return (
92
- <line
93
- data-testid={`threshold-${threshold}-tooltip`}
94
- key={`threshold-${thresholdLabels?.[index]}-${threshold}-tooltip`}
95
- stroke="transparent"
96
- strokeWidth={4}
97
- x1={0}
98
- x2={width}
99
- y1={threshold}
100
- y2={threshold}
101
- onMouseEnter={(): void => {
102
- if (!thresholdLabels?.[index]) {
103
- return;
104
- }
105
- showTooltip({
106
- tooltipData: thresholdLabels?.[index],
107
- tooltipLeft: 0,
108
- tooltipTop: threshold
109
- });
110
- }}
111
- onMouseLeave={hideTooltip}
112
- />
113
- );
114
- })}
115
- </>
116
- );
117
- };
118
-
119
- export default Thresholds;
@@ -1,21 +0,0 @@
1
- import { always, cond, equals } from 'ramda';
2
-
3
- interface Props {
4
- globalRefreshInterval?: number;
5
- refreshInterval: 'default' | 'custom' | 'manual';
6
- refreshIntervalCustom?: number;
7
- }
8
-
9
- export const useRefreshInterval = ({
10
- refreshInterval,
11
- refreshIntervalCustom,
12
- globalRefreshInterval
13
- }: Props): number | false => {
14
- const refreshIntervalToUse = cond([
15
- [equals('default'), always(globalRefreshInterval)],
16
- [equals('custom'), always(refreshIntervalCustom)],
17
- [equals('manual'), always(0)]
18
- ])(refreshInterval);
19
-
20
- return refreshIntervalToUse ? refreshIntervalToUse * 1000 : false;
21
- };