@evoke-platform/ui-components 1.6.0-dev.2 → 1.6.0-dev.20

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 (76) hide show
  1. package/dist/published/components/core/SwipeableDrawer/SwipeableDrawer.d.ts +4 -0
  2. package/dist/published/components/core/SwipeableDrawer/SwipeableDrawer.js +8 -0
  3. package/dist/published/components/core/SwipeableDrawer/index.d.ts +3 -0
  4. package/dist/published/components/core/SwipeableDrawer/index.js +3 -0
  5. package/dist/published/components/core/index.d.ts +2 -1
  6. package/dist/published/components/core/index.js +2 -1
  7. package/dist/published/components/custom/BuilderGrid/BuilderGrid.js +27 -27
  8. package/dist/published/components/custom/Form/FormComponents/ImageComponent/Image.js +2 -2
  9. package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/RepeatableField.js +87 -57
  10. package/dist/published/components/custom/Form/tests/Form.test.js +1 -1
  11. package/dist/published/components/custom/FormField/AddressFieldComponent/addressFieldComponent.js +1 -1
  12. package/dist/published/components/custom/FormField/BooleanSelect/BooleanSelect.js +3 -3
  13. package/dist/published/components/custom/FormField/DatePickerSelect/DatePickerSelect.js +7 -1
  14. package/dist/published/components/custom/FormField/DateTimePickerSelect/DateTimePickerSelect.js +7 -1
  15. package/dist/published/components/custom/FormField/InputFieldComponent/InputFieldComponent.js +6 -3
  16. package/dist/published/components/custom/FormField/Select/Select.js +17 -5
  17. package/dist/published/components/custom/FormField/TimePickerSelect/TimePickerSelect.js +13 -3
  18. package/dist/published/components/custom/FormV2/components/ActionButtons.d.ts +19 -0
  19. package/dist/published/components/custom/FormV2/components/ActionButtons.js +106 -0
  20. package/dist/published/components/custom/FormV2/components/FieldWrapper.d.ts +24 -0
  21. package/dist/published/components/custom/FormV2/components/FieldWrapper.js +100 -0
  22. package/dist/published/components/custom/FormV2/components/FormContext.d.ts +12 -0
  23. package/dist/published/components/custom/FormV2/components/FormContext.js +8 -0
  24. package/dist/published/components/custom/FormV2/components/FormFieldTypes/AddressFields.d.ts +17 -0
  25. package/dist/published/components/custom/FormV2/components/FormFieldTypes/AddressFields.js +50 -0
  26. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/ActionDialog.d.ts +14 -0
  27. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/ActionDialog.js +83 -0
  28. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DocumentViewerCell.d.ts +13 -0
  29. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DocumentViewerCell.js +140 -0
  30. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableField.d.ts +17 -0
  31. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableField.js +233 -0
  32. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableFieldInput.d.ts +40 -0
  33. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableFieldInput.js +95 -0
  34. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/RepeatableField.d.ts +12 -0
  35. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/RepeatableField.js +526 -0
  36. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Criteria.d.ts +12 -0
  37. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Criteria.js +93 -0
  38. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.d.ts +16 -0
  39. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.js +73 -0
  40. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/DocumentList.d.ts +13 -0
  41. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/DocumentList.js +179 -0
  42. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Image.d.ts +12 -0
  43. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Image.js +108 -0
  44. package/dist/published/components/custom/FormV2/components/FormFieldTypes/UserProperty.d.ts +16 -0
  45. package/dist/published/components/custom/FormV2/components/FormFieldTypes/UserProperty.js +125 -0
  46. package/dist/published/components/custom/FormV2/components/TabNav.d.ts +10 -0
  47. package/dist/published/components/custom/FormV2/components/TabNav.js +23 -0
  48. package/dist/published/components/custom/FormV2/components/ValidationFiles/Validation.d.ts +3 -0
  49. package/dist/published/components/custom/FormV2/components/ValidationFiles/Validation.js +176 -0
  50. package/dist/published/components/custom/FormV2/components/ValidationFiles/ValidationErrorDisplay.d.ts +10 -0
  51. package/dist/published/components/custom/FormV2/components/ValidationFiles/ValidationErrorDisplay.js +45 -0
  52. package/dist/published/components/custom/FormV2/components/types.d.ts +26 -0
  53. package/dist/published/components/custom/FormV2/components/types.js +1 -0
  54. package/dist/published/components/custom/FormV2/components/utils.d.ts +35 -0
  55. package/dist/published/components/custom/FormV2/components/utils.js +249 -0
  56. package/dist/published/components/custom/HistoryLog/HistoryData.d.ts +1 -0
  57. package/dist/published/components/custom/HistoryLog/HistoryData.js +14 -6
  58. package/dist/published/components/custom/HistoryLog/HistoryLoading.d.ts +4 -1
  59. package/dist/published/components/custom/HistoryLog/HistoryLoading.js +14 -8
  60. package/dist/published/components/custom/HistoryLog/index.d.ts +2 -0
  61. package/dist/published/components/custom/HistoryLog/index.js +4 -4
  62. package/dist/published/components/custom/ResponsiveOverflow/ResponsiveOverflow.d.ts +33 -0
  63. package/dist/published/components/custom/ResponsiveOverflow/ResponsiveOverflow.js +143 -0
  64. package/dist/published/components/custom/ResponsiveOverflow/ResponsiveOverflow.test.d.ts +1 -0
  65. package/dist/published/components/custom/ResponsiveOverflow/ResponsiveOverflow.test.js +100 -0
  66. package/dist/published/components/custom/ResponsiveOverflow/index.d.ts +4 -0
  67. package/dist/published/components/custom/ResponsiveOverflow/index.js +3 -0
  68. package/dist/published/components/custom/index.d.ts +1 -0
  69. package/dist/published/components/custom/index.js +1 -0
  70. package/dist/published/index.d.ts +1 -1
  71. package/dist/published/index.js +1 -1
  72. package/dist/published/stories/ResponsiveOverflow.stories.d.ts +8 -0
  73. package/dist/published/stories/ResponsiveOverflow.stories.js +91 -0
  74. package/dist/published/theme/hooks.d.ts +7 -0
  75. package/dist/published/theme/hooks.js +9 -0
  76. package/package.json +4 -2
