@centreon/ui 23.10.75 → 23.10.76

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.75",
3
+ "version": "23.10.76",
4
4
  "description": "Centreon UI Components",
5
5
  "scripts": {
6
6
  "eslint": "eslint ./src --ext .js,.jsx,.ts,.tsx --max-warnings 0",
@@ -16,7 +16,7 @@ interface Props {
16
16
  graphHeight: number;
17
17
  highlight?: boolean;
18
18
  lineColor: string;
19
- metric: string;
19
+ metric_id: number;
20
20
  shapeAreaClosed?: Record<string, unknown>;
21
21
  shapeLinePath?: Record<string, unknown>;
22
22
  timeSeries: Array<TimeValue>;
@@ -30,7 +30,7 @@ const RegularLine = ({
30
30
  filled,
31
31
  timeSeries,
32
32
  highlight,
33
- metric,
33
+ metric_id,
34
34
  lineColor,
35
35
  unit,
36
36
  yScale,
@@ -43,13 +43,13 @@ const RegularLine = ({
43
43
  const props = {
44
44
  curve,
45
45
  data: timeSeries,
46
- defined: (value): boolean => !isNil(value[metric]),
46
+ defined: (value): boolean => !isNil(value[metric_id]),
47
47
  opacity: 1,
48
48
  stroke: lineColor,
49
49
  strokeWidth: !highlight ? 1 : 2,
50
50
  unit,
51
51
  x: (timeValue): number => xScale(getTime(timeValue)) as number,
52
- y: (timeValue): number => yScale(prop(metric, timeValue)) ?? null
52
+ y: (timeValue): number => yScale(prop(metric_id, timeValue)) ?? null
53
53
  };
54
54
 
55
55
  if (filled) {
@@ -57,7 +57,7 @@ const RegularLine = ({
57
57
  <Shape.AreaClosed<TimeValue>
58
58
  fill={getFillColor({ areaColor, transparency })}
59
59
  fillRule="nonzero"
60
- key={metric}
60
+ key={metric_id}
61
61
  y0={Math.min(yScale(0), graphHeight)}
62
62
  yScale={yScale}
63
63
  {...props}
@@ -32,11 +32,13 @@ const StackLines = ({
32
32
  data={timeSeries}
33
33
  defined={(d): boolean => {
34
34
  return pipe(
35
- map(prop('metric')) as unknown as (displayedLines) => Array<string>,
36
- all((metric) => pipe(path(['data', metric]), isNil, not)(d))
35
+ map(prop('metric_id')) as unknown as (
36
+ displayedLines
37
+ ) => Array<string>,
38
+ all((metric_id) => pipe(path(['data', metric_id]), isNil, not)(d))
37
39
  )(lines);
38
40
  }}
39
- keys={map(prop('metric'), lines)}
41
+ keys={map(prop('metric_id'), lines)}
40
42
  x={(d): number => xScale(getTime(d.data)) ?? 0}
41
43
  y0={(d): number => yScale(d[0]) ?? 0}
42
44
  y1={(d): number => yScale(d[1]) ?? 0}
@@ -53,21 +53,21 @@ const useScaleThreshold = ({
53
53
  const [, secondUnit, thirdUnit] = getUnits(lines);
54
54
 
55
55
  const {
56
- metric: metricY1,
56
+ metric_id: metricY1,
57
57
  unit: unitY1,
58
58
  invert: invertY1,
59
59
  lineColor: lineColorY1
60
60
  } = lineUpper;
61
61
 
62
62
  const {
63
- metric: metricY0,
63
+ metric_id: metricY0,
64
64
  unit: unitY0,
65
65
  invert: invertY0,
66
66
  lineColor: lineColorY0
67
67
  } = lineLower;
68
68
 
69
69
  const {
70
- metric: metricOrigin,
70
+ metric_id: metricOrigin,
71
71
  unit: unitYOrigin,
72
72
  invert: invertYOrigin
73
73
  } = lineOrigin;
@@ -129,14 +129,14 @@ const Lines = ({
129
129
  {displayAreaRegularLines
130
130
  ? regularLines.map(
131
131
  ({
132
- metric,
133
132
  areaColor,
134
133
  transparency,
135
134
  lineColor,
136
135
  filled,
137
136
  unit,
138
137
  highlight,
139
- invert
138
+ invert,
139
+ metric_id
140
140
  }) => {
141
141
  const [, secondUnit, thirdUnit] = getUnits(
142
142
  regularLines as Array<Line>
@@ -151,12 +151,12 @@ const Lines = ({
151
151
  });
152
152
 
153
153
  return (
154
- <g key={metric}>
154
+ <g key={metric_id}>
155
155
  {displayGuidingLines && (
156
156
  <RegularAnchorPoint
157
157
  areaColor={areaColor}
158
158
  lineColor={lineColor}
159
- metric={metric}
159
+ metric_id={metric_id}
160
160
  timeSeries={timeSeries}
161
161
  transparency={transparency}
162
162
  xScale={xScale}
@@ -170,7 +170,7 @@ const Lines = ({
170
170
  graphHeight={height}
171
171
  highlight={highlight}
172
172
  lineColor={lineColor}
173
- metric={metric}
173
+ metric_id={metric_id}
174
174
  timeSeries={timeSeries}
175
175
  transparency={transparency}
176
176
  unit={unit}
@@ -11,7 +11,7 @@ import AnchorPoint from '.';
11
11
 
12
12
  interface Props {
13
13
  lineColor: string;
14
- metric: string;
14
+ metric_id: number;
15
15
  timeSeries: Array<TimeValue>;
16
16
  xScale: ScaleTime<number, number>;
17
17
  yScale: ScaleLinear<number, number>;
@@ -21,18 +21,18 @@ const getYAnchorPoint = ({
21
21
  timeTick,
22
22
  timeSeries,
23
23
  yScale,
24
- metric
24
+ metric_id
25
25
  }: GetYAnchorPoint): number => {
26
26
  const index = bisectDate(getDates(timeSeries), timeTick);
27
27
  const timeValue = timeSeries[index];
28
28
 
29
- return yScale(prop(metric, timeValue) as number);
29
+ return yScale(prop(metric_id, timeValue) as number);
30
30
  };
31
31
 
32
32
  const RegularAnchorPoint = ({
33
33
  xScale,
34
34
  yScale,
35
- metric,
35
+ metric_id,
36
36
  timeSeries,
37
37
  lineColor
38
38
  }: Props): JSX.Element | null => {
@@ -48,7 +48,7 @@ const RegularAnchorPoint = ({
48
48
  const xAnchorPoint = xScale(timeTick);
49
49
 
50
50
  const yAnchorPoint = getYAnchorPoint({
51
- metric,
51
+ metric_id,
52
52
  timeSeries,
53
53
  timeTick,
54
54
  yScale
@@ -32,7 +32,7 @@ export interface GuidingLines {
32
32
  }
33
33
 
34
34
  export interface GetYAnchorPoint {
35
- metric: string;
35
+ metric_id: number;
36
36
  timeSeries: Array<TimeValue>;
37
37
  timeTick: Date;
38
38
  yScale: ScaleLinear<number, number>;
@@ -69,25 +69,25 @@ const MainLegend = ({
69
69
  value
70
70
  }) || 'N/A';
71
71
 
72
- const selectMetric = ({ event, metric }): void => {
72
+ const selectMetric = ({ event, metric_id }): void => {
73
73
  if (!toggable) {
74
74
  return;
75
75
  }
76
76
 
77
77
  if (event.ctrlKey || event.metaKey) {
78
- toggleMetricLine(metric);
78
+ toggleMetricLine(metric_id);
79
79
 
80
80
  return;
81
81
  }
82
82
 
83
- selectMetricLine(metric);
83
+ selectMetricLine(metric_id);
84
84
  };
85
85
 
86
86
  return (
87
87
  <div className={classes.legend}>
88
88
  <div className={classes.items}>
89
89
  {displayedLines.map((line) => {
90
- const { color, name, display, metric, highlight } = line;
90
+ const { color, display, highlight, metric_id } = line;
91
91
 
92
92
  const markerColor = display
93
93
  ? color
@@ -119,9 +119,9 @@ const MainLegend = ({
119
119
  highlight ? classes.highlight : classes.normal,
120
120
  toggable && classes.toggable
121
121
  )}
122
- key={name}
123
- onClick={(event): void => selectMetric({ event, metric })}
124
- onMouseEnter={(): void => highlightLine(metric)}
122
+ key={metric_id}
123
+ onClick={(event): void => selectMetric({ event, metric_id })}
124
+ onMouseEnter={(): void => highlightLine(metric_id)}
125
125
  onMouseLeave={(): void => clearHighlight()}
126
126
  >
127
127
  <LegendMarker color={markerColor} disabled={!display} />
@@ -43,34 +43,34 @@ const useInteractiveValues = ({
43
43
  equals(item.timeTick, timeValue?.timeTick)
44
44
  );
45
45
 
46
- const getMetricsToDisplay = (): Array<string> => {
46
+ const getMetricsToDisplay = (): Array<number> => {
47
47
  if (isNil(graphTimeValue)) {
48
48
  return [];
49
49
  }
50
50
  const metricsData = getMetrics(graphTimeValue as TimeValue);
51
51
 
52
- const metricsToDisplay = metricsData.filter((metric) => {
53
- const line = getLineForMetric({ lines, metric });
52
+ const metricsToDisplay = metricsData.filter((metric_id) => {
53
+ const line = getLineForMetric({ lines, metric_id: Number(metric_id) });
54
54
 
55
- return !isNil(graphTimeValue[metric]) && !isNil(line);
55
+ return !isNil(graphTimeValue[metric_id]) && !isNil(line);
56
56
  });
57
57
 
58
- return metricsToDisplay;
58
+ return metricsToDisplay.map(Number);
59
59
  };
60
60
 
61
61
  const metrics = useMemo(() => getMetricsToDisplay(), [graphTimeValue]);
62
62
 
63
63
  const getFormattedMetricData = (
64
- metric: string
64
+ metric_id: number
65
65
  ): FormattedMetricData | null => {
66
66
  if (isNil(graphTimeValue)) {
67
67
  return null;
68
68
  }
69
- const value = graphTimeValue[metric] as number;
69
+ const value = graphTimeValue[metric_id] as number;
70
70
 
71
71
  const { color, name, unit } = getLineForMetric({
72
72
  lines,
73
- metric
73
+ metric_id
74
74
  }) as Line;
75
75
 
76
76
  const formattedValue = formatMetricValue({
@@ -88,9 +88,9 @@ const useInteractiveValues = ({
88
88
  };
89
89
 
90
90
  const getFormattedValue = (line: Line): string | undefined | null => {
91
- const metric = find(equals(line.metric), metrics);
91
+ const metric_id = find(equals(line.metric_id), metrics);
92
92
 
93
- return metric && getFormattedMetricData(metric)?.formattedValue;
93
+ return metric_id ? getFormattedMetricData(metric_id)?.formattedValue : null;
94
94
  };
95
95
 
96
96
  return { getFormattedValue };
@@ -11,18 +11,16 @@ import {
11
11
  prop,
12
12
  propEq,
13
13
  reject,
14
- sortBy,
15
- compose,
16
- toLower
14
+ sortBy
17
15
  } from 'ramda';
18
16
 
19
17
  import { Line } from '../../common/timeSeries/models';
20
18
 
21
19
  interface LegendActions {
22
20
  clearHighlight: () => void;
23
- highlightLine: (metric: string) => void;
24
- selectMetricLine: (metric: string) => void;
25
- toggleMetricLine: (metric: string) => void;
21
+ highlightLine: (metric_id: number) => void;
22
+ selectMetricLine: (metric_id: number) => void;
23
+ toggleMetricLine: (metric_id: number) => void;
26
24
  }
27
25
 
28
26
  interface Props {
@@ -32,26 +30,26 @@ interface Props {
32
30
 
33
31
  const useLegend = ({ lines, setLinesGraph }: Props): LegendActions => {
34
32
  const displayedLines = reject(propEq('display', false), lines);
35
- const getLineByMetric = (metric: string): Line =>
36
- find(propEq('metric', metric), lines) as Line;
33
+ const getLineByMetric = (metric_id: number): Line =>
34
+ find(propEq('metric_id', metric_id), lines) as Line;
37
35
 
38
- const toggleMetricLine = (metric): void => {
39
- const line = getLineByMetric(metric);
36
+ const toggleMetricLine = (metric_id): void => {
37
+ const line = getLineByMetric(metric_id);
40
38
 
41
39
  setLinesGraph([
42
- ...reject(propEq('metric', metric), lines),
40
+ ...reject(propEq('metric_id', metric_id), lines),
43
41
  { ...line, display: !line.display }
44
42
  ]);
45
43
  };
46
44
 
47
- const highlightLine = (metric): void => {
45
+ const highlightLine = (metric_id): void => {
48
46
  const fadedLines = map((line) => ({ ...line, highlight: false }), lines);
49
47
  const data = [
50
- ...reject(propEq('metric', metric), fadedLines),
51
- { ...getLineByMetric(metric), highlight: true }
48
+ ...reject(propEq('metric_id', metric_id), fadedLines),
49
+ { ...getLineByMetric(metric_id), highlight: true }
52
50
  ];
53
51
 
54
- const sortedData = sortBy(compose(toLower, prop('name')), data);
52
+ const sortedData = sortBy(prop('metric_id'), data);
55
53
 
56
54
  setLinesGraph(sortedData);
57
55
  };
@@ -60,8 +58,8 @@ const useLegend = ({ lines, setLinesGraph }: Props): LegendActions => {
60
58
  setLinesGraph(map((line) => ({ ...line, highlight: undefined }), lines));
61
59
  };
62
60
 
63
- const selectMetricLine = (metric: string): void => {
64
- const metricLine = getLineByMetric(metric);
61
+ const selectMetricLine = (metric_id: number): void => {
62
+ const metricLine = getLineByMetric(metric_id);
65
63
 
66
64
  const isLineDisplayed = pipe(head, equals(metricLine))(displayedLines);
67
65
  const isOnlyLineDisplayed =
@@ -99,7 +97,7 @@ const useLegend = ({ lines, setLinesGraph }: Props): LegendActions => {
99
97
 
100
98
  const newLines = lines.map((line) => ({
101
99
  ...line,
102
- display: find(propEq('name', line.name), lines)?.display ?? true
100
+ display: find(propEq('metric_id', line.metric_id), lines)?.display ?? true
103
101
  }));
104
102
 
105
103
  setLinesGraph(newLines);
@@ -24,6 +24,7 @@ describe('timeSeries', () => {
24
24
  legend: 'Round-Trip-Time Average (ms)',
25
25
  maximum_value: 1.5,
26
26
  metric: 'rta',
27
+ metric_id: 1,
27
28
  minimum_value: 0.5,
28
29
  unit: 'ms'
29
30
  },
@@ -43,6 +44,7 @@ describe('timeSeries', () => {
43
44
  legend: 'Time (ms)',
44
45
  maximum_value: 1.5,
45
46
  metric: 'time',
47
+ metric_id: 2,
46
48
  minimum_value: 0.5,
47
49
  unit: 'ms'
48
50
  },
@@ -62,6 +64,7 @@ describe('timeSeries', () => {
62
64
  legend: 'Average duration (ms)',
63
65
  maximum_value: 1.5,
64
66
  metric: 'avgDuration',
67
+ metric_id: 3,
65
68
  minimum_value: 0.5,
66
69
  unit: 'ms'
67
70
  },
@@ -81,6 +84,7 @@ describe('timeSeries', () => {
81
84
  legend: 'Duration (ms)',
82
85
  maximum_value: 1.5,
83
86
  metric: 'duration',
87
+ metric_id: 4,
84
88
  minimum_value: 0.5,
85
89
  unit: 'ms'
86
90
  },
@@ -100,6 +104,7 @@ describe('timeSeries', () => {
100
104
  legend: 'Packet Loss (%)',
101
105
  maximum_value: 1.5,
102
106
  metric: 'packet_loss',
107
+ metric_id: 5,
103
108
  minimum_value: 0.5,
104
109
  unit: '%'
105
110
  }
@@ -111,19 +116,19 @@ describe('timeSeries', () => {
111
116
  it('returns the time series for the given graph data', () => {
112
117
  expect(timeSeries.getTimeSeries(graphData)).toEqual([
113
118
  {
114
- avgDuration: 6,
115
- duration: 12,
116
- packet_loss: 0,
117
- rta: 0,
118
- time: 0.5,
119
+ 1: 0,
120
+ 2: 0.5,
121
+ 3: 6,
122
+ 4: 12,
123
+ 5: 0,
119
124
  timeTick: '2020-11-05T10:35:00Z'
120
125
  },
121
126
  {
122
- avgDuration: 4,
123
- duration: 25,
124
- packet_loss: 1,
125
- rta: 1,
126
- time: 3,
127
+ 1: 1,
128
+ 2: 3,
129
+ 3: 4,
130
+ 4: 25,
131
+ 5: 1,
127
132
  timeTick: '2020-11-05T10:40:00Z'
128
133
  }
129
134
  ]);
@@ -139,17 +144,17 @@ describe('timeSeries', () => {
139
144
 
140
145
  expect(timeSeries.getTimeSeries(graphDataWithLowerLimit)).toEqual([
141
146
  {
142
- avgDuration: 6,
143
- duration: 12,
144
- time: 0.5,
147
+ 2: 0.5,
148
+ 3: 6,
149
+ 4: 12,
145
150
  timeTick: '2020-11-05T10:35:00Z'
146
151
  },
147
152
  {
148
- avgDuration: 4,
149
- duration: 25,
150
- packet_loss: 1,
151
- rta: 1,
152
- time: 3,
153
+ 1: 1,
154
+ 2: 3,
155
+ 3: 4,
156
+ 4: 25,
157
+ 5: 1,
153
158
  timeTick: '2020-11-05T10:40:00Z'
154
159
  }
155
160
  ]);
@@ -171,6 +176,7 @@ describe('timeSeries', () => {
171
176
  lineColor: 'black',
172
177
  maximum_value: 1.5,
173
178
  metric: 'rta',
179
+ metric_id: 1,
174
180
  minimum_value: 0.5,
175
181
  name: 'Round-Trip-Time Average (ms)',
176
182
  stackOrder: null,
@@ -189,6 +195,7 @@ describe('timeSeries', () => {
189
195
  lineColor: 'blue',
190
196
  maximum_value: 1.5,
191
197
  metric: 'time',
198
+ metric_id: 2,
192
199
  minimum_value: 0.5,
193
200
  name: 'Time (ms)',
194
201
  stackOrder: null,
@@ -207,6 +214,7 @@ describe('timeSeries', () => {
207
214
  lineColor: 'red',
208
215
  maximum_value: 1.5,
209
216
  metric: 'avgDuration',
217
+ metric_id: 3,
210
218
  minimum_value: 0.5,
211
219
  name: 'Average duration (ms)',
212
220
  stackOrder: 2,
@@ -225,6 +233,7 @@ describe('timeSeries', () => {
225
233
  lineColor: 'yellow',
226
234
  maximum_value: 1.5,
227
235
  metric: 'duration',
236
+ metric_id: 4,
228
237
  minimum_value: 0.5,
229
238
  name: 'Duration (ms)',
230
239
  stackOrder: 1,
@@ -243,6 +252,7 @@ describe('timeSeries', () => {
243
252
  lineColor: 'yellow',
244
253
  maximum_value: 1.5,
245
254
  metric: 'packet_loss',
255
+ metric_id: 5,
246
256
  minimum_value: 0.5,
247
257
  name: 'Packet Loss (%)',
248
258
  stackOrder: null,
@@ -300,7 +310,7 @@ describe('timeSeries', () => {
300
310
  it('returns the line corresponding to the given metrics', () => {
301
311
  const lines = timeSeries.getLineData(graphData);
302
312
 
303
- expect(timeSeries.getLineForMetric({ lines, metric: 'rta' })).toEqual({
313
+ expect(timeSeries.getLineForMetric({ lines, metric_id: 1 })).toEqual({
304
314
  areaColor: 'transparent',
305
315
  average_value: 1,
306
316
  color: 'black',
@@ -312,6 +322,7 @@ describe('timeSeries', () => {
312
322
  lineColor: 'black',
313
323
  maximum_value: 1.5,
314
324
  metric: 'rta',
325
+ metric_id: 1,
315
326
  minimum_value: 0.5,
316
327
  name: 'Round-Trip-Time Average (ms)',
317
328
  stackOrder: null,
@@ -369,6 +380,7 @@ describe('timeSeries', () => {
369
380
  lineColor: 'yellow',
370
381
  maximum_value: 1.5,
371
382
  metric: 'duration',
383
+ metric_id: 4,
372
384
  minimum_value: 0.5,
373
385
  name: 'Duration (ms)',
374
386
  stackOrder: 1,
@@ -387,6 +399,7 @@ describe('timeSeries', () => {
387
399
  lineColor: 'red',
388
400
  maximum_value: 1.5,
389
401
  metric: 'avgDuration',
402
+ metric_id: 3,
390
403
  minimum_value: 0.5,
391
404
  name: 'Average duration (ms)',
392
405
  stackOrder: 2,
@@ -423,13 +436,13 @@ describe('timeSeries', () => {
423
436
  })
424
437
  ).toEqual([
425
438
  {
426
- avgDuration: 6,
427
- duration: 12,
439
+ 3: 6,
440
+ 4: 12,
428
441
  timeTick: '2020-11-05T10:35:00Z'
429
442
  },
430
443
  {
431
- avgDuration: 4,
432
- duration: 25,
444
+ 3: 4,
445
+ 4: 25,
433
446
  timeTick: '2020-11-05T10:40:00Z'
434
447
  }
435
448
  ]);
@@ -453,6 +466,7 @@ describe('timeSeries', () => {
453
466
  lineColor: 'yellow',
454
467
  maximum_value: 1.5,
455
468
  metric: 'duration',
469
+ metric_id: 4,
456
470
  minimum_value: 0.5,
457
471
  name: 'Duration (ms)',
458
472
  stackOrder: 1,
@@ -480,6 +494,7 @@ describe('timeSeries', () => {
480
494
  lineColor: 'red',
481
495
  maximum_value: 1.5,
482
496
  metric: 'avgDuration',
497
+ metric_id: 3,
483
498
  minimum_value: 0.5,
484
499
  name: 'Average duration (ms)',
485
500
  stackOrder: 2,
@@ -70,9 +70,9 @@ const toTimeTickValue = (
70
70
  timeIndex: number
71
71
  ): TimeValue => {
72
72
  const getMetricsForIndex = (): Omit<TimeValue, 'timeTick'> => {
73
- const addMetricForTimeIndex = (acc, { metric, data }): TimeValue => ({
73
+ const addMetricForTimeIndex = (acc, { metric_id, data }): TimeValue => ({
74
74
  ...acc,
75
- [metric]: data[timeIndex]
75
+ [metric_id]: data[timeIndex]
76
76
  });
77
77
 
78
78
  return reduce(addMetricForTimeIndex, {} as TimeValue, metrics);
@@ -116,7 +116,8 @@ const toLine = ({
116
116
  unit,
117
117
  average_value,
118
118
  minimum_value,
119
- maximum_value
119
+ maximum_value,
120
+ metric_id
120
121
  }: Metric): Line => ({
121
122
  areaColor: ds_data.ds_color_area,
122
123
  average_value,
@@ -129,6 +130,7 @@ const toLine = ({
129
130
  lineColor: ds_data.ds_color_line,
130
131
  maximum_value,
131
132
  metric,
133
+ metric_id,
132
134
  minimum_value,
133
135
  name: legend,
134
136
  stackOrder: equals(ds_data.ds_stack, '1')
@@ -153,8 +155,8 @@ const getMetrics = (timeValue: TimeValue): Array<string> =>
153
155
 
154
156
  const getValueForMetric =
155
157
  (timeValue: TimeValue) =>
156
- (metric: string): number =>
157
- prop(metric, timeValue) as number;
158
+ (metric_id: number): number =>
159
+ prop(metric_id, timeValue) as number;
158
160
 
159
161
  const getUnits = (lines: Array<Line>): Array<string> =>
160
162
  pipe(map(prop('unit')), uniq)(lines);
@@ -170,15 +172,15 @@ const getMetricValuesForUnit = ({
170
172
  timeSeries,
171
173
  unit
172
174
  }: ValuesForUnitProps): Array<number> => {
173
- const getTimeSeriesValuesForMetric = (metric): Array<number> =>
175
+ const getTimeSeriesValuesForMetric = (metric_id): Array<number> =>
174
176
  map(
175
- (timeValue) => getValueForMetric(timeValue)(metric),
177
+ (timeValue) => getValueForMetric(timeValue)(metric_id),
176
178
  timeSeries
177
179
  ) as Array<number>;
178
180
 
179
181
  return pipe(
180
182
  filter(propEq('unit', unit)) as (line) => Array<Line>,
181
- map(prop('metric')),
183
+ map(prop('metric_id')),
182
184
  map(getTimeSeriesValuesForMetric),
183
185
  flatten,
184
186
  reject(isNil)
@@ -194,14 +196,14 @@ const getDates = (timeSeries: Array<TimeValue>): Array<Date> => {
194
196
 
195
197
  interface LineForMetricProps {
196
198
  lines: Array<Line>;
197
- metric: string;
199
+ metric_id: number;
198
200
  }
199
201
 
200
202
  const getLineForMetric = ({
201
203
  lines,
202
- metric
204
+ metric_id
203
205
  }: LineForMetricProps): Line | undefined =>
204
- find(propEq('metric', metric), lines);
206
+ find(propEq('metric_id', metric_id), lines);
205
207
 
206
208
  interface LinesTimeSeries {
207
209
  lines: Array<Line>;
@@ -222,11 +224,11 @@ const getStackedMetricValues = ({
222
224
  lines,
223
225
  timeSeries
224
226
  }: LinesTimeSeries): Array<number> => {
225
- const getTimeSeriesValuesForMetric = (metric): Array<number> =>
226
- map((timeValue) => getValueForMetric(timeValue)(metric), timeSeries);
227
+ const getTimeSeriesValuesForMetric = (metric_id): Array<number> =>
228
+ map((timeValue) => getValueForMetric(timeValue)(metric_id), timeSeries);
227
229
 
228
230
  const metricsValues = pipe(
229
- map(prop('metric')) as (metric) => Array<string>,
231
+ map(prop('metric_id')) as (metric) => Array<number>,
230
232
  map(getTimeSeriesValuesForMetric) as () => Array<Array<number>>
231
233
  )(lines as Array<Line>);
232
234
 
@@ -279,14 +281,14 @@ const getTimeSeriesForLines = ({
279
281
  lines,
280
282
  timeSeries
281
283
  }: LinesTimeSeries): Array<TimeValue> => {
282
- const metrics = map(prop('metric'), lines);
284
+ const metrics = map(prop('metric_id'), lines);
283
285
 
284
286
  return map(
285
287
  ({ timeTick, ...metricsValue }): TimeValue => ({
286
288
  ...reduce(
287
- (acc, metric): Omit<TimeValue, 'timePick'> => ({
289
+ (acc, metric_id): Omit<TimeValue, 'timePick'> => ({
288
290
  ...acc,
289
- [metric]: metricsValue[metric]
291
+ [metric_id]: metricsValue[metric_id]
290
292
  }),
291
293
  {},
292
294
  metrics
@@ -21,6 +21,7 @@ export interface Metric {
21
21
  legend: string;
22
22
  maximum_value: number | null;
23
23
  metric: string;
24
+ metric_id: number;
24
25
  minimum_value: number | null;
25
26
  unit: string;
26
27
  warning_high_threshold: number | null;
@@ -30,7 +31,7 @@ export interface Metric {
30
31
  type TimeSeries = { timeTick: string };
31
32
 
32
33
  export type TimeValue = TimeSeries & {
33
- [field: string]: number;
34
+ [field: number]: number;
34
35
  };
35
36
 
36
37
  export interface Line {
@@ -45,6 +46,7 @@ export interface Line {
45
46
  lineColor: string;
46
47
  maximum_value: number | null;
47
48
  metric: string;
49
+ metric_id: number;
48
50
  minimum_value: number | null;
49
51
  name: string;
50
52
  stackOrder: number | null;
@@ -10,7 +10,8 @@ import {
10
10
  pipe,
11
11
  not,
12
12
  has,
13
- omit
13
+ omit,
14
+ uniqBy
14
15
  } from 'ramda';
15
16
 
16
17
  import { CircularProgress, useTheme } from '@mui/material';
@@ -30,6 +31,7 @@ import {
30
31
  import useFetchQuery from '../../../../api/useFetchQuery';
31
32
 
32
33
  export interface ConnectedAutoCompleteFieldProps<TData> {
34
+ allowUniqOption?: boolean;
33
35
  conditionField?: keyof SelectEntry;
34
36
  field: string;
35
37
  getEndpoint: ({ search, page }) => string;
@@ -57,6 +59,7 @@ const ConnectedAutocompleteField = (
57
59
  getRequestHeaders,
58
60
  displayOptionThumbnail,
59
61
  queryKey,
62
+ allowUniqOption,
60
63
  ...props
61
64
  }: ConnectedAutoCompleteFieldProps<TData> &
62
65
  Omit<AutocompleteFieldProps, 'options'>): JSX.Element => {
@@ -305,7 +308,9 @@ const ConnectedAutocompleteField = (
305
308
  filterOptions={(opt): SelectEntry => opt}
306
309
  loading={isFetching}
307
310
  open={optionsOpen}
308
- options={options}
311
+ options={
312
+ allowUniqOption ? uniqBy(getRenderedOptionText, options) : options
313
+ }
309
314
  renderOption={renderOptions}
310
315
  onChange={(_, value) => setAutocompleteChangedValue(value)}
311
316
  onClose={(): void => setOptionsOpen(false)}
@@ -1,7 +1,7 @@
1
1
  import { includes, map, prop, reject } from 'ramda';
2
2
  import { makeStyles } from 'tss-react/mui';
3
3
 
4
- import { Chip, ChipProps } from '@mui/material';
4
+ import { Chip, ChipProps, Tooltip } from '@mui/material';
5
5
  import { UseAutocompleteProps } from '@mui/material/useAutocomplete';
6
6
 
7
7
  import Autocomplete, { Props as AutocompleteProps } from '..';
@@ -34,6 +34,7 @@ export interface Props
34
34
  > {
35
35
  chipProps?: ChipProps;
36
36
  disableSortedOptions?: boolean;
37
+ getOptionTooltipLabel?: (option) => string;
37
38
  getTagLabel?: (option) => string;
38
39
  optionProperty?: string;
39
40
  }
@@ -45,6 +46,7 @@ const MultiAutocompleteField = ({
45
46
  optionProperty = 'name',
46
47
  getOptionLabel = (option): string => option.name,
47
48
  getTagLabel = (option): string => option[optionProperty],
49
+ getOptionTooltipLabel,
48
50
  chipProps,
49
51
  ...props
50
52
  }: Props): JSX.Element => {
@@ -52,17 +54,22 @@ const MultiAutocompleteField = ({
52
54
 
53
55
  const renderTags = (renderedValue, getTagProps): Array<JSX.Element> =>
54
56
  renderedValue.map((option, index) => (
55
- <Chip
56
- classes={{
57
- deleteIcon: classes.deleteIcon,
58
- root: classes.tag
59
- }}
57
+ <Tooltip
60
58
  key={option.id}
61
- label={getTagLabel(option)}
62
- size="medium"
63
- {...getTagProps({ index })}
64
- {...chipProps}
65
- />
59
+ placement="top"
60
+ title={getOptionTooltipLabel?.(option)}
61
+ >
62
+ <Chip
63
+ classes={{
64
+ deleteIcon: classes.deleteIcon,
65
+ root: classes.tag
66
+ }}
67
+ label={getTagLabel(option)}
68
+ size="medium"
69
+ {...getTagProps({ index })}
70
+ {...chipProps}
71
+ />
72
+ </Tooltip>
66
73
  ));
67
74
 
68
75
  const getLimitTagsText = (more): JSX.Element => <Option>{`+${more}`}</Option>;
@@ -1,6 +1,7 @@
1
1
  import { useAtomValue } from 'jotai';
2
2
  import { makeStyles } from 'tss-react/mui';
3
3
  import { equals } from 'ramda';
4
+ import { useTranslation } from 'react-i18next';
4
5
 
5
6
  import { Typography } from '@mui/material';
6
7
  import { LocalizationProvider } from '@mui/x-date-pickers';
@@ -34,6 +35,7 @@ const useStyles = makeStyles()((theme) => ({
34
35
  textAlign: 'left'
35
36
  },
36
37
  row: {
38
+ alignItems: 'center',
37
39
  display: 'flex',
38
40
  flexDirection: 'row',
39
41
  gap: theme.spacing(1)
@@ -63,11 +65,12 @@ const PickerDateWithLabel = ({
63
65
  direction = PickersStartEndDateDirection.column
64
66
  }: PropsPickersDateWithLabel): JSX.Element => {
65
67
  const { classes, cx } = useStyles();
68
+ const { t } = useTranslation();
66
69
  const isRow = equals(direction, PickersStartEndDateDirection.row);
67
70
 
68
71
  return (
69
72
  <div aria-label={label} className={cx({ [classes.row]: isRow })}>
70
- <Typography component={isRow ? 'div' : 'p'}>{label}</Typography>
73
+ <Typography component={isRow ? 'div' : 'p'}>{t(label)}</Typography>
71
74
  <DateTimePickerInput
72
75
  changeDate={changeDate}
73
76
  date={date}
@@ -106,10 +109,10 @@ const PickersStartEndDate = ({
106
109
  const { locale } = useAtomValue(userAtom);
107
110
  const error = useAtomValue(errorTimePeriodAtom);
108
111
 
109
- const maxStart = rangeStartDate?.max;
112
+ const maxStart = rangeStartDate?.max || endDate;
110
113
  const minStart = rangeStartDate?.min;
111
114
  const maxEnd = rangeEndDate?.max;
112
- const minEnd = rangeEndDate?.min;
115
+ const minEnd = rangeEndDate?.min || startDate;
113
116
 
114
117
  const styleContainer = equals(direction, PickersStartEndDateDirection.column)
115
118
  ? classes.verticalDirection
@@ -132,7 +135,7 @@ const PickersStartEndDate = ({
132
135
  direction={direction}
133
136
  disabled={disabled?.isDisabledStartPicker}
134
137
  label="From"
135
- maxDate={maxStart}
138
+ maxDate={maxStart || undefined}
136
139
  minDate={minStart}
137
140
  property={CustomTimePeriodProperty.start}
138
141
  />
@@ -141,9 +144,9 @@ const PickersStartEndDate = ({
141
144
  date={endDate}
142
145
  direction={direction}
143
146
  disabled={disabled?.isDisabledEndPicker}
144
- label="To"
147
+ label="to"
145
148
  maxDate={maxEnd}
146
- minDate={minEnd}
149
+ minDate={minEnd || undefined}
147
150
  property={CustomTimePeriodProperty.end}
148
151
  />
149
152
  </div>
@@ -0,0 +1,28 @@
1
+ import PickersStartEndDate from './PopoverCustomTimePeriod/PickersStartEndDate';
2
+ import {
3
+ AcceptDateProps,
4
+ PickersStartEndDateDirection
5
+ } from './PopoverCustomTimePeriod/models';
6
+
7
+ interface Props {
8
+ changeDate: (props: AcceptDateProps) => void;
9
+ endDate: Date;
10
+ startDate: Date;
11
+ }
12
+
13
+ const SimpleCustomTimePeriod = ({
14
+ startDate,
15
+ endDate,
16
+ changeDate
17
+ }: Props): JSX.Element => {
18
+ return (
19
+ <PickersStartEndDate
20
+ changeDate={changeDate}
21
+ direction={PickersStartEndDateDirection.row}
22
+ endDate={endDate}
23
+ startDate={startDate}
24
+ />
25
+ );
26
+ };
27
+
28
+ export default SimpleCustomTimePeriod;
@@ -4,6 +4,7 @@ import dayjs from 'dayjs';
4
4
  import Switch from '@mui/material/Switch';
5
5
 
6
6
  import { dateFormat } from './models';
7
+ import SimpleCustomTimePeriod from './CustomTimePeriod/SimpleCustomTimePeriod';
7
8
 
8
9
  import TimePeriod from '.';
9
10
 
@@ -16,10 +17,16 @@ export default meta;
16
17
 
17
18
  type Story = StoryObj<typeof TimePeriod>;
18
19
 
20
+ type StorySimpleTimePeriod = StoryObj<typeof SimpleCustomTimePeriod>;
21
+
19
22
  const Template: Story = {
20
23
  render: (args) => <TimePeriod {...args} />
21
24
  };
22
25
 
26
+ const TemplateWithSimpleTimePeriod: StorySimpleTimePeriod = {
27
+ render: (args) => <SimpleCustomTimePeriod {...args} />
28
+ };
29
+
23
30
  const TemplateWithExternalComponent: Story = {
24
31
  render: (args) => (
25
32
  <TimePeriod {...args} renderExternalComponent={<Switch />} />
@@ -96,3 +103,11 @@ export const WithExternalComponent: Story = {
96
103
  ...TemplateWithExternalComponent,
97
104
  argTypes
98
105
  };
106
+
107
+ export const SimpleTimePeriod: StorySimpleTimePeriod = {
108
+ ...TemplateWithSimpleTimePeriod,
109
+ args: {
110
+ endDate: dayjs(Date.now()).toDate(),
111
+ startDate: dayjs(Date.now()).subtract(29, 'day').toDate()
112
+ }
113
+ };
@@ -1,9 +1,9 @@
1
- import { equals, flatten, has, isEmpty, join, pipe, pluck } from 'ramda';
1
+ import { equals, has, isEmpty, pluck } from 'ramda';
2
2
  import dayjs from 'dayjs';
3
3
 
4
- import { LineChartData, useFetchQuery } from '../..';
4
+ import { LineChartData, buildListingEndpoint, useFetchQuery } from '../..';
5
5
 
6
- import { ServiceMetric } from './models';
6
+ import { Resource, WidgetResourceType } from './models';
7
7
 
8
8
  interface CustomTimePeriod {
9
9
  end: string;
@@ -12,8 +12,9 @@ interface CustomTimePeriod {
12
12
 
13
13
  interface UseMetricsQueryProps {
14
14
  baseEndpoint: string;
15
- metrics: Array<ServiceMetric>;
15
+ metrics: Array<string>;
16
16
  refreshInterval?: number | false;
17
+ resources?: Array<Resource>;
17
18
  timePeriod?: {
18
19
  end?: string | null;
19
20
  start?: string | null;
@@ -25,7 +26,7 @@ interface UseMetricsQueryState {
25
26
  end: string;
26
27
  graphData: LineChartData | undefined;
27
28
  isGraphLoading: boolean;
28
- isMetricIdsEmpty: boolean;
29
+ isMetricsEmpty: boolean;
29
30
  start: string;
30
31
  }
31
32
 
@@ -51,21 +52,28 @@ interface PerformanceGraphData extends Omit<LineChartData, 'global'> {
51
52
  base: number;
52
53
  }
53
54
 
55
+ const resourceTypeQueryParameter = {
56
+ [WidgetResourceType.host]: 'host.id',
57
+ [WidgetResourceType.hostCategory]: 'hostcategory.id',
58
+ [WidgetResourceType.hostGroup]: 'hostgroup.id',
59
+ [WidgetResourceType.service]: 'service.name'
60
+ };
61
+
62
+ const areResourcesFullfilled = (value: Array<Resource>): boolean =>
63
+ value?.every(
64
+ ({ resourceType, resources }) =>
65
+ !isEmpty(resourceType) && !isEmpty(resources)
66
+ );
67
+
54
68
  const useGraphQuery = ({
55
69
  metrics,
70
+ resources = [],
56
71
  baseEndpoint,
57
72
  timePeriod = {
58
73
  timePeriodType: 1
59
74
  },
60
75
  refreshInterval = false
61
76
  }: UseMetricsQueryProps): UseMetricsQueryState => {
62
- const metricIds = pipe(
63
- pluck('metrics'),
64
- flatten,
65
- pluck('id'),
66
- join(',')
67
- )(metrics);
68
-
69
77
  const timePeriodToUse = equals(timePeriod?.timePeriodType, -1)
70
78
  ? {
71
79
  end: timePeriod.end,
@@ -73,27 +81,44 @@ const useGraphQuery = ({
73
81
  }
74
82
  : timePeriod?.timePeriodType;
75
83
 
84
+ const startAndEnd = isCustomTimePeriod(timePeriodToUse)
85
+ ? (timePeriodToUse as CustomTimePeriod)
86
+ : getStartEndFromTimePeriod(timePeriodToUse as number);
87
+
88
+ const definedMetrics = metrics.filter((metric) => metric);
89
+
76
90
  const {
77
91
  data: graphData,
78
92
  isFetching,
79
93
  isLoading
80
94
  } = useFetchQuery<PerformanceGraphData>({
81
95
  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}`;
96
+ const endpoint = buildListingEndpoint({
97
+ baseEndpoint,
98
+ parameters: {
99
+ search: {
100
+ lists: resources.map((resource) => ({
101
+ field: resourceTypeQueryParameter[resource.resourceType],
102
+ values: equals(resource.resourceType, 'service')
103
+ ? pluck('name', resource.resources)
104
+ : pluck('id', resource.resources)
105
+ }))
106
+ }
107
+ }
108
+ });
109
+
110
+ return `${endpoint}&start=${startAndEnd.start}&end=${
111
+ startAndEnd.end
112
+ }&metric_names=[${definedMetrics.join(',')}]`;
93
113
  },
94
- getQueryKey: () => ['graph', metricIds, timePeriod],
114
+ getQueryKey: () => [
115
+ 'graph',
116
+ JSON.stringify(definedMetrics),
117
+ JSON.stringify(resources),
118
+ timePeriod
119
+ ],
95
120
  queryOptions: {
96
- enabled: !isEmpty(metricIds),
121
+ enabled: areResourcesFullfilled(resources) && !isEmpty(definedMetrics),
97
122
  refetchInterval: refreshInterval,
98
123
  suspense: false
99
124
  }
@@ -117,8 +142,8 @@ const useGraphQuery = ({
117
142
  return {
118
143
  end,
119
144
  graphData: formattedGraphData,
120
- isGraphLoading: isFetching || (isLoading && !isEmpty(metricIds)),
121
- isMetricIdsEmpty: isEmpty(metricIds),
145
+ isGraphLoading: isFetching || (isLoading && !isEmpty(definedMetrics)),
146
+ isMetricsEmpty: isEmpty(definedMetrics),
122
147
  start
123
148
  };
124
149
  };
@@ -1,12 +1,13 @@
1
- interface NamedEntity {
2
- id: number;
3
- name: string;
4
- }
1
+ import { SelectEntry } from '../..';
5
2
 
6
- interface Metric extends NamedEntity {
7
- unit: string;
3
+ export interface Resource {
4
+ resourceType: string;
5
+ resources: Array<SelectEntry>;
8
6
  }
9
7
 
10
- export interface ServiceMetric extends NamedEntity {
11
- metrics: Array<Metric>;
8
+ export enum WidgetResourceType {
9
+ host = 'host',
10
+ hostCategory = 'host-category',
11
+ hostGroup = 'host-group',
12
+ service = 'service'
12
13
  }
package/src/index.ts CHANGED
@@ -147,3 +147,6 @@ export * from './Dashboard';
147
147
  export * from './Graph';
148
148
  export type { LineChartData } from './Graph/common/models';
149
149
  export * from './Graph/common/timeSeries';
150
+
151
+ export { default as TimePeriods } from './TimePeriods';
152
+ export { default as SimpleCustomTimePeriod } from './TimePeriods/CustomTimePeriod/SimpleCustomTimePeriod';