@evoke-platform/ui-components 1.6.0-testing.1 → 1.6.0-testing.3

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.
@@ -47,7 +47,7 @@ export { Tooltip } from './Tooltip';
47
47
  export { Typography } from './Typography';
48
48
  export { TabContext, TabList, TabPanel, TreeItem, TreeView } from '@mui/lab';
49
49
  export { CardActionArea, CardActions, CardContent, CardHeader, CardMedia, Input, InputAdornment, InputLabel, ListItemButton, ListItemText, MenuList, SvgIcon, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TableSortLabel, } from '@mui/material';
50
- export { useGridApiRef } from '@mui/x-data-grid';
50
+ export { GridToolbarContainer, GridToolbarQuickFilter, useGridApiRef } from '@mui/x-data-grid';
51
51
  export { TreeItem as RichTreeItem, RichTreeView, TreeItem2Content, TreeItem2DragAndDropOverlay, TreeItem2GroupTransition, TreeItem2Icon, TreeItem2IconContainer, TreeItem2Label, TreeItem2Provider, TreeItem2Root, useTreeItem2, } from '@mui/x-tree-view';
52
52
  export type { GridSize } from '@mui/material';
53
53
  export type { GridCellParams, GridColDef, GridEventListener, GridFilterModel, GridInitialState, GridRowParams, GridSortModel, GridValueFormatterParams, GridValueGetterParams, } from '@mui/x-data-grid';
@@ -48,5 +48,5 @@ export { Typography } from './Typography';
48
48
  //TODO: Review following components. They also need theme control:
49
49
  export { TabContext, TabList, TabPanel, TreeItem, TreeView } from '@mui/lab';
50
50
  export { CardActionArea, CardActions, CardContent, CardHeader, CardMedia, Input, InputAdornment, InputLabel, ListItemButton, ListItemText, MenuList, SvgIcon, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TableSortLabel, } from '@mui/material';
51
- export { useGridApiRef } from '@mui/x-data-grid';
51
+ export { GridToolbarContainer, GridToolbarQuickFilter, useGridApiRef } from '@mui/x-data-grid';
52
52
  export { TreeItem as RichTreeItem, RichTreeView, TreeItem2Content, TreeItem2DragAndDropOverlay, TreeItem2GroupTransition, TreeItem2Icon, TreeItem2IconContainer, TreeItem2Label, TreeItem2Provider, TreeItem2Root, useTreeItem2, } from '@mui/x-tree-view';
@@ -17,7 +17,32 @@ const BuilderGrid = (props) => {
17
17
  borderBottom: 'none',
18
18
  boxShadow: 'rgba(145, 158, 171, 0.2) 0px 8px 16px',
19
19
  } },