@@ -0,0 +1,176 @@
1
+ import { isArray } from 'lodash';
2
+ import { DateTime } from 'luxon';
3
+ import Handlebars from 'no-eval-handlebars';
4
+ function isNumericValidation(validation) {
5
+ return 'minimum' in validation || 'maximum' in validation;
6
+ }
7
+ function isCalendarValidation(validation) {
8
+ return 'to' in validation || 'from' in validation;
9
+ }
10
+ function isStringValidation(validation) {
11
+ return 'operator' in validation;
12
+ }
13
+ function isDocumentValidation(validation) {
14
+ const documentValidationKeys = ['minDocuments', 'maxDocuments', 'errorMessage'];
15
+ return !validation || Object.keys(validation).every((key) => documentValidationKeys.includes(key));
16
+ }
17
+ export const handleValidation = (entries, register, formValues, parameters, instance) => {
18
+ entries?.forEach((entry) => {
19
+ if (entry.type === 'sections' || entry.type === 'columns') {
20
+ const subEntries = entry.type === 'sections' ? entry.sections : entry.columns;
21
+ subEntries.forEach((subEntry) => {
22
+ if (subEntry.entries) {
23
+ handleValidation(subEntry.entries, register, formValues, parameters, instance);
24
+ }
25
+ });
26
+ return;
27
+ }
28
+ else if (entry.type !== 'input' && entry.type !== 'inputField') {
29
+ return;
30
+ }
31
+ const display = entry?.display;
32
+ const parameter = entry.type === 'input'
33
+ ? parameters?.find((param) => param.id === entry.parameterId)
34
+ : entry.type === 'inputField'
35
+ ? entry.input
36
+ : undefined;
37
+ const validation = parameter?.validation || {};
38
+ const fieldName = display?.label;
39
+ const errorMsg = validation?.errorMessage;
40
+ const validationRules = {};
41
+ // Required fields
42
+ if (entry.type !== 'inputField' && parameter?.required) {
43
+ validationRules.required = `${fieldName} is required`;
44
+ }
45
+ if (parameter?.type === 'boolean' && parameter?.strictlyTrue) {
46
+ validationRules.required = {
47
+ value: true,
48
+ message: display?.booleanDisplay === 'switch'
49
+ ? `${fieldName} must be toggled on`
50
+ : `${fieldName} must be checked`,
51
+ };
52
+ }
53
+ // Min/max char string fields
54
+ if (typeof validation.minLength === 'number') {
55
+ validationRules.minLength = {
56
+ value: validation.minLength,
57
+ message: `${fieldName} must have at least ${validation.minLength} characters`,
58
+ };
59
+ }
60
+ if (typeof validation.maxLength === 'number') {
61
+ validationRules.maxLength = {
62
+ value: validation.maxLength,
63
+ message: `${fieldName} must have no more than ${validation.maxLength} characters`,
64
+ };
65
+ }
66
+ // Min/max number fields
67
+ if (isNumericValidation(validation) && validation.maximum) {
68
+ validationRules.max = {
69
+ value: validation.maximum,
70
+ message: errorMsg || `${fieldName} must have a value under ${validation.maximum}`,
71
+ };
72
+ }
73
+ if (isNumericValidation(validation) && validation.minimum) {
74
+ validationRules.min = {
75
+ value: validation.minimum,
76
+ message: errorMsg || `${fieldName} must have a value over ${validation.minimum}`,
77
+ };
78
+ }
79
+ validationRules.validate = (value) => {
80
+ if (!value)
81
+ return true;
82
+ // Document validation
83
+ if (isDocumentValidation(validation)) {
84
+ const amountOfDocuments = isArray(value) ? value.length : 0;
85
+ const min = validation?.minDocuments;
86
+ const max = validation?.maxDocuments;
87
+ if (max && min && (amountOfDocuments > max || amountOfDocuments < min)) {
88
+ return errorMsg || `Please select between ${min} and ${max} document${max > 1 ? 's' : ''}`;
89
+ }
90
+ else if (min && amountOfDocuments < min) {
91
+ return errorMsg || `Please select at least ${min} document${min > 1 ? 's' : ''}`;
92
+ }
93
+ else if (max && amountOfDocuments > max) {
94
+ return errorMsg || `Please select no more than ${max} document${max > 1 ? 's' : ''}`;
95
+ }
96
+ }
97
+ // Date and Time validation
98
+ if (isCalendarValidation(validation)) {
99
+ const data = {
100
+ __today__: DateTime.now().toISODate(),
101
+ input: formValues,
102
+ };
103
+ if (validation.from) {
104
+ let earliestAllowed = validation.from;
105
+ if (/{{[\w.]+(?:\s+[\w.]+)*(?:\s+\d+)?}}/.test(earliestAllowed)) {
106
+ earliestAllowed = Handlebars.compileAST(earliestAllowed)(data);
107
+ }
108
+ if (earliestAllowed && value < earliestAllowed) {
109
+ return (errorMsg ||
110
+ `${fieldName} must be ${parameter?.type === 'time' ? 'at' : 'on'} or later than ${earliestAllowed || 'a field with no value'}`);
111
+ }
112
+ }
113
+ if (validation.to) {
114
+ let latestAllowed = validation.to;
115
+ if (/{{[\w.]+(?:\s+[\w.]+)*(?:\s+\d+)?}}/.test(latestAllowed)) {
116
+ latestAllowed = Handlebars.compileAST(latestAllowed)(data);
117
+ }
118
+ if (latestAllowed && value > latestAllowed) {
119
+ return (errorMsg ||
120
+ `${fieldName} must be ${parameter?.type === 'time' ? 'at' : 'on'} or before ${latestAllowed || 'a field with no value'}`);
121
+ }
122
+ }
123
+ }
124
+ // Regex validation
125
+ if (isStringValidation(validation) && validation.rules) {
126
+ const rules = validation.rules;
127
+ const failedRules = rules.filter((rule) => {
128
+ const regex = new RegExp(rule.regex);
129
+ return !regex.test(value);
130
+ });
131
+ const operator = validation.operator;
132
+ if (failedRules.length > 0) {
133
+ if (operator === 'all') {
134
+ const messages = failedRules
135
+ .map((rule) => rule.errorMessage || 'Property is not in a valid format')
136
+ .join(' and ');
137
+ return `${fieldName}: ${messages}`;
138
+ }
139
+ if (operator === 'any' && failedRules.length < rules.length) {
140
+ return true; // passes if at least one rule passed
141
+ }
142
+ const messages = failedRules
143
+ .map((rule) => rule.errorMessage || 'Property is not in a valid format')
144
+ .join(' or ');
145
+ return `${fieldName}: ${messages}`;
146
+ }
147
+ }
148
+ // Integer check
149
+ if (parameter?.type === 'integer') {
150
+ if (value && !Number.isInteger(value)) {
151
+ return `${fieldName} must be an integer`;
152
+ }
153
+ }
154
+ // Invalid date check
155
+ if (value?.invalid && value?.dateText) {
156
+ return `Invalid Date`;
157
+ }
158
+ return true;
159
+ };
160
+ register(entry.parameterId || entry.input?.id, validationRules);
161
+ });
162
+ };
163
+ Handlebars.registerHelper('addDays', function (addend1, addend2) {
164
+ const dateAddend1 = DateTime.fromISO(addend1);
165
+ if (dateAddend1.isValid) {
166
+ return dateAddend1.plus({ days: addend2 }).toISODate();
167
+ }
168
+ return undefined;
169
+ });
170
+ Handlebars.registerHelper('subDays', function (minuend, subtrahend) {
171
+ const dateMinuend = DateTime.fromISO(minuend);
172
+ if (dateMinuend.isValid) {
173
+ return dateMinuend.minus({ days: subtrahend }).toISODate();
174
+ }
175
+ return undefined;
176
+ });
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { FieldErrors } from 'react-hook-form';
3
+ export type ValidationErrorDisplayProps = {
4
+ errors: FieldErrors;
5
+ show: boolean;
6
+ formId: string;
7
+ title?: string;
8
+ };
9
+ declare function ValidationErrorDisplay(props: ValidationErrorDisplayProps): React.JSX.Element | null;
10
+ export default ValidationErrorDisplay;
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ import { useResponsive } from '../../../../../theme';
3
+ import { List, ListItem, Typography } from '../../../../core';
4
+ import { Box } from '../../../../layout';
5
+ function ValidationErrorDisplay(props) {
6
+ const { errors, show, formId, title } = props;
7
+ const { isSm, isXs } = useResponsive();
8
+ function extractErrorMessages(errors) {
9
+ const messages = [];
10
+ for (const key in errors) {
11
+ const error = errors[key];
12
+ if (error?.message) {
13
+ messages.push(error.message);
14
+ }
15
+ else if (error) {
16
+ for (const nestedKey in error) {
17
+ const nestedError = error[nestedKey];
18
+ if (nestedError?.message) {
19
+ messages.push(nestedError.message);
20
+ }
21
+ }
22
+ }
23
+ }
24
+ return messages;
25
+ }
26
+ const errorMessages = extractErrorMessages(errors);
27
+ return show && errorMessages.length > 0 ? (React.createElement(Box, { id: `validation-error-display-${formId}`, sx: {
28
+ backgroundColor: '#f8d7da',
29
+ borderColor: '#f5c6cb',
30
+ color: '#721c24',
31
+ border: '1px solid #721c24',
32
+ padding: '8px 24px',
33
+ borderRadius: '4px',
34
+ marginBottom: isSm || isXs ? 2 : 3,
35
+ marginTop: !title ? (isSm || isXs ? -2 : -3) : undefined,
36
+ } },
37
+ React.createElement(Typography, { sx: { color: '#721c24', mt: '16px', mb: '8px' } }, "Please fix the following errors before submitting:"),
38
+ React.createElement(List, { sx: {
39
+ listStyleType: 'disc',
40
+ paddingLeft: '40px',
41
+ mb: '8px',
42
+ fontFamily: 'Arial, Helvetica, sans-serif',
43
+ } }, errorMessages.map((msg, index) => (React.createElement(ListItem, { key: index, sx: { display: 'list-item', p: 0 } }, msg)))))) : null;
44
+ }
45
+ export default ValidationErrorDisplay;
@@ -0,0 +1,26 @@
1
+ export type FieldAddress = {
2
+ line1?: string;
3
+ line2?: string;
4
+ city?: string;
5
+ county?: string;
6
+ state?: string;
7
+ zipCode?: string;
8
+ };
9
+ export type AccessCheck = {
10
+ result: boolean;
11
+ };
12
+ export type SavedDocumentReference = {
13
+ id: string;
14
+ name: string;
15
+ };
16
+ export type Document = {
17
+ id: string;
18
+ name: string;
19
+ contentType: string;
20
+ size: number;
21
+ uploadedDate: string;
22
+ metadata: {
23
+ [field: string]: unknown;
24
+ };
25
+ versionId?: string;
26
+ };
@@ -0,0 +1,35 @@
1
+ import { Columns, FormEntry, InputParameter, Obj, ObjectInstance, Property, Sections } from '@evoke-platform/context';
2
+ import { LocalDateTime } from '@js-joda/core';
3
+ import { FieldValues } from 'react-hook-form';
4
+ import { AutocompleteOption } from '../../../core';
5
+ export declare const scrollIntoViewWithOffset: (el: HTMLElement, offset: number, container?: HTMLElement) => void;
6
+ export declare const normalizeDateTime: (dateTime: LocalDateTime) => string;
7
+ export declare function isAddressProperty(key: string): boolean;
8
+ /**
9
+ * Determine if a form entry is visible or not.
10
+ */
11
+ export declare const entryIsVisible: (entry: FormEntry, formValues: FieldValues, instance?: FieldValues) => boolean;
12
+ /**
13
+ * Recursively retrieves all parameter IDs from a given entry of type Sections or Columns.
14
+ *
15
+ * @param {Sections | Columns} entry - The entry object, which can be of type Sections or Columns.
16
+ * @returns {string[]} - An array of parameter IDs found within the entry.
17
+ */
18
+ export declare const getNestedParameterIds: (entry: Sections | Columns) => string[];
19
+ export declare const getEntryId: (entry: FormEntry) => string | undefined;
20
+ export declare function getPrefixedUrl(url: string): string;
21
+ export declare const isOptionEqualToValue: (option: AutocompleteOption | string, value: unknown) => boolean;
22
+ export declare function addressProperties(addressProperty: Property): Property[];
23
+ export declare const normalizeDates: (instance: ObjectInstance, evokeObject?: Obj) => ObjectInstance;
24
+ export declare const transformToWhere: (mongoQuery: Record<string, unknown>) => Record<string, unknown>;
25
+ export declare const getMiddleObject: (fieldDefinition: InputParameter | Property, endObjectId: string, endObjectName: string, instance?: FieldValues) => {
26
+ [x: string]: {
27
+ id: any;
28
+ name: any;
29
+ };
30
+ } | undefined;
31
+ export declare const getMiddleObjectFilter: (fieldDefinition: InputParameter | Property, instanceId: string) => {
32
+ where: {
33
+ [x: string]: string;
34
+ };
35
+ };
@@ -0,0 +1,249 @@
1
+ import { LocalDateTime } from '@js-joda/core';
2
+ import jsonLogic from 'json-logic-js';
3
+ import { get, isArray, isObject, transform } from 'lodash';
4
+ import { DateTime } from 'luxon';
5
+ export const scrollIntoViewWithOffset = (el, offset, container) => {
6
+ const elementRect = el.getBoundingClientRect();
7
+ const containerRect = container ? container.getBoundingClientRect() : document.body.getBoundingClientRect();
8
+ const topPosition = elementRect.top - containerRect.top + (container?.scrollTop || 0) - offset;
9
+ if (container) {
10
+ container.scrollTo({
11
+ behavior: 'smooth',
12
+ top: topPosition,
13
+ });
14
+ }
15
+ else {
16
+ window.scrollTo({
17
+ behavior: 'smooth',
18
+ top: topPosition,
19
+ });
20
+ }
21
+ };
22
+ export const normalizeDateTime = (dateTime) => new Date(dateTime.toString()).toISOString();
23
+ const evaluateCondition = (condition, formValues, instance) => {
24
+ if (typeof condition !== 'object') {
25
+ console.error('Invalid condition format: ', condition);
26
+ return true;
27
+ }
28
+ if (isArray(condition)) {
29
+ const firstCondition = condition[0];
30
+ const { property, value, operator } = firstCondition;
31
+ let fieldValue = firstCondition.isInstanceProperty ? get(instance, property) : get(formValues, property);
32
+ if (typeof fieldValue === 'object' && fieldValue !== null) {
33
+ if (fieldValue instanceof LocalDateTime) {
34
+ fieldValue = normalizeDateTime(fieldValue);
35
+ }
36
+ else {
37
+ fieldValue = Object.values(fieldValue).includes(value)
38
+ ? value
39
+ : Object.values(fieldValue).find((val) => val !== undefined && val !== null);
40
+ }
41
+ }
42
+ switch (operator) {
43
+ case 'ne':
44
+ return fieldValue != value;
45
+ case 'eq':
46
+ return fieldValue == value;
47
+ default:
48
+ console.error(`Unsupported operator: ${operator}`);
49
+ return false;
50
+ }
51
+ }
52
+ // Handling custom JSON logic
53
+ else {
54
+ const data = {
55
+ data: formValues,
56
+ instance: instance,
57
+ };
58
+ const result = jsonLogic.apply(condition, data);
59
+ return result === true;
60
+ }
61
+ };
62
+ export function isAddressProperty(key) {
63
+ return /\.line1|\.line2|\.city|\.county|\.state|\.zipCode$/.test(key);
64
+ }
65
+ /**
66
+ * Determine if a form entry is visible or not.
67
+ */
68
+ export const entryIsVisible = (entry, formValues, instance) => {
69
+ const display = 'display' in entry ? entry.display : undefined;
70
+ const { visibility } = display ?? ('visibility' in entry ? entry : {});
71
+ if (isObject(visibility) && 'conditions' in visibility && isArray(visibility.conditions)) {
72
+ // visibility is a simple condition
73
+ const { conditions } = visibility;
74
+ return evaluateCondition(conditions, formValues, instance);
75
+ }
76
+ else if (visibility) {
77
+ // visibility is a JSONlogic condition
78
+ return evaluateCondition(visibility, formValues, instance);
79
+ }
80
+ return true;
81
+ };
82
+ /**
83
+ * Recursively retrieves all parameter IDs from a given entry of type Sections or Columns.
84
+ *
85
+ * @param {Sections | Columns} entry - The entry object, which can be of type Sections or Columns.
86
+ * @returns {string[]} - An array of parameter IDs found within the entry.
87
+ */
88
+ export const getNestedParameterIds = (entry) => {
89
+ const parameterIds = [];
90
+ const entries = entry.type === 'columns'
91
+ ? entry.columns.flatMap((column) => column.entries ?? [])
92
+ : entry.sections.flatMap((section) => section.entries ?? []);
93
+ for (const subEntry of entries) {
94
+ if (subEntry.type === 'columns' || subEntry.type === 'sections') {
95
+ parameterIds.push(...getNestedParameterIds(subEntry));
96
+ }
97
+ else {
98
+ const paramId = getEntryId(subEntry);
99
+ if (paramId && paramId !== 'collection') {
100
+ parameterIds.push(paramId);
101
+ }
102
+ }
103
+ }
104
+ return parameterIds;
105
+ };
106
+ export const getEntryId = (entry) => {
107
+ return entry.type === 'input'
108
+ ? entry.parameterId
109
+ : entry.type === 'readonlyField'
110
+ ? entry.propertyId
111
+ : entry.type === 'inputField'
112
+ ? entry.input.id
113
+ : undefined;
114
+ };
115
+ export function getPrefixedUrl(url) {
116
+ const wcsMatchers = ['/apps', '/pages', '/widgets'];
117
+ const dataMatchers = ['/objects', '/correspondenceTemplates', '/documents', '/payments', '/locations'];
118
+ const signalrMatchers = ['/hubs'];
119
+ const accessManagementMatchers = ['/users'];
120
+ const workflowMatchers = ['/workflows'];
121
+ if (wcsMatchers.some((endpoint) => url.startsWith(endpoint)))
122
+ return `/webContent${url}`;
123
+ if (dataMatchers.some((endpoint) => url.startsWith(endpoint)))
124
+ return `/data${url}`;
125
+ if (signalrMatchers.some((endpoint) => url.startsWith(endpoint)))
126
+ return `/signalr${url}`;
127
+ if (accessManagementMatchers.some((endpoint) => url.startsWith(endpoint)))
128
+ return `/accessManagement${url}`;
129
+ if (workflowMatchers.some((endpoint) => url.startsWith(endpoint)))
130
+ return `/workflow${url}`;
131
+ console.error('Invalid URL');
132
+ return url;
133
+ }
134
+ export const isOptionEqualToValue = (option, value) => {
135
+ if (typeof option === 'string') {
136
+ return option === value;
137
+ }
138
+ return option.value === value;
139
+ };
140
+ export function addressProperties(addressProperty) {
141
+ return [
142
+ {
143
+ id: `${addressProperty.id}.line1`,
144
+ name: `${addressProperty.name} Line 1`,
145
+ type: 'string',
146
+ },
147
+ {
148
+ id: `${addressProperty.id}.line2`,
149
+ name: `${addressProperty.name} Line 2`,
150
+ type: 'string',
151
+ },
152
+ {
153
+ id: `${addressProperty.id}.city`,
154
+ name: `${addressProperty.name} City`,
155
+ type: 'string',
156
+ },
157
+ {
158
+ id: `${addressProperty.id}.county`,
159
+ name: `${addressProperty.name} County`,
160
+ type: 'string',
161
+ },
162
+ {
163
+ id: `${addressProperty.id}.state`,
164
+ name: `${addressProperty.name} State`,
165
+ type: 'string',
166
+ },
167
+ {
168
+ id: `${addressProperty.id}.zipCode`,
169
+ name: `${addressProperty.name} Zip Code`,
170
+ type: 'string',
171
+ },
172
+ ];
173
+ }
174
+ export const normalizeDates = (instance, evokeObject) => {
175
+ const dateProps = ['date', 'date-time', 'time'];
176
+ const properties = evokeObject?.properties
177
+ ?.filter((property) => dateProps.includes(property.type))
178
+ .reduce((agg, property) => Object.assign(agg, { [property.id]: property.type }), {}) ?? {};
179
+ const propKeys = Object.keys(properties);
180
+ const updatedInstance = { ...instance };
181
+ Object.keys(instance).forEach((key) => {
182
+ // Ignore non-datelike and empty fields.
183
+ if (!propKeys.includes(key) || !instance[key]) {
184
+ return;
185
+ }
186
+ switch (properties[key]) {
187
+ case 'date':
188
+ // Casting here is valid because the value has already been
189
+ // determined to be a datelike field that is non-empty.
190
+ updatedInstance[key] = DateTime.fromISO(instance[key]).toLocaleString(DateTime.DATE_SHORT);
191
+ break;
192
+ case 'date-time':
193
+ // Casting here is valid because the value has already been
194
+ // determined to be a datelike field that is non-empty.
195
+ updatedInstance[key] = DateTime.fromISO(instance[key]).toLocaleString(DateTime.DATETIME_SHORT);
196
+ break;
197
+ case 'time':
198
+ // Casting here is valid because the value has already been
199
+ // determined to be a datelike field that is non-empty.
200
+ updatedInstance[key] = DateTime.fromISO(instance[key]).toLocaleString(DateTime.TIME_SIMPLE);
201
+ break;
202
+ }
203
+ });
204
+ return updatedInstance;
205
+ };
206
+ const OPERATOR_MAP = {
207
+ $and: 'and',
208
+ $or: 'or',
209
+ $eq: 'eq',
210
+ $ne: 'neq',
211
+ $lt: 'lt',
212
+ $lte: 'lte',
213
+ $gt: 'gt',
214
+ $gte: 'gte',
215
+ $in: 'inq',
216
+ $nin: 'nin',
217
+ $regex: 'regexp',
218
+ $exists: 'exists',
219
+ $not: 'not',
220
+ };
221
+ export const transformToWhere = (mongoQuery) => {
222
+ return transform(mongoQuery, (result, value, key) => {
223
+ const newKey = typeof key === 'string' && key.startsWith('$') ? OPERATOR_MAP[key] : key;
224
+ if (newKey === undefined) {
225
+ throw new Error(`Unsupported operator ${key}`);
226
+ }
227
+ result[newKey] = isObject(value) ? transformToWhere(value) : value;
228
+ });
229
+ };
230
+ export const getMiddleObject = (fieldDefinition, endObjectId, endObjectName, instance) => {
231
+ if (fieldDefinition.relatedPropertyId && fieldDefinition.manyToManyPropertyId) {
232
+ const middleObject = {
233
+ [fieldDefinition.relatedPropertyId]: {
234
+ id: instance?.id,
235
+ name: instance?.name,
236
+ },
237
+ [fieldDefinition.manyToManyPropertyId]: {
238
+ id: endObjectId,
239
+ name: endObjectName,
240
+ },
241
+ };
242
+ return middleObject;
243
+ }
244
+ };
245
+ export const getMiddleObjectFilter = (fieldDefinition, instanceId) => {
246
+ const filterProperty = `${fieldDefinition.relatedPropertyId}.id`;
247
+ const filter = { where: { [filterProperty]: instanceId } };
248
+ return filter;
249
+ };
@@ -7,6 +7,7 @@ type HistoryDataProps = {
7
7
  documentHistory?: Record<string, History[]>;
8
8
  object: Obj;
9
9
  referencedObjects?: Obj[];
10
+ hideTimeline?: boolean;
10
11
  };
