@@ -70,180 +70,171 @@ private class CoderWorkspaceStepDialog(
7070 }
7171}
7272
73- /* *
74- * Generic function to ask for consent.
75- */
76- fun confirm (
77- title : String ,
78- comment : String ,
79- details : String ,
80- ):Boolean {
81- var inputFromUser= false
82- ApplicationManager .getApplication().invokeAndWait({
83- val panel=
84- panel {
85- row {
86- label(comment)
87- }
88- row {
89- label(details)
90- }
91- }
92- AppIcon .getInstance().requestAttention(null ,true )
93- if (! dialog(
94- title= title,
95- panel= panel,
96- ).showAndGet()
97- ) {
98- return @invokeAndWait
99- }
100- inputFromUser= true
101- },ModalityState .defaultModalityState())
102- return inputFromUser
73+ fun askIDE (
74+ name : String ,
75+ agent : WorkspaceAgent ,
76+ workspace : Workspace ,
77+ cli : CoderCLIManager ,
78+ client : CoderRestClient ,
79+ workspaces : List <Workspace >,
80+ ):WorkspaceProjectIDE ? {
81+ var data: WorkspaceProjectIDE ? = null
82+ ApplicationManager .getApplication().invokeAndWait {
83+ val dialog=
84+ CoderWorkspaceStepDialog (
85+ name,
86+ CoderWorkspacesStepSelection (agent, workspace, cli, client, workspaces),
87+ )
88+ data= dialog.showAndGetData()
89+ }
90+ return data
10391}
10492
10593/* *
106- * Generic function to ask for input.
94+ * Dialog implementation for standalone Gateway.
95+ *
96+ * This is meant to mimic ToolboxUi.
10797*/
108- fun ask (
109- comment : String ,
110- isError : Boolean = false,
111- link : Pair <String ,String >? = null,
112- default : String? = null,
113- ):String? {
114- var inputFromUser: String? = null
115- ApplicationManager .getApplication().invokeAndWait({
116- lateinit var inputTextField: JBTextField
117- val panel=
118- panel {
119- row {
120- if (link!= null ) browserLink(link.first, link.second)
121- inputTextField=
122- textField()
123- .applyToComponent {
124- text= default? : " "
125- minimumSize= Dimension (520 ,- 1 )
126- }.component
127- }.layout(RowLayout .PARENT_GRID )
128- row {
129- cell()// To align with the text box.
130- cell(
131- ComponentPanelBuilder .createCommentComponent(comment,false ,- 1 ,true )
132- .applyIf(isError) {
133- apply {
134- foreground= UIUtil .getErrorForeground()
135- }
136- },
137- )
138- }.layout(RowLayout .PARENT_GRID )
98+ class DialogUi (
99+ private val settings : CoderSettings ,
100+ ) {
101+ fun confirm (title : String ,description : String ):Boolean {
102+ var inputFromUser= false
103+ ApplicationManager .getApplication().invokeAndWait({
104+ AppIcon .getInstance().requestAttention(null ,true )
105+ if (! dialog(
106+ title= title,
107+ panel= panel {
108+ row {
109+ label(description)
110+ }
111+ },
112+ ).showAndGet()
113+ ) {
114+ return @invokeAndWait
139115 }
140- AppIcon .getInstance().requestAttention(null ,true )
141- if (! dialog(
142- comment,
143- panel= panel,
144- focusedComponent= inputTextField,
145- ).showAndGet()
146- ) {
147- return @invokeAndWait
148- }
149- inputFromUser= inputTextField.text
150- },ModalityState .any())
151- return inputFromUser
152- }
116+ inputFromUser= true
117+ },ModalityState .defaultModalityState())
118+ return inputFromUser
119+ }
153120
154- /* *
155- * Open a dialog for providing the token. Show any existing token so
156- * the user can validate it if a previous connection failed.
157- *
158- * If we are not retrying and the user has not checked the existing
159- * token box then also open a browser to the auth page.
160- *
161- * If the user has checked the existing token box then return the token
162- * on disk immediately and skip the dialog (this will overwrite any
163- * other existing token) unless this is a retry to avoid clobbering the
164- * token that just failed.
165- */
166- fun askToken (
167- url : URL ,
168- token : Pair <String ,Source >? ,
169- isRetry : Boolean ,
170- useExisting : Boolean ,
171- settings : CoderSettings ,
172- ):Pair <String ,Source >? {
173- var (existingToken, tokenSource)= token? : Pair (" " ,Source .USER )
174- val getTokenUrl= url.withPath(" /login?redirect=%2Fcli-auth" )
121+ fun ask (
122+ title : String ,
123+ description : String ,
124+ placeholder : String? = null,
125+ isError : Boolean = false,
126+ link : Pair <String ,String >? = null,
127+ ):String? {
128+ var inputFromUser: String? = null
129+ ApplicationManager .getApplication().invokeAndWait({
130+ lateinit var inputTextField: JBTextField
131+ AppIcon .getInstance().requestAttention(null ,true )
132+ if (! dialog(
133+ title= title,
134+ panel= panel {
135+ row {
136+ if (link!= null ) browserLink(link.first, link.second)
137+ inputTextField=
138+ textField()
139+ .applyToComponent {
140+ this .text= placeholder
141+ minimumSize= Dimension (520 ,- 1 )
142+ }.component
143+ }.layout(RowLayout .PARENT_GRID )
144+ row {
145+ cell()// To align with the text box.
146+ cell(
147+ ComponentPanelBuilder .createCommentComponent(description,false ,- 1 ,true )
148+ .applyIf(isError) {
149+ apply {
150+ foreground= UIUtil .getErrorForeground()
151+ }
152+ },
153+ )
154+ }.layout(RowLayout .PARENT_GRID )
155+ },
156+ focusedComponent= inputTextField,
157+ ).showAndGet()
158+ ) {
159+ return @invokeAndWait
160+ }
161+ inputFromUser= inputTextField.text
162+ },ModalityState .any())
163+ return inputFromUser
164+ }
165+
166+ private fun openUrl (url : URL ) {
167+ BrowserUtil .browse(url)
168+ }
169+
170+ /* *
171+ * Open a dialog for providing the token. Show any existing token so
172+ * the user can validate it if a previous connection failed.
173+ *
174+ * If we are not retrying and the user has not checked the existing
175+ * token box then also open a browser to the auth page.
176+ *
177+ * If the user has checked the existing token box then return the token
178+ * on disk immediately and skip the dialog (this will overwrite any
179+ * other existing token) unless this is a retry to avoid clobbering the
180+ * token that just failed.
181+ */
182+ fun askToken (
183+ url : URL ,
184+ token : Pair <String ,Source >? ,
185+ isRetry : Boolean ,
186+ useExisting : Boolean ,
187+ ):Pair <String ,Source >? {
188+ var (existingToken, tokenSource)= token? : Pair (" " ,Source .USER )
189+ val getTokenUrl= url.withPath(" /login?redirect=%2Fcli-auth" )
175190
176- // On the first run either open a browser to generate a new token
177- // or, if using an existing token, use the token on disk if it
178- // exists otherwise assume the user already copied an existing
179- // token and they will paste in.
180- if (! isRetry) {
181- if (! useExisting) {
182- BrowserUtil .browse(getTokenUrl)
183- }else {
184- // Look on disk in case we already have a token, either in
185- // the deployment's config or the global config.
186- val tryToken= settings.token(url)
187- if (tryToken!= null && tryToken.first!= existingToken) {
188- return tryToken
191+ // On the first run either open a browser to generate a new token
192+ // or, if using an existing token, use the token on disk if it
193+ // exists otherwise assume the user already copied an existing
194+ // token and they will paste in.
195+ if (! isRetry) {
196+ if (! useExisting) {
197+ openUrl(getTokenUrl)
198+ }else {
199+ // Look on disk in case we already have a token, either in
200+ // the deployment's config or the global config.
201+ val tryToken= settings.token(url)
202+ if (tryToken!= null && tryToken.first!= existingToken) {
203+ return tryToken
204+ }
189205 }
190206 }
191- }
192207
193- // On subsequent tries or if not using an existing token, ask the user
194- // for the token.
195- val tokenFromUser=
196- ask(
197- CoderGatewayBundle .message(
198- if (isRetry) {
199- " gateway.connector.view.workspaces. token. rejected"
208+ // On subsequent tries or if not using an existing token, ask the user
209+ // for the token.
210+ val tokenFromUser=
211+ ask(
212+ title = " Session Token " ,
213+ description = if (isRetry) {
214+ " This token was rejected by ${url.host} . "
200215 }else if (tokenSource== Source .CONFIG ) {
201- " gateway.connector.view.workspaces. token.injected- global"
216+ " This token was pulled from your global CLI config. "
202217 }else if (tokenSource== Source .DEPLOYMENT_CONFIG ) {
203- " gateway.connector.view.workspaces. token.injected "
218+ " This token was pulled from your CLI config for ${url.host} . "
204219 }else if (tokenSource== Source .LAST_USED ) {
205- " gateway.connector.view.workspaces. token. last- used"
220+ " This token was the last used token for ${url.host} . "
206221 }else if (tokenSource== Source .QUERY ) {
207- " gateway.connector.view.workspaces. token.query "
222+ " This token was pulled from the Gateway link from ${url.host} . "
208223 }else if (existingToken.isNotBlank()) {
209- " gateway.connector.view.workspaces. token.comment "
224+ " The last used token for ${url.host} is shown above. "
210225 }else {
211- " gateway.connector.view.workspaces. token.none "
226+ " No existing token for ${url.host} found. "
212227 },
213- url.host,
214- ),
215- isRetry,
216- Pair (
217- CoderGatewayBundle .message(" gateway.connector.view.login.token.label" ),
218- getTokenUrl.toString(),
219- ),
220- existingToken,
221- )
222- if (tokenFromUser.isNullOrBlank()) {
223- return null
224- }
225- if (tokenFromUser!= existingToken) {
226- tokenSource= Source .USER
227- }
228- return Pair (tokenFromUser, tokenSource)
229- }
230-
231- fun askIDE (
232- name : String ,
233- agent : WorkspaceAgent ,
234- workspace : Workspace ,
235- cli : CoderCLIManager ,
236- client : CoderRestClient ,
237- workspaces : List <Workspace >,
238- ):WorkspaceProjectIDE ? {
239- var data: WorkspaceProjectIDE ? = null
240- ApplicationManager .getApplication().invokeAndWait {
241- val dialog=
242- CoderWorkspaceStepDialog (
243- name,
244- CoderWorkspacesStepSelection (agent, workspace, cli, client, workspaces),
228+ placeholder= existingToken,
229+ link= Pair (" Session Token:" , getTokenUrl.toString()),
230+ isError= isRetry,
245231 )
246- data= dialog.showAndGetData()
232+ if (tokenFromUser.isNullOrBlank()) {
233+ return null
234+ }
235+ if (tokenFromUser!= existingToken) {
236+ tokenSource= Source .USER
237+ }
238+ return Pair (tokenFromUser, tokenSource)
247239 }
248- return data
249240}