11import * as React from "react" ;
22import { Checkbox , DefaultButton , IDropdownOption , mergeStyleSets , PrimaryButton , Spinner , TextField , } from "@fluentui/react" ;
33import { StackShim } from "@fluentui/react-migration-v8-v9" ;
4+ import { scopedLogger } from "@hpcc-js/util" ;
45import { useForm , Controller } from "react-hook-form" ;
56import nlsHPCC from "src/nlsHPCC" ;
67import * as FileSpray from "src/FileSpray" ;
@@ -9,11 +10,14 @@ import { pushUrl } from "../../util/history";
910import { TargetGroupTextField } from "./Fields" ;
1011import * as FormStyles from "./landing-zone/styles" ;
1112
13+ const logger = scopedLogger ( "src-react/components/forms/CopyFile.tsx" ) ;
14+
1215interface CopyFileFormValues {
1316 destGroup : string ;
1417 destLogicalName : string ;
1518 targetCopyName ?: {
16- name : string
19+ name : string ,
20+ numParts : string
1721 } [ ] ;
1822 overwrite : boolean ;
1923 replicate : boolean ;
@@ -69,32 +73,42 @@ export const CopyFile: React.FunctionComponent<CopyFileProps> = ({
6973 ( data , evt ) => {
7074 setSubmitDisabled ( true ) ;
7175 setSpinnerHidden ( false ) ;
72- if ( logicalFiles . length > 0 ) {
73- if ( logicalFiles . length === 1 ) {
74- const request = { ...data , sourceLogicalName : logicalFiles [ 0 ] } ;
75- FileSpray . Copy ( { request : request } ) . then ( response => {
76- setSubmitDisabled ( false ) ;
77- setSpinnerHidden ( true ) ;
78- closeForm ( ) ;
79- pushUrl ( `/dfuworkunits/${ response . CopyResponse . result } ` ) ;
80- } ) ;
76+ const requests = [ ] ;
77+ logicalFiles . forEach ( ( logicalFile , idx ) => {
78+ const destLogicalName = data . targetCopyName [ idx ] . name ? data . targetCopyName [ idx ] . name : "" ;
79+ const destNumParts = data . targetCopyName [ idx ] . numParts ? data . targetCopyName [ idx ] . numParts : "0" ;
80+ const request = { ...data , sourceLogicalName : logicalFile , destLogicalName, DestNumParts : destNumParts } ;
81+ requests . push ( FileSpray . Copy ( { request : request } ) ) ;
82+ } ) ;
83+ Promise . all ( requests ) . then ( responses => {
84+ const urls : string [ ] = [ ] ;
85+ const errors : string [ ] = [ ] ;
86+ responses . forEach ( response => {
87+ if ( response ?. Exceptions ) {
88+ const err = response . Exceptions . Exception [ 0 ] . Message ;
89+ errors . push ( err ) ;
90+ logger . error ( err ) ;
91+ } else if ( response . CopyResponse ?. result ) {
92+ urls . push ( `#/dfuworkunits/${ response . CopyResponse . result } ` ) ;
93+ }
94+ } ) ;
95+ setSubmitDisabled ( false ) ;
96+ setSpinnerHidden ( true ) ;
97+ if ( errors . length === 0 ) {
98+ closeForm ( ) ;
99+ }
100+ if ( urls . length === 1 ) {
101+ pushUrl ( urls [ 0 ] ) ;
81102 } else {
82- logicalFiles . forEach ( ( logicalFile , idx ) => {
83- const request = { ...data , sourceLogicalName : logicalFile , destLogicalName : data . targetCopyName [ idx ] . name } ;
84- const requests = [ ] ;
85- requests . push ( FileSpray . Copy ( { request : request } ) ) ;
86- Promise . all ( requests ) . then ( _ => {
87- setSubmitDisabled ( false ) ;
88- setSpinnerHidden ( true ) ;
89- closeForm ( ) ;
90- if ( refreshGrid ) refreshGrid ( ) ;
91- } ) ;
92- } ) ;
103+ if ( refreshGrid ) {
104+ window . setTimeout ( ( ) => refreshGrid ( ) , 200 ) ;
105+ }
106+ urls . forEach ( url => window . open ( url ) ) ;
93107 }
94- }
108+ } ) ;
95109 } ,
96110 err => {
97- console . log ( err ) ;
111+ logger . error ( err ) ;
98112 }
99113 ) ( ) ;
100114 } , [ closeForm , handleSubmit , logicalFiles , refreshGrid ] ) ;
@@ -109,17 +123,12 @@ export const CopyFile: React.FunctionComponent<CopyFileProps> = ({
109123 ) ;
110124
111125 React . useEffect ( ( ) => {
112- if ( logicalFiles ?. length === 1 ) {
113- const newValues = { ...defaultValues , destLogicalName : logicalFiles [ 0 ] } ;
114- reset ( newValues ) ;
115- } else if ( logicalFiles ?. length > 1 ) {
116- const _files = [ ] ;
117- logicalFiles . forEach ( file => {
118- _files . push ( { name : file } ) ;
119- } ) ;
120- const newValues = { ...defaultValues , targetCopyName : _files } ;
121- reset ( newValues ) ;
122- }
126+ const _files = [ ] ;
127+ logicalFiles . forEach ( file => {
128+ _files . push ( { name : file , numParts : "" } ) ;
129+ } ) ;
130+ const newValues = { ...defaultValues , targetCopyName : _files } ;
131+ reset ( newValues ) ;
123132 } , [ logicalFiles , reset ] ) ;
124133
125134 return < MessageBox title = { nlsHPCC . Copy } show = { showForm } setShow = { closeForm }
@@ -149,60 +158,60 @@ export const CopyFile: React.FunctionComponent<CopyFileProps> = ({
149158 required : `${ nlsHPCC . SelectA } ${ nlsHPCC . Group } `
150159 } }
151160 />
152- { logicalFiles . length === 1 &&
153- < Controller
154- control = { control } name = "destLogicalName"
155- render = { ( {
156- field : { onChange, name : fieldName , value } ,
157- fieldState : { error }
158- } ) => < TextField
159- name = { fieldName }
160- onChange = { onChange }
161- required = { true }
162- label = { nlsHPCC . TargetName }
163- value = { value }
164- errorMessage = { error && error . message }
165- /> }
166- rules = { {
167- required : nlsHPCC . ValidationErrorRequired
168- } }
169- />
170- }
171161 </ StackShim >
172- { logicalFiles . length > 1 &&
173- < StackShim >
174- < table className = { `${ componentStyles . twoColumnTable } ${ componentStyles . selectionTable } ` } >
175- < thead >
176- < tr >
177- < th > { nlsHPCC . TargetName } </ th >
178- </ tr >
179- </ thead >
180- < tbody >
181- { logicalFiles . map ( ( file , idx ) => {
182- return < tr key = { `File-${ idx } ` } >
183- < td >
184- < Controller
185- control = { control } name = { `targetCopyName.${ idx } .name` as const }
186- render = { ( {
187- field : { onChange, name : fieldName , value : file } ,
188- fieldState : { error }
189- } ) => < TextField
190- name = { fieldName }
191- onChange = { onChange }
192- value = { file }
193- errorMessage = { error && error ?. message }
194- /> }
195- rules = { {
196- required : nlsHPCC . ValidationErrorTargetNameRequired
197- } }
198- />
199- </ td >
200- </ tr > ;
201- } ) }
202- </ tbody >
203- </ table >
204- </ StackShim >
205- }
162+ < StackShim >
163+ < table className = { `${ componentStyles . twoColumnTable } ${ componentStyles . selectionTable } ` } >
164+ < thead >
165+ < tr >
166+ < th > { nlsHPCC . TargetName } </ th >
167+ < th > { nlsHPCC . NumberofParts } </ th >
168+ </ tr >
169+ </ thead >
170+ < tbody >
171+ { logicalFiles . map ( ( file , idx ) => {
172+ return < tr key = { `File-${ idx } ` } >
173+ < td >
174+ < Controller
175+ control = { control } name = { `targetCopyName.${ idx } .name` as const }
176+ render = { ( {
177+ field : { onChange, name : fieldName , value : file } ,
178+ fieldState : { error }
179+ } ) => < TextField
180+ name = { fieldName }
181+ onChange = { onChange }
182+ value = { file }
183+ errorMessage = { error && error ?. message }
184+ /> }
185+ rules = { {
186+ required : nlsHPCC . ValidationErrorTargetNameRequired
187+ } }
188+ />
189+ </ td >
190+ < td >
191+ < Controller
192+ control = { control } name = { `targetCopyName.${ idx } .numParts` as const }
193+ render = { ( {
194+ field : { onChange, name : fieldName , value } ,
195+ fieldState : { error }
196+ } ) => < TextField
197+ name = { fieldName }
198+ onChange = { onChange }
199+ value = { value }
200+ errorMessage = { error && error ?. message }
201+ /> }
202+ rules = { {
203+ pattern : {
204+ value : / ^ [ 0 - 9 ] + $ / i,
205+ message : nlsHPCC . ValidationErrorEnterNumber
206+ }
207+ } }
208+ />
209+ </ td >
210+ </ tr > ;
211+ } ) }
212+ </ tbody >
213+ </ table >
214+ </ StackShim >
206215 < StackShim >
207216 < table className = { componentStyles . twoColumnTable } >
208217 < tbody >
0 commit comments