5
5
6
6
import React , { useState , useEffect } from 'react' ;
7
7
import { getIn , useFormikContext } from 'formik' ;
8
+ import { isEmpty } from 'lodash' ;
8
9
import { useSelector } from 'react-redux' ;
10
+ import { flattie } from 'flattie' ;
9
11
import {
10
12
EuiAccordion ,
11
13
EuiSmallButtonEmpty ,
@@ -25,14 +27,15 @@ import {
25
27
ML_INFERENCE_DOCS_LINK ,
26
28
WorkflowFormValues ,
27
29
ModelInterface ,
30
+ IndexMappings ,
28
31
} from '../../../../../common' ;
29
32
import { MapArrayField , ModelField } from '../input_fields' ;
30
- import { isEmpty } from 'lodash' ;
31
33
import { InputTransformModal } from './input_transform_modal' ;
32
34
import { OutputTransformModal } from './output_transform_modal' ;
33
- import { AppState } from '../../../../store' ;
35
+ import { AppState , getMappings , useAppDispatch } from '../../../../store' ;
34
36
import {
35
37
formikToPartialPipeline ,
38
+ getDataSourceId ,
36
39
parseModelInputs ,
37
40
parseModelOutputs ,
38
41
} from '../../../../utils' ;
@@ -52,7 +55,10 @@ interface MLProcessorInputsProps {
52
55
* output map configuration forms, respectively.
53
56
*/
54
57
export function MLProcessorInputs ( props : MLProcessorInputsProps ) {
58
+ const dispatch = useAppDispatch ( ) ;
59
+ const dataSourceId = getDataSourceId ( ) ;
55
60
const models = useSelector ( ( state : AppState ) => state . ml . models ) ;
61
+ const indices = useSelector ( ( state : AppState ) => state . opensearch . indices ) ;
56
62
const { values, setFieldValue, setFieldTouched } = useFormikContext <
57
63
WorkflowFormValues
58
64
> ( ) ;
@@ -115,7 +121,7 @@ export function MLProcessorInputs(props: MLProcessorInputsProps) {
115
121
// 1: update model interface states
116
122
// 2. clear out any persisted input_map/output_map form values, as those would now be invalid
117
123
function onModelChange ( modelId : string ) {
118
- updateModelInterfaceStates ( modelId ) ;
124
+ setModelInterface ( models [ modelId ] ?. interface ) ;
119
125
setFieldValue ( inputMapFieldPath , [ ] ) ;
120
126
setFieldValue ( outputMapFieldPath , [ ] ) ;
121
127
setFieldTouched ( inputMapFieldPath , false ) ;
@@ -127,16 +133,75 @@ export function MLProcessorInputs(props: MLProcessorInputsProps) {
127
133
if ( ! isEmpty ( models ) ) {
128
134
const modelId = getIn ( values , `${ modelFieldPath } .id` ) ;
129
135
if ( modelId ) {
130
- updateModelInterfaceStates ( modelId ) ;
136
+ setModelInterface ( models [ modelId ] ?. interface ) ;
131
137
}
132
138
}
133
139
} , [ models ] ) ;
134
140
135
- // reusable function to update interface states based on the model ID
136
- function updateModelInterfaceStates ( modelId : string ) {
137
- const newSelectedModel = models [ modelId ] ;
138
- setModelInterface ( newSelectedModel ?. interface ) ;
139
- }
141
+ // persisting doc/query/index mapping fields to collect a list
142
+ // of options to display in the dropdowns when configuring input / output maps
143
+ const [ docFields , setDocFields ] = useState < { label : string } [ ] > ( [ ] ) ;
144
+ const [ queryFields , setQueryFields ] = useState < { label : string } [ ] > ( [ ] ) ;
145
+ const [ indexMappingFields , setIndexMappingFields ] = useState <
146
+ { label : string } [ ]
147
+ > ( [ ] ) ;
148
+ useEffect ( ( ) => {
149
+ try {
150
+ const docObjKeys = Object . keys (
151
+ flattie ( ( JSON . parse ( values . ingest . docs ) as { } [ ] ) [ 0 ] )
152
+ ) ;
153
+ if ( docObjKeys . length > 0 ) {
154
+ setDocFields (
155
+ docObjKeys . map ( ( key ) => {
156
+ return {
157
+ label : key ,
158
+ } ;
159
+ } )
160
+ ) ;
161
+ }
162
+ } catch { }
163
+ } , [ values ?. ingest ?. docs ] ) ;
164
+ useEffect ( ( ) => {
165
+ try {
166
+ const queryObjKeys = Object . keys (
167
+ flattie ( JSON . parse ( values . search . request ) )
168
+ ) ;
169
+ if ( queryObjKeys . length > 0 ) {
170
+ setQueryFields (
171
+ queryObjKeys . map ( ( key ) => {
172
+ return {
173
+ label : key ,
174
+ } ;
175
+ } )
176
+ ) ;
177
+ }
178
+ } catch { }
179
+ } , [ values ?. search ?. request ] ) ;
180
+ useEffect ( ( ) => {
181
+ const indexName = values ?. search ?. index ?. name as string | undefined ;
182
+ if ( indexName !== undefined && indices [ indexName ] !== undefined ) {
183
+ dispatch (
184
+ getMappings ( {
185
+ index : indexName ,
186
+ dataSourceId,
187
+ } )
188
+ )
189
+ . unwrap ( )
190
+ . then ( ( resp : IndexMappings ) => {
191
+ const mappingsObjKeys = Object . keys ( resp . properties ) ;
192
+ if ( mappingsObjKeys . length > 0 ) {
193
+ setIndexMappingFields (
194
+ mappingsObjKeys . map ( ( key ) => {
195
+ return {
196
+ label : key ,
197
+ type : resp . properties [ key ] ?. type ,
198
+ } ;
199
+ } )
200
+ ) ;
201
+ }
202
+ } ) ;
203
+ }
204
+ } , [ values ?. search ?. index ?. name ] ) ;
140
205
141
206
return (
142
207
< >
@@ -148,6 +213,13 @@ export function MLProcessorInputs(props: MLProcessorInputsProps) {
148
213
inputMapField = { inputMapField }
149
214
inputMapFieldPath = { inputMapFieldPath }
150
215
modelInterface = { modelInterface }
216
+ valueOptions = {
217
+ props . context === PROCESSOR_CONTEXT . INGEST
218
+ ? docFields
219
+ : props . context === PROCESSOR_CONTEXT . SEARCH_REQUEST
220
+ ? queryFields
221
+ : indexMappingFields
222
+ }
151
223
onClose = { ( ) => setIsInputTransformModalOpen ( false ) }
152
224
/>
153
225
) }
@@ -212,12 +284,19 @@ export function MLProcessorInputs(props: MLProcessorInputsProps) {
212
284
root object selector "${ JSONPATH_ROOT_SELECTOR } "` }
213
285
helpLink = { ML_INFERENCE_DOCS_LINK }
214
286
keyPlaceholder = "Model input field"
287
+ keyOptions = { parseModelInputs ( modelInterface ) }
215
288
valuePlaceholder = {
216
289
props . context === PROCESSOR_CONTEXT . SEARCH_REQUEST
217
290
? 'Query field'
218
291
: 'Document field'
219
292
}
220
- keyOptions = { parseModelInputs ( modelInterface ) }
293
+ valueOptions = {
294
+ props . context === PROCESSOR_CONTEXT . INGEST
295
+ ? docFields
296
+ : props . context === PROCESSOR_CONTEXT . SEARCH_REQUEST
297
+ ? queryFields
298
+ : indexMappingFields
299
+ }
221
300
/>
222
301
< EuiSpacer size = "l" />
223
302
< EuiFlexGroup direction = "row" >
@@ -262,7 +341,7 @@ export function MLProcessorInputs(props: MLProcessorInputsProps) {
262
341
keyPlaceholder = {
263
342
props . context === PROCESSOR_CONTEXT . SEARCH_REQUEST
264
343
? 'Query field'
265
- : 'Document field'
344
+ : 'New document field'
266
345
}
267
346
valuePlaceholder = "Model output field"
268
347
valueOptions = { parseModelOutputs ( modelInterface ) }
0 commit comments