@pega/cosmos-react-condition-builder 2.0.0-dev.2.1 → 2.0.0-dev.20.0

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 (89) hide show
  1. package/lib/components/ConditionBuilder/AtomicCondition.d.ts +11 -4
  2. package/lib/components/ConditionBuilder/AtomicCondition.d.ts.map +1 -1
  3. package/lib/components/ConditionBuilder/AtomicCondition.js +22 -24
  4. package/lib/components/ConditionBuilder/AtomicCondition.js.map +1 -1
  5. package/lib/components/ConditionBuilder/ConditionBuilder.d.ts.map +1 -1
  6. package/lib/components/ConditionBuilder/ConditionBuilder.js +23 -44
  7. package/lib/components/ConditionBuilder/ConditionBuilder.js.map +1 -1
  8. package/lib/components/ConditionBuilder/ConditionBuilder.types.d.ts +42 -2
  9. package/lib/components/ConditionBuilder/ConditionBuilder.types.d.ts.map +1 -1
  10. package/lib/components/ConditionBuilder/ConditionBuilder.types.js.map +1 -1
  11. package/lib/components/ConditionBuilder/FieldCondition.d.ts.map +1 -1
  12. package/lib/components/ConditionBuilder/FieldCondition.js +6 -9
  13. package/lib/components/ConditionBuilder/FieldCondition.js.map +1 -1
  14. package/lib/components/ConditionBuilder/FieldCondition.types.d.ts +10 -2
  15. package/lib/components/ConditionBuilder/FieldCondition.types.d.ts.map +1 -1
  16. package/lib/components/ConditionBuilder/FieldCondition.types.js.map +1 -1
  17. package/lib/components/ConditionBuilder/HelpButton.d.ts.map +1 -1
  18. package/lib/components/ConditionBuilder/HelpButton.js +2 -4
  19. package/lib/components/ConditionBuilder/HelpButton.js.map +1 -1
  20. package/lib/components/ConditionBuilder/RhsControls/DateFunctionMenu.d.ts +18 -0
  21. package/lib/components/ConditionBuilder/RhsControls/DateFunctionMenu.d.ts.map +1 -0
  22. package/lib/components/ConditionBuilder/RhsControls/DateFunctionMenu.js +115 -0
  23. package/lib/components/ConditionBuilder/RhsControls/DateFunctionMenu.js.map +1 -0
  24. package/lib/components/ConditionBuilder/{FieldSelector.d.ts → RhsControls/FieldSelector.d.ts} +1 -1
  25. package/lib/components/ConditionBuilder/RhsControls/FieldSelector.d.ts.map +1 -0
  26. package/lib/components/ConditionBuilder/{FieldSelector.js → RhsControls/FieldSelector.js} +5 -5
  27. package/lib/components/ConditionBuilder/RhsControls/FieldSelector.js.map +1 -0
  28. package/lib/components/ConditionBuilder/{MultiValueSelector.d.ts → RhsControls/MultiValueSelector.d.ts} +1 -1
  29. package/lib/components/ConditionBuilder/RhsControls/MultiValueSelector.d.ts.map +1 -0
  30. package/lib/components/ConditionBuilder/RhsControls/MultiValueSelector.js +43 -0
  31. package/lib/components/ConditionBuilder/RhsControls/MultiValueSelector.js.map +1 -0
  32. package/lib/components/ConditionBuilder/RhsControls/NumericInput.d.ts +18 -0
  33. package/lib/components/ConditionBuilder/RhsControls/NumericInput.d.ts.map +1 -0
  34. package/lib/components/ConditionBuilder/RhsControls/NumericInput.js +19 -0
  35. package/lib/components/ConditionBuilder/RhsControls/NumericInput.js.map +1 -0
  36. package/lib/components/ConditionBuilder/RhsControls/RelativeDateMenu.d.ts +18 -0
  37. package/lib/components/ConditionBuilder/RhsControls/RelativeDateMenu.d.ts.map +1 -0
  38. package/lib/components/ConditionBuilder/RhsControls/RelativeDateMenu.js +109 -0
  39. package/lib/components/ConditionBuilder/RhsControls/RelativeDateMenu.js.map +1 -0
  40. package/lib/components/ConditionBuilder/RhsControls/RhsModeSwitch.d.ts +24 -0
  41. package/lib/components/ConditionBuilder/RhsControls/RhsModeSwitch.d.ts.map +1 -0
  42. package/lib/components/ConditionBuilder/RhsControls/RhsModeSwitch.js +122 -0
  43. package/lib/components/ConditionBuilder/RhsControls/RhsModeSwitch.js.map +1 -0
  44. package/lib/components/ConditionBuilder/RhsControls/TimePeriodInput.d.ts +8 -0
  45. package/lib/components/ConditionBuilder/RhsControls/TimePeriodInput.d.ts.map +1 -0
  46. package/lib/components/ConditionBuilder/RhsControls/TimePeriodInput.js +89 -0
  47. package/lib/components/ConditionBuilder/RhsControls/TimePeriodInput.js.map +1 -0
  48. package/lib/components/ConditionBuilder/RhsControls/TimePeriodMenu.d.ts +20 -0
  49. package/lib/components/ConditionBuilder/RhsControls/TimePeriodMenu.d.ts.map +1 -0
  50. package/lib/components/ConditionBuilder/RhsControls/TimePeriodMenu.js +11 -0
  51. package/lib/components/ConditionBuilder/RhsControls/TimePeriodMenu.js.map +1 -0
  52. package/lib/components/ConditionBuilder/{RhsControls.d.ts → RhsControls/index.d.ts} +16 -6
  53. package/lib/components/ConditionBuilder/RhsControls/index.d.ts.map +1 -0
  54. package/lib/components/ConditionBuilder/RhsControls/index.js +219 -0
  55. package/lib/components/ConditionBuilder/RhsControls/index.js.map +1 -0
  56. package/lib/components/ConditionBuilder/core/evaluator.d.ts.map +1 -1
  57. package/lib/components/ConditionBuilder/core/evaluator.js +110 -9
  58. package/lib/components/ConditionBuilder/core/evaluator.js.map +1 -1
  59. package/lib/components/ConditionBuilder/core/extendDayJs.d.ts +2 -0
  60. package/lib/components/ConditionBuilder/core/extendDayJs.d.ts.map +1 -0
  61. package/lib/components/ConditionBuilder/core/extendDayJs.js +4 -0
  62. package/lib/components/ConditionBuilder/core/extendDayJs.js.map +1 -0
  63. package/lib/components/ConditionBuilder/core/formatter.d.ts +10 -1
  64. package/lib/components/ConditionBuilder/core/formatter.d.ts.map +1 -1
  65. package/lib/components/ConditionBuilder/core/formatter.js +95 -13
  66. package/lib/components/ConditionBuilder/core/formatter.js.map +1 -1
  67. package/lib/components/ConditionBuilder/core/transformer.d.ts +7 -0
  68. package/lib/components/ConditionBuilder/core/transformer.d.ts.map +1 -0
  69. package/lib/components/ConditionBuilder/core/transformer.js +164 -0
  70. package/lib/components/ConditionBuilder/core/transformer.js.map +1 -0
  71. package/lib/components/ConditionBuilder/core/types.d.ts +7 -1
  72. package/lib/components/ConditionBuilder/core/types.d.ts.map +1 -1
  73. package/lib/components/ConditionBuilder/core/types.js.map +1 -1
  74. package/lib/components/ConditionBuilder/core/utils.d.ts.map +1 -1
  75. package/lib/components/ConditionBuilder/core/utils.js +4 -8
  76. package/lib/components/ConditionBuilder/core/utils.js.map +1 -1
  77. package/lib/components/ConditionBuilder/index.d.ts +2 -1
  78. package/lib/components/ConditionBuilder/index.d.ts.map +1 -1
  79. package/lib/components/ConditionBuilder/index.js +2 -1
  80. package/lib/components/ConditionBuilder/index.js.map +1 -1
  81. package/package.json +17 -15
  82. package/lib/components/ConditionBuilder/FieldSelector.d.ts.map +0 -1
  83. package/lib/components/ConditionBuilder/FieldSelector.js.map +0 -1
  84. package/lib/components/ConditionBuilder/MultiValueSelector.d.ts.map +0 -1
  85. package/lib/components/ConditionBuilder/MultiValueSelector.js +0 -77
  86. package/lib/components/ConditionBuilder/MultiValueSelector.js.map +0 -1
  87. package/lib/components/ConditionBuilder/RhsControls.d.ts.map +0 -1
  88. package/lib/components/ConditionBuilder/RhsControls.js +0 -277
  89. package/lib/components/ConditionBuilder/RhsControls.js.map +0 -1
