@@ -31,6 +31,7 @@ import {
31
31
IndexMappings ,
32
32
InputMapEntry ,
33
33
InputMapFormValue ,
34
+ Transform ,
34
35
TRANSFORM_TYPE ,
35
36
EMPTY_INPUT_MAP_ENTRY ,
36
37
WorkflowConfig ,
@@ -98,6 +99,16 @@ export function ModelInputs(props: ModelInputsProps) {
98
99
ModelInterface | undefined
99
100
> ( undefined ) ;
100
101
102
+ // get the model interface based on the selected ID and list of known models
103
+ useEffect ( ( ) => {
104
+ if ( ! isEmpty ( models ) ) {
105
+ const modelId = getIn ( values , modelFieldPath ) ?. id ;
106
+ if ( modelId ) {
107
+ setModelInterface ( models [ modelId ] ?. interface ) ;
108
+ }
109
+ }
110
+ } , [ models , getIn ( values , modelFieldPath ) ?. id ] ) ;
111
+
101
112
// various modal states
102
113
const [ templateModalIdx , setTemplateModalIdx ] = useState < number | undefined > (
103
114
undefined
@@ -106,15 +117,70 @@ export function ModelInputs(props: ModelInputsProps) {
106
117
number | undefined
107
118
> ( undefined ) ;
108
119
109
- // get the model interface based on the selected ID and list of known models
120
+ const [ debouncedInputMap , setDebouncedInputMap ] = useState < any > ( ) ;
110
121
useEffect ( ( ) => {
111
- if ( ! isEmpty ( models ) ) {
112
- const modelId = getIn ( values , modelFieldPath ) ?. id ;
113
- if ( modelId ) {
114
- setModelInterface ( models [ modelId ] ?. interface ) ;
115
- }
122
+ // Set a timeout to update debounced value after 500ms
123
+ const handler = setTimeout ( ( ) => {
124
+ setDebouncedInputMap ( getIn ( values , inputMapFieldPath ) ) ;
125
+ } , 500 ) ;
126
+
127
+ // Cleanup the timeout if `query` changes before 500ms
128
+ return ( ) => {
129
+ clearTimeout ( handler ) ;
130
+ } ;
131
+ } , [ getIn ( values , inputMapFieldPath ) ] ) ;
132
+
133
+ // TODO: this works ok, but does not allow clearing out any form value, or it resets to the last-known/cached value.
134
+ // need to filter out on this use case.
135
+
136
+ // Temporarily cache any configured transformations for different transform types.
137
+ // For example, if a user configures a prompt, swaps the transform
138
+ // type to "Data field", and swaps back to "Prompt", the prompt will be persisted.
139
+ const [ inputMapCache , _ ] = useState < {
140
+ [ idx : number ] : Transform [ ] ;
141
+ } > ( { } ) ;
142
+ useEffect ( ( ) => {
143
+ const curFormValues = debouncedInputMap as InputMapFormValue | undefined ;
144
+ if ( curFormValues !== undefined && ! isEmpty ( curFormValues ) ) {
145
+ // for each form value: populate the cache with a non-empty value and/or populate the
146
+ // form value with its cached value, if found.
147
+ curFormValues . forEach ( ( mapEntry , idx ) => {
148
+ const curCacheForIdx = inputMapCache [ idx ] ;
149
+ if ( curCacheForIdx === undefined || isEmpty ( curCacheForIdx ) ) {
150
+ // case 1: there is no persisted state for this entry index. create a fresh arr
151
+ inputMapCache [ idx ] = [ mapEntry . value ] ;
152
+ } else if (
153
+ ! curCacheForIdx . some (
154
+ ( transform : Transform ) =>
155
+ transform . transformType === mapEntry . value . transformType
156
+ )
157
+ ) {
158
+ // case 2: there is persisted state for this entry index, but not for the particular
159
+ // transform type. append to the arr
160
+ inputMapCache [ idx ] = [ ...inputMapCache [ idx ] , mapEntry . value ] ;
161
+ } else {
162
+ // case 3: there is persisted state for this entry index, and for the particular transform type.
163
+ // Either update the cache with the current form value(s) (if non-empty), or update the form
164
+ // with any value found in the cache
165
+ inputMapCache [ idx ] = inputMapCache [ idx ] . map ( ( cachedEntry ) => {
166
+ if ( cachedEntry . transformType === mapEntry . value . transformType ) {
167
+ const formValue = mapEntry . value . value ;
168
+ // form is non-empty. update the cache
169
+ if ( formValue !== undefined && ! isEmpty ( formValue ) ) {
170
+ return mapEntry . value ;
171
+ // form is empty. update the form with cached value(s)
172
+ } else {
173
+ setFieldValue ( `${ inputMapFieldPath } .${ idx } .value` , cachedEntry ) ;
174
+ return cachedEntry ;
175
+ }
176
+ } else {
177
+ return cachedEntry ;
178
+ }
179
+ } ) ;
180
+ }
181
+ } ) ;
116
182
}
117
- } , [ models , getIn ( values , modelFieldPath ) ?. id ] ) ;
183
+ } , [ debouncedInputMap ] ) ;
118
184
119
185
// persisting doc/query/index mapping fields to collect a list
120
186
// of options to display in the dropdowns when configuring input / output maps
0 commit comments