1- import React , { useEffect , useMemo , useState } from 'react' ;
1+ import React , { useMemo , useState } from 'react' ;
22
33import {
44 ComboboxWithCustomOption ,
@@ -10,27 +10,34 @@ import {
1010import type { WizardComponentProps } from '..' ;
1111
1212// Types
13- type ProjectFormState = string [ ] ;
13+ type ProjectionFields = string [ ] ;
1414export type ProjectionType = 'include' | 'exclude' ;
15+ type ProjectFormState = {
16+ projectionFields : ProjectionFields ;
17+ projectionType : ProjectionType ;
18+ } ;
1519
1620// Helpers
1721export const SELECT_PLACEHOLDER_TEXT = 'Select projection type' ;
1822export const COMBOBOX_PLACEHOLDER_TEXT = 'Select field names' ;
1923
20- export const mapProjectFormStateToStageValue = (
21- projectionType : ProjectionType ,
22- formState : ProjectFormState
23- ) => {
24- return formState . reduce < { [ field : string ] : 1 | 0 } > ( ( projection , field ) => {
25- if ( field === null ) {
26- return projection ;
27- } else {
28- return {
29- ...projection ,
30- [ field ] : projectionType === 'include' ? 1 : 0 ,
31- } ;
32- }
33- } , { } ) ;
24+ export const mapProjectFormStateToStageValue = ( {
25+ projectionFields,
26+ projectionType,
27+ } : ProjectFormState ) => {
28+ return projectionFields . reduce < { [ field : string ] : 1 | 0 } > (
29+ ( projection , field ) => {
30+ if ( field === null ) {
31+ return projection ;
32+ } else {
33+ return {
34+ ...projection ,
35+ [ field ] : projectionType === 'include' ? 1 : 0 ,
36+ } ;
37+ }
38+ } ,
39+ { }
40+ ) ;
3441} ;
3542
3643// Generates parent paths for a list of paths
@@ -96,27 +103,29 @@ const comboboxStyles = css({ width: '350px' });
96103
97104const ProjectForm = ( { fields, onChange } : WizardComponentProps ) => {
98105 const fieldNames = useMemo ( ( ) => fields . map ( ( { name } ) => name ) , [ fields ] ) ;
99- const [ projectionType , setProjectionType ] =
100- useState < ProjectionType > ( 'include' ) ;
101- const [ projectFields , setProjectFields ] = useState < ProjectFormState > ( [ ] ) ;
102-
103- useEffect ( ( ) => {
104- const stageValue = mapProjectFormStateToStageValue (
105- projectionType ,
106- projectFields
107- ) ;
108106
107+ const [ projectFormState , setProjectFormState ] = useState < ProjectFormState > ( {
108+ projectionType : 'include' ,
109+ projectionFields : [ ] ,
110+ } ) ;
111+
112+ const handleProjectFormStateChange = < T extends keyof ProjectFormState > (
113+ property : T ,
114+ value : ProjectFormState [ T ]
115+ ) => {
116+ const nextProjectState = {
117+ ...projectFormState ,
118+ [ property ] : value ,
119+ } ;
120+ setProjectFormState ( nextProjectState ) ;
121+
122+ const stageValue = mapProjectFormStateToStageValue ( nextProjectState ) ;
109123 onChange (
110124 JSON . stringify ( stageValue ) ,
111125 Object . keys ( stageValue ) . length === 0
112126 ? new Error ( 'No field selected' )
113127 : null
114128 ) ;
115- } , [ projectFields , onChange , projectionType ] ) ;
116-
117- const onSelectField = ( value : string [ ] ) => {
118- const nextProjectFields = [ ...value ] ;
119- setProjectFields ( nextProjectFields ) ;
120129 } ;
121130
122131 return (
@@ -128,8 +137,13 @@ const ProjectForm = ({ fields, onChange }: WizardComponentProps) => {
128137 className = { selectStyles }
129138 allowDeselect = { false }
130139 aria-label = { SELECT_PLACEHOLDER_TEXT }
131- value = { projectionType }
132- onChange = { ( value ) => setProjectionType ( value as ProjectionType ) }
140+ value = { projectFormState . projectionType }
141+ onChange = { ( value ) =>
142+ handleProjectFormStateChange (
143+ 'projectionType' ,
144+ value as ProjectionType
145+ )
146+ }
133147 >
134148 < Option value = "include" > Include</ Option >
135149 < Option value = "exclude" > Exclude</ Option >
@@ -142,12 +156,16 @@ const ProjectForm = ({ fields, onChange }: WizardComponentProps) => {
142156 size = "default"
143157 clearable = { true }
144158 multiselect = { true }
145- value = { projectFields }
146- onChange = { onSelectField }
159+ value = { projectFormState . projectionFields }
160+ onChange = { ( fields ) =>
161+ handleProjectFormStateChange ( 'projectionFields' , [ ...fields ] )
162+ }
147163 options = { fieldNames }
148164 optionLabel = "Field:"
149165 overflow = "scroll-x"
150- isOptionDisabled = { makeIsOptionDisabled ( projectFields ) }
166+ isOptionDisabled = { makeIsOptionDisabled (
167+ projectFormState . projectionFields
168+ ) }
151169 // Used for testing to access the popover for a stage
152170 popoverClassName = "project-form-field-combobox"
153171 />
0 commit comments