@centreon/ui 24.10.8 → 24.10.10

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centreon/ui",
3
- "version": "24.10.8",
3
+ "version": "24.10.10",
4
4
  "description": "Centreon UI Components",
5
5
  "scripts": {
6
6
  "update:deps": "pnpx npm-check-updates -i --format group",
@@ -30,23 +30,15 @@ interface StylesProps {
30
30
  const useStyles = makeStyles<StylesProps>()(
31
31
  (theme, { hasCustomDropZoneContent, isDraggingOver }) => ({
32
32
  dropzone: {
33
- '&:hover': hasCustomDropZoneContent
34
- ? undefined
35
- : {
36
- backgroundColor: alpha(theme.palette.primary.main, 0.1),
37
- border: `${theme.spacing(0.3)} dashed ${
38
- theme.palette.primary.main
39
- }`,
40
- boxShadow: theme.shadows[3],
41
- cursor: 'pointer'
42
- },
43
- border: `${theme.spacing(0.3)} dashed ${
44
- hasCustomDropZoneContent && !isDraggingOver
45
- ? 'transparent'
46
- : theme.palette.primary.main
47
- }`,
33
+ '&:hover': {
34
+ backgroundColor: alpha(theme.palette.primary.main, 0.1),
35
+ boxShadow: theme.shadows[3],
36
+ cursor: 'pointer'
37
+ },
38
+ border: `${theme.spacing(0.3)} dashed ${theme.palette.primary.main}`,
48
39
  boxShadow: isDraggingOver ? theme.shadows[3] : theme.shadows[0],
49
- padding: hasCustomDropZoneContent ? undefined : theme.spacing(1),
40
+ borderRadius: `${theme.shape.borderRadius}px`,
41
+ padding: theme.spacing(0.5, 1),
50
42
  width: hasCustomDropZoneContent ? '100%' : theme.spacing(50)
51
43
  },
52
44
  dropzoneInfo: {
@@ -66,7 +58,7 @@ const useStyles = makeStyles<StylesProps>()(
66
58
  export type CustomDropZoneContentProps = Pick<
67
59
  UseDropzoneState,
68
60
  'openFileExplorer'
69
- >;
61
+ > & { files: FileList | null; label?: string };
70
62
 
71
63
  interface Props {
72
64
  CustomDropZoneContent?: ({
@@ -79,6 +71,7 @@ interface Props {
79
71
  maxFileSize?: number;
80
72
  multiple?: boolean;
81
73
  resetFilesStatusAndUploadData: () => void;
74
+ label?: string;
82
75
  }
83
76
 
84
77
  const getExtensions = cond([
@@ -115,7 +108,8 @@ const Dropzone = ({
115
108
  accept,
116
109
  CustomDropZoneContent,
117
110
  maxFileSize,
118
- className
111
+ className,
112
+ label
119
113
  }: Props): JSX.Element => {
120
114
  const hasCustomDropZoneContent = !isNil(CustomDropZoneContent);
121
115
  const {
@@ -145,25 +139,29 @@ const Dropzone = ({
145
139
  <div>
146
140
  <Box
147
141
  className={cx(classes.dropzone, className)}
148
- onClick={!hasCustomDropZoneContent ? openFileExplorer : undefined}
142
+ onClick={openFileExplorer}
149
143
  onDragLeave={dragOver(false)}
150
144
  onDragOver={dragOver(true)}
151
145
  onDrop={dropFiles}
152
146
  >
153
147
  <div className={classes.dropzoneInfo}>
154
148
  {hasCustomDropZoneContent ? (
155
- <CustomDropZoneContent openFileExplorer={openFileExplorer} />
149
+ <CustomDropZoneContent
150
+ openFileExplorer={openFileExplorer}
151
+ files={files}
152
+ label={label}
153
+ />
156
154
  ) : (
157
- <>
155
+ <Box sx={{ display: 'flex', gap: 2, alignItems: 'center' }}>
158
156
  <PostAddIcon color="primary" fontSize="large" />
159
157
  <Typography>
160
158
  {t(labelDropOr)} {t(labelSelectAFile)}
161
159
  </Typography>
162
- </>
160
+ </Box>
163
161
  )}
164
162
  <input
165
163
  accept={accept}
166
- aria-label={t(labelSelectAFile) || ''}
164
+ aria-label={t(labelSelectAFile)}
167
165
  className={classes.input}
168
166
  multiple={multiple}
169
167
  ref={fileInputRef}
@@ -43,7 +43,8 @@ const useStyles = makeStyles()((theme) => ({
43
43
  },
44
44
  tooltip: {
45
45
  maxWidth: theme.spacing(60)
46
- }
46
+ },
47
+ title: {}
47
48
  }));
48
49
 
49
50
  const CollapsibleGroup = ({
@@ -97,7 +98,7 @@ const CollapsibleGroup = ({
97
98
  <div className={classes.groupTitleIcon}>
98
99
  <Typography
99
100
  className="groupText"
100
- variant="h5"
101
+ variant="h6"
101
102
  {...group?.titleAttributes}
102
103
  >
103
104
  {t(group?.name as string)}
@@ -131,3 +131,42 @@ describe('Form list', () => {
131
131
  cy.makeSnapshot();
132
132
  });
133
133
  });
134
+
135
+ const initializeFile = (): void => {
136
+ cy.mount({
137
+ Component: (
138
+ <Form
139
+ initialValues={{
140
+ list: []
141
+ }}
142
+ inputs={[
143
+ {
144
+ fieldName: 'file',
145
+ group: '',
146
+ label: 'json',
147
+ type: InputType.File,
148
+ file: {
149
+ accept: '.json'
150
+ }
151
+ }
152
+ ]}
153
+ submit={cy.stub()}
154
+ validationSchema={object()}
155
+ />
156
+ )
157
+ });
158
+ };
159
+
160
+ describe('File', () => {
161
+ it('uploads a file when a file is selected', () => {
162
+ initializeFile();
163
+
164
+ cy.contains('Drop or select a file').should('be.visible');
165
+ cy.findByLabelText('select a file').selectFile('package.json', {
166
+ force: true
167
+ });
168
+ cy.contains('package.json').should('be.visible');
169
+
170
+ cy.makeSnapshot();
171
+ });
172
+ });
@@ -1,7 +1,7 @@
1
1
  import { useCallback, useMemo, useState } from 'react';
2
2
 
3
3
  import { FormikValues, useFormikContext } from 'formik';
4
- import { path, equals, isNil, map, not, prop, type } from 'ramda';
4
+ import { equals, isNil, map, not, path, prop, type } from 'ramda';
5
5
  import { useTranslation } from 'react-i18next';
6
6
 
7
7
  import { FormHelperText, Stack } from '@mui/material';
@@ -53,7 +53,15 @@ const Autocomplete = ({
53
53
 
54
54
  const [inputText, setInputText] = useState('');
55
55
 
56
- const { values, setFieldValue, errors } = useFormikContext<FormikValues>();
56
+ const {
57
+ values,
58
+ setFieldValue,
59
+ setFieldTouched,
60
+ errors,
61
+ touched,
62
+ setValues,
63
+ setTouched
64
+ } = useFormikContext<FormikValues>();
57
65
 
58
66
  const isMultiple = equals(inputType, InputType.MultiAutocomplete);
59
67
 
@@ -67,11 +75,20 @@ const Autocomplete = ({
67
75
  setInputText('');
68
76
 
69
77
  if (change) {
70
- change({ setFieldValue, value: normalizedNewValues });
78
+ setFieldTouched(fieldName, true, false);
79
+ change({
80
+ setFieldValue,
81
+ value: normalizedNewValues,
82
+ setFieldTouched,
83
+ setValues,
84
+ values,
85
+ setTouched
86
+ });
71
87
 
72
88
  return;
73
89
  }
74
90
 
91
+ setFieldTouched(fieldName, true, false);
75
92
  setFieldValue(fieldName, normalizedNewValues);
76
93
  };
77
94
 
@@ -83,6 +100,10 @@ const Autocomplete = ({
83
100
  );
84
101
 
85
102
  const getError = useCallback((): Array<string> | undefined => {
103
+ if (!path([...fieldName.split('.')], touched)) {
104
+ return undefined;
105
+ }
106
+
86
107
  const error = path([...fieldName.split('.')], errors) as
87
108
  | Array<string>
88
109
  | string
@@ -111,7 +132,7 @@ const Autocomplete = ({
111
132
  const filteredError = formattedError?.filter(Boolean);
112
133
 
113
134
  return (filteredError as Array<string>) || undefined;
114
- }, [errors, fieldName, isMultiple, selectedValues]);
135
+ }, [errors, fieldName, isMultiple, selectedValues, touched]);
115
136
 
116
137
  const textChange = useCallback(
117
138
  (event): void => setInputText(event.target.value),
@@ -167,6 +188,7 @@ const Autocomplete = ({
167
188
  value={getValues() ?? null}
168
189
  onChange={changeValues}
169
190
  onTextChange={textChange}
191
+ style={{ width: autocomplete?.fullWidth ?? true ? 'auto' : '180px' }}
170
192
  />
171
193
  {inputErrors && (
172
194
  <Stack>
@@ -180,6 +202,7 @@ const Autocomplete = ({
180
202
  </div>
181
203
  ),
182
204
  memoProps: [
205
+ values,
183
206
  getValues(),
184
207
  inputErrors,
185
208
  additionalLabel,
@@ -1,7 +1,7 @@
1
1
  import { useCallback, useMemo } from 'react';
2
2
 
3
3
  import { FormikValues, useFormikContext } from 'formik';
4
- import { path, equals, isEmpty, propEq, reject, split } from 'ramda';
4
+ import { equals, isEmpty, path, propEq, reject, split } from 'ramda';
5
5
  import { useTranslation } from 'react-i18next';
6
6
 
7
7
  import {
@@ -30,8 +30,15 @@ const ConnectedAutocomplete = ({
30
30
  }: InputPropsWithoutGroup): JSX.Element => {
31
31
  const { t } = useTranslation();
32
32
 
33
- const { values, touched, errors, setFieldValue, setFieldTouched } =
34
- useFormikContext<FormikValues>();
33
+ const {
34
+ values,
35
+ touched,
36
+ errors,
37
+ setFieldValue,
38
+ setFieldTouched,
39
+ setValues,
40
+ setTouched
41
+ } = useFormikContext<FormikValues>();
35
42
 
36
43
  const filterKey = connectedAutocomplete?.filterKey || defaultFilterKey;
37
44
 
@@ -58,18 +65,20 @@ const ConnectedAutocomplete = ({
58
65
  const changeAutocomplete = useCallback(
59
66
  (_, value): void => {
60
67
  if (change) {
61
- change({ setFieldValue, value });
68
+ change({
69
+ setFieldValue,
70
+ value,
71
+ setFieldTouched,
72
+ setValues,
73
+ values,
74
+ setTouched
75
+ });
62
76
 
63
77
  return;
64
78
  }
65
79
 
80
+ setFieldTouched(fieldName, true, false);
66
81
  setFieldValue(fieldName, value);
67
-
68
- if (path(fieldNamePath, touched)) {
69
- return;
70
- }
71
-
72
- setFieldTouched(fieldName, true);
73
82
  },
74
83
  [fieldName, touched, additionalMemoProps]
75
84
  );
@@ -105,6 +114,7 @@ const ConnectedAutocomplete = ({
105
114
  const deleteItem = (_, option): void => {
106
115
  const newValue = reject(propEq(option.id, 'id'), value);
107
116
 
117
+ setFieldTouched(fieldName, true, false);
108
118
  setFieldValue(fieldName, newValue);
109
119
  };
110
120
 
@@ -0,0 +1,69 @@
1
+ import DescriptionOutlinedIcon from '@mui/icons-material/DescriptionOutlined';
2
+ import { Box, Typography } from '@mui/material';
3
+ import { FormikValues, useFormikContext } from 'formik';
4
+ import { path, split } from 'ramda';
5
+ import { useMemo } from 'react';
6
+ import { useTranslation } from 'react-i18next';
7
+ import FileDropZone, { transformFileListToArray } from '../../FileDropZone';
8
+ import { InputPropsWithoutGroup } from './models';
9
+
10
+ const File = ({
11
+ fieldName,
12
+ file,
13
+ change,
14
+ dataTestId,
15
+ label
16
+ }: InputPropsWithoutGroup): JSX.Element => {
17
+ const { t } = useTranslation();
18
+
19
+ const { values, setFieldValue, setFieldTouched } =
20
+ useFormikContext<FormikValues>();
21
+
22
+ const fieldNamePath = split('.', fieldName);
23
+
24
+ const files = useMemo(
25
+ () => path(fieldNamePath, values),
26
+ [values]
27
+ ) as FileList;
28
+
29
+ const filesArray = transformFileListToArray(files);
30
+
31
+ const changeFiles = (newFiles: FileList | null): void => {
32
+ if (change) {
33
+ change({ setFieldValue, setFieldTouched, value: newFiles });
34
+
35
+ return;
36
+ }
37
+
38
+ setFieldValue(fieldName, newFiles);
39
+ };
40
+
41
+ return (
42
+ <Box data-testid={dataTestId} aria-label={t(label)}>
43
+ <Typography variant="h6">{t(label)}</Typography>
44
+ <Box sx={{ display: 'flex', gap: 1, flexDirection: 'column' }}>
45
+ <FileDropZone
46
+ {...file}
47
+ accept={file?.accept || '*'}
48
+ files={files || null}
49
+ changeFiles={changeFiles}
50
+ resetFilesStatusAndUploadData={() => undefined}
51
+ label={label}
52
+ />
53
+ <Box sx={{ display: 'flex', gap: 1, flexDirection: 'column' }}>
54
+ {filesArray.map((file) => (
55
+ <Box
56
+ key={file.name}
57
+ sx={{ display: 'flex', gap: 1, flexDirection: 'row' }}
58
+ >
59
+ <DescriptionOutlinedIcon color="success" fontSize="small" />
60
+ <Typography>{file.name}</Typography>
61
+ </Box>
62
+ ))}
63
+ </Box>
64
+ </Box>
65
+ </Box>
66
+ );
67
+ };
68
+
69
+ export default File;
@@ -2,6 +2,8 @@ import { makeStyles } from 'tss-react/mui';
2
2
 
3
3
  import { InputPropsWithoutGroup } from './models';
4
4
 
5
+ import { Box, Typography } from '@mui/material';
6
+ import { FormikValues, useFormikContext } from 'formik';
5
7
  import { getInput } from '.';
6
8
 
7
9
  interface StylesProps {
@@ -22,13 +24,22 @@ const useStyles = makeStyles<StylesProps>()(
22
24
  })
23
25
  );
24
26
 
25
- const Grid = ({ grid }: InputPropsWithoutGroup): JSX.Element => {
27
+ const Grid = ({
28
+ grid,
29
+ hideInput
30
+ }: InputPropsWithoutGroup): JSX.Element | null => {
26
31
  const { classes, cx } = useStyles({
27
32
  alignItems: grid?.alignItems,
28
33
  columns: grid?.columns.length,
29
34
  gridTemplateColumns: grid?.gridTemplateColumns
30
35
  });
31
36
 
37
+ const { values } = useFormikContext<FormikValues>();
38
+
39
+ if (hideInput?.(values) ?? false) {
40
+ return null;
41
+ }
42
+
32
43
  const className = grid?.className || '';
33
44
 
34
45
  return (
@@ -36,7 +47,24 @@ const Grid = ({ grid }: InputPropsWithoutGroup): JSX.Element => {
36
47
  {grid?.columns.map((field) => {
37
48
  const Input = getInput(field.type);
38
49
 
39
- return <Input key={field.fieldName} {...field} />;
50
+ if (field.hideInput?.(values) ?? false) {
51
+ return null;
52
+ }
53
+
54
+ return (
55
+ <Box sx={{ width: '100%' }} key={field.fieldName}>
56
+ {field.additionalLabel && (
57
+ <Typography
58
+ sx={{ marginBottom: 0.5, color: 'primary.main' }}
59
+ className={cx(field?.additionalLabelClassName)}
60
+ variant="h6"
61
+ >
62
+ {field.additionalLabel}
63
+ </Typography>
64
+ )}
65
+ <Input {...field} />
66
+ </Box>
67
+ );
40
68
  })}
41
69
  </div>
42
70
  );
@@ -1,5 +1,5 @@
1
1
  import { FormikValues, useFormikContext } from 'formik';
2
- import { path, equals, includes, split, type } from 'ramda';
2
+ import { equals, includes, path, split, type } from 'ramda';
3
3
  import { useTranslation } from 'react-i18next';
4
4
 
5
5
  import {
@@ -26,12 +26,20 @@ const Radio = ({
26
26
  }: InputPropsWithoutGroup): JSX.Element => {
27
27
  const { t } = useTranslation();
28
28
 
29
- const { values, setFieldValue } = useFormikContext<FormikValues>();
29
+ const { values, setFieldValue, setFieldTouched, setValues, setTouched } =
30
+ useFormikContext<FormikValues>();
30
31
 
31
32
  const changeRadio = (_, value): void => {
32
33
  if (includes(value, ['true', 'false'])) {
33
34
  if (change) {
34
- change({ setFieldValue, value: equals(value, 'true') });
35
+ change({
36
+ setFieldValue,
37
+ value: equals(value, 'true'),
38
+ values,
39
+ setFieldTouched,
40
+ setValues,
41
+ setTouched
42
+ });
35
43
 
36
44
  return;
37
45
  }
@@ -42,7 +50,7 @@ const Radio = ({
42
50
  }
43
51
 
44
52
  if (change) {
45
- change({ setFieldValue, value });
53
+ change({ setFieldValue, value, values, setFieldTouched, setValues });
46
54
 
47
55
  return;
48
56
  }
@@ -22,11 +22,19 @@ const Switch = ({
22
22
  }: InputPropsWithoutGroup): JSX.Element => {
23
23
  const { t } = useTranslation();
24
24
 
25
- const { values, setFieldValue } = useFormikContext<FormikValues>();
25
+ const { values, setFieldValue, setFieldTouched, setValues, setTouched } =
26
+ useFormikContext<FormikValues>();
26
27
 
27
28
  const changeSwitchValue = (event: ChangeEvent<HTMLInputElement>): void => {
28
29
  if (change) {
29
- change({ setFieldValue, value: event.target.checked });
30
+ change({
31
+ setFieldValue,
32
+ value: event.target.checked,
33
+ values,
34
+ setFieldTouched,
35
+ setValues,
36
+ setTouched
37
+ });
30
38
 
31
39
  return;
32
40
  }
@@ -2,11 +2,11 @@ import { ChangeEvent, useCallback, useState } from 'react';
2
2
 
3
3
  import { FormikValues, useFormikContext } from 'formik';
4
4
  import {
5
- path,
6
5
  equals,
7
6
  gt,
8
7
  isEmpty,
9
8
  not,
9
+ path,
10
10
  split,
11
11
  type as variableType
12
12
  } from 'ramda';
@@ -42,7 +42,9 @@ const Text = ({
42
42
  touched,
43
43
  errors,
44
44
  handleBlur,
45
- setFieldTouched
45
+ setFieldTouched,
46
+ setValues,
47
+ setTouched
46
48
  } = useFormikContext<FormikValues>();
47
49
 
48
50
  const fieldNamePath = split('.', fieldName);
@@ -50,7 +52,14 @@ const Text = ({
50
52
  const changeText = (event: ChangeEvent<HTMLInputElement>): void => {
51
53
  const { value } = event.target;
52
54
  if (change) {
53
- change({ setFieldValue, value, setFieldTouched });
55
+ change({
56
+ setFieldValue,
57
+ value,
58
+ setFieldTouched,
59
+ setValues,
60
+ values,
61
+ setTouched
62
+ });
54
63
 
55
64
  return;
56
65
  }
@@ -113,7 +122,7 @@ const Text = ({
113
122
  return useMemoComponent({
114
123
  Component: (
115
124
  <TextField
116
- fullWidth
125
+ fullWidth={text?.fullWidth ?? true}
117
126
  EndAdornment={EndAdornment}
118
127
  ariaLabel={t(label) || ''}
119
128
  autoFocus={autoFocus}
@@ -36,6 +36,7 @@ import CheckboxGroup from './CheckboxGroup';
36
36
  import ConnectedAutocomplete from './ConnectedAutocomplete';
37
37
  import Custom from './Custom';
38
38
  import FieldsTable from './FieldsTable/FieldsTable';
39
+ import File from './File';
39
40
  import Grid from './Grid';
40
41
  import List from './List/List';
41
42
  import LoadingSkeleton from './LoadingSkeleton';
@@ -78,6 +79,7 @@ export const getInput = cond<
78
79
  always(CheckboxGroup)
79
80
  ],
80
81
  [equals(InputType.List) as (b: InputType) => boolean, always(List)],
82
+ [equals(InputType.File) as (b: InputType) => boolean, always(File)],
81
83
  [T, always(TextInput)]
82
84
  ]);
83
85
 
@@ -113,7 +115,8 @@ const useStyles = makeStyles<StylesProps>()((theme, { groupDirection }) => ({
113
115
  display: 'flex',
114
116
  flexDirection: 'column',
115
117
  marginTop: theme.spacing(1),
116
- rowGap: theme.spacing(2)
118
+ rowGap: theme.spacing(2),
119
+ marginBottom: theme.spacing(1)
117
120
  }
118
121
  }));
119
122
 
@@ -165,7 +168,7 @@ const Inputs = ({
165
168
  );
166
169
 
167
170
  return pluck('name', usedGroups);
168
- }, []);
171
+ }, [inputsByGroup, groups]);
169
172
 
170
173
  const sortedInputsByGroup = useMemo(
171
174
  () =>
@@ -19,7 +19,8 @@ export enum InputType {
19
19
  Custom = 10,
20
20
  Checkbox = 11,
21
21
  CheckboxGroup = 12,
22
- List = 13
22
+ List = 13,
23
+ File = 14
23
24
  }
24
25
 
25
26
  interface FieldsTableGetRequiredProps {
@@ -37,8 +38,16 @@ export interface InputProps {
37
38
  autocomplete?: {
38
39
  creatable?: boolean;
39
40
  options: Array<SelectEntry>;
41
+ fullWidth?: boolean;
40
42
  };
41
- change?: ({ setFieldValue, value, setFieldTouched }) => void;
43
+ change?: ({
44
+ setFieldValue,
45
+ value,
46
+ setFieldTouched,
47
+ setValues,
48
+ values,
49
+ setTouched
50
+ }) => void;
42
51
  checkbox?: {
43
52
  direction?: 'horizontal' | 'vertical';
44
53
  labelPlacement?: LabelPlacement;
@@ -51,6 +60,12 @@ export interface InputProps {
51
60
  filterKey?: string;
52
61
  getRenderedOptionText?: (option) => string | JSX.Element;
53
62
  };
63
+ file?: {
64
+ multiple?: boolean;
65
+ accept?: string;
66
+ maxFileSize?: number;
67
+ CustomDropZoneContent: ({ files }) => JSX.Element;
68
+ };
54
69
  custom?: {
55
70
  Component: React.ComponentType<InputPropsWithoutGroup>;
56
71
  };
@@ -103,6 +118,7 @@ export interface InputProps {
103
118
  placeholder?: string;
104
119
  type?: string;
105
120
  min?: number;
121
+ fullWidth?: boolean;
106
122
  };
107
123
  type: InputType;
108
124
  }
@@ -8,7 +8,7 @@ import { Typography } from '@mui/material';
8
8
  import { SelectEntry } from '../InputField/Select';
9
9
  import { Listing } from '../api/models';
10
10
 
11
- import { array, boolean, number, object, string } from 'yup';
11
+ import { array, boolean, mixed, number, object, string } from 'yup';
12
12
  import {
13
13
  Group,
14
14
  InputProps,
@@ -78,7 +78,8 @@ export const basicFormValidationSchema = object().shape({
78
78
  })
79
79
  ),
80
80
  scopes: array().of(string().min(3, '3 characters min').required('Required')),
81
- sports: array().of(selectEntryValidationSchema.required('Required'))
81
+ sports: array().of(selectEntryValidationSchema.required('Required')),
82
+ file: mixed()
82
83
  });
83
84
 
84
85
  const roleEntries: Array<SelectEntry> = [
@@ -134,7 +135,8 @@ export const basicFormInitialValues = {
134
135
  }
135
136
  ],
136
137
  scopes: [],
137
- sports: []
138
+ sports: [],
139
+ file: null
138
140
  };
139
141
 
140
142
  export const classOptions = [...Array(10).keys()].map((idx) => ({
@@ -444,6 +446,16 @@ export const basicFormInputs: Array<InputProps> = [
444
446
  multilineRows: 4
445
447
  },
446
448
  type: InputType.Text
449
+ },
450
+ {
451
+ fieldName: 'file',
452
+ group: 'First group',
453
+ label: 'File',
454
+ type: InputType.File,
455
+ file: {
456
+ accept: 'image/*',
457
+ multiple: true
458
+ }
447
459
  }
448
460
  ];
449
461
 
@@ -5,3 +5,4 @@ export const labelSaved = 'Saved';
5
5
  export const labelReset = 'Reset';
6
6
  export const labelDisplayThePassword = 'Display the password';
7
7
  export const labelHideThePassword = 'Hide the password';
8
+ export const labelDropOrSelectAFile = 'Drop or select a file';
@@ -53,7 +53,8 @@ const initializeDataTableEmpty = (canCreate = false): void => {
53
53
  actions: {
54
54
  create: 'Create'
55
55
  },
56
- title: 'Welcome'
56
+ title: 'Welcome',
57
+ description: 'Description'
57
58
  }}
58
59
  onCreate={cy.stub()}
59
60
  />
@@ -48,6 +48,23 @@ export const AsEmptyState: Story = {
48
48
  }
49
49
  };
50
50
 
51
+ export const AsEmptyStateWithDescription: Story = {
52
+ args: {
53
+ children: (
54
+ <DataTable.EmptyState
55
+ labels={{
56
+ actions: {
57
+ create: 'Create item'
58
+ },
59
+ title: 'No items found',
60
+ description: 'Description'
61
+ }}
62
+ />
63
+ ),
64
+ isEmpty: true
65
+ }
66
+ };
67
+
51
68
  export const withFixedHeightContainer: Story = {
52
69
  args: { ...Default.args },
53
70
  render: (args) => (
@@ -10,7 +10,6 @@ const useStyles = makeStyles()((theme) => ({
10
10
  display: 'flex',
11
11
  flexDirection: 'column',
12
12
  gap: theme.spacing(4),
13
-
14
13
  h2: {
15
14
  color: theme.palette.text.primary,
16
15
  font: 'normal normal 600 34px/36px Roboto',
@@ -45,7 +45,7 @@ const useStyles = makeStyles<{
45
45
  width: '400px'
46
46
  },
47
47
  '&[data-size="xlarge"] .MuiDialog-paper': {
48
- maxWidth: '1400px',
48
+ maxWidth: '900px',
49
49
  width: 'calc(100% - 64px)'
50
50
  }
51
51
  },