@centreon/ui 24.10.12 → 24.10.13
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 +3 -2
- package/public/mockServiceWorker.js +1 -1
- package/src/Button/Icon/index.tsx +3 -1
- package/src/Dashboard/Dashboard.styles.ts +3 -4
- package/src/Dashboard/DashboardLayout.stories.tsx +1 -1
- package/src/Dashboard/Grid.tsx +11 -17
- package/src/Dashboard/Layout.tsx +27 -56
- package/src/Dialog/UnsavedChanges/index.tsx +15 -13
- package/src/Dialog/UnsavedChanges/translatedLabels.ts +15 -13
- package/src/Form/Form.tsx +0 -1
- package/src/Form/Inputs/Autocomplete.tsx +1 -1
- package/src/Form/Inputs/ConnectedAutocomplete.tsx +5 -2
- package/src/Form/Inputs/Grid.tsx +7 -1
- package/src/Form/Inputs/Radio.tsx +1 -1
- package/src/Form/Inputs/Switch.tsx +1 -1
- package/src/Form/Inputs/Text.tsx +1 -1
- package/src/Form/Inputs/index.tsx +25 -24
- package/src/Form/Inputs/models.ts +2 -0
- package/src/Graph/BarChart/BarChart.cypress.spec.tsx +3 -3
- package/src/Graph/BarChart/BarChart.tsx +24 -31
- package/src/Graph/BarChart/BarGroup.tsx +32 -59
- package/src/Graph/BarChart/BarStack.tsx +64 -13
- package/src/Graph/BarChart/MemoizedGroup.tsx +123 -0
- package/src/Graph/BarChart/ResponsiveBarChart.tsx +21 -7
- package/src/Graph/BarStack/BarStack.cypress.spec.tsx +87 -9
- package/src/Graph/BarStack/BarStack.stories.tsx +13 -4
- package/src/Graph/BarStack/BarStack.styles.ts +57 -33
- package/src/Graph/BarStack/Graph.tsx +173 -0
- package/src/Graph/BarStack/GraphAndLegend.tsx +117 -0
- package/src/Graph/BarStack/ResponsiveBarStack.tsx +61 -168
- package/src/Graph/BarStack/constants.ts +5 -0
- package/src/Graph/BarStack/models.ts +0 -1
- package/src/Graph/BarStack/useGraphAndLegend.ts +84 -0
- package/src/Graph/BarStack/useResponsiveBarStack.ts +73 -97
- package/src/Graph/Chart/Chart.cypress.spec.tsx +14 -26
- package/src/Graph/Chart/Chart.stories.tsx +1 -1
- package/src/Graph/Chart/Chart.tsx +53 -37
- package/src/Graph/Chart/InteractiveComponents/AnchorPoint/GuidingLines.tsx +3 -3
- package/src/Graph/Chart/InteractiveComponents/AnchorPoint/useTickGraph.ts +19 -6
- package/src/Graph/Chart/Legend/Legend.styles.ts +25 -11
- package/src/Graph/Chart/Legend/index.tsx +6 -24
- package/src/Graph/Chart/index.tsx +34 -43
- package/src/Graph/Chart/models.ts +0 -1
- package/src/Graph/Chart/useChartData.ts +19 -1
- package/src/Graph/HeatMap/ResponsiveHeatMap.tsx +20 -2
- package/src/Graph/HeatMap/model.ts +6 -2
- package/src/Graph/Legend/Legend.styles.ts +10 -0
- package/src/Graph/Legend/Legend.tsx +6 -1
- package/src/Graph/SingleBar/ResponsiveSingleBar.tsx +9 -10
- package/src/Graph/SingleBar/ThresholdLine.tsx +6 -6
- package/src/Graph/Text/Text.styles.ts +2 -2
- package/src/Graph/Text/Text.tsx +23 -10
- package/src/Graph/Timeline/ResponsiveTimeline.tsx +152 -0
- package/src/Graph/Timeline/Timeline.cypress.spec.tsx +148 -0
- package/src/Graph/Timeline/Timeline.stories.tsx +91 -0
- package/src/Graph/Timeline/Timeline.tsx +28 -0
- package/src/Graph/Timeline/index.ts +1 -0
- package/src/Graph/Timeline/models.ts +20 -0
- package/src/Graph/Timeline/timeline.styles.ts +11 -0
- package/src/Graph/Timeline/translatedLabel.ts +6 -0
- package/src/Graph/Timeline/useTimeline.ts +90 -0
- package/src/Graph/Tree/Links.tsx +2 -2
- package/src/Graph/Tree/Tree.tsx +2 -2
- package/src/Graph/Tree/constants.ts +1 -1
- package/src/Graph/common/Axes/index.tsx +1 -1
- package/src/Graph/common/Axes/useAxisY.ts +8 -4
- package/src/Graph/common/BaseChart/BaseChart.tsx +3 -12
- package/src/Graph/common/BaseChart/ChartSvgWrapper.tsx +12 -4
- package/src/Graph/common/BaseChart/Header/index.tsx +3 -1
- package/src/Graph/common/BaseChart/useComputeBaseChartDimensions.ts +23 -11
- package/src/Graph/common/BaseChart/useComputeYAxisMaxCharacters.ts +92 -0
- package/src/Graph/common/models.ts +7 -8
- package/src/Graph/common/timeSeries/index.test.ts +1 -1
- package/src/Graph/common/timeSeries/index.ts +56 -29
- package/src/Graph/common/timeSeries/models.ts +2 -0
- package/src/Graph/common/utils.ts +51 -3
- package/src/Graph/index.ts +4 -1
- package/src/Graph/mockedData/lastDayWithNullValues.json +6 -6
- package/src/Graph/mockedData/pingServiceLinesBars.json +47 -47
- package/src/Icon/DowntimeIcon.tsx +8 -1
- package/src/Icon/FlappingIcon.tsx +22 -0
- package/src/Icon/index.ts +1 -0
- package/src/InputField/Select/Autocomplete/Connected/Multi/index.test.tsx +21 -1
- package/src/InputField/Select/Autocomplete/Connected/index.test.tsx +2 -2
- package/src/InputField/Select/Autocomplete/Connected/index.tsx +52 -15
- package/src/InputField/Select/Autocomplete/Multi/index.stories.tsx +19 -0
- package/src/InputField/Select/Autocomplete/Multi/index.tsx +8 -5
- package/src/InputField/Select/Autocomplete/index.tsx +79 -54
- package/src/InputField/Text/index.tsx +6 -4
- package/src/InputField/translatedLabels.ts +2 -0
- package/src/Listing/ActionBar/index.tsx +1 -1
- package/src/Listing/Listing.styles.ts +3 -3
- package/src/Listing/index.tsx +40 -37
- package/src/Listing/models.ts +0 -8
- package/src/Listing/useStyleTable.ts +58 -32
- package/src/MultiSelectEntries/index.tsx +2 -0
- package/src/PopoverMenu/index.tsx +2 -9
- package/src/SortableItems/index.tsx +0 -1
- package/src/ThemeProvider/index.tsx +1 -1
- package/src/ThemeProvider/palettes.ts +6 -0
- package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +2 -3
- package/src/TimePeriods/DateTimePickerInput.tsx +3 -1
- package/src/api/buildListingEndpoint/getSearchQueryParameterValue.ts +7 -1
- package/src/api/buildListingEndpoint/models.ts +1 -0
- package/src/api/customFetch.ts +4 -1
- package/src/api/models.ts +9 -0
- package/src/api/useGraphQuery/index.ts +117 -20
- package/src/api/useGraphQuery/models.ts +1 -0
- package/src/api/useMutationQuery/index.ts +1 -1
- package/src/components/DataTable/DataTable.styles.ts +1 -1
- package/src/components/DataTable/EmptyState/DataTableEmptyState.styles.ts +2 -1
- package/src/components/DataTable/EmptyState/DataTableEmptyState.tsx +4 -1
- package/src/components/DataTable/Item/DataTableItem.styles.ts +28 -2
- package/src/components/DataTable/Item/DataTableItem.tsx +19 -4
- package/src/components/Form/FormActions.tsx +21 -12
- package/src/components/Layout/AreaIndicator.tsx +1 -1
- package/src/components/Layout/PageLayout/PageLayout.styles.ts +2 -7
- package/src/components/Layout/PageLayout/PageLayoutBody.tsx +0 -1
- package/src/components/Zoom/Zoom.tsx +9 -2
- package/src/components/Zoom/ZoomContent.tsx +143 -136
- package/src/components/Zoom/models.ts +18 -15
- package/src/components/Zoom/useMinimap.ts +5 -8
- package/src/components/Zoom/useZoom.ts +3 -3
- package/src/index.ts +2 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/useLocale/index.ts +9 -0
- package/src/utils/useLocale/useLocale.cypress.spec.tsx +38 -0
- package/src/utils/useLocaleDateTimeFormat/index.ts +4 -2
- package/src/utils/usePluralizedTranslation.ts +2 -3
- package/src/Graph/common/timeSeries/index.test.ts-E +0 -622
- package/src/components/CrudPage/Actions/Actions.styles.ts +0 -16
- package/src/components/CrudPage/Actions/Actions.tsx +0 -24
- package/src/components/CrudPage/Actions/AddButton.tsx +0 -23
- package/src/components/CrudPage/Actions/Filters.tsx +0 -25
- package/src/components/CrudPage/Actions/Search.tsx +0 -31
- package/src/components/CrudPage/Actions/useSearch.tsx +0 -24
- package/src/components/CrudPage/Columns/Actions.tsx +0 -88
- package/src/components/CrudPage/CrudPage.cypress.spec.tsx +0 -559
- package/src/components/CrudPage/CrudPage.stories.tsx +0 -278
- package/src/components/CrudPage/CrudPageRoot.tsx +0 -142
- package/src/components/CrudPage/DeleteModal.tsx +0 -77
- package/src/components/CrudPage/Form/AddModal.tsx +0 -35
- package/src/components/CrudPage/Form/Buttons.tsx +0 -98
- package/src/components/CrudPage/Form/UpdateModal.tsx +0 -60
- package/src/components/CrudPage/Listing.tsx +0 -63
- package/src/components/CrudPage/atoms.ts +0 -30
- package/src/components/CrudPage/hooks/useDeleteItem.ts +0 -53
- package/src/components/CrudPage/hooks/useGetItem.ts +0 -36
- package/src/components/CrudPage/hooks/useGetItems.ts +0 -67
- package/src/components/CrudPage/hooks/useListingQueryKey.ts +0 -31
- package/src/components/CrudPage/index.tsx +0 -7
- package/src/components/CrudPage/models.ts +0 -118
- package/src/components/CrudPage/utils.ts +0 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
1
|
+
import { useEffect, useMemo } from 'react';
|
|
2
2
|
|
|
3
3
|
import { useAtomValue, useSetAtom } from 'jotai';
|
|
4
|
-
import { equals, isNil, pick, type } from 'ramda';
|
|
4
|
+
import { equals, isEmpty, isNil, pick, type, update } from 'ramda';
|
|
5
5
|
import { CSSObject } from 'tss-react';
|
|
6
6
|
|
|
7
7
|
import { Theme } from '@mui/material';
|
|
@@ -12,14 +12,11 @@ import { Column, TableStyleAtom as Style } from './models';
|
|
|
12
12
|
import { tableStyleAtom, tableStyleDerivedAtom } from './tableAtoms';
|
|
13
13
|
|
|
14
14
|
interface TableStyle {
|
|
15
|
-
checkable?: boolean;
|
|
16
|
-
currentVisibleColumns?: Array<Column>;
|
|
17
15
|
listingVariant?: ListingVariant;
|
|
18
16
|
}
|
|
19
17
|
|
|
20
18
|
interface TableStyleState {
|
|
21
19
|
dataStyle: Style;
|
|
22
|
-
getGridTemplateColumn: string;
|
|
23
20
|
}
|
|
24
21
|
|
|
25
22
|
const isCompactMode = equals<ListingVariant | undefined>(
|
|
@@ -40,35 +37,11 @@ export const getTextStyleByViewMode = ({
|
|
|
40
37
|
theme.typography[isCompactMode(listingVariant) ? 'body2' : 'body1']
|
|
41
38
|
);
|
|
42
39
|
|
|
43
|
-
const useStyleTable = ({
|
|
44
|
-
checkable,
|
|
45
|
-
currentVisibleColumns,
|
|
46
|
-
listingVariant
|
|
47
|
-
}: TableStyle): TableStyleState => {
|
|
40
|
+
const useStyleTable = ({ listingVariant }: TableStyle): TableStyleState => {
|
|
48
41
|
const dataStyle = useAtomValue(tableStyleAtom);
|
|
49
42
|
|
|
50
43
|
const updateStyleTable = useSetAtom(tableStyleDerivedAtom);
|
|
51
44
|
|
|
52
|
-
const getGridTemplateColumn = (): string => {
|
|
53
|
-
const checkbox = checkable ? 'fit-content(1rem) ' : ''; // SelectAction (checkbox) cell adjusts to content
|
|
54
|
-
|
|
55
|
-
const columnTemplate = currentVisibleColumns
|
|
56
|
-
?.filter((column) => column)
|
|
57
|
-
?.map(({ width, shortLabel }) => {
|
|
58
|
-
if (!isNil(shortLabel)) {
|
|
59
|
-
return 'min-content';
|
|
60
|
-
}
|
|
61
|
-
if (isNil(width)) {
|
|
62
|
-
return 'auto';
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return equals(type(width), 'Number') ? `${width}px` : width;
|
|
66
|
-
})
|
|
67
|
-
.join(' ');
|
|
68
|
-
|
|
69
|
-
return `${checkbox}${columnTemplate}`;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
45
|
useEffect(() => {
|
|
73
46
|
if (listingVariant) {
|
|
74
47
|
updateStyleTable({ listingVariant });
|
|
@@ -76,9 +49,62 @@ const useStyleTable = ({
|
|
|
76
49
|
}, [listingVariant]);
|
|
77
50
|
|
|
78
51
|
return {
|
|
79
|
-
dataStyle
|
|
80
|
-
getGridTemplateColumn: getGridTemplateColumn()
|
|
52
|
+
dataStyle
|
|
81
53
|
};
|
|
82
54
|
};
|
|
83
55
|
|
|
84
56
|
export default useStyleTable;
|
|
57
|
+
|
|
58
|
+
interface UseColumnStyleProps {
|
|
59
|
+
checkable?: boolean;
|
|
60
|
+
currentVisibleColumns?: Array<Column>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const useColumnStyle = ({
|
|
64
|
+
checkable,
|
|
65
|
+
currentVisibleColumns
|
|
66
|
+
}: UseColumnStyleProps): string => {
|
|
67
|
+
const gridTemplateColumn = useMemo((): string => {
|
|
68
|
+
const checkbox = checkable ? 'fit-content(1rem) ' : ''; // SelectAction (checkbox) cell adjusts to content
|
|
69
|
+
|
|
70
|
+
const columnTemplate: Array<string> =
|
|
71
|
+
currentVisibleColumns
|
|
72
|
+
?.filter((column) => column)
|
|
73
|
+
?.map(({ width, shortLabel }) => {
|
|
74
|
+
if (!isNil(shortLabel)) {
|
|
75
|
+
return 'min-content';
|
|
76
|
+
}
|
|
77
|
+
if (isNil(width)) {
|
|
78
|
+
return 'auto';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
equals(type(width), 'Number') ? `${width}px` : width
|
|
83
|
+
) as string;
|
|
84
|
+
}) || [];
|
|
85
|
+
|
|
86
|
+
const hasOnlyContainerResponsiveColumns =
|
|
87
|
+
!isEmpty(columnTemplate) &&
|
|
88
|
+
columnTemplate.every(
|
|
89
|
+
(width: string) =>
|
|
90
|
+
width.includes('auto') ||
|
|
91
|
+
width.includes('fr') ||
|
|
92
|
+
width.includes('%') ||
|
|
93
|
+
width.includes('px')
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
if (!hasOnlyContainerResponsiveColumns) {
|
|
97
|
+
const fixedColumnTemplate = update(
|
|
98
|
+
columnTemplate.length - 1,
|
|
99
|
+
'auto',
|
|
100
|
+
columnTemplate
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
return `${checkbox}${fixedColumnTemplate.join(' ')}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return `${checkbox}${columnTemplate.join(' ')}`;
|
|
107
|
+
}, [checkable, currentVisibleColumns]);
|
|
108
|
+
|
|
109
|
+
return gridTemplateColumn;
|
|
110
|
+
};
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
} from '@mui/material';
|
|
11
11
|
import type { PopperProps } from '@mui/material/Popper';
|
|
12
12
|
|
|
13
|
-
import { equals, type } from 'ramda';
|
|
14
13
|
import { IconButton } from '..';
|
|
15
14
|
|
|
16
15
|
const useStyles = makeStyles()((theme) => ({
|
|
@@ -30,9 +29,8 @@ interface PopoverData {
|
|
|
30
29
|
|
|
31
30
|
interface Props {
|
|
32
31
|
canOpen?: boolean;
|
|
33
|
-
children: (props?) => JSX.Element
|
|
32
|
+
children: (props?) => JSX.Element;
|
|
34
33
|
className?: string;
|
|
35
|
-
tooltipClassName?: string;
|
|
36
34
|
dataTestId?: string;
|
|
37
35
|
getPopoverData?: (data: PopoverData) => void;
|
|
38
36
|
icon: JSX.Element;
|
|
@@ -54,7 +52,6 @@ const PopoverMenu = ({
|
|
|
54
52
|
className,
|
|
55
53
|
dataTestId,
|
|
56
54
|
getPopoverData,
|
|
57
|
-
tooltipClassName,
|
|
58
55
|
popperProps
|
|
59
56
|
}: Props): JSX.Element => {
|
|
60
57
|
const { classes, cx } = useStyles();
|
|
@@ -116,11 +113,7 @@ const PopoverMenu = ({
|
|
|
116
113
|
onResizeCapture={(): undefined => undefined}
|
|
117
114
|
{...popperProps}
|
|
118
115
|
>
|
|
119
|
-
<Paper
|
|
120
|
-
{equals(type(children), 'Function')
|
|
121
|
-
? children({ close })
|
|
122
|
-
: children}
|
|
123
|
-
</Paper>
|
|
116
|
+
<Paper>{children({ close })}</Paper>
|
|
124
117
|
</Popper>
|
|
125
118
|
</ClickAwayListener>
|
|
126
119
|
)}
|
|
@@ -185,7 +185,6 @@ const SortableItems = <T extends { [propertyToFilterItemsOn]: string }>({
|
|
|
185
185
|
>
|
|
186
186
|
<SortableContext items={sortableItemsIds} strategy={sortingStrategy}>
|
|
187
187
|
<RootComponent>
|
|
188
|
-
{/* biome-ignore lint: */}
|
|
189
188
|
<>
|
|
190
189
|
{sortableItemsIds.map((sortableItemId, index) => {
|
|
191
190
|
const item = getItemById(sortableItemId) as
|
|
@@ -261,7 +261,7 @@ export const getTheme = (mode: ThemeMode): ThemeOptions => ({
|
|
|
261
261
|
{
|
|
262
262
|
backgroundColor: theme.palette.background.default,
|
|
263
263
|
border: 'none',
|
|
264
|
-
borderRadius:
|
|
264
|
+
borderRadius: 0,
|
|
265
265
|
boxShadow: theme.shadows[3]
|
|
266
266
|
}
|
|
267
267
|
})
|
|
@@ -27,6 +27,8 @@ declare module '@mui/material/styles/createPalette' {
|
|
|
27
27
|
acknowledgedBackground: string;
|
|
28
28
|
inDowntime: string;
|
|
29
29
|
inDowntimeBackground: string;
|
|
30
|
+
inFlapping: string;
|
|
31
|
+
inFlappingBackground: string;
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
34
|
|
|
@@ -159,6 +161,8 @@ export const lightPalette: PaletteOptions = {
|
|
|
159
161
|
action: {
|
|
160
162
|
acknowledged: '#745F35',
|
|
161
163
|
acknowledgedBackground: '#DFD2B9',
|
|
164
|
+
inFlapping: '#064A3F',
|
|
165
|
+
inFlappingBackground: '#D8F3EF',
|
|
162
166
|
activatedOpacity: 0.12,
|
|
163
167
|
active: '#666666',
|
|
164
168
|
disabled: '#999999',
|
|
@@ -299,6 +303,8 @@ export const darkPalette: PaletteOptions = {
|
|
|
299
303
|
action: {
|
|
300
304
|
acknowledged: '#DFD2B9',
|
|
301
305
|
acknowledgedBackground: '#745F35',
|
|
306
|
+
inFlapping: '#D8F3EF',
|
|
307
|
+
inFlappingBackground: '#064A3F',
|
|
302
308
|
activatedOpacity: 0.3,
|
|
303
309
|
active: '#B5B5B5',
|
|
304
310
|
disabled: '#999999',
|
|
@@ -10,8 +10,6 @@ import { Typography } from '@mui/material';
|
|
|
10
10
|
import { LocalizationProvider } from '@mui/x-date-pickers';
|
|
11
11
|
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
|
12
12
|
|
|
13
|
-
import { userAtom } from '@centreon/ui-context';
|
|
14
|
-
|
|
15
13
|
import DateTimePickerInput from '../../DateTimePickerInput';
|
|
16
14
|
import { isInvalidDate } from '../../helpers';
|
|
17
15
|
import {
|
|
@@ -20,6 +18,7 @@ import {
|
|
|
20
18
|
} from '../../models';
|
|
21
19
|
import { errorTimePeriodAtom } from '../../timePeriodsAtoms';
|
|
22
20
|
|
|
21
|
+
import { useLocale } from '../../../utils';
|
|
23
22
|
import ErrorText from './ErrorText';
|
|
24
23
|
import {
|
|
25
24
|
PickersStartEndDateDirection,
|
|
@@ -100,7 +99,7 @@ const PickersStartEndDate = ({
|
|
|
100
99
|
}: PickersStartEndDateProps): JSX.Element => {
|
|
101
100
|
const { classes } = useStyles();
|
|
102
101
|
|
|
103
|
-
const
|
|
102
|
+
const locale = useLocale();
|
|
104
103
|
const error = useAtomValue(errorTimePeriodAtom);
|
|
105
104
|
const isError = error || isInvalidDate({ endDate, startDate });
|
|
106
105
|
|
|
@@ -13,6 +13,7 @@ import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
|
|
13
13
|
|
|
14
14
|
import { userAtom } from '@centreon/ui-context';
|
|
15
15
|
|
|
16
|
+
import { useLocale } from '../utils';
|
|
16
17
|
import { CustomTimePeriodProperty } from './models';
|
|
17
18
|
|
|
18
19
|
interface ChangeDateProps {
|
|
@@ -50,6 +51,7 @@ const DateTimePickerInput = ({
|
|
|
50
51
|
'@media (min-width: 1024px) or (pointer: fine)';
|
|
51
52
|
|
|
52
53
|
const user = useAtomValue(userAtom);
|
|
54
|
+
const localeToUse = useLocale();
|
|
53
55
|
|
|
54
56
|
const isUTC = equals(timezone ?? user.timezone, 'UTC');
|
|
55
57
|
|
|
@@ -72,7 +74,7 @@ const DateTimePickerInput = ({
|
|
|
72
74
|
|
|
73
75
|
return (
|
|
74
76
|
<LocalizationProvider
|
|
75
|
-
adapterLocale={(locale ??
|
|
77
|
+
adapterLocale={(locale ?? localeToUse).substring(0, 2)}
|
|
76
78
|
dateAdapter={AdapterDayjs}
|
|
77
79
|
dateLibInstance={dayjs}
|
|
78
80
|
>
|
|
@@ -93,8 +93,14 @@ const getConditionsSearchQueryParameterValue = (
|
|
|
93
93
|
equals(listField, field)
|
|
94
94
|
);
|
|
95
95
|
|
|
96
|
+
const globalOperator = filteredItems.every(({ operator }) =>
|
|
97
|
+
equals(operator, filteredItems[0].operator)
|
|
98
|
+
)
|
|
99
|
+
? filteredItems[0].operator || '$or'
|
|
100
|
+
: '$or';
|
|
101
|
+
|
|
96
102
|
return {
|
|
97
|
-
|
|
103
|
+
[globalOperator]: flatten(
|
|
98
104
|
filteredItems.map(({ value, values }) => {
|
|
99
105
|
if (!isNil(value)) {
|
|
100
106
|
return [
|
package/src/api/customFetch.ts
CHANGED
|
@@ -55,10 +55,13 @@ export const customFetch = <T>({
|
|
|
55
55
|
? `${baseEndpoint}${endpoint}`
|
|
56
56
|
: endpoint;
|
|
57
57
|
|
|
58
|
+
const isFormData = payload instanceof FormData;
|
|
59
|
+
|
|
58
60
|
const options = isMutation
|
|
59
61
|
? {
|
|
60
62
|
...defaultOptions,
|
|
61
|
-
body:
|
|
63
|
+
body: isFormData ? payload : JSON.stringify(payload),
|
|
64
|
+
headers: isFormData ? undefined : headers
|
|
62
65
|
}
|
|
63
66
|
: defaultOptions;
|
|
64
67
|
|
package/src/api/models.ts
CHANGED
|
@@ -8,3 +8,12 @@ export interface Listing<TEntity> {
|
|
|
8
8
|
meta: ListingMeta;
|
|
9
9
|
result: Array<TEntity>;
|
|
10
10
|
}
|
|
11
|
+
|
|
12
|
+
export interface ListingMap<TEntity> {
|
|
13
|
+
content: Array<TEntity>;
|
|
14
|
+
totalPages: number;
|
|
15
|
+
totalElements: number;
|
|
16
|
+
size: number;
|
|
17
|
+
number: number;
|
|
18
|
+
numberOfElements: number;
|
|
19
|
+
}
|
|
@@ -36,6 +36,7 @@ interface UseMetricsQueryProps {
|
|
|
36
36
|
start?: string | null;
|
|
37
37
|
timePeriodType: number;
|
|
38
38
|
};
|
|
39
|
+
isEnabled?: boolean;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
interface UseMetricsQueryState {
|
|
@@ -46,6 +47,12 @@ interface UseMetricsQueryState {
|
|
|
46
47
|
start: string;
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
interface FormatLegend {
|
|
51
|
+
host?: string | null;
|
|
52
|
+
service?: string | null;
|
|
53
|
+
metric: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
49
56
|
const getStartEndFromTimePeriod = (
|
|
50
57
|
timePeriod: number
|
|
51
58
|
): { end: string; start: string } => {
|
|
@@ -74,7 +81,8 @@ export const resourceTypeQueryParameter = {
|
|
|
74
81
|
[WidgetResourceType.hostGroup]: 'hostgroup.id',
|
|
75
82
|
[WidgetResourceType.serviceCategory]: 'servicecategory.id',
|
|
76
83
|
[WidgetResourceType.serviceGroup]: 'servicegroup.id',
|
|
77
|
-
[WidgetResourceType.service]: 'service.name'
|
|
84
|
+
[WidgetResourceType.service]: 'service.name',
|
|
85
|
+
[WidgetResourceType.metaService]: 'metaservice.id'
|
|
78
86
|
};
|
|
79
87
|
|
|
80
88
|
const areResourcesFullfilled = (value: Array<Resource>): boolean =>
|
|
@@ -94,7 +102,8 @@ const useGraphQuery = ({
|
|
|
94
102
|
refreshInterval = false,
|
|
95
103
|
refreshCount,
|
|
96
104
|
bypassQueryParams = false,
|
|
97
|
-
prefix
|
|
105
|
+
prefix,
|
|
106
|
+
isEnabled = true
|
|
98
107
|
}: UseMetricsQueryProps): UseMetricsQueryState => {
|
|
99
108
|
const timePeriodToUse = equals(timePeriod?.timePeriodType, -1)
|
|
100
109
|
? {
|
|
@@ -108,9 +117,9 @@ const useGraphQuery = ({
|
|
|
108
117
|
: getStartEndFromTimePeriod(timePeriodToUse as number);
|
|
109
118
|
|
|
110
119
|
const definedMetrics = metrics.filter((metric) => metric);
|
|
111
|
-
const formattedDefinedMetrics = definedMetrics
|
|
112
|
-
encodeURIComponent(metric.name)
|
|
113
|
-
|
|
120
|
+
const formattedDefinedMetrics = definedMetrics
|
|
121
|
+
.map((metric) => `metric_names[]=${encodeURIComponent(metric.name)}`)
|
|
122
|
+
.join('&');
|
|
114
123
|
|
|
115
124
|
const prefixQuery = prefix ? [prefix] : [];
|
|
116
125
|
|
|
@@ -129,7 +138,9 @@ const useGraphQuery = ({
|
|
|
129
138
|
parameters: {
|
|
130
139
|
search: {
|
|
131
140
|
lists: resources.map((resource) => ({
|
|
132
|
-
field:
|
|
141
|
+
field: equals(resource.resourceType, 'hostgroup')
|
|
142
|
+
? resourceTypeQueryParameter[WidgetResourceType.hostGroup]
|
|
143
|
+
: resourceTypeQueryParameter[resource.resourceType],
|
|
133
144
|
values: equals(resource.resourceType, 'service')
|
|
134
145
|
? pluck('name', resource.resources)
|
|
135
146
|
: pluck('id', resource.resources)
|
|
@@ -138,9 +149,7 @@ const useGraphQuery = ({
|
|
|
138
149
|
}
|
|
139
150
|
});
|
|
140
151
|
|
|
141
|
-
return `${endpoint}&start=${startAndEnd.start}&end=${
|
|
142
|
-
startAndEnd.end
|
|
143
|
-
}&metric_names=[${formattedDefinedMetrics.join(',')}]`;
|
|
152
|
+
return `${endpoint}&start=${startAndEnd.start}&end=${startAndEnd.end}&${formattedDefinedMetrics}`;
|
|
144
153
|
},
|
|
145
154
|
getQueryKey: () => [
|
|
146
155
|
...prefixQuery,
|
|
@@ -151,7 +160,10 @@ const useGraphQuery = ({
|
|
|
151
160
|
refreshCount || 0
|
|
152
161
|
],
|
|
153
162
|
queryOptions: {
|
|
154
|
-
enabled:
|
|
163
|
+
enabled:
|
|
164
|
+
areResourcesFullfilled(resources) &&
|
|
165
|
+
!isEmpty(definedMetrics) &&
|
|
166
|
+
isEnabled,
|
|
155
167
|
refetchInterval: refreshInterval,
|
|
156
168
|
suspense: false
|
|
157
169
|
},
|
|
@@ -163,22 +175,107 @@ const useGraphQuery = ({
|
|
|
163
175
|
data.current = graphData;
|
|
164
176
|
}
|
|
165
177
|
|
|
178
|
+
const getCurrentMetrics = () => {
|
|
179
|
+
if (!data.current) {
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return bypassMetricsExclusion
|
|
184
|
+
? data.current.metrics
|
|
185
|
+
: data.current.metrics.filter(({ metric_id }) => {
|
|
186
|
+
return pipe(
|
|
187
|
+
pluck('excludedMetrics'),
|
|
188
|
+
flatten,
|
|
189
|
+
includes(metric_id),
|
|
190
|
+
not
|
|
191
|
+
)(metrics);
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const formatLegend = ({
|
|
196
|
+
host = null,
|
|
197
|
+
service = null,
|
|
198
|
+
metric
|
|
199
|
+
}: FormatLegend) => {
|
|
200
|
+
if (!host && !service) {
|
|
201
|
+
return metric;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (!host) {
|
|
205
|
+
return `${service}: ${metric}`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (!service) {
|
|
209
|
+
return `${host}: ${metric}`;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return `${host} ${service}: ${metric}`;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const getFormattedMetrics = () => {
|
|
216
|
+
const metrics = getCurrentMetrics();
|
|
217
|
+
|
|
218
|
+
if (equals(metrics?.length, 1)) {
|
|
219
|
+
return metrics?.map((line) => {
|
|
220
|
+
const formattedLegend = formatLegend({
|
|
221
|
+
host: line?.host_name,
|
|
222
|
+
service: line?.service_name,
|
|
223
|
+
metric: line?.metric
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
return { ...line, legend: formattedLegend };
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return metrics?.map((line) => {
|
|
231
|
+
const areHostNameRedundant = metrics.every(({ host_name }) =>
|
|
232
|
+
equals(host_name, line.host_name)
|
|
233
|
+
);
|
|
234
|
+
const areServiceNameRedundant = metrics.every(({ service_name }) =>
|
|
235
|
+
equals(service_name, line.service_name)
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
if (areHostNameRedundant && areServiceNameRedundant) {
|
|
239
|
+
const formattedLegend = formatLegend({ metric: line.metric });
|
|
240
|
+
|
|
241
|
+
return { ...line, legend: formattedLegend };
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (areHostNameRedundant) {
|
|
245
|
+
const formattedLegend = formatLegend({
|
|
246
|
+
service: line.service_name,
|
|
247
|
+
metric: line.metric
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
return { ...line, legend: formattedLegend };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (areServiceNameRedundant) {
|
|
254
|
+
const formattedLegend = formatLegend({
|
|
255
|
+
host: line.host_name,
|
|
256
|
+
metric: line.metric
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
return { ...line, legend: formattedLegend };
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const formattedLegend = formatLegend({
|
|
263
|
+
host: line.host_name,
|
|
264
|
+
service: line.service_name,
|
|
265
|
+
metric: line.metric
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
return { ...line, legend: formattedLegend };
|
|
269
|
+
});
|
|
270
|
+
};
|
|
271
|
+
|
|
166
272
|
const formattedGraphData = data.current
|
|
167
273
|
? {
|
|
168
274
|
global: {
|
|
169
275
|
base: data.current.base,
|
|
170
276
|
title: ''
|
|
171
277
|
},
|
|
172
|
-
metrics:
|
|
173
|
-
? data.current.metrics
|
|
174
|
-
: data.current.metrics.filter(({ metric_id }) => {
|
|
175
|
-
return pipe(
|
|
176
|
-
pluck('excludedMetrics'),
|
|
177
|
-
flatten,
|
|
178
|
-
includes(metric_id),
|
|
179
|
-
not
|
|
180
|
-
)(metrics);
|
|
181
|
-
}),
|
|
278
|
+
metrics: getFormattedMetrics(),
|
|
182
279
|
times: data.current.times
|
|
183
280
|
}
|
|
184
281
|
: undefined;
|
|
@@ -100,7 +100,7 @@ const useMutationQuery = <T extends object, TMeta>({
|
|
|
100
100
|
defaultFailureMessage,
|
|
101
101
|
endpoint: getEndpoint(_meta as TMeta),
|
|
102
102
|
headers: new Headers({
|
|
103
|
-
'Content-Type': 'application/
|
|
103
|
+
'Content-Type': 'application/json',
|
|
104
104
|
...fetchHeaders
|
|
105
105
|
}),
|
|
106
106
|
isMutation: true,
|
|
@@ -8,7 +8,7 @@ const useStyles = makeStyles()((theme) => ({
|
|
|
8
8
|
},
|
|
9
9
|
display: 'grid',
|
|
10
10
|
gridGap: theme.spacing(2.5),
|
|
11
|
-
gridTemplateColumns: `repeat(auto-fill, ${theme.spacing(
|
|
11
|
+
gridTemplateColumns: `repeat(auto-fill, ${theme.spacing(53)})`
|
|
12
12
|
},
|
|
13
13
|
'&[data-variant="listing"]': {
|
|
14
14
|
height: '100%'
|
|
@@ -19,12 +19,14 @@ type ListEmptyStateProps = {
|
|
|
19
19
|
description?: string;
|
|
20
20
|
};
|
|
21
21
|
onCreate?: () => void;
|
|
22
|
+
buttonCreateTestId?: string;
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
const DataTableEmptyState = ({
|
|
25
26
|
labels,
|
|
26
27
|
onCreate,
|
|
27
|
-
canCreate = true
|
|
28
|
+
canCreate = true,
|
|
29
|
+
buttonCreateTestId
|
|
28
30
|
}: ListEmptyStateProps): ReactElement => {
|
|
29
31
|
const { classes } = useStyles();
|
|
30
32
|
const { t } = useTranslation();
|
|
@@ -47,6 +49,7 @@ const DataTableEmptyState = ({
|
|
|
47
49
|
icon={<AddIcon />}
|
|
48
50
|
iconVariant="start"
|
|
49
51
|
onClick={() => onCreate?.()}
|
|
52
|
+
data-testid={buttonCreateTestId}
|
|
50
53
|
>
|
|
51
54
|
{t(labels.actions?.create || '')}
|
|
52
55
|
</Button>
|
|
@@ -6,6 +6,16 @@ const useStyles = makeStyles()((theme) => ({
|
|
|
6
6
|
flexDirection: 'row',
|
|
7
7
|
justifyContent: 'space-between'
|
|
8
8
|
},
|
|
9
|
+
cardActions: {
|
|
10
|
+
backgroundColor: theme.palette.background.paper,
|
|
11
|
+
bottom: 0,
|
|
12
|
+
position: 'absolute',
|
|
13
|
+
width: '100%'
|
|
14
|
+
},
|
|
15
|
+
cardContent: {
|
|
16
|
+
padding: theme.spacing(2),
|
|
17
|
+
zIndex: 1
|
|
18
|
+
},
|
|
9
19
|
dataTableItem: {
|
|
10
20
|
'& .MuiCardActionArea-root': {
|
|
11
21
|
alignItems: 'flex-start',
|
|
@@ -22,16 +32,32 @@ const useStyles = makeStyles()((theme) => ({
|
|
|
22
32
|
display: 'flex',
|
|
23
33
|
justifyContent: 'space-between'
|
|
24
34
|
},
|
|
35
|
+
'&:hover img[alt*="thumbnail"]': {
|
|
36
|
+
transform: 'scale(1.1)',
|
|
37
|
+
transformOrigin: 'center'
|
|
38
|
+
},
|
|
25
39
|
borderRadius: theme.shape.borderRadius,
|
|
26
40
|
display: 'flex',
|
|
27
41
|
flexDirection: 'column',
|
|
28
|
-
height: '
|
|
42
|
+
height: '250px',
|
|
29
43
|
justifyContent: 'space-between',
|
|
30
44
|
p: {
|
|
31
45
|
color: theme.palette.text.secondary,
|
|
32
46
|
letterSpacing: '0',
|
|
33
47
|
margin: '0'
|
|
34
|
-
}
|
|
48
|
+
},
|
|
49
|
+
position: 'relative'
|
|
50
|
+
},
|
|
51
|
+
description: {
|
|
52
|
+
maxHeight: '42px',
|
|
53
|
+
overflow: 'hidden'
|
|
54
|
+
},
|
|
55
|
+
thumbnail: {
|
|
56
|
+
height: theme.spacing(10.25),
|
|
57
|
+
objectFit: 'cover',
|
|
58
|
+
objectPosition: 'top',
|
|
59
|
+
transition: 'transform 150ms ease-out',
|
|
60
|
+
width: '100%'
|
|
35
61
|
}
|
|
36
62
|
}));
|
|
37
63
|
|