11
12
  declare const HistoricalData: (props: HistoryDataProps) => React.JSX.Element;
12
13
  export default HistoricalData;
@@ -19,8 +19,7 @@ const styles = {
19
19
  color: '#637381',
20
20
  },
21
21
  timelineConnector: {
22
- padding: '1px 0px 24px 22px',
23
- borderLeft: '2px rgba(145, 158, 171, 0.24) solid',
22
+ padding: '1px 0px 24px 0px',
24
23
  marginLeft: '5px',
25
24
  },
26
25
  historyData: {
@@ -30,15 +29,24 @@ const styles = {
30
29
  },
31
30
  };
32
31
  const HistoricalData = (props) => {
33
- const { records, documentHistory, object, referencedObjects } = props;
32
+ const { records, documentHistory, object, referencedObjects, hideTimeline } = props;
34
33
  const getPastDocumentVersion = (history) => {
35
34
  const documentVersions = documentHistory?.[history.subject?.id ?? 'unknown'] ?? [];
36
35
  const currentVersion = documentVersions?.map((v) => v.timestamp).indexOf(history.timestamp);
37
36
  return currentVersion ? documentVersions[currentVersion - 1] : undefined;
38
37
  };
39
- return (React.createElement(Box, { sx: styles.timelineConnector }, records.map((r) => (React.createElement(Box, { margin: '16px 0px', key: `${r.timestamp}-${nanoid()}` },
40
- React.createElement(Box, { sx: { display: 'flex', justifyContent: 'space-between' } },
41
- React.createElement(Box, { sx: { display: 'flex', maxWidth: '60%', alignContent: 'flex-start' } },
38
+ return (React.createElement(Box, { sx: {
39
+ ...styles.timelineConnector,
40
+ borderLeft: !hideTimeline ? '2px rgba(145, 158, 171, 0.24) solid' : undefined,
41
+ } }, records.map((r) => (React.createElement(Box, { margin: '16px 0px', key: `${r.timestamp}-${nanoid()}` },
42
+ React.createElement(Box, { sx: {
43
+ display: 'flex',
44
+ justifyContent: 'space-between',
45
+ flexDirection: { xs: 'column', sm: 'row' },
46
+ alignItems: { xs: 'flex-start', sm: 'center' },
47
+ gap: 0,
48
+ } },
49
+ React.createElement(Box, { sx: { display: 'flex', maxWidth: { sx: '100%', sm: '60%' }, alignContent: 'flex-start' } },
42
50
  React.createElement(Typography, { sx: { fontSize: '12px', color: '#637381' } },
43
51
  React.createElement(Typography, { component: 'span', sx: { fontWeight: 600, fontSize: '12px' } }, r.user.name ?? 'Unknown User'),
44
52
  "\u00A0",
@@ -1,3 +1,6 @@
1
1
  import React from 'react';
2
- declare const HistoryLoading: () => React.JSX.Element;
2
+ type HistoryLoadingProps = {
3
+ hideTimeline?: boolean;
4
+ };
5
+ declare const HistoryLoading: (props: HistoryLoadingProps) => React.JSX.Element;
3
6
  export default HistoryLoading;
@@ -1,11 +1,10 @@
1
+ import { Circle } from '@mui/icons-material';
1
2
  import React from 'react';
2
- import { Box } from '../../layout';
3
3
  import { Skeleton } from '../../core';
4
- import { Circle } from '@mui/icons-material';
4
+ import { Box } from '../../layout';
5
5
  const styles = {
6
6
  timelineConnector: {
7
7
  padding: '1px 0px 5px 22px',
8
- borderLeft: '2px rgba(145, 158, 171, 0.24) solid',
9
8
  marginLeft: '5px',
10
9
  },
11
10
  headerSkeleton: {
@@ -18,20 +17,27 @@ const styles = {
18
17
  borderRadius: '7px',
19
18
  },
20
19
  };
21
- const HistoryLoading = () => {
20
+ const HistoryLoading = (props) => {
21
+ const { hideTimeline } = props;
22
22
  return (React.createElement(React.Fragment, { key: 'history-log-loading' },
23
23
  React.createElement(Box, { sx: { display: 'flex', alignItems: 'center' } },
24
- React.createElement(Circle, { color: "primary", sx: { fontSize: '12px', marginRight: '12px' } }),
24
+ !hideTimeline && React.createElement(Circle, { color: "primary", sx: { fontSize: '12px', marginRight: '12px' } }),
25
25
  React.createElement(Skeleton, { variant: "text", sx: styles.headerSkeleton })),
26
- React.createElement(Box, { sx: styles.timelineConnector },
26
+ React.createElement(Box, { sx: {
27
+ ...styles.timelineConnector,
28
+ borderLeft: !hideTimeline ? '2px rgba(145, 158, 171, 0.24) solid' : undefined,
29
+ } },
27
30
  React.createElement(Box, { margin: '4px 0px 24px 0px' },
28
31
  React.createElement(Skeleton, { variant: "text", sx: { ...styles.dataSkeleton, width: '120px' } }),
29
32
  React.createElement(Skeleton, { variant: "text", sx: { ...styles.dataSkeleton, width: '65%' } }),
30
33
  React.createElement(Skeleton, { variant: "text", sx: { ...styles.dataSkeleton, width: '75%' } }))),
31
34
  React.createElement(Box, { sx: { display: 'flex', alignItems: 'center' } },
32
- React.createElement(Circle, { color: "primary", sx: { fontSize: '12px', marginRight: '12px' } }),
35
+ !hideTimeline && React.createElement(Circle, { color: "primary", sx: { fontSize: '12px', marginRight: '12px' } }),
33
36
  React.createElement(Skeleton, { variant: "text", sx: styles.headerSkeleton })),
34
- React.createElement(Box, { sx: styles.timelineConnector },
37
+ React.createElement(Box, { sx: {
38
+ ...styles.timelineConnector,
39
+ borderLeft: !hideTimeline ? '2px rgba(145, 158, 171, 0.24) solid' : undefined,
40
+ } },
35
41
  React.createElement(Box, { margin: '4px 0px 20px 0px' },
36
42
  React.createElement(Skeleton, { variant: "text", sx: { ...styles.dataSkeleton, width: '120px' } }),
37
43
  React.createElement(Skeleton, { variant: "text", sx: { ...styles.dataSkeleton, width: '55%' } })))));
@@ -10,6 +10,8 @@ export type HistoryLogProps = {
10
10
  loading?: boolean;
11
11
  /** The title displayed above the timeline */
12
12
  title?: string;
13
+ /** Whether to hide the timeline in the history log */
14
+ hideTimeline?: boolean;
13
15
  };
14
16
  /**
15
17
  * Renders a timeline of the instance's history log.