20
- React.createElement(MuiDataGrid, { autoPageSize: !disablePagination, hideFooterPagination: disablePagination, hideFooter: disablePagination, onMenuOpen: (env) => setAnchorEl(env.target), loading: loading, rows: rows, ...rest, sx: {
20
+ React.createElement(MuiDataGrid, { autoPageSize: !disablePagination, hideFooterPagination: disablePagination, hideFooter: disablePagination, onMenuOpen: (env) => setAnchorEl(env.target), loading: loading, rows: rows, getRowId: (row) => row.id, disableColumnMenu: true, initialState: {
21
+ sorting: {
22
+ sortModel: initialSort ? [initialSort] : [],
23
+ },
24
+ }, componentsProps: {
25
+ panel: {
26
+ anchorEl: anchorEl,
27
+ placement: 'bottom-end',
28
+ sx: {
29
+ '& .MuiPaper-root': {
30
+ borderRadius: '6px',
31
+ boxShadow: '0px 24px 48px rgba(145, 158, 171, 0.4)',
32
+ padding: '8px',
33
+ stop: -120,
34
+ },
35
+ },
36
+ },
37
+ }, slots: {
38
+ toolbar: hideToolbar ? null : toolbar,
39
+ noResultsOverlay: () => {
40
+ return React.createElement(Box, null);
41
+ },
42
+ noRowsOverlay: () => {
43
+ return noRowsOverlay ? noRowsOverlay : null;
44
+ },
45
+ }, rowHeight: 60, columnHeaderHeight: 62, ...rest, sx: {
21
46
  border: 'none',
22
47
  '& .MuiDataGrid-toolbarContainer': {
23
48
  padding: '0',
@@ -64,32 +89,7 @@ const BuilderGrid = (props) => {
64
89
  },
65
90
  height: disablePagination && !loading ? 'auto' : 'calc(100vh - 240px)',
66
91
  ...rest.sx,
67
- }, getRowId: (row) => row.id, disableColumnMenu: true, initialState: {
68
- sorting: {
69
- sortModel: initialSort ? [initialSort] : [],
70
- },
71
- }, componentsProps: {
72
- panel: {
73
- anchorEl: anchorEl,
74
- placement: 'bottom-end',
75
- sx: {
76
- '& .MuiPaper-root': {
77
- borderRadius: '6px',
78
- boxShadow: '0px 24px 48px rgba(145, 158, 171, 0.4)',
79
- padding: '8px',
80
- stop: -120,
81
- },
82
- },
83
- },
84
- }, slots: {
85
- toolbar: hideToolbar ? null : toolbar,
86
- noResultsOverlay: () => {
87
- return React.createElement(Box, null);
88
- },
89
- noRowsOverlay: () => {
90
- return noRowsOverlay ? noRowsOverlay : null;
91
- },
92
- }, rowHeight: 60, columnHeaderHeight: 62 }))) : (React.createElement(React.Fragment, null, error ? (React.createElement(Box, { sx: {
92
+ } }))) : (React.createElement(React.Fragment, null, error ? (React.createElement(Box, { sx: {
93
93
  backgroundColor: '#fff',
94
94
  borderRadius: '6px',
95
95
  display: 'flex',
@@ -7,6 +7,7 @@ import sift from 'sift';
7
7
  import { Edit, TrashCan } from '../../../../../icons';
8
8
  import { Button, IconButton, Skeleton, Snackbar, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Tooltip, Typography, } from '../../../../core';
9
9
  import { Box } from '../../../../layout';
10
+ import { getReadableQuery } from '../../../CriteriaBuilder';
10
11
  import { getPrefixedUrl, normalizeDateTime, retrieveCustomErrorMessage } from '../../utils';
11
12
  import { ActionDialog } from './ActionDialog';
12
13
  import { DocumentViewerCell } from './DocumentViewerCell';
@@ -37,6 +38,7 @@ const RepeatableField = (props) => {
37
38
  const [relatedObject, setRelatedObject] = useState();
38
39
  const [hasCreateAction, setHasCreateAction] = useState(false);
39
40
  const [users, setUsers] = useState();
41
+ const [criteriaObjects, setCriteriaObjects] = useState([]);
40
42
  const [openDialog, setOpenDialog] = useState(false);
41
43
  const [dialogType, setDialogType] = useState();
42
44
  const [selectedRow, setSelectedRow] = useState();
@@ -50,9 +52,7 @@ const RepeatableField = (props) => {
50
52
  const [error, setError] = useState(false);
51
53
  const DEFAULT_CREATE_ACTION = '_create';
52
54
  const { instanceChanges } = useNotification();
53
- const fetchRelatedInstances = useCallback(async () => {
54
- if (openDialog)
55
- return;
55
+ const fetchRelatedObject = useCallback(async () => {
56
56
  let relatedObject;
57
57
  if (property.objectId) {
58
58
  try {
@@ -80,31 +80,83 @@ const RepeatableField = (props) => {
80
80
  catch (err) {
81
81
  console.error(error);
82
82
  }
83
- if (property.relatedPropertyId && instance?.id) {
84
- const filterProperty = `${property.relatedPropertyId}.id`;
85
- const filter = { where: { [filterProperty]: instance?.id }, limit: 100 };
86
- const objectId = property.objectId;
87
- try {
88
- const timeout = setTimeout(() => {
89
- setLoading(false);
90
- }, 300);
91
- setLoading(true);
92
- const instances = await apiServices.get(getPrefixedUrl(`/objects/${objectId}/instances`), {
93
- params: { filter: JSON.stringify(filter) },
94
- });
95
- clearTimeout(timeout);
83
+ }
84
+ relatedObject && checkCreateAccess(relatedObject);
85
+ }, [apiServices, property]);
86
+ const fetchRelatedInstances = useCallback(async () => {
87
+ if (openDialog)
88
+ return;
89
+ if (property.objectId && property.relatedPropertyId && instance?.id) {
90
+ const filterProperty = `${property.relatedPropertyId}.id`;
91
+ const filter = { where: { [filterProperty]: instance?.id }, limit: 100 };
92
+ const objectId = property.objectId;
93
+ try {
94
+ const timeout = setTimeout(() => {
96
95
  setLoading(false);
97
- if (instances) {
98
- setRelatedInstances(instances);
99
- }
100
- }
101
- catch (error) {
102
- setError(true);
96
+ }, 300);
97
+ setLoading(true);
98
+ const instances = await apiServices.get(getPrefixedUrl(`/objects/${objectId}/instances`), {
99
+ params: { filter: JSON.stringify(filter) },
100
+ });
101
+ clearTimeout(timeout);
102
+ setLoading(false);
103
+ if (instances) {
104
+ setRelatedInstances(instances);
103
105
  }
104
106
  }
107
+ catch (error) {
108
+ setError(true);
109
+ }
105
110
  }
106
- relatedObject && checkCreateAccess(relatedObject);
107
- }, [apiServices, property, viewLayout]);
111
+ }, [apiServices, property]);
112
+ const fetchCriteriaObjects = useCallback(async () => {
113
+ let objectIds = [];
114
+ const criteriaProperties = relatedObject?.properties?.filter((property) => property.type === 'criteria' && property.objectId) ?? [];
115
+ if (tableViewLayout) {
116
+ objectIds = criteriaProperties
117
+ .filter((p) => tableViewLayout.properties.some((column) => column.id === p.id))
118
+ .map((property) => property.objectId);
119
+ }
120
+ else {
121
+ objectIds = criteriaProperties.map((p) => p.objectId);
122
+ }
123
+ const objects = [];
124
+ for (const objectId of new Set(objectIds)) {
125
+ try {
126
+ const criteriaObject = await apiServices.get(getPrefixedUrl(`/objects/${objectId}/effective`), {
127
+ params: { fields: ['id', 'name', 'properties'] },
128
+ });
129
+ objects.push(criteriaObject);
130
+ }
131
+ catch (error) {
132
+ console.error(`Error fetching criteria object with ID ${objectId}:`, error);
133
+ }
134
+ }
135
+ setCriteriaObjects(objects);
136
+ }, [apiServices, tableViewLayout]);
137
+ useEffect(() => {
138
+ (async () => {
139
+ try {
140
+ const users = await apiServices.get(getPrefixedUrl(`/users`));
141
+ setUsers(users);
142
+ }
143
+ catch (error) {
144
+ console.error(error);
145
+ }
146
+ })();
147
+ }, [apiServices]);
148
+ useEffect(() => {
149
+ fetchRelatedObject();
150
+ fetchCriteriaObjects();
151
+ fetchRelatedInstances();
152
+ }, [fetchRelatedInstances, fetchCriteriaObjects, fetchRelatedObject, reloadOnErrorTrigger, instance]);
153
+ useEffect(() => {
154
+ if (relatedObject?.rootObjectId) {
155
+ const callback = () => fetchRelatedInstances();
156
+ instanceChanges?.subscribe(relatedObject?.rootObjectId, callback);
157
+ return () => instanceChanges?.unsubscribe(relatedObject?.rootObjectId, callback);
158
+ }
159
+ }, [instanceChanges, relatedObject]);
108
160
  const retrieveCriteria = (relatedObjProperty, action, object) => {
109
161
  let property;
110
162
  if (action.parameters) {
@@ -171,27 +223,6 @@ const RepeatableField = (props) => {
171
223
  });
172
224
  }
173
225
  };
174
- useEffect(() => {
175
- (async () => {
176
- try {
177
- const users = await apiServices.get(getPrefixedUrl(`/users`));
178
- setUsers(users);
179
- }
180
- catch (error) {
181
- console.error(error);
182
- }
183
- })();
184
- }, [apiServices]);
185
- useEffect(() => {
186
- fetchRelatedInstances();
187
- }, [fetchRelatedInstances, reloadOnErrorTrigger, instance]);
188
- useEffect(() => {
189
- if (relatedObject?.rootObjectId) {
190
- const callback = () => fetchRelatedInstances();
191
- instanceChanges?.subscribe(relatedObject?.rootObjectId, callback);
192
- return () => instanceChanges?.unsubscribe(relatedObject?.rootObjectId, callback);
193
- }
194
- }, [instanceChanges, relatedObject]);
195
226
  const deleteRow = (id) => {
196
227
  setDialogType('delete');
197
228
  setSelectedRow(id);
@@ -334,28 +365,24 @@ const RepeatableField = (props) => {
334
365
  };
335
366
  const getValue = (relatedInstance, propertyId, propertyType) => {
336
367
  const value = get(relatedInstance, propertyId);
337
- // If the property is not date-like then just return the
338
- // value found at the given path.
339
- if (!['date', 'date-time', 'time'].includes(propertyType)) {
340
- return value;
341
- }
342
368
  // If the date-like value is empty then there is no need to format.
343
369
  if (!value) {
344
370
  return value;
345
371
  }
346
- // At this point it has been asserted that there is a value
347
- // and since the property is date-like the value must be
348
- // a string.
349
- const stringValue = value;
350
372
  if (propertyType === 'date') {
351
- return DateTime.fromISO(stringValue).toLocaleString(DateTime.DATE_SHORT);
373
+ return DateTime.fromISO(value).toLocaleString(DateTime.DATE_SHORT);
352
374
  }
353
375
  if (propertyType === 'date-time') {
354
- return DateTime.fromISO(stringValue).toLocaleString(DateTime.DATETIME_SHORT);
376
+ return DateTime.fromISO(value).toLocaleString(DateTime.DATETIME_SHORT);
355
377
  }
356
378
  if (propertyType === 'time') {
357
- return DateTime.fromISO(stringValue).toLocaleString(DateTime.TIME_SIMPLE);
379
+ return DateTime.fromISO(value).toLocaleString(DateTime.TIME_SIMPLE);
380
+ }
381
+ if (propertyType === 'criteria' && typeof value === 'object') {
382
+ const property = relatedObject?.properties?.find((p) => p.id === propertyId);
383
+ return getReadableQuery(value, criteriaObjects.find((o) => o.id === property?.objectId)?.properties ?? []);
358
384
  }
385
+ return value;
359
386
  };
360
387
  const columns = retrieveViewLayout();
361
388
  return loading ? (React.createElement(React.Fragment, null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evoke-platform/ui-components",
3
- "version": "1.6.0-testing.1",
3
+ "version": "1.6.0-testing.3",
4
4
  "description": "",
5
5
  "main": "dist/published/index.js",
6
6
  "module": "dist/published/index.js",