Skip to content

Commit

Permalink
Refactor processor form components (opensearch-project#464)
Browse files Browse the repository at this point in the history
Signed-off-by: Tyler Ohlsen <[email protected]>
  • Loading branch information
ohltyler authored Nov 6, 2024
1 parent ef463cf commit cdbeff7
Show file tree
Hide file tree
Showing 7 changed files with 293 additions and 207 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ interface MapArrayFieldProps {
valueOptions?: { label: string }[];
addMapEntryButtonText?: string;
addMapButtonText?: string;
mappingDirection?: 'sortRight' | 'sortLeft' | undefined;
}

/**
Expand Down Expand Up @@ -130,6 +131,7 @@ export function MapArrayField(props: MapArrayFieldProps) {
keyOptions={props.keyOptions}
valueOptions={props.valueOptions}
addEntryButtonText={props.addMapEntryButtonText}
mappingDirection={props.mappingDirection}
/>
</EuiPanel>
</EuiAccordion>
Expand All @@ -150,6 +152,7 @@ export function MapArrayField(props: MapArrayFieldProps) {
keyOptions={props.keyOptions}
valueOptions={props.valueOptions}
addEntryButtonText={props.addMapEntryButtonText}
mappingDirection={props.mappingDirection}
/>
</EuiPanel>
<EuiSpacer size="s" />
Expand All @@ -172,14 +175,20 @@ export function MapArrayField(props: MapArrayFieldProps) {
{'Configure'}
</EuiSmallButton>
) : (
<EuiSmallButtonEmpty
style={{ marginLeft: '-8px', marginTop: '-4px' }}
onClick={() => {
addMap(field.value);
}}
>
{props.addMapButtonText || `(Advanced) Add another map`}
</EuiSmallButtonEmpty>
<EuiPanel grow={true} paddingSize="none">
<EuiFlexItem grow={true} style={{ margin: '0px' }}>
<EuiSmallButtonEmpty
iconType="plusInCircle"
iconSide="left"
onClick={() => {
addMap(field.value);
}}
>
{props.addMapButtonText ||
`Add another map (Advanced)`}
</EuiSmallButtonEmpty>
</EuiFlexItem>
</EuiPanel>
)}
</>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import {
EuiIcon,
EuiLink,
EuiText,
EuiSmallButton,
EuiIconTip,
EuiSmallButtonEmpty,
} from '@elastic/eui';
import { Field, FieldProps, getIn, useFormikContext } from 'formik';
import { isEmpty } from 'lodash';
Expand All @@ -37,6 +37,7 @@ interface MapFieldProps {
keyOptions?: { label: string }[];
valueOptions?: { label: string }[];
addEntryButtonText?: string;
mappingDirection?: 'sortRight' | 'sortLeft' | undefined;
}

// The keys will be more static in general. Give more space for values where users
Expand All @@ -50,9 +51,13 @@ const VALUE_FLEX_RATIO = 6;
* Allow custom options as a backup/default to ensure flexibility.
*/
export function MapField(props: MapFieldProps) {
const { setFieldValue, setFieldTouched, errors, touched } = useFormikContext<
WorkflowFormValues
>();
const {
setFieldValue,
setFieldTouched,
errors,
touched,
values,
} = useFormikContext<WorkflowFormValues>();

// Adding a map entry to the end of the existing arr
function addMapEntry(curEntries: MapFormValue): void {
Expand Down Expand Up @@ -139,7 +144,28 @@ export function MapField(props: MapFieldProps) {
<>
<EuiFlexItem>
<>
{!isEmpty(props.keyOptions) ? (
{/**
* We determine if there is an interface based on if there are key options or not,
* as the options would be derived from the underlying interface.
* And if so, these values should be static.
* So, we only display the static text with no mechanism to change it's value.
* Note we still allow more entries, if a user wants to override / add custom
* keys if there is some gaps in the model interface.
*/}
{!isEmpty(props.keyOptions) &&
!isEmpty(
getIn(values, `${props.fieldPath}.${idx}.key`)
) ? (
<EuiText
size="s"
style={{ marginTop: '4px' }}
>
{getIn(
values,
`${props.fieldPath}.${idx}.key`
)}
</EuiText>
) : !isEmpty(props.keyOptions) ? (
<SelectWithCustomOptions
fieldPath={`${props.fieldPath}.${idx}.key`}
options={props.keyOptions as any[]}
Expand All @@ -163,7 +189,9 @@ export function MapField(props: MapFieldProps) {
grow={false}
style={{ marginTop: '10px' }}
>
<EuiIcon type="sortRight" />
<EuiIcon
type={props.mappingDirection || 'sortRight'}
/>
</EuiFlexItem>
</>
</EuiFlexGroup>
Expand Down Expand Up @@ -212,13 +240,16 @@ export function MapField(props: MapFieldProps) {
})}
<EuiFlexItem grow={false}>
<div>
<EuiSmallButton
<EuiSmallButtonEmpty
style={{ marginLeft: '-8px', marginTop: '0px' }}
iconType={'plusInCircle'}
iconSide="left"
onClick={() => {
addMapEntry(field.value);
}}
>
{props.addEntryButtonText || 'Add more'}
</EuiSmallButton>
</EuiSmallButtonEmpty>
</div>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ import {
ModelInterface,
IndexMappings,
PROMPT_FIELD,
MapArrayFormValue,
MapEntry,
MapFormValue,
} from '../../../../../common';
import { MapArrayField, ModelField } from '../input_fields';
import {
Expand Down Expand Up @@ -132,9 +135,27 @@ export function MLProcessorInputs(props: MLProcessorInputsProps) {
// 1: update model interface states
// 2. clear out any persisted input_map/output_map form values, as those would now be invalid
function onModelChange(modelId: string) {
setModelInterface(models[modelId]?.interface);
setFieldValue(inputMapFieldPath, []);
setFieldValue(outputMapFieldPath, []);
const newModelInterface = models[modelId]?.interface;
setModelInterface(newModelInterface);
const modelInputsAsForm = [
parseModelInputs(newModelInterface).map((modelInput) => {
return {
key: modelInput.label,
value: '',
} as MapEntry;
}) as MapFormValue,
] as MapArrayFormValue;
const modelOutputsAsForm = [
parseModelOutputs(newModelInterface).map((modelOutput) => {
return {
key: modelOutput.label,
value: '',
} as MapEntry;
}) as MapFormValue,
] as MapArrayFormValue;

setFieldValue(inputMapFieldPath, modelInputsAsForm);
setFieldValue(outputMapFieldPath, modelOutputsAsForm);
setFieldTouched(inputMapFieldPath, false);
setFieldTouched(outputMapFieldPath, false);
}
Expand Down Expand Up @@ -380,7 +401,8 @@ export function MLProcessorInputs(props: MLProcessorInputsProps) {
: indexMappingFields
}
addMapEntryButtonText="Add input"
addMapButtonText="(Advanced) Add input group"
addMapButtonText="Add input group (Advanced)"
mappingDirection="sortLeft"
/>
<EuiSpacer size="l" />
<EuiFlexGroup direction="row" justifyContent="spaceBetween">
Expand Down Expand Up @@ -415,25 +437,26 @@ export function MLProcessorInputs(props: MLProcessorInputsProps) {
fieldPath={outputMapFieldPath}
helpText={`An array specifying how to map the model’s output to new document fields. Dot notation is used by default. To explicitly use JSONPath, please ensure to prepend with the
root object selector "${JSONPATH_ROOT_SELECTOR}"`}
keyTitle={
keyTitle="Name"
keyPlaceholder="Name"
keyOptions={
fullResponsePath
? undefined
: parseModelOutputs(modelInterface, false)
}
valueTitle={
props.context === PROCESSOR_CONTEXT.SEARCH_REQUEST
? 'Query field'
: 'New document field'
}
keyPlaceholder={
valuePlaceholder={
props.context === PROCESSOR_CONTEXT.SEARCH_REQUEST
? 'Specify a query field'
: 'Define a document field'
}
valueTitle="Name"
valuePlaceholder="Name"
valueOptions={
fullResponsePath
? undefined
: parseModelOutputs(modelInterface, false)
}
addMapEntryButtonText="Add output"
addMapButtonText="(Advanced) Add output group"
addMapButtonText="Add output group (Advanced)"
mappingDirection="sortRight"
/>
<EuiSpacer size="s" />
{inputMapValue.length !== outputMapValue.length &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,8 @@ export function InputTransformModal(props: InputTransformModalProps) {
}
}}
addMapEntryButtonText="Add input"
addMapButtonText="(Advanced) Add input group"
addMapButtonText="Add input group (Advanced)"
mappingDirection="sortLeft"
/>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,23 +215,23 @@ export function OutputTransformModal(props: OutputTransformModalProps) {
fieldPath={'output_map'}
helpText={`An array specifying how to map the model’s output to new fields. Dot notation is used by default. To explicitly use JSONPath, please ensure to prepend with the
root object selector "${JSONPATH_ROOT_SELECTOR}"`}
keyTitle={
keyTitle="Name"
keyPlaceholder="Name"
keyOptions={
tempFullResponsePath
? undefined
: parseModelOutputs(props.modelInterface, false)
}
valueTitle={
props.context === PROCESSOR_CONTEXT.SEARCH_REQUEST
? 'Query field'
: 'New document field'
}
keyPlaceholder={
valuePlaceholder={
props.context === PROCESSOR_CONTEXT.SEARCH_REQUEST
? 'Specify a query field'
: 'Define a document field'
}
valueTitle="Name"
valuePlaceholder="Name"
valueOptions={
tempFullResponsePath
? undefined
: parseModelOutputs(props.modelInterface, false)
}
// If the map we are adding is the first one, populate the selected option to index 0
onMapAdd={(curArray) => {
if (isEmpty(curArray)) {
Expand All @@ -247,7 +247,8 @@ root object selector "${JSONPATH_ROOT_SELECTOR}"`}
}
}}
addMapEntryButtonText="Add output"
addMapButtonText="(Advanced) Add output group"
addMapButtonText="Add output group (Advanced)"
mappingDirection="sortRight"
/>
);

Expand Down
Loading

0 comments on commit cdbeff7

Please sign in to comment.