@@ -1,277 +0,0 @@
1
- import React, { useState, useEffect, useMemo } from 'react';
2
- import { DateInput, DateTimeInput, Flex, Input, MenuButton, Select, Option, hasProp } from '@pega/cosmos-react-core';
3
- import MultiValueSelector from './MultiValueSelector';
4
- import FieldSelector from './FieldSelector';
5
- import { convertTimeValueToMs, convertMsToTimeValue } from './core/time-utils';
6
- /** Verifies if the condition has all valid values */
7
- export function isValidRhs(rhs, fieldType, trimValues = false, validRhsTypes) {
8
- // RHS would be `undefined` when no RHS is needed. Treat it as a valid value
9
- if (rhs === undefined) {
10
- return true;
11
- }
12
- // Field-selector on the RHS
13
- if (hasProp(rhs, 'field') && !validRhsTypes.has('FIELD')) {
14
- return false;
15
- }
16
- if (hasProp(rhs, 'field')) {
17
- // RHS is invalid if no field is selected
18
- return rhs.field !== '';
19
- }
20
- // List-input cases
21
- if (hasProp(rhs, 'values') && !validRhsTypes.has('LITERAL')) {
22
- return false;
23
- }
24
- if (hasProp(rhs, 'values')) {
25
- // RHS is invalid if the list is empty
26
- if (rhs.values.length === 0) {
27
- return false;
28
- }
29
- // For numeric fields, RHS is invalid if any NaN values are present in the list
30
- if (fieldType === 'NUMBER') {
31
- if (rhs.values.some(v => Number.isNaN(v))) {
32
- return false;
33
- }
34
- }
35
- }
36
- if (hasProp(rhs, 'value') && !validRhsTypes.has('LITERAL')) {
37
- return false;
38
- }
39
- if (hasProp(rhs, 'value')) {
40
- // Identify any invalid numbers (not expected)
41
- if (typeof rhs.value === 'number') {
42
- return !Number.isNaN(rhs.value);
43
- }
44
- // NOTE: Not trimming the value in the change-handler so that users can freely type spaces between words
45
- if (trimValues) {
46
- rhs.value = rhs.value.trim();
47
- }
48
- // Can be empty on init and on clearing the value
49
- if (rhs.value.trim() === '') {
50
- return false;
51
- }
52
- // This check is needed to eliminate invalid dates like `Feb 31` (02/31/2020), which the input allows
53
- if (fieldType === 'DATE_TIME' || fieldType === 'DATE_ONLY') {
54
- if (Number.isNaN(new Date(rhs.value).getTime())) {
55
- return false;
56
- }
57
- }
58
- }
59
- return true;
60
- }
61
- /** For a condition with the given comparator and lhs-field-type, determines an appropriate default value for the Rhs */
62
- export function getDefaultRhs(fieldType, comparator, validRhsTypes) {
63
- switch (comparator) {
64
- case 'IS_TRUE':
65
- case 'IS_FALSE':
66
- case 'IS_NULL':
67
- case 'IS_NOT_NULL':
68
- return undefined; // These comparators do not have an Rhs
69
- case 'IN':
70
- case 'NOT_IN':
71
- return { values: [] };
72
- case 'EQ':
73
- case 'NEQ': {
74
- if (fieldType === 'BOOLEAN') {
75
- // For booleans, these comparators can only be used for comparing with other fields
76
- return { field: '' };
77
- }
78
- if (validRhsTypes.size === 1 && validRhsTypes.has('FIELD')) {
79
- return { field: '' };
80
- }
81
- return { value: '' };
82
- }
83
- default: {
84
- // For all other comparators: GT/GTE/LT/LTE/STARTS_WITH/NOT_STARTS_WITH/ENDS_WITH/NOT_ENDS_WITH/CONTAINS/NOT_CONTAINS
85
- if (validRhsTypes.has('LITERAL'))
86
- return { value: '' };
87
- if (validRhsTypes.has('FIELD'))
88
- return { field: '' };
89
- }
90
- }
91
- }
92
- // FIXME: TR
93
- // Label for the `Enter <value>` option on the gear-menu
94
- function getValueOptionLabel(fieldType, isValueSelectorPossible) {
95
- if (isValueSelectorPossible) {
96
- return 'Select value';
97
- }
98
- switch (fieldType) {
99
- case 'TEXT':
100
- return 'Enter text';
101
- case 'NUMBER':
102
- return 'Enter number';
103
- case 'DATE_TIME':
104
- case 'DATE_ONLY':
105
- return 'Enter date';
106
- case 'TIME_ONLY':
107
- return 'Enter time';
108
- default:
109
- return 'Enter value'; // Not needed (BOOLEAN is not expected to be passed to the function)
110
- }
111
- }
112
- // Truncates output values from DateInput/DateTimeInput to return a wall time on the RHS
113
- // NOTE: This assumes that the input date is set up on the UTC timezone
114
- function truncateISODateString(dateString, fieldType) {
115
- const date = new Date(dateString);
116
- const YYYY = date.getUTCFullYear().toString().padStart(4, '0');
117
- const MM = (date.getUTCMonth() + 1).toString().padStart(2, '0');
118
- const DD = date.getUTCDate().toString().padStart(2, '0');
119
- // For DATE_ONLY fields, returning a YYYY-MM-DD format as per spec
120
- if (fieldType === 'DATE_ONLY')
121
- return `${YYYY}-${MM}-${DD}`;
122
- const hh = date.getUTCHours().toString().padStart(2, '0');
123
- const mm = date.getUTCMinutes().toString().padStart(2, '0');
124
- // cspell:disable-next-line
125
- // For DATE_TIME fields, returning a YYYY-MM-DDTHH:mm format and discarding the time-zone etc. to be consistent with the previous spec which was returning a wall time
126
- return `${YYYY}-${MM}-${DD}T${hh}:${mm}`;
127
- }
128
- /** A controlled component for controls on a Condition's RHS */
129
- const RhsControls = (props) => {
130
- const { lhs, comparator, rhs, fields, onChange, indicateErrors, validRhsTypes } = props;
131
- // If a field is not selected or if the comparator doesn't need any RHS, don't render anything
132
- if (rhs === undefined) {
133
- return React.createElement("div", null); // Rendering a placeholder div to keep the layout consistent
134
- }
135
- // Find the field corresponding to the LHS
136
- const matchingField = fields.find(f => f.name === lhs.field);
137
- if (matchingField === undefined) {
138
- // For safety against any rare cases where the LHS from an input condition is not present in the input fields to the ConditionBuilder
139
- // In those cases, don't render an RHS and wait for a valid value to be picked on LHS
140
- return React.createElement("div", null); // Rendering a placeholder div to keep the layout consistent
141
- }
142
- const fieldType = matchingField.type;
143
- // If errors should be indicated inline, validate the current rhs
144
- let showError = false;
145
- if (indicateErrors) {
146
- showError = !isValidRhs(rhs, fieldType, false, validRhsTypes);
147
- }
148
- // Set up the gear-menu
149
- // Boolean conditions either don't use an rhs or always use the field-selector
150
- // For IN/NOT_IN comparators, only one mode is possible for a given case - CSV Input or a Value-selector
151
- const showGearMenu = validRhsTypes.size > 1 && fieldType !== 'BOOLEAN' && !['IN', 'NOT_IN'].includes(comparator);
152
- // Apply an action from the gear-menu
153
- const applyGearAction = (actionType) => {
154
- if (actionType === 'USE_VALUE') {
155
- if (hasProp(rhs, 'value'))
156
- return; // Ignore if already in that mode
157
- onChange({ value: '' }); // Submit a new RHS to re-render with the new mode
158
- }
159
- else {
160
- if (hasProp(rhs, 'field'))
161
- return; // Ignore if already in that mode
162
- onChange({ field: '' }); // Submit a new RHS to re-render with the new mode
163
- }
164
- };
165
- // Set up Value-selector (if applicable)
166
- const { possibleValues } = matchingField; // These are passed when possible values are known ahead of time
167
- const isValueSelectorPossible = fieldType === 'TEXT' &&
168
- possibleValues !== undefined &&
169
- ['EQ', 'NEQ', 'IN', 'NOT_IN'].includes(comparator); // A ValueSelector in single/multiple mode is possible when these criteria are met
170
- const useValueSelector = isValueSelectorPossible && !hasProp(rhs, 'field'); // Use the ValueSelector component if it is applicable and if not in ANOTHER_FIELD mode
171
- // Handle changes from the Value-selector
172
- const handleValueSelection = (selection) => {
173
- if (typeof selection === 'string') {
174
- onChange({ value: selection }); // Submit a new RHS
175
- }
176
- else {
177
- onChange({ values: selection }); // Submit a new RHS
178
- }
179
- };
180
- // Options for the Field-selector (if applicable)
181
- const fieldOptions = useMemo(() => {
182
- // Show all other fields of the same data type as the LHS
183
- return fields.filter(f => f.type === fieldType && f.name !== lhs.field);
184
- }, [fields, lhs]);
185
- // Handle changes from the Field-selector
186
- const handleFieldChange = (id) => {
187
- onChange({ field: id }); // Submit a new RHS
188
- };
189
- // Handle changes from a Value-input
190
- const handleValueChange = (e) => {
191
- // NOTE: Not trimming the value here so that users can freely type spaces between words. Trimming is done on Submit, via the isValidRhs call
192
- let newValue = e.target.value;
193
- if (fieldType === 'NUMBER' && newValue !== '') {
194
- // Save as a number unless it is an empty string
195
- // If empty strings aren't allowed, users wont be able to clear a value to type something else
196
- newValue = Number(newValue);
197
- }
198
- onChange({ value: newValue }); // Submit a new RHS
199
- };
200
- // Handle changes from a Time-input
201
- const handleTimeValueChange = (e) => {
202
- let newValue = e.target.value;
203
- if (newValue.length === 5) {
204
- newValue += ':00'; // Enforce a fixed hh:mm:ss format
205
- }
206
- onChange({ value: convertTimeValueToMs(newValue) }); // Submit a new RHS
207
- };
208
- // Handle changes from a DateInput
209
- const handleDateValueChange = ({ valueAsISOString, valueAsTimestamp, state }) => {
210
- // NOTE: Not relying fully on `state` since in some cases state and valueAsTimestamp as both undefined
211
- if (valueAsTimestamp === undefined || state === 'incomplete' || state === 'invalid')
212
- return;
213
- const truncatedValue = truncateISODateString(valueAsISOString, fieldType); // Truncate to return a wall time as per spec
214
- onChange({ value: truncatedValue });
215
- };
216
- // Set up a CSV input for IN/NOT_IN comparators
217
- const [csvInput, setCsvInput] = useState(hasProp(rhs, 'values') ? rhs.values.join(', ') : '');
218
- useEffect(() => {
219
- // If moving away from the CSV-mode, clear the CSV Input.
220
- // This ensures that if a different `rhs.values` is passed (a new empty array can be passed when an applicable comparator is selected), the local state matches the new input.
221
- if (!hasProp(rhs, 'values') && csvInput) {
222
- setCsvInput('');
223
- }
224
- }, [rhs]);
225
- // Handle changes from a CSV-input
226
- const handleCSVChange = (e) => {
227
- // Update the controlled input
228
- setCsvInput(e.target.value);
229
- // Submit a new RHS
230
- let newValues = e.target.value
231
- .split(',')
232
- .map(v => v.trim())
233
- .filter(v => v.length > 0); // Ignore empty strings
234
- if (fieldType === 'NUMBER') {
235
- newValues = newValues.map(v => Number(v)); // This can set up some NaN values. Those are used to show an appropriate feedback when the submit button is hit
236
- }
237
- onChange({ values: newValues });
238
- };
239
- return (React.createElement(Flex, { container: {
240
- justify: 'between',
241
- alignItems: 'start',
242
- itemGap: 0.5
243
- } },
244
- showGearMenu && (React.createElement(MenuButton, { text: 'Value options', icon: 'gear', iconOnly: true, variant: 'simple', menu: {
245
- items: [
246
- {
247
- id: 'USE_VALUE',
248
- primary: getValueOptionLabel(fieldType, isValueSelectorPossible),
249
- onClick: () => applyGearAction('USE_VALUE')
250
- },
251
- {
252
- id: 'ANOTHER_FIELD',
253
- primary: 'Another field',
254
- onClick: () => applyGearAction('ANOTHER_FIELD')
255
- }
256
- ]
257
- } })),
258
- hasProp(rhs, 'field') && (React.createElement(Flex, { item: { grow: 1 } },
259
- React.createElement(FieldSelector, { value: rhs.field, onChange: handleFieldChange, fields: fieldOptions, status: showError ? 'error' : undefined, info: showError ? 'No selection' : undefined }))),
260
- hasProp(rhs, 'value') && (React.createElement(Flex, { item: { grow: 1 } },
261
- fieldType === 'TEXT' && useValueSelector && (React.createElement(Select, { value: rhs.value, onChange: (e) => handleValueSelection(e.target.value), status: showError ? 'error' : undefined, info: showError ? 'No selection' : undefined, label: '-', labelHidden: true },
262
- React.createElement(Option, { value: '' }, "Select value"),
263
- possibleValues.map(value => (React.createElement(Option, { key: value, value: value }, value))))),
264
- fieldType === 'TEXT' && !useValueSelector && (React.createElement(Input, { value: rhs.value, onChange: handleValueChange, status: showError ? 'error' : undefined, info: showError ? 'Empty value' : undefined, label: '-', labelHidden: true })),
265
- fieldType === 'NUMBER' && (
266
- // NOTE: If `as string` is used instead of `.toString()`, users won't be able to enter the value `0`
267
- React.createElement(Input, { type: 'number', value: rhs.value.toString(), onChange: handleValueChange, status: showError ? 'error' : undefined, info: showError ? 'Invalid number' : undefined, label: '-', labelHidden: true })),
268
- fieldType === 'TIME_ONLY' && (React.createElement(Input, { type: 'time', step: '1', value: typeof rhs.value === 'string' ? rhs.value : convertMsToTimeValue(rhs.value), onChange: handleTimeValueChange, status: showError ? 'error' : undefined, info: showError ? 'Invalid time' : undefined, label: '-', labelHidden: true })),
269
- fieldType === 'DATE_ONLY' && (React.createElement(DateInput, { value: rhs.value, onBlur: handleDateValueChange, status: showError ? 'error' : undefined, info: showError ? 'Invalid date' : '', label: '-', labelHidden: true })),
270
- fieldType === 'DATE_TIME' && (React.createElement(DateTimeInput, { value: rhs.value !== '' ? rhs.value : undefined, onBlur: handleDateValueChange, status: showError ? 'error' : undefined, info: showError ? 'Invalid date' : '', label: '-', labelHidden: true })))),
271
- hasProp(rhs, 'values') && (React.createElement(Flex, { item: { grow: 1 } },
272
- useValueSelector && (React.createElement(MultiValueSelector, { values: rhs.values, options: possibleValues, onChange: handleValueSelection, status: showError ? 'error' : undefined })),
273
- !useValueSelector && (React.createElement(Input, { value: csvInput, onChange: handleCSVChange, status: showError ? 'error' : undefined, info: showError ? 'Invalid values' : undefined, label: '-', labelHidden: true, placeholder: 'Enter comma separated values' // FIXME: TR
274
- }))))));
275
- };
276
- export default RhsControls;
277
- //# sourceMappingURL=RhsControls.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RhsControls.js","sourceRoot":"","sources":["../../../src/components/ConditionBuilder/RhsControls.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { FunctionComponent, ChangeEvent, useState, useEffect, useMemo } from 'react';\n\nimport {\n DateInput,\n DateTimeInput,\n Flex,\n Input,\n MenuButton,\n Select,\n Option,\n hasProp,\n BaseProps,\n ForwardProps\n} from '@pega/cosmos-react-core';\nimport { DateTimeCallbackParameter } from '@pega/cosmos-react-core/lib/components/DateTime/Input/DateTime.types';\n\nimport { FieldType, Comparator, RHSType } from './core/types';\nimport { LeafCondition, Field } from './ConditionBuilder.types';\nimport MultiValueSelector from './MultiValueSelector';\nimport FieldSelector from './FieldSelector';\nimport { convertTimeValueToMs, convertMsToTimeValue } from './core/time-utils';\n\n/** Verifies if the condition has all valid values */\nexport function isValidRhs(\n rhs: LeafCondition['rhs'],\n fieldType: FieldType | undefined,\n trimValues: boolean = false,\n validRhsTypes: Set<RHSType>\n): boolean {\n // RHS would be `undefined` when no RHS is needed. Treat it as a valid value\n if (rhs === undefined) {\n return true;\n }\n\n // Field-selector on the RHS\n if (hasProp(rhs, 'field') && !validRhsTypes.has('FIELD')) {\n return false;\n }\n if (hasProp(rhs, 'field')) {\n // RHS is invalid if no field is selected\n return rhs.field !== '';\n }\n\n // List-input cases\n if (hasProp(rhs, 'values') && !validRhsTypes.has('LITERAL')) {\n return false;\n }\n if (hasProp(rhs, 'values')) {\n // RHS is invalid if the list is empty\n if (rhs.values.length === 0) {\n return false;\n }\n // For numeric fields, RHS is invalid if any NaN values are present in the list\n if (fieldType === 'NUMBER') {\n if ((rhs.values as number[]).some(v => Number.isNaN(v))) {\n return false;\n }\n }\n }\n\n if (hasProp(rhs, 'value') && !validRhsTypes.has('LITERAL')) {\n return false;\n }\n if (hasProp(rhs, 'value')) {\n // Identify any invalid numbers (not expected)\n if (typeof rhs.value === 'number') {\n return !Number.isNaN(rhs.value);\n }\n\n // NOTE: Not trimming the value in the change-handler so that users can freely type spaces between words\n if (trimValues) {\n rhs.value = rhs.value.trim();\n }\n\n // Can be empty on init and on clearing the value\n if (rhs.value.trim() === '') {\n return false;\n }\n\n // This check is needed to eliminate invalid dates like `Feb 31` (02/31/2020), which the input allows\n if (fieldType === 'DATE_TIME' || fieldType === 'DATE_ONLY') {\n if (Number.isNaN(new Date(rhs.value).getTime())) {\n return false;\n }\n }\n }\n\n return true;\n}\n\n/** For a condition with the given comparator and lhs-field-type, determines an appropriate default value for the Rhs */\nexport function getDefaultRhs(\n fieldType: FieldType,\n comparator: Comparator,\n validRhsTypes: Set<RHSType>\n): LeafCondition['rhs'] {\n switch (comparator) {\n case 'IS_TRUE':\n case 'IS_FALSE':\n case 'IS_NULL':\n case 'IS_NOT_NULL':\n return undefined; // These comparators do not have an Rhs\n\n case 'IN':\n case 'NOT_IN':\n return { values: [] };\n\n case 'EQ':\n case 'NEQ': {\n if (fieldType === 'BOOLEAN') {\n // For booleans, these comparators can only be used for comparing with other fields\n return { field: '' };\n }\n if (validRhsTypes.size === 1 && validRhsTypes.has('FIELD')) {\n return { field: '' };\n }\n\n return { value: '' };\n }\n\n default: {\n // For all other comparators: GT/GTE/LT/LTE/STARTS_WITH/NOT_STARTS_WITH/ENDS_WITH/NOT_ENDS_WITH/CONTAINS/NOT_CONTAINS\n if (validRhsTypes.has('LITERAL')) return { value: '' };\n if (validRhsTypes.has('FIELD')) return { field: '' };\n }\n }\n}\n\n// FIXME: TR\n// Label for the `Enter <value>` option on the gear-menu\nfunction getValueOptionLabel(fieldType: FieldType, isValueSelectorPossible: boolean): string {\n if (isValueSelectorPossible) {\n return 'Select value';\n }\n switch (fieldType) {\n case 'TEXT':\n return 'Enter text';\n case 'NUMBER':\n return 'Enter number';\n case 'DATE_TIME':\n case 'DATE_ONLY':\n return 'Enter date';\n case 'TIME_ONLY':\n return 'Enter time';\n default:\n return 'Enter value'; // Not needed (BOOLEAN is not expected to be passed to the function)\n }\n}\n\n// Truncates output values from DateInput/DateTimeInput to return a wall time on the RHS\n// NOTE: This assumes that the input date is set up on the UTC timezone\nfunction truncateISODateString(dateString: string, fieldType: FieldType): string {\n const date = new Date(dateString);\n const YYYY = date.getUTCFullYear().toString().padStart(4, '0');\n const MM = (date.getUTCMonth() + 1).toString().padStart(2, '0');\n const DD = date.getUTCDate().toString().padStart(2, '0');\n\n // For DATE_ONLY fields, returning a YYYY-MM-DD format as per spec\n if (fieldType === 'DATE_ONLY') return `${YYYY}-${MM}-${DD}`;\n\n const hh = date.getUTCHours().toString().padStart(2, '0');\n const mm = date.getUTCMinutes().toString().padStart(2, '0');\n\n // cspell:disable-next-line\n // For DATE_TIME fields, returning a YYYY-MM-DDTHH:mm format and discarding the time-zone etc. to be consistent with the previous spec which was returning a wall time\n return `${YYYY}-${MM}-${DD}T${hh}:${mm}`;\n}\n\n/** Type definition for the input props of RhsControls */\ninterface RhsControlProps extends BaseProps {\n /** Lhs for the condition */\n lhs: LeafCondition['lhs'];\n\n /** Comparator for the condition */\n comparator: Comparator;\n\n /** Rhs for the condition */\n rhs: LeafCondition['rhs'];\n\n /** Metadata (data-model) for the Fields to use in the RHS field-selector */\n fields: Field[];\n\n /** Callback for any modifications to the Rhs */\n onChange: (rhs: LeafCondition['rhs']) => void;\n\n /** Used to enable inline error indicators on invalid inputs */\n indicateErrors: boolean;\n\n /** Restricts RHS values to only specified RHS types */\n validRhsTypes: Set<RHSType>;\n}\n\n/** A controlled component for controls on a Condition's RHS */\nconst RhsControls: FunctionComponent<RhsControlProps & ForwardProps> = (props: RhsControlProps) => {\n const { lhs, comparator, rhs, fields, onChange, indicateErrors, validRhsTypes } = props;\n\n // If a field is not selected or if the comparator doesn't need any RHS, don't render anything\n if (rhs === undefined) {\n return <div />; // Rendering a placeholder div to keep the layout consistent\n }\n\n // Find the field corresponding to the LHS\n const matchingField = fields.find(f => f.name === lhs.field);\n if (matchingField === undefined) {\n // For safety against any rare cases where the LHS from an input condition is not present in the input fields to the ConditionBuilder\n // In those cases, don't render an RHS and wait for a valid value to be picked on LHS\n return <div />; // Rendering a placeholder div to keep the layout consistent\n }\n const fieldType = matchingField.type;\n\n // If errors should be indicated inline, validate the current rhs\n let showError = false;\n if (indicateErrors) {\n showError = !isValidRhs(rhs, fieldType, false, validRhsTypes);\n }\n\n // Set up the gear-menu\n // Boolean conditions either don't use an rhs or always use the field-selector\n // For IN/NOT_IN comparators, only one mode is possible for a given case - CSV Input or a Value-selector\n const showGearMenu =\n validRhsTypes.size > 1 && fieldType !== 'BOOLEAN' && !['IN', 'NOT_IN'].includes(comparator);\n\n // Apply an action from the gear-menu\n const applyGearAction = (actionType: string) => {\n if (actionType === 'USE_VALUE') {\n if (hasProp(rhs, 'value')) return; // Ignore if already in that mode\n onChange({ value: '' }); // Submit a new RHS to re-render with the new mode\n } else {\n if (hasProp(rhs, 'field')) return; // Ignore if already in that mode\n onChange({ field: '' }); // Submit a new RHS to re-render with the new mode\n }\n };\n\n // Set up Value-selector (if applicable)\n const { possibleValues } = matchingField; // These are passed when possible values are known ahead of time\n const isValueSelectorPossible =\n fieldType === 'TEXT' &&\n possibleValues !== undefined &&\n ['EQ', 'NEQ', 'IN', 'NOT_IN'].includes(comparator); // A ValueSelector in single/multiple mode is possible when these criteria are met\n const useValueSelector = isValueSelectorPossible && !hasProp(rhs, 'field'); // Use the ValueSelector component if it is applicable and if not in ANOTHER_FIELD mode\n\n // Handle changes from the Value-selector\n const handleValueSelection = (selection: string | string[]) => {\n if (typeof selection === 'string') {\n onChange({ value: selection }); // Submit a new RHS\n } else {\n onChange({ values: selection }); // Submit a new RHS\n }\n };\n\n // Options for the Field-selector (if applicable)\n const fieldOptions = useMemo(() => {\n // Show all other fields of the same data type as the LHS\n return fields.filter(f => f.type === fieldType && f.name !== lhs.field);\n }, [fields, lhs]);\n\n // Handle changes from the Field-selector\n const handleFieldChange = (id: string) => {\n onChange({ field: id }); // Submit a new RHS\n };\n\n // Handle changes from a Value-input\n const handleValueChange = (e: ChangeEvent<HTMLInputElement>) => {\n // NOTE: Not trimming the value here so that users can freely type spaces between words. Trimming is done on Submit, via the isValidRhs call\n let newValue: string | number = e.target.value;\n if (fieldType === 'NUMBER' && newValue !== '') {\n // Save as a number unless it is an empty string\n // If empty strings aren't allowed, users wont be able to clear a value to type something else\n newValue = Number(newValue);\n }\n onChange({ value: newValue }); // Submit a new RHS\n };\n\n // Handle changes from a Time-input\n const handleTimeValueChange = (e: ChangeEvent<HTMLInputElement>) => {\n let newValue = e.target.value;\n if (newValue.length === 5) {\n newValue += ':00'; // Enforce a fixed hh:mm:ss format\n }\n onChange({ value: convertTimeValueToMs(newValue) }); // Submit a new RHS\n };\n\n // Handle changes from a DateInput\n const handleDateValueChange = ({\n valueAsISOString,\n valueAsTimestamp,\n state\n }: DateTimeCallbackParameter) => {\n // NOTE: Not relying fully on `state` since in some cases state and valueAsTimestamp as both undefined\n if (valueAsTimestamp === undefined || state === 'incomplete' || state === 'invalid') return;\n\n const truncatedValue = truncateISODateString(valueAsISOString, fieldType); // Truncate to return a wall time as per spec\n onChange({ value: truncatedValue });\n };\n\n // Set up a CSV input for IN/NOT_IN comparators\n const [csvInput, setCsvInput] = useState(hasProp(rhs, 'values') ? rhs.values.join(', ') : '');\n useEffect(() => {\n // If moving away from the CSV-mode, clear the CSV Input.\n // This ensures that if a different `rhs.values` is passed (a new empty array can be passed when an applicable comparator is selected), the local state matches the new input.\n if (!hasProp(rhs, 'values') && csvInput) {\n setCsvInput('');\n }\n }, [rhs]);\n\n // Handle changes from a CSV-input\n const handleCSVChange = (e: ChangeEvent<HTMLInputElement>) => {\n // Update the controlled input\n setCsvInput(e.target.value);\n\n // Submit a new RHS\n let newValues: string[] | number[] = e.target.value\n .split(',')\n .map(v => v.trim())\n .filter(v => v.length > 0); // Ignore empty strings\n if (fieldType === 'NUMBER') {\n newValues = newValues.map(v => Number(v)); // This can set up some NaN values. Those are used to show an appropriate feedback when the submit button is hit\n }\n onChange({ values: newValues });\n };\n\n return (\n <Flex\n container={{\n justify: 'between',\n alignItems: 'start',\n itemGap: 0.5\n }}\n >\n {/* Gear Menu */}\n {showGearMenu && (\n <MenuButton\n text='Value options'\n icon='gear'\n iconOnly\n variant='simple'\n menu={{\n items: [\n {\n id: 'USE_VALUE',\n primary: getValueOptionLabel(fieldType as FieldType, isValueSelectorPossible),\n onClick: () => applyGearAction('USE_VALUE')\n },\n {\n id: 'ANOTHER_FIELD',\n primary: 'Another field',\n onClick: () => applyGearAction('ANOTHER_FIELD')\n }\n ]\n }}\n />\n )}\n\n {/* Field-selector */}\n {hasProp(rhs, 'field') && (\n <Flex item={{ grow: 1 }}>\n <FieldSelector\n value={rhs.field}\n onChange={handleFieldChange}\n fields={fieldOptions}\n status={showError ? 'error' : undefined}\n info={showError ? 'No selection' : undefined} // FIXME: TR\n />\n </Flex>\n )}\n\n {/* Value input */}\n {hasProp(rhs, 'value') && (\n <Flex item={{ grow: 1 }}>\n {fieldType === 'TEXT' && useValueSelector && (\n <Select\n value={rhs.value as string}\n onChange={(e: ChangeEvent<HTMLSelectElement>) => handleValueSelection(e.target.value)}\n status={showError ? 'error' : undefined}\n info={showError ? 'No selection' : undefined} // FIXME: TR\n label='-'\n labelHidden\n >\n <Option value=''>Select value</Option>\n {possibleValues!.map(value => (\n <Option key={value} value={value}>\n {value}\n </Option>\n ))}\n </Select>\n )}\n {fieldType === 'TEXT' && !useValueSelector && (\n <Input\n value={rhs.value as string}\n onChange={handleValueChange}\n status={showError ? 'error' : undefined}\n info={showError ? 'Empty value' : undefined} // FIXME: TR\n label='-'\n labelHidden\n />\n )}\n {fieldType === 'NUMBER' && (\n // NOTE: If `as string` is used instead of `.toString()`, users won't be able to enter the value `0`\n <Input\n type='number'\n value={rhs.value.toString()}\n onChange={handleValueChange}\n status={showError ? 'error' : undefined}\n info={showError ? 'Invalid number' : undefined} // FIXME: TR\n label='-'\n labelHidden\n />\n )}\n {fieldType === 'TIME_ONLY' && (\n <Input\n type='time'\n step='1'\n value={typeof rhs.value === 'string' ? rhs.value : convertMsToTimeValue(rhs.value)}\n onChange={handleTimeValueChange}\n status={showError ? 'error' : undefined}\n info={showError ? 'Invalid time' : undefined} // FIXME: TR\n label='-'\n labelHidden\n />\n )}\n {fieldType === 'DATE_ONLY' && (\n <DateInput\n value={rhs.value}\n onBlur={handleDateValueChange}\n status={showError ? 'error' : undefined}\n info={showError ? 'Invalid date' : ''} // FIXME: TR , NOTE: Using empty quotes to disable the default info which indicates the format\n label='-'\n labelHidden\n />\n )}\n {fieldType === 'DATE_TIME' && (\n <DateTimeInput\n value={rhs.value !== '' ? rhs.value : undefined}\n onBlur={handleDateValueChange}\n status={showError ? 'error' : undefined}\n info={showError ? 'Invalid date' : ''} // FIXME: TR , NOTE: Using empty quotes to disable the default info which indicates the format\n label='-'\n labelHidden\n />\n )}\n </Flex>\n )}\n\n {/* Multiple-values input */}\n {hasProp(rhs, 'values') && (\n <Flex item={{ grow: 1 }}>\n {useValueSelector && (\n <MultiValueSelector\n values={rhs.values as string[]}\n options={possibleValues!}\n onChange={handleValueSelection}\n status={showError ? 'error' : undefined}\n />\n )}\n {!useValueSelector && (\n <Input\n value={csvInput}\n onChange={handleCSVChange}\n status={showError ? 'error' : undefined}\n info={showError ? 'Invalid values' : undefined} // FIXME: TR\n label='-'\n labelHidden\n placeholder='Enter comma separated values' // FIXME: TR\n />\n )}\n </Flex>\n )}\n </Flex>\n );\n};\nexport default RhsControls;\n"]}