@centreon/ui 24.9.2 → 24.9.4

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.9.2",
3
+ "version": "24.9.4",
4
4
  "description": "Centreon UI Components",
5
5
  "scripts": {
6
6
  "update:deps": "pnpx npm-check-updates -i --format group",
@@ -134,6 +134,7 @@
134
134
  "anylogger": "^1.0.11",
135
135
  "d3-array": "3.2.4",
136
136
  "dayjs": "^1.11.12",
137
+ "highlight.js": "^11.10.0",
137
138
  "humanize-duration": "^3.32.1",
138
139
  "lexical": "^0.17.0",
139
140
  "notistack": "^3.0.1",
@@ -36,15 +36,21 @@ const Text = ({
36
36
 
37
37
  const [isVisible, setIsVisible] = useState(false);
38
38
 
39
- const { values, setFieldValue, touched, errors, handleBlur } =
40
- useFormikContext<FormikValues>();
39
+ const {
40
+ values,
41
+ setFieldValue,
42
+ touched,
43
+ errors,
44
+ handleBlur,
45
+ setFieldTouched
46
+ } = useFormikContext<FormikValues>();
41
47
 
42
48
  const fieldNamePath = split('.', fieldName);
43
49
 
44
50
  const changeText = (event: ChangeEvent<HTMLInputElement>): void => {
45
51
  const { value } = event.target;
46
52
  if (change) {
47
- change({ setFieldValue, value });
53
+ change({ setFieldValue, value, setFieldTouched });
48
54
 
49
55
  return;
50
56
  }
@@ -111,7 +117,7 @@ const Text = ({
111
117
  EndAdornment={EndAdornment}
112
118
  ariaLabel={t(label) || ''}
113
119
  autoFocus={autoFocus}
114
- dataTestId={dataTestId || ''}
120
+ dataTestId={dataTestId || label}
115
121
  disabled={disabled}
116
122
  error={error as string | undefined}
117
123
  label={t(label)}
@@ -123,6 +129,11 @@ const Text = ({
123
129
  value={value || ''}
124
130
  onBlur={handleBlur(fieldName)}
125
131
  onChange={changeText}
132
+ inputProps={{
133
+ 'data-testid': dataTestId || label,
134
+ 'aria-label': label,
135
+ min: text?.min
136
+ }}
126
137
  />
127
138
  ),
128
139
  memoProps: [
@@ -38,7 +38,7 @@ export interface InputProps {
38
38
  creatable?: boolean;
39
39
  options: Array<SelectEntry>;
40
40
  };
41
- change?: ({ setFieldValue, value }) => void;
41
+ change?: ({ setFieldValue, value, setFieldTouched }) => void;
42
42
  checkbox?: {
43
43
  direction?: 'horizontal' | 'vertical';
44
44
  labelPlacement?: LabelPlacement;
@@ -102,6 +102,7 @@ export interface InputProps {
102
102
  multilineRows?: number;
103
103
  placeholder?: string;
104
104
  type?: string;
105
+ min?: number;
105
106
  };
106
107
  type: InputType;
107
108
  }
@@ -1,4 +1,4 @@
1
- import { Dispatch, SetStateAction, useEffect, useState } from 'react';
1
+ import { type Dispatch, type SetStateAction, useEffect, useState } from 'react';
2
2
 
3
3
  import { makeStyles } from 'tss-react/mui';
4
4
 
@@ -6,9 +6,9 @@ import {
6
6
  ClickAwayListener,
7
7
  Paper,
8
8
  Popper,
9
- PopperPlacementType
9
+ type PopperPlacementType
10
10
  } from '@mui/material';
11
- import { PopperProps } from '@mui/material/Popper';
11
+ import type { PopperProps } from '@mui/material/Popper';
12
12
 
13
13
  import { IconButton } from '..';
14
14
 
@@ -80,7 +80,7 @@ const PopoverMenu = ({
80
80
  };
81
81
 
82
82
  useEffect(() => {
83
- if (!canOpen) {
83
+ if (!canOpen && isOpen) {
84
84
  close();
85
85
  }
86
86
  }, [canOpen]);
@@ -0,0 +1,155 @@
1
+ import { ThemeMode, userAtom } from '@centreon/ui-context';
2
+ import { mount } from 'cypress/react18';
3
+ import { Provider, createStore } from 'jotai';
4
+ import SnackbarProvider from '../../Snackbar/SnackbarProvider';
5
+ import ThemeProvider from '../../ThemeProvider';
6
+ import CopyCommand, { CopyCommandProps } from './CopyCommand';
7
+
8
+ const initialize = (props: CopyCommandProps & { theme?: ThemeMode }): void => {
9
+ const store = createStore();
10
+ store.set(userAtom, { themeMode: props.theme || ThemeMode.light });
11
+ mount(
12
+ <Provider store={store}>
13
+ <ThemeProvider>
14
+ <SnackbarProvider>
15
+ <CopyCommand {...props} />
16
+ </SnackbarProvider>
17
+ </ThemeProvider>
18
+ </Provider>
19
+ );
20
+ };
21
+
22
+ describe('CopyCommand', () => {
23
+ it('displays bash code when props are set', () => {
24
+ initialize({
25
+ text: `# a simple command
26
+ echo "hello" | grep "hel"`,
27
+ language: 'bash',
28
+ commandToCopy: 'echo "hello" | grep "hel"'
29
+ });
30
+
31
+ cy.contains('# a simple command').should('be.visible');
32
+ cy.contains('echo').should('be.visible');
33
+ cy.contains('bash').should('be.visible');
34
+ cy.findByTestId('Copy command').should('be.visible');
35
+
36
+ cy.makeSnapshot();
37
+ });
38
+
39
+ it('displays yaml code when props are set', () => {
40
+ initialize({
41
+ text: `key:
42
+ with:
43
+ input: "input"`,
44
+ language: 'yaml',
45
+ commandToCopy: 'echo "hello" | grep "hel"'
46
+ });
47
+
48
+ cy.contains('key').should('be.visible');
49
+ cy.contains('"input"').should('be.visible');
50
+ cy.contains('yaml').should('be.visible');
51
+
52
+ cy.makeSnapshot();
53
+ });
54
+
55
+ it('displays php code when props are set', () => {
56
+ initialize({
57
+ text: `<?php
58
+ echo 'Hello ' . htmlspecialchars($_POST["name"]) . '!';
59
+ ?>`,
60
+ language: 'php',
61
+ commandToCopy: 'echo "hello" | grep "hel"'
62
+ });
63
+
64
+ cy.contains('echo').should('be.visible');
65
+ cy.contains('"name"').should('be.visible');
66
+ cy.contains('php').should('be.visible');
67
+
68
+ cy.makeSnapshot();
69
+ });
70
+
71
+ it('displays json code when props are set', () => {
72
+ initialize({
73
+ text: `{
74
+ "number": 1,
75
+ "boolean": true,
76
+ "array": [
77
+ {
78
+ "string": "text"
79
+ }
80
+ ]
81
+ }`,
82
+ language: 'json',
83
+ commandToCopy: 'echo "hello" | grep "hel"'
84
+ });
85
+
86
+ cy.contains('"number"').should('be.visible');
87
+ cy.contains('true').should('be.visible');
88
+ cy.contains('json').should('be.visible');
89
+
90
+ cy.makeSnapshot();
91
+ });
92
+
93
+ it('does not display the copy button when the corresponding prop is not passed', () => {
94
+ initialize({
95
+ text: `{
96
+ "number": 1,
97
+ "boolean": true,
98
+ "array": [
99
+ {
100
+ "string": "text"
101
+ }
102
+ ]
103
+ }`,
104
+ language: 'json'
105
+ });
106
+
107
+ cy.findByTestId('Copy command').should('not.exist');
108
+
109
+ cy.makeSnapshot();
110
+ });
111
+
112
+ it('displays the highlighted code in dark mode when the theme is changed', () => {
113
+ initialize({
114
+ text: `{
115
+ "number": 1,
116
+ "boolean": true,
117
+ "array": [
118
+ {
119
+ "string": "text"
120
+ }
121
+ ]
122
+ }`,
123
+ language: 'json',
124
+ theme: ThemeMode.dark
125
+ });
126
+
127
+ cy.get('.hljs-keyword').should('have.css', 'color', 'rgb(255, 123, 114)');
128
+
129
+ cy.makeSnapshot();
130
+ });
131
+
132
+ it('copies the command to the clipboard when the button is clicked', () => {
133
+ initialize({
134
+ text: `# a simple command
135
+ echo "hello" | grep "hel"`,
136
+ language: 'bash',
137
+ commandToCopy: 'echo "hello" | grep "hel"'
138
+ });
139
+
140
+ cy.window()
141
+ .its('navigator.clipboard')
142
+ .then((clipboard) => {
143
+ cy.spy(clipboard, 'writeText').as('writeText');
144
+ });
145
+
146
+ cy.findByTestId('Copy command').click();
147
+
148
+ cy.get('@writeText').should(
149
+ 'have.been.calledOnceWith',
150
+ 'echo "hello" | grep "hel"'
151
+ );
152
+
153
+ cy.makeSnapshot();
154
+ });
155
+ });
@@ -0,0 +1,54 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import CopyCommand from './CopyCommand';
3
+
4
+ const meta: Meta<typeof CopyCommand> = {
5
+ component: CopyCommand
6
+ };
7
+
8
+ export default meta;
9
+ type Story = StoryObj<typeof CopyCommand>;
10
+
11
+ export const Default: Story = {
12
+ args: {
13
+ text: 'key:\n with:\n input: "heyyy"',
14
+ language: 'yaml'
15
+ }
16
+ };
17
+
18
+ export const OneLine: Story = {
19
+ args: {
20
+ text: 'echo "hello" | grep "hel"',
21
+ language: 'bash'
22
+ }
23
+ };
24
+
25
+ export const WithCopyCommandIcon: Story = {
26
+ args: {
27
+ text: `# a simple command
28
+ echo "hello" | grep "hel"`,
29
+ language: 'bash',
30
+ commandToCopy: 'echo "hello" | grep "hel"'
31
+ }
32
+ };
33
+
34
+ export const UsingJson: Story = {
35
+ args: {
36
+ text: `{
37
+ "number": 1,
38
+ "boolean": true,
39
+ "array": [
40
+ {
41
+ "string": "text"
42
+ }
43
+ ]
44
+ }`,
45
+ language: 'json'
46
+ }
47
+ };
48
+
49
+ export const UsingPhp: Story = {
50
+ args: {
51
+ text: "<?php echo '<p>Hello World</p>'; ?>",
52
+ language: 'php'
53
+ }
54
+ };
@@ -0,0 +1,93 @@
1
+ import { ThemeMode } from '@centreon/ui-context';
2
+ import { Theme } from '@mui/material';
3
+ import { equals } from 'ramda';
4
+ import { makeStyles } from 'tss-react/mui';
5
+
6
+ const isDarkMode = (theme: Theme): boolean => {
7
+ return equals(theme.palette.mode, ThemeMode.dark);
8
+ };
9
+
10
+ export const useCopyCommandStyle = makeStyles()((theme) => ({
11
+ code: {
12
+ background: theme.palette.background.default,
13
+ padding: theme.spacing(1.5),
14
+ borderRadius: theme.shape.borderRadius
15
+ },
16
+ codeContainer: {
17
+ position: 'relative'
18
+ },
19
+ languageChip: {
20
+ position: 'absolute',
21
+ top: 0,
22
+ right: 0,
23
+ borderRadius: `0px ${theme.shape.borderRadius}px ${theme.shape.borderRadius}px ${theme.shape.borderRadius}px`,
24
+ background: theme.palette.background.listingHeader,
25
+ color: theme.palette.common.white,
26
+ padding: `0px ${theme.spacing(0.5)}`,
27
+ fontSize: theme.typography.body2.fontSize
28
+ },
29
+ copyButton: {
30
+ position: 'absolute',
31
+ top: theme.spacing(0.5),
32
+ right: theme.spacing(6),
33
+ opacity: 0.8,
34
+ '&:hover': {
35
+ opacity: 1
36
+ }
37
+ },
38
+ highlight: {
39
+ '.hljs': {
40
+ color: isDarkMode(theme) ? '#c9d1d9' : '#24292e'
41
+ },
42
+ '.hljs-doctag, .hljs-keyword, .hljs-meta, .hljs-keyword, .hljs-template-tag, .hljs-template-variable, .hljs-type, .hljs-variable.language_':
43
+ {
44
+ color: isDarkMode(theme) ? '#ff7b72' : '#d73a49'
45
+ },
46
+ '.hljs-title, .hljs-title.class,_ .hljs-title.class_.inherited,__ .hljs-title.function_':
47
+ {
48
+ color: isDarkMode(theme) ? '#d2a8ff' : '#6f42c1'
49
+ },
50
+ '.hljs-attr, .hljs-attribute, .hljs-literal, .hljs-meta, .hljs-number, .hljs-operator, .hljs-variable, .hljs-selector-attr, .hljs-selector-class, .hljs-selector-id':
51
+ {
52
+ color: isDarkMode(theme) ? '#79c0ff' : '#005cc5'
53
+ },
54
+ '.hljs-regexp, .hljs-string, .hljs-meta, .hljs-string': {
55
+ color: isDarkMode(theme) ? '#a5d6ff' : '#032f62'
56
+ },
57
+ '.hljs-built_in, .hljs-symbol': {
58
+ color: isDarkMode(theme) ? '#ffa657' : '#e36209'
59
+ },
60
+ '.hljs-code, .hljs-comment, .hljs-formula': {
61
+ color: isDarkMode(theme) ? '#8b949e' : '#6a737d'
62
+ },
63
+ '.hljs-name, .hljs-quote, .hljs-selector-tag, .hljs-selector-pseudo': {
64
+ color: isDarkMode(theme) ? '#7ee787' : '#22863a'
65
+ },
66
+ '.hljs-subst': {
67
+ color: isDarkMode(theme) ? '#c9d1d9' : '#24292e'
68
+ },
69
+ '.hljs-section': {
70
+ color: isDarkMode(theme) ? '#1f6feb' : '#005cc5',
71
+ fontWeight: theme.typography.fontWeightBold
72
+ },
73
+ '.hljs-bullet': {
74
+ color: isDarkMode(theme) ? '#f2cc60' : '#735c0f'
75
+ },
76
+ '.hljs-emphasis': {
77
+ color: isDarkMode(theme) ? '#c9d1d9' : '#24292e',
78
+ fontStyle: 'italic'
79
+ },
80
+ '.hljs-strong': {
81
+ color: isDarkMode(theme) ? '#c9d1d9' : '#24292e',
82
+ fontWeight: theme.typography.fontWeightBold
83
+ },
84
+ '.hljs-addition': {
85
+ color: isDarkMode(theme) ? '#aff5b4' : '#22863a'
86
+ },
87
+ '.hljs-deletion': {
88
+ color: isDarkMode(theme) ? '#ffdcd7' : '#b31d28'
89
+ },
90
+ '.hljs-char.escape_, .hljs-link, .hljs-params, .hljs-property, .hljs-punctuation, .hljs-tag':
91
+ {}
92
+ }
93
+ }));
@@ -0,0 +1,80 @@
1
+ import hljs from 'highlight.js/lib/core';
2
+
3
+ import bash from 'highlight.js/lib/languages/bash';
4
+ import json from 'highlight.js/lib/languages/json';
5
+ import php from 'highlight.js/lib/languages/php';
6
+ import yaml from 'highlight.js/lib/languages/yaml';
7
+
8
+ import ContentCopy from '@mui/icons-material/ContentCopy';
9
+ import parse from 'html-react-parser';
10
+ import { useTranslation } from 'react-i18next';
11
+ import { useCopyToClipboard } from '../../utils';
12
+ import { IconButton } from '../Button';
13
+ import { useCopyCommandStyle } from './CopyCommand.styles';
14
+ import {
15
+ labelCommandCopied,
16
+ labelFailedToCopyCommand
17
+ } from './translatedLabels';
18
+
19
+ hljs.registerLanguage('bash', bash);
20
+ hljs.registerLanguage('shell', bash);
21
+ hljs.registerLanguage('yaml', yaml);
22
+ hljs.registerLanguage('yml', yaml);
23
+ hljs.registerLanguage('json', json);
24
+ hljs.registerLanguage('php', php);
25
+
26
+ hljs.addPlugin({
27
+ 'after:highlight': (result) => {
28
+ const leadingSpaces = result.value.match(/\n\s+/g);
29
+
30
+ leadingSpaces?.forEach((leadingSpace) => {
31
+ const sanitizedLeadingSpace = leadingSpace.replace(/\s/g, '&nbsp;');
32
+ result.value = result.value.replace(
33
+ leadingSpace,
34
+ `\n${sanitizedLeadingSpace}`
35
+ );
36
+ });
37
+ }
38
+ });
39
+
40
+ export interface CopyCommandProps {
41
+ text: string;
42
+ commandToCopy?: string;
43
+ language: string;
44
+ }
45
+
46
+ const CopyCommand = ({ text, commandToCopy, language }: CopyCommandProps) => {
47
+ const { t } = useTranslation();
48
+ const { classes, cx } = useCopyCommandStyle();
49
+
50
+ const { copy } = useCopyToClipboard({
51
+ successMessage: t(labelCommandCopied),
52
+ errorMessage: t(labelFailedToCopyCommand)
53
+ });
54
+
55
+ const copyCommand = (): Promise<void> | undefined | '' =>
56
+ commandToCopy && copy(commandToCopy);
57
+
58
+ const highlightedText = hljs.highlight(text, { language }).value;
59
+
60
+ return (
61
+ <div className={classes.codeContainer}>
62
+ <pre className={cx(classes.code, classes.highlight)}>
63
+ {parse(`${highlightedText}`)}
64
+ </pre>
65
+ <div className={classes.languageChip}>{language}</div>
66
+ {commandToCopy && (
67
+ <IconButton
68
+ data-testid="Copy command"
69
+ variant="ghost"
70
+ className={classes.copyButton}
71
+ icon={<ContentCopy fontSize="small" />}
72
+ size="small"
73
+ onClick={copyCommand}
74
+ />
75
+ )}
76
+ </div>
77
+ );
78
+ };
79
+
80
+ export default CopyCommand;
@@ -0,0 +1,2 @@
1
+ export const labelCommandCopied = 'Command copied';
2
+ export const labelFailedToCopyCommand = 'Failed to copy command';
@@ -13,3 +13,4 @@ export * from './CollapsibleItem';
13
13
  export * from './Inputs';
14
14
  export { default as Zoom } from './Zoom/Zoom';
15
15
  export * from './Tabs';
16
+ export { default as CopyCommand } from './CopyCommand/CopyCommand';
@@ -1,481 +0,0 @@
1
- import { FormikValues, useFormikContext } from 'formik';
2
- import { equals, prop } from 'ramda';
3
-
4
- import HelpOutlineIcon from '@mui/icons-material/HelpOutline';
5
- import MailIcon from '@mui/icons-material/MailOutline';
6
- import { Typography } from '@mui/material';
7
-
8
- import { SelectEntry } from '../InputField/Select';
9
- import { Listing } from '../api/models';
10
-
11
- import {
12
- Group,
13
- InputProps,
14
- InputPropsWithoutGroup,
15
- InputType
16
- } from './Inputs/models';
17
- import { object } from ';
18
-
19
- export interface BasicForm {
20
- active: boolean;
21
- activeSortableFieldsTable: boolean;
22
- animals: Array<SelectEntry>;
23
- anotherText: string;
24
- certificate: string;
25
- class: { id: number; name: string } | null;
26
- custom: string;
27
- email: string;
28
- group: { id: number; name: string } | null;
29
- inviteUsers: Array<{
30
- role: SelectEntry;
31
- user: string;
32
- }>;
33
- inviteUsers2: Array<string>;
34
- isForced: boolean;
35
- language: string;
36
- name: string;
37
- password: string;
38
- roleMapping: Array<{
39
- role: SelectEntry;
40
- value: string;
41
- }>;
42
- scopes: Array<string>;
43
- sports: Array<SelectEntry>;
44
- }
45
-
46
- const selectEntryValidationSchema = object().shape({
47
- id: number().required('Required'),
48
- name: string().required('Required')
49
- });
50
-
51
- export const basicFormValidationSchema = object().shape({
52
- active: boolean().required('Active is required'),
53
- activeSortableFieldsTable: boolean().required(
54
- 'Active Sortable FieldsTable is required'
55
- ),
56
- animals: array().of(selectEntryValidationSchema.required('Required')),
57
- anotherText: string(),
58
- certificate: string(),
59
- class: selectEntryValidationSchema.nullable().required('Required'),
60
- custom: string().required('Custom is required'),
61
- email: string().email('Invalid email').required('Email is required'),
62
- group: selectEntryValidationSchema.nullable().required('Required'),
63
- inviteUsers: array().of(
64
- object({
65
- email: string()
66
- .email('Invalid user email')
67
- .required('Email is required'),
68
- role: selectEntryValidationSchema
69
- })
70
- ),
71
- inviteUsers2: array().of(string().email('Invalid user email')),
72
- isForced: boolean().required('Is forced is required'),
73
- language: string().required('Language is required'),
74
- name: string().required('Name is required'),
75
- password: string().required('Password is required'),
76
- roleMapping: array().of(
77
- object({
78
- role: selectEntryValidationSchema,
79
- value: string().required('Role value is required')
80
- })
81
- ),
82
- scopes: array().of(
83
- string().min(3, '3 characters min').required('Required')
84
- ),
85
- sports: Yup.array().of(selectEntryValidationSchema.required('Required'))
86
- });
87
-
88
- const roleEntries: Array<SelectEntry> = [
89
- {
90
- id: 1,
91
- name: 'Administrator'
92
- },
93
- {
94
- id: 2,
95
- name: 'User'
96
- },
97
- {
98
- id: 3,
99
- name: 'Editor'
100
- }
101
- ];
102
-
103
- export const basicFormInitialValues = {
104
- active: false,
105
- activeSortableFieldsTable: false,
106
- animals: [],
107
- certificate: '',
108
- class: { id: 0, name: 'Class 0' },
109
- custom: '',
110
- email: '',
111
- group: null,
112
- inviteUsers: [],
113
- inviteUsers2: [],
114
- isForced: false,
115
- language: 'French',
116
- name: '',
117
- notifications: {
118
- channels: { Icon: MailIcon, checked: true, label: 'mail' },
119
- hostevents: ['ok', 'warning'],
120
- includeServices: { checked: true, label: 'Include services for this host' }
121
- },
122
- password: '',
123
- roleMapping: [
124
- {
125
- priority: 0,
126
- role: roleEntries[0],
127
- value: 'example'
128
- },
129
- {
130
- priority: 1,
131
- role: roleEntries[1],
132
- value: 'example2'
133
- },
134
- {
135
- priority: 2,
136
- role: roleEntries[2],
137
- value: 'example3'
138
- }
139
- ],
140
- scopes: [],
141
- sports: []
142
- };
143
-
144
- export const classOptions = [...Array(10).keys()].map((idx) => ({
145
- id: idx,
146
- name: `Class ${idx}`
147
- }));
148
-
149
- export const sportOptions = [...Array(10).keys()].map((idx) => ({
150
- id: idx,
151
- name: `Sport ${idx}`
152
- }));
153
-
154
- export const basicFormGroups: Array<Group> = [
155
- {
156
- name: 'First group',
157
- order: 1
158
- },
159
- {
160
- EndIcon: () => <HelpOutlineIcon />,
161
- TooltipContent: (): JSX.Element => <Typography>Tooltip content</Typography>,
162
- name: 'Second group',
163
- order: 2
164
- },
165
- {
166
- name: 'Third group',
167
- order: 3
168
- }
169
- ];
170
-
171
- export const basicFormInputs: Array<InputProps> = [
172
- {
173
- fieldName: 'name',
174
- group: 'First group',
175
- label: 'Name',
176
- type: InputType.Text
177
- },
178
- {
179
- fieldName: 'email',
180
- group: 'First group',
181
- label: 'Email',
182
- text: {
183
- endAdornment: <MailIcon />,
184
- placeholder: 'Your email here'
185
- },
186
- type: InputType.Text
187
- },
188
- {
189
- fieldName: 'active',
190
- group: 'Second group',
191
- label: 'Active',
192
- type: InputType.Switch
193
- },
194
- {
195
- additionalLabel: 'This a very special label',
196
- fieldName: 'password',
197
- group: 'First group',
198
- hideInput: (values) => values.active,
199
- label: 'Password',
200
- type: InputType.Password
201
- },
202
- {
203
- fieldName: 'language',
204
- group: 'First group',
205
- label: 'Language',
206
- radio: {
207
- options: [
208
- {
209
- label: 'French',
210
- value: 'French'
211
- },
212
- {
213
- label: 'English',
214
- value: 'English'
215
- }
216
- ]
217
- },
218
- type: InputType.Radio
219
- },
220
- {
221
- additionalLabel: 'Notifications',
222
- fieldName: '',
223
- grid: {
224
- alignItems: 'center',
225
- columns: [
226
- {
227
- checkbox: {
228
- direction: 'horizontal'
229
- },
230
- fieldName: 'notifications.channels',
231
- label: 'channels',
232
- type: InputType.Checkbox
233
- },
234
- {
235
- fieldName: 'notifications.includeServices',
236
- label: 'Iclude services',
237
- type: InputType.Checkbox
238
- },
239
- {
240
- checkbox: {
241
- direction: 'horizontal',
242
- labelPlacement: 'top',
243
- options: ['ok', 'warning', 'critical', 'unknown']
244
- },
245
- fieldName: 'notifications.hostevents',
246
- label: 'host events',
247
- type: InputType.CheckboxGroup
248
- }
249
- ]
250
- },
251
- group: 'Third group',
252
- label: 'Notifications',
253
- type: InputType.Grid
254
- },
255
- {
256
- fieldName: 'anotherText',
257
- group: 'First group',
258
- hideInput: ({ language }) => equals(language, 'French'),
259
- label: 'Another Text input',
260
- type: InputType.Text
261
- },
262
- {
263
- fieldName: 'isForced',
264
- group: 'First group',
265
- label: 'Is Forced?',
266
- radio: {
267
- options: [
268
- {
269
- label: 'Is not forced',
270
- value: false
271
- },
272
- {
273
- label: 'Is forced',
274
- value: true
275
- }
276
- ]
277
- },
278
- type: InputType.Radio
279
- },
280
- {
281
- fieldName: '',
282
- grid: {
283
- columns: [
284
- {
285
- autocomplete: {
286
- options: classOptions
287
- },
288
- fieldName: 'class',
289
- label: 'Class (Single autocomplete)',
290
- type: InputType.SingleAutocomplete
291
- },
292
- {
293
- autocomplete: {
294
- options: sportOptions
295
- },
296
- fieldName: 'sports',
297
- label: 'Sports (Multi autocomplete)',
298
- type: InputType.MultiAutocomplete
299
- }
300
- ]
301
- },
302
- group: 'First group',
303
- label: 'autocompletes',
304
- type: InputType.Grid
305
- },
306
- {
307
- autocomplete: {
308
- creatable: true,
309
- options: []
310
- },
311
- fieldName: 'scopes',
312
- group: 'First group',
313
- label: 'Scopes (Multi autocomplete that allows value creation)',
314
- type: InputType.MultiAutocomplete
315
- },
316
- {
317
- fieldName: '',
318
- grid: {
319
- columns: [
320
- {
321
- connectedAutocomplete: {
322
- additionalConditionParameters: [],
323
- endpoint: 'endpoint'
324
- },
325
- fieldName: 'group',
326
- label: 'Group (Single connected autocomplete)',
327
- type: InputType.SingleConnectedAutocomplete
328
- },
329
- {
330
- connectedAutocomplete: {
331
- additionalConditionParameters: [],
332
- endpoint: 'endpoint'
333
- },
334
- fieldName: 'animals',
335
- label: 'Animals (Multi connected autocomplete)',
336
- type: InputType.MultiConnectedAutocomplete
337
- }
338
- ],
339
- gridTemplateColumns: '400px 1fr'
340
- },
341
- group: 'First group',
342
- label: 'connected autocompletes',
343
- type: InputType.Grid
344
- },
345
- {
346
- custom: {
347
- Component: ({ label }: InputPropsWithoutGroup): JSX.Element => (
348
- <Typography>This is a {label} component</Typography>
349
- )
350
- },
351
- fieldName: 'custom',
352
- group: 'Second group',
353
- label: 'Custom',
354
- type: InputType.Custom
355
- },
356
- {
357
- fieldName: 'inviteUsers',
358
- fieldsTable: {
359
- columns: [
360
- {
361
- fieldName: 'email',
362
- label: 'Email',
363
- required: true,
364
- type: InputType.Text
365
- },
366
- {
367
- autocomplete: {
368
- creatable: false,
369
- options: roleEntries
370
- },
371
- fieldName: 'role',
372
- label: 'Role',
373
- type: InputType.SingleAutocomplete
374
- }
375
- ],
376
- defaultRowValue: {
377
- email: 'example@test.fr',
378
- role: null
379
- },
380
- deleteLabel: 'Delete'
381
- },
382
- group: 'First group',
383
- label: 'inviteUsers',
384
- type: InputType.FieldsTable
385
- },
386
- {
387
- fieldName: 'inviteUsers2',
388
- fieldsTable: {
389
- columns: [
390
- {
391
- fieldName: 'email',
392
- label: 'Email',
393
- required: true,
394
- type: InputType.Text
395
- }
396
- ],
397
- defaultRowValue: 'example',
398
- deleteLabel: 'Delete',
399
- hasSingleValue: true
400
- },
401
- group: 'First group',
402
- label: 'inviteUsers2',
403
- type: InputType.FieldsTable
404
- },
405
- {
406
- fieldName: 'activeSortableFieldsTable',
407
- group: 'First group',
408
- label: 'Active Sortable Fields Table',
409
- type: InputType.Switch
410
- },
411
- {
412
- fieldName: 'roleMapping',
413
- fieldsTable: {
414
- columns: [
415
- {
416
- fieldName: 'value',
417
- label: 'RoleValue',
418
- required: true,
419
- type: InputType.Text
420
- },
421
- {
422
- autocomplete: {
423
- creatable: false,
424
- options: roleEntries
425
- },
426
- fieldName: 'role',
427
- label: 'RoleAcl',
428
- type: InputType.SingleAutocomplete
429
- }
430
- ],
431
- defaultRowValue: {
432
- role: null,
433
- value: ''
434
- },
435
- deleteLabel: 'Delete',
436
- getSortable: (values: FormikValues): boolean =>
437
- prop('activeSortableFieldsTable', values)
438
- },
439
- group: 'First group',
440
- label: 'roleMapping',
441
- type: InputType.FieldsTable
442
- },
443
- {
444
- fieldName: 'certificate',
445
- group: 'First group',
446
- label: 'Certificate',
447
- text: {
448
- multilineRows: 4
449
- },
450
- type: InputType.Text
451
- }
452
- ];
453
-
454
- export const CustomButton = (): JSX.Element => {
455
- const { dirty, isValid } = useFormikContext();
456
-
457
- return (
458
- <div>
459
- <Typography>Has form changed? {JSON.stringify(dirty)}</Typography>
460
- <Typography>Is valid? {JSON.stringify(isValid)}</Typography>
461
- </div>
462
- );
463
- };
464
-
465
- const buildEntities = (from): Array<SelectEntry> => {
466
- return Array(10)
467
- .fill(0)
468
- .map((_, index) => ({
469
- id: from + index,
470
- name: `Entity ${from + index}`
471
- }));
472
- };
473
-
474
- export const buildResult = (page): Listing<SelectEntry> => ({
475
- meta: {
476
- limit: 10,
477
- page,
478
- total: 40
479
- },
480
- result: buildEntities((page - 1) * 10)
481
- });