@centreon/ui 23.10.24 → 23.10.25-feature-MON-19319.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 +8 -1
- package/src/Dashboard/DashboardLayout.stories.tsx +3 -5
- package/src/Dashboard/Layout.tsx +4 -4
- package/src/Dashboard/utils.ts +28 -28
- package/src/ThemeProvider/index.tsx +6 -5
- package/src/ThemeProvider/palettes.ts +234 -208
- package/src/components/Button/Button.styles.ts +7 -2
- package/src/components/Header/Header.styles.ts +0 -27
- package/src/components/Header/PageHeader/PageHeader.stories.tsx +83 -0
- package/src/components/Header/PageHeader/PageHeader.styles.ts +105 -0
- package/src/components/Header/PageHeader/PageHeader.tsx +15 -0
- package/src/components/Header/PageHeader/PageHeaderActions.tsx +17 -0
- package/src/components/Header/PageHeader/PageHeaderMain.tsx +15 -0
- package/src/components/Header/PageHeader/PageHeaderMenu.tsx +15 -0
- package/src/components/Header/PageHeader/PageHeaderTitle.tsx +44 -0
- package/src/components/Header/PageHeader/index.ts +12 -0
- package/src/components/Header/index.ts +1 -1
- package/src/components/Layout/AreaIndicator.styles.ts +33 -0
- package/src/components/Layout/AreaIndicator.tsx +35 -0
- package/src/components/Layout/PageLayout/PageLayout.stories.tsx +81 -0
- package/src/components/Layout/PageLayout/PageLayout.styles.ts +30 -0
- package/src/components/Layout/PageLayout/PageLayout.tsx +21 -0
- package/src/components/Layout/PageLayout/PageLayoutActions.tsx +15 -0
- package/src/components/Layout/PageLayout/PageLayoutBody.tsx +24 -0
- package/src/components/Layout/PageLayout/PageLayoutHeader.tsx +15 -0
- package/src/components/Layout/PageLayout/index.ts +10 -0
- package/src/components/Layout/index.ts +1 -0
- package/src/components/Menu/Menu.tsx +0 -0
- package/src/components/Tooltip/TextOverflowTooltip/TextOverflowTooltip.stories.tsx +71 -0
- package/src/components/Tooltip/TextOverflowTooltip/TextOverflowTooltip.styles.ts +5 -0
- package/src/components/Tooltip/TextOverflowTooltip/TextOverflowTooltip.tsx +115 -0
- package/src/components/Tooltip/TextOverflowTooltip/index.tsx +1 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +41 -0
- package/src/components/Tooltip/Tooltip.styles.ts +5 -0
- package/src/components/Tooltip/Tooltip.tsx +46 -0
- package/src/components/Tooltip/index.ts +1 -0
- package/src/components/index.ts +2 -0
- package/src/index.ts +0 -2
- package/src/screens/dashboard/DashboardsOverview.stories.tsx +109 -101
- package/src/utils/useResizeObserver.ts +6 -0
- package/test/setupTests.js +3 -0
- package/src/components/Header/Header.stories.tsx +0 -27
- package/src/components/Header/Header.tsx +0 -23
- package/src/layout/TiledListingPage/TiledListingActions.tsx +0 -15
- package/src/layout/TiledListingPage/TiledListingContent.tsx +0 -21
- package/src/layout/TiledListingPage/TiledListingList.tsx +0 -11
- package/src/layout/TiledListingPage/TiledListingPage.styles.ts +0 -16
- package/src/layout/TiledListingPage/TiledListingPage.tsx +0 -15
- package/src/layout/TiledListingPage/index.ts +0 -4
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/* eslint-disable react-hooks/rules-of-hooks */
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
|
|
4
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
5
|
+
|
|
6
|
+
// import { expect } from '@storybook/jest';
|
|
7
|
+
import { TextOverflowTooltip } from './TextOverflowTooltip';
|
|
8
|
+
|
|
9
|
+
const meta: Meta<typeof TextOverflowTooltip> = {
|
|
10
|
+
args: {},
|
|
11
|
+
component: TextOverflowTooltip,
|
|
12
|
+
parameters: {
|
|
13
|
+
layout: 'centered'
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default meta;
|
|
18
|
+
type Story = StoryObj<typeof TextOverflowTooltip>;
|
|
19
|
+
|
|
20
|
+
export const Default: Story = {
|
|
21
|
+
args: {
|
|
22
|
+
label:
|
|
23
|
+
'Qui deserunt pariatur quis. Duis nisi velit culpa labore ipsum reprehenderit sunt laborum anim sint quis magna consequat amet. Voluptate tempor nostrud eiusmod enim qui reprehenderit.'
|
|
24
|
+
},
|
|
25
|
+
render: ({ label, ...args }) => {
|
|
26
|
+
const [labelValue, setLabelValue] = useState(label);
|
|
27
|
+
useEffect(() => setLabelValue(label), [label]);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<TextOverflowTooltip {...args} data-testid="tooltip" label={labelValue}>
|
|
31
|
+
<p
|
|
32
|
+
data-testid="paragraph"
|
|
33
|
+
style={{
|
|
34
|
+
overflow: 'hidden',
|
|
35
|
+
textOverflow: 'ellipsis',
|
|
36
|
+
whiteSpace: 'nowrap',
|
|
37
|
+
width: '40vw'
|
|
38
|
+
}}
|
|
39
|
+
>
|
|
40
|
+
{labelValue}
|
|
41
|
+
</p>
|
|
42
|
+
</TextOverflowTooltip>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const AsMultiLine: Story = {
|
|
48
|
+
args: {
|
|
49
|
+
...Default.args
|
|
50
|
+
},
|
|
51
|
+
render: ({ label, ...args }) => {
|
|
52
|
+
const [labelValue, setLabelValue] = useState(label);
|
|
53
|
+
useEffect(() => setLabelValue(label), [label]);
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<TextOverflowTooltip {...args} label={labelValue}>
|
|
57
|
+
<p
|
|
58
|
+
style={{
|
|
59
|
+
WebkitBoxOrient: 'vertical',
|
|
60
|
+
WebkitLineClamp: '2',
|
|
61
|
+
display: '-webkit-box',
|
|
62
|
+
overflow: 'hidden',
|
|
63
|
+
width: '40vw'
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
{labelValue}
|
|
67
|
+
</p>
|
|
68
|
+
</TextOverflowTooltip>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { ReactElement, useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
import { atom, useAtom } from 'jotai';
|
|
4
|
+
|
|
5
|
+
import { Tooltip, TooltipProps } from '../Tooltip';
|
|
6
|
+
import { useResizeObserver } from '../../../utils/useResizeObserver';
|
|
7
|
+
|
|
8
|
+
import { useStyles } from './TextOverflowTooltip.styles';
|
|
9
|
+
|
|
10
|
+
type TextOverflowTooltipProps = Omit<TooltipProps, 'followCursor' | 'hasCaret'>;
|
|
11
|
+
|
|
12
|
+
/** @description
|
|
13
|
+
* This component is used to display a tooltip when the text is too long, and displays the full text on hover.
|
|
14
|
+
*
|
|
15
|
+
* It's up to the child component to define it's `width` / `max-width`, and ellipsis.
|
|
16
|
+
*
|
|
17
|
+
* For single lines use :
|
|
18
|
+
* ```
|
|
19
|
+
* width: var(--width-of-the-text);
|
|
20
|
+
* white-space: nowrap;
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* For multi-lines use :
|
|
24
|
+
* ```
|
|
25
|
+
* width: var(--width-of-the-text);
|
|
26
|
+
* display: -webkit-box;
|
|
27
|
+
* -webkit-box-orient: vertical;
|
|
28
|
+
* -webkit-line-clamp: var(--max-lines-of-the-text);
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
const TextOverflowTooltip = ({
|
|
33
|
+
children,
|
|
34
|
+
label,
|
|
35
|
+
position = 'bottom',
|
|
36
|
+
isOpen,
|
|
37
|
+
...tooltipProps
|
|
38
|
+
}: TextOverflowTooltipProps): ReactElement => {
|
|
39
|
+
const { classes } = useStyles();
|
|
40
|
+
|
|
41
|
+
const stateAtom = useRef(
|
|
42
|
+
atom<{
|
|
43
|
+
hasOverflow: boolean;
|
|
44
|
+
isOpen: boolean;
|
|
45
|
+
}>({ hasOverflow: false, isOpen: false })
|
|
46
|
+
).current;
|
|
47
|
+
|
|
48
|
+
const [state, setState] = useAtom(stateAtom);
|
|
49
|
+
|
|
50
|
+
const onMouseEnter = useCallback(
|
|
51
|
+
() =>
|
|
52
|
+
state.hasOverflow &&
|
|
53
|
+
setState({
|
|
54
|
+
...state,
|
|
55
|
+
isOpen: true
|
|
56
|
+
}),
|
|
57
|
+
[state.hasOverflow]
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const onMouseLeave = useCallback(
|
|
61
|
+
() =>
|
|
62
|
+
state.hasOverflow &&
|
|
63
|
+
setState({
|
|
64
|
+
...state,
|
|
65
|
+
isOpen: false
|
|
66
|
+
}),
|
|
67
|
+
[state.hasOverflow]
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const elRef = useRef<HTMLDivElement>(null);
|
|
71
|
+
|
|
72
|
+
const onResize = (): void => {
|
|
73
|
+
const { firstElementChild: el } = elRef.current || {};
|
|
74
|
+
if (el instanceof HTMLElement) {
|
|
75
|
+
setState({
|
|
76
|
+
...state,
|
|
77
|
+
hasOverflow:
|
|
78
|
+
el.scrollWidth > el.offsetWidth || el.scrollHeight > el.offsetHeight
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
useResizeObserver({
|
|
84
|
+
onResize,
|
|
85
|
+
ref: elRef
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
if (isOpen) setState({ ...state, isOpen });
|
|
90
|
+
onResize();
|
|
91
|
+
}, [isOpen, label]);
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<Tooltip
|
|
95
|
+
followCursor
|
|
96
|
+
hasCaret={false}
|
|
97
|
+
isOpen={state.isOpen}
|
|
98
|
+
label={label}
|
|
99
|
+
position={position}
|
|
100
|
+
{...tooltipProps}
|
|
101
|
+
>
|
|
102
|
+
<div
|
|
103
|
+
className={classes.textOverflowTooltip}
|
|
104
|
+
data-has-overflow={state.hasOverflow}
|
|
105
|
+
ref={elRef}
|
|
106
|
+
onMouseEnter={onMouseEnter}
|
|
107
|
+
onMouseLeave={onMouseLeave}
|
|
108
|
+
>
|
|
109
|
+
{children}
|
|
110
|
+
</div>
|
|
111
|
+
</Tooltip>
|
|
112
|
+
);
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export { TextOverflowTooltip };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './TextOverflowTooltip';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
|
|
3
|
+
import { Info as InfoIcon } from '@mui/icons-material';
|
|
4
|
+
|
|
5
|
+
import { Tooltip } from './Tooltip';
|
|
6
|
+
|
|
7
|
+
const meta: Meta<typeof Tooltip> = {
|
|
8
|
+
argTypes: {
|
|
9
|
+
position: {
|
|
10
|
+
control: {
|
|
11
|
+
options: ['top', 'bottom', 'left', 'right']
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
component: Tooltip,
|
|
16
|
+
parameters: {
|
|
17
|
+
layout: 'centered'
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default meta;
|
|
22
|
+
type Story = StoryObj<typeof Tooltip>;
|
|
23
|
+
|
|
24
|
+
export const Default: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
children: <InfoIcon />,
|
|
27
|
+
label: 'Tooltip content'
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const WrappedContent: Story = {
|
|
32
|
+
args: {
|
|
33
|
+
children: <InfoIcon />,
|
|
34
|
+
followCursor: false,
|
|
35
|
+
hasCaret: true,
|
|
36
|
+
isOpen: true,
|
|
37
|
+
label:
|
|
38
|
+
'Qui deserunt pariatur quis. Duis nisi velit culpa labore ipsum reprehenderit sunt laborum anim sint quis magna consequat amet. Voluptate tempor nostrud eiusmod enim qui reprehenderit.',
|
|
39
|
+
position: 'right'
|
|
40
|
+
}
|
|
41
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ReactElement, ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import { Tooltip as MuiTooltip } from '@mui/material';
|
|
4
|
+
|
|
5
|
+
import { AriaLabelingAttributes } from '../../@types/aria-attributes';
|
|
6
|
+
import { DataTestAttributes } from '../../@types/data-attributes';
|
|
7
|
+
|
|
8
|
+
import { useStyles } from './Tooltip.styles';
|
|
9
|
+
|
|
10
|
+
export type TooltipProps = {
|
|
11
|
+
children: ReactElement;
|
|
12
|
+
followCursor?: boolean;
|
|
13
|
+
hasCaret?: boolean;
|
|
14
|
+
isOpen?: boolean;
|
|
15
|
+
label: ReactNode;
|
|
16
|
+
position?: 'top' | 'bottom' | 'left' | 'right';
|
|
17
|
+
} & AriaLabelingAttributes &
|
|
18
|
+
DataTestAttributes;
|
|
19
|
+
|
|
20
|
+
const Tooltip = ({
|
|
21
|
+
children,
|
|
22
|
+
label,
|
|
23
|
+
position = 'bottom',
|
|
24
|
+
followCursor = true,
|
|
25
|
+
isOpen,
|
|
26
|
+
hasCaret = false,
|
|
27
|
+
...attr
|
|
28
|
+
}: TooltipProps): ReactElement => {
|
|
29
|
+
const { classes } = useStyles();
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<MuiTooltip
|
|
33
|
+
arrow={hasCaret}
|
|
34
|
+
className={classes.tooltip}
|
|
35
|
+
followCursor={followCursor}
|
|
36
|
+
open={isOpen}
|
|
37
|
+
placement={position}
|
|
38
|
+
title={label}
|
|
39
|
+
{...attr}
|
|
40
|
+
>
|
|
41
|
+
{children}
|
|
42
|
+
</MuiTooltip>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export { Tooltip };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Tooltip';
|
package/src/components/index.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -140,8 +140,6 @@ export { default as ActionsList } from './ActionsList';
|
|
|
140
140
|
|
|
141
141
|
export type { ResponseError, CatchErrorProps } from './api/customFetch';
|
|
142
142
|
|
|
143
|
-
export * from './layout/TiledListingPage';
|
|
144
|
-
|
|
145
143
|
export * from './utils';
|
|
146
144
|
export { default as FluidTypography } from './Typography/FluidTypography';
|
|
147
145
|
export * from './Dashboard';
|
|
@@ -11,16 +11,11 @@ import {
|
|
|
11
11
|
DashboardForm,
|
|
12
12
|
DashboardFormProps,
|
|
13
13
|
DataTable,
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
Modal,
|
|
15
|
+
PageHeader,
|
|
16
|
+
PageLayout
|
|
16
17
|
} from '../../components';
|
|
17
18
|
import { Default as DashboardFormDefaultStory } from '../../components/Form/Dashboard/DashboardForm.stories';
|
|
18
|
-
import {
|
|
19
|
-
TiledListingActions,
|
|
20
|
-
TiledListingContent,
|
|
21
|
-
TiledListingList,
|
|
22
|
-
TiledListingPage
|
|
23
|
-
} from '../../layout/TiledListingPage';
|
|
24
19
|
|
|
25
20
|
const meta: Meta = {
|
|
26
21
|
args: {
|
|
@@ -64,6 +59,9 @@ const meta: Meta = {
|
|
|
64
59
|
},
|
|
65
60
|
title: 'Dashboards overview'
|
|
66
61
|
},
|
|
62
|
+
parameters: {
|
|
63
|
+
layout: 'fullscreen'
|
|
64
|
+
},
|
|
67
65
|
title: 'screens/Dashboards'
|
|
68
66
|
};
|
|
69
67
|
|
|
@@ -134,10 +132,16 @@ const DefaultView = (args): JSX.Element => {
|
|
|
134
132
|
};
|
|
135
133
|
|
|
136
134
|
return (
|
|
137
|
-
<
|
|
138
|
-
<Header
|
|
139
|
-
|
|
140
|
-
|
|
135
|
+
<PageLayout>
|
|
136
|
+
<PageLayout.Header>
|
|
137
|
+
<PageHeader>
|
|
138
|
+
<PageHeader.Main>
|
|
139
|
+
<PageHeader.Title title={title} />
|
|
140
|
+
</PageHeader.Main>
|
|
141
|
+
</PageHeader>
|
|
142
|
+
</PageLayout.Header>
|
|
143
|
+
<PageLayout.Body>
|
|
144
|
+
<PageLayout.Actions>
|
|
141
145
|
{dataDashboards.length !== 0 && (
|
|
142
146
|
<Button
|
|
143
147
|
aria-label="add"
|
|
@@ -150,101 +154,105 @@ const DefaultView = (args): JSX.Element => {
|
|
|
150
154
|
{actions.create.label}
|
|
151
155
|
</Button>
|
|
152
156
|
)}
|
|
153
|
-
</
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
setDialogState({ item: null, open: true, variant: 'create' })
|
|
161
|
-
}
|
|
162
|
-
/>
|
|
163
|
-
) : (
|
|
164
|
-
dataDashboards.map((dashboard) => (
|
|
165
|
-
<DataTable.Item
|
|
166
|
-
hasActions
|
|
167
|
-
hasCardAction
|
|
168
|
-
description={dashboard.description}
|
|
169
|
-
key={dashboard.id}
|
|
170
|
-
title={dashboard.name}
|
|
171
|
-
onDelete={() =>
|
|
172
|
-
setDeleteDialogState({ item: dashboard, open: true })
|
|
173
|
-
}
|
|
174
|
-
onEdit={() =>
|
|
175
|
-
setDialogState({
|
|
176
|
-
item: dashboard,
|
|
177
|
-
open: true,
|
|
178
|
-
variant: 'update'
|
|
179
|
-
})
|
|
180
|
-
}
|
|
181
|
-
/>
|
|
182
|
-
))
|
|
183
|
-
)}
|
|
184
|
-
</DataTable>
|
|
185
|
-
</TiledListingContent>
|
|
186
|
-
<Modal
|
|
187
|
-
open={dialogState.open}
|
|
188
|
-
onClose={() =>
|
|
189
|
-
setDialogState({
|
|
190
|
-
item: null,
|
|
191
|
-
open: false,
|
|
192
|
-
variant: dialogState.variant
|
|
193
|
-
})
|
|
194
|
-
}
|
|
195
|
-
>
|
|
196
|
-
<Modal.Header>
|
|
197
|
-
{form.labels.title[dialogState.variant ?? 'create']}
|
|
198
|
-
</Modal.Header>
|
|
199
|
-
<Modal.Body>
|
|
200
|
-
<DashboardForm
|
|
201
|
-
labels={DashboardFormDefaultStory!.args!.labels!}
|
|
202
|
-
resource={dialogState.item || undefined}
|
|
203
|
-
variant={dialogState.variant}
|
|
204
|
-
onCancel={() =>
|
|
157
|
+
</PageLayout.Actions>
|
|
158
|
+
|
|
159
|
+
<DataTable isEmpty={dataDashboards.length === 0}>
|
|
160
|
+
{dataDashboards.length === 0 ? (
|
|
161
|
+
<DataTable.EmptyState
|
|
162
|
+
labels={list.emptyState.labels}
|
|
163
|
+
onCreate={() =>
|
|
205
164
|
setDialogState({
|
|
206
165
|
item: null,
|
|
207
|
-
open:
|
|
208
|
-
variant:
|
|
166
|
+
open: true,
|
|
167
|
+
variant: 'create'
|
|
209
168
|
})
|
|
210
169
|
}
|
|
211
|
-
onSubmit={(values) =>
|
|
212
|
-
dialogState.variant === 'create'
|
|
213
|
-
? createDashboard(values)
|
|
214
|
-
: updateDashboard(values)
|
|
215
|
-
}
|
|
216
170
|
/>
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
171
|
+
) : (
|
|
172
|
+
dataDashboards.map((dashboard) => (
|
|
173
|
+
<DataTable.Item
|
|
174
|
+
hasActions
|
|
175
|
+
hasCardAction
|
|
176
|
+
description={dashboard.description}
|
|
177
|
+
key={dashboard.id}
|
|
178
|
+
title={dashboard.name}
|
|
179
|
+
onDelete={() =>
|
|
180
|
+
setDeleteDialogState({ item: dashboard, open: true })
|
|
181
|
+
}
|
|
182
|
+
onEdit={() =>
|
|
183
|
+
setDialogState({
|
|
184
|
+
item: dashboard,
|
|
185
|
+
open: true,
|
|
186
|
+
variant: 'update'
|
|
187
|
+
})
|
|
188
|
+
}
|
|
189
|
+
/>
|
|
190
|
+
))
|
|
191
|
+
)}
|
|
192
|
+
</DataTable>
|
|
193
|
+
</PageLayout.Body>
|
|
194
|
+
|
|
195
|
+
<Modal
|
|
196
|
+
open={dialogState.open}
|
|
197
|
+
onClose={() =>
|
|
198
|
+
setDialogState({
|
|
199
|
+
item: null,
|
|
200
|
+
open: false,
|
|
201
|
+
variant: dialogState.variant
|
|
202
|
+
})
|
|
203
|
+
}
|
|
204
|
+
>
|
|
205
|
+
<Modal.Header>
|
|
206
|
+
{form.labels.title[dialogState.variant ?? 'create']}
|
|
207
|
+
</Modal.Header>
|
|
208
|
+
<Modal.Body>
|
|
209
|
+
<DashboardForm
|
|
210
|
+
labels={DashboardFormDefaultStory!.args!.labels!}
|
|
211
|
+
resource={dialogState.item || undefined}
|
|
212
|
+
variant={dialogState.variant}
|
|
213
|
+
onCancel={() =>
|
|
214
|
+
setDialogState({
|
|
215
|
+
item: null,
|
|
216
|
+
open: false,
|
|
217
|
+
variant: dialogState.variant
|
|
218
|
+
})
|
|
219
|
+
}
|
|
220
|
+
onSubmit={(values) =>
|
|
221
|
+
dialogState.variant === 'create'
|
|
222
|
+
? createDashboard(values)
|
|
223
|
+
: updateDashboard(values)
|
|
224
|
+
}
|
|
244
225
|
/>
|
|
245
|
-
</Modal>
|
|
246
|
-
</
|
|
247
|
-
|
|
226
|
+
</Modal.Body>
|
|
227
|
+
</Modal>
|
|
228
|
+
<Modal
|
|
229
|
+
open={deleteDialogState.open}
|
|
230
|
+
onClose={() =>
|
|
231
|
+
setDeleteDialogState({
|
|
232
|
+
...deleteDialogState,
|
|
233
|
+
open: false
|
|
234
|
+
})
|
|
235
|
+
}
|
|
236
|
+
>
|
|
237
|
+
<Modal.Header>{deleteConfirmation.labels.title}</Modal.Header>
|
|
238
|
+
<Modal.Body>
|
|
239
|
+
<p>
|
|
240
|
+
{deleteConfirmation.labels.description(
|
|
241
|
+
deleteDialogState.item?.name
|
|
242
|
+
)}
|
|
243
|
+
</p>
|
|
244
|
+
</Modal.Body>
|
|
245
|
+
<Modal.Actions
|
|
246
|
+
isDanger
|
|
247
|
+
labels={deleteConfirmation.labels.actions}
|
|
248
|
+
onCancel={() => setDeleteDialogState({ item: null, open: false })}
|
|
249
|
+
onConfirm={() => {
|
|
250
|
+
deleteDashboard(deleteDialogState.item?.id);
|
|
251
|
+
setDeleteDialogState({ item: null, open: false });
|
|
252
|
+
}}
|
|
253
|
+
/>
|
|
254
|
+
</Modal>
|
|
255
|
+
</PageLayout>
|
|
248
256
|
);
|
|
249
257
|
};
|
|
250
258
|
|
package/test/setupTests.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/* eslint-disable no-underscore-dangle */
|
|
2
2
|
/* eslint-disable no-undef */
|
|
3
|
+
// FIXME: testing library setup
|
|
4
|
+
// import '@testing-library/jest-dom';
|
|
5
|
+
// import '@testing-library/react';
|
|
3
6
|
// import '@testing-library/jest-dom/extend-expect';
|
|
4
7
|
import i18n from 'i18next';
|
|
5
8
|
import { initReactI18next } from 'react-i18next';
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
|
|
3
|
-
import { Settings as SettingsIcon } from '@mui/icons-material';
|
|
4
|
-
|
|
5
|
-
import { IconButton } from '../Button';
|
|
6
|
-
|
|
7
|
-
import { Header } from './Header';
|
|
8
|
-
|
|
9
|
-
const meta: Meta<typeof Header> = {
|
|
10
|
-
component: Header
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export default meta;
|
|
14
|
-
type Story = StoryObj<typeof Header>;
|
|
15
|
-
|
|
16
|
-
export const Default: Story = {
|
|
17
|
-
args: {
|
|
18
|
-
title: 'Header'
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export const WithNav: Story = {
|
|
23
|
-
args: {
|
|
24
|
-
nav: <IconButton icon={<SettingsIcon />} size="small" variant="ghost" />,
|
|
25
|
-
title: 'Header with nav'
|
|
26
|
-
}
|
|
27
|
-
};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { ReactElement, ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
import { Typography as MuiTypography } from '@mui/material';
|
|
4
|
-
|
|
5
|
-
import { useStyles } from './Header.styles';
|
|
6
|
-
|
|
7
|
-
type HeaderProps = {
|
|
8
|
-
nav?: ReactNode;
|
|
9
|
-
title: string;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const Header = ({ title, nav }: HeaderProps): ReactElement => {
|
|
13
|
-
const { classes } = useStyles();
|
|
14
|
-
|
|
15
|
-
return (
|
|
16
|
-
<header className={classes.header}>
|
|
17
|
-
<MuiTypography variant="h1">{title}</MuiTypography>
|
|
18
|
-
{nav && <nav>{nav}</nav>}
|
|
19
|
-
</header>
|
|
20
|
-
);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export { Header };
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
import { useTiledListingActionsStyles } from './TiledListingPage.styles';
|
|
4
|
-
|
|
5
|
-
interface TiledListingActionsProps {
|
|
6
|
-
children: Array<ReactNode> | ReactNode;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const TiledListingActions = ({
|
|
10
|
-
children
|
|
11
|
-
}: TiledListingActionsProps): JSX.Element => {
|
|
12
|
-
const { classes } = useTiledListingActionsStyles();
|
|
13
|
-
|
|
14
|
-
return <div className={classes.actions}>{children}</div>;
|
|
15
|
-
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
import Responsive from '../../Responsive';
|
|
4
|
-
|
|
5
|
-
import { useTiledListingActionsStyles } from './TiledListingPage.styles';
|
|
6
|
-
|
|
7
|
-
interface TiledListingContentProps {
|
|
8
|
-
children: ReactNode;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const TiledListingContent = ({
|
|
12
|
-
children
|
|
13
|
-
}: TiledListingContentProps): JSX.Element => {
|
|
14
|
-
const { classes } = useTiledListingActionsStyles();
|
|
15
|
-
|
|
16
|
-
return (
|
|
17
|
-
<Responsive>
|
|
18
|
-
<div className={classes.actions}>{children}</div>
|
|
19
|
-
</Responsive>
|
|
20
|
-
);
|
|
21
|
-
};
|