@evoke-platform/ui-components 1.0.0-dev.218 → 1.0.0-dev.220

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 (25) hide show
  1. package/dist/published/components/custom/Form/Common/Form.d.ts +4 -3
  2. package/dist/published/components/custom/Form/Common/Form.js +1 -1
  3. package/dist/published/components/custom/Form/FormComponents/FormFieldComponent.js +2 -2
  4. package/dist/published/components/custom/HistoryLog/DisplayedProperty.d.ts +8 -0
  5. package/dist/published/components/custom/HistoryLog/DisplayedProperty.js +70 -0
  6. package/dist/published/components/custom/HistoryLog/Filter.d.ts +11 -0
  7. package/dist/published/components/custom/HistoryLog/Filter.js +55 -0
  8. package/dist/published/components/custom/HistoryLog/HistoryData.d.ts +10 -0
  9. package/dist/published/components/custom/HistoryLog/HistoryData.js +83 -0
  10. package/dist/published/components/custom/HistoryLog/HistoryLoading.d.ts +3 -0
  11. package/dist/published/components/custom/HistoryLog/HistoryLoading.js +39 -0
  12. package/dist/published/components/custom/HistoryLog/index.d.ts +22 -0
  13. package/dist/published/components/custom/HistoryLog/index.js +92 -0
  14. package/dist/published/components/custom/RichTextViewer/index.d.ts +15 -0
  15. package/dist/published/components/custom/RichTextViewer/index.js +47 -0
  16. package/dist/published/components/custom/index.d.ts +2 -0
  17. package/dist/published/components/custom/index.js +2 -0
  18. package/dist/published/index.d.ts +1 -1
  19. package/dist/published/index.js +1 -1
  20. package/dist/published/stories/HistoryLog.stories.d.ts +6 -0
  21. package/dist/published/stories/HistoryLog.stories.js +79 -0
  22. package/dist/published/stories/RichTextViewer.stories.d.ts +6 -0
  23. package/dist/published/stories/RichTextViewer.stories.js +12 -0
  24. package/dist/published/types.d.ts +20 -0
  25. package/package.json +5 -2
@@ -1,7 +1,8 @@
1
+ /// <reference types="react" />
1
2
  import { ApiServices, Obj, ObjectInstance, UserAccount } from '@evoke-platform/context';
2
- import { ReactNode } from 'react';
3
- import { Document, ObjectPropertyInputProps } from '../types';
3
+ import { ReactComponent } from '@formio/react';
4
4
  import '../../../../styles/form-component.css';
5
+ import { Document, ObjectPropertyInputProps } from '../types';
5
6
  declare type OnSaveResponse = {
6
7
  isSuccessful: boolean;
7
8
  error?: Record<string, unknown>;
@@ -32,7 +33,7 @@ export declare type FormProps = {
32
33
  };
33
34
  queryAddresses?: unknown;
34
35
  fieldHeight?: 'small' | 'medium';
35
- richTextEditor?: ReactNode;
36
+ richTextEditor?: typeof ReactComponent;
36
37
  };
37
38
  export declare function Form(props: FormProps): JSX.Element;
38
39
  export default Form;
@@ -12,11 +12,11 @@ import { Components, Form as FormIO } from '@formio/react';
12
12
  import { flatten } from 'flat';
13
13
  import { isEqual, toPairs } from 'lodash';
14
14
  import React, { useEffect, useRef, useState } from 'react';
15
+ import '../../../../styles/form-component.css';
15
16
  import { Skeleton, Snackbar } from '../../../core';
16
17
  import { Box } from '../../../layout';
17
18
  import { ButtonComponent, DocumentComponent, FormFieldComponent, ImageComponent, ObjectComponent, RepeatableFieldComponent, UserComponent, ViewOnlyComponent, } from '../FormComponents';
18
19
  import { addObjectPropertiesToComponentProps, buildComponentPropsFromDocumentProperties, buildComponentPropsFromObjectProperties, convertFormToComponents, getFlattenEntries, getPrefixedUrl, } from '../utils';
