@orchestrator-ui/orchestrator-ui-components 8.5.0 → 8.6.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.
- package/.turbo/turbo-build.log +10 -14
- package/.turbo/turbo-lint.log +2 -4
- package/.turbo/turbo-test.log +7 -9
- package/CHANGELOG.md +6 -0
- package/dist/index.d.ts +84 -74
- package/dist/index.js +2568 -2252
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/WfoAutoExpandableTextArea/WfoAutoExpandableTextArea.tsx +54 -0
- package/src/components/WfoAutoExpandableTextArea/index.ts +1 -0
- package/src/components/WfoAutoExpandableTextArea/styles.ts +18 -0
- package/src/components/WfoPageTemplate/paths.ts +1 -0
- package/src/components/WfoTable/WfoStructuredSearchTable/WfoAddGroupAction.tsx +1 -1
- package/src/components/WfoTable/WfoStructuredSearchTable/WfoCombinatorSelector.tsx +3 -0
- package/src/components/WfoTable/WfoStructuredSearchTable/WfoFieldSelector.tsx +58 -4
- package/src/components/WfoTable/WfoStructuredSearchTable/WfoFilterBuilder.tsx +37 -28
- package/src/components/WfoTable/WfoStructuredSearchTable/WfoInlineCombinator.tsx +17 -0
- package/src/components/WfoTable/WfoStructuredSearchTable/WfoRemoveRuleAction.tsx +3 -3
- package/src/components/WfoTable/WfoStructuredSearchTable/WfoRuleGroup.tsx +6 -3
- package/src/components/WfoTable/WfoStructuredSearchTable/WfoSearchFieldWithActions.tsx +56 -0
- package/src/components/WfoTable/WfoStructuredSearchTable/WfoStructuredSearchTable.tsx +84 -81
- package/src/components/WfoTable/WfoStructuredSearchTable/styles.ts +52 -16
- package/src/components/WfoTable/WfoStructuredSearchTable/utils.ts +45 -0
- package/src/components/WfoTable/WfoTableSettingsModal/WfoTableSettingsModal.tsx +9 -0
- package/src/components/index.ts +1 -0
- package/src/configuration/version.ts +1 -1
- package/src/messages/en-GB.json +1 -0
- package/src/messages/nl-NL.json +1 -0
- package/src/pages/WfoSearchPocPage.tsx +151 -25
- package/src/types/search.ts +3 -0
package/package.json
CHANGED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
import { EuiTextArea, EuiTextAreaProps } from '@elastic/eui';
|
|
4
|
+
|
|
5
|
+
import { useWithOrchestratorTheme } from '@/hooks';
|
|
6
|
+
|
|
7
|
+
import { getStyles } from './styles';
|
|
8
|
+
|
|
9
|
+
export const WfoAutoExpandableTextArea = ({ inputRef, onChange, ...restProps }: EuiTextAreaProps) => {
|
|
10
|
+
const { autoExpandableTextAreaStyles } = useWithOrchestratorTheme(getStyles);
|
|
11
|
+
const textAreaRef = useRef<HTMLTextAreaElement | null>(null);
|
|
12
|
+
|
|
13
|
+
const adjustTextAreaHeight = (textArea: HTMLTextAreaElement | null) => {
|
|
14
|
+
if (!textArea) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
textArea.style.height = 'auto';
|
|
18
|
+
textArea.style.height = `${textArea.scrollHeight}px`;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
adjustTextAreaHeight(textAreaRef.current);
|
|
23
|
+
}, [restProps.value]);
|
|
24
|
+
|
|
25
|
+
const handleInputRef = useCallback(
|
|
26
|
+
(node: HTMLTextAreaElement | null) => {
|
|
27
|
+
textAreaRef.current = node;
|
|
28
|
+
adjustTextAreaHeight(node);
|
|
29
|
+
|
|
30
|
+
if (typeof inputRef === 'function') {
|
|
31
|
+
inputRef(node);
|
|
32
|
+
} else if (inputRef) {
|
|
33
|
+
(inputRef as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
[inputRef],
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<EuiTextArea
|
|
41
|
+
css={autoExpandableTextAreaStyles}
|
|
42
|
+
rows={1}
|
|
43
|
+
fullWidth={true}
|
|
44
|
+
isClearable={true}
|
|
45
|
+
resize={'none'}
|
|
46
|
+
{...restProps}
|
|
47
|
+
inputRef={handleInputRef}
|
|
48
|
+
onChange={(event) => {
|
|
49
|
+
adjustTextAreaHeight(event.target);
|
|
50
|
+
onChange?.(event);
|
|
51
|
+
}}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { WfoAutoExpandableTextArea } from './WfoAutoExpandableTextArea';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { css } from '@emotion/react';
|
|
2
|
+
|
|
3
|
+
import { WfoThemeHelpers } from '@/hooks';
|
|
4
|
+
|
|
5
|
+
export const getStyles = ({ theme, toSecondaryColor }: WfoThemeHelpers) => {
|
|
6
|
+
const autoExpandableTextAreaStyles = css({
|
|
7
|
+
width: '100%',
|
|
8
|
+
maxInlineSize: '100%',
|
|
9
|
+
height: 'auto',
|
|
10
|
+
overflowY: 'hidden',
|
|
11
|
+
resize: 'none',
|
|
12
|
+
border: `thin solid ${toSecondaryColor(theme.colors.borderBasePlain)}`,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
autoExpandableTextAreaStyles,
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -3,6 +3,7 @@ export const PATH_START_NEW_WORKFLOW = '/workflows/new';
|
|
|
3
3
|
export const PATH_START_NEW_TASK = '/tasks/new';
|
|
4
4
|
export const PATH_WORKFLOWS = '/workflows';
|
|
5
5
|
export const PATH_SUBSCRIPTIONS = '/subscriptions';
|
|
6
|
+
export const PATH_SUBSCRIPTIONS_BETA = '/beta-subscriptions';
|
|
6
7
|
export const PATH_METADATA = '/metadata';
|
|
7
8
|
export const PATH_METADATA_PRODUCTS = '/metadata/products';
|
|
8
9
|
export const PATH_METADATA_PRODUCT_BLOCKS = '/metadata/productblocks';
|
|
@@ -12,7 +12,7 @@ export const WfoAddGroupAction = ({ disabled, handleOnClick }: ActionProps) => {
|
|
|
12
12
|
const t = useTranslations('search.page');
|
|
13
13
|
const { addGroupStyles, addRulePlusStyles } = useWithOrchestratorTheme(getWfoStructuredSearchTableStyles);
|
|
14
14
|
return disabled ? null : (
|
|
15
|
-
<EuiFlexItem css={addGroupStyles} onClick={() => handleOnClick()}>
|
|
15
|
+
<EuiFlexItem grow={true} css={addGroupStyles} onClick={() => handleOnClick()}>
|
|
16
16
|
<span css={addRulePlusStyles}>+</span> {t('addGroup')}
|
|
17
17
|
</EuiFlexItem>
|
|
18
18
|
);
|
|
@@ -8,6 +8,9 @@ import { useWithOrchestratorTheme } from '@/hooks';
|
|
|
8
8
|
|
|
9
9
|
export const WfoCombinatorSelector = (props: CombinatorSelectorProps) => {
|
|
10
10
|
const { buttonGroupStyles } = useWithOrchestratorTheme(getWfoStructuredSearchTableStyles);
|
|
11
|
+
|
|
12
|
+
if (props.rules.length < 2) return null;
|
|
13
|
+
|
|
11
14
|
const options = props.options.map((option) => ({
|
|
12
15
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
13
16
|
// @ts-ignore This seems to be a typing error in the react-querybuilde library. Option.name does exist
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { FieldSelectorProps } from 'react-querybuilder';
|
|
3
3
|
|
|
4
4
|
import { useTranslations } from 'next-intl';
|
|
@@ -7,16 +7,21 @@ import type { EuiComboBoxOptionOption } from '@elastic/eui';
|
|
|
7
7
|
import { EuiComboBox } from '@elastic/eui';
|
|
8
8
|
|
|
9
9
|
import { usePathAutocomplete } from '@/hooks';
|
|
10
|
-
import { EntityKind, PathInfo } from '@/types';
|
|
10
|
+
import { EntityKind, FieldToOperatorMap, PathInfo } from '@/types';
|
|
11
11
|
|
|
12
12
|
export const WfoFieldSelector = ({ handleOnChange, disabled, rule, context }: FieldSelectorProps) => {
|
|
13
13
|
const { field } = rule;
|
|
14
|
+
const prefilledFieldOptions: FieldToOperatorMap = context.prefilledFieldOptions;
|
|
14
15
|
const [selectedValue, setSelectedValue] = useState<string>(field);
|
|
16
|
+
const [searchInput, setSearchInput] = useState<HTMLInputElement | null>(null);
|
|
17
|
+
const optionsRef = useRef<EuiComboBoxOptionOption<string>[]>([]);
|
|
18
|
+
const handleFieldSelectionRef = useRef<(selected: EuiComboBoxOptionOption<string>[]) => void>(() => {});
|
|
15
19
|
const t = useTranslations('search.page');
|
|
16
20
|
const getOption = (path: string) => ({
|
|
17
21
|
value: path,
|
|
18
22
|
label: path,
|
|
19
23
|
});
|
|
24
|
+
|
|
20
25
|
const getOptionsFromPathInfo = (pathInfos: PathInfo[]): EuiComboBoxOptionOption<string>[] => {
|
|
21
26
|
const pathOptions: EuiComboBoxOptionOption<string>[] = [];
|
|
22
27
|
|
|
@@ -40,14 +45,26 @@ export const WfoFieldSelector = ({ handleOnChange, disabled, rule, context }: Fi
|
|
|
40
45
|
error: errorMessage,
|
|
41
46
|
} = usePathAutocomplete(selectedValue, EntityKind.SUBSCRIPTION);
|
|
42
47
|
|
|
43
|
-
const
|
|
48
|
+
const prefilledOptions: EuiComboBoxOptionOption<string>[] = Array.from(prefilledFieldOptions.keys()).map(getOption);
|
|
49
|
+
const autocompleteOptions = getOptionsFromPathInfo(paths);
|
|
50
|
+
const placeholderOption: EuiComboBoxOptionOption<string> = {
|
|
51
|
+
label: '──────',
|
|
52
|
+
disabled: true,
|
|
53
|
+
};
|
|
54
|
+
const showPlaceholder = prefilledOptions.length > 0 && autocompleteOptions.length > 0;
|
|
55
|
+
const options: EuiComboBoxOptionOption<string>[] = [
|
|
56
|
+
...prefilledOptions,
|
|
57
|
+
...(showPlaceholder ? [placeholderOption] : []),
|
|
58
|
+
...autocompleteOptions,
|
|
59
|
+
];
|
|
44
60
|
|
|
45
61
|
const storeFieldOperators = (selectedValue: string) => {
|
|
46
62
|
const matchingPath =
|
|
47
63
|
paths.find((path) => path.path === selectedValue)
|
|
48
64
|
?? paths.find((path) => path.availablePaths?.includes(selectedValue));
|
|
65
|
+
const operators = matchingPath?.operators ?? prefilledFieldOptions.get(selectedValue) ?? [];
|
|
49
66
|
|
|
50
|
-
context?.onFieldSelected?.(selectedValue,
|
|
67
|
+
context?.onFieldSelected?.(selectedValue, operators);
|
|
51
68
|
};
|
|
52
69
|
|
|
53
70
|
const handleFieldSelection = (selectedOptions: EuiComboBoxOptionOption<string>[]) => {
|
|
@@ -59,6 +76,42 @@ export const WfoFieldSelector = ({ handleOnChange, disabled, rule, context }: Fi
|
|
|
59
76
|
handleOnChange(selectedValue);
|
|
60
77
|
};
|
|
61
78
|
|
|
79
|
+
// EuiComboBox only auto-selects on Enter/Tab when exactly one option matches the typed
|
|
80
|
+
// text. When several options share the typed prefix, the exact-match option is not picked
|
|
81
|
+
// unless the user arrow-navigates. Patch that with a native keydown listener on the input.
|
|
82
|
+
optionsRef.current = options;
|
|
83
|
+
handleFieldSelectionRef.current = handleFieldSelection;
|
|
84
|
+
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
if (!searchInput) return;
|
|
87
|
+
|
|
88
|
+
const autoSelectExactMatchOption = (event: KeyboardEvent) => {
|
|
89
|
+
if (event.key !== 'Enter' && event.key !== 'Tab') return;
|
|
90
|
+
// Let EuiComboBox handle selection when an option is keyboard-highlighted.
|
|
91
|
+
if (searchInput.getAttribute('aria-activedescendant')) return;
|
|
92
|
+
const typed = searchInput.value.trim();
|
|
93
|
+
if (!typed) return;
|
|
94
|
+
const exactMatch = optionsRef.current.find(
|
|
95
|
+
(option) => !option.disabled && option.label.toLowerCase() === typed.toLowerCase(),
|
|
96
|
+
);
|
|
97
|
+
if (!exactMatch) return;
|
|
98
|
+
if (event.key === 'Enter') event.preventDefault();
|
|
99
|
+
handleFieldSelectionRef.current([exactMatch]);
|
|
100
|
+
|
|
101
|
+
// EuiComboBox keeps its own internal `searchValue` and `isListOpen` state. Clearing
|
|
102
|
+
// the value via the React-recognised native setter + input event suppresses EUI's
|
|
103
|
+
// "typed-but-not-selected" warning icon (the `markAsInvalid` branch in combo_box.js).
|
|
104
|
+
// The synthetic Escape closes the dropdown without disturbing focus.
|
|
105
|
+
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')?.set;
|
|
106
|
+
nativeInputValueSetter?.call(searchInput, '');
|
|
107
|
+
searchInput.dispatchEvent(new Event('input', { bubbles: true }));
|
|
108
|
+
searchInput.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
searchInput.addEventListener('keydown', autoSelectExactMatchOption);
|
|
112
|
+
return () => searchInput.removeEventListener('keydown', autoSelectExactMatchOption);
|
|
113
|
+
}, [searchInput]);
|
|
114
|
+
|
|
62
115
|
return (
|
|
63
116
|
<EuiComboBox
|
|
64
117
|
placeholder={t('searchFieldsPlaceholder')}
|
|
@@ -73,6 +126,7 @@ export const WfoFieldSelector = ({ handleOnChange, disabled, rule, context }: Fi
|
|
|
73
126
|
setSelectedValue(inputValue);
|
|
74
127
|
}
|
|
75
128
|
}}
|
|
129
|
+
inputRef={setSearchInput}
|
|
76
130
|
singleSelection={{ asPlainText: true }}
|
|
77
131
|
isLoading={isLoading}
|
|
78
132
|
isClearable
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
|
-
import { FullOperator, QueryBuilder, type RuleGroupType } from 'react-querybuilder';
|
|
2
|
+
import { FullOperator, QueryBuilder, type RuleGroupType, generateID } from 'react-querybuilder';
|
|
3
3
|
import 'react-querybuilder/dist/query-builder.css';
|
|
4
4
|
|
|
5
5
|
import { useTranslations } from 'next-intl';
|
|
6
6
|
|
|
7
|
-
import { EuiButton, EuiFlexGroup, EuiFlexItem
|
|
7
|
+
import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
|
8
8
|
|
|
9
|
-
import { SearchParams, WfoTextAnchor } from '@/components';
|
|
9
|
+
import { SearchParams, WfoAutoExpandableTextArea, WfoTextAnchor } from '@/components';
|
|
10
10
|
import { WfoCombinatorSelector } from '@/components/WfoTable/WfoStructuredSearchTable/WfoCombinatorSelector';
|
|
11
11
|
import { useWithOrchestratorTheme } from '@/hooks';
|
|
12
|
-
import { OperatorDisplay
|
|
12
|
+
import { OperatorDisplay } from '@/types';
|
|
13
|
+
import type { FieldToOperatorMap } from '@/types';
|
|
13
14
|
|
|
14
15
|
import { WfoFieldSelector } from './WfoFieldSelector';
|
|
16
|
+
import { WfoInlineCombinator } from './WfoInlineCombinator';
|
|
15
17
|
import { WfoOperatorSelector } from './WfoOperatorSelector';
|
|
16
18
|
import { WfoRemoveRuleAction } from './WfoRemoveRuleAction';
|
|
17
19
|
import { WfoRule } from './WfoRule';
|
|
@@ -48,7 +50,6 @@ const OPERATOR_MAP: Record<string, OperatorDisplay> = {
|
|
|
48
50
|
/* TODO: Add the missing operators
|
|
49
51
|
['has_component', 'not_has_component'];
|
|
50
52
|
*/
|
|
51
|
-
type FieldPathInfoMap = Map<string, PathInfo>;
|
|
52
53
|
|
|
53
54
|
interface WfoFilterBuilderProps {
|
|
54
55
|
filterString?: string;
|
|
@@ -57,6 +58,9 @@ interface WfoFilterBuilderProps {
|
|
|
57
58
|
queryBuilderRuleGroup?: RuleGroupType;
|
|
58
59
|
onUpdateQueryBuilder: (ruleGroup: RuleGroupType | false) => void;
|
|
59
60
|
handleSearch: (searchParams?: SearchParams) => void;
|
|
61
|
+
isFilterBuilderVisible: boolean;
|
|
62
|
+
onToggleFilterBuilder: (isVisible: boolean) => void;
|
|
63
|
+
prefilledFieldOptions: FieldToOperatorMap;
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
const initialRuleGroup: RuleGroupType = {
|
|
@@ -65,6 +69,11 @@ const initialRuleGroup: RuleGroupType = {
|
|
|
65
69
|
combinator: 'and',
|
|
66
70
|
};
|
|
67
71
|
|
|
72
|
+
const onAddGroupHandler = (ruleGroup: RuleGroupType): RuleGroupType => {
|
|
73
|
+
const [firstRule] = ruleGroup.rules;
|
|
74
|
+
return firstRule ? { ...ruleGroup, rules: [...ruleGroup.rules, { ...firstRule, id: generateID() }] } : ruleGroup;
|
|
75
|
+
};
|
|
76
|
+
|
|
68
77
|
export const WfoFilterBuilder = ({
|
|
69
78
|
filterString,
|
|
70
79
|
onUpdateFilterString,
|
|
@@ -72,9 +81,12 @@ export const WfoFilterBuilder = ({
|
|
|
72
81
|
queryBuilderRuleGroup = initialRuleGroup,
|
|
73
82
|
onUpdateQueryBuilder,
|
|
74
83
|
handleSearch,
|
|
84
|
+
prefilledFieldOptions,
|
|
85
|
+
isFilterBuilderVisible,
|
|
86
|
+
onToggleFilterBuilder,
|
|
75
87
|
}: WfoFilterBuilderProps) => {
|
|
76
|
-
const
|
|
77
|
-
return (
|
|
88
|
+
const mapOperatorsToRQBOperatorOptions = (operators?: string[]): FullOperator[] => {
|
|
89
|
+
return (operators ?? []).map((operator) => {
|
|
78
90
|
const { symbol, description } = OPERATOR_MAP[operator] || { symbol: operator, description: operator };
|
|
79
91
|
const rqbOperator = SEARCH_OPERATOR_TO_RQB_OPERATOR_MAP[operator] ?? operator;
|
|
80
92
|
return { name: rqbOperator, label: `${symbol} ${description}`, value: rqbOperator };
|
|
@@ -82,34 +94,32 @@ export const WfoFilterBuilder = ({
|
|
|
82
94
|
};
|
|
83
95
|
|
|
84
96
|
const t = useTranslations('common');
|
|
85
|
-
const { queryBuilderContainerStyles, toggleButtonStyles
|
|
97
|
+
const { queryBuilderContainerStyles, toggleButtonStyles } = useWithOrchestratorTheme(
|
|
86
98
|
getWfoStructuredSearchTableStyles,
|
|
87
99
|
);
|
|
88
|
-
const [
|
|
89
|
-
const [fieldPathInfoMap, setFieldPathInfoMap] = useState<FieldPathInfoMap>(new Map());
|
|
100
|
+
const [fieldToOperatorMap, setFieldToOperatorMap] = useState<FieldToOperatorMap>(prefilledFieldOptions);
|
|
90
101
|
|
|
91
|
-
const handleFieldSelected = (field: string,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
});
|
|
96
|
-
}
|
|
102
|
+
const handleFieldSelected = (field: string, operators: string[]) => {
|
|
103
|
+
setFieldToOperatorMap((previousMap) => {
|
|
104
|
+
return new Map(previousMap).set(field, operators);
|
|
105
|
+
});
|
|
97
106
|
};
|
|
98
107
|
|
|
99
108
|
return (
|
|
100
|
-
<EuiFlexGroup css={queryBuilderContainerStyles}>
|
|
109
|
+
<EuiFlexGroup css={isFilterBuilderVisible ? queryBuilderContainerStyles : undefined}>
|
|
101
110
|
{(isFilterBuilderVisible && (
|
|
102
111
|
<EuiFlexGroup direction={'column'}>
|
|
103
112
|
<EuiFlexItem>
|
|
104
113
|
<QueryBuilder
|
|
105
114
|
query={queryBuilderRuleGroup}
|
|
115
|
+
enableMountQueryChange={false}
|
|
106
116
|
onQueryChange={(ruleGroup: RuleGroupType) => {
|
|
107
117
|
onUpdateQueryBuilder(ruleGroup);
|
|
108
118
|
}}
|
|
109
|
-
context={{ onFieldSelected: handleFieldSelected,
|
|
119
|
+
context={{ onFieldSelected: handleFieldSelected, prefilledFieldOptions }}
|
|
110
120
|
getOperators={(field) => {
|
|
111
|
-
const
|
|
112
|
-
return
|
|
121
|
+
const operators = fieldToOperatorMap.get(field);
|
|
122
|
+
return mapOperatorsToRQBOperatorOptions(operators);
|
|
113
123
|
}}
|
|
114
124
|
controlElements={{
|
|
115
125
|
fieldSelector: WfoFieldSelector,
|
|
@@ -118,27 +128,26 @@ export const WfoFilterBuilder = ({
|
|
|
118
128
|
ruleGroup: WfoRuleGroup,
|
|
119
129
|
rule: WfoRule,
|
|
120
130
|
combinatorSelector: WfoCombinatorSelector,
|
|
131
|
+
inlineCombinator: WfoInlineCombinator,
|
|
121
132
|
addRuleAction: null,
|
|
122
133
|
addGroupAction: null,
|
|
123
134
|
removeGroupAction: null,
|
|
124
135
|
removeRuleAction: WfoRemoveRuleAction,
|
|
125
136
|
}}
|
|
126
137
|
addRuleToNewGroups
|
|
138
|
+
onAddGroup={onAddGroupHandler}
|
|
127
139
|
maxLevels={5}
|
|
140
|
+
showCombinatorsBetweenRules
|
|
128
141
|
/>
|
|
129
142
|
</EuiFlexItem>
|
|
130
143
|
<EuiFlexItem>
|
|
131
|
-
<
|
|
132
|
-
css={textAreaStyles}
|
|
144
|
+
<WfoAutoExpandableTextArea
|
|
133
145
|
id={'searchbox-textarea'}
|
|
134
|
-
value={filterString}
|
|
146
|
+
value={filterString ?? ''}
|
|
135
147
|
onChange={(e) => {
|
|
136
148
|
const filterString = e.target.value;
|
|
137
149
|
onUpdateFilterString(filterString);
|
|
138
150
|
}}
|
|
139
|
-
fullWidth={true}
|
|
140
|
-
isClearable={true}
|
|
141
|
-
resize={'vertical'}
|
|
142
151
|
isInvalid={!isValidFilterString}
|
|
143
152
|
/>
|
|
144
153
|
</EuiFlexItem>
|
|
@@ -164,7 +173,7 @@ export const WfoFilterBuilder = ({
|
|
|
164
173
|
// we call with ruleGroup: false explictly to
|
|
165
174
|
// avoid state not having caught up yet when searching
|
|
166
175
|
handleSearch({ ruleGroup: false });
|
|
167
|
-
|
|
176
|
+
onToggleFilterBuilder(false);
|
|
168
177
|
}}
|
|
169
178
|
/>
|
|
170
179
|
</EuiFlexGroup>
|
|
@@ -172,7 +181,7 @@ export const WfoFilterBuilder = ({
|
|
|
172
181
|
)) || (
|
|
173
182
|
<EuiButton
|
|
174
183
|
css={toggleButtonStyles}
|
|
175
|
-
onClick={() =>
|
|
184
|
+
onClick={() => onToggleFilterBuilder(true)}
|
|
176
185
|
id={'button-toggle-filter-builder'}
|
|
177
186
|
data-test-id={'button-toggle-filter-builder'}
|
|
178
187
|
fill
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { CombinatorSelectorProps } from 'react-querybuilder';
|
|
3
|
+
|
|
4
|
+
import { getWfoStructuredSearchTableStyles } from '@/components/WfoTable/WfoStructuredSearchTable/styles';
|
|
5
|
+
import { useWithOrchestratorTheme } from '@/hooks';
|
|
6
|
+
|
|
7
|
+
import { WfoCombinatorSelector } from './WfoCombinatorSelector';
|
|
8
|
+
|
|
9
|
+
export const WfoInlineCombinator = (props: CombinatorSelectorProps) => {
|
|
10
|
+
const { inlineCombinatorStyles } = useWithOrchestratorTheme(getWfoStructuredSearchTableStyles);
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<div css={inlineCombinatorStyles}>
|
|
14
|
+
<WfoCombinatorSelector {...props} />
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
@@ -6,15 +6,15 @@ import { useTranslations } from 'next-intl';
|
|
|
6
6
|
import { EuiFlexItem } from '@elastic/eui';
|
|
7
7
|
|
|
8
8
|
import { useOrchestratorTheme } from '@/hooks';
|
|
9
|
-
import {
|
|
9
|
+
import { WfoTrashFilled } from '@/icons';
|
|
10
10
|
|
|
11
11
|
export const WfoRemoveRuleAction = (props: ActionProps) => {
|
|
12
12
|
const { theme } = useOrchestratorTheme();
|
|
13
13
|
|
|
14
14
|
const t = useTranslations('search.page');
|
|
15
15
|
return (
|
|
16
|
-
<EuiFlexItem onClick={props.handleOnClick} css={{ cursor: 'pointer' }}>
|
|
17
|
-
<
|
|
16
|
+
<EuiFlexItem onClick={props.handleOnClick} css={{ cursor: 'pointer', paddingRight: theme.size.s }}>
|
|
17
|
+
<WfoTrashFilled color={theme.colors.textPrimary} aria-label={t('removeRule')} />
|
|
18
18
|
</EuiFlexItem>
|
|
19
19
|
);
|
|
20
20
|
};
|
|
@@ -20,6 +20,7 @@ export const WfoRuleGroup = (props: RuleGroupProps) => {
|
|
|
20
20
|
ruleGroupContainerWhiteStyles,
|
|
21
21
|
innerGroupContainerWhiteStyles,
|
|
22
22
|
innerGroupContainerBlueStyles,
|
|
23
|
+
ruleGroupBodyGridStyles,
|
|
23
24
|
} = useWithOrchestratorTheme(getWfoStructuredSearchTableStyles);
|
|
24
25
|
const getGroupContainerStyles = () => {
|
|
25
26
|
if (ruleGroupProps.path.length % 2) {
|
|
@@ -32,16 +33,18 @@ export const WfoRuleGroup = (props: RuleGroupProps) => {
|
|
|
32
33
|
const { addRule, path, schema, disabled, ruleGroup, addGroup } = ruleGroupProps;
|
|
33
34
|
|
|
34
35
|
return (
|
|
35
|
-
<EuiFlexGroup gutterSize={'none'} alignItems="center">
|
|
36
|
+
<EuiFlexGroup gutterSize={'none'} responsive={false} alignItems="center">
|
|
36
37
|
<EuiFlexItem>
|
|
37
|
-
<EuiFlexGroup direction="column"
|
|
38
|
+
<EuiFlexGroup direction="column" css={getGroupContainerStyles()}>
|
|
38
39
|
<EuiFlexItem>
|
|
39
40
|
<EuiFlexGroup gutterSize="none">
|
|
40
41
|
<RuleGroupHeaderComponents {...ruleGroupProps} />
|
|
41
42
|
</EuiFlexGroup>
|
|
42
43
|
</EuiFlexItem>
|
|
43
44
|
<EuiFlexItem>
|
|
44
|
-
<
|
|
45
|
+
<div css={ruleGroupBodyGridStyles}>
|
|
46
|
+
<RuleGroupBodyComponents {...ruleGroupProps} />
|
|
47
|
+
</div>
|
|
45
48
|
</EuiFlexItem>
|
|
46
49
|
<EuiFlexItem>
|
|
47
50
|
<WfoAddRuleAction
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { useTranslations } from 'next-intl';
|
|
4
|
+
|
|
5
|
+
import { EuiButtonIcon, EuiFieldSearch, EuiFlexItem, EuiFormRow } from '@elastic/eui';
|
|
6
|
+
|
|
7
|
+
import { useWithOrchestratorTheme } from '@/hooks';
|
|
8
|
+
import { getFormFieldsBaseStyle } from '@/theme';
|
|
9
|
+
|
|
10
|
+
export type SearchFieldWithActionsProps = {
|
|
11
|
+
queryText?: string;
|
|
12
|
+
onChangeQueryText: (queryText: string) => void;
|
|
13
|
+
onSearchQueryText: (queryText: string) => void;
|
|
14
|
+
onShowInformation: () => void;
|
|
15
|
+
onShowTableSettings: () => void;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Search field with the info and table-settings actions, rendered as EuiFlexItems inside an EuiFlexGroup.
|
|
19
|
+
export const WfoSearchFieldWithActions = ({
|
|
20
|
+
queryText,
|
|
21
|
+
onChangeQueryText,
|
|
22
|
+
onSearchQueryText,
|
|
23
|
+
onShowInformation,
|
|
24
|
+
onShowTableSettings,
|
|
25
|
+
}: SearchFieldWithActionsProps) => {
|
|
26
|
+
const t = useTranslations('common');
|
|
27
|
+
const { formFieldBaseStyle } = useWithOrchestratorTheme(getFormFieldsBaseStyle);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<>
|
|
31
|
+
<EuiFlexItem>
|
|
32
|
+
<EuiFormRow fullWidth>
|
|
33
|
+
<EuiFieldSearch
|
|
34
|
+
css={formFieldBaseStyle}
|
|
35
|
+
value={queryText}
|
|
36
|
+
placeholder={`${t('search')}...`}
|
|
37
|
+
onChange={(e) => onChangeQueryText(e.target.value)}
|
|
38
|
+
onSearch={(queryText) => onSearchQueryText(queryText)}
|
|
39
|
+
fullWidth
|
|
40
|
+
/>
|
|
41
|
+
</EuiFormRow>
|
|
42
|
+
</EuiFlexItem>
|
|
43
|
+
<EuiFlexItem grow={false}>
|
|
44
|
+
<EuiButtonIcon
|
|
45
|
+
onClick={onShowInformation}
|
|
46
|
+
iconSize={'l'}
|
|
47
|
+
iconType={'info'}
|
|
48
|
+
aria-label={t('searchModalTitle')}
|
|
49
|
+
/>
|
|
50
|
+
</EuiFlexItem>
|
|
51
|
+
<EuiFlexItem grow={false}>
|
|
52
|
+
<EuiButtonIcon onClick={onShowTableSettings} iconSize={'l'} iconType={'gear'} aria-label={t('tableSettings')} />
|
|
53
|
+
</EuiFlexItem>
|
|
54
|
+
</>
|
|
55
|
+
);
|
|
56
|
+
};
|