@centreon/ui 23.10.119 → 23.10.120
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 +16 -12
- package/src/Button/Save/StartIcon.tsx +3 -3
- package/src/Dashboard/Item.tsx +1 -1
- package/src/Dashboard/Layout.tsx +2 -2
- package/src/FileDropZone/index.tsx +3 -1
- package/src/Form/Inputs/CheckboxGroup.tsx +1 -4
- package/src/Form/Inputs/index.tsx +1 -1
- package/src/Graph/LineChart/BasicComponents/Lines/Threshold/Circle.tsx +2 -2
- package/src/Graph/LineChart/BasicComponents/Lines/Threshold/index.tsx +5 -4
- package/src/Graph/LineChart/BasicComponents/Thresholds.tsx +2 -2
- package/src/Graph/LineChart/BasicComponents/useFilterLines.ts +1 -1
- package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/GuidingLines.tsx +2 -2
- package/src/Graph/LineChart/InteractiveComponents/Annotations/Annotation/index.tsx +2 -3
- package/src/Graph/LineChart/InteractiveComponents/Annotations/EventAnnotations.tsx +1 -1
- package/src/Graph/LineChart/Legend/useLegend.ts +5 -5
- package/src/Graph/LineChart/LineChart.tsx +5 -2
- package/src/Graph/LineChart/helpers/doc.ts +16 -13
- package/src/Graph/LineChart/helpers/index.ts +1 -1
- package/src/Graph/LineChart/index.stories.tsx +1 -2
- package/src/Graph/SingleBar/Thresholds.tsx +2 -2
- package/src/Graph/Text/Text.stories.tsx +60 -4
- package/src/Graph/common/timeSeries/index.ts +3 -3
- package/src/InputField/Select/Autocomplete/Connected/index.tsx +10 -7
- package/src/InputField/Select/Autocomplete/Draggable/SortableList.tsx +1 -1
- package/src/InputField/Select/Autocomplete/Draggable/SortableListContent.tsx +1 -1
- package/src/InputField/Select/Autocomplete/Draggable/index.tsx +1 -1
- package/src/InputField/Select/IconPopover/index.tsx +2 -2
- package/src/InputField/Select/index.tsx +1 -1
- package/src/Listing/Header/ListingHeader.tsx +1 -1
- package/src/Listing/index.stories.tsx +12 -1
- package/src/Listing/index.tsx +1 -1
- package/src/RichTextEditor/RichTextEditor.cypress.spec.tsx +100 -52
- package/src/RichTextEditor/RichTextEditor.tsx +21 -4
- package/src/RichTextEditor/plugins/ToolbarPlugin/AlignPicker.tsx +21 -20
- package/src/RichTextEditor/plugins/ToolbarPlugin/BlockButtons.tsx +35 -77
- package/src/RichTextEditor/plugins/ToolbarPlugin/FormatButtons.tsx +29 -83
- package/src/RichTextEditor/plugins/ToolbarPlugin/LinkButton.tsx +106 -0
- package/src/RichTextEditor/plugins/ToolbarPlugin/ListButton.tsx +155 -0
- package/src/RichTextEditor/plugins/ToolbarPlugin/MacrosButton.tsx +23 -39
- package/src/RichTextEditor/plugins/ToolbarPlugin/ToolbarPlugin.styles.ts +24 -14
- package/src/RichTextEditor/plugins/ToolbarPlugin/UndoRedoButtons.tsx +6 -0
- package/src/RichTextEditor/plugins/ToolbarPlugin/index.tsx +5 -10
- package/src/RichTextEditor/translatedLabels.ts +3 -0
- package/src/SortableItems/index.tsx +2 -7
- package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +8 -3
- package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/models.ts +0 -2
- package/src/TimePeriods/DateTimePickerInput.tsx +45 -17
- package/src/TimePeriods/TimePeriods.cypress.spec.tsx +9 -33
- package/src/TimePeriods/helpers/index.ts +1 -1
- package/src/TimePeriods/index.tsx +2 -2
- package/src/api/QueryProvider.tsx +1 -1
- package/src/api/TestQueryProvider.tsx +1 -1
- package/src/api/useFetchQuery/index.ts +28 -24
- package/src/api/useMutationQuery/index.ts +39 -17
- package/src/components/DataTable/Item/DataTableItem.tsx +2 -2
- package/src/components/Form/AccessRights/__fixtures__/contactAccessRight.mock.ts +2 -0
- package/src/components/Form/AccessRights/useAccessRightsForm.utils.ts +1 -1
- package/src/components/Form/Dashboard/DashboardForm.tsx +15 -12
- package/src/components/ItemComposition/ItemComposition.tsx +4 -2
- package/src/components/Menu/Button/MenuButton.tsx +4 -2
- package/src/components/Menu/MenuItem.tsx +5 -3
- package/src/components/Menu/MenuItems.tsx +4 -3
- package/src/index.ts +1 -0
- package/src/queryParameters/url/index.ts +5 -1
- package/src/utils/index.ts +0 -1
- package/src/utils/{useLicenseExpirationWarning.cypress.spec.tsx → useLicenseExpirationWarning.test.tsx} +48 -37
- package/src/utils/useLicenseExpirationWarning.ts +18 -18
- package/src/screens/dashboard/DashboardsDetail.stories.tsx +0 -108
- package/src/screens/dashboard/DashboardsOverview.stories.tsx +0 -281
- package/src/utils/useDateTimePickerAdapter.ts +0 -309
|
@@ -1,76 +1,38 @@
|
|
|
1
1
|
import { useState, useCallback, useEffect, useMemo } from 'react';
|
|
2
2
|
|
|
3
|
-
import { makeStyles } from 'tss-react/mui';
|
|
4
3
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
5
4
|
import {
|
|
6
5
|
$getSelection,
|
|
7
6
|
$isRangeSelection,
|
|
8
7
|
FORMAT_TEXT_COMMAND,
|
|
9
|
-
RangeSelection,
|
|
10
8
|
SELECTION_CHANGE_COMMAND,
|
|
11
|
-
TextFormatType
|
|
12
|
-
ElementNode,
|
|
13
|
-
TextNode
|
|
9
|
+
TextFormatType
|
|
14
10
|
} from 'lexical';
|
|
15
|
-
import { $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link';
|
|
16
|
-
import { $isAtNodeEnd } from '@lexical/selection';
|
|
17
11
|
import { mergeRegister } from '@lexical/utils';
|
|
18
|
-
import { useAtom } from 'jotai';
|
|
19
12
|
|
|
13
|
+
import FormatTextIcon from '@mui/icons-material/FormatColorText';
|
|
20
14
|
import FormatBoldIcon from '@mui/icons-material/FormatBold';
|
|
21
15
|
import FormatItalicIcon from '@mui/icons-material/FormatItalic';
|
|
22
16
|
import FormatUnderlinedIcon from '@mui/icons-material/FormatUnderlined';
|
|
23
17
|
import StrikethroughSIcon from '@mui/icons-material/StrikethroughS';
|
|
24
|
-
import LinkIcon from '@mui/icons-material/Link';
|
|
25
|
-
import { alpha } from '@mui/material';
|
|
26
18
|
|
|
27
|
-
import {
|
|
28
|
-
import { isInsertingLinkAtom } from '../../atoms';
|
|
19
|
+
import { Menu } from '../../../components';
|
|
29
20
|
|
|
30
|
-
|
|
21
|
+
import { useStyles } from './ToolbarPlugin.styles';
|
|
31
22
|
|
|
32
|
-
const
|
|
33
|
-
buttonSelected: {
|
|
34
|
-
backgroundColor: alpha(
|
|
35
|
-
theme.palette.primary.main,
|
|
36
|
-
theme.palette.action.activatedOpacity
|
|
37
|
-
)
|
|
38
|
-
},
|
|
39
|
-
container: {
|
|
40
|
-
columnGap: theme.spacing(1),
|
|
41
|
-
display: 'flex',
|
|
42
|
-
marginBottom: theme.spacing(1)
|
|
43
|
-
}
|
|
44
|
-
}));
|
|
45
|
-
|
|
46
|
-
const getSelectedNode = (selection: RangeSelection): ElementNode | TextNode => {
|
|
47
|
-
const { anchor } = selection;
|
|
48
|
-
const { focus } = selection;
|
|
49
|
-
const anchorNode = selection.anchor.getNode();
|
|
50
|
-
const focusNode = selection.focus.getNode();
|
|
51
|
-
if (anchorNode === focusNode) {
|
|
52
|
-
return anchorNode;
|
|
53
|
-
}
|
|
54
|
-
const isBackward = selection.isBackward();
|
|
55
|
-
if (isBackward) {
|
|
56
|
-
return $isAtNodeEnd(focus) ? anchorNode : focusNode;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return $isAtNodeEnd(anchor) ? focusNode : anchorNode;
|
|
60
|
-
};
|
|
23
|
+
const LowPriority = 1;
|
|
61
24
|
|
|
62
25
|
interface Props {
|
|
63
26
|
disabled: boolean;
|
|
64
27
|
}
|
|
65
28
|
|
|
66
29
|
const FormatButtons = ({ disabled }: Props): JSX.Element => {
|
|
67
|
-
const { classes
|
|
30
|
+
const { classes } = useStyles();
|
|
68
31
|
|
|
69
32
|
const [isBold, setIsBold] = useState(false);
|
|
70
33
|
const [isItalic, setIsItalic] = useState(false);
|
|
71
34
|
const [isUnderline, setIsUnderline] = useState(false);
|
|
72
35
|
const [isStrikeThrough, setIsStrikeThrough] = useState(false);
|
|
73
|
-
const [isLink, setIsLink] = useAtom(isInsertingLinkAtom);
|
|
74
36
|
|
|
75
37
|
const [editor] = useLexicalComposerContext();
|
|
76
38
|
|
|
@@ -83,24 +45,8 @@ const FormatButtons = ({ disabled }: Props): JSX.Element => {
|
|
|
83
45
|
setIsItalic(selection.hasFormat('italic'));
|
|
84
46
|
setIsUnderline(selection.hasFormat('underline'));
|
|
85
47
|
setIsStrikeThrough(selection.hasFormat('strikethrough'));
|
|
86
|
-
|
|
87
|
-
const node = getSelectedNode(selection);
|
|
88
|
-
const parent = node.getParent();
|
|
89
|
-
if ($isLinkNode(parent) || $isLinkNode(node)) {
|
|
90
|
-
setIsLink(true);
|
|
91
|
-
} else {
|
|
92
|
-
setIsLink(false);
|
|
93
|
-
}
|
|
94
48
|
}, [editor]);
|
|
95
49
|
|
|
96
|
-
const insertLink = useCallback(() => {
|
|
97
|
-
if (!isLink) {
|
|
98
|
-
editor.dispatchCommand(TOGGLE_LINK_COMMAND, 'https://');
|
|
99
|
-
} else {
|
|
100
|
-
editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
|
|
101
|
-
}
|
|
102
|
-
}, [editor, isLink]);
|
|
103
|
-
|
|
104
50
|
useEffect(() => {
|
|
105
51
|
return mergeRegister(
|
|
106
52
|
editor.registerCommand(
|
|
@@ -144,34 +90,34 @@ const FormatButtons = ({ disabled }: Props): JSX.Element => {
|
|
|
144
90
|
isSelected: isStrikeThrough,
|
|
145
91
|
onClickFunction: toggleTextFormat('strikethrough'),
|
|
146
92
|
type: 'strikethrough'
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
Icon: LinkIcon,
|
|
150
|
-
isSelected: isLink,
|
|
151
|
-
onClickFunction: insertLink,
|
|
152
|
-
type: 'link'
|
|
153
93
|
}
|
|
154
94
|
],
|
|
155
|
-
[isBold, isItalic, isUnderline, isStrikeThrough
|
|
95
|
+
[isBold, isItalic, isUnderline, isStrikeThrough]
|
|
156
96
|
);
|
|
157
97
|
|
|
158
98
|
return (
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
99
|
+
<Menu>
|
|
100
|
+
<Menu.Button
|
|
101
|
+
ariaLabel="format"
|
|
102
|
+
className={classes.button}
|
|
103
|
+
disabled={disabled}
|
|
104
|
+
>
|
|
105
|
+
<FormatTextIcon />
|
|
106
|
+
</Menu.Button>
|
|
107
|
+
<Menu.Items className={classes.menuItems}>
|
|
108
|
+
<div className={classes.menu}>
|
|
109
|
+
{formatButtons.map(({ Icon, onClickFunction, isSelected, type }) => (
|
|
110
|
+
<Menu.Item
|
|
111
|
+
isActive={isSelected}
|
|
112
|
+
key={type}
|
|
113
|
+
onClick={onClickFunction}
|
|
114
|
+
>
|
|
115
|
+
<Icon aria-label={type} />
|
|
116
|
+
</Menu.Item>
|
|
117
|
+
))}
|
|
118
|
+
</div>
|
|
119
|
+
</Menu.Items>
|
|
120
|
+
</Menu>
|
|
175
121
|
);
|
|
176
122
|
};
|
|
177
123
|
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { useCallback, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
4
|
+
import {
|
|
5
|
+
$getSelection,
|
|
6
|
+
$isRangeSelection,
|
|
7
|
+
RangeSelection,
|
|
8
|
+
SELECTION_CHANGE_COMMAND,
|
|
9
|
+
ElementNode,
|
|
10
|
+
TextNode
|
|
11
|
+
} from 'lexical';
|
|
12
|
+
import { $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link';
|
|
13
|
+
import { $isAtNodeEnd } from '@lexical/selection';
|
|
14
|
+
import { mergeRegister } from '@lexical/utils';
|
|
15
|
+
import { useAtom } from 'jotai';
|
|
16
|
+
|
|
17
|
+
import LinkIcon from '@mui/icons-material/Link';
|
|
18
|
+
|
|
19
|
+
import { IconButton } from '../../..';
|
|
20
|
+
import { isInsertingLinkAtom } from '../../atoms';
|
|
21
|
+
|
|
22
|
+
import { useStyles } from './ToolbarPlugin.styles';
|
|
23
|
+
|
|
24
|
+
const LowPriority = 1;
|
|
25
|
+
|
|
26
|
+
const getSelectedNode = (selection: RangeSelection): ElementNode | TextNode => {
|
|
27
|
+
const { anchor } = selection;
|
|
28
|
+
const { focus } = selection;
|
|
29
|
+
const anchorNode = selection.anchor.getNode();
|
|
30
|
+
const focusNode = selection.focus.getNode();
|
|
31
|
+
if (anchorNode === focusNode) {
|
|
32
|
+
return anchorNode;
|
|
33
|
+
}
|
|
34
|
+
const isBackward = selection.isBackward();
|
|
35
|
+
if (isBackward) {
|
|
36
|
+
return $isAtNodeEnd(focus) ? anchorNode : focusNode;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return $isAtNodeEnd(anchor) ? focusNode : anchorNode;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
interface Props {
|
|
43
|
+
disabled: boolean;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const LinkButton = ({ disabled }: Props): JSX.Element => {
|
|
47
|
+
const { classes, cx } = useStyles();
|
|
48
|
+
|
|
49
|
+
const [isLink, setIsLink] = useAtom(isInsertingLinkAtom);
|
|
50
|
+
|
|
51
|
+
const [editor] = useLexicalComposerContext();
|
|
52
|
+
|
|
53
|
+
const updateToolbar = useCallback((): void => {
|
|
54
|
+
const selection = $getSelection();
|
|
55
|
+
if (!$isRangeSelection(selection)) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const node = getSelectedNode(selection);
|
|
60
|
+
const parent = node.getParent();
|
|
61
|
+
if ($isLinkNode(parent) || $isLinkNode(node)) {
|
|
62
|
+
setIsLink(true);
|
|
63
|
+
} else {
|
|
64
|
+
setIsLink(false);
|
|
65
|
+
}
|
|
66
|
+
}, [editor]);
|
|
67
|
+
|
|
68
|
+
const insertLink = useCallback(() => {
|
|
69
|
+
if (!isLink) {
|
|
70
|
+
editor.dispatchCommand(TOGGLE_LINK_COMMAND, 'https://');
|
|
71
|
+
} else {
|
|
72
|
+
editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
|
|
73
|
+
}
|
|
74
|
+
}, [editor, isLink]);
|
|
75
|
+
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
return mergeRegister(
|
|
78
|
+
editor.registerCommand(
|
|
79
|
+
SELECTION_CHANGE_COMMAND,
|
|
80
|
+
() => {
|
|
81
|
+
updateToolbar();
|
|
82
|
+
|
|
83
|
+
return false;
|
|
84
|
+
},
|
|
85
|
+
LowPriority
|
|
86
|
+
)
|
|
87
|
+
);
|
|
88
|
+
}, [editor, updateToolbar]);
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<IconButton
|
|
92
|
+
ariaLabel="link"
|
|
93
|
+
className={cx(classes.button, { [classes.buttonSelected]: isLink })}
|
|
94
|
+
disabled={disabled}
|
|
95
|
+
key="link"
|
|
96
|
+
size="medium"
|
|
97
|
+
title="link"
|
|
98
|
+
tooltipPlacement="top"
|
|
99
|
+
onClick={insertLink}
|
|
100
|
+
>
|
|
101
|
+
<LinkIcon />
|
|
102
|
+
</IconButton>
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export default LinkButton;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
$isListNode,
|
|
5
|
+
INSERT_ORDERED_LIST_COMMAND,
|
|
6
|
+
INSERT_UNORDERED_LIST_COMMAND,
|
|
7
|
+
ListNode,
|
|
8
|
+
REMOVE_LIST_COMMAND
|
|
9
|
+
} from '@lexical/list';
|
|
10
|
+
import { $getSelection, $isRootOrShadowRoot } from 'lexical';
|
|
11
|
+
import {
|
|
12
|
+
$findMatchingParent,
|
|
13
|
+
$getNearestNodeOfType,
|
|
14
|
+
mergeRegister
|
|
15
|
+
} from '@lexical/utils';
|
|
16
|
+
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
17
|
+
import { equals, isNil } from 'ramda';
|
|
18
|
+
import { useTranslation } from 'react-i18next';
|
|
19
|
+
|
|
20
|
+
import UnorderedListIcon from '@mui/icons-material/FormatListBulleted';
|
|
21
|
+
import OrderedListIcon from '@mui/icons-material/FormatListNumbered';
|
|
22
|
+
|
|
23
|
+
import { Menu } from '../../../components';
|
|
24
|
+
import { labelOrderedList, labelUnorderedList } from '../../translatedLabels';
|
|
25
|
+
|
|
26
|
+
import { useStyles } from './ToolbarPlugin.styles';
|
|
27
|
+
|
|
28
|
+
const options = [
|
|
29
|
+
{
|
|
30
|
+
Icon: UnorderedListIcon,
|
|
31
|
+
label: labelUnorderedList,
|
|
32
|
+
value: 'bullet'
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
Icon: OrderedListIcon,
|
|
36
|
+
label: labelOrderedList,
|
|
37
|
+
value: 'number'
|
|
38
|
+
}
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
interface Props {
|
|
42
|
+
disabled?: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const ListButton = ({ disabled }: Props): JSX.Element => {
|
|
46
|
+
const { classes } = useStyles();
|
|
47
|
+
const { t } = useTranslation();
|
|
48
|
+
|
|
49
|
+
const [editor] = useLexicalComposerContext();
|
|
50
|
+
|
|
51
|
+
const [elementList, setElementList] = useState(null);
|
|
52
|
+
|
|
53
|
+
const formatBulletList = (): void => {
|
|
54
|
+
if (elementList !== 'bullet') {
|
|
55
|
+
editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined);
|
|
56
|
+
} else {
|
|
57
|
+
editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const formatNumberedList = (): void => {
|
|
62
|
+
if (elementList !== 'number') {
|
|
63
|
+
editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);
|
|
64
|
+
} else {
|
|
65
|
+
editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const formatList = (type): void => {
|
|
70
|
+
if (equals(type, elementList)) {
|
|
71
|
+
setElementList(null);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (equals(type, 'bullet')) {
|
|
75
|
+
formatBulletList();
|
|
76
|
+
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
formatNumberedList();
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const updateToolbar = useCallback(() => {
|
|
83
|
+
const selection = $getSelection();
|
|
84
|
+
const anchorNode = selection?.anchor.getNode();
|
|
85
|
+
const element = equals(anchorNode?.getKey(), 'root')
|
|
86
|
+
? anchorNode
|
|
87
|
+
: $findMatchingParent(anchorNode, (e) => {
|
|
88
|
+
const parent = e.getParent();
|
|
89
|
+
|
|
90
|
+
return parent !== null && $isRootOrShadowRoot(parent);
|
|
91
|
+
}) || anchorNode?.getTopLevelElementOrThrow();
|
|
92
|
+
|
|
93
|
+
const elementKey = element?.getKey();
|
|
94
|
+
const elementDOM = editor.getElementByKey(elementKey);
|
|
95
|
+
|
|
96
|
+
if (isNil(elementDOM)) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if ($isListNode(element)) {
|
|
101
|
+
const parentList = $getNearestNodeOfType(anchorNode, ListNode);
|
|
102
|
+
const type = parentList
|
|
103
|
+
? parentList.getListType()
|
|
104
|
+
: element.getListType();
|
|
105
|
+
setElementList(type);
|
|
106
|
+
}
|
|
107
|
+
}, [editor]);
|
|
108
|
+
|
|
109
|
+
const selectedList = options.find(({ value }) => equals(value, elementList));
|
|
110
|
+
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
return editor.registerUpdateListener(({ editorState }) => {
|
|
113
|
+
editorState.read(() => {
|
|
114
|
+
updateToolbar();
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
}, [editor, updateToolbar]);
|
|
118
|
+
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
return mergeRegister(
|
|
121
|
+
editor.registerUpdateListener(({ editorState }) => {
|
|
122
|
+
editorState.read(() => {
|
|
123
|
+
updateToolbar();
|
|
124
|
+
});
|
|
125
|
+
})
|
|
126
|
+
);
|
|
127
|
+
}, [editor, updateToolbar]);
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<Menu>
|
|
131
|
+
<Menu.Button
|
|
132
|
+
ariaLabel="list"
|
|
133
|
+
className={classes.button}
|
|
134
|
+
disabled={disabled}
|
|
135
|
+
>
|
|
136
|
+
{selectedList ? <selectedList.Icon /> : <UnorderedListIcon />}
|
|
137
|
+
</Menu.Button>
|
|
138
|
+
<Menu.Items className={classes.menuItems}>
|
|
139
|
+
<div className={classes.menu}>
|
|
140
|
+
{options.map(({ Icon, value, label }) => (
|
|
141
|
+
<Menu.Item
|
|
142
|
+
isActive={equals(value, elementList)}
|
|
143
|
+
key={value}
|
|
144
|
+
onClick={() => formatList(value)}
|
|
145
|
+
>
|
|
146
|
+
<Icon aria-label={t(label)} />
|
|
147
|
+
</Menu.Item>
|
|
148
|
+
))}
|
|
149
|
+
</div>
|
|
150
|
+
</Menu.Items>
|
|
151
|
+
</Menu>
|
|
152
|
+
);
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
export default ListButton;
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
2
|
-
|
|
3
1
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
4
2
|
import { createCommand, LexicalCommand } from 'lexical';
|
|
5
3
|
|
|
6
4
|
import MacrosIcon from '@mui/icons-material/TerminalOutlined';
|
|
7
5
|
|
|
8
|
-
import {
|
|
6
|
+
import { Menu } from '../../../components';
|
|
9
7
|
|
|
10
|
-
import { useStyles } from '.';
|
|
8
|
+
import { useStyles } from './ToolbarPlugin.styles';
|
|
11
9
|
|
|
12
10
|
const LowPriority = 1;
|
|
13
11
|
|
|
@@ -27,15 +25,12 @@ export const standardMacros = [
|
|
|
27
25
|
|
|
28
26
|
const MacrosButton = ({ disabled }: Props): JSX.Element => {
|
|
29
27
|
const { classes } = useStyles();
|
|
30
|
-
const [arMacrosDiplayed, setAreMacrosDiplayed] = useState(false);
|
|
31
28
|
|
|
32
29
|
const [editor] = useLexicalComposerContext();
|
|
33
30
|
|
|
34
31
|
const INSERT_MACROS_COMMAND: LexicalCommand<string> = createCommand();
|
|
35
32
|
|
|
36
|
-
const onClick = (
|
|
37
|
-
const macro = e.target.id || e.target.textContent.trim();
|
|
38
|
-
|
|
33
|
+
const onClick = (macro): void => {
|
|
39
34
|
editor.dispatchCommand(INSERT_MACROS_COMMAND, macro);
|
|
40
35
|
};
|
|
41
36
|
|
|
@@ -53,38 +48,27 @@ const MacrosButton = ({ disabled }: Props): JSX.Element => {
|
|
|
53
48
|
LowPriority
|
|
54
49
|
);
|
|
55
50
|
|
|
56
|
-
const displayMacros = (): void => {
|
|
57
|
-
setAreMacrosDiplayed(true);
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const actions = standardMacros.map((macro) => ({
|
|
61
|
-
label: macro,
|
|
62
|
-
onClick
|
|
63
|
-
}));
|
|
64
|
-
|
|
65
51
|
return (
|
|
66
|
-
<
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
<
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
)}
|
|
87
|
-
</PopoverMenu>
|
|
52
|
+
<Menu>
|
|
53
|
+
<Menu.Button
|
|
54
|
+
ariaLabel="Macros"
|
|
55
|
+
className={classes.button}
|
|
56
|
+
disabled={disabled}
|
|
57
|
+
>
|
|
58
|
+
<MacrosIcon />
|
|
59
|
+
</Menu.Button>
|
|
60
|
+
<Menu.Items className={classes.menuItems}>
|
|
61
|
+
{standardMacros.map((name) => (
|
|
62
|
+
<Menu.Item
|
|
63
|
+
className={classes.menuItem}
|
|
64
|
+
key={name}
|
|
65
|
+
onClick={(): void => onClick(name)}
|
|
66
|
+
>
|
|
67
|
+
{name}
|
|
68
|
+
</Menu.Item>
|
|
69
|
+
))}
|
|
70
|
+
</Menu.Items>
|
|
71
|
+
</Menu>
|
|
88
72
|
);
|
|
89
73
|
};
|
|
90
74
|
|
|
@@ -1,22 +1,32 @@
|
|
|
1
1
|
import { makeStyles } from 'tss-react/mui';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
autocomplete: {
|
|
5
|
-
width: theme.spacing(17)
|
|
6
|
-
}
|
|
7
|
-
}));
|
|
3
|
+
import { alpha } from '@mui/system';
|
|
8
4
|
|
|
9
|
-
export const
|
|
5
|
+
export const useStyles = makeStyles()((theme) => ({
|
|
10
6
|
button: {
|
|
11
|
-
|
|
12
|
-
display: 'flex',
|
|
13
|
-
flexDirection: 'row',
|
|
14
|
-
gap: theme.spacing(1)
|
|
7
|
+
color: theme.palette.text.primary
|
|
15
8
|
},
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
buttonSelected: {
|
|
10
|
+
backgroundColor: alpha(
|
|
11
|
+
theme.palette.primary.main,
|
|
12
|
+
theme.palette.action.activatedOpacity
|
|
13
|
+
)
|
|
14
|
+
},
|
|
15
|
+
menu: {
|
|
18
16
|
display: 'flex',
|
|
19
|
-
flexDirection: 'row'
|
|
20
|
-
|
|
17
|
+
flexDirection: 'row'
|
|
18
|
+
},
|
|
19
|
+
menuItem: {
|
|
20
|
+
'&, &.MuiMenuItem-root': {
|
|
21
|
+
fontSize: theme.typography.body2.fontSize
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
menuItems: {
|
|
25
|
+
'& > .MuiPaper-root.MuiMenu-paper': {
|
|
26
|
+
minWidth: 0
|
|
27
|
+
},
|
|
28
|
+
'& ul, & ul.MuiMenu-list': {
|
|
29
|
+
padding: 0
|
|
30
|
+
}
|
|
21
31
|
}
|
|
22
32
|
}));
|
|
@@ -16,6 +16,8 @@ import RedoIcon from '@mui/icons-material/Redo';
|
|
|
16
16
|
import { IconButton } from '../../..';
|
|
17
17
|
import { labelRedo, labelUndo } from '../../translatedLabels';
|
|
18
18
|
|
|
19
|
+
import { useStyles } from './ToolbarPlugin.styles';
|
|
20
|
+
|
|
19
21
|
const LowPriority = 1;
|
|
20
22
|
|
|
21
23
|
interface Props {
|
|
@@ -23,6 +25,8 @@ interface Props {
|
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
const UndoRedoButtons = ({ disabled }: Props): JSX.Element => {
|
|
28
|
+
const { classes } = useStyles();
|
|
29
|
+
|
|
26
30
|
const { t } = useTranslation();
|
|
27
31
|
|
|
28
32
|
const [canUndo, setCanUndo] = useState(false);
|
|
@@ -68,6 +72,7 @@ const UndoRedoButtons = ({ disabled }: Props): JSX.Element => {
|
|
|
68
72
|
<>
|
|
69
73
|
<IconButton
|
|
70
74
|
ariaLabel={translatedUndo}
|
|
75
|
+
className={classes.button}
|
|
71
76
|
disabled={!canUndo || disabled}
|
|
72
77
|
title={translatedUndo}
|
|
73
78
|
tooltipPlacement="top"
|
|
@@ -77,6 +82,7 @@ const UndoRedoButtons = ({ disabled }: Props): JSX.Element => {
|
|
|
77
82
|
</IconButton>
|
|
78
83
|
<IconButton
|
|
79
84
|
ariaLabel={translatedRedo}
|
|
85
|
+
className={classes.button}
|
|
80
86
|
disabled={!canRedo || disabled}
|
|
81
87
|
title={translatedRedo}
|
|
82
88
|
tooltipPlacement="top"
|
|
@@ -5,8 +5,10 @@ import { Divider } from '@mui/material';
|
|
|
5
5
|
import FormatButtons from './FormatButtons';
|
|
6
6
|
import UndoRedoButtons from './UndoRedoButtons';
|
|
7
7
|
import MacrosButton from './MacrosButton';
|
|
8
|
-
import BlockButtons from './BlockButtons';
|
|
9
8
|
import AlignPicker from './AlignPicker';
|
|
9
|
+
import ListButton from './ListButton';
|
|
10
|
+
import LinkButton from './LinkButton';
|
|
11
|
+
import BlockButtons from './BlockButtons';
|
|
10
12
|
|
|
11
13
|
interface Props {
|
|
12
14
|
className?: string;
|
|
@@ -22,14 +24,6 @@ export const useStyles = makeStyles()((theme) => ({
|
|
|
22
24
|
columnGap: theme.spacing(1),
|
|
23
25
|
display: 'flex',
|
|
24
26
|
marginBottom: theme.spacing(1)
|
|
25
|
-
},
|
|
26
|
-
macros: {
|
|
27
|
-
'& span': {
|
|
28
|
-
fontSize: theme.typography.caption.fontSize
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
macrosButton: {
|
|
32
|
-
marginBottom: theme.spacing(0.5)
|
|
33
27
|
}
|
|
34
28
|
}));
|
|
35
29
|
|
|
@@ -51,9 +45,10 @@ const ToolbarPlugin = ({
|
|
|
51
45
|
<BlockButtons disabled={disabled} />
|
|
52
46
|
</>
|
|
53
47
|
)}
|
|
54
|
-
<Divider flexItem orientation="vertical" />
|
|
55
48
|
<FormatButtons disabled={disabled} />
|
|
56
49
|
<AlignPicker disabled={disabled} />
|
|
50
|
+
<ListButton disabled={disabled} />
|
|
51
|
+
<LinkButton disabled={disabled} />
|
|
57
52
|
{displayMacrosButton && (
|
|
58
53
|
<>
|
|
59
54
|
<Divider flexItem orientation="vertical" />
|
|
@@ -3,3 +3,6 @@ export const labelRedo = 'Redo';
|
|
|
3
3
|
export const labelInputLink = 'Insert link';
|
|
4
4
|
export const labelSavedLink = 'Saved link';
|
|
5
5
|
export const labelEditLink = 'Edit link';
|
|
6
|
+
export const labelAlignPicker = 'align picker';
|
|
7
|
+
export const labelUnorderedList = 'Unordered List';
|
|
8
|
+
export const labelOrderedList = 'Ordered List';
|
|
@@ -15,11 +15,7 @@ import {
|
|
|
15
15
|
DragEndEvent,
|
|
16
16
|
Over
|
|
17
17
|
} from '@dnd-kit/core';
|
|
18
|
-
import {
|
|
19
|
-
SortableContext,
|
|
20
|
-
sortableKeyboardCoordinates,
|
|
21
|
-
SortingStrategy
|
|
22
|
-
} from '@dnd-kit/sortable';
|
|
18
|
+
import { SortableContext, SortingStrategy } from '@dnd-kit/sortable';
|
|
23
19
|
import {
|
|
24
20
|
equals,
|
|
25
21
|
find,
|
|
@@ -117,7 +113,6 @@ const SortableItems = <T extends { [propertyToFilterItemsOn]: string }>({
|
|
|
117
113
|
useSensor(MouseSensor),
|
|
118
114
|
useSensor(PointerSensor),
|
|
119
115
|
useSensor(KeyboardSensor, {
|
|
120
|
-
coordinateGetter: sortableKeyboardCoordinates,
|
|
121
116
|
keyboardCodes: {
|
|
122
117
|
cancel: ['Escape'],
|
|
123
118
|
end: ['Space', 'Enter'],
|
|
@@ -169,7 +164,7 @@ const SortableItems = <T extends { [propertyToFilterItemsOn]: string }>({
|
|
|
169
164
|
};
|
|
170
165
|
|
|
171
166
|
const getItemById = (id): T | undefined =>
|
|
172
|
-
find(propEq(
|
|
167
|
+
find(propEq(id, propertyToFilterItemsOn), items);
|
|
173
168
|
|
|
174
169
|
const activeItem = getItemById(activeId) as Record<string, unknown>;
|
|
175
170
|
|