@orchestrator-ui/orchestrator-ui-components 8.7.0 → 8.7.2
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/.turbo/turbo-build.log +8 -8
- package/.turbo/turbo-lint.log +1 -1
- package/.turbo/turbo-test.log +12 -12
- package/CHANGELOG.md +14 -0
- package/dist/index.d.ts +379 -1244
- package/dist/index.js +1021 -1068
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/WfoPydanticForm/fields/WfoSummary.tsx +42 -7
- package/src/components/WfoSearchPage/WfoFilterGroup/WfoFilterGroup.tsx +1 -1
- package/src/components/WfoTable/WfoStructuredSearchTable/WfoFieldSelector.tsx +1 -1
- package/src/components/WfoTable/WfoStructuredSearchTable/WfoFilterBuilder.tsx +25 -7
- package/src/components/WfoTable/WfoStructuredSearchTable/WfoOperatorSelector.tsx +18 -1
- package/src/components/WfoTable/WfoStructuredSearchTable/WfoRangeEditor.tsx +38 -50
- package/src/components/WfoTable/WfoStructuredSearchTable/WfoValueEditor.tsx +34 -29
- package/src/configuration/version.ts +1 -1
- package/src/messages/en-GB.json +452 -578
- package/src/messages/getTranslationMessages.spec.ts +47 -30
- package/src/messages/nl-NL.json +450 -430
package/package.json
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
3
|
import { capitalize } from 'lodash';
|
|
4
|
-
import
|
|
4
|
+
import {
|
|
5
|
+
type PydanticFormElement,
|
|
6
|
+
type PydanticFormLabelProviderResponse,
|
|
7
|
+
useGetConfig,
|
|
8
|
+
useLabelProvider,
|
|
9
|
+
} from 'pydantic-forms';
|
|
5
10
|
|
|
6
11
|
import { EuiFlexItem, EuiFormRow, EuiText } from '@elastic/eui';
|
|
7
12
|
|
|
@@ -14,24 +19,53 @@ import { getNestedSummaryLabel } from './wfoPydanticFormUtils';
|
|
|
14
19
|
export const WfoSummary: PydanticFormElement = ({ pydanticFormField }) => {
|
|
15
20
|
const { summaryFieldStyle } = useWithOrchestratorTheme(summaryFieldStyles);
|
|
16
21
|
const { formRowStyle } = useWithOrchestratorTheme(getCommonFormFieldStyles);
|
|
22
|
+
const config = useGetConfig();
|
|
23
|
+
const { data }: { data: PydanticFormLabelProviderResponse | undefined } = useLabelProvider(
|
|
24
|
+
config.labelProvider,
|
|
25
|
+
'temp',
|
|
26
|
+
'test',
|
|
27
|
+
);
|
|
28
|
+
const rawLabels = data?.labels || { summary: {} };
|
|
29
|
+
const labelTranslations: Record<string, string> = {
|
|
30
|
+
...(rawLabels as Record<string, string>),
|
|
31
|
+
...(rawLabels?.summary as Record<string, string>),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const translateSummaryField = (value: string) => {
|
|
35
|
+
if (value in labelTranslations) {
|
|
36
|
+
return labelTranslations[value];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const match = value.match(/^(.+)_(\d+)$/);
|
|
40
|
+
if (!match) {
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
const [, base, suffix] = match;
|
|
44
|
+
|
|
45
|
+
if (base in labelTranslations) {
|
|
46
|
+
return `${labelTranslations[base]} ${suffix}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return snakeToHuman(capitalize(value));
|
|
50
|
+
};
|
|
17
51
|
|
|
18
52
|
const { id, title, description } = pydanticFormField;
|
|
19
53
|
const uniforms = pydanticFormField.schema.uniforms;
|
|
20
54
|
const summaryData = uniforms?.data as unknown as {
|
|
21
|
-
headers: string[]
|
|
55
|
+
headers: string[];
|
|
22
56
|
labels: string[];
|
|
23
57
|
columns: string[][];
|
|
24
58
|
};
|
|
25
59
|
|
|
26
|
-
const headers = summaryData?.headers
|
|
27
|
-
const labels = summaryData?.labels
|
|
60
|
+
const headers = summaryData?.headers;
|
|
61
|
+
const labels = summaryData?.labels;
|
|
28
62
|
const columns = summaryData?.columns || [];
|
|
29
63
|
|
|
30
64
|
const extraColumnsData = columns.filter((_, index) => index !== 0);
|
|
31
65
|
|
|
32
66
|
const rows = columns[0].map((row, index) => (
|
|
33
67
|
<tr key={index}>
|
|
34
|
-
{labels && <td className={`label`}>{getNestedSummaryLabel(labels, index)}</td>}
|
|
68
|
+
{labels && <td className={`label`}>{translateSummaryField(getNestedSummaryLabel(labels, index))}</td>}
|
|
35
69
|
<td className={`value`}>
|
|
36
70
|
{typeof row === 'string' && row.includes('<!doctype html>') ?
|
|
37
71
|
<div className="emailMessage" dangerouslySetInnerHTML={{ __html: row }}></div>
|
|
@@ -52,11 +86,12 @@ export const WfoSummary: PydanticFormElement = ({ pydanticFormField }) => {
|
|
|
52
86
|
: <tr>
|
|
53
87
|
{labels && <th />}
|
|
54
88
|
{headers.map((header, idx) => (
|
|
55
|
-
<th key={idx}>{header}</th>
|
|
89
|
+
<th key={idx}>{translateSummaryField(header)}</th>
|
|
56
90
|
))}
|
|
57
91
|
</tr>;
|
|
58
92
|
|
|
59
|
-
const formattedTitle =
|
|
93
|
+
const formattedTitle =
|
|
94
|
+
title === 'MigrationSummaryValue' ? translateSummaryField(id) : snakeToHuman(capitalize(title ?? ''));
|
|
60
95
|
|
|
61
96
|
return (
|
|
62
97
|
<EuiFlexItem data-testid={id} css={[summaryFieldStyle, formRowStyle]}>
|
|
@@ -113,7 +113,7 @@ export const FilterGroup: FC<FilterGroupProps> = ({
|
|
|
113
113
|
<EuiFlexGroup gutterSize="s" alignItems="center">
|
|
114
114
|
<EuiFlexItem grow={false}>
|
|
115
115
|
<EuiButton size="s" iconType="plusInCircle" onClick={addCondition}>
|
|
116
|
-
{t('
|
|
116
|
+
{t('addRule')}
|
|
117
117
|
</EuiButton>
|
|
118
118
|
</EuiFlexItem>
|
|
119
119
|
<EuiFlexItem grow={false}>
|
|
@@ -85,7 +85,7 @@ export const WfoFieldSelector = ({ handleOnChange, disabled, rule, context }: Fi
|
|
|
85
85
|
?? paths.find((path) => path.availablePaths?.includes(selectedValue));
|
|
86
86
|
const operators = matchingPath?.operators ?? prefilledFieldOptions.get(selectedValue) ?? [];
|
|
87
87
|
|
|
88
|
-
context?.onFieldSelected?.(selectedValue, operators);
|
|
88
|
+
context?.onFieldSelected?.(selectedValue, operators, matchingPath);
|
|
89
89
|
};
|
|
90
90
|
|
|
91
91
|
const handleFieldSelection = (selectedOptions: EuiComboBoxOptionOption<string>[]) => {
|
|
@@ -10,7 +10,7 @@ import { SearchParams, WfoAutoExpandableTextArea, WfoTextAnchor } from '@/compon
|
|
|
10
10
|
import { WfoCombinatorSelector } from '@/components/WfoTable/WfoStructuredSearchTable/WfoCombinatorSelector';
|
|
11
11
|
import { useWithOrchestratorTheme } from '@/hooks';
|
|
12
12
|
import { OperatorDisplay } from '@/types';
|
|
13
|
-
import type { FieldToOperatorMap } from '@/types';
|
|
13
|
+
import type { FieldToOperatorMap, PathInfo } from '@/types';
|
|
14
14
|
|
|
15
15
|
import { WfoFieldSelector } from './WfoFieldSelector';
|
|
16
16
|
import { WfoInlineCombinator } from './WfoInlineCombinator';
|
|
@@ -23,6 +23,9 @@ import { getWfoStructuredSearchTableStyles } from './styles';
|
|
|
23
23
|
|
|
24
24
|
// Maps PathInfo operator names to react-querybuilder's native operator names,
|
|
25
25
|
// which is what parseCEL produces and formatQuery(cel) expects.
|
|
26
|
+
// has_component/not_has_component ride on notNull/null: they survive the CEL round trip
|
|
27
|
+
// (`field != null` / `field == null`) and formatQuery(elasticsearch) turns them into
|
|
28
|
+
// exists / must_not-exists, which the backend translates to component-presence filters.
|
|
26
29
|
const SEARCH_OPERATOR_TO_RQB_OPERATOR_MAP: Record<string, string> = {
|
|
27
30
|
eq: '=',
|
|
28
31
|
neq: '!=',
|
|
@@ -32,8 +35,13 @@ const SEARCH_OPERATOR_TO_RQB_OPERATOR_MAP: Record<string, string> = {
|
|
|
32
35
|
gte: '>=',
|
|
33
36
|
between: 'between',
|
|
34
37
|
like: 'contains',
|
|
38
|
+
has_component: 'notNull',
|
|
39
|
+
not_has_component: 'null',
|
|
35
40
|
};
|
|
36
41
|
|
|
42
|
+
// Operators without a value; marking them unary makes react-querybuilder's Rule hide the value editor.
|
|
43
|
+
const RQB_UNARY_OPERATORS = ['null', 'notNull'];
|
|
44
|
+
|
|
37
45
|
const OPERATOR_MAP: Record<string, OperatorDisplay> = {
|
|
38
46
|
eq: { symbol: '=', description: 'equals' },
|
|
39
47
|
neq: { symbol: '≠', description: 'not equals' },
|
|
@@ -47,10 +55,6 @@ const OPERATOR_MAP: Record<string, OperatorDisplay> = {
|
|
|
47
55
|
like: { symbol: '∋', description: 'contains' },
|
|
48
56
|
};
|
|
49
57
|
|
|
50
|
-
/* TODO: Add the missing operators
|
|
51
|
-
['has_component', 'not_has_component'];
|
|
52
|
-
*/
|
|
53
|
-
|
|
54
58
|
interface WfoFilterBuilderProps {
|
|
55
59
|
filterString?: string;
|
|
56
60
|
onUpdateFilterString: (filterString: string) => void;
|
|
@@ -87,13 +91,21 @@ export const WfoFilterBuilder = ({
|
|
|
87
91
|
return (operators ?? []).map((operator) => {
|
|
88
92
|
const { symbol, description } = OPERATOR_MAP[operator] || { symbol: operator, description: operator };
|
|
89
93
|
const rqbOperator = SEARCH_OPERATOR_TO_RQB_OPERATOR_MAP[operator] ?? operator;
|
|
90
|
-
return {
|
|
94
|
+
return {
|
|
95
|
+
name: rqbOperator,
|
|
96
|
+
label: `${symbol} ${description}`,
|
|
97
|
+
value: rqbOperator,
|
|
98
|
+
...(RQB_UNARY_OPERATORS.includes(rqbOperator) && { arity: 'unary' }),
|
|
99
|
+
};
|
|
91
100
|
});
|
|
92
101
|
};
|
|
93
102
|
|
|
94
103
|
const t = useTranslations('common');
|
|
95
104
|
const { queryBuilderContainerStyles } = useWithOrchestratorTheme(getWfoStructuredSearchTableStyles);
|
|
96
105
|
const [fieldToOperatorMap, setFieldToOperatorMap] = useState<FieldToOperatorMap>(prefilledFieldOptions);
|
|
106
|
+
// Path info per selected field, so the value editor can pick a typed editor (date picker,
|
|
107
|
+
// number input, boolean toggle or range editor)
|
|
108
|
+
const [fieldPathInfoMap, setFieldPathInfoMap] = useState<Map<string, PathInfo>>(new Map());
|
|
97
109
|
|
|
98
110
|
// Enter in a value editor commits its value on blur, and that state update has not
|
|
99
111
|
// flushed yet when the search runs in the same keydown. onQueryChange fires
|
|
@@ -106,10 +118,15 @@ export const WfoFilterBuilder = ({
|
|
|
106
118
|
handleSearch({ ruleGroup: latestRuleGroupRef.current });
|
|
107
119
|
};
|
|
108
120
|
|
|
109
|
-
const handleFieldSelected = (field: string, operators: string[]) => {
|
|
121
|
+
const handleFieldSelected = (field: string, operators: string[], pathInfo?: PathInfo) => {
|
|
110
122
|
setFieldToOperatorMap((previousMap) => {
|
|
111
123
|
return new Map(previousMap).set(field, operators);
|
|
112
124
|
});
|
|
125
|
+
if (pathInfo) {
|
|
126
|
+
setFieldPathInfoMap((previousMap) => {
|
|
127
|
+
return new Map(previousMap).set(field, pathInfo);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
113
130
|
};
|
|
114
131
|
|
|
115
132
|
return (
|
|
@@ -126,6 +143,7 @@ export const WfoFilterBuilder = ({
|
|
|
126
143
|
context={{
|
|
127
144
|
onFieldSelected: handleFieldSelected,
|
|
128
145
|
prefilledFieldOptions,
|
|
146
|
+
fieldPathInfoMap,
|
|
129
147
|
onValueEditorEnter: handleValueEditorEnter,
|
|
130
148
|
}}
|
|
131
149
|
getOperators={(field) => {
|
|
@@ -7,6 +7,14 @@ import { EuiSelect } from '@elastic/eui';
|
|
|
7
7
|
const isOptionGroup = (operator: FullOperator | OptionGroup<FullOperator>): operator is OptionGroup<FullOperator> =>
|
|
8
8
|
'options' in operator;
|
|
9
9
|
|
|
10
|
+
// The search backend has no is-null operator: null/notNull only occur here as the
|
|
11
|
+
// react-querybuilder encoding of the component-presence operators, so a restored rule
|
|
12
|
+
// should label them accordingly instead of using defaultOperators' "is (not) null".
|
|
13
|
+
const FALLBACK_OPERATOR_LABELS: Record<string, string> = {
|
|
14
|
+
notNull: '✓ has component',
|
|
15
|
+
null: '✗ does not have component',
|
|
16
|
+
};
|
|
17
|
+
|
|
10
18
|
export const WfoOperatorSelector = (props: OperatorSelectorProps) => {
|
|
11
19
|
const { value, handleOnChange } = props;
|
|
12
20
|
|
|
@@ -44,7 +52,16 @@ export const WfoOperatorSelector = (props: OperatorSelectorProps) => {
|
|
|
44
52
|
const currentValueIsListed = !value || selectOptions.some((option) => option.value === value);
|
|
45
53
|
const displayOptions =
|
|
46
54
|
currentValueIsListed ? selectOptions : (
|
|
47
|
-
[
|
|
55
|
+
[
|
|
56
|
+
...selectOptions,
|
|
57
|
+
{
|
|
58
|
+
value,
|
|
59
|
+
text:
|
|
60
|
+
FALLBACK_OPERATOR_LABELS[value]
|
|
61
|
+
?? defaultOperators.find((operator) => operator.name === value)?.label
|
|
62
|
+
?? value,
|
|
63
|
+
},
|
|
64
|
+
]
|
|
48
65
|
);
|
|
49
66
|
|
|
50
67
|
return (
|
|
@@ -1,64 +1,52 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import type { ValueEditorProps } from 'react-querybuilder';
|
|
2
3
|
|
|
3
4
|
import { EuiFlexGroup } from '@elastic/eui';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
handleOnChange: (value: string | number | undefined, rangeIndex?: number) => void;
|
|
7
|
-
value: string;
|
|
8
|
-
operator?: string;
|
|
9
|
-
rangeIndex?: number;
|
|
10
|
-
}
|
|
6
|
+
import type { EditorComponent } from './WfoValueEditor';
|
|
11
7
|
|
|
12
8
|
interface WfoRangeEditorProps {
|
|
13
|
-
handleOnChange:
|
|
14
|
-
operator: string;
|
|
9
|
+
handleOnChange: ValueEditorProps['handleOnChange'];
|
|
15
10
|
value: string;
|
|
16
|
-
|
|
11
|
+
InputElement: EditorComponent;
|
|
17
12
|
}
|
|
18
13
|
|
|
19
|
-
export const WfoRangeEditor = ({ handleOnChange,
|
|
20
|
-
const [currentOperator, setCurrentOperator] = useState(operator);
|
|
14
|
+
export const WfoRangeEditor = ({ handleOnChange, InputElement, value: currentValue }: WfoRangeEditorProps) => {
|
|
21
15
|
const startValue = currentValue ? currentValue?.toString().split(',') : [];
|
|
22
|
-
const [value, setValue] = useState<string[]>(startValue);
|
|
16
|
+
const [value, setValue] = useState<(string | undefined)[]>(startValue);
|
|
17
|
+
|
|
18
|
+
const handleRangeChange = (newValue: string | number | boolean | undefined, rangeIndex: number) => {
|
|
19
|
+
setValue((currentValues) => {
|
|
20
|
+
const next = [...currentValues];
|
|
21
|
+
const isCleared = newValue === undefined || (typeof newValue === 'number' && Number.isNaN(newValue));
|
|
22
|
+
next[rangeIndex] = isCleared ? undefined : String(newValue);
|
|
23
|
+
return next;
|
|
24
|
+
});
|
|
25
|
+
};
|
|
23
26
|
|
|
27
|
+
// Notify the parent only when both ends of the range hold a value
|
|
24
28
|
useEffect(() => {
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
handleOnChange('');
|
|
28
|
-
setCurrentOperator(operator);
|
|
29
|
-
}
|
|
30
|
-
}, [currentOperator, handleOnChange, operator]);
|
|
31
|
-
|
|
32
|
-
const handleChange = (value: string | number | undefined, rangeIndex: number = 0) => {
|
|
33
|
-
if (operator === 'between') {
|
|
34
|
-
setValue((currentDates) => {
|
|
35
|
-
// remove value if set to undefined
|
|
36
|
-
if (value === null) {
|
|
37
|
-
return currentDates.filter((_, index) => index !== rangeIndex);
|
|
38
|
-
}
|
|
39
|
-
// add value at supplied index
|
|
40
|
-
currentDates[rangeIndex] = value as string;
|
|
41
|
-
|
|
42
|
-
// call the parent if 2 values are present
|
|
43
|
-
if (currentDates.length === 2) {
|
|
44
|
-
handleOnChange(`${currentDates[0]},${currentDates[1]}`);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return currentDates;
|
|
48
|
-
});
|
|
49
|
-
} else {
|
|
50
|
-
handleOnChange(value);
|
|
29
|
+
if (value[0] !== undefined && value[1] !== undefined) {
|
|
30
|
+
handleOnChange(`${value[0]},${value[1]}`);
|
|
51
31
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
32
|
+
// handleOnChange comes from react-querybuilder and is not referentially stable
|
|
33
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
34
|
+
}, [value]);
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<EuiFlexGroup direction="row" gutterSize="s">
|
|
38
|
+
<InputElement
|
|
39
|
+
handleOnChange={(value) => {
|
|
40
|
+
handleRangeChange(value, 0);
|
|
41
|
+
}}
|
|
42
|
+
value={value[0]}
|
|
43
|
+
/>
|
|
44
|
+
<InputElement
|
|
45
|
+
handleOnChange={(value) => {
|
|
46
|
+
handleRangeChange(value, 1);
|
|
47
|
+
}}
|
|
48
|
+
value={value[1]}
|
|
49
|
+
/>
|
|
50
|
+
</EuiFlexGroup>
|
|
51
|
+
);
|
|
64
52
|
};
|
|
@@ -7,10 +7,15 @@ import { useTranslations } from 'next-intl';
|
|
|
7
7
|
|
|
8
8
|
import { EuiButtonGroup, EuiDatePicker, EuiFieldNumber, EuiFieldText } from '@elastic/eui';
|
|
9
9
|
|
|
10
|
+
import { WfoRangeEditor } from '@/components/WfoTable/WfoStructuredSearchTable/WfoRangeEditor';
|
|
10
11
|
import { getWfoStructuredSearchTableStyles } from '@/components/WfoTable/WfoStructuredSearchTable/styles';
|
|
11
12
|
import { useWithOrchestratorTheme } from '@/hooks';
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
export interface EditorInputFieldProps<T = string> {
|
|
15
|
+
handleOnChange: ValueEditorProps['handleOnChange'];
|
|
16
|
+
value: T;
|
|
17
|
+
}
|
|
18
|
+
export type EditorComponent = React.ComponentType<EditorInputFieldProps<ValueEditorProps['value']>>;
|
|
14
19
|
|
|
15
20
|
enum UiFieldType {
|
|
16
21
|
text = 'text',
|
|
@@ -19,15 +24,7 @@ enum UiFieldType {
|
|
|
19
24
|
datetime = 'datetime',
|
|
20
25
|
}
|
|
21
26
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
export interface EditorProps<T> {
|
|
25
|
-
handleOnChange: HandleOnChange<T>;
|
|
26
|
-
value: T;
|
|
27
|
-
operator?: string;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const BooleanEditor = ({ handleOnChange, value: currentValue = true }: EditorProps<boolean>) => {
|
|
27
|
+
const BooleanEditor = ({ handleOnChange, value: currentValue = true }: EditorInputFieldProps<boolean>) => {
|
|
31
28
|
const [value, setValue] = useState<string>(currentValue.toString());
|
|
32
29
|
|
|
33
30
|
useEffect(() => {
|
|
@@ -65,7 +62,7 @@ const BooleanEditor = ({ handleOnChange, value: currentValue = true }: EditorPro
|
|
|
65
62
|
);
|
|
66
63
|
};
|
|
67
64
|
|
|
68
|
-
const TextEditor = ({ handleOnChange, value: currentValue = '' }:
|
|
65
|
+
const TextEditor = ({ handleOnChange, value: currentValue = '' }: EditorInputFieldProps<string>) => {
|
|
69
66
|
const [value, setValue] = useState<string>(currentValue);
|
|
70
67
|
|
|
71
68
|
const handleTextChange: ChangeEventHandler<HTMLInputElement> = (e) => {
|
|
@@ -85,7 +82,7 @@ const TextEditor = ({ handleOnChange, value: currentValue = '' }: EditorProps<st
|
|
|
85
82
|
return <EuiFieldText value={value} onChange={handleTextChange} onBlur={handleOnBlur} onKeyDown={handleOnKeyDown} />;
|
|
86
83
|
};
|
|
87
84
|
|
|
88
|
-
const NumberEditor = ({ handleOnChange,
|
|
85
|
+
const NumberEditor = ({ handleOnChange, value: currentValue }: EditorInputFieldProps<number>) => {
|
|
89
86
|
const [value, setValue] = useState<string>(currentValue?.toString() || '');
|
|
90
87
|
|
|
91
88
|
const handleNumberChange: ChangeEventHandler<HTMLInputElement> = (e) => {
|
|
@@ -94,7 +91,7 @@ const NumberEditor = ({ handleOnChange, rangeIndex, value: currentValue }: WfoRa
|
|
|
94
91
|
|
|
95
92
|
const handleOnBlur = () => {
|
|
96
93
|
const numberValue = parseFloat(value);
|
|
97
|
-
handleOnChange(numberValue
|
|
94
|
+
handleOnChange(numberValue);
|
|
98
95
|
};
|
|
99
96
|
|
|
100
97
|
const handleOnKeyDown: KeyboardEventHandler<HTMLInputElement> = (e) => {
|
|
@@ -113,7 +110,7 @@ const NumberEditor = ({ handleOnChange, rangeIndex, value: currentValue }: WfoRa
|
|
|
113
110
|
);
|
|
114
111
|
};
|
|
115
112
|
|
|
116
|
-
const DatePicker = ({ handleOnChange,
|
|
113
|
+
const DatePicker = ({ handleOnChange, value: currentValue }: EditorInputFieldProps<string>) => {
|
|
117
114
|
const [date, setDate] = useState<string>(currentValue || '');
|
|
118
115
|
const t = useTranslations('search.page');
|
|
119
116
|
|
|
@@ -123,9 +120,8 @@ const DatePicker = ({ handleOnChange, rangeIndex, value: currentValue }: WfoRang
|
|
|
123
120
|
onChange={(date) => {
|
|
124
121
|
const utcDate = date ? moment.utc(date) : undefined;
|
|
125
122
|
setDate(utcDate?.toISOString() || '');
|
|
126
|
-
handleOnChange(utcDate?.toISOString()
|
|
123
|
+
handleOnChange(utcDate?.toISOString());
|
|
127
124
|
}}
|
|
128
|
-
id={rangeIndex ? `date-range-${rangeIndex}` : 'date-range'}
|
|
129
125
|
css={{ width: '330px' }}
|
|
130
126
|
showTimeSelect
|
|
131
127
|
dateFormat="yyyy-MM-dd HH:mm"
|
|
@@ -145,27 +141,36 @@ export const WfoValueEditor = ({
|
|
|
145
141
|
value,
|
|
146
142
|
className,
|
|
147
143
|
}: ValueEditorProps) => {
|
|
144
|
+
// For components that don't take a value in addition to an operator - for example where you
|
|
145
|
+
// only choose 'Has component' or 'Does not have component' - the WfoValueEditor should not be rendered.
|
|
146
|
+
// React-query-builder handles this by default by setting the unary constant in the getOperators
|
|
147
|
+
// property of the QueryBuilder component (see WfoFilterBuilder)
|
|
148
|
+
// Because this check might not have run yet when the query is rebuild from an URL
|
|
149
|
+
// we make the check explicitly here aswell.
|
|
150
|
+
if (operator === 'null' || operator === 'notNull') {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const getComponentByType = (): EditorComponent => {
|
|
155
|
+
if (uiFieldType === UiFieldType.boolean) return BooleanEditor;
|
|
156
|
+
if (uiFieldType === UiFieldType.datetime) return DatePicker;
|
|
157
|
+
if (uiFieldType === UiFieldType.number) return NumberEditor;
|
|
158
|
+
return TextEditor;
|
|
159
|
+
};
|
|
160
|
+
|
|
148
161
|
const fieldPathInfoMap = context?.fieldPathInfoMap;
|
|
149
162
|
|
|
150
163
|
const fieldInfo = fieldPathInfoMap && fieldPathInfoMap.has(fieldName) ? fieldPathInfoMap.get(fieldName) : undefined;
|
|
151
|
-
const uiFieldType = fieldInfo?.ui_types[0] || UiFieldType.text;
|
|
164
|
+
const uiFieldType = fieldInfo?.ui_types?.[0] || UiFieldType.text;
|
|
152
165
|
|
|
153
166
|
const getEditor = () => {
|
|
154
|
-
|
|
155
|
-
return <BooleanEditor handleOnChange={handleOnChange} value={value} />;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (uiFieldType === UiFieldType.datetime) {
|
|
159
|
-
return <WfoRangeEditor handleOnChange={handleOnChange} operator={operator} Element={DatePicker} value={value} />;
|
|
160
|
-
}
|
|
167
|
+
const InputElement = getComponentByType();
|
|
161
168
|
|
|
162
|
-
if (
|
|
163
|
-
return
|
|
164
|
-
<WfoRangeEditor handleOnChange={handleOnChange} operator={operator} Element={NumberEditor} value={value} />
|
|
165
|
-
);
|
|
169
|
+
if (operator === 'between') {
|
|
170
|
+
return <WfoRangeEditor handleOnChange={handleOnChange} value={value} InputElement={InputElement} />;
|
|
166
171
|
}
|
|
167
172
|
|
|
168
|
-
return <
|
|
173
|
+
return <InputElement handleOnChange={handleOnChange} value={value} />;
|
|
169
174
|
};
|
|
170
175
|
|
|
171
176
|
const handleWrapperKeyDown: KeyboardEventHandler<HTMLDivElement> = (event) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const ORCHESTRATOR_UI_LIBRARY_VERSION = '8.7.
|
|
1
|
+
export const ORCHESTRATOR_UI_LIBRARY_VERSION = '8.7.2';
|