@dartech/arsenal-ui 0.0.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.
Files changed (124) hide show
  1. package/.babelrc +12 -0
  2. package/.eslintrc.json +22 -0
  3. package/README.md +7 -0
  4. package/index.ts +3 -0
  5. package/jest.config.js +9 -0
  6. package/package.json +21 -0
  7. package/project.json +69 -0
  8. package/rollup.config.js +135 -0
  9. package/src/interfaces/common.ts +12 -0
  10. package/src/interfaces/definition.ts +143 -0
  11. package/src/interfaces/index.ts +3 -0
  12. package/src/interfaces/ui.ts +35 -0
  13. package/src/lib/Alert/Alert.tsx +108 -0
  14. package/src/lib/Alert/index.ts +1 -0
  15. package/src/lib/Definition/CreateDefinition/CreateDefinition.tsx +74 -0
  16. package/src/lib/Definition/CreateDefinition/index.ts +1 -0
  17. package/src/lib/Definition/DefinitionFiller/DefinitionFiller.tsx +85 -0
  18. package/src/lib/Definition/DefinitionFiller/WidgetDefinitionFiller.tsx +96 -0
  19. package/src/lib/Definition/DefinitionFiller/index.ts +2 -0
  20. package/src/lib/Definition/index.ts +2 -0
  21. package/src/lib/DemPropertyField/DemPropertyField.tsx +93 -0
  22. package/src/lib/DemPropertyField/DemPropertyView/DemPropertyView.tsx +44 -0
  23. package/src/lib/DemPropertyField/DemPropertyView/index.ts +1 -0
  24. package/src/lib/DemPropertyField/MultipleDemField/MultipleDemField.tsx +293 -0
  25. package/src/lib/DemPropertyField/MultipleDemField/index.tsx +1 -0
  26. package/src/lib/DemPropertyField/RestrictedValuesEditor.tsx +63 -0
  27. package/src/lib/DemPropertyField/SingleDemField/SingleDemField.tsx +156 -0
  28. package/src/lib/DemPropertyField/SingleDemField/index.ts +1 -0
  29. package/src/lib/DemPropertyField/index.ts +2 -0
  30. package/src/lib/DemPropertyField/styles.ts +50 -0
  31. package/src/lib/DemPropertyField/widgets/DemBooleanWidget.tsx +26 -0
  32. package/src/lib/DemPropertyField/widgets/DemDateTimeWidget.tsx +34 -0
  33. package/src/lib/DemPropertyField/widgets/DemDateWidget.tsx +33 -0
  34. package/src/lib/DemPropertyField/widgets/DemFieldWidget.tsx +67 -0
  35. package/src/lib/DemPropertyField/widgets/DemFloatWidget.tsx +49 -0
  36. package/src/lib/DemPropertyField/widgets/DemIntegerWidget.tsx +63 -0
  37. package/src/lib/DemPropertyField/widgets/DemJsonWidget.tsx +33 -0
  38. package/src/lib/DemPropertyField/widgets/DemStringWidget.tsx +35 -0
  39. package/src/lib/DemPropertyField/widgets/DemTimeWidget.tsx +46 -0
  40. package/src/lib/DemPropertyField/widgets/index.ts +1 -0
  41. package/src/lib/Forms/BackButton.tsx +45 -0
  42. package/src/lib/Forms/ControlAceEditor.tsx +103 -0
  43. package/src/lib/Forms/ControlAutocomplete.tsx +134 -0
  44. package/src/lib/Forms/ControlCheckbox.tsx +57 -0
  45. package/src/lib/Forms/ControlDebouncedInput.tsx +69 -0
  46. package/src/lib/Forms/ControlInput.tsx +102 -0
  47. package/src/lib/Forms/ControlNumberInput.tsx +144 -0
  48. package/src/lib/Forms/ControlRadioBtn.tsx +46 -0
  49. package/src/lib/Forms/ControlSelect.tsx +135 -0
  50. package/src/lib/Forms/CopyButton.tsx +49 -0
  51. package/src/lib/Forms/index.ts +10 -0
  52. package/src/lib/InfoItem/InfoItem.tsx +39 -0
  53. package/src/lib/InfoItem/index.ts +1 -0
  54. package/src/lib/InfoItem/styles.ts +17 -0
  55. package/src/lib/JsonPathPicker/JsonPathPicker.tsx +71 -0
  56. package/src/lib/JsonPathPicker/PropertyStep.tsx +74 -0
  57. package/src/lib/JsonPathPicker/index.ts +1 -0
  58. package/src/lib/JsonView/JsonView.tsx +43 -0
  59. package/src/lib/JsonView/index.ts +1 -0
  60. package/src/lib/Loader/Loader.tsx +41 -0
  61. package/src/lib/Loader/index.ts +1 -0
  62. package/src/lib/Modals/JsonModalView.tsx +52 -0
  63. package/src/lib/Modals/index.ts +1 -0
  64. package/src/lib/Property/PropertyValueField/BooleanValueField.tsx +41 -0
  65. package/src/lib/Property/PropertyValueField/DateTimeValueField.tsx +59 -0
  66. package/src/lib/Property/PropertyValueField/DateValueField.tsx +59 -0
  67. package/src/lib/Property/PropertyValueField/EntityValueField.tsx +33 -0
  68. package/src/lib/Property/PropertyValueField/JsonValueField.tsx +64 -0
  69. package/src/lib/Property/PropertyValueField/PropertyValue.tsx +97 -0
  70. package/src/lib/Property/PropertyValueField/PropertyValueField.tsx +86 -0
  71. package/src/lib/Property/PropertyValueField/StringValueField.tsx +21 -0
  72. package/src/lib/Property/PropertyValueField/TimeValueField.tsx +68 -0
  73. package/src/lib/Property/PropertyValueField/ValueComponent.tsx +63 -0
  74. package/src/lib/Property/PropertyValueField/index.ts +1 -0
  75. package/src/lib/Property/PropertyWidget/PropertyWidget.tsx +167 -0
  76. package/src/lib/Property/PropertyWidget/index.ts +1 -0
  77. package/src/lib/Property/UpsertProperty/CreatePropertiesList.tsx +131 -0
  78. package/src/lib/Property/UpsertProperty/CreatePropertyFormFields.tsx +147 -0
  79. package/src/lib/Property/UpsertProperty/CustomPropertyField.tsx +40 -0
  80. package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/BigDecimalPropertyFields.tsx +41 -0
  81. package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/DateAdditionalFields.tsx +27 -0
  82. package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/EntityAdditionalFields.tsx +133 -0
  83. package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/EntityReferencePropertyFields.tsx +46 -0
  84. package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/PropertyAdditionalFields.tsx +52 -0
  85. package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/StringPropertyFields.tsx +98 -0
  86. package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/index.ts +1 -0
  87. package/src/lib/Property/UpsertProperty/index.ts +2 -0
  88. package/src/lib/Property/UpsertProperty/useCustomFields.ts +22 -0
  89. package/src/lib/Property/ViewPropertiesList/ViewPropertiesList.tsx +50 -0
  90. package/src/lib/Property/ViewPropertiesList/index.ts +1 -0
  91. package/src/lib/Property/ViewProperty/EntityPropertiesShortView.tsx +41 -0
  92. package/src/lib/Property/ViewProperty/EntityPropertiesView.tsx +48 -0
  93. package/src/lib/Property/ViewProperty/PropertyDataTable.tsx +139 -0
  94. package/src/lib/Property/ViewProperty/PropertyItem.tsx +46 -0
  95. package/src/lib/Property/ViewProperty/ViewProperty.tsx +52 -0
  96. package/src/lib/Property/ViewProperty/index.ts +1 -0
  97. package/src/lib/Property/index.ts +4 -0
  98. package/src/lib/Status/Status.tsx +15 -0
  99. package/src/lib/Status/index.ts +1 -0
  100. package/src/lib/Status/styles.ts +14 -0
  101. package/src/lib/Table/Table.tsx +116 -0
  102. package/src/lib/Table/TableColumnMenu.tsx +12 -0
  103. package/src/lib/Table/TablePagination.tsx +42 -0
  104. package/src/lib/Table/index.ts +1 -0
  105. package/src/lib/Table/styles.ts +59 -0
  106. package/src/lib/Table/usePagination.ts +15 -0
  107. package/src/lib/Table/useTableQueryPagination.ts +49 -0
  108. package/src/lib/Table/useTableQuerySorting.ts +52 -0
  109. package/src/lib/Tabs/RouteTabs.tsx +54 -0
  110. package/src/lib/Tabs/TabPanel.tsx +42 -0
  111. package/src/lib/Tabs/index.ts +2 -0
  112. package/src/lib/TemplateContent/ExpressionDecorator.tsx +7 -0
  113. package/src/lib/TemplateContent/TemplateContentEditor.tsx +144 -0
  114. package/src/lib/TemplateContent/index.ts +1 -0
  115. package/src/lib/index.ts +14 -0
  116. package/src/utils/common.ts +68 -0
  117. package/src/utils/dem.ts +78 -0
  118. package/src/utils/hooks.ts +41 -0
  119. package/src/utils/index.ts +5 -0
  120. package/src/utils/ui-utils.tsx +71 -0
  121. package/src/utils/validators.ts +130 -0
  122. package/tsconfig.json +24 -0
  123. package/tsconfig.lib.json +22 -0
  124. package/tsconfig.spec.json +19 -0
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import Box from '@material-ui/core/Box';
3
+ import Pagination from '@material-ui/lab/Pagination';
4
+ import MuiTablePagination from '@material-ui/core/TablePagination';
5
+ import {
6
+ gridPageCountSelector,
7
+ gridPageSelector,
8
+ gridRowCountSelector,
9
+ gridPageSizeSelector,
10
+ useGridApiContext,
11
+ useGridSelector,
12
+ } from '@mui/x-data-grid';
13
+
14
+ const TablePagination = () => {
15
+ const apiRef = useGridApiContext();
16
+ const page = useGridSelector(apiRef, gridPageSelector);
17
+ const pageCount = useGridSelector(apiRef, gridPageCountSelector);
18
+ const rowCount = useGridSelector(apiRef, gridRowCountSelector);
19
+ const pageSize = useGridSelector(apiRef, gridPageSizeSelector);
20
+
21
+ const onPageChange = (value) => apiRef.current.setPage(value);
22
+ const onRowsPerPageChange = (event: React.ChangeEvent<HTMLInputElement>) =>
23
+ apiRef.current.setPageSize(parseInt(event.target.value, 10));
24
+
25
+ return (
26
+ <Box px={2} display="flex" alignItems="center">
27
+ <MuiTablePagination
28
+ component="div"
29
+ page={page}
30
+ count={rowCount}
31
+ rowsPerPage={pageSize}
32
+ rowsPerPageOptions={[10, 20, 50, 100]}
33
+ onPageChange={(event, value) => onPageChange(value)}
34
+ onRowsPerPageChange={onRowsPerPageChange}
35
+ ActionsComponent={() => <></>}
36
+ />
37
+ <Pagination count={pageCount} page={page + 1} onChange={(event, value) => onPageChange(value - 1)} />
38
+ </Box>
39
+ );
40
+ };
41
+
42
+ export default TablePagination;
@@ -0,0 +1 @@
1
+ export * from './Table';
@@ -0,0 +1,59 @@
1
+ import { makeStyles } from '@material-ui/core/styles';
2
+
3
+ export default makeStyles({
4
+ root: {
5
+ width: '100%',
6
+
7
+ '& .MuiDataGrid-virtualScrollerContent': {
8
+ height: 'auto !important',
9
+ minHeight: '56px !important',
10
+ },
11
+
12
+ '& .MuiDataGrid-virtualScrollerRenderZone': {
13
+ position: 'static',
14
+ },
15
+
16
+ '& .MuiDataGrid-renderingZone': {
17
+ maxHeight: 'none !important',
18
+ },
19
+
20
+ '& .MuiDataGrid-cell': {
21
+ maxHeight: 'none !important',
22
+ lineHeight: 'unset !important',
23
+ whiteSpace: 'normal !important',
24
+ textOverflow: 'ellipsis',
25
+ wordBreak: 'break-all',
26
+
27
+ '& .MuiDataGrid-actionsCell': {
28
+ width: '100%',
29
+ gridGap: '4px',
30
+ flexWrap: 'wrap',
31
+
32
+ '& > button[aria-label="more"]': {
33
+ marginLeft: 'auto',
34
+ },
35
+ },
36
+ },
37
+
38
+ '& .MuiDataGrid-row': {
39
+ maxHeight: 'none !important',
40
+ },
41
+
42
+ '& .Sorted': {
43
+ '& .MuiDataGrid-iconButtonContainer': {
44
+ visibility: 'visible',
45
+ width: 'auto',
46
+
47
+ '& svg': {
48
+ opacity: '1 !important',
49
+ },
50
+ },
51
+
52
+ '&.--desc': {
53
+ '& svg': {
54
+ transform: 'rotate(180deg)',
55
+ },
56
+ },
57
+ },
58
+ },
59
+ });
@@ -0,0 +1,15 @@
1
+ import { useEffect, useState } from 'react';
2
+
3
+ const usePagination = (initialPageSize?: number) => {
4
+ const [pageSize, setPageSize] = useState(10);
5
+
6
+ useEffect(() => {
7
+ setPageSize(initialPageSize);
8
+ }, [initialPageSize]);
9
+
10
+ const handlePageSizeChange = (size) => setPageSize(size);
11
+
12
+ return { pageSize, handlePageSizeChange };
13
+ };
14
+
15
+ export default usePagination;
@@ -0,0 +1,49 @@
1
+ import { useEffect, useMemo } from 'react';
2
+ import { useLocation, useHistory } from 'react-router-dom';
3
+ import { GridFeatureMode } from '@mui/x-data-grid';
4
+
5
+ interface Props {
6
+ mode: GridFeatureMode;
7
+ }
8
+
9
+ export const useTableQueryPagination = ({ mode }: Props) => {
10
+ const history = useHistory();
11
+ const { search, state } = useLocation();
12
+ const queryParams = useMemo(() => new URLSearchParams(search), [search]);
13
+
14
+ const page = +queryParams.get('page') || 0;
15
+ const size = +queryParams.get('size') || 10;
16
+
17
+ const onPageChange = (newPage: number) => {
18
+ queryParams.set('page', `${newPage}`);
19
+ history.replace({ pathname: history.location.pathname, search: queryParams.toString() });
20
+ };
21
+
22
+ const onSizeChange = (count: number) => {
23
+ queryParams.set('size', `${count}`);
24
+ history.replace({ pathname: history.location.pathname, search: queryParams.toString() });
25
+ };
26
+
27
+ useEffect(() => {
28
+ if (mode === 'server') {
29
+ if (!queryParams.has('page')) {
30
+ queryParams.set('page', '0');
31
+ }
32
+
33
+ if (!queryParams.has('size')) {
34
+ queryParams.set('size', `10`);
35
+ }
36
+
37
+ history.replace({ pathname: history.location.pathname, search: queryParams.toString() }, state);
38
+ }
39
+ }, [search, mode]);
40
+
41
+ return {
42
+ page,
43
+ size,
44
+ onPageChange,
45
+ onSizeChange,
46
+ };
47
+ };
48
+
49
+ export default useTableQueryPagination;
@@ -0,0 +1,52 @@
1
+ import { useMemo } from 'react';
2
+ import { useHistory, useLocation } from 'react-router-dom';
3
+ import { GridColumnHeaderParams, GridColumns } from '@mui/x-data-grid';
4
+
5
+ export const useTableQuerySorting = () => {
6
+ const history = useHistory();
7
+ const { search, state } = useLocation();
8
+
9
+ const queryParams = useMemo(() => new URLSearchParams(search), [search]);
10
+ const sortParams = queryParams.getAll('sort').map((param) => param.split(','));
11
+
12
+ const onColumnHeaderClick = ({ field }: GridColumnHeaderParams) => {
13
+ let keyFound = false;
14
+
15
+ const sortValues = queryParams.getAll('sort');
16
+ queryParams.delete('sort');
17
+
18
+ sortValues.forEach((sortValue) => {
19
+ const [key, sort] = sortValue.split(',');
20
+ if (key === field) {
21
+ keyFound = true;
22
+ if (sort === 'asc') {
23
+ queryParams.append('sort', `${key},desc`);
24
+ }
25
+ } else {
26
+ queryParams.append('sort', `${key},${sort}`);
27
+ }
28
+ });
29
+
30
+ if (!keyFound) {
31
+ queryParams.append('sort', `${field},asc`);
32
+ }
33
+
34
+ history.replace({ pathname: history.location.pathname, search: queryParams.toString() }, state);
35
+ };
36
+
37
+ const getSortedColumns = (columns: GridColumns): GridColumns => {
38
+ return columns.map((column) => {
39
+ const columnSort = sortParams.find((param) => param[0] === column.field);
40
+ if (columnSort) {
41
+ column.headerClassName = `Sorted --${columnSort[1]} `;
42
+ } else {
43
+ column.headerClassName = '';
44
+ }
45
+ return column;
46
+ });
47
+ };
48
+
49
+ return { onColumnHeaderClick, getSortedColumns };
50
+ };
51
+
52
+ export default useTableQuerySorting;
@@ -0,0 +1,54 @@
1
+ import { useMemo } from 'react';
2
+ import Box from '@material-ui/core/Box';
3
+ import Paper from '@material-ui/core/Paper';
4
+ import Tab from '@material-ui/core/Tab';
5
+ import Tabs from '@material-ui/core/Tabs';
6
+ import TabPanel from './TabPanel';
7
+
8
+ import { useHistory, useLocation } from 'react-router-dom';
9
+
10
+ interface RouteTab {
11
+ name: string;
12
+ label: string;
13
+ component: React.ReactElement;
14
+ }
15
+
16
+ interface Props {
17
+ tabs: RouteTab[];
18
+ }
19
+
20
+ export const RouteTabs = (props: Props) => {
21
+ const { tabs } = props;
22
+
23
+ const history = useHistory();
24
+ const location = useLocation();
25
+
26
+ const queryParams = useMemo(() => new URLSearchParams(location.search), [location.search]);
27
+ const value = queryParams.get('tab');
28
+
29
+ const handleChange = (event, newValue: string) => {
30
+ queryParams.set('tab', newValue);
31
+ history.replace({ pathname: history.location.pathname, search: queryParams.toString() });
32
+ };
33
+
34
+ return (
35
+ <Box>
36
+ <Paper>
37
+ <Tabs value={value || tabs[0]?.name} indicatorColor="primary" textColor="primary" onChange={handleChange}>
38
+ {tabs.map((tab) => (
39
+ <Tab key={tab.name} value={tab.name} label={tab.label} />
40
+ ))}
41
+ </Tabs>
42
+ </Paper>
43
+ <Box mt={2}>
44
+ {tabs.map((tab) => (
45
+ <TabPanel key={tab.name} value={value || tabs[0]?.name} index={tab.name}>
46
+ {tab.component}
47
+ </TabPanel>
48
+ ))}
49
+ </Box>
50
+ </Box>
51
+ );
52
+ };
53
+
54
+ export default RouteTabs;
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+
3
+ /**
4
+ * This interface is referencing the [[TabPanel]] component props.
5
+ * @category Common UI components
6
+ */
7
+ export interface TabPanelProps {
8
+ /**
9
+ * Active tab value
10
+ */
11
+ value: number | string;
12
+ /**
13
+ * Index of current panel
14
+ */
15
+ index: number | string;
16
+ /**
17
+ * Rendered children component
18
+ */
19
+ children: React.ReactElement;
20
+ }
21
+
22
+ /**
23
+ * Tab panel component. Used with tabs component
24
+ * @category Common UI components
25
+ */
26
+ export const TabPanel = (props: TabPanelProps) => {
27
+ const { children, value, index, ...other } = props;
28
+
29
+ return (
30
+ <div
31
+ role="tabpanel"
32
+ hidden={value !== index}
33
+ id={`simple-tabpanel-${index}`}
34
+ aria-labelledby={`simple-tab-${index}`}
35
+ {...other}
36
+ >
37
+ {value === index ? children : null}
38
+ </div>
39
+ );
40
+ };
41
+
42
+ export default TabPanel;
@@ -0,0 +1,2 @@
1
+ export * from './TabPanel';
2
+ export * from './RouteTabs';
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+
3
+ const ExpressionDecorator = ({ children }) => {
4
+ return <span style={{ backgroundColor: '#e4ecff' }}>{children}</span>;
5
+ };
6
+
7
+ export default ExpressionDecorator;
@@ -0,0 +1,144 @@
1
+ import MUIRichTextEditor from 'mui-rte';
2
+ import { createTheme, ThemeProvider } from '@material-ui/core/styles';
3
+ import { ContentState, EditorState, Modifier, convertFromHTML, convertToRaw } from 'draft-js';
4
+ import FunctionsIcon from '@material-ui/icons/Functions';
5
+ import Typography from '@material-ui/core/Typography';
6
+ import ExpressionDecorator from './ExpressionDecorator';
7
+ import { JsonPathPicker } from '../JsonPathPicker';
8
+
9
+ import { useEffect, useState } from 'react';
10
+ // import { stateToHTML } from 'draft-js-export-html';
11
+ import { useToggle } from '../../utils';
12
+ import { JsonPathPickerProperties, PropertiesArrayType } from '../../interfaces';
13
+ import { useController, useFormContext } from 'react-hook-form';
14
+
15
+ type Props = {
16
+ fieldName: string;
17
+ getProperties?: () => JsonPathPickerProperties;
18
+ initialText?: string;
19
+ };
20
+
21
+ const defaultTheme = createTheme();
22
+
23
+ Object.assign(defaultTheme, {
24
+ overrides: {
25
+ MUIRichTextEditor: {
26
+ root: {
27
+ marginTop: 20,
28
+ width: '100%',
29
+ border: '1px solid gray',
30
+ padding: '8px',
31
+ },
32
+ editor: {
33
+ minHeight: '300px',
34
+ },
35
+ toolbar: {
36
+ backgroundColor: '#eee',
37
+ },
38
+ },
39
+ },
40
+ });
41
+
42
+ export const TemplateContentEditor = ({ fieldName, getProperties, initialText }: Props) => {
43
+ const { control, setValue, clearErrors } = useFormContext();
44
+ const {
45
+ fieldState: { error },
46
+ } = useController({
47
+ control,
48
+ name: fieldName,
49
+ rules: {
50
+ required: 'Please, fill content',
51
+ },
52
+ });
53
+
54
+ const defaultContent = convertToRaw(EditorState.createEmpty().getCurrentContent());
55
+ const { open: jsonPathPickerOpen, onOpen: onJsonPathPickerOpen, onClose: onJsonPathPickerClose } = useToggle();
56
+
57
+ const [content, setContent] = useState(JSON.stringify(defaultContent));
58
+ const [properties, setProperties] = useState<
59
+ {
60
+ properties: PropertiesArrayType;
61
+ pathPrefix: string;
62
+ title: string;
63
+ }[]
64
+ >([]);
65
+ const [editorState, setEditorState] = useState<EditorState>(null);
66
+
67
+ useEffect(() => {
68
+ if (initialText) {
69
+ const contentState = convertFromHTML(initialText);
70
+ const state =
71
+ contentState && ContentState.createFromBlockArray(contentState.contentBlocks, contentState.entityMap);
72
+ setContent(JSON.stringify(convertToRaw(state)));
73
+ }
74
+ }, [initialText]);
75
+
76
+ const handleChange = (state: EditorState) => {
77
+ const currentContentState = state.getCurrentContent();
78
+ const selectionState = state.getSelection();
79
+ EditorState.push(state, Modifier.replaceText(currentContentState, selectionState, ''), 'remove-range');
80
+
81
+ const isEmpty = !state.getCurrentContent().hasText();
82
+ const content = currentContentState.getPlainText();
83
+ // stateToHTML(currentContentState);
84
+
85
+ setValue(fieldName, !isEmpty ? content : '');
86
+ clearErrors(fieldName);
87
+ };
88
+
89
+ const handleJsonPathPickerClick = (eState) => {
90
+ setEditorState(eState);
91
+ setProperties(getProperties());
92
+ onJsonPathPickerOpen();
93
+ };
94
+
95
+ const handleJsonPathPaste = (jsonPath: string) => {
96
+ const currentContentState = editorState.getCurrentContent();
97
+ const selectionState = editorState.getSelection();
98
+
99
+ const state = EditorState.push(
100
+ editorState,
101
+ Modifier.insertText(currentContentState, selectionState, jsonPath),
102
+ 'insert-characters'
103
+ ).getCurrentContent();
104
+
105
+ setContent(JSON.stringify(convertToRaw(state)));
106
+ onJsonPathPickerClose();
107
+ };
108
+
109
+ return (
110
+ <ThemeProvider theme={defaultTheme}>
111
+ <MUIRichTextEditor
112
+ defaultValue={content}
113
+ label="Start here..."
114
+ controls={['title', 'bold', 'italic', 'strikethrough', 'numberList', 'bulletList', 'code', 'jsonPathPicker']}
115
+ onChange={handleChange}
116
+ customControls={[
117
+ {
118
+ name: 'jsonPathPicker',
119
+ icon: <FunctionsIcon />,
120
+ type: 'callback',
121
+ onClick: handleJsonPathPickerClick,
122
+ },
123
+ ]}
124
+ decorators={[
125
+ {
126
+ component: ExpressionDecorator,
127
+ regex: /\$\([^\s]*\)/g,
128
+ },
129
+ ]}
130
+ />
131
+ <Typography color="secondary">{error?.message}</Typography>
132
+ {jsonPathPickerOpen && (
133
+ <JsonPathPicker
134
+ open={jsonPathPickerOpen}
135
+ properties={properties}
136
+ onClose={onJsonPathPickerClose}
137
+ onPaste={handleJsonPathPaste}
138
+ />
139
+ )}
140
+ </ThemeProvider>
141
+ );
142
+ };
143
+
144
+ export default TemplateContentEditor;
@@ -0,0 +1 @@
1
+ export * from './TemplateContentEditor';
@@ -0,0 +1,14 @@
1
+ export * from './Alert';
2
+ export * from './Forms';
3
+ export * from './Loader';
4
+ export * from './Table';
5
+ export * from './Tabs';
6
+ export * from './DemPropertyField';
7
+ export * from './Modals';
8
+ export * from './InfoItem';
9
+ export * from './Definition';
10
+ export * from './Property';
11
+ export * from './Status';
12
+ export * from './JsonView';
13
+ export * from './JsonPathPicker';
14
+ export * from './TemplateContent';
@@ -0,0 +1,68 @@
1
+ export const removeArrayItem = (arr: Array<unknown>, index: number) => {
2
+ const newArr = [...arr];
3
+ newArr.splice(index, 1);
4
+ return newArr;
5
+ };
6
+
7
+ export const validateJson = (value: string): boolean => {
8
+ try {
9
+ JSON.parse(value);
10
+ } catch (error) {
11
+ return false;
12
+ }
13
+ return true;
14
+ };
15
+
16
+ export function capitalize(str: string): string {
17
+ return str.replace(/(^\w)|([-\s]\w)/g, (c) => c.toUpperCase());
18
+ }
19
+
20
+ export const sortArrayOfObjects = (a: any, b: any, key: string, order = 'asc') => {
21
+ const valueA = a[key];
22
+ const valueB = b[key];
23
+
24
+ if (valueA < valueB) return order === 'asc' ? -1 : 1;
25
+ if (valueA > valueB) return order === 'asc' ? 1 : -1;
26
+ return 0;
27
+ };
28
+
29
+ export const getJsonStringValue = (value: unknown): string => {
30
+ if (!value) return '';
31
+ if (typeof value !== 'string') {
32
+ try {
33
+ return JSON.stringify(value, null, '\t');
34
+ } catch (error) {
35
+ return 'Failed to stringify JSON';
36
+ }
37
+ }
38
+ return value;
39
+ };
40
+
41
+ export const safeParseJson = (value: string) => {
42
+ try {
43
+ return JSON.parse(value);
44
+ } catch (error) {
45
+ return null;
46
+ }
47
+ };
48
+
49
+ export const deepParseJson = (value: string) => {
50
+ try {
51
+ const parsedValue = JSON.parse(value);
52
+ Object.keys(parsedValue).forEach((key) => {
53
+ parsedValue[key] = deepParseJson(parsedValue[key]);
54
+ });
55
+ return parsedValue;
56
+ } catch (error) {
57
+ return value;
58
+ }
59
+ };
60
+
61
+ // export const convertArrayToObjectByKey = (array: { [key: string]: string }[], key: string) => {
62
+ // const obj = {};
63
+ // array.forEach((el) => {
64
+ // obj[el[key]] = { ...el };
65
+ // delete obj[el[key]][key];
66
+ // });
67
+ // return obj;
68
+ // };
@@ -0,0 +1,78 @@
1
+ import { PropertyType, EntityTypeProperty, PropertiesArrayType } from '../interfaces';
2
+ import { sortArrayOfObjects } from './common';
3
+ import { format } from 'date-fns';
4
+
5
+ export const isExpression = (value: unknown): boolean => {
6
+ return typeof value === 'string' ? value.startsWith('$') : false;
7
+ };
8
+
9
+ export function propertiesObjectToArray(properties, fields?: { [key: string]: unknown }) {
10
+ return Object.keys(properties)
11
+ .map((key) => {
12
+ const propObj = { key, ...properties[key], ...(fields ? fields : {}) };
13
+ if (propObj['propertyType'] === PropertyType.ENTITY) {
14
+ propObj['properties'] = propertiesObjectToArray(propObj['properties'], fields);
15
+ }
16
+
17
+ if (propObj['propertyType'] === PropertyType.JSON) {
18
+ try {
19
+ propObj.defaultValue = JSON.stringify(propObj.defaultValue);
20
+ } catch (error) {
21
+ propObj.defaultValue = '';
22
+ }
23
+ }
24
+
25
+ if (propObj['uiSettings']) {
26
+ try {
27
+ propObj.uiSettings = JSON.stringify(propObj.uiSettings);
28
+ } catch (error) {
29
+ propObj.uiSettings = '';
30
+ }
31
+ }
32
+
33
+ if (propObj['isMultiple']) {
34
+ if ('defaultValues' in propObj) {
35
+ propObj['defaultValue'] = propObj.defaultValues;
36
+ }
37
+ if ('values' in propObj) {
38
+ propObj['value'] = propObj.values;
39
+ }
40
+ }
41
+
42
+ return propObj;
43
+ })
44
+ .sort((a, b) => sortArrayOfObjects(a, b, 'sortOrder'));
45
+ }
46
+
47
+ export const getDemPropertyDateFormat = (defaultFormat: string, propertyFormat: string) => {
48
+ if (propertyFormat) {
49
+ try {
50
+ const correctFormat = propertyFormat.replace(/Z/g, 'XXX');
51
+ format(new Date(), correctFormat);
52
+ return correctFormat;
53
+ } catch (e) {
54
+ console.error('Incorrect format', e);
55
+ return defaultFormat;
56
+ }
57
+ }
58
+ return defaultFormat;
59
+ };
60
+
61
+ export const getEntityStarterValue = (property: EntityTypeProperty) => {
62
+ let properties: PropertiesArrayType = [];
63
+ if (Array.isArray(property.properties)) {
64
+ properties = property.properties;
65
+ } else {
66
+ properties = propertiesObjectToArray(property.properties);
67
+ }
68
+
69
+ return properties.reduce((value, property) => {
70
+ const result = JSON.parse(JSON.stringify(value));
71
+ if (property.propertyType === PropertyType.ENTITY) {
72
+ result[property.key] = getEntityStarterValue(property);
73
+ } else {
74
+ result[property.key] = property.propertyType;
75
+ }
76
+ return result;
77
+ }, {});
78
+ };
@@ -0,0 +1,41 @@
1
+ import { useEffect, useRef, useState } from 'react';
2
+
3
+ export function useDebounce(func: (args?: any) => void, delay: number) {
4
+ const timer = useRef<NodeJS.Timeout>();
5
+
6
+ useEffect(() => {
7
+ return () => {
8
+ if (!timer.current) return;
9
+ clearTimeout(timer.current);
10
+ };
11
+ }, []);
12
+
13
+ const debounceFunction = (...args) => {
14
+ clearTimeout(timer.current);
15
+ timer.current = setTimeout(() => {
16
+ func(...args);
17
+ }, delay);
18
+ };
19
+
20
+ return debounceFunction;
21
+ }
22
+
23
+
24
+ export const useToggle = () => {
25
+ const [open, setOpen] = useState(false);
26
+
27
+ const toggle = () => {
28
+ setOpen((prevState) => !prevState);
29
+ };
30
+
31
+ const onClose = () => {
32
+ setOpen(false);
33
+ };
34
+
35
+ const onOpen = () => {
36
+ setOpen(true);
37
+ };
38
+
39
+ return { open, toggle, onClose, onOpen };
40
+ };
41
+
@@ -0,0 +1,5 @@
1
+ export * from './common';
2
+ export * from './ui-utils';
3
+ export * from './hooks';
4
+ export * from './validators';
5
+ export * from './dem';