@centreon/ui 25.9.3 → 25.10.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/src/Form/Inputs/Grid.tsx +3 -2
- package/src/Form/Section/navigateToSection.ts +6 -6
- package/src/Graph/BarChart/BarChart.cypress.spec.tsx +9 -0
- package/src/Graph/BarChart/BarChart.stories.tsx +42 -1
- package/src/Graph/BarChart/BarChart.tsx +1 -1
- package/src/Graph/BarChart/ResponsiveBarChart.tsx +2 -1
- package/src/Graph/Chart/Chart.cypress.spec.tsx +24 -5
- package/src/Graph/Chart/Chart.stories.tsx +34 -1
- package/src/Graph/Chart/Chart.tsx +3 -2
- package/src/Graph/Chart/Legend/index.tsx +26 -2
- package/src/Graph/Chart/models.ts +6 -1
- package/src/Graph/Chart/useChartData.ts +1 -1
- package/src/Graph/common/BaseChart/BaseChart.tsx +6 -1
- package/src/Graph/common/timeSeries/index.ts +32 -11
- package/src/Graph/common/utils.ts +10 -4
- package/src/Graph/mockedData/dataWithMissingPoint.json +74 -0
- package/src/InputField/Select/index.tsx +1 -2
- package/src/Module/index.tsx +1 -1
- package/src/ThemeProvider/tailwindcss.css +10 -10
- package/src/api/useGraphQuery/index.ts +5 -2
- package/src/components/Modal/Modal.styles.ts +1 -2
- package/src/components/Modal/ModalHeader.tsx +5 -1
package/package.json
CHANGED
package/src/Form/Inputs/Grid.tsx
CHANGED
|
@@ -21,8 +21,9 @@ const Grid = ({
|
|
|
21
21
|
<div
|
|
22
22
|
className={`${className} grid gap-3`}
|
|
23
23
|
style={{
|
|
24
|
-
gridTemplateColumns:
|
|
25
|
-
|
|
24
|
+
gridTemplateColumns: className
|
|
25
|
+
? grid?.gridTemplateColumns || undefined
|
|
26
|
+
: grid?.gridTemplateColumns ||
|
|
26
27
|
`repeat(${grid?.columns.length || 1}, 1fr)`,
|
|
27
28
|
alignItems: grid?.alignItems || 'flex-start'
|
|
28
29
|
}}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export const useNavigateToSection = () => {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
return (sectionName: string) => {
|
|
3
|
+
const section = document.querySelector(
|
|
4
|
+
`[data-section-group-form-id="${sectionName}"]`
|
|
5
|
+
);
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
section?.scrollIntoView({ behavior: 'smooth' });
|
|
8
|
+
};
|
|
9
9
|
};
|
|
@@ -8,6 +8,7 @@ import dataLastWeek from '../mockedData/lastWeek.json';
|
|
|
8
8
|
import dataPingService from '../mockedData/pingService.json';
|
|
9
9
|
import dataPingServiceMixedStacked from '../mockedData/pingServiceMixedStacked.json';
|
|
10
10
|
import dataPingServiceStacked from '../mockedData/pingServiceStacked.json';
|
|
11
|
+
import dataMissingPoint from '../mockedData/dataWithMissingPoint.json';
|
|
11
12
|
|
|
12
13
|
import BarChart, { BarChartProps } from './BarChart';
|
|
13
14
|
|
|
@@ -312,4 +313,12 @@ describe('Bar chart', () => {
|
|
|
312
313
|
cy.contains('1 s').should('be.visible');
|
|
313
314
|
cy.contains('1%').should('be.visible');
|
|
314
315
|
});
|
|
316
|
+
|
|
317
|
+
it('displays the stacked bar chart correctly when a point is missing compare to the time serie', () => {
|
|
318
|
+
initialize({ data: dataMissingPoint });
|
|
319
|
+
|
|
320
|
+
cy.findByTestId('stacked-bar-2-0-139').should('be.visible');
|
|
321
|
+
|
|
322
|
+
cy.makeSnapshot();
|
|
323
|
+
});
|
|
315
324
|
});
|
|
@@ -6,6 +6,8 @@ import dataPingService from '../mockedData/pingService.json';
|
|
|
6
6
|
import dataPingServiceMixedStacked from '../mockedData/pingServiceMixedStacked.json';
|
|
7
7
|
import dataPingServiceStacked from '../mockedData/pingServiceStacked.json';
|
|
8
8
|
|
|
9
|
+
import { ClickAwayListener } from '@mui/material';
|
|
10
|
+
import { useState } from 'react';
|
|
9
11
|
import BarChart from './BarChart';
|
|
10
12
|
|
|
11
13
|
const meta: Meta<typeof BarChart> = {
|
|
@@ -259,4 +261,43 @@ export const mixedStackedMinMax: Story = {
|
|
|
259
261
|
max: 20
|
|
260
262
|
},
|
|
261
263
|
render: Template
|
|
262
|
-
};
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
const LegendSecondaryClick = (args) => {
|
|
267
|
+
const [position, setPosition] = useState<Array<[number, number]> | null>(
|
|
268
|
+
null
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
return (
|
|
272
|
+
<>
|
|
273
|
+
<Template
|
|
274
|
+
{...args}
|
|
275
|
+
legend={{
|
|
276
|
+
secondaryClick: ({ position }) => setPosition(position)
|
|
277
|
+
}}
|
|
278
|
+
/>
|
|
279
|
+
{position && (
|
|
280
|
+
<ClickAwayListener onClickAway={() => setPosition(null)}>
|
|
281
|
+
<div
|
|
282
|
+
className="absolute py-1 px-2 rounded-sm bg-background-widget shadow-md"
|
|
283
|
+
style={{ left: position?.[0], top: position?.[1] }}
|
|
284
|
+
open={Boolean(position)}
|
|
285
|
+
onClose={() => setPosition(null)}
|
|
286
|
+
>
|
|
287
|
+
menu
|
|
288
|
+
</div>
|
|
289
|
+
</ClickAwayListener>
|
|
290
|
+
)}
|
|
291
|
+
</>
|
|
292
|
+
);
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
export const withLegendSecondaryClick: Story = {
|
|
296
|
+
args: defaultArgs,
|
|
297
|
+
render: (args) => (
|
|
298
|
+
<LegendSecondaryClick
|
|
299
|
+
{...args}
|
|
300
|
+
data={dataPingService as unknown as LineChartData}
|
|
301
|
+
/>
|
|
302
|
+
)
|
|
303
|
+
};
|
|
@@ -196,7 +196,8 @@ const ResponsiveBarChart = ({
|
|
|
196
196
|
displayLegend,
|
|
197
197
|
mode: legend?.mode,
|
|
198
198
|
placement: legend?.placement,
|
|
199
|
-
renderExtraComponent: legend?.renderExtraComponent
|
|
199
|
+
renderExtraComponent: legend?.renderExtraComponent,
|
|
200
|
+
secondaryClick: legend?.secondaryClick
|
|
200
201
|
}}
|
|
201
202
|
legendRef={legendRef}
|
|
202
203
|
limitLegend={limitLegend}
|
|
@@ -180,7 +180,7 @@ describe('Line chart', () => {
|
|
|
180
180
|
cy.contains('06/18/2023').should('be.visible');
|
|
181
181
|
|
|
182
182
|
cy.contains('0.4 s').should('be.visible');
|
|
183
|
-
|
|
183
|
+
cy.contains('75.64%').should('be.visible');
|
|
184
184
|
|
|
185
185
|
cy.makeSnapshot();
|
|
186
186
|
});
|
|
@@ -532,7 +532,7 @@ describe('Line chart', () => {
|
|
|
532
532
|
|
|
533
533
|
checkGraphWidth();
|
|
534
534
|
cy.contains(':00 AM').should('be.visible');
|
|
535
|
-
cy.get('circle[cx="
|
|
535
|
+
cy.get('circle[cx="248.33333333333334"]').should('be.visible');
|
|
536
536
|
cy.get('circle[cy="251.79089393069725"]').should('be.visible');
|
|
537
537
|
|
|
538
538
|
cy.makeSnapshot();
|
|
@@ -591,7 +591,7 @@ describe('Line chart', () => {
|
|
|
591
591
|
cy.get('path.visx-area-closed')
|
|
592
592
|
.should('have.attr', 'stroke-dasharray')
|
|
593
593
|
.and('equals', '5 4');
|
|
594
|
-
cy.get('circle[cx="33.
|
|
594
|
+
cy.get('circle[cx="33.11111111111111"]').should('be.visible');
|
|
595
595
|
|
|
596
596
|
cy.makeSnapshot();
|
|
597
597
|
});
|
|
@@ -746,9 +746,11 @@ describe('Lines and bars', () => {
|
|
|
746
746
|
|
|
747
747
|
checkGraphWidth();
|
|
748
748
|
|
|
749
|
-
cy.get(
|
|
749
|
+
cy.get(
|
|
750
|
+
'path[d="M7.501377410468319,350.5553648585503 h56.51239669421488 h1v1 v23.44463514144968 a1,1 0 0 1 -1,1 h-56.51239669421488 a1,1 0 0 1 -1,-1 v-23.44463514144968 v-1h1z"]'
|
|
750
751
|
).should('be.visible');
|
|
751
|
-
cy.get(
|
|
752
|
+
cy.get(
|
|
753
|
+
'path[d="M24.05509641873278,201.58170928199803 h23.404958677685954 a17.553719008264462,17.553719008264462 0 0 1 17.553719008264462,17.553719008264462 v113.86621756002336 v17.553719008264462h-17.553719008264462 h-23.404958677685954 h-17.553719008264462v-17.553719008264462 v-113.86621756002336 a17.553719008264462,17.553719008264462 0 0 1 17.553719008264462,-17.553719008264462z"]'
|
|
752
754
|
).should('be.visible');
|
|
753
755
|
|
|
754
756
|
cy.makeSnapshot();
|
|
@@ -814,4 +816,21 @@ describe('Lines and bars', () => {
|
|
|
814
816
|
|
|
815
817
|
cy.makeSnapshot();
|
|
816
818
|
});
|
|
819
|
+
|
|
820
|
+
it('calls the secondary function when a metric is clicked in the legend', () => {
|
|
821
|
+
const secondaryClick = cy.stub().as('secondaryClick');
|
|
822
|
+
initialize({
|
|
823
|
+
data: dataPingServiceLines,
|
|
824
|
+
legend: {
|
|
825
|
+
mode: 'grid',
|
|
826
|
+
placement: 'bottom',
|
|
827
|
+
secondaryClick
|
|
828
|
+
}
|
|
829
|
+
});
|
|
830
|
+
|
|
831
|
+
checkGraphWidth();
|
|
832
|
+
|
|
833
|
+
cy.contains('Packet Loss').rightclick();
|
|
834
|
+
cy.get('@secondaryClick').should('have.been.called');
|
|
835
|
+
});
|
|
817
836
|
});
|
|
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { Meta, StoryObj } from '@storybook/react';
|
|
4
4
|
|
|
5
|
-
import { Button } from '@mui/material';
|
|
5
|
+
import { Button, Menu } from '@mui/material';
|
|
6
6
|
import ButtonGroup from '@mui/material/ButtonGroup';
|
|
7
7
|
import Switch from '@mui/material/Switch';
|
|
8
8
|
import Tooltip from '@mui/material/Tooltip';
|
|
@@ -758,3 +758,36 @@ export const linesAndBarsMinMaxForUnit: Story = {
|
|
|
758
758
|
/>
|
|
759
759
|
)
|
|
760
760
|
};
|
|
761
|
+
|
|
762
|
+
const LegendSecondaryClick = (args) => {
|
|
763
|
+
const [anchor, setAnchor] = useState<EventTarget | null>(null);
|
|
764
|
+
|
|
765
|
+
return (
|
|
766
|
+
<>
|
|
767
|
+
<WrapperChart
|
|
768
|
+
{...args}
|
|
769
|
+
legend={{
|
|
770
|
+
secondaryClick: ({ element }) => setAnchor(element)
|
|
771
|
+
}}
|
|
772
|
+
/>
|
|
773
|
+
<Menu
|
|
774
|
+
anchorEl={anchor}
|
|
775
|
+
open={Boolean(anchor)}
|
|
776
|
+
onClose={() => setAnchor(null)}
|
|
777
|
+
>
|
|
778
|
+
menu
|
|
779
|
+
</Menu>
|
|
780
|
+
</>
|
|
781
|
+
);
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
export const withLegendSecondaryClick: Story = {
|
|
785
|
+
argTypes,
|
|
786
|
+
args: argumentsData,
|
|
787
|
+
render: (args) => (
|
|
788
|
+
<LegendSecondaryClick
|
|
789
|
+
{...args}
|
|
790
|
+
data={dataPingService as unknown as LineChartData}
|
|
791
|
+
/>
|
|
792
|
+
)
|
|
793
|
+
};
|
|
@@ -277,7 +277,8 @@ const Chart = ({
|
|
|
277
277
|
legendHeight: legend?.height,
|
|
278
278
|
mode: legend?.mode,
|
|
279
279
|
placement: legend?.placement,
|
|
280
|
-
renderExtraComponent: legend?.renderExtraComponent
|
|
280
|
+
renderExtraComponent: legend?.renderExtraComponent,
|
|
281
|
+
secondaryClick: legend?.secondaryClick
|
|
281
282
|
}}
|
|
282
283
|
legendRef={legendRef}
|
|
283
284
|
limitLegend={limitLegend}
|
|
@@ -394,4 +395,4 @@ const Chart = ({
|
|
|
394
395
|
);
|
|
395
396
|
};
|
|
396
397
|
|
|
397
|
-
export default Chart;
|
|
398
|
+
export default Chart;
|
|
@@ -26,6 +26,11 @@ interface Props extends Pick<LegendModel, 'placement' | 'mode'> {
|
|
|
26
26
|
setLinesGraph: Dispatch<SetStateAction<Array<Line> | null>>;
|
|
27
27
|
shouldDisplayLegendInCompactMode: boolean;
|
|
28
28
|
toggable?: boolean;
|
|
29
|
+
secondaryClick?: (props: {
|
|
30
|
+
element: EventTarget | null;
|
|
31
|
+
metricId: number | string;
|
|
32
|
+
position: [number, number];
|
|
33
|
+
}) => void;
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
const MainLegend = ({
|
|
@@ -38,7 +43,8 @@ const MainLegend = ({
|
|
|
38
43
|
shouldDisplayLegendInCompactMode,
|
|
39
44
|
placement,
|
|
40
45
|
height,
|
|
41
|
-
mode
|
|
46
|
+
mode,
|
|
47
|
+
secondaryClick
|
|
42
48
|
}: Props): JSX.Element => {
|
|
43
49
|
const { classes, cx } = useStyles({
|
|
44
50
|
limitLegendRows: Boolean(limitLegend),
|
|
@@ -65,7 +71,24 @@ const MainLegend = ({
|
|
|
65
71
|
value
|
|
66
72
|
}) || 'N/A';
|
|
67
73
|
|
|
68
|
-
const
|
|
74
|
+
const contextMenuClick =
|
|
75
|
+
(metricId: number) =>
|
|
76
|
+
(event: MouseEvent): void => {
|
|
77
|
+
if (!secondaryClick) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
event.preventDefault();
|
|
81
|
+
secondaryClick({
|
|
82
|
+
element: event.target,
|
|
83
|
+
metricId,
|
|
84
|
+
position: [event.pageX, event.pageY]
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const selectMetric = ({
|
|
89
|
+
event,
|
|
90
|
+
metric_id
|
|
91
|
+
}: { event: MouseEvent; metric_id: number }): void => {
|
|
69
92
|
if (!toggable) {
|
|
70
93
|
return;
|
|
71
94
|
}
|
|
@@ -127,6 +150,7 @@ const MainLegend = ({
|
|
|
127
150
|
onClick={(event): void => selectMetric({ event, metric_id })}
|
|
128
151
|
onMouseEnter={(): void => highlightLine(metric_id)}
|
|
129
152
|
onMouseLeave={(): void => clearHighlight()}
|
|
153
|
+
onContextMenu={contextMenuClick(metric_id)}
|
|
130
154
|
>
|
|
131
155
|
<LegendHeader
|
|
132
156
|
color={markerColor}
|
|
@@ -175,6 +175,11 @@ export interface LegendModel {
|
|
|
175
175
|
mode: 'grid' | 'list';
|
|
176
176
|
placement: 'bottom' | 'left' | 'right';
|
|
177
177
|
renderExtraComponent?: ReactNode;
|
|
178
|
+
secondaryClick?: (props: {
|
|
179
|
+
element: EventTarget | null;
|
|
180
|
+
metricId: number | string;
|
|
181
|
+
position: [number, number];
|
|
182
|
+
}) => void;
|
|
178
183
|
}
|
|
179
184
|
|
|
180
185
|
export interface GetDate {
|
|
@@ -193,4 +198,4 @@ export interface GraphTooltipData {
|
|
|
193
198
|
unit: string;
|
|
194
199
|
value: number;
|
|
195
200
|
}>;
|
|
196
|
-
}
|
|
201
|
+
}
|
|
@@ -19,7 +19,10 @@ interface Props {
|
|
|
19
19
|
header?: LineChartHeader;
|
|
20
20
|
height: number | null;
|
|
21
21
|
isHorizontal?: boolean;
|
|
22
|
-
legend: Pick<
|
|
22
|
+
legend: Pick<
|
|
23
|
+
LegendModel,
|
|
24
|
+
'renderExtraComponent' | 'placement' | 'mode' | 'secondaryClick'
|
|
25
|
+
> & {
|
|
23
26
|
displayLegend: boolean;
|
|
24
27
|
legendHeight?: number;
|
|
25
28
|
};
|
|
@@ -101,6 +104,7 @@ const BaseChart = ({
|
|
|
101
104
|
shouldDisplayLegendInCompactMode={
|
|
102
105
|
shouldDisplayLegendInCompactMode
|
|
103
106
|
}
|
|
107
|
+
secondaryClick={legend?.secondaryClick}
|
|
104
108
|
/>
|
|
105
109
|
</div>
|
|
106
110
|
)}
|
|
@@ -122,6 +126,7 @@ const BaseChart = ({
|
|
|
122
126
|
renderExtraComponent={legend.renderExtraComponent}
|
|
123
127
|
setLinesGraph={setLines}
|
|
124
128
|
shouldDisplayLegendInCompactMode={shouldDisplayLegendInCompactMode}
|
|
129
|
+
secondaryClick={legend?.secondaryClick}
|
|
125
130
|
/>
|
|
126
131
|
</div>
|
|
127
132
|
)}
|
|
@@ -72,7 +72,7 @@ const toTimeTickValue = (
|
|
|
72
72
|
const getMetricsForIndex = (): Omit<TimeValue, 'timeTick'> => {
|
|
73
73
|
const addMetricForTimeIndex = (acc, { metric_id, data }): TimeValue => ({
|
|
74
74
|
...acc,
|
|
75
|
-
[metric_id]: data[timeIndex]
|
|
75
|
+
[metric_id]: data[timeIndex] === undefined ? null : data[timeIndex]
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
return reduce(addMetricForTimeIndex, {} as TimeValue, metrics);
|
|
@@ -240,7 +240,10 @@ const getStackedMetricValues = ({
|
|
|
240
240
|
timeSeries
|
|
241
241
|
}: LinesTimeSeries): Array<number> => {
|
|
242
242
|
const getTimeSeriesValuesForMetric = (metric_id): Array<number> =>
|
|
243
|
-
map(
|
|
243
|
+
map(
|
|
244
|
+
(timeValue) => getValueForMetric(timeValue)(metric_id) || 0,
|
|
245
|
+
timeSeries
|
|
246
|
+
);
|
|
244
247
|
|
|
245
248
|
const metricsValues = pipe(
|
|
246
249
|
map(prop('metric_id')) as (metric) => Array<number>,
|
|
@@ -593,15 +596,15 @@ const getYScalePerUnit = ({
|
|
|
593
596
|
return scalePerUnit;
|
|
594
597
|
};
|
|
595
598
|
|
|
596
|
-
const formatTime = (value
|
|
597
|
-
return `${numeral(value).format('0.[00]a')}
|
|
599
|
+
const formatTime = ({ value, unit }): string => {
|
|
600
|
+
return `${numeral(value).format('0.[00]a')} ${unit}`;
|
|
598
601
|
};
|
|
599
602
|
|
|
600
603
|
const registerMsUnitToNumeral = (): null => {
|
|
601
604
|
try {
|
|
602
605
|
numeral.register('format', 'milliseconds', {
|
|
603
606
|
format: (value) => {
|
|
604
|
-
return formatTime(value);
|
|
607
|
+
return formatTime({ value, unit: 'ms' });
|
|
605
608
|
},
|
|
606
609
|
regexps: {
|
|
607
610
|
format: /(ms)/,
|
|
@@ -618,6 +621,27 @@ const registerMsUnitToNumeral = (): null => {
|
|
|
618
621
|
|
|
619
622
|
registerMsUnitToNumeral();
|
|
620
623
|
|
|
624
|
+
const registerSecondsUnitToNumeral = (): null => {
|
|
625
|
+
try {
|
|
626
|
+
numeral.register('format', 'seconds', {
|
|
627
|
+
format: (value) => {
|
|
628
|
+
return formatTime({ value, unit: 's' });
|
|
629
|
+
},
|
|
630
|
+
regexps: {
|
|
631
|
+
format: /(s)/,
|
|
632
|
+
unformat: /(s)/
|
|
633
|
+
},
|
|
634
|
+
unformat: () => ''
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
return null;
|
|
638
|
+
} catch (_) {
|
|
639
|
+
return null;
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
registerSecondsUnitToNumeral();
|
|
644
|
+
|
|
621
645
|
const getBase1024 = ({ unit, base }): boolean => {
|
|
622
646
|
const base2Units = [
|
|
623
647
|
'B',
|
|
@@ -647,6 +671,7 @@ const formatMetricValue = ({
|
|
|
647
671
|
|
|
648
672
|
const formatSuffix = cond([
|
|
649
673
|
[equals('ms'), always(' ms')],
|
|
674
|
+
[equals('s'), always(' s')],
|
|
650
675
|
[T, always(base1024 ? ' ib' : 'a')]
|
|
651
676
|
])(unit);
|
|
652
677
|
|
|
@@ -671,8 +696,6 @@ const formatMetricValueWithUnit = ({
|
|
|
671
696
|
return null;
|
|
672
697
|
}
|
|
673
698
|
|
|
674
|
-
const base1024 = getBase1024({ base, unit });
|
|
675
|
-
|
|
676
699
|
if (isRaw) {
|
|
677
700
|
const unitText = equals('%', unit) ? unit : ` ${unit}`;
|
|
678
701
|
|
|
@@ -685,9 +708,7 @@ const formatMetricValueWithUnit = ({
|
|
|
685
708
|
|
|
686
709
|
const formattedMetricValue = formatMetricValue({ base, unit, value });
|
|
687
710
|
|
|
688
|
-
return
|
|
689
|
-
? formattedMetricValue
|
|
690
|
-
: `${formattedMetricValue} ${unit}`;
|
|
711
|
+
return formattedMetricValue;
|
|
691
712
|
};
|
|
692
713
|
|
|
693
714
|
const bisectDate = bisector(identity).center;
|
|
@@ -766,4 +787,4 @@ export {
|
|
|
766
787
|
formatMetricValueWithUnit,
|
|
767
788
|
getYScaleUnit,
|
|
768
789
|
getYScalePerUnit
|
|
769
|
-
};
|
|
790
|
+
};
|
|
@@ -25,7 +25,7 @@ import { BarStyle } from '../BarChart/models';
|
|
|
25
25
|
import { margin } from '../Chart/common';
|
|
26
26
|
import { LineStyle } from '../Chart/models';
|
|
27
27
|
import { Threshold, Thresholds } from './models';
|
|
28
|
-
import {
|
|
28
|
+
import { formatMetricValueWithUnit } from './timeSeries';
|
|
29
29
|
import { Line, TimeValue } from './timeSeries/models';
|
|
30
30
|
|
|
31
31
|
interface GetColorFromDataAndThresholdsProps {
|
|
@@ -234,7 +234,7 @@ export const getFormattedAxisValues = ({
|
|
|
234
234
|
|
|
235
235
|
const formattedData = metricIds.map((metricId) =>
|
|
236
236
|
timeSeries.map((data) =>
|
|
237
|
-
|
|
237
|
+
formatMetricValueWithUnit({
|
|
238
238
|
value: data[metricId],
|
|
239
239
|
unit: axisUnit,
|
|
240
240
|
base
|
|
@@ -246,7 +246,7 @@ export const getFormattedAxisValues = ({
|
|
|
246
246
|
|
|
247
247
|
const formattedThresholdValues = equals(thresholdUnit, axisUnit)
|
|
248
248
|
? threshold.map(({ value }) =>
|
|
249
|
-
|
|
249
|
+
formatMetricValueWithUnit({
|
|
250
250
|
value,
|
|
251
251
|
unit: axisUnit,
|
|
252
252
|
base
|
|
@@ -273,5 +273,11 @@ export const computeGElementMarginLeft = ({
|
|
|
273
273
|
export const computPixelsToShiftMouse = (xScale): number => {
|
|
274
274
|
const domain = xScale.domain();
|
|
275
275
|
|
|
276
|
-
|
|
276
|
+
const hoursDiffInGraph = dayjs(domain[1]).diff(domain[0], 'h');
|
|
277
|
+
|
|
278
|
+
if (!hoursDiffInGraph) {
|
|
279
|
+
return 0;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return Math.round(8 / hoursDiffInGraph);
|
|
277
283
|
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"global": {},
|
|
3
|
+
"metrics": [
|
|
4
|
+
{
|
|
5
|
+
"metric": "count",
|
|
6
|
+
"metric_id": 1,
|
|
7
|
+
"legend": "count",
|
|
8
|
+
"displayAs": "bar",
|
|
9
|
+
"ds_data": {
|
|
10
|
+
"ds_stack": true,
|
|
11
|
+
"ds_transparency": 0,
|
|
12
|
+
"ds_filled": false,
|
|
13
|
+
"ds_color_area": "#4269d0",
|
|
14
|
+
"ds_color_line": "#4269d0"
|
|
15
|
+
},
|
|
16
|
+
"datasourceOptions": {
|
|
17
|
+
"field": null,
|
|
18
|
+
"group_by": null,
|
|
19
|
+
"op": "count-doc",
|
|
20
|
+
"query": "severity_text:\"Fatal\" OR severity_text:\"Error\"",
|
|
21
|
+
"period": 3600
|
|
22
|
+
},
|
|
23
|
+
"data": [
|
|
24
|
+
217, 270, 293, 300, 303, 295, 298, 283, 299, 299, 297, 285, 270, 248,
|
|
25
|
+
274, 292, 284, 47
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"metric": "count",
|
|
30
|
+
"metric_id": 2,
|
|
31
|
+
"legend": "count",
|
|
32
|
+
"displayAs": "bar",
|
|
33
|
+
"ds_data": {
|
|
34
|
+
"ds_stack": true,
|
|
35
|
+
"ds_transparency": 0,
|
|
36
|
+
"ds_filled": false,
|
|
37
|
+
"ds_color_area": "#efb118",
|
|
38
|
+
"ds_color_line": "#efb118"
|
|
39
|
+
},
|
|
40
|
+
"datasourceOptions": {
|
|
41
|
+
"field": null,
|
|
42
|
+
"group_by": null,
|
|
43
|
+
"op": "count-doc",
|
|
44
|
+
"query": "",
|
|
45
|
+
"period": 3600
|
|
46
|
+
},
|
|
47
|
+
"data": [
|
|
48
|
+
32, 825, 939, 922, 918, 939, 943, 947, 946, 909, 931, 939, 883, 907,
|
|
49
|
+
928, 904, 923, 893, 139
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"times": [
|
|
54
|
+
"2025-10-04T16:19:30.000Z",
|
|
55
|
+
"2025-10-04T16:20:00.000Z",
|
|
56
|
+
"2025-10-04T16:20:30.000Z",
|
|
57
|
+
"2025-10-04T16:21:00.000Z",
|
|
58
|
+
"2025-10-04T16:21:30.000Z",
|
|
59
|
+
"2025-10-04T16:22:00.000Z",
|
|
60
|
+
"2025-10-04T16:22:30.000Z",
|
|
61
|
+
"2025-10-04T16:23:00.000Z",
|
|
62
|
+
"2025-10-04T16:23:30.000Z",
|
|
63
|
+
"2025-10-04T16:24:00.000Z",
|
|
64
|
+
"2025-10-04T16:24:30.000Z",
|
|
65
|
+
"2025-10-04T16:25:00.000Z",
|
|
66
|
+
"2025-10-04T16:25:30.000Z",
|
|
67
|
+
"2025-10-04T16:26:00.000Z",
|
|
68
|
+
"2025-10-04T16:26:30.000Z",
|
|
69
|
+
"2025-10-04T16:27:00.000Z",
|
|
70
|
+
"2025-10-04T16:27:30.000Z",
|
|
71
|
+
"2025-10-04T16:28:00.000Z",
|
|
72
|
+
"2025-10-04T16:28:30.000Z"
|
|
73
|
+
]
|
|
74
|
+
}
|
|
@@ -96,7 +96,6 @@ const SelectField = ({
|
|
|
96
96
|
fullWidth={fullWidth}
|
|
97
97
|
size="small"
|
|
98
98
|
{...formControlProps}
|
|
99
|
-
|
|
100
99
|
>
|
|
101
100
|
{label && <InputLabel>{label}</InputLabel>}
|
|
102
101
|
<Select
|
|
@@ -151,4 +150,4 @@ const SelectField = ({
|
|
|
151
150
|
);
|
|
152
151
|
};
|
|
153
152
|
|
|
154
|
-
export default SelectField;
|
|
153
|
+
export default SelectField;
|
package/src/Module/index.tsx
CHANGED
|
@@ -3,9 +3,9 @@ import { Provider as JotaiProvider, createStore } from 'jotai';
|
|
|
3
3
|
|
|
4
4
|
import { StylesProvider, createGenerateClassName } from '@mui/styles';
|
|
5
5
|
|
|
6
|
+
import { ThemeOptions } from '@mui/material';
|
|
6
7
|
import { QueryProvider, ThemeProvider } from '..';
|
|
7
8
|
import SnackbarProvider from '../Snackbar/SnackbarProvider';
|
|
8
|
-
import { ThemeOptions } from '@mui/material';
|
|
9
9
|
|
|
10
10
|
export interface ModuleProps {
|
|
11
11
|
children: React.ReactElement;
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
/* =============
|
|
26
26
|
COLOR SYSTEM
|
|
27
27
|
============= */
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
/* Action colors */
|
|
30
30
|
--color-action-acknowledged: #745f35;
|
|
31
31
|
--color-action-acknowledged-background: #dfd2b9;
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
--color-action-in-downtime-background: #e5d8f3;
|
|
44
44
|
--color-action-selected: rgba(102, 102, 102, 0.3);
|
|
45
45
|
--color-action-selected-opacity: 0.3;
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
/* Background colors */
|
|
48
48
|
--color-background-default: #f4f4f4;
|
|
49
49
|
--color-background-listing-header: #666666;
|
|
@@ -52,18 +52,18 @@
|
|
|
52
52
|
--color-background-paper: #ffffff;
|
|
53
53
|
--color-background-tooltip: #434e58;
|
|
54
54
|
--color-background-widget: #f8f8f8;
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
/* Chip colors */
|
|
57
57
|
--color-chip-error: #ff6666;
|
|
58
58
|
--color-chip-info: #1588d1;
|
|
59
59
|
--color-chip-neutral: #6da4e4;
|
|
60
60
|
--color-chip-success: #88b922;
|
|
61
61
|
--color-chip-warning: #fd9b27;
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
/* Utility colors */
|
|
64
64
|
--color-divider: #e3e3e3;
|
|
65
65
|
--color-error-main: #ff4a4a;
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
/* Header colors */
|
|
68
68
|
--color-header-page-action-background-active: #1975d10f;
|
|
69
69
|
--color-header-page-action-background-default: #ffffff00;
|
|
@@ -90,10 +90,10 @@
|
|
|
90
90
|
--color-header-menu-item-color-active: #3e85d5;
|
|
91
91
|
--color-header-menu-item-color-default: #1b2127;
|
|
92
92
|
--color-header-menu-item-color-hover: #101418;
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
/* State colors */
|
|
95
95
|
--color-pending-main: #1ebeb3;
|
|
96
|
-
|
|
96
|
+
|
|
97
97
|
/* Primary & Secondary colors */
|
|
98
98
|
--color-primary-main: #2e68aa;
|
|
99
99
|
--color-primary-light: #cde7fc;
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
--color-secondary-main: #c772d6;
|
|
102
102
|
--color-secondary-light: #e5a5f0;
|
|
103
103
|
--color-secondary-dark: #ac28c1;
|
|
104
|
-
|
|
104
|
+
|
|
105
105
|
/* Status colors */
|
|
106
106
|
--color-status-background-error: #ff6666;
|
|
107
107
|
--color-status-background-none: --alpha(#2e68aa / 10%);
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
--color-stauts-background-unknown: #e3e3e3;
|
|
111
111
|
--color-status-background-warning: #fd9b27;
|
|
112
112
|
--color-success-main: #88b922;
|
|
113
|
-
|
|
113
|
+
|
|
114
114
|
/* Text colors */
|
|
115
115
|
--color-text-disabled: #999999;
|
|
116
116
|
--color-text-primary: #000000;
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
--color-warning-main: #fd9b27;
|
|
119
119
|
--color-warning-light: #fcc481;
|
|
120
120
|
--color-warning-dark: #fc7e00;
|
|
121
|
-
|
|
121
|
+
|
|
122
122
|
/* Base colors */
|
|
123
123
|
--color-white: #ffffff;
|
|
124
124
|
--color-black: #000000;
|
|
@@ -103,7 +103,7 @@ const useGraphQuery = ({
|
|
|
103
103
|
refreshCount,
|
|
104
104
|
bypassQueryParams = false,
|
|
105
105
|
prefix,
|
|
106
|
-
isEnabled=true
|
|
106
|
+
isEnabled = true
|
|
107
107
|
}: UseMetricsQueryProps): UseMetricsQueryState => {
|
|
108
108
|
const timePeriodToUse = equals(timePeriod?.timePeriodType, -1)
|
|
109
109
|
? {
|
|
@@ -160,7 +160,10 @@ const useGraphQuery = ({
|
|
|
160
160
|
refreshCount || 0
|
|
161
161
|
],
|
|
162
162
|
queryOptions: {
|
|
163
|
-
enabled:
|
|
163
|
+
enabled:
|
|
164
|
+
areResourcesFullfilled(resources) &&
|
|
165
|
+
!isEmpty(definedMetrics) &&
|
|
166
|
+
isEnabled,
|
|
164
167
|
refetchInterval: refreshInterval,
|
|
165
168
|
suspense: false
|
|
166
169
|
},
|
|
@@ -16,7 +16,11 @@ const ModalHeader = ({
|
|
|
16
16
|
}: ModalHeaderProps & DialogTitleProps): ReactElement => {
|
|
17
17
|
return (
|
|
18
18
|
<div className={modalHeader}>
|
|
19
|
-
<MuiDialogTitle
|
|
19
|
+
<MuiDialogTitle
|
|
20
|
+
className="p-0 font-bold text-2xl"
|
|
21
|
+
color="primary"
|
|
22
|
+
{...rest}
|
|
23
|
+
>
|
|
20
24
|
{children}
|
|
21
25
|
</MuiDialogTitle>
|
|
22
26
|
</div>
|