@centreon/ui 26.7.0 → 26.7.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/src/Dashboard/DashboardLayout.stories.tsx +13 -11
- package/src/Graph/BarChart/ResponsiveBarChart.tsx +0 -1
- package/src/Graph/Chart/Chart.tsx +0 -1
- package/src/Graph/Gauge/AnimatedPie.tsx +3 -1
- package/src/Graph/SingleBar/ResponsiveSingleBar.tsx +3 -1
- package/src/Graph/common/BaseChart/ChartSvgWrapper.tsx +2 -2
- package/src/Graph/common/timeSeries/index.ts +8 -13
- package/src/InputField/Select/Autocomplete/Connected/index.stories.tsx +1 -0
- package/src/InputField/Select/Autocomplete/Connected/index.test.tsx +110 -109
- package/src/InputField/Text/index.stories.tsx +7 -1
- package/src/Listing/ActionBar/PaginationActions.tsx +10 -1
- package/src/Listing/Header/Cell/SelectActionListingHeaderCell.tsx +1 -1
- package/src/api/customFetch.ts +7 -2
- package/src/api/useFetchQuery/index.test.ts +6 -1
- package/src/api/useFetchQuery/index.ts +10 -6
- package/src/components/Tabs/Tab.styles.ts +0 -3
- package/src/components/Tabs/TabPanel.tsx +5 -15
package/package.json
CHANGED
|
@@ -72,17 +72,19 @@ const DashboardTemplate = ({
|
|
|
72
72
|
header,
|
|
73
73
|
layout = dashboardLayout
|
|
74
74
|
}: DashboardTemplateProps): ReactElement => (
|
|
75
|
-
<
|
|
76
|
-
{layout
|
|
77
|
-
|
|
78
|
-
{
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
75
|
+
<div className="h-150 overflow-y-auto">
|
|
76
|
+
<DashboardLayout.Layout<CustomLayout> layout={layout}>
|
|
77
|
+
{layout.map(({ i, content, shouldUseFluidTypography }) => (
|
|
78
|
+
<DashboardLayout.Item header={header} id={i} key={i}>
|
|
79
|
+
{shouldUseFluidTypography ? (
|
|
80
|
+
<FluidTypography text={content} />
|
|
81
|
+
) : (
|
|
82
|
+
<Typography>{content}</Typography>
|
|
83
|
+
)}
|
|
84
|
+
</DashboardLayout.Item>
|
|
85
|
+
))}
|
|
86
|
+
</DashboardLayout.Layout>
|
|
87
|
+
</div>
|
|
86
88
|
);
|
|
87
89
|
|
|
88
90
|
const meta: Meta<typeof DashboardTemplate> = {
|
|
@@ -8,6 +8,8 @@ import type { Thresholds } from '../common/models';
|
|
|
8
8
|
|
|
9
9
|
type AnimatedStyles = { endAngle: number; opacity: number; startAngle: number };
|
|
10
10
|
|
|
11
|
+
const AnimatedPath = animated('path');
|
|
12
|
+
|
|
11
13
|
const fromLeaveTransition = ({
|
|
12
14
|
endAngle
|
|
13
15
|
}: {
|
|
@@ -63,7 +65,7 @@ const AnimatedPie = <Datum,>({
|
|
|
63
65
|
|
|
64
66
|
return transitions((props, arc, { key }) => (
|
|
65
67
|
<g key={key}>
|
|
66
|
-
<
|
|
68
|
+
<AnimatedPath
|
|
67
69
|
d={to([props.startAngle, props.endAngle], (startAngle, endAngle) =>
|
|
68
70
|
path({
|
|
69
71
|
...arc,
|
|
@@ -20,6 +20,8 @@ import type { SingleBarProps } from './models';
|
|
|
20
20
|
import { barHeights, lineMargins } from './ThresholdLine';
|
|
21
21
|
import Thresholds, { groupMargin } from './Thresholds';
|
|
22
22
|
|
|
23
|
+
const AnimatedRect = animated('rect');
|
|
24
|
+
|
|
23
25
|
interface Props extends SingleBarProps {
|
|
24
26
|
height: number;
|
|
25
27
|
width: number;
|
|
@@ -176,7 +178,7 @@ const ResponsiveSingleBar = ({
|
|
|
176
178
|
<title>single bar</title>
|
|
177
179
|
<Group.Group>
|
|
178
180
|
{text}
|
|
179
|
-
<
|
|
181
|
+
<AnimatedRect
|
|
180
182
|
data-testid={`${latestMetricData}-bar-${barColor}`}
|
|
181
183
|
fill={barColor}
|
|
182
184
|
height={realBarHeight}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Group } from '@visx/visx';
|
|
2
2
|
import type { ScaleBand, ScaleLinear, ScaleTime } from 'd3-scale';
|
|
3
3
|
import { equals } from 'ramda';
|
|
4
|
-
import type { MutableRefObject, ReactElement } from 'react';
|
|
4
|
+
import type { MutableRefObject, ReactElement, ReactNode } from 'react';
|
|
5
5
|
|
|
6
6
|
import { margin } from '../../Chart/common';
|
|
7
7
|
import type { ChartAxis } from '../../Chart/models';
|
|
@@ -15,7 +15,7 @@ interface Props {
|
|
|
15
15
|
allUnits: Array<string>;
|
|
16
16
|
axis?: ChartAxis;
|
|
17
17
|
base?: number;
|
|
18
|
-
children:
|
|
18
|
+
children: ReactNode;
|
|
19
19
|
displayedLines: Array<Line>;
|
|
20
20
|
graphHeight: number;
|
|
21
21
|
graphWidth: number;
|
|
@@ -343,19 +343,14 @@ const getTimeSeriesForLines = ({
|
|
|
343
343
|
return map(
|
|
344
344
|
({ timeTick, ...metricsValue }): TimeValue => ({
|
|
345
345
|
...reduce(
|
|
346
|
-
(acc, metric_id): Omit<TimeValue, 'timePick'> => {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
[metric_id]
|
|
350
|
-
|
|
351
|
-
metricsValue[metric_id]
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
: metricsValue[metric_id]
|
|
355
|
-
};
|
|
356
|
-
},
|
|
357
|
-
// @ts-expect-error - suppressing pre-existing type mismatch
|
|
358
|
-
{},
|
|
346
|
+
(acc, metric_id): Omit<TimeValue, 'timePick'> => ({
|
|
347
|
+
...acc,
|
|
348
|
+
[metric_id]:
|
|
349
|
+
invert && metricsValue[metric_id] && gt(metricsValue[metric_id], 0)
|
|
350
|
+
? negate(metricsValue[metric_id])
|
|
351
|
+
: metricsValue[metric_id]
|
|
352
|
+
}),
|
|
353
|
+
{} as Omit<TimeValue, 'timePick'>,
|
|
359
354
|
metrics
|
|
360
355
|
),
|
|
361
356
|
timeTick
|
|
@@ -36,6 +36,7 @@ const getEndpoint = ({ endpoint, parameters }): string =>
|
|
|
36
36
|
|
|
37
37
|
const mockSearch = (page: number): object => ({
|
|
38
38
|
delay: 1000,
|
|
39
|
+
headers: { 'Content-Type': 'application/json' },
|
|
39
40
|
method: 'GET',
|
|
40
41
|
response: (request): Listing<SelectEntry> => {
|
|
41
42
|
const { searchParams } = request;
|
|
@@ -1,129 +1,130 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from
|
|
11
|
-
import buildListingEndpoint from
|
|
2
|
+
act,
|
|
3
|
+
fireEvent,
|
|
4
|
+
getFetchCall,
|
|
5
|
+
mockResponse,
|
|
6
|
+
type RenderResult,
|
|
7
|
+
render,
|
|
8
|
+
resetMocks,
|
|
9
|
+
waitFor
|
|
10
|
+
} from '../../../../../test/testRenderer';
|
|
11
|
+
import buildListingEndpoint from '../../../../api/buildListingEndpoint';
|
|
12
12
|
import type {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
} from
|
|
16
|
-
import TestQueryProvider from
|
|
13
|
+
BuildListingEndpointParameters,
|
|
14
|
+
ConditionsSearchParameter
|
|
15
|
+
} from '../../../../api/buildListingEndpoint/models';
|
|
16
|
+
import TestQueryProvider from '../../../../api/TestQueryProvider';
|
|
17
|
+
import SingleConnectedAutocompleteField from './Single';
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const label = "Connected Autocomplete";
|
|
21
|
-
const placeholder = "Type here...";
|
|
19
|
+
const label = 'Connected Autocomplete';
|
|
20
|
+
const placeholder = 'Type here...';
|
|
22
21
|
|
|
23
22
|
const optionsData = {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
23
|
+
meta: {
|
|
24
|
+
limit: 2,
|
|
25
|
+
page: 1,
|
|
26
|
+
total: 20
|
|
27
|
+
},
|
|
28
|
+
result: [
|
|
29
|
+
{ id: 0, name: 'My Option 1' },
|
|
30
|
+
{ id: 1, name: 'My Option 2' }
|
|
31
|
+
]
|
|
33
32
|
};
|
|
34
33
|
|
|
35
|
-
const baseEndpoint =
|
|
34
|
+
const baseEndpoint = 'endpoint';
|
|
36
35
|
|
|
37
36
|
const getEndpoint = (
|
|
38
|
-
|
|
37
|
+
parameters: BuildListingEndpointParameters['parameters']
|
|
39
38
|
): string => {
|
|
40
|
-
|
|
39
|
+
return buildListingEndpoint({ baseEndpoint, parameters });
|
|
41
40
|
};
|
|
42
41
|
|
|
43
42
|
interface Props {
|
|
44
|
-
|
|
43
|
+
searchConditions?: Array<ConditionsSearchParameter>;
|
|
45
44
|
}
|
|
46
45
|
|
|
46
|
+
const mockParams = { headers: { 'Content-Type': 'application/json' } };
|
|
47
|
+
|
|
47
48
|
const renderSingleConnectedAutocompleteField = (
|
|
48
|
-
|
|
49
|
+
{ searchConditions }: Props = { searchConditions: undefined }
|
|
49
50
|
): RenderResult =>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
51
|
+
render(
|
|
52
|
+
<TestQueryProvider>
|
|
53
|
+
<SingleConnectedAutocompleteField
|
|
54
|
+
baseEndpoint=""
|
|
55
|
+
field="host.name"
|
|
56
|
+
getEndpoint={getEndpoint}
|
|
57
|
+
label={label}
|
|
58
|
+
placeholder="Type here..."
|
|
59
|
+
searchConditions={searchConditions}
|
|
60
|
+
/>
|
|
61
|
+
</TestQueryProvider>
|
|
62
|
+
);
|
|
62
63
|
|
|
63
64
|
describe(SingleConnectedAutocompleteField, () => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
65
|
+
beforeEach(() => {
|
|
66
|
+
resetMocks();
|
|
67
|
+
mockResponse({ data: optionsData, options: mockParams });
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('populates options with the first page result from the endpoint request', async () => {
|
|
71
|
+
const { getByLabelText, getByText } =
|
|
72
|
+
renderSingleConnectedAutocompleteField();
|
|
73
|
+
|
|
74
|
+
fireEvent.click(getByLabelText('Open'));
|
|
75
|
+
|
|
76
|
+
expect(getFetchCall(0)).toEqual(`${baseEndpoint}?page=1`);
|
|
77
|
+
|
|
78
|
+
await waitFor(() => {
|
|
79
|
+
expect(getByText('My Option 1')).toBeInTheDocument();
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('populates options with the first page result from the endpoint request after typing something in input field', async () => {
|
|
84
|
+
const { getByLabelText, getByPlaceholderText } =
|
|
85
|
+
renderSingleConnectedAutocompleteField();
|
|
86
|
+
|
|
87
|
+
act(() => {
|
|
88
|
+
fireEvent.click(getByLabelText('Open'));
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
await waitFor(() => {
|
|
92
|
+
expect(getFetchCall(0)).toEqual(`${baseEndpoint}?page=1`);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
await waitFor(() => {
|
|
96
|
+
expect(getFetchCall(1)).toEqual(`${baseEndpoint}?page=2`);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
fireEvent.change(getByPlaceholderText(placeholder), {
|
|
100
|
+
target: { value: 'My Option 2' }
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
await waitFor(() => {
|
|
104
|
+
expect(decodeURIComponent(getFetchCall(2) as string)).toEqual(
|
|
105
|
+
'endpoint?page=1&search={"$and":[{"$and":[{"host.name":{"$lk":"%My Option 2%"}}]}]}'
|
|
106
|
+
);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('adds search conditions to the endpoint request when the corresponding prop is passed', async () => {
|
|
111
|
+
const { getByLabelText } = renderSingleConnectedAutocompleteField({
|
|
112
|
+
searchConditions: [
|
|
113
|
+
{
|
|
114
|
+
field: 'parent_name',
|
|
115
|
+
value: {
|
|
116
|
+
$eq: 'Centreon-Server'
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
fireEvent.click(getByLabelText('Open'));
|
|
123
|
+
|
|
124
|
+
await waitFor(() => {
|
|
125
|
+
expect(getFetchCall(0)).toEqual(
|
|
126
|
+
`${baseEndpoint}?page=1&search=%7B%22%24and%22%3A%5B%7B%22%24or%22%3A%5B%7B%22parent_name%22%3A%7B%22%24eq%22%3A%22Centreon-Server%22%7D%7D%5D%7D%5D%7D`
|
|
127
|
+
);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
129
130
|
});
|
|
@@ -104,7 +104,13 @@ export const autoSizeWithEndAdornment = (): JSX.Element => (
|
|
|
104
104
|
autoSize
|
|
105
105
|
autoSizeCustomPadding={10}
|
|
106
106
|
autoSizeDefaultWidth={60}
|
|
107
|
-
EndAdornment={AbcIcon}
|
|
108
107
|
placeholder="Auto size"
|
|
108
|
+
textFieldSlotsAndSlotProps={{
|
|
109
|
+
slotProps: {
|
|
110
|
+
input: {
|
|
111
|
+
endAdornment: <AbcIcon />
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}}
|
|
109
115
|
/>
|
|
110
116
|
);
|
|
@@ -3,7 +3,16 @@ import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft';
|
|
|
3
3
|
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';
|
|
4
4
|
import LastPageIcon from '@mui/icons-material/LastPage';
|
|
5
5
|
import IconButton from '@mui/material/IconButton';
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
type TablePaginationActionsProps = {
|
|
8
|
+
count: number;
|
|
9
|
+
onPageChange: (
|
|
10
|
+
event: React.MouseEvent<HTMLButtonElement> | null,
|
|
11
|
+
page: number
|
|
12
|
+
) => void;
|
|
13
|
+
page: number;
|
|
14
|
+
rowsPerPage: number;
|
|
15
|
+
};
|
|
7
16
|
|
|
8
17
|
import { useTranslation } from 'react-i18next';
|
|
9
18
|
|
|
@@ -48,7 +48,7 @@ const SelectActionListingHeaderCell = ({
|
|
|
48
48
|
icon={<ArrowDropDownIcon />}
|
|
49
49
|
title={labelPredefinedRowsSelectionMenu}
|
|
50
50
|
>
|
|
51
|
-
{(props): JSX.Element => (
|
|
51
|
+
{(props: { close?: () => void } | undefined): JSX.Element => (
|
|
52
52
|
<PredefinedSelectionList
|
|
53
53
|
close={props?.close ?? ((): void => undefined)}
|
|
54
54
|
onSelectRowsWithCondition={onSelectRowsWithCondition}
|
package/src/api/customFetch.ts
CHANGED
|
@@ -74,8 +74,13 @@ export const customFetch = <T>({
|
|
|
74
74
|
};
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
.
|
|
77
|
+
const responseParsingMethod = response.headers
|
|
78
|
+
.get('Content-Type')
|
|
79
|
+
?.startsWith('text')
|
|
80
|
+
? 'text'
|
|
81
|
+
: 'json';
|
|
82
|
+
|
|
83
|
+
return response[responseParsingMethod]()
|
|
79
84
|
.then((data) => {
|
|
80
85
|
if (!response.ok) {
|
|
81
86
|
const defaultError = {
|
|
@@ -37,6 +37,8 @@ const renderFetchQuery = <T extends object>(
|
|
|
37
37
|
wrapper: TestQueryProvider
|
|
38
38
|
}) as RenderHookResult<UseFetchQueryState<T>, unknown>;
|
|
39
39
|
|
|
40
|
+
const mockParams = { headers: { 'Content-Type': 'application/json' } };
|
|
41
|
+
|
|
40
42
|
describe('useFetchQuery', () => {
|
|
41
43
|
beforeEach(() => {
|
|
42
44
|
mockedShowErrorMessage.mockReset();
|
|
@@ -57,7 +59,7 @@ describe('useFetchQuery', () => {
|
|
|
57
59
|
});
|
|
58
60
|
|
|
59
61
|
it('retrieves data from an endpoint', async () => {
|
|
60
|
-
fetchMock.once(JSON.stringify(user));
|
|
62
|
+
fetchMock.once(JSON.stringify(user), mockParams);
|
|
61
63
|
const { result } = renderFetchQuery<User>({
|
|
62
64
|
getEndpoint: () => '/endpoint',
|
|
63
65
|
getQueryKey: () => ['queryKey']
|
|
@@ -70,6 +72,7 @@ describe('useFetchQuery', () => {
|
|
|
70
72
|
|
|
71
73
|
it("shows an error from the API via the Snackbar and inside the browser's console", async () => {
|
|
72
74
|
fetchMock.once(JSON.stringify({ code: 2, message: 'custom message' }), {
|
|
75
|
+
...mockParams,
|
|
73
76
|
status: 400
|
|
74
77
|
});
|
|
75
78
|
|
|
@@ -109,6 +112,7 @@ describe('useFetchQuery', () => {
|
|
|
109
112
|
|
|
110
113
|
it('shows a default failure message via the Snackbar as fallback', async () => {
|
|
111
114
|
fetchMock.once(JSON.stringify({}), {
|
|
115
|
+
...mockParams,
|
|
112
116
|
status: 400
|
|
113
117
|
});
|
|
114
118
|
|
|
@@ -134,6 +138,7 @@ describe('useFetchQuery', () => {
|
|
|
134
138
|
|
|
135
139
|
it('does not show any message via the Snackbar when the httpCodesBypassErrorSnackbar is passed', async () => {
|
|
136
140
|
fetchMock.once(JSON.stringify({}), {
|
|
141
|
+
...mockParams,
|
|
137
142
|
status: 400
|
|
138
143
|
});
|
|
139
144
|
|
|
@@ -38,16 +38,16 @@ export interface UseFetchQueryProps<T> {
|
|
|
38
38
|
useLongCache?: boolean;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
export interface PrefetchPageParams {
|
|
42
|
-
getPrefetchQueryKey: (page: number) => QueryKey;
|
|
43
|
-
page: number;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
41
|
export interface PrefetchQueryParams {
|
|
47
42
|
endpointParams?: PrefetchEndpointParams;
|
|
48
43
|
queryKey: QueryKey;
|
|
49
44
|
}
|
|
50
45
|
|
|
46
|
+
export interface PrefetchPageParams {
|
|
47
|
+
getPrefetchQueryKey: (page: number) => QueryKey;
|
|
48
|
+
page: number;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
51
|
export type UseFetchQueryState<T> = {
|
|
52
52
|
data?: T;
|
|
53
53
|
error: Omit<ResponseError, 'isError'> | null;
|
|
@@ -82,7 +82,11 @@ const useFetchQuery = <T extends object>({
|
|
|
82
82
|
|
|
83
83
|
const { showErrorMessage } = useSnackbar();
|
|
84
84
|
|
|
85
|
-
const isCypressTest = equals(
|
|
85
|
+
const isCypressTest = equals(
|
|
86
|
+
(window as Window & { Cypress?: { testingType: string } }).Cypress
|
|
87
|
+
?.testingType,
|
|
88
|
+
'component'
|
|
89
|
+
);
|
|
86
90
|
|
|
87
91
|
const cacheOptions =
|
|
88
92
|
!isCypressTest && useLongCache ? { gcTime: 60 * 1000 } : {};
|
|
@@ -1,22 +1,12 @@
|
|
|
1
1
|
import { TabPanel as MuiTabPanel } from '@mui/lab';
|
|
2
2
|
|
|
3
|
-
import { useTabsStyles } from './Tab.styles';
|
|
4
|
-
|
|
5
3
|
type Props = {
|
|
6
4
|
children: JSX.Element;
|
|
7
5
|
value: string;
|
|
8
6
|
};
|
|
9
7
|
|
|
10
|
-
export const TabPanel = ({ children, value }: Props): JSX.Element =>
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
className={classes.tabPanel}
|
|
16
|
-
data-tabPanel={value}
|
|
17
|
-
value={value}
|
|
18
|
-
>
|
|
19
|
-
{children}
|
|
20
|
-
</MuiTabPanel>
|
|
21
|
-
);
|
|
22
|
-
};
|
|
8
|
+
export const TabPanel = ({ children, value }: Props): JSX.Element => (
|
|
9
|
+
<MuiTabPanel className="p-0 pt-2" data-tabPanel={value} value={value}>
|
|
10
|
+
{children}
|
|
11
|
+
</MuiTabPanel>
|
|
12
|
+
);
|