@centreon/ui 25.10.1 → 25.10.2
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/public/mockServiceWorker.js +8 -31
- package/src/Form/Inputs/Grid.tsx +2 -3
- package/src/Form/Section/navigateToSection.ts +6 -6
- package/src/Graph/BarChart/BarChart.cypress.spec.tsx +0 -9
- package/src/Graph/BarChart/BarChart.stories.tsx +1 -42
- package/src/Graph/BarChart/BarChart.tsx +1 -1
- package/src/Graph/BarChart/ResponsiveBarChart.tsx +1 -2
- package/src/Graph/Chart/Chart.cypress.spec.tsx +5 -24
- package/src/Graph/Chart/Chart.stories.tsx +1 -34
- package/src/Graph/Chart/Chart.tsx +2 -3
- package/src/Graph/Chart/Legend/index.tsx +2 -26
- package/src/Graph/Chart/models.ts +1 -6
- package/src/Graph/Chart/useChartData.ts +1 -1
- package/src/Graph/common/BaseChart/BaseChart.tsx +1 -6
- package/src/Graph/common/BaseChart/Header/index.tsx +3 -1
- package/src/Graph/common/timeSeries/index.ts +11 -32
- package/src/Graph/common/utils.ts +4 -10
- package/src/Graph/index.ts +1 -0
- package/src/InputField/Select/index.tsx +2 -1
- package/src/Module/index.tsx +2 -8
- package/src/ThemeProvider/index.tsx +21 -30
- package/src/ThemeProvider/tailwindcss.css +10 -10
- package/src/components/Modal/Modal.styles.ts +2 -1
- package/src/components/Modal/ModalHeader.tsx +1 -5
- package/src/Graph/mockedData/dataWithMissingPoint.json +0 -74
package/package.json
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* - Please do NOT serve this file on production.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
const PACKAGE_VERSION = '2.
|
|
12
|
-
const INTEGRITY_CHECKSUM = '
|
|
11
|
+
const PACKAGE_VERSION = '2.2.14'
|
|
12
|
+
const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423'
|
|
13
13
|
const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
|
|
14
14
|
const activeClientIds = new Set()
|
|
15
15
|
|
|
@@ -62,12 +62,7 @@ self.addEventListener('message', async function (event) {
|
|
|
62
62
|
|
|
63
63
|
sendToClient(client, {
|
|
64
64
|
type: 'MOCKING_ENABLED',
|
|
65
|
-
payload:
|
|
66
|
-
client: {
|
|
67
|
-
id: client.id,
|
|
68
|
-
frameType: client.frameType,
|
|
69
|
-
},
|
|
70
|
-
},
|
|
65
|
+
payload: true,
|
|
71
66
|
})
|
|
72
67
|
break
|
|
73
68
|
}
|
|
@@ -160,10 +155,6 @@ async function handleRequest(event, requestId) {
|
|
|
160
155
|
async function resolveMainClient(event) {
|
|
161
156
|
const client = await self.clients.get(event.clientId)
|
|
162
157
|
|
|
163
|
-
if (activeClientIds.has(event.clientId)) {
|
|
164
|
-
return client
|
|
165
|
-
}
|
|
166
|
-
|
|
167
158
|
if (client?.frameType === 'top-level') {
|
|
168
159
|
return client
|
|
169
160
|
}
|
|
@@ -192,26 +183,12 @@ async function getResponse(event, client, requestId) {
|
|
|
192
183
|
const requestClone = request.clone()
|
|
193
184
|
|
|
194
185
|
function passthrough() {
|
|
195
|
-
|
|
196
|
-
// so the headers can be manipulated with.
|
|
197
|
-
const headers = new Headers(requestClone.headers)
|
|
198
|
-
|
|
199
|
-
// Remove the "accept" header value that marked this request as passthrough.
|
|
200
|
-
// This prevents request alteration and also keeps it compliant with the
|
|
201
|
-
// user-defined CORS policies.
|
|
202
|
-
const acceptHeader = headers.get('accept')
|
|
203
|
-
if (acceptHeader) {
|
|
204
|
-
const values = acceptHeader.split(',').map((value) => value.trim())
|
|
205
|
-
const filteredValues = values.filter(
|
|
206
|
-
(value) => value !== 'msw/passthrough',
|
|
207
|
-
)
|
|
186
|
+
const headers = Object.fromEntries(requestClone.headers.entries())
|
|
208
187
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
}
|
|
188
|
+
// Remove internal MSW request header so the passthrough request
|
|
189
|
+
// complies with any potential CORS preflight checks on the server.
|
|
190
|
+
// Some servers forbid unknown request headers.
|
|
191
|
+
delete headers['x-msw-intention']
|
|
215
192
|
|
|
216
193
|
return fetch(requestClone, { headers })
|
|
217
194
|
}
|
package/src/Form/Inputs/Grid.tsx
CHANGED
|
@@ -21,9 +21,8 @@ const Grid = ({
|
|
|
21
21
|
<div
|
|
22
22
|
className={`${className} grid gap-3`}
|
|
23
23
|
style={{
|
|
24
|
-
gridTemplateColumns:
|
|
25
|
-
? grid?.gridTemplateColumns || undefined
|
|
26
|
-
: grid?.gridTemplateColumns ||
|
|
24
|
+
gridTemplateColumns:
|
|
25
|
+
className ? grid?.gridTemplateColumns || undefined : grid?.gridTemplateColumns ||
|
|
27
26
|
`repeat(${grid?.columns.length || 1}, 1fr)`,
|
|
28
27
|
alignItems: grid?.alignItems || 'flex-start'
|
|
29
28
|
}}
|
|
@@ -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,7 +8,6 @@ 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';
|
|
12
11
|
|
|
13
12
|
import BarChart, { BarChartProps } from './BarChart';
|
|
14
13
|
|
|
@@ -313,12 +312,4 @@ describe('Bar chart', () => {
|
|
|
313
312
|
cy.contains('1 s').should('be.visible');
|
|
314
313
|
cy.contains('1%').should('be.visible');
|
|
315
314
|
});
|
|
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
|
-
});
|
|
324
315
|
});
|
|
@@ -6,8 +6,6 @@ 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';
|
|
11
9
|
import BarChart from './BarChart';
|
|
12
10
|
|
|
13
11
|
const meta: Meta<typeof BarChart> = {
|
|
@@ -261,43 +259,4 @@ export const mixedStackedMinMax: Story = {
|
|
|
261
259
|
max: 20
|
|
262
260
|
},
|
|
263
261
|
render: Template
|
|
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
|
-
};
|
|
262
|
+
};
|
|
@@ -196,8 +196,7 @@ const ResponsiveBarChart = ({
|
|
|
196
196
|
displayLegend,
|
|
197
197
|
mode: legend?.mode,
|
|
198
198
|
placement: legend?.placement,
|
|
199
|
-
renderExtraComponent: legend?.renderExtraComponent
|
|
200
|
-
secondaryClick: legend?.secondaryClick
|
|
199
|
+
renderExtraComponent: legend?.renderExtraComponent
|
|
201
200
|
}}
|
|
202
201
|
legendRef={legendRef}
|
|
203
202
|
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="250.83333333333334"]').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.44444444444444"]').should('be.visible');
|
|
595
595
|
|
|
596
596
|
cy.makeSnapshot();
|
|
597
597
|
});
|
|
@@ -746,11 +746,9 @@ describe('Lines and bars', () => {
|
|
|
746
746
|
|
|
747
747
|
checkGraphWidth();
|
|
748
748
|
|
|
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"]'
|
|
749
|
+
cy.get('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"]'
|
|
751
750
|
).should('be.visible');
|
|
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"]'
|
|
751
|
+
cy.get('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"]'
|
|
754
752
|
).should('be.visible');
|
|
755
753
|
|
|
756
754
|
cy.makeSnapshot();
|
|
@@ -816,21 +814,4 @@ describe('Lines and bars', () => {
|
|
|
816
814
|
|
|
817
815
|
cy.makeSnapshot();
|
|
818
816
|
});
|
|
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
|
-
});
|
|
836
817
|
});
|
|
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { Meta, StoryObj } from '@storybook/react';
|
|
4
4
|
|
|
5
|
-
import { Button
|
|
5
|
+
import { Button } 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,36 +758,3 @@ 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,8 +277,7 @@ const Chart = ({
|
|
|
277
277
|
legendHeight: legend?.height,
|
|
278
278
|
mode: legend?.mode,
|
|
279
279
|
placement: legend?.placement,
|
|
280
|
-
renderExtraComponent: legend?.renderExtraComponent
|
|
281
|
-
secondaryClick: legend?.secondaryClick
|
|
280
|
+
renderExtraComponent: legend?.renderExtraComponent
|
|
282
281
|
}}
|
|
283
282
|
legendRef={legendRef}
|
|
284
283
|
limitLegend={limitLegend}
|
|
@@ -395,4 +394,4 @@ const Chart = ({
|
|
|
395
394
|
);
|
|
396
395
|
};
|
|
397
396
|
|
|
398
|
-
export default Chart;
|
|
397
|
+
export default Chart;
|
|
@@ -26,11 +26,6 @@ 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;
|
|
34
29
|
}
|
|
35
30
|
|
|
36
31
|
const MainLegend = ({
|
|
@@ -43,8 +38,7 @@ const MainLegend = ({
|
|
|
43
38
|
shouldDisplayLegendInCompactMode,
|
|
44
39
|
placement,
|
|
45
40
|
height,
|
|
46
|
-
mode
|
|
47
|
-
secondaryClick
|
|
41
|
+
mode
|
|
48
42
|
}: Props): JSX.Element => {
|
|
49
43
|
const { classes, cx } = useStyles({
|
|
50
44
|
limitLegendRows: Boolean(limitLegend),
|
|
@@ -71,24 +65,7 @@ const MainLegend = ({
|
|
|
71
65
|
value
|
|
72
66
|
}) || 'N/A';
|
|
73
67
|
|
|
74
|
-
const
|
|
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 => {
|
|
68
|
+
const selectMetric = ({ event, metric_id }): void => {
|
|
92
69
|
if (!toggable) {
|
|
93
70
|
return;
|
|
94
71
|
}
|
|
@@ -150,7 +127,6 @@ const MainLegend = ({
|
|
|
150
127
|
onClick={(event): void => selectMetric({ event, metric_id })}
|
|
151
128
|
onMouseEnter={(): void => highlightLine(metric_id)}
|
|
152
129
|
onMouseLeave={(): void => clearHighlight()}
|
|
153
|
-
onContextMenu={contextMenuClick(metric_id)}
|
|
154
130
|
>
|
|
155
131
|
<LegendHeader
|
|
156
132
|
color={markerColor}
|
|
@@ -175,11 +175,6 @@ 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;
|
|
183
178
|
}
|
|
184
179
|
|
|
185
180
|
export interface GetDate {
|
|
@@ -198,4 +193,4 @@ export interface GraphTooltipData {
|
|
|
198
193
|
unit: string;
|
|
199
194
|
value: number;
|
|
200
195
|
}>;
|
|
201
|
-
}
|
|
196
|
+
}
|
|
@@ -19,10 +19,7 @@ interface Props {
|
|
|
19
19
|
header?: LineChartHeader;
|
|
20
20
|
height: number | null;
|
|
21
21
|
isHorizontal?: boolean;
|
|
22
|
-
legend: Pick<
|
|
23
|
-
LegendModel,
|
|
24
|
-
'renderExtraComponent' | 'placement' | 'mode' | 'secondaryClick'
|
|
25
|
-
> & {
|
|
22
|
+
legend: Pick<LegendModel, 'renderExtraComponent' | 'placement' | 'mode'> & {
|
|
26
23
|
displayLegend: boolean;
|
|
27
24
|
legendHeight?: number;
|
|
28
25
|
};
|
|
@@ -104,7 +101,6 @@ const BaseChart = ({
|
|
|
104
101
|
shouldDisplayLegendInCompactMode={
|
|
105
102
|
shouldDisplayLegendInCompactMode
|
|
106
103
|
}
|
|
107
|
-
secondaryClick={legend?.secondaryClick}
|
|
108
104
|
/>
|
|
109
105
|
</div>
|
|
110
106
|
)}
|
|
@@ -126,7 +122,6 @@ const BaseChart = ({
|
|
|
126
122
|
renderExtraComponent={legend.renderExtraComponent}
|
|
127
123
|
setLinesGraph={setLines}
|
|
128
124
|
shouldDisplayLegendInCompactMode={shouldDisplayLegendInCompactMode}
|
|
129
|
-
secondaryClick={legend?.secondaryClick}
|
|
130
125
|
/>
|
|
131
126
|
</div>
|
|
132
127
|
)}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
|
|
1
3
|
import Typography from '@mui/material/Typography';
|
|
2
4
|
|
|
3
5
|
import { useMemoComponent } from '@centreon/ui';
|
|
@@ -10,7 +12,7 @@ interface Props {
|
|
|
10
12
|
title: string;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
|
-
const Header = ({ title, header }: Props):
|
|
15
|
+
const Header = ({ title, header }: Props): ReactElement => {
|
|
14
16
|
const { classes } = ussHeaderChartStyles();
|
|
15
17
|
|
|
16
18
|
const displayTitle = header?.displayTitle ?? true;
|
|
@@ -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]
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
return reduce(addMetricForTimeIndex, {} as TimeValue, metrics);
|
|
@@ -240,10 +240,7 @@ const getStackedMetricValues = ({
|
|
|
240
240
|
timeSeries
|
|
241
241
|
}: LinesTimeSeries): Array<number> => {
|
|
242
242
|
const getTimeSeriesValuesForMetric = (metric_id): Array<number> =>
|
|
243
|
-
map(
|
|
244
|
-
(timeValue) => getValueForMetric(timeValue)(metric_id) || 0,
|
|
245
|
-
timeSeries
|
|
246
|
-
);
|
|
243
|
+
map((timeValue) => getValueForMetric(timeValue)(metric_id), timeSeries);
|
|
247
244
|
|
|
248
245
|
const metricsValues = pipe(
|
|
249
246
|
map(prop('metric_id')) as (metric) => Array<number>,
|
|
@@ -596,15 +593,15 @@ const getYScalePerUnit = ({
|
|
|
596
593
|
return scalePerUnit;
|
|
597
594
|
};
|
|
598
595
|
|
|
599
|
-
const formatTime = (
|
|
600
|
-
return `${numeral(value).format('0.[00]a')}
|
|
596
|
+
const formatTime = (value: number): string => {
|
|
597
|
+
return `${numeral(value).format('0.[00]a')} ms`;
|
|
601
598
|
};
|
|
602
599
|
|
|
603
600
|
const registerMsUnitToNumeral = (): null => {
|
|
604
601
|
try {
|
|
605
602
|
numeral.register('format', 'milliseconds', {
|
|
606
603
|
format: (value) => {
|
|
607
|
-
return formatTime(
|
|
604
|
+
return formatTime(value);
|
|
608
605
|
},
|
|
609
606
|
regexps: {
|
|
610
607
|
format: /(ms)/,
|
|
@@ -621,27 +618,6 @@ const registerMsUnitToNumeral = (): null => {
|
|
|
621
618
|
|
|
622
619
|
registerMsUnitToNumeral();
|
|
623
620
|
|
|
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
|
-
|
|
645
621
|
const getBase1024 = ({ unit, base }): boolean => {
|
|
646
622
|
const base2Units = [
|
|
647
623
|
'B',
|
|
@@ -671,7 +647,6 @@ const formatMetricValue = ({
|
|
|
671
647
|
|
|
672
648
|
const formatSuffix = cond([
|
|
673
649
|
[equals('ms'), always(' ms')],
|
|
674
|
-
[equals('s'), always(' s')],
|
|
675
650
|
[T, always(base1024 ? ' ib' : 'a')]
|
|
676
651
|
])(unit);
|
|
677
652
|
|
|
@@ -696,6 +671,8 @@ const formatMetricValueWithUnit = ({
|
|
|
696
671
|
return null;
|
|
697
672
|
}
|
|
698
673
|
|
|
674
|
+
const base1024 = getBase1024({ base, unit });
|
|
675
|
+
|
|
699
676
|
if (isRaw) {
|
|
700
677
|
const unitText = equals('%', unit) ? unit : ` ${unit}`;
|
|
701
678
|
|
|
@@ -708,7 +685,9 @@ const formatMetricValueWithUnit = ({
|
|
|
708
685
|
|
|
709
686
|
const formattedMetricValue = formatMetricValue({ base, unit, value });
|
|
710
687
|
|
|
711
|
-
return
|
|
688
|
+
return base1024 || !unit || equals(unit, 'ms')
|
|
689
|
+
? formattedMetricValue
|
|
690
|
+
: `${formattedMetricValue} ${unit}`;
|
|
712
691
|
};
|
|
713
692
|
|
|
714
693
|
const bisectDate = bisector(identity).center;
|
|
@@ -787,4 +766,4 @@ export {
|
|
|
787
766
|
formatMetricValueWithUnit,
|
|
788
767
|
getYScaleUnit,
|
|
789
768
|
getYScalePerUnit
|
|
790
|
-
};
|
|
769
|
+
};
|
|
@@ -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 { formatMetricValue } 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
|
+
formatMetricValue({
|
|
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
|
+
formatMetricValue({
|
|
250
250
|
value,
|
|
251
251
|
unit: axisUnit,
|
|
252
252
|
base
|
|
@@ -273,11 +273,5 @@ export const computeGElementMarginLeft = ({
|
|
|
273
273
|
export const computPixelsToShiftMouse = (xScale): number => {
|
|
274
274
|
const domain = xScale.domain();
|
|
275
275
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
if (!hoursDiffInGraph) {
|
|
279
|
-
return 0;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
return Math.round(8 / hoursDiffInGraph);
|
|
276
|
+
return Math.round(8 / dayjs(domain[1]).diff(domain[0], 'h'));
|
|
283
277
|
};
|
package/src/Graph/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { default as BarChart } from './BarChart/BarChart';
|
|
|
6
6
|
export { Gauge } from './Gauge';
|
|
7
7
|
export { SingleBar } from './SingleBar';
|
|
8
8
|
export { Text as GraphText } from './Text';
|
|
9
|
+
export { default as Header } from './common/BaseChart/Header';
|
|
9
10
|
|
|
10
11
|
export { HeatMap } from './HeatMap';
|
|
11
12
|
export { BarStack } from './BarStack';
|
|
@@ -96,6 +96,7 @@ const SelectField = ({
|
|
|
96
96
|
fullWidth={fullWidth}
|
|
97
97
|
size="small"
|
|
98
98
|
{...formControlProps}
|
|
99
|
+
|
|
99
100
|
>
|
|
100
101
|
{label && <InputLabel>{label}</InputLabel>}
|
|
101
102
|
<Select
|
|
@@ -150,4 +151,4 @@ const SelectField = ({
|
|
|
150
151
|
);
|
|
151
152
|
};
|
|
152
153
|
|
|
153
|
-
export default SelectField;
|
|
154
|
+
export default SelectField;
|
package/src/Module/index.tsx
CHANGED
|
@@ -3,7 +3,6 @@ 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';
|
|
7
6
|
import { QueryProvider, ThemeProvider } from '..';
|
|
8
7
|
import SnackbarProvider from '../Snackbar/SnackbarProvider';
|
|
9
8
|
|
|
@@ -13,10 +12,6 @@ export interface ModuleProps {
|
|
|
13
12
|
queryClient?: QueryClient;
|
|
14
13
|
seedName: string;
|
|
15
14
|
store: ReturnType<typeof createStore>;
|
|
16
|
-
overrideTheme?: {
|
|
17
|
-
light: Partial<ThemeOptions>;
|
|
18
|
-
dark: Partial<ThemeOptions>;
|
|
19
|
-
};
|
|
20
15
|
}
|
|
21
16
|
|
|
22
17
|
const Module = ({
|
|
@@ -24,8 +19,7 @@ const Module = ({
|
|
|
24
19
|
seedName,
|
|
25
20
|
maxSnackbars = 3,
|
|
26
21
|
store,
|
|
27
|
-
queryClient
|
|
28
|
-
overrideTheme
|
|
22
|
+
queryClient
|
|
29
23
|
}: ModuleProps): JSX.Element => {
|
|
30
24
|
const generateClassName = createGenerateClassName({
|
|
31
25
|
seed: seedName
|
|
@@ -35,7 +29,7 @@ const Module = ({
|
|
|
35
29
|
<QueryProvider queryClient={queryClient}>
|
|
36
30
|
<JotaiProvider store={store}>
|
|
37
31
|
<StylesProvider generateClassName={generateClassName}>
|
|
38
|
-
<ThemeProvider
|
|
32
|
+
<ThemeProvider>
|
|
39
33
|
<SnackbarProvider maxSnackbars={maxSnackbars}>
|
|
40
34
|
{children}
|
|
41
35
|
</SnackbarProvider>
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { useAtomValue } from 'jotai';
|
|
2
|
-
import { equals
|
|
2
|
+
import { equals } from 'ramda';
|
|
3
3
|
import { CSSInterpolation } from 'tss-react';
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
ButtonProps,
|
|
7
7
|
InputBaseProps,
|
|
8
8
|
ThemeProvider as MuiThemeProvider,
|
|
9
|
-
PaletteOptions,
|
|
10
9
|
StyledEngineProvider,
|
|
11
10
|
Theme,
|
|
12
11
|
createTheme
|
|
@@ -27,7 +26,7 @@ import { ReactNode, useMemo } from 'react';
|
|
|
27
26
|
import { getPalette } from './palettes';
|
|
28
27
|
|
|
29
28
|
declare module '@mui/styles/defaultTheme' {
|
|
30
|
-
interface DefaultTheme extends Theme {}
|
|
29
|
+
interface DefaultTheme extends Theme { }
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
declare module '@mui/material/TextField' {
|
|
@@ -199,14 +198,14 @@ export const getTheme = (mode: ThemeMode): ThemeOptions => ({
|
|
|
199
198
|
styleOverrides: {
|
|
200
199
|
root: ({ theme }) => ({
|
|
201
200
|
'&:hover, &.Mui-selected, &.Mui-selected:hover, &.Mui-selected:focus':
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
201
|
+
{
|
|
202
|
+
background: equals(theme.palette.mode, ThemeMode.dark)
|
|
203
|
+
? theme.palette.primary.dark
|
|
204
|
+
: theme.palette.primary.light,
|
|
205
|
+
color: equals(theme.palette.mode, ThemeMode.dark)
|
|
206
|
+
? theme.palette.common.white
|
|
207
|
+
: theme.palette.primary.main
|
|
208
|
+
},
|
|
210
209
|
fontSize: theme.typography.body2.fontSize
|
|
211
210
|
})
|
|
212
211
|
}
|
|
@@ -223,12 +222,12 @@ export const getTheme = (mode: ThemeMode): ThemeOptions => ({
|
|
|
223
222
|
styleOverrides: {
|
|
224
223
|
root: ({ theme }) => ({
|
|
225
224
|
[`[role="tooltip"] &, &.MuiMenu-paper, &.${autocompleteClasses.paper}`]:
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
225
|
+
{
|
|
226
|
+
backgroundColor: theme.palette.background.default,
|
|
227
|
+
border: 'none',
|
|
228
|
+
borderRadius: `${theme.shape.borderRadius}px`,
|
|
229
|
+
boxShadow: theme.shadows[3]
|
|
230
|
+
}
|
|
232
231
|
})
|
|
233
232
|
}
|
|
234
233
|
},
|
|
@@ -258,23 +257,15 @@ export const getTheme = (mode: ThemeMode): ThemeOptions => ({
|
|
|
258
257
|
|
|
259
258
|
interface Props {
|
|
260
259
|
children: ReactNode;
|
|
261
|
-
overrideTheme?: {
|
|
262
|
-
light: Partial<PaletteOptions>;
|
|
263
|
-
dark: Partial<PaletteOptions>;
|
|
264
|
-
};
|
|
265
260
|
}
|
|
266
261
|
|
|
267
|
-
const ThemeProvider = ({ children
|
|
262
|
+
const ThemeProvider = ({ children }: Props): JSX.Element => {
|
|
268
263
|
const { themeMode } = useAtomValue(userAtom);
|
|
269
264
|
|
|
270
|
-
const theme = useMemo(
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
palette: overrideThemeByMode || {}
|
|
275
|
-
})
|
|
276
|
-
);
|
|
277
|
-
}, [themeMode, overrideTheme]);
|
|
265
|
+
const theme = useMemo(
|
|
266
|
+
() => createTheme(getTheme(themeMode || ThemeMode.light)),
|
|
267
|
+
[themeMode]
|
|
268
|
+
);
|
|
278
269
|
|
|
279
270
|
return (
|
|
280
271
|
<StyledEngineProvider injectFirst enableCssLayer>
|
|
@@ -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;
|
|
@@ -16,11 +16,7 @@ const ModalHeader = ({
|
|
|
16
16
|
}: ModalHeaderProps & DialogTitleProps): ReactElement => {
|
|
17
17
|
return (
|
|
18
18
|
<div className={modalHeader}>
|
|
19
|
-
<MuiDialogTitle
|
|
20
|
-
className="p-0 font-bold text-2xl"
|
|
21
|
-
color="primary"
|
|
22
|
-
{...rest}
|
|
23
|
-
>
|
|
19
|
+
<MuiDialogTitle className="p-0 font-bold text-2xl" color="primary" {...rest}>
|
|
24
20
|
{children}
|
|
25
21
|
</MuiDialogTitle>
|
|
26
22
|
</div>
|
|
@@ -1,74 +0,0 @@
|
|
|
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
|
-
}
|