@@ -107,8 +107,8 @@ export function ApplicationComponent(props) {
107107 var tierName = tiers [ i ]
108108 // min, max, computeSize, cpu/memory/instanceType (not in form), filesystem, database
109109 let thisTier = thisService ?. tiers [ tierName ] || {
110- min : 0 ,
111- max : 0 ,
110+ min : 1 ,
111+ max : 1 ,
112112 computeSize : '' ,
113113 }
114114 const filesystem = {
@@ -183,120 +183,137 @@ export function ApplicationComponent(props) {
183183 }
184184
185185 // min, max, computeSize, cpu/memory/instanceType (not in form), filesystem, database
186- const singleTierValidationSpec = Yup . object ( {
187- min : Yup . number ( )
188- . required ( 'Minimum count is a required field.' )
189- . integer ( 'Minimum count must be an integer value' )
190- . min ( 1 , 'Minimum count must be at least ${min}' ) ,
191- max : Yup . number ( )
192- . required ( 'Maximum count is a required field.' )
193- . integer ( 'Maximum count must be an integer value' )
194- . max ( 10 , 'Maximum count can be no larger than ${max}' )
195- . test ( 'match' , 'Max cannot be smaller than min' , function ( max ) {
196- return max >= this . parent . min
197- } ) ,
198- computeSize : Yup . string ( ) . required ( 'Compute size is a required field.' ) ,
199- database : Yup . object ( ) . when ( 'provisionDb' , {
200- is : true ,
201- then : Yup . object ( {
202- engine : Yup . string ( ) . required ( 'Engine is required' ) ,
203- version : Yup . string ( ) . required ( 'Version is required' ) ,
204- instance : Yup . string ( ) . required ( 'Instance is required' ) ,
205- username : Yup . string ( )
206- . matches ( '^[a-zA-Z]+[a-zA-Z0-9_$]*$' , 'Username is not valid' )
207- . required ( 'Username is required' ) ,
208- password : Yup . string ( )
209- . matches ( '^[a-zA-Z0-9/@"\' ]{8,}$' , 'Password is not valid' )
210- . required ( 'Password is required' ) ,
211- database : Yup . string ( ) ,
186+ const singleTierValidationSpec = ( tombstone ) => {
187+ return Yup . object ( {
188+ min : requiredIfNotTombstoned ( tombstone , Yup . number ( )
189+ . integer ( 'Minimum count must be an integer value' )
190+ . min ( 1 , 'Minimum count must be at least ${min}' ) , 'Minimum count is a required field.' ) ,
191+ max : Yup . number ( )
192+ . required ( 'Maximum count is a required field.' )
193+ . integer ( 'Maximum count must be an integer value' )
194+ . max ( 10 , 'Maximum count can be no larger than ${max}' )
195+ . test ( 'match' , 'Max cannot be smaller than min' , function ( max ) {
196+ return max >= this . parent . min
212197 } ) ,
213- otherwise : Yup . object ( ) ,
214- } ) ,
215- filesystem : Yup . object ( ) . when ( 'provisionFS' , {
216- is : true ,
217- then : Yup . object ( {
218- mountPoint : Yup . string ( ) . when ( 'fileSystemType' , {
219- is : EFS ,
220- then : Yup . string ( )
221- . matches ( / ^ ( \/ [ a - z A - Z . _ - ] + ) * $ / , 'Invalid path. Ex: /mnt' )
222- . max ( 100 , "The full path can't exceed 100 characters in length" )
223- . test (
224- 'subdirectories' ,
225- 'The path can only include up to four subdirectories' ,
226- ( val ) => ( val ?. match ( / \/ / g) || [ ] ) . length <= 4 ,
227- )
228- . required ( ) ,
229- otherwise : Yup . string ( )
230- . matches (
231- / ^ [ a - z A - Z ] : \\ ( ( (? ! [ < > : " / \\ | ? * ] ) .) + ( (?< ! [ . ] ) \\ ) ? ) * $ / ,
232- 'Invalid path. Ex: C:\\data' ,
233- )
234- . required ( ) ,
235- } ) ,
236- fsx : Yup . object ( ) . when ( 'fileSystemType' , {
237- is : FSX ,
238- then : Yup . object ( {
239- storageGb : Yup . number ( )
240- . required ( )
241- . min ( 32 , 'Storage minimum is 32 GB' )
242- . max ( 1048 , 'Storage maximum is 1048 GB' ) ,
243- throughputMbs : Yup . number ( )
244- . required ( )
245- . min ( 8 , 'Throughput minimum is 8 MB/s' )
246- . max ( 2048 , 'Throughput maximum is 2048 MB/s' ) ,
247- backupRetentionDays : Yup . number ( )
248- . required ( )
249- . min ( 7 , 'Minimum retention time is 7 days' )
250- . max ( 35 , 'Maximum retention time is 35 days' ) ,
251- dailyBackupTime : Yup . string ( ) . required ( 'Daily backup time is required' ) ,
252- weeklyMaintenanceTime : Yup . string ( ) . required ( 'Weekly maintenance time is required' ) ,
253- windowsMountDrive : Yup . string ( ) . required ( 'Windows mount drive is required' ) ,
198+ computeSize : requiredIfNotTombstoned ( tombstone , Yup . string ( ) , 'Compute size is a required field.' ) ,
199+ database : Yup . object ( ) . when ( 'provisionDb' , {
200+ is : true ,
201+ then : Yup . object ( {
202+ engine : Yup . string ( ) . required ( 'Engine is required' ) ,
203+ version : Yup . string ( ) . required ( 'Version is required' ) ,
204+ instance : Yup . string ( ) . required ( 'Instance is required' ) ,
205+ username : Yup . string ( )
206+ . matches ( '^[a-zA-Z]+[a-zA-Z0-9_$]*$' , 'Username is not valid' )
207+ . required ( 'Username is required' ) ,
208+ password : Yup . string ( )
209+ . matches ( '^[a-zA-Z0-9/@"\' ]{8,}$' , 'Password is not valid' )
210+ . required ( 'Password is required' ) ,
211+ database : Yup . string ( ) ,
254212 } ) ,
255- otherwise : Yup . object ( ) . nullable ( ) ,
213+ otherwise : Yup . object ( ) ,
256214 } ) ,
257- efs : Yup . object ( ) . when ( 'fileSystemType' , {
258- is : EFS ,
259- then : Yup . object ( {
260- encryptAtRest : Yup . bool ( ) ,
261- lifecycle : Yup . number ( ) . required ( 'Lifecycle is required' ) ,
262- filesystemLifecycle : Yup . string ( ) ,
215+ filesystem : Yup . object ( ) . when ( 'provisionFS' , {
216+ is : true ,
217+ then : Yup . object ( {
218+ mountPoint : Yup . string ( ) . when ( 'fileSystemType' , {
219+ is : EFS ,
220+ then : Yup . string ( )
221+ . matches ( / ^ ( \/ [ a - z A - Z . _ - ] + ) * $ / , 'Invalid path. Ex: /mnt' )
222+ . max ( 100 , "The full path can't exceed 100 characters in length" )
223+ . test (
224+ 'subdirectories' ,
225+ 'The path can only include up to four subdirectories' ,
226+ ( val ) => ( val ?. match ( / \/ / g) || [ ] ) . length <= 4 ,
227+ )
228+ . required ( ) ,
229+ otherwise : Yup . string ( )
230+ . matches (
231+ / ^ [ a - z A - Z ] : \\ ( ( (? ! [ < > : " / \\ | ? * ] ) .) + ( (?< ! [ . ] ) \\ ) ? ) * $ / ,
232+ 'Invalid path. Ex: C:\\data' ,
233+ )
234+ . required ( ) ,
235+ } ) ,
236+ fsx : Yup . object ( ) . when ( 'fileSystemType' , {
237+ is : FSX ,
238+ then : Yup . object ( {
239+ storageGb : Yup . number ( )
240+ . required ( )
241+ . min ( 32 , 'Storage minimum is 32 GB' )
242+ . max ( 1048 , 'Storage maximum is 1048 GB' ) ,
243+ throughputMbs : Yup . number ( )
244+ . required ( )
245+ . min ( 8 , 'Throughput minimum is 8 MB/s' )
246+ . max ( 2048 , 'Throughput maximum is 2048 MB/s' ) ,
247+ backupRetentionDays : Yup . number ( )
248+ . required ( )
249+ . min ( 7 , 'Minimum retention time is 7 days' )
250+ . max ( 35 , 'Maximum retention time is 35 days' ) ,
251+ dailyBackupTime : Yup . string ( ) . required ( 'Daily backup time is required' ) ,
252+ weeklyMaintenanceTime : Yup . string ( ) . required ( 'Weekly maintenance time is required' ) ,
253+ windowsMountDrive : Yup . string ( ) . required ( 'Windows mount drive is required' ) ,
254+ } ) ,
255+ otherwise : Yup . object ( ) . nullable ( ) ,
256+ } ) ,
257+ efs : Yup . object ( ) . when ( 'fileSystemType' , {
258+ is : EFS ,
259+ then : Yup . object ( {
260+ encryptAtRest : Yup . bool ( ) ,
261+ lifecycle : Yup . number ( ) . required ( 'Lifecycle is required' ) ,
262+ filesystemLifecycle : Yup . string ( ) ,
263+ } ) ,
264+ otherwise : Yup . object ( ) . nullable ( ) ,
263265 } ) ,
264- otherwise : Yup . object ( ) . nullable ( ) ,
265266 } ) ,
267+ otherwise : Yup . object ( ) ,
266268 } ) ,
267- otherwise : Yup . object ( ) ,
268- } ) ,
269- } )
269+ } )
270+ }
270271
271- const allTiersValidationSpec = { }
272- for ( var i = 0 ; i < tiers . length ; i ++ ) {
273- var tierName = tiers [ i ]
274- allTiersValidationSpec [ tierName ] = singleTierValidationSpec
272+ const allTiersValidationSpec = ( tombstone ) => {
273+ let allTiers = { }
274+ for ( var i = 0 ; i < tiers . length ; i ++ ) {
275+ var tierName = tiers [ i ]
276+ allTiers [ tierName ] = singleTierValidationSpec ( tombstone )
277+ }
278+ return Yup . object ( allTiers )
279+ }
280+
281+ const requiredIfNotTombstoned = ( tombstone , schema , requiredMessage ) => {
282+ return tombstone ? schema : schema . required ( message )
275283 }
276284
277285 const validationSpecs = Yup . object ( {
278286 name : Yup . string ( ) . required ( 'Name is a required field.' ) ,
279287 services : Yup . array ( Yup . object ( {
280288 public : Yup . boolean ( ) ,
281- name : Yup . string ( ) . required ( 'Service Name is a required field.' ) ,
289+ name : Yup . string ( ) . when ( 'tombstone' , ( tombstone , schema ) => {
290+ return requiredIfNotTombstoned ( tombstone , schema , 'Service Name is a required field.' )
291+ } ) ,
282292 description : Yup . string ( ) ,
283- path : Yup . string ( ) . matches ( / ^ .+ $ / , 'error message' , ) . required ( ) ,
293+ path : Yup . string ( ) . matches ( / ^ .+ $ / , 'error message' , ) . when ( 'tombstone' , ( tombstone , schema ) => {
294+ return requiredIfNotTombstoned ( tombstone , schema , 'Path Name is a required field.' )
295+ } ) ,
284296 containerPort : Yup . number ( )
285297 . integer ( 'Container port must be an integer value.' )
286298 . required ( 'Container port is a required field.' ) ,
287299 containerTag : Yup . string ( ) . required ( 'Container Tag is a required field.' ) ,
288300 healthCheckUrl : Yup . string ( )
289301 . required ( 'Health Check URL is a required field' )
290302 . matches ( / ^ \/ / , 'Health Check must start with forward slash (/)' ) ,
291- operatingSystem : Yup . string ( ) . required ( 'Container OS is a required field.' ) ,
303+ operatingSystem : Yup . string ( ) . when ( 'tombstone' , ( tombstone , schema ) => {
304+ return requiredIfNotTombstoned ( tombstone , schema , 'Container OS is a required field.' )
305+ } ) ,
292306 windowsVersion : Yup . string ( ) . when ( 'operatingSystem' , {
293307 is : ( containerOs ) => containerOs && containerOs === WINDOWS ,
294308 then : Yup . string ( ) . required ( 'Windows version is a required field' ) ,
295309 otherwise : Yup . string ( ) . nullable ( ) ,
296310 } ) ,
297311 provisionDb : Yup . boolean ( ) ,
298312 provisionFS : Yup . boolean ( ) ,
299- tiers : Yup . object ( allTiersValidationSpec ) ,
313+ tiers : Yup . object ( ) . when ( 'tombstone' , ( tombstone , schema ) => {
314+ return allTiersValidationSpec ( tombstone )
315+ } ) ,
316+ tombstone : Yup . boolean ( ) ,
300317 } ) ) . min ( 1 , 'Application must have at least ${min} service(s).' ) ,
301318 provisionBilling : Yup . boolean ( ) ,
302319 } )
@@ -343,6 +360,7 @@ export function ApplicationComponent(props) {
343360 < Formik
344361 initialValues = { initialValues }
345362 validationSchema = { validationSpecs }
363+ validateOnChange = { false }
346364 onSubmit = { updateConfig }
347365 enableReinitialize = { true }
348366 >
0 commit comments