@centreon/ui 23.10.47 → 23.10.48
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 +2 -1
- package/src/ActionsList/index.tsx +17 -10
- package/src/RichTextEditor/RichTextEditor.cypress.spec.tsx +29 -0
- package/src/RichTextEditor/RichTextEditor.tsx +8 -2
- package/src/RichTextEditor/index.stories.tsx +5 -0
- package/src/RichTextEditor/plugins/ToolbarPlugin/MacrosButton.tsx +87 -0
- package/src/RichTextEditor/plugins/ToolbarPlugin/index.tsx +20 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@centreon/ui",
|
|
3
|
-
"version": "23.10.
|
|
3
|
+
"version": "23.10.48",
|
|
4
4
|
"description": "Centreon UI Components",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"eslint": "eslint ./src --ext .js,.jsx,.ts,.tsx --max-warnings 0",
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
"@testing-library/jest-dom": "^5.16.5",
|
|
72
72
|
"@testing-library/react": "^13.4.0",
|
|
73
73
|
"@testing-library/react-hooks": "^8.0.1",
|
|
74
|
+
"@types/cypress": "^1.1.3",
|
|
74
75
|
"@types/jest": "^27.5.0",
|
|
75
76
|
"@types/ramda": "^0.28.12",
|
|
76
77
|
"@types/react": "^18.0.26",
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
/* eslint-disable react/no-array-index-key */
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
|
|
4
2
|
import { makeStyles } from 'tss-react/mui';
|
|
5
3
|
import { useTranslation } from 'react-i18next';
|
|
6
4
|
import { equals } from 'ramda';
|
|
@@ -15,14 +13,15 @@ import {
|
|
|
15
13
|
} from '@mui/material';
|
|
16
14
|
|
|
17
15
|
interface ActionsType {
|
|
18
|
-
Icon
|
|
16
|
+
Icon?: (props: SvgIconProps) => JSX.Element;
|
|
19
17
|
label: string;
|
|
20
|
-
onClick?: () => void;
|
|
18
|
+
onClick?: (e?) => void;
|
|
21
19
|
}
|
|
22
20
|
|
|
23
21
|
interface Props {
|
|
24
22
|
actions: Array<ActionsType | 'divider'>;
|
|
25
23
|
className?: string;
|
|
24
|
+
listItemClassName?: string;
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
const useStyles = makeStyles()({
|
|
@@ -31,7 +30,11 @@ const useStyles = makeStyles()({
|
|
|
31
30
|
}
|
|
32
31
|
});
|
|
33
32
|
|
|
34
|
-
const ActionsList = ({
|
|
33
|
+
const ActionsList = ({
|
|
34
|
+
className,
|
|
35
|
+
listItemClassName,
|
|
36
|
+
actions
|
|
37
|
+
}: Props): JSX.Element => {
|
|
35
38
|
const { cx, classes } = useStyles();
|
|
36
39
|
const { t } = useTranslation();
|
|
37
40
|
|
|
@@ -45,11 +48,15 @@ const ActionsList = ({ className, actions }: Props): JSX.Element => {
|
|
|
45
48
|
const { label, Icon, onClick } = action as ActionsType;
|
|
46
49
|
|
|
47
50
|
return (
|
|
48
|
-
<MenuItem aria-label={label} key={label} onClick={onClick}>
|
|
49
|
-
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
<MenuItem aria-label={label} id={label} key={label} onClick={onClick}>
|
|
52
|
+
{Icon && (
|
|
53
|
+
<ListItemIcon>
|
|
54
|
+
<Icon fontSize="small" />
|
|
55
|
+
</ListItemIcon>
|
|
56
|
+
)}
|
|
57
|
+
<ListItemText className={listItemClassName}>
|
|
58
|
+
{t(label)}
|
|
59
|
+
</ListItemText>
|
|
53
60
|
</MenuItem>
|
|
54
61
|
);
|
|
55
62
|
})}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import RichTextEditor from './RichTextEditor';
|
|
2
|
+
import { standardMacros } from './plugins/ToolbarPlugin/MacrosButton';
|
|
2
3
|
|
|
3
4
|
interface CheckElementStyleOnRichTextEditorProps {
|
|
4
5
|
check: boolean;
|
|
@@ -201,4 +202,32 @@ describe('Rich Text Editor', () => {
|
|
|
201
202
|
);
|
|
202
203
|
});
|
|
203
204
|
});
|
|
205
|
+
|
|
206
|
+
describe('Rich Text Editor with Macros Plugin', () => {
|
|
207
|
+
beforeEach(() => {
|
|
208
|
+
cy.mount({
|
|
209
|
+
Component: <RichTextEditor displayMacrosButton editable />
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('displays the Macros button when the "displayMacrosButton" prop is set to true', () => {
|
|
214
|
+
cy.findByLabelText('Macros').should('be.visible');
|
|
215
|
+
cy.findByLabelText('Macros').click();
|
|
216
|
+
|
|
217
|
+
standardMacros.forEach((macro) => {
|
|
218
|
+
cy.findByText(macro).should('be.visible');
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('ensures that the selected macro is inserted into the RichTextEditor', () => {
|
|
223
|
+
cy.get('[data-testid="RichTextEditor"]').type('macro : ');
|
|
224
|
+
|
|
225
|
+
cy.findByLabelText('Macros').click({});
|
|
226
|
+
|
|
227
|
+
standardMacros.forEach((macro) => {
|
|
228
|
+
cy.findByText(macro).should('be.visible').click({ force: true });
|
|
229
|
+
cy.get('[data-testid="RichTextEditor"]').should('contain', macro);
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
});
|
|
204
233
|
});
|
|
@@ -18,6 +18,7 @@ import FloatingLinkEditorPlugin from './plugins/FloatingLinkEditorPlugin';
|
|
|
18
18
|
|
|
19
19
|
export interface RichTextEditorProps {
|
|
20
20
|
contentClassName?: string;
|
|
21
|
+
displayMacrosButton?: boolean;
|
|
21
22
|
editable: boolean;
|
|
22
23
|
editorState?: string;
|
|
23
24
|
error?: string;
|
|
@@ -92,7 +93,8 @@ const RichTextEditor = ({
|
|
|
92
93
|
toolbarPositions = 'start',
|
|
93
94
|
error,
|
|
94
95
|
onBlur,
|
|
95
|
-
contentClassName
|
|
96
|
+
contentClassName,
|
|
97
|
+
displayMacrosButton = false
|
|
96
98
|
}: RichTextEditorProps): JSX.Element => {
|
|
97
99
|
const { classes } = useStyles({ toolbarPositions });
|
|
98
100
|
|
|
@@ -122,7 +124,11 @@ const RichTextEditor = ({
|
|
|
122
124
|
<LexicalComposer initialConfig={initialConfig}>
|
|
123
125
|
<div className={classes.container}>
|
|
124
126
|
<div className={classes.toolbar}>
|
|
125
|
-
<ToolbarPlugin
|
|
127
|
+
<ToolbarPlugin
|
|
128
|
+
displayMacrosButton={displayMacrosButton}
|
|
129
|
+
editable={editable}
|
|
130
|
+
getEditorState={getEditorState}
|
|
131
|
+
/>
|
|
126
132
|
</div>
|
|
127
133
|
<div>
|
|
128
134
|
<RichTextPlugin
|
|
@@ -56,6 +56,11 @@ withCustomPlaceholder.args = {
|
|
|
56
56
|
placeholder: 'Custom placeholder...'
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
+
export const withMacrosPlugin = Template.bind({});
|
|
60
|
+
withMacrosPlugin.args = {
|
|
61
|
+
displayMacrosButton: true
|
|
62
|
+
};
|
|
63
|
+
|
|
59
64
|
export const withEditableFalse = Template.bind({});
|
|
60
65
|
withEditableFalse.args = {
|
|
61
66
|
editable: false,
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
4
|
+
import { createCommand, LexicalCommand } from 'lexical';
|
|
5
|
+
|
|
6
|
+
import MacrosIcon from '@mui/icons-material/TerminalOutlined';
|
|
7
|
+
|
|
8
|
+
import { ActionsList, IconButton, PopoverMenu } from '../../..';
|
|
9
|
+
|
|
10
|
+
import { useStyles } from '.';
|
|
11
|
+
|
|
12
|
+
const LowPriority = 1;
|
|
13
|
+
|
|
14
|
+
export const standardMacros = [
|
|
15
|
+
'{{SHORTDATETIME}}',
|
|
16
|
+
'{{LONGDATETIME}}',
|
|
17
|
+
'{{ALIAS}}',
|
|
18
|
+
'{{ID}}',
|
|
19
|
+
'{{NAME}}',
|
|
20
|
+
'{{OUTPUT}}',
|
|
21
|
+
'{{STATE}}',
|
|
22
|
+
'{{STATETYPE}}'
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const MacrosButton = (): JSX.Element => {
|
|
26
|
+
const { classes } = useStyles();
|
|
27
|
+
const [arMacrosDiplayed, setAreMacrosDiplayed] = useState(false);
|
|
28
|
+
|
|
29
|
+
const [editor] = useLexicalComposerContext();
|
|
30
|
+
|
|
31
|
+
const INSERT_MACROS_COMMAND: LexicalCommand<string> = createCommand();
|
|
32
|
+
|
|
33
|
+
const onClick = (e): void => {
|
|
34
|
+
const macro = e.target.id || e.target.textContent.trim();
|
|
35
|
+
|
|
36
|
+
editor.dispatchCommand(INSERT_MACROS_COMMAND, macro);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
editor.registerCommand(
|
|
40
|
+
INSERT_MACROS_COMMAND,
|
|
41
|
+
(payload: string) => {
|
|
42
|
+
if (!editor) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
document.execCommand('insertText', false, payload);
|
|
47
|
+
|
|
48
|
+
return true;
|
|
49
|
+
},
|
|
50
|
+
LowPriority
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const displayMacros = (): void => {
|
|
54
|
+
setAreMacrosDiplayed(true);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const actions = standardMacros.map((macro) => ({
|
|
58
|
+
label: macro,
|
|
59
|
+
onClick
|
|
60
|
+
}));
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<PopoverMenu
|
|
64
|
+
icon={
|
|
65
|
+
<IconButton
|
|
66
|
+
ariaLabel="Macros"
|
|
67
|
+
className={classes.macrosButton}
|
|
68
|
+
title="Macros"
|
|
69
|
+
tooltipPlacement="top"
|
|
70
|
+
onClick={displayMacros}
|
|
71
|
+
>
|
|
72
|
+
<MacrosIcon />
|
|
73
|
+
</IconButton>
|
|
74
|
+
}
|
|
75
|
+
>
|
|
76
|
+
{(): JSX.Element => (
|
|
77
|
+
<div>
|
|
78
|
+
{arMacrosDiplayed && (
|
|
79
|
+
<ActionsList actions={actions} listItemClassName={classes.macros} />
|
|
80
|
+
)}
|
|
81
|
+
</div>
|
|
82
|
+
)}
|
|
83
|
+
</PopoverMenu>
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export default MacrosButton;
|
|
@@ -5,23 +5,35 @@ import { Divider } from '@mui/material';
|
|
|
5
5
|
|
|
6
6
|
import FormatButtons from './FormatButtons';
|
|
7
7
|
import UndoRedoButtons from './UndoRedoButtons';
|
|
8
|
+
import MacrosButton from './MacrosButton';
|
|
8
9
|
|
|
9
10
|
interface Props {
|
|
11
|
+
displayMacrosButton?: boolean;
|
|
10
12
|
editable: boolean;
|
|
11
13
|
getEditorState?: (editorState: EditorState) => void;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
|
-
const useStyles = makeStyles()((theme) => ({
|
|
16
|
+
export const useStyles = makeStyles()((theme) => ({
|
|
15
17
|
container: {
|
|
18
|
+
alignItems: 'center',
|
|
16
19
|
columnGap: theme.spacing(1),
|
|
17
20
|
display: 'flex',
|
|
18
21
|
marginBottom: theme.spacing(1)
|
|
22
|
+
},
|
|
23
|
+
macros: {
|
|
24
|
+
'& span': {
|
|
25
|
+
fontSize: theme.typography.caption.fontSize
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
macrosButton: {
|
|
29
|
+
marginBottom: theme.spacing(0.5)
|
|
19
30
|
}
|
|
20
31
|
}));
|
|
21
32
|
|
|
22
33
|
const ToolbarPlugin = ({
|
|
23
34
|
getEditorState,
|
|
24
|
-
editable
|
|
35
|
+
editable,
|
|
36
|
+
displayMacrosButton
|
|
25
37
|
}: Props): JSX.Element | null => {
|
|
26
38
|
const { classes } = useStyles();
|
|
27
39
|
|
|
@@ -30,6 +42,12 @@ const ToolbarPlugin = ({
|
|
|
30
42
|
<UndoRedoButtons />
|
|
31
43
|
<Divider flexItem orientation="vertical" />
|
|
32
44
|
<FormatButtons getEditorState={getEditorState} />
|
|
45
|
+
{displayMacrosButton && (
|
|
46
|
+
<>
|
|
47
|
+
<Divider flexItem orientation="vertical" />
|
|
48
|
+
<MacrosButton />
|
|
49
|
+
</>
|
|
50
|
+
)}
|
|
33
51
|
</div>
|
|
34
52
|
) : null;
|
|
35
53
|
};
|