19
- import '../../../../styles/form-component.css';
20
20
  const usePrevious = (value) => {
21
21
  const ref = useRef();
22
22
  useEffect(() => {
@@ -320,10 +320,10 @@ export class FormFieldComponent extends ReactComponent {
320
320
  delete this.errorDetails['time'];
321
321
  }
322
322
  }
323
- if (validate.min || validate.max) {
323
+ if (!isNil(validate.min) || !isNil(validate.max)) {
324
324
  if (!isNil(value) &&
325
325
  value !== '' &&
326
- ((validate.min && value < validate.min) || (validate.max && value > validate.max))) {
326
+ ((!isNil(validate.min) && value < validate.min) || (!isNil(validate.max) && value > validate.max))) {
327
327
  this.errorDetails['min-max'] = validate.customMessage;
328
328
  }
329
329
  else {
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ import { ObjectProperty } from '../../../types';
3
+ declare type DisplayedPropertyProps = {
4
+ property: ObjectProperty;
5
+ value: unknown;
6
+ };
7
+ declare const DisplayedProperty: (props: DisplayedPropertyProps) => JSX.Element;
8
+ export default DisplayedProperty;
@@ -0,0 +1,70 @@
1
+ import React from 'react';
2
+ import { Grid } from '../../layout';
3
+ import { CardMedia, Typography } from '../../core';
4
+ import { DateTime } from 'luxon';
5
+ import { RichTextViewer } from '../RichTextViewer';
6
+ const DisplayedProperty = (props) => {
7
+ const { property, value } = props;
8
+ const getAddressAsString = (address) => {
9
+ let stringAddress = '';
10
+ if (address === null || address === void 0 ? void 0 : address.line1)
11
+ stringAddress = stringAddress.concat(address.line1);
12
+ if (address === null || address === void 0 ? void 0 : address.line2)
13
+ stringAddress = stringAddress ? stringAddress.concat(' ' + address.line2) : address.line2;
14
+ if (address === null || address === void 0 ? void 0 : address.city)
15
+ stringAddress = stringAddress ? stringAddress.concat(', ' + address.city) : address.city;
16
+ if (address === null || address === void 0 ? void 0 : address.county)
17
+ stringAddress = stringAddress ? stringAddress.concat(', ' + address.county) : address.county;
18
+ if (address === null || address === void 0 ? void 0 : address.state)
19
+ stringAddress = stringAddress ? stringAddress.concat(', ' + address.state) : address.state;
20
+ if (address === null || address === void 0 ? void 0 : address.zipCode)
21
+ stringAddress = stringAddress ? stringAddress.concat(' ' + address.zipCode) : address.zipCode;
22
+ return stringAddress;
23
+ };
24
+ const formatData = (property, value) => {
25
+ var _a, _b;
26
+ if (property === null || property === void 0 ? void 0 : property.objectId) {
27
+ return (_a = value === null || value === void 0 ? void 0 : value.name) !== null && _a !== void 0 ? _a : value === null || value === void 0 ? void 0 : value.id;
28
+ }
29
+ switch (property === null || property === void 0 ? void 0 : property.type) {
30
+ case 'string':
31
+ case 'boolean':
32
+ case 'number':
33
+ case 'integer':
34
+ return value === null || value === void 0 ? void 0 : value.toString();
35
+ case 'array':
36
+ return value === null || value === void 0 ? void 0 : value.toString().replaceAll(',', ', ');
37
+ case 'address':
38
+ return getAddressAsString(value);
39
+ case 'user':
40
+ return (_b = value === null || value === void 0 ? void 0 : value.name) !== null && _b !== void 0 ? _b : value === null || value === void 0 ? void 0 : value.id;
41
+ case 'time':
42
+ return value
43
+ ? DateTime.fromISO(DateTime.now().toISODate() + 'T' + value).toFormat('hh:mm a')
44
+ : undefined;
45
+ case 'date':
46
+ return value ? DateTime.fromISO(value).toFormat('MM/dd/yyyy') : undefined;
47
+ case 'date-time':
48
+ return value ? DateTime.fromISO(value).toFormat('MM/dd/yyyy hh:mm a') : undefined;
49
+ case 'document':
50
+ return value && Array.isArray(value) ? value.map((v) => v.name).join(', ') : undefined;
51
+ }
52
+ return value;
53
+ };
54
+ return (React.createElement(Grid, { item: true, xs: 4.75 }, property.type === 'image' && value ? (React.createElement(CardMedia, { component: "img", image: value, sx: {
55
+ borderRadius: '8px',
56
+ width: 'fit-content',
57
+ maxWidth: '100%',
58
+ maxHeight: '80px',
59
+ margin: '10px',
60
+ position: 'relative',
61
+ display: 'inline-block',
62
+ objectFit: 'contain',
63
+ } })) : property.type === 'richText' && typeof value === 'string' ? (React.createElement(RichTextViewer, { value: value })) : (React.createElement(Typography, { sx: {
64
+ fontSize: '12px',
65
+ padding: '0px 8px',
66
+ overflowWrap: 'break-word',
67
+ alignSelf: 'flex-start',
68
+ } }, value ? formatData(property, value) : 'None'))));
69
+ };
70
+ export default DisplayedProperty;
@@ -0,0 +1,11 @@
1
+ /// <reference types="react" />
2
+ import { EvokeObject } from '../../../types';
3
+ declare type HistoryFilterProps = {
4
+ filter: string[];
5
+ setFilter: (filter: string[]) => void;
6
+ object: EvokeObject;
7
+ order?: 'desc' | 'asc';
8
+ setOrder: (order: 'desc' | 'asc') => void;
9
+ };
10
+ declare const HistoryFilter: (props: HistoryFilterProps) => JSX.Element;
11
+ export default HistoryFilter;
@@ -0,0 +1,55 @@
1
+ import React from 'react';
2
+ import { Box } from '../../layout';
3
+ import { Button, Checkbox, MenuItem, Select, Typography } from '../../core';
4
+ import { SwapVert } from '@mui/icons-material';
5
+ import { isArray, startCase } from 'lodash';
6
+ const HistoryFilter = (props) => {
7
+ const { order, setOrder, filter, setFilter, object } = props;
8
+ return (React.createElement(Box, { sx: { display: 'flex', width: '100%' } },
9
+ React.createElement(Select, { size: 'small', renderValue: (selected) => {
10
+ if (isArray(selected) && selected.length) {
11
+ const selectedValues = selected.map((s) => s === object.name || s === 'instance' ? object.name : s);
12
+ return `Type: ${selectedValues
13
+ .map((s) => {
14
+ return s === object.name || s === 'instance' ? object.name : startCase(s + 's');
15
+ })
16
+ .join(', ')}`;
17
+ }
18
+ return 'Type: All';
19
+ }, displayEmpty: true, value: filter, sx: {
20
+ width: '100%',
21
+ borderRadius: '8px',
22
+ margin: '0 4px 16px 0',
23
+ maxWidth: '400px',
24
+ '@media (min-width: 600px)': { width: '72%' },
25
+ }, MenuProps: {
26
+ PaperProps: {
27
+ sx: {
28
+ boxShadow: '0px 24px 48px 0px rgba(145, 158, 171, 0.35)',
29
+ borderRadius: '12px',
30
+ },
31
+ },
32
+ } },
33
+ React.createElement(MenuItem, { sx: { borderBottom: '1px solid rgba(145, 158, 171, 0.24)' }, onClick: () => setFilter([]), disabled: !filter.length },
34
+ React.createElement(Typography, { fontSize: '14px', color: filter.length ? 'primary' : '#919EAB', sx: { marginLeft: '6px' } }, "Clear Selected Items")),
35
+ ['instance', 'document', 'correspondence'].map((option) => (React.createElement(MenuItem, { key: option, onClick: () => {
36
+ filter.includes(option)
37
+ ? setFilter(filter.filter((o) => o !== option))
38
+ : setFilter(filter.concat([option]));
39
+ } },
40
+ React.createElement(Checkbox, { sx: { padding: '3px', marginRight: '5px' }, checked: filter.includes(option) }),
41
+ React.createElement(Typography, { fontSize: '14px' }, option === 'instance' ? object.name : startCase(option + 's')))))),
42
+ React.createElement(Button, { variant: "outlined", color: 'inherit', sx: {
43
+ width: '100%',
44
+ maxHeight: '40px',
45
+ border: '1px solid #cbcbcb',
46
+ maxWidth: '135px',
47
+ '@media (min-width: 600px)': {
48
+ width: '27%',
49
+ },
50
+ }, onClick: () => (order === 'asc' ? setOrder('desc') : setOrder('asc')) },
51
+ React.createElement(Box, { display: 'flex', alignItems: 'center' },
52
+ React.createElement(SwapVert, { sx: { color: 'black', fontSize: '20px', marginRight: '4px' } }),
53
+ React.createElement(Typography, { fontWeight: 700, fontSize: '13px' }, order === 'asc' ? 'Newest First' : 'Oldest First')))));
54
+ };
55
+ export default HistoryFilter;
@@ -0,0 +1,10 @@
1
+ /// <reference types="react" />
2
+ import { EvokeObject, History } from '../../../types';
3
+ export declare const nanoid: (size?: number | undefined) => string;
4
+ declare type HistoryDataProps = {
5
+ records: History[];
6
+ documentHistory?: Record<string, History[]>;
7
+ object: EvokeObject;
8
+ };
9
+ declare const HistoricalData: (props: HistoryDataProps) => JSX.Element;
10
+ export default HistoricalData;
@@ -0,0 +1,83 @@
1
+ import React from 'react';
2
+ import { Box, Grid } from '../../layout';
3
+ import { Typography } from '../../core';
4
+ import { ArrowForward } from '@mui/icons-material';
5
+ import { customAlphabet } from 'nanoid';
6
+ import { lowercase, uppercase } from 'nanoid-dictionary';
7
+ import { lowerCase } from 'lodash';
8
+ import DisplayedProperty from './DisplayedProperty';
9
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
10
+ const { format } = require('small-date');
11
+ export const nanoid = customAlphabet(uppercase + lowercase);
12
+ const styles = {
13
+ timelineHeader: {
14
+ fontWeight: 600,
15
+ fontSize: '16px',
16
+ },
17
+ timelineItemHeader: {
18
+ fontSize: '12px',
19
+ color: '#637381',
20
+ },
21
+ timelineConnector: {
22
+ padding: '1px 0px 24px 22px',
23
+ borderLeft: '2px rgba(145, 158, 171, 0.24) solid',
24
+ marginLeft: '5px',
25
+ },
26
+ historyData: {
27
+ fontSize: '12px',
28
+ padding: '0px 8px',
29
+ overflowWrap: 'break-word',
30
+ },
31
+ };
32
+ const HistoricalData = (props) => {
33
+ const { records, documentHistory, object } = props;
34
+ const getPastDocumentVersion = (history) => {
35
+ var _a, _b, _c;
36
+ const documentVersions = (_c = documentHistory === null || documentHistory === void 0 ? void 0 : documentHistory[(_b = (_a = history.subject) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : 'unknown']) !== null && _c !== void 0 ? _c : [];
37
+ const currentVersion = documentVersions === null || documentVersions === void 0 ? void 0 : documentVersions.map((v) => v.timestamp).indexOf(history.timestamp);
38
+ return currentVersion ? documentVersions[currentVersion - 1] : undefined;
39
+ };
40
+ return (React.createElement(Box, { sx: styles.timelineConnector }, records.map((r) => {
41
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
42
+ return (React.createElement(Box, { margin: '16px 0px', key: `${r.timestamp}-${nanoid()}` },
43
+ React.createElement(Box, { sx: { display: 'flex', justifyContent: 'space-between' } },
44
+ React.createElement(Box, { sx: { display: 'flex', maxWidth: '60%', alignContent: 'flex-start' } },
45
+ React.createElement(Typography, { sx: { fontSize: '12px', color: '#637381' } },
46
+ React.createElement(Typography, { component: 'span', sx: { fontWeight: 600, fontSize: '12px' } }, (_a = r.user.name) !== null && _a !== void 0 ? _a : 'Unknown User'),
47
+ "\u00A0",
48
+ ['document', 'correspondence'].includes(r.type) ? lowerCase(r.event) : `- ${r.event}`)),
49
+ React.createElement(Box, null,
50
+ React.createElement(Typography, { sx: { fontSize: '12px', color: '#637381' } }, new Date(r.timestamp).getHours() === 12
51
+ ? format(new Date(r.timestamp), 'MMM dd, yyyy H:mm a')
52
+ : format(new Date(r.timestamp), 'MMM dd, yyyy h:mm a')))),
53
+ ((r.data && r.eventType !== 'create' && r.type === 'instance') ||
54
+ ['document', 'correspondence'].includes(r.type)) && (React.createElement(Box, { sx: {
55
+ backgroundColor: '#F4F6F8',
56
+ borderRadius: '4px',
57
+ paddingTop: ((_b = r.data) === null || _b === void 0 ? void 0 : _b.length) ? '4px' : '0px',
58
+ paddingBottom: ((_c = r.data) === null || _c === void 0 ? void 0 : _c.length) ? '4px' : '0px',
59
+ } },
60
+ r.type === 'instance' && r.data && (React.createElement(Box, null, r.data.map((d) => {
61
+ var _a;
62
+ const property = (_a = object.properties) === null || _a === void 0 ? void 0 : _a.find((p) => p.id === d.property);
63
+ return (property && (React.createElement(Grid, { container: true, key: property.id, display: "flex", gridTemplateColumns: 'fit-content(25%) fit-content(80%) fit-content(2%) fit-content(80%)', alignItems: "flex-start", justifyContent: "center", sx: {
64
+ overflowWrap: 'break-word',
65
+ } },
66
+ React.createElement(Grid, { item: true, xs: 2 },
67
+ React.createElement(Typography, { sx: Object.assign(Object.assign({}, styles.historyData), { fontWeight: 600, minWidth: 'fit-content', alignSelf: 'flex-start' }) }, property.name)),
68
+ React.createElement(DisplayedProperty, { property: property, value: d.historicalValue }),
69
+ React.createElement(Grid, { item: true, xs: 0.5 },
70
+ React.createElement(ArrowForward, { sx: { fontSize: '12px' } })),
71
+ React.createElement(DisplayedProperty, { property: property, value: d.updatedValue }))));
72
+ }))),
73
+ ['document', 'correspondence'].includes(r.type) && (React.createElement(Box, null,
74
+ React.createElement(Box, { display: "grid", gridTemplateColumns: 'fit-content(100%) fit-content(2%) fit-content(100%)', alignItems: "center", sx: { overflowWrap: 'break-word' } },
75
+ r.type === 'document' &&
76
+ r.event === 'Uploaded Document Version' &&
77
+ ((_d = r.subject) === null || _d === void 0 ? void 0 : _d.name) !== ((_f = (_e = getPastDocumentVersion(r)) === null || _e === void 0 ? void 0 : _e.subject) === null || _f === void 0 ? void 0 : _f.name) && (React.createElement(React.Fragment, null,
78
+ React.createElement(Typography, { sx: styles.historyData }, (_h = (_g = getPastDocumentVersion(r)) === null || _g === void 0 ? void 0 : _g.subject) === null || _h === void 0 ? void 0 : _h.name),
79
+ React.createElement(ArrowForward, { sx: { fontSize: '8px' } }))),
80
+ React.createElement(Typography, { sx: Object.assign(Object.assign({}, styles.historyData), { fontWeight: 600, minWidth: 'fit-content' }) }, (_j = r.subject) === null || _j === void 0 ? void 0 : _j.name))))))));
81
+ })));
82
+ };
83
+ export default HistoricalData;
@@ -0,0 +1,3 @@
1
+ /// <reference types="react" />
2
+ declare const HistoryLoading: () => JSX.Element;
3
+ export default HistoryLoading;
@@ -0,0 +1,39 @@
1
+ import React from 'react';
2
+ import { Box } from '../../layout';
3
+ import { Skeleton } from '../../core';
4
+ import { Circle } from '@mui/icons-material';
5
+ const styles = {
6
+ timelineConnector: {
7
+ padding: '1px 0px 5px 22px',
8
+ borderLeft: '2px rgba(145, 158, 171, 0.24) solid',
9
+ marginLeft: '5px',
10
+ },
11
+ headerSkeleton: {
12
+ height: '40px',
13
+ width: '210px',
14
+ borderRadius: '8px',
15
+ },
16
+ dataSkeleton: {
17
+ height: '25px',
18
+ borderRadius: '7px',
19
+ },
20
+ };
21
+ const HistoryLoading = () => {
22
+ return (React.createElement(React.Fragment, { key: 'history-log-loading' },
23
+ React.createElement(Box, { sx: { display: 'flex', alignItems: 'center' } },
24
+ React.createElement(Circle, { color: "primary", sx: { fontSize: '12px', marginRight: '12px' } }),
25
+ React.createElement(Skeleton, { variant: "text", sx: styles.headerSkeleton })),
26
+ React.createElement(Box, { sx: styles.timelineConnector },
27
+ React.createElement(Box, { margin: '4px 0px 24px 0px' },
28
+ React.createElement(Skeleton, { variant: "text", sx: Object.assign(Object.assign({}, styles.dataSkeleton), { width: '120px' }) }),
29
+ React.createElement(Skeleton, { variant: "text", sx: Object.assign(Object.assign({}, styles.dataSkeleton), { width: '65%' }) }),
30
+ React.createElement(Skeleton, { variant: "text", sx: Object.assign(Object.assign({}, styles.dataSkeleton), { width: '75%' }) }))),
31
+ React.createElement(Box, { sx: { display: 'flex', alignItems: 'center' } },
32
+ React.createElement(Circle, { color: "primary", sx: { fontSize: '12px', marginRight: '12px' } }),
33
+ React.createElement(Skeleton, { variant: "text", sx: styles.headerSkeleton })),
34
+ React.createElement(Box, { sx: styles.timelineConnector },
35
+ React.createElement(Box, { margin: '4px 0px 20px 0px' },
36
+ React.createElement(Skeleton, { variant: "text", sx: Object.assign(Object.assign({}, styles.dataSkeleton), { width: '120px' }) }),
37
+ React.createElement(Skeleton, { variant: "text", sx: Object.assign(Object.assign({}, styles.dataSkeleton), { width: '55%' }) })))));
38
+ };
39
+ export default HistoryLoading;
@@ -0,0 +1,22 @@
1
+ /// <reference types="react" />
2
+ import { EvokeObject, History } from '../../../types';
3
+ export declare type HistoryLogProps = {
4
+ /** The object instance associated with the history log */
5
+ object: EvokeObject;
6
+ /** An array of history entries representing the log. */
7
+ history: History[];
8
+ /** Indicates whether the history data is loading */
9
+ loading?: boolean;
10
+ /** The title displayed above the timeline */
11
+ title?: string;
12
+ };
13
+ /**
14
+ * Renders a timeline of the instance's history log.
15
+ * Users can filter the history by type and sort by date.
16
+ * Each update displays the state before and after the change.
17
+ *
18
+ * @param {HistoryLogProps} props - Configuration properties for the History Log component.
19
+ * @returns {JSX.Element} A timeline view representing the instance's history.
20
+ */
21
+ export declare const HistoryLog: (props: HistoryLogProps) => JSX.Element;
22
+ export default HistoryLog;
@@ -0,0 +1,92 @@
1
+ import { Box, Typography } from '../../../index';
2
+ import { Circle } from '@mui/icons-material';
3
+ import { DateTime } from 'luxon';
4
+ import React, { useEffect, useState } from 'react';
5
+ import HistoryFilter from './Filter';
6
+ import HistoricalData from './HistoryData';
7
+ import HistoryLoading from './HistoryLoading';
8
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
9
+ const { format } = require('small-date');
10
+ /**
11
+ * Renders a timeline of the instance's history log.
12
+ * Users can filter the history by type and sort by date.
13
+ * Each update displays the state before and after the change.
14
+ *
15
+ * @param {HistoryLogProps} props - Configuration properties for the History Log component.
16
+ * @returns {JSX.Element} A timeline view representing the instance's history.
17
+ */
18
+ export const HistoryLog = (props) => {
19
+ const { object, history, loading: initialLoading, title } = props;
20
+ const [historyMap, setHistoryMap] = useState({});
21
+ const [documentHistory, setDocumentHistory] = useState({});
22
+ const [filteredHistory, setFilteredHistory] = useState({});
23
+ const [filter, setFilter] = useState([]);
24
+ const [order, setOrder] = useState('desc');
25
+ const [loading, setLoading] = useState(initialLoading !== null && initialLoading !== void 0 ? initialLoading : true);
26
+ const sortHistoryByTimestamp = (historicalData, order) => {
27
+ return historicalData.sort((a, b) => order === 'desc' ? b.timestamp.localeCompare(a.timestamp) : a.timestamp.localeCompare(b.timestamp));
28
+ };
29
+ const sortGroupedHistoryByDate = (groupedHistory, order = 'desc') => {
30
+ return Object.fromEntries(Object.entries(groupedHistory)
31
+ .sort((a, b) => (order === 'desc' ? b[0].localeCompare(a[0]) : a[0].localeCompare(b[0])))
32
+ .map(([date, records]) => [date, sortHistoryByTimestamp(records, order)]));
33
+ };
34
+ useEffect(() => {
35
+ const groupedHistory = {};
36
+ const documentHistory = {};
37
+ history.forEach((h) => {
38
+ var _a, _b, _c, _d, _e, _f;
39
+ const timestamp = DateTime.fromISO(h.timestamp).toFormat('yyyy-MM-dd');
40
+ groupedHistory[timestamp] = ((_a = groupedHistory[timestamp]) !== null && _a !== void 0 ? _a : []).concat(h);
41
+ if (h.type === 'document') {
42
+ documentHistory[(_c = (_b = h.subject) === null || _b === void 0 ? void 0 : _b.id) !== null && _c !== void 0 ? _c : 'unknown'] = ((_f = documentHistory[(_e = (_d = h.subject) === null || _d === void 0 ? void 0 : _d.id) !== null && _e !== void 0 ? _e : 'unknown']) !== null && _f !== void 0 ? _f : []).concat(h);
43
+ }
44
+ });
45
+ setHistoryMap(sortGroupedHistoryByDate(groupedHistory, 'desc'));
46
+ setFilteredHistory(sortGroupedHistoryByDate(groupedHistory, 'desc'));
47
+ setDocumentHistory(sortGroupedHistoryByDate(documentHistory, 'asc'));
48
+ setLoading(false);
49
+ }, [history]);
50
+ useEffect(() => {
51
+ if (!filter.length) {
52
+ setFilteredHistory(sortGroupedHistoryByDate(historyMap !== null && historyMap !== void 0 ? historyMap : {}, order));
53
+ }
54
+ else {
55
+ const filtered = Object.fromEntries(Object.entries(historyMap !== null && historyMap !== void 0 ? historyMap : {}).map(([date, historicalData]) => [
56
+ date,
57
+ historicalData.filter((r) => filter.includes(r.type)),
58
+ ]));
59
+ setFilteredHistory(sortGroupedHistoryByDate(filtered, order));
60
+ }
61
+ }, [filter, historyMap, order]);
62
+ useEffect(() => {
63
+ setFilteredHistory(sortGroupedHistoryByDate(filteredHistory !== null && filteredHistory !== void 0 ? filteredHistory : {}, order));
64
+ }, [order]);
65
+ return (React.createElement(Box, { sx: { margin: '15px 24px 24px 24px' } },
66
+ !!title && (React.createElement(Box, { sx: { backgroundColor: '#fff', position: 'sticky', top: 0, padding: '15px 0', zIndex: 1400 } },
67
+ React.createElement(Typography, { sx: { fontWeight: 700, fontSize: '18px' } }, "History"))),
68
+ React.createElement(HistoryFilter, { order: order, setOrder: setOrder, filter: filter, setFilter: setFilter, object: object }),
69
+ !loading &&
70
+ filteredHistory &&
71
+ Object.entries(filteredHistory).map(([date, records]) => {
72
+ if (records.length) {
73
+ return (React.createElement(React.Fragment, { key: date },
74
+ React.createElement(Box, { sx: { display: 'flex', alignItems: 'center' } },
75
+ React.createElement(Circle, { color: "primary", sx: { fontSize: '12px', marginRight: '12px' } }),
76
+ React.createElement(Typography, { sx: { fontWeight: 600, fontSize: '16px' } },
77
+ format(new Date(), 'yyyy-MM-dd') === date
78
+ ? 'Today'
79
+ : format(new Date(date + ' 00:00:000'), 'DDD'),
80
+ ' ',
81
+ "\u00A0"),
82
+ React.createElement(Typography, { sx: { fontWeight: 600, fontSize: '16px', color: '#637381' } }, format(new Date(date + ' 00:00:000'), 'MMM dd, yyyy'))),
83
+ React.createElement(HistoricalData, { object: object, records: records, documentHistory: documentHistory })));
84
+ }
85
+ return null;
86
+ }),
87
+ !loading && filteredHistory && Object.values(filteredHistory).every((v) => !v.length) && (React.createElement(Box, { width: '100%', display: 'grid', justifyContent: 'center', marginTop: '60px' },
88
+ React.createElement(Typography, { fontSize: '20px', fontWeight: 700 }, "You Have No History"),
89
+ React.createElement(Typography, { fontSize: '14px', fontWeight: 400 }, "Try modifying the history type."))),
90
+ loading && React.createElement(HistoryLoading, null)));
91
+ };
92
+ export default HistoryLog;
@@ -0,0 +1,15 @@
1
+ /// <reference types="react" />
2
+ export declare type RichTextViewerProps = {
3
+ /**
4
+ * The RTF content to be displayed.
5
+ */
6
+ value: string;
7
+ };
8
+ /**
9
+ * This component takes RTF (Rich Text Format) content generated in
10
+ * the rich text property and renders it as a React component.
11
+ *
12
+ * @param props - The props for the component, including the RTF content.
13
+ * @returns The rendered HTML content.
14
+ */
15
+ export declare const RichTextViewer: (props: RichTextViewerProps) => JSX.Element;
@@ -0,0 +1,47 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import parse from 'html-react-parser';
3
+ import { EMFJS, RTFJS, WMFJS } from 'rtf.js';
4
+ import { Box } from '../../layout';
5
+ RTFJS.loggingEnabled(false);
6
+ WMFJS.loggingEnabled(false);
7
+ EMFJS.loggingEnabled(false);
8
+ /**
9
+ * This component takes RTF (Rich Text Format) content generated in
10
+ * the rich text property and renders it as a React component.
11
+ *
12
+ * @param props - The props for the component, including the RTF content.
13
+ * @returns The rendered HTML content.
14
+ */
15
+ export const RichTextViewer = (props) => {
16
+ const { value } = props;
17
+ const [htmlContent, setHtmlContent] = useState('');
18
+ useEffect(() => {
19
+ if (typeof value === 'string') {
20
+ let rtf = value;
21
+ // rtf.js does not support alignment commands inside of groups, so move them outside
22
+ rtf = rtf.replace(/\\pard\\plain\\q([lrc])\{([^}]+)\}/g, (match, align, text) => {
23
+ return `\\pard\\plain\\q${align} ${text}`;
24
+ });
25
+ // rtf.js does not support color tables, so replace the color table with the actual colors
26
+ rtf = rtf.replace(/\\cbpat(\d+)/g, (match, p1) => `\\highlight${p1}`);
27
+ // Fix list issue with rtf.js
28
+ rtf = rtf.replace(/\\listtext\\pard\\plain\s*(\d+)\.\d+/g, (match, p1) => `\\listtext\\pard\\plain ${p1}.`);
29
+ const doc = new RTFJS.Document(stringToArrayBuffer(rtf), {});
30
+ doc.render()
31
+ .then((htmlElements) => {
32
+ const combinedHtml = htmlElements.map((elem) => elem.outerHTML).join('');
33
+ setHtmlContent(combinedHtml);
34
+ })
35
+ .catch((error) => console.error(error));
36
+ }
37
+ }, [value]);
38
+ function stringToArrayBuffer(str) {
39
+ const buffer = new ArrayBuffer(str.length);
40
+ const bufferView = new Uint8Array(buffer);
41
+ for (let i = 0; i < str.length; i++) {
42
+ bufferView[i] = str.charCodeAt(i);
43
+ }
44
+ return buffer;
45
+ }
46
+ return React.createElement(Box, null, parse(htmlContent));
47
+ };
@@ -8,3 +8,5 @@ export { MenuBar } from './Menubar';
8
8
  export { MultiSelect } from './MultiSelect';
9
9
  export { RepeatableField } from './RepeatableField';
10
10
  export { UserAvatar } from './UserAvatar';
11
+ export { HistoryLog } from './HistoryLog';
12
+ export { RichTextViewer } from './RichTextViewer';
@@ -8,3 +8,5 @@ export { MenuBar } from './Menubar';
8
8
  export { MultiSelect } from './MultiSelect';
9
9
  export { RepeatableField } from './RepeatableField';
10
10
  export { UserAvatar } from './UserAvatar';
11
+ export { HistoryLog } from './HistoryLog';
12
+ export { RichTextViewer } from './RichTextViewer';
@@ -1,7 +1,7 @@
1
1
  export { ClickAwayListener, Toolbar, createTheme, styled } from '@mui/material';
2
2
  export { CalendarPicker, DateTimePicker, MonthPicker, PickersDay, StaticDateTimePicker, StaticTimePicker, TimePicker, YearPicker, } from '@mui/x-date-pickers';
3
3
  export * from './components/core';
4
- export { BuilderGrid, CriteriaBuilder, DataGrid, ErrorComponent, Form, FormField, MenuBar, MultiSelect, RepeatableField, UserAvatar, } from './components/custom';
4
+ export { BuilderGrid, CriteriaBuilder, DataGrid, ErrorComponent, Form, FormField, MenuBar, MultiSelect, RepeatableField, UserAvatar, HistoryLog, RichTextViewer, } from './components/custom';
5
5
  export { Box, Container, Grid, Stack } from './components/layout';
6
6
  export * as EVOKE_TYPES from './types';
7
7
  export * from './util';
@@ -1,7 +1,7 @@
1
1
  export { ClickAwayListener, Toolbar, createTheme, styled } from '@mui/material';
2
2
  export { CalendarPicker, DateTimePicker, MonthPicker, PickersDay, StaticDateTimePicker, StaticTimePicker, TimePicker, YearPicker, } from '@mui/x-date-pickers';
3
3
  export * from './components/core';
4
- export { BuilderGrid, CriteriaBuilder, DataGrid, ErrorComponent, Form, FormField, MenuBar, MultiSelect, RepeatableField, UserAvatar, } from './components/custom';
4
+ export { BuilderGrid, CriteriaBuilder, DataGrid, ErrorComponent, Form, FormField, MenuBar, MultiSelect, RepeatableField, UserAvatar, HistoryLog, RichTextViewer, } from './components/custom';
5
5
  export { Box, Container, Grid, Stack } from './components/layout';
6
6
  export * as EVOKE_TYPES from './types';
7
7
  export * from './util';
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ import { ComponentStory, ComponentMeta } from '@storybook/react';
3
+ import { HistoryLogProps } from '../components/custom/HistoryLog';
4
+ declare const _default: ComponentMeta<(props: HistoryLogProps) => JSX.Element>;
5
+ export default _default;
6
+ export declare const HistoryLog: ComponentStory<(props: HistoryLogProps) => JSX.Element>;
@@ -0,0 +1,79 @@
1
+ import React from 'react';
2
+ import { HistoryLog as CustomHistoryLog } from '../index';
3
+ export default {
4
+ title: 'Custom/HistoryLog',
5
+ component: CustomHistoryLog,
6
+ };
7
+ const HistoryLogTemplate = (args) => (React.createElement(CustomHistoryLog, Object.assign({}, args)));
8
+ export const HistoryLog = HistoryLogTemplate.bind({});
9
+ HistoryLog.args = {
10
+ title: 'History Log',
11
+ object: {
12
+ id: 'person',
13
+ name: 'Person',
14
+ properties: [
15
+ { id: 'firstName', name: 'First Name', type: 'string' },
16
+ { id: 'lastName', name: 'Last Name', type: 'string' },
17
+ { id: 'notes', name: 'Notes', type: 'richText' },
18
+ ],
19
+ actions: [],
20
+ },
21
+ history: [
22
+ {
23
+ user: { id: '1', name: 'Test User' },
24
+ event: 'Person Created',
25
+ eventType: 'create',
26
+ type: 'instance',
27
+ timestamp: '2021-09-01T12:00:00',
28
+ subject: {
29
+ id: '1',
30
+ name: 'Test Subject',
31
+ },
32
+ data: [
33
+ {
34
+ property: 'firstName',
35
+ updatedValue: 'Jane',
36
+ },
37
+ {
38
+ property: 'lastName',
39
+ updatedValue: 'Doe',
40
+ },
41
+ ],
42
+ },
43
+ {
44
+ user: { id: '1', name: 'Test User' },
45
+ event: 'Name Updated',
46
+ eventType: 'update',
47
+ type: 'instance',
48
+ timestamp: '2021-09-02T12:00:00',
49
+ subject: { id: '1', name: 'Test Subject' },
50
+ data: [
51
+ {
52
+ property: 'firstName',
53
+ historicalValue: 'Jane',
54
+ updatedValue: 'Jane Jr.',
55
+ },
56
+ {
57
+ property: 'lastName',
58
+ historicalValue: 'Doe',
59
+ updatedValue: 'Doe',
60
+ },
61
+ ],
62
+ },
63
+ {
64
+ user: { id: '1', name: 'Test User' },
65
+ event: 'Name Updated',
66
+ eventType: 'update',
67
+ type: 'instance',
68
+ timestamp: '2021-09-03T12:00:00',
69
+ subject: { id: '1', name: 'Test Subject' },
70
+ data: [
71
+ {
72
+ property: 'notes',
73
+ historicalValue: '{\\rtf1\\ansi\n\\pard\\plain\\ql Left aligned text.\\par\n\\pard\\plain\\qc Centered text.\\par\n\\pard\\plain\\qr Right aligned text.\\par\n}',
74
+ updatedValue: '{\\rtf1\\ansi\n\\pard\\plain\\ql \\b\\i\\ul Left aligned text.\\b0\\i0\\ulnone\\par\n\\pard\\plain\\qc \\b\\i\\ul Centered text.\\b0\\i0\\ulnone\\par\n\\pard\\plain\\qr \\b\\i\\ul Right aligned text.\\b0\\i0\\ulnone\\par\n\\pard\\plain\\qj \\b\\i\\ul Justified text.\\b0\\i0\\ulnone\\par\n}',
75
+ },
76
+ ],
77
+ },
78
+ ],
79
+ };
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ import { ComponentStory, ComponentMeta } from '@storybook/react';
3
+ import { RichTextViewerProps } from '../components/custom/RichTextViewer';
4
+ declare const _default: ComponentMeta<(props: RichTextViewerProps) => JSX.Element>;
5
+ export default _default;
6
+ export declare const RichTextViewer: ComponentStory<(props: RichTextViewerProps) => JSX.Element>;
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { RichTextViewer as CustomRichTextViewer } from '../index';
3
+ export default {
4
+ title: 'Custom/RichTextViewer',
5
+ component: CustomRichTextViewer,
6
+ };
7
+ const RichTextViewerTemplate = (args) => (React.createElement(CustomRichTextViewer, Object.assign({}, args)));
8
+ export const RichTextViewer = RichTextViewerTemplate.bind({});
9
+ RichTextViewer.args = {
10
+ // This is a sample RTF content generated from the evoke rich text editor.
11
+ value: "{\\rtf1\\deff0{\\fonttbl{\\f0 Calibri;}{\\f1 Times New Roman;}{\\f2 Arial;}{\\f3 Comic Sans MS;}{\\f4 Courier New;}{\\f5 Impact;}{\\f6 Lucida Console;}{\\f7 Tahoma;}{\\f8 Verdana;}}{\\colortbl ;\\red0\\green0\\blue255 ;\\red255\\green0\\blue0 ;\\red161\\green182\\blue214 ;\\red0\\green0\\blue0 ;}{\\*\\defchp \\f1\\fs22}{\\stylesheet {\\ql\\f1\\fs22 Normal;}{\\*\\cs1\\f1\\fs22 Default Paragraph Font;}{\\*\\cs2\\ul\\f1\\fs22\\cf1 Hyperlink;}{\\*\\ts3\\tsrowd\\fs22\\ql\\tsvertalt\\cltxlrtb Normal Table;}}{\\*\\listtable {\\list\\listtemplateid-1\\listhybrid{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid1724828877 \\'02\\'00.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li720\\lin720}{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid1648004642 \\'02\\'01.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li1440\\lin1440}{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid1794977542 \\'02\\'02.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li2160\\lin2160}{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid2120433904 \\'02\\'03.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li2880\\lin2880}{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid575479593 \\'02\\'04.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li3600\\lin3600}{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid1286449543 \\'02\\'05.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li4320\\lin4320}{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid1264123316 \\'02\\'06.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li5040\\lin5040}{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid1047350518 \\'02\\'07.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li5760\\lin5760}{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid226529494 \\'02\\'08.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li6480\\lin6480}{\\listname ;}\\listid1}{\\list\\listtemplateid-1\\listhybrid{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid1532193306 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li720\\lin720}{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid2107293787 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li1440\\lin1440}{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid9569355 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li2160\\lin2160}{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid364031910 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li2880\\lin2880}{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid472054489 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li3600\\lin3600}{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid242557682 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li4320\\lin4320}{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid330708956 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li5040\\lin5040}{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid781235209 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li5760\\lin5760}{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid417914393 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li6480\\lin6480}{\\listname ;}\\listid2}{\\list\\listtemplateid-1\\listhybrid{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid631399824 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li720\\lin720}{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid777553364 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li1440\\lin1440}{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid1040940783 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li2160\\lin2160}{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid1534400223 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li2880\\lin2880}{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid1619661386 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li3600\\lin3600}{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid1032775825 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li4320\\lin4320}{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid1278562953 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li5040\\lin5040}{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid1164322782 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li5760\\lin5760}{\\listlevel\\levelnfc23\\levelnfcn23\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid1907985166 \\'01\\u8226\\'e2;}{\\levelnumbers;}\\levellegal0\\levelnorestart0\\fi-360\\li6480\\lin6480}{\\listname ;}\\listid3}{\\list\\listtemplateid-1\\listhybrid{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid390960229 \\'02\\'00.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li720\\lin720}{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid181252923 \\'02\\'01.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li1440\\lin1440}{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid441957082 \\'02\\'02.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li2160\\lin2160}{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid1835039521 \\'02\\'03.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li2880\\lin2880}{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid239806422 \\'02\\'04.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li3600\\lin3600}{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid304908989 \\'02\\'05.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li4320\\lin4320}{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid431571160 \\'02\\'06.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li5040\\lin5040}{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid375482639 \\'02\\'07.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li5760\\lin5760}{\\listlevel\\levelnfc0\\levelnfcn0\\leveljc0\\leveljcn0\\levelfollow0\\levelstartat1{\\leveltext\\leveltemplateid1116549653 \\'02\\'08.;}{\\levelnumbers\\'01;}\\levellegal0\\levelnorestart0\\fi-360\\li6480\\lin6480}{\\listname ;}\\listid4}}{\\*\\listoverridetable {\\listoverride\\listid1\\listoverridecount0\\ls1}{\\listoverride\\listid2\\listoverridecount0\\ls2}{\\listoverride\\listid3\\listoverridecount0\\ls3}{\\listoverride\\listid4\\listoverridecount0\\ls4}}{\\info}\\nouicompat\\splytwnine\\htmautsp\\expshrtn\\spltpgpar\\deftab720\\sectd\\marglsxn1440\\margrsxn1440\\margtsxn1440\\margbsxn1440\\headery720\\footery720\\pgwsxn12240\\pghsxn15840\\cols1\\colsx720\\pard\\plain\\ql{\\f1\\fs16\\cf0 Small font}\\f1\\fs16\\cf0\\par\\pard\\plain\\ql\\f1\\fs16\\cf0\\par\\pard\\plain\\ql{\\f2\\fs16\\cf0 Arial Font}\\f2\\fs16\\cf0\\par\\pard\\plain\\ql\\f2\\fs16\\cf0\\par\\pard\\plain\\ql{\\f3\\fs16\\cf0 Comic Sans MS}\\f3\\fs16\\cf0\\par\\pard\\plain\\ql\\f3\\fs16\\cf0\\par\\pard\\plain\\ql{\\f4\\fs16\\cf0 Courier}\\f4\\fs16\\cf0\\par\\pard\\plain\\ql\\f4\\fs16\\cf0\\par\\pard\\plain\\ql{\\f5\\fs16\\cf0 Impact}\\f5\\fs16\\cf0\\par\\pard\\plain\\ql\\f5\\fs16\\cf0\\par\\pard\\plain\\ql{\\f6\\fs16\\cf0 Lucida }\\f6\\fs16\\cf0\\par\\pard\\plain\\ql\\f6\\fs16\\cf0\\par\\pard\\plain\\ql{\\f7\\fs16\\cf0 Tahoma}\\f7\\fs16\\cf0\\par\\pard\\plain\\ql\\f7\\fs16\\cf0\\par\\pard\\plain\\ql{\\f8\\fs16\\cf0 Verdana}\\f8\\fs16\\cf0\\par\\pard\\plain\\ql\\f8\\fs22\\cf0\\par\\pard\\plain\\ql{\\f1\\fs32\\cf0 large font}\\f1\\fs22\\cf0\\par\\pard\\plain\\ql{\\f1\\fs22\\cf2 red text}\\f1\\fs22\\cf2\\par\\pard\\plain\\ql\\shading0\\cbpat3{\\f1\\fs22\\cf4 background color}\\f1\\fs22\\cf4\\par\\pard\\plain\\ql{\\b\\f1\\fs22\\cf0 bold}\\f1\\fs22\\cf0\\par\\pard\\plain\\ql{\\i\\f1\\fs22\\cf0 italic}\\f1\\fs22\\cf0\\par\\pard\\plain\\ql{\\ul\\f1\\fs22\\cf0 underline}\\f1\\fs22\\cf0\\par\\pard\\plain\\ql{\\strike\\f1\\fs22\\cf0 cross out}\\f1\\fs22\\cf0\\par\\pard\\plain\\ql{\\f1\\fs22\\cf0 super}{\\super\\f1\\fs18\\cf0 script}\\f1\\fs22\\cf0\\par\\pard\\plain\\ql{\\f1\\fs22\\cf0 sub}{\\sub\\f1\\fs18\\cf0 script}\\f1\\fs22\\cf0\\par\\pard\\plain\\ql{\\f1\\fs22\\cf0 left align}\\f1\\fs22\\cf0\\par\\pard\\plain\\qc{\\f1\\fs22\\cf0 center align}\\f1\\fs22\\cf0\\par\\pard\\plain\\qr{\\f1\\fs22\\cf0 right align}\\f1\\fs22\\cf0\\par\\pard\\plain\\ql{\\f1\\fs22\\cf0 \\u8226\\'e2}{\\f1\\fs22\\cf0 bullet}\\f1\\fs22\\cf0\\par\\pard\\plain\\ql{\\f1\\fs22\\cf0 \\u8226\\'e2}{\\f1\\fs22\\cf0 list}\\f1\\fs22\\cf0\\par\\pard\\plain\\ql\\f1\\fs22\\cf0\\par{\\listtext\\pard\\plain 1.0}\\pard\\plain\\ilvl0\\ls4\\ql\\fi-360\\li720\\lin720{\\f1\\fs22\\cf0 number}\\f1\\fs22\\cf0\\par{\\listtext\\pard\\plain 2.0}\\pard\\plain\\ilvl0\\ls4\\ql\\fi-360\\li720\\lin720{\\f1\\fs22\\cf0 list}\\f1\\fs22\\cf0\\par\\pard\\plain\\ql\\f1\\fs22\\cf0\\par\\pard\\plain\\ql\\f1\\fs22\\cf0\\par\\pard\\plain\\ql\\f1\\fs22\\cf0\\par}",
12
+ };
@@ -76,4 +76,24 @@ export declare type ContainerView = {
76
76
  type: 'container';
77
77
  children?: ContainerView[] | ConfiguredWidget[];
78
78
  };
79
+ export declare type HistoryEventType = 'create' | 'update' | 'delete' | 'queue' | 'print' | 'email' | 'upload';
80
+ export declare type HistoryType = 'correspondence' | 'document' | 'instance';
81
+ export declare type History = {
82
+ user: Reference;
83
+ event: string;
84
+ eventType: HistoryEventType;
85
+ type: HistoryType;
86
+ timestamp: string;
87
+ subject: Reference;
88
+ data?: HistoryData[];
89
+ };
90
+ export declare type HistoryData = {
91
+ property: string;
92
+ historicalValue?: unknown;
93
+ updatedValue?: unknown;
94
+ };
95
+ export declare type Reference = {
96
+ id: string;
97
+ name?: string;
98
+ };
79
99
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evoke-platform/ui-components",
3
- "version": "1.0.0-dev.218",
3
+ "version": "1.0.0-dev.220",
4
4
  "description": "",
5
5
  "main": "dist/published/index.js",
6
6
  "module": "dist/published/index.js",
@@ -114,8 +114,10 @@
114
114
  "eslint-plugin-no-inline-styles": "^1.0.5",
115
115
  "flat": "^6.0.1",
116
116
  "formiojs": "^4.15.0-rc.23",
117
- "handlebars": "^4.7.8",
117
+ "html-react-parser": "^5.1.18",
118
118
  "luxon": "^2.5.2",
119
+ "nanoid": "^5.0.8",
120
+ "handlebars": "^4.7.8",
119
121
  "nanoid-dictionary": "^4.3.0",
120
122
  "pluralize": "^8.0.0",
121
123
  "pretty-bytes": "^6.1.1",
@@ -123,6 +125,7 @@
123
125
  "react-input-mask": "^2.0.4",
124
126
  "react-number-format": "^4.9.3",
125
127
  "react-querybuilder": "^6.0.2",
128
+ "rtf.js": "^3.0.9",
126
129
  "sift": "^17.1.3",
127
130
  "small-date": "^2.0.0"
128
131
  },