@@ -11,7 +11,7 @@ import {
11
11
Stepper ,
12
12
Typography ,
13
13
} from "@mui/material" ;
14
- import { useState } from "react" ;
14
+ import { FC , useRef , useState } from "react" ;
15
15
import { MdClose } from "react-icons/md" ;
16
16
import { useRecoilState } from "recoil" ;
17
17
import DeployedCodeUpdate from "../Icons/DeployedCodeUpdate" ;
@@ -29,17 +29,32 @@ const components = [
29
29
( ) => < p > Finish</ p > ,
30
30
] ;
31
31
32
+ type NextValidator = ( ) => boolean | Promise < boolean > ;
33
+
34
+ export type StepProps = {
35
+ setNextValidator : ( validator : NextValidator ) => void ;
36
+ } ;
37
+
32
38
export default function ExtensionInstallModal ( { extension } : Props ) {
33
39
const [ state , setState ] = useRecoilState ( ExtensionPageState ) ;
34
40
const [ activeStep , setActiveStep ] = useState ( 0 ) ;
35
41
const [ skipped , setSkipped ] = useState ( new Set < number > ( ) ) ;
42
+ const nextValidatorRef = useRef < NextValidator | null > ( null ) ;
36
43
const onClose = ( ) => {
37
- setState ( ( state ) => ( { ...state , installModalOpen : false } ) ) ;
44
+ setState ( ( state ) => ( {
45
+ ...state ,
46
+ installModalOpen : false ,
47
+ selectedInstanceIds : [ ] ,
48
+ } ) ) ;
38
49
setActiveStep ( 0 ) ;
39
50
setSkipped ( new Set < number > ( ) ) ;
40
51
} ;
41
52
42
- const StepComponent = components [ activeStep ] ;
53
+ const setNextValidator = ( validator : NextValidator ) => {
54
+ nextValidatorRef . current = validator ;
55
+ } ;
56
+
57
+ const StepComponent = components [ activeStep ] as FC < StepProps > ;
43
58
44
59
const isStepOptional = ( step : number ) => {
45
60
return false ;
@@ -49,18 +64,29 @@ export default function ExtensionInstallModal({ extension }: Props) {
49
64
return skipped . has ( step ) ;
50
65
} ;
51
66
52
- const handleNext = ( ) => {
67
+ const handleNext = async ( ) => {
53
68
let newSkipped = skipped ;
69
+
54
70
if ( isStepSkipped ( activeStep ) ) {
55
71
newSkipped = new Set ( newSkipped . values ( ) ) ;
56
72
newSkipped . delete ( activeStep ) ;
57
73
}
58
74
75
+ if ( nextValidatorRef . current ) {
76
+ const valid = await nextValidatorRef . current ( ) ;
77
+
78
+ if ( ! valid ) {
79
+ return ;
80
+ }
81
+ }
82
+
83
+ nextValidatorRef . current = null ;
59
84
setActiveStep ( ( prevActiveStep ) => prevActiveStep + 1 ) ;
60
85
setSkipped ( newSkipped ) ;
61
86
} ;
62
87
63
88
const handleBack = ( ) => {
89
+ nextValidatorRef . current = null ;
64
90
setActiveStep ( ( prevActiveStep ) => prevActiveStep - 1 ) ;
65
91
} ;
66
92
@@ -69,6 +95,7 @@ export default function ExtensionInstallModal({ extension }: Props) {
69
95
throw new Error ( "You can't skip a step that isn't optional." ) ;
70
96
}
71
97
98
+ nextValidatorRef . current = null ;
72
99
setActiveStep ( ( prevActiveStep ) => prevActiveStep + 1 ) ;
73
100
setSkipped ( ( prevSkipped ) => {
74
101
const newSkipped = new Set ( prevSkipped . values ( ) ) ;
@@ -77,10 +104,6 @@ export default function ExtensionInstallModal({ extension }: Props) {
77
104
} ) ;
78
105
} ;
79
106
80
- const handleReset = ( ) => {
81
- setActiveStep ( 0 ) ;
82
- } ;
83
-
84
107
return (
85
108
< Modal
86
109
open = { state . installModalOpen }
@@ -142,18 +165,15 @@ export default function ExtensionInstallModal({ extension }: Props) {
142
165
</ Typography >
143
166
</ >
144
167
) : (
145
- < StepComponent />
168
+ < StepComponent
169
+ setNextValidator = { setNextValidator }
170
+ />
146
171
) }
147
172
</ Box >
148
173
149
174
< div className = "rounded-b-lg flex justify-end gap-4 p-4 absolute bottom-0 left-0 w-[100%] z-[10000] bg-white dark:bg-[#222] [box-shadow:0_-1px_1px_0_rgba(0,0,0,0.1)] dark:[box-shadow:0_0_1px_0_rgba(255,255,255,0.4)]" >
150
- < Button
151
- color = "inherit"
152
- disabled = { activeStep === 0 }
153
- onClick = { handleBack }
154
- sx = { { mr : 1 } }
155
- >
156
- Back
175
+ < Button color = "inherit" onClick = { onClose } >
176
+ Cancel
157
177
</ Button >
158
178
< Box sx = { { flex : "1 1 auto" } } />
159
179
{ isStepOptional ( activeStep ) && (
@@ -165,7 +185,13 @@ export default function ExtensionInstallModal({ extension }: Props) {
165
185
Skip
166
186
</ Button >
167
187
) }
168
- < Button onClick = { onClose } > Cancel</ Button > { " " }
188
+ < Button
189
+ disabled = { activeStep === 0 }
190
+ onClick = { handleBack }
191
+ sx = { { mr : 1 } }
192
+ >
193
+ Back
194
+ </ Button > { " " }
169
195
< Button onClick = { handleNext } variant = "outlined" >
170
196
{ activeStep === steps . length - 1
171
197
? "Finish"
0 commit comments