@evoke-platform/ui-components 1.0.0-dev.219 → 1.0.0-dev.221
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.d.ts +1 -0
- package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.js +23 -9
- package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.test.d.ts +1 -0
- package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.test.js +53 -0
- package/dist/published/components/custom/Form/Common/Form.d.ts +4 -3
- package/dist/published/components/custom/Form/Common/Form.js +1 -1
- package/dist/published/components/custom/Form/FormComponents/FormFieldComponent.js +2 -2
- package/dist/published/stories/CriteriaBuilder.stories.d.ts +1 -0
- package/dist/published/stories/CriteriaBuilder.stories.js +17 -0
- package/package.json +5 -1
@@ -22,6 +22,7 @@ export declare type CriteriaInputProps = {
|
|
22
22
|
disabled?: boolean;
|
23
23
|
hideBorder?: boolean;
|
24
24
|
presetGroupLabel?: string;
|
25
|
+
freeSolo?: boolean;
|
25
26
|
};
|
26
27
|
export declare const valueEditor: (props: ValueEditorProps) => JSX.Element;
|
27
28
|
declare const CriteriaBuilder: (props: CriteriaInputProps) => JSX.Element;
|
@@ -77,8 +77,9 @@ const customSelector = (props) => {
|
|
77
77
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
78
78
|
const rule = props.rule;
|
79
79
|
let width = '90px';
|
80
|
-
let
|
80
|
+
let displayedValue = value;
|
81
81
|
let opts = options;
|
82
|
+
const isFreeSoloEnabled = context.freeSolo && title === 'Fields';
|
82
83
|
let readOnly = false;
|
83
84
|
if (context.disabledCriteria) {
|
84
85
|
readOnly =
|
@@ -95,24 +96,32 @@ const customSelector = (props) => {
|
|
95
96
|
opts = options
|
96
97
|
.filter((option) => ['null', 'notNull', 'in', 'notIn'].includes(option.name))
|
97
98
|
.map((option) => ({ name: option.name, label: option.label }));
|
98
|
-
|
99
|
+
displayedValue =
|
100
|
+
value === '='
|
101
|
+
? ''
|
102
|
+
: options.find((option) => option.name === displayedValue).name;
|
99
103
|
}
|
100
104
|
else if (((_b = props.fieldData) === null || _b === void 0 ? void 0 : _b.inputType) === 'document') {
|
101
105
|
opts = options
|
102
106
|
.filter((option) => ['null', 'notNull'].includes(option.name))
|
103
107
|
.map((option) => ({ name: option.name, label: option.label }));
|
104
|
-
|
108
|
+
displayedValue =
|
109
|
+
value === '='
|
110
|
+
? ''
|
111
|
+
: options.find((option) => option.name === displayedValue).name;
|
105
112
|
}
|
106
113
|
break;
|
107
114
|
case 'Fields':
|
108
115
|
width = '33%';
|
109
|
-
|
116
|
+
displayedValue = (_c = options.find((option) => option.name === displayedValue)) === null || _c === void 0 ? void 0 : _c.label;
|
117
|
+
if (isFreeSoloEnabled && !displayedValue) {
|
118
|
+
displayedValue = value;
|
119
|
+
}
|
110
120
|
break;
|
111
121
|
}
|
112
|
-
return (React.createElement(Autocomplete, { options: opts, value:
|
113
|
-
var _a;
|
122
|
+
return (React.createElement(Autocomplete, { options: opts, value: displayedValue !== null && displayedValue !== void 0 ? displayedValue : null, getOptionLabel: (option) => {
|
114
123
|
if (typeof option === 'string') {
|
115
|
-
return
|
124
|
+
return option;
|
116
125
|
}
|
117
126
|
return option.label;
|
118
127
|
}, isOptionEqualToValue: (option, value) => {
|
@@ -121,7 +130,11 @@ const customSelector = (props) => {
|
|
121
130
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
122
131
|
onChange: (event, newValue) => {
|
123
132
|
handleOnChange(newValue === null || newValue === void 0 ? void 0 : newValue.value.name);
|
124
|
-
},
|
133
|
+
}, onInputChange: (event, value) => {
|
134
|
+
if (isFreeSoloEnabled) {
|
135
|
+
handleOnChange(value);
|
136
|
+
}
|
137
|
+
}, renderInput: (params) => React.createElement(TextField, Object.assign({}, params, { size: "small", name: title })), sx: { width: width, maxWidth: title === 'Operators' ? '200px' : 'none' }, disableClearable: true, readOnly: readOnly }));
|
125
138
|
};
|
126
139
|
const customCombinator = (props) => {
|
127
140
|
const { options, value, handleOnChange, context, level } = props;
|
@@ -169,7 +182,7 @@ export const valueEditor = (props) => {
|
|
169
182
|
return ValueEditor(props);
|
170
183
|
};
|
171
184
|
const CriteriaBuilder = (props) => {
|
172
|
-
const { properties, criteria, setCriteria, originalCriteria, enablePresetValues, presetValues, operators, dynamicContentInput, disabled, disabledCriteria, hideBorder, presetGroupLabel, } = props;
|
185
|
+
const { properties, criteria, setCriteria, originalCriteria, enablePresetValues, presetValues, operators, dynamicContentInput, disabled, disabledCriteria, hideBorder, presetGroupLabel, freeSolo, } = props;
|
173
186
|
const [query, setQuery] = useState(undefined);
|
174
187
|
useEffect(() => {
|
175
188
|
if (criteria || originalCriteria) {
|
@@ -261,6 +274,7 @@ const CriteriaBuilder = (props) => {
|
|
261
274
|
enablePresetValues,
|
262
275
|
presetGroupLabel,
|
263
276
|
disabledCriteria,
|
277
|
+
freeSolo,
|
264
278
|
}, controlClassnames: {
|
265
279
|
queryBuilder: 'queryBuilder-branches',
|
266
280
|
ruleGroup: 'container',
|
@@ -0,0 +1 @@
|
|
1
|
+
import '@testing-library/jest-dom/extend-expect';
|
@@ -0,0 +1,53 @@
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
8
|
+
});
|
9
|
+
};
|
10
|
+
import React from 'react';
|
11
|
+
import { render, screen } from '@testing-library/react';
|
12
|
+
import userEvent from '@testing-library/user-event';
|
13
|
+
import '@testing-library/jest-dom/extend-expect';
|
14
|
+
import CriteriaBuilder from './CriteriaBuilder';
|
15
|
+
const mockProperties = [
|
16
|
+
{ id: 'name', name: 'name', type: 'string', required: true },
|
17
|
+
{ id: 'licenseNumber', name: 'license number', type: 'string', required: true },
|
18
|
+
{ id: 'issueDate', name: 'issue date', type: 'date', required: false },
|
19
|
+
];
|
20
|
+
describe('CriteriaBuilder', () => {
|
21
|
+
test('allows selection of a property and clears value input when selected', () => __awaiter(void 0, void 0, void 0, function* () {
|
22
|
+
const user = userEvent.setup();
|
23
|
+
render(React.createElement(CriteriaBuilder, { properties: mockProperties, criteria: {
|
24
|
+
$or: [
|
25
|
+
{
|
26
|
+
name: 'test value',
|
27
|
+
},
|
28
|
+
],
|
29
|
+
}, setCriteria: jest.fn(), freeSolo: true }));
|
30
|
+
const field = yield screen.findByDisplayValue(/name/);
|
31
|
+
const value = yield screen.findByDisplayValue(/test value/);
|
32
|
+
yield user.click(field);
|
33
|
+
const option = yield screen.findByRole('option', { name: /license number/ });
|
34
|
+
yield user.click(option);
|
35
|
+
expect(field).toHaveValue('license number');
|
36
|
+
expect(value).toHaveValue('');
|
37
|
+
}));
|
38
|
+
test('allows free solo input when freeSolo is true, clears value input when entered', () => __awaiter(void 0, void 0, void 0, function* () {
|
39
|
+
const user = userEvent.setup();
|
40
|
+
render(React.createElement(CriteriaBuilder, { properties: mockProperties, criteria: {
|
41
|
+
$or: [
|
42
|
+
{
|
43
|
+
name: 'test value',
|
44
|
+
},
|
45
|
+
],
|
46
|
+
}, setCriteria: jest.fn(), freeSolo: true }));
|
47
|
+
const field = yield screen.findByDisplayValue(/name/);
|
48
|
+
const value = yield screen.findByDisplayValue(/test value/);
|
49
|
+
yield user.type(field, 'person.license.name');
|
50
|
+
expect(field).toHaveValue('person.license.name');
|
51
|
+
expect(value).toHaveValue('');
|
52
|
+
}));
|
53
|
+
});
|
@@ -1,7 +1,8 @@
|
|
1
|
+
/// <reference types="react" />
|
1
2
|
import { ApiServices, Obj, ObjectInstance, UserAccount } from '@evoke-platform/context';
|
2
|
-
import {
|
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?:
|
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 {
|
@@ -4,5 +4,6 @@ import { CriteriaInputProps } from '../components/custom/CriteriaBuilder/Criteri
|
|
4
4
|
declare const _default: ComponentMeta<(props: CriteriaInputProps) => JSX.Element>;
|
5
5
|
export default _default;
|
6
6
|
export declare const CriteriaBuilder: ComponentStory<(props: CriteriaInputProps) => JSX.Element>;
|
7
|
+
export declare const FreeSolo: ComponentStory<(props: CriteriaInputProps) => JSX.Element>;
|
7
8
|
export declare const CriteriaBuilderPresetUserID: ComponentStory<(props: CriteriaInputProps) => JSX.Element>;
|
8
9
|
export declare const CriteriaBuilderGroupedPresetValues: ComponentStory<(props: CriteriaInputProps) => JSX.Element>;
|
@@ -109,6 +109,23 @@ CriteriaBuilder.args = {
|
|
109
109
|
},
|
110
110
|
enablePresetValues: false,
|
111
111
|
};
|
112
|
+
export const FreeSolo = CriteriaBuilderTemplate.bind({});
|
113
|
+
FreeSolo.args = Object.assign(Object.assign({}, CriteriaBuilder.args), { criteria: {
|
114
|
+
$or: [
|
115
|
+
{
|
116
|
+
'person.license.name': 'bert',
|
117
|
+
},
|
118
|
+
{
|
119
|
+
licensedFor: { $in: ['hot dogs', 'amusements', 'entertainment'] },
|
120
|
+
},
|
121
|
+
{
|
122
|
+
licenseNumber: '123456',
|
123
|
+
},
|
124
|
+
{
|
125
|
+
issueDate: '2023-03-16',
|
126
|
+
},
|
127
|
+
],
|
128
|
+
}, freeSolo: true });
|
112
129
|
export const CriteriaBuilderPresetUserID = CriteriaBuilderTemplate.bind({});
|
113
130
|
CriteriaBuilderPresetUserID.args = {
|
114
131
|
properties: [
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@evoke-platform/ui-components",
|
3
|
-
"version": "1.0.0-dev.
|
3
|
+
"version": "1.0.0-dev.221",
|
4
4
|
"description": "",
|
5
5
|
"main": "dist/published/index.js",
|
6
6
|
"module": "dist/published/index.js",
|
@@ -72,6 +72,7 @@
|
|
72
72
|
"eslint-plugin-prettier": "^5.1.2",
|
73
73
|
"eslint-plugin-testing-library": "^6.2.0",
|
74
74
|
"husky": "^8.0.3",
|
75
|
+
"identity-obj-proxy": "^3.0.0",
|
75
76
|
"is-ci": "^3.0.1",
|
76
77
|
"jest": "^28.1.2",
|
77
78
|
"jest-environment-jsdom": "^28.1.2",
|
@@ -143,6 +144,9 @@
|
|
143
144
|
"jest": {
|
144
145
|
"verbose": true,
|
145
146
|
"testEnvironment": "jsdom",
|
147
|
+
"moduleNameMapper": {
|
148
|
+
"\\.(css|less|scss|sass)$": "identity-obj-proxy"
|
149
|
+
},
|
146
150
|
"testPathIgnorePatterns": [
|
147
151
|
"/node_modules/",
|
148
152
|
"<rootDir>/dist/"
|