From 436d773d6931026f0fd4e511072745d11f87c043 Mon Sep 17 00:00:00 2001 From: Asher Date: Thu, 23 Mar 2023 12:51:35 -0800 Subject: [PATCH 1/8] Tweak header alignment to match previous step --- .../gateway/views/steps/CoderLocateRemoteProjectStepView.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt b/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt index 558e6dd5..b2ba9b11 100644 --- a/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt +++ b/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt @@ -94,8 +94,7 @@ class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit font = JBFont.h3().asBold() icon = CoderIcons.LOGO_16 }.component - }.bottomGap(BottomGap.MEDIUM) - + }.topGap(TopGap.SMALL) row { label("IDE:") cbIDE = cell(IDEComboBox(ideComboBoxModel).apply { From 896076e27123c640097af692d70212eaad76bdf7 Mon Sep 17 00:00:00 2001 From: Asher Date: Thu, 23 Mar 2023 12:54:29 -0800 Subject: [PATCH 2/8] Change IDE help text based on installed status --- .../steps/CoderLocateRemoteProjectStepView.kt | 34 +++++++++++++++---- .../messages/CoderGatewayBundle.properties | 3 ++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt b/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt index b2ba9b11..a40be941 100644 --- a/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt +++ b/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt @@ -20,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.ui.ComboBox import com.intellij.openapi.ui.ComponentValidator import com.intellij.openapi.ui.ValidationInfo +import com.intellij.openapi.ui.panel.ComponentPanelBuilder import com.intellij.openapi.util.Disposer import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeScreenUIManager import com.intellij.remote.AuthType @@ -82,6 +83,7 @@ class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit private lateinit var titleLabel: JLabel private lateinit var wizard: CoderWorkspacesWizardModel private lateinit var cbIDE: IDEComboBox + private lateinit var cbIDEComment: JLabel private var tfProject = JBTextField() private lateinit var terminalLink: LazyBrowserLink private lateinit var ideResolvingJob: Job @@ -99,17 +101,37 @@ class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit label("IDE:") cbIDE = cell(IDEComboBox(ideComboBoxModel).apply { renderer = IDECellRenderer() - }).resizableColumn().align(AlignX.FILL).comment("The IDE will be downloaded from jetbrains.com").component - cell() - }.topGap(TopGap.NONE).layout(RowLayout.PARENT_GRID) - + addActionListener { + ApplicationManager.getApplication().invokeLater { + logger.info("Selected IDE: ${this.selectedItem}") + when (this.selectedItem?.status) { + IdeStatus.ALREADY_INSTALLED -> + cbIDEComment.text = CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.ide.installed.comment") + IdeStatus.DOWNLOAD -> + cbIDEComment.text = CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.ide.download.comment") + else -> + cbIDEComment.text = CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.ide.none.comment") + } + } + } + }).resizableColumn().align(AlignX.FILL).component + cell() // To leave space on the right. + }.topGap(TopGap.NONE).bottomGap(BottomGap.NONE).layout(RowLayout.PARENT_GRID) + row { + cell() // Empty cell for alignment. + cbIDEComment = cell(ComponentPanelBuilder.createCommentComponent( + CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.ide.none.comment"), + false, -1, true) + ).component + cell() // To leave space on the right. + }.topGap(TopGap.NONE).bottomGap(BottomGap.NONE).layout(RowLayout.PARENT_GRID) row { label("Project directory:") cell(tfProject).resizableColumn().align(AlignX.FILL).component - cell() + cell() // To leave space on the right. }.topGap(TopGap.NONE).bottomGap(BottomGap.NONE).layout(RowLayout.PARENT_GRID) row { - cell() + cell() // Empty cell for alignment. terminalLink = cell( LazyBrowserLink( CoderIcons.OPEN_TERMINAL, diff --git a/src/main/resources/messages/CoderGatewayBundle.properties b/src/main/resources/messages/CoderGatewayBundle.properties index 95b34a1b..69f4f93f 100644 --- a/src/main/resources/messages/CoderGatewayBundle.properties +++ b/src/main/resources/messages/CoderGatewayBundle.properties @@ -26,6 +26,9 @@ gateway.connector.view.coder.remoteproject.ide.error.text=Could not retrieve any gateway.connector.view.coder.remoteproject.ssh.error.text=Can't connect to the workspace. Please make sure Coder Agent is running! gateway.connector.view.coder.remoteproject.next.text=Start IDE and connect gateway.connector.view.coder.remoteproject.choose.text=Choose IDE and project for workspace {0} +gateway.connector.view.coder.remoteproject.ide.download.comment=This IDE will be downloaded from jetbrains.com and installed to the default path on the remote host. +gateway.connector.view.coder.remoteproject.ide.installed.comment=This IDE is already installed and will be used as-is. +gateway.connector.view.coder.remoteproject.ide.none.comment=No IDE selected. gateway.connector.recentconnections.title=Recent Coder Workspaces gateway.connector.recentconnections.new.wizard.button.tooltip=Open a new Coder Workspace gateway.connector.recentconnections.remove.button.tooltip=Remove from Recent Connections From ee4d53f2c04c92b27e1dd1860f226544ac5c060d Mon Sep 17 00:00:00 2001 From: Asher Date: Thu, 23 Mar 2023 12:51:56 -0800 Subject: [PATCH 3/8] Standardize panel width Before we used an empty cell which created a gap on the right but that caused the IDE dropdown to change sizes based on its content. I removed `indent` and added an empty border so we get consistent padding on both sides although I have no idea if this is the idiomatic way to do this. --- .../views/CoderGatewayConnectorWizardView.kt | 21 ++-- .../steps/CoderLocateRemoteProjectStepView.kt | 109 +++++++++--------- .../views/steps/CoderWorkspacesStepView.kt | 106 +++++++++-------- 3 files changed, 126 insertions(+), 110 deletions(-) diff --git a/src/main/kotlin/com/coder/gateway/views/CoderGatewayConnectorWizardView.kt b/src/main/kotlin/com/coder/gateway/views/CoderGatewayConnectorWizardView.kt index 49673158..dc74a082 100644 --- a/src/main/kotlin/com/coder/gateway/views/CoderGatewayConnectorWizardView.kt +++ b/src/main/kotlin/com/coder/gateway/views/CoderGatewayConnectorWizardView.kt @@ -106,20 +106,18 @@ class CoderGatewayConnectorWizardView : BorderLayoutPanel(), Disposable { nextButton = JButton() return panel { separator(background = WelcomeScreenUIManager.getSeparatorColor()) - indent { - row { - - label("").resizableColumn().align(AlignX.FILL).gap(RightGap.SMALL) - previousButton = button("") { previous() }.align(AlignX.RIGHT).gap(RightGap.SMALL).applyToComponent { background = WelcomeScreenUIManager.getMainAssociatedComponentBackground() }.component - nextButton = button("") { next() }.align(AlignX.RIGHT).gap(RightGap.SMALL).applyToComponent { background = WelcomeScreenUIManager.getMainAssociatedComponentBackground() }.component - cell() - } - }.apply { - background = WelcomeScreenUIManager.getMainAssociatedComponentBackground() + row { + label("").resizableColumn().align(AlignX.FILL).gap(RightGap.SMALL) + previousButton = button("") { previous() } + .align(AlignX.RIGHT).gap(RightGap.SMALL) + .applyToComponent { background = WelcomeScreenUIManager.getMainAssociatedComponentBackground() }.component + nextButton = button("") { next() } + .align(AlignX.RIGHT) + .applyToComponent { background = WelcomeScreenUIManager.getMainAssociatedComponentBackground() }.component } - }.apply { background = WelcomeScreenUIManager.getMainAssociatedComponentBackground() + border = JBUI.Borders.empty(0, 16, 0, 16) } } @@ -127,4 +125,3 @@ class CoderGatewayConnectorWizardView : BorderLayoutPanel(), Disposable { steps.clear() } } - diff --git a/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt b/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt index a40be941..0d4f8f4d 100644 --- a/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt +++ b/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt @@ -30,12 +30,9 @@ import com.intellij.ui.AnimatedIcon import com.intellij.ui.ColoredListCellRenderer import com.intellij.ui.DocumentAdapter import com.intellij.ui.components.JBTextField -import com.intellij.ui.dsl.builder.AlignX -import com.intellij.ui.dsl.builder.BottomGap -import com.intellij.ui.dsl.builder.RowLayout -import com.intellij.ui.dsl.builder.TopGap -import com.intellij.ui.dsl.builder.panel +import com.intellij.ui.dsl.builder.* import com.intellij.util.ui.JBFont +import com.intellij.util.ui.JBUI import com.intellij.util.ui.UIUtil import com.intellij.util.ui.update.MergingUpdateQueue import com.intellij.util.ui.update.Update @@ -90,57 +87,63 @@ class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit private val pathValidationJobs = MergingUpdateQueue("remote-path-validation", 1000, true, tfProject) override val component = panel { - indent { - row { - titleLabel = label("").applyToComponent { - font = JBFont.h3().asBold() - icon = CoderIcons.LOGO_16 - }.component - }.topGap(TopGap.SMALL) - row { - label("IDE:") - cbIDE = cell(IDEComboBox(ideComboBoxModel).apply { - renderer = IDECellRenderer() - addActionListener { - ApplicationManager.getApplication().invokeLater { - logger.info("Selected IDE: ${this.selectedItem}") - when (this.selectedItem?.status) { - IdeStatus.ALREADY_INSTALLED -> - cbIDEComment.text = CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.ide.installed.comment") - IdeStatus.DOWNLOAD -> - cbIDEComment.text = CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.ide.download.comment") - else -> - cbIDEComment.text = CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.ide.none.comment") - } + row { + titleLabel = label("").applyToComponent { + font = JBFont.h3().asBold() + icon = CoderIcons.LOGO_16 + }.component + }.topGap(TopGap.SMALL) + row { + label("IDE:") + cbIDE = cell(IDEComboBox(ideComboBoxModel).apply { + renderer = IDECellRenderer() + addActionListener { + ApplicationManager.getApplication().invokeLater { + logger.info("Selected IDE: ${this.selectedItem}") + when (this.selectedItem?.status) { + IdeStatus.ALREADY_INSTALLED -> + cbIDEComment.text = + CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.ide.installed.comment") + + IdeStatus.DOWNLOAD -> + cbIDEComment.text = + CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.ide.download.comment") + + else -> + cbIDEComment.text = + CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.ide.none.comment") } } - }).resizableColumn().align(AlignX.FILL).component - cell() // To leave space on the right. - }.topGap(TopGap.NONE).bottomGap(BottomGap.NONE).layout(RowLayout.PARENT_GRID) - row { - cell() // Empty cell for alignment. - cbIDEComment = cell(ComponentPanelBuilder.createCommentComponent( + } + }).resizableColumn().align(AlignX.FILL).component + }.topGap(TopGap.NONE).bottomGap(BottomGap.NONE).layout(RowLayout.PARENT_GRID) + row { + cell() // Empty cell for alignment. + cbIDEComment = cell( + ComponentPanelBuilder.createCommentComponent( CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.ide.none.comment"), - false, -1, true) - ).component - cell() // To leave space on the right. - }.topGap(TopGap.NONE).bottomGap(BottomGap.NONE).layout(RowLayout.PARENT_GRID) - row { - label("Project directory:") - cell(tfProject).resizableColumn().align(AlignX.FILL).component - cell() // To leave space on the right. - }.topGap(TopGap.NONE).bottomGap(BottomGap.NONE).layout(RowLayout.PARENT_GRID) - row { - cell() // Empty cell for alignment. - terminalLink = cell( - LazyBrowserLink( - CoderIcons.OPEN_TERMINAL, - "Open Terminal" - ) - ).component - }.topGap(TopGap.NONE).layout(RowLayout.PARENT_GRID) - } - }.apply { background = WelcomeScreenUIManager.getMainAssociatedComponentBackground() } + false, -1, true + ) + ).component + }.topGap(TopGap.NONE).bottomGap(BottomGap.NONE).layout(RowLayout.PARENT_GRID) + row { + label("Project directory:") + cell(tfProject).resizableColumn().align(AlignX.FILL).component + }.topGap(TopGap.NONE).bottomGap(BottomGap.NONE).layout(RowLayout.PARENT_GRID) + row { + cell() // Empty cell for alignment. + terminalLink = cell( + LazyBrowserLink( + CoderIcons.OPEN_TERMINAL, + "Open Terminal" + ) + ).component + }.topGap(TopGap.NONE).layout(RowLayout.PARENT_GRID) + gap(RightGap.SMALL) + }.apply { + background = WelcomeScreenUIManager.getMainAssociatedComponentBackground() + border = JBUI.Borders.empty(0, 16, 0, 16) + } override val previousActionText = IdeBundle.message("button.back") override val nextActionText = CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.next.text") diff --git a/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt b/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt index efbc0b3b..cdad0a0d 100644 --- a/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt +++ b/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt @@ -194,55 +194,71 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) : private var poller: Job? = null override val component = panel { - indent { - row { - label(CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.header.text")).applyToComponent { - font = JBFont.h3().asBold() - icon = CoderIcons.LOGO_16 - } - }.topGap(TopGap.SMALL) - row { - cell(ComponentPanelBuilder.createCommentComponent(CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.comment"), false, -1, true)) - } - row { - browserLink(CoderGatewayBundle.message("gateway.connector.view.login.documentation.action"), "https://coder.com/docs/coder-oss/latest/workspaces") - } - row(CoderGatewayBundle.message("gateway.connector.view.login.url.label")) { - tfUrl = textField().resizableColumn().align(AlignX.FILL).gap(RightGap.SMALL).bindText(localWizardModel::coderURL).applyToComponent { - addActionListener { - poller?.cancel() - listTableModelOfWorkspaces.items = emptyList() - askTokenAndOpenSession(true) - } - }.component - button(CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.connect.text")) { + row { + label(CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.header.text")).applyToComponent { + font = JBFont.h3().asBold() + icon = CoderIcons.LOGO_16 + } + }.topGap(TopGap.SMALL) + row { + cell( + ComponentPanelBuilder.createCommentComponent( + CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.comment"), + false, + -1, + true + ) + ) + } + row { + browserLink( + CoderGatewayBundle.message("gateway.connector.view.login.documentation.action"), + "https://coder.com/docs/coder-oss/latest/workspaces" + ) + } + row(CoderGatewayBundle.message("gateway.connector.view.login.url.label")) { + tfUrl = textField().resizableColumn().align(AlignX.FILL).gap(RightGap.SMALL) + .bindText(localWizardModel::coderURL).applyToComponent { + addActionListener { poller?.cancel() listTableModelOfWorkspaces.items = emptyList() askTokenAndOpenSession(true) - }.applyToComponent { - background = WelcomeScreenUIManager.getMainAssociatedComponentBackground() } - cell() - } - row { - cbExistingToken = checkBox(CoderGatewayBundle.message("gateway.connector.view.login.existing-token.label")) - .bindSelected(localWizardModel::useExistingToken) - .component - } - row { - cell(ComponentPanelBuilder.createCommentComponent( - CoderGatewayBundle.message("gateway.connector.view.login.existing-token.tooltip", - CoderGatewayBundle.message("gateway.connector.view.login.existing-token.label")), - false, -1, true)) - } - row { - scrollCell(toolbar.createPanel().apply { - add(notificationBanner.component.apply { isVisible = false }, "South") - }).resizableColumn().align(AlignX.FILL).align(AlignY.FILL) - cell() - }.topGap(TopGap.NONE).bottomGap(BottomGap.NONE).resizableRow() - } - }.apply { background = WelcomeScreenUIManager.getMainAssociatedComponentBackground() } + }.component + button(CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.connect.text")) { + poller?.cancel() + listTableModelOfWorkspaces.items = emptyList() + askTokenAndOpenSession(true) + }.applyToComponent { + background = WelcomeScreenUIManager.getMainAssociatedComponentBackground() + } + } + row { + cbExistingToken = checkBox(CoderGatewayBundle.message("gateway.connector.view.login.existing-token.label")) + .bindSelected(localWizardModel::useExistingToken) + .component + } + row { + cell( + ComponentPanelBuilder.createCommentComponent( + CoderGatewayBundle.message( + "gateway.connector.view.login.existing-token.tooltip", + CoderGatewayBundle.message("gateway.connector.view.login.existing-token.label") + ), + false, -1, true + ) + ) + } + row { + scrollCell(toolbar.createPanel().apply { + add(notificationBanner.component.apply { isVisible = false }, "South") + }).resizableColumn().align(AlignX.FILL).align(AlignY.FILL) + }.topGap(TopGap.NONE).bottomGap(BottomGap.NONE).resizableRow() + + }.apply { + background = WelcomeScreenUIManager.getMainAssociatedComponentBackground() + border = JBUI.Borders.empty(0, 16, 0, 16) + } override val previousActionText = IdeBundle.message("button.back") override val nextActionText = CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.next.text") From 6c458b9449b7168472357f0418d38fa4ac7e0f2e Mon Sep 17 00:00:00 2001 From: Asher Date: Tue, 28 Mar 2023 14:16:53 -0800 Subject: [PATCH 4/8] Call out button name in existing token help message Just to help make it clear the checkbox applies to when the connect button is pressed and not the table below. --- .../com/coder/gateway/views/steps/CoderWorkspacesStepView.kt | 3 ++- src/main/resources/messages/CoderGatewayBundle.properties | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt b/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt index cdad0a0d..7d97b805 100644 --- a/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt +++ b/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt @@ -243,7 +243,8 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) : ComponentPanelBuilder.createCommentComponent( CoderGatewayBundle.message( "gateway.connector.view.login.existing-token.tooltip", - CoderGatewayBundle.message("gateway.connector.view.login.existing-token.label") + CoderGatewayBundle.message("gateway.connector.view.login.existing-token.label"), + CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.connect.text") ), false, -1, true ) diff --git a/src/main/resources/messages/CoderGatewayBundle.properties b/src/main/resources/messages/CoderGatewayBundle.properties index 69f4f93f..14f92f73 100644 --- a/src/main/resources/messages/CoderGatewayBundle.properties +++ b/src/main/resources/messages/CoderGatewayBundle.properties @@ -4,7 +4,7 @@ gateway.connector.action.text=Connect to Coder gateway.connector.view.login.documentation.action=Learn more about Coder gateway.connector.view.login.url.label=URL: gateway.connector.view.login.existing-token.label=Use existing token -gateway.connector.view.login.existing-token.tooltip=Checking "{0}" will prevent the browser from being launched for generating a new token. Additionally, if a token is already configured for this URL via the CLI it will appear as the default and can be used as-is or replaced. +gateway.connector.view.login.existing-token.tooltip=Checking "{0}" will prevent the browser from being launched for generating a new token after pressing "{1}". Additionally, if a token is already configured for this URL via the CLI it will appear as the default and can be used as-is or replaced. gateway.connector.view.login.token.dialog=Paste your token here: gateway.connector.view.login.token.label=Session Token: gateway.connector.view.coder.workspaces.header.text=Coder Workspaces From 1ca06f17f883d235713962cf5d0b4c14b8affb7d Mon Sep 17 00:00:00 2001 From: Asher Date: Tue, 28 Mar 2023 14:17:40 -0800 Subject: [PATCH 5/8] Align existing token checkbox with URL text box To help make it clear it applies to the connect action and not to whatever happens to be displayed below in the table. --- .../coder/gateway/views/steps/CoderWorkspacesStepView.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt b/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt index 7d97b805..aaff7803 100644 --- a/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt +++ b/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt @@ -232,13 +232,15 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) : }.applyToComponent { background = WelcomeScreenUIManager.getMainAssociatedComponentBackground() } - } + }.layout(RowLayout.PARENT_GRID) row { + cell() // Empty cell for alignment. cbExistingToken = checkBox(CoderGatewayBundle.message("gateway.connector.view.login.existing-token.label")) .bindSelected(localWizardModel::useExistingToken) .component - } + }.layout(RowLayout.PARENT_GRID) row { + cell() // Empty cell for alignment. cell( ComponentPanelBuilder.createCommentComponent( CoderGatewayBundle.message( @@ -249,7 +251,7 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) : false, -1, true ) ) - } + }.layout(RowLayout.PARENT_GRID) row { scrollCell(toolbar.createPanel().apply { add(notificationBanner.component.apply { isVisible = false }, "South") From fd46c431a32be423881397562d57e289f35c5613 Mon Sep 17 00:00:00 2001 From: Asher Date: Tue, 28 Mar 2023 14:22:56 -0800 Subject: [PATCH 6/8] Disable next button instead of removing it UI moving around can be confusing. --- .../gateway/views/CoderGatewayConnectorWizardView.kt | 11 ++++++----- .../views/steps/CoderLocateRemoteProjectStepView.kt | 7 ++++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/com/coder/gateway/views/CoderGatewayConnectorWizardView.kt b/src/main/kotlin/com/coder/gateway/views/CoderGatewayConnectorWizardView.kt index dc74a082..6e7c14f2 100644 --- a/src/main/kotlin/com/coder/gateway/views/CoderGatewayConnectorWizardView.kt +++ b/src/main/kotlin/com/coder/gateway/views/CoderGatewayConnectorWizardView.kt @@ -9,6 +9,7 @@ import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeScreenUIManager import com.intellij.ui.dsl.builder.AlignX import com.intellij.ui.dsl.builder.RightGap import com.intellij.ui.dsl.builder.panel +import com.intellij.util.ui.JBUI import com.intellij.util.ui.components.BorderLayoutPanel import com.jetbrains.gateway.api.GatewayUI import java.awt.Component @@ -30,11 +31,9 @@ class CoderGatewayConnectorWizardView : BorderLayoutPanel(), Disposable { background = WelcomeScreenUIManager.getMainAssociatedComponentBackground() registerStep(CoderWorkspacesStepView { nextButton.isEnabled = it }) - registerStep(CoderLocateRemoteProjectStepView { - nextButton.isVisible = false - }) + registerStep(CoderLocateRemoteProjectStepView { nextButton.isEnabled = it }) - addToBottom(createBackComponent()) + addToBottom(createButtons()) steps[0].apply { onInit(model) @@ -42,6 +41,7 @@ class CoderGatewayConnectorWizardView : BorderLayoutPanel(), Disposable { updateUI() nextButton.text = nextActionText previousButton.text = previousActionText + nextButton.isEnabled = false } } @@ -73,6 +73,7 @@ class CoderGatewayConnectorWizardView : BorderLayoutPanel(), Disposable { private fun showNavigationButtons() { nextButton.isVisible = true previousButton.isVisible = true + nextButton.isEnabled = false } private fun next() { @@ -101,7 +102,7 @@ class CoderGatewayConnectorWizardView : BorderLayoutPanel(), Disposable { } } - private fun createBackComponent(): Component { + private fun createButtons(): Component { previousButton = JButton() nextButton = JButton() return panel { diff --git a/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt b/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt index 0d4f8f4d..f6b447fe 100644 --- a/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt +++ b/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt @@ -71,7 +71,7 @@ import javax.swing.ListCellRenderer import javax.swing.SwingConstants import javax.swing.event.DocumentEvent -class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit) : CoderWorkspacesWizardStep, Disposable { +class CoderLocateRemoteProjectStepView(private val enableNextButton: (Boolean) -> Unit) : CoderWorkspacesWizardStep, Disposable { private val cs = CoroutineScope(Dispatchers.Main) private val coderClient: CoderRestClientService = ApplicationManager.getApplication().getService(CoderRestClientService::class.java) @@ -98,6 +98,7 @@ class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit cbIDE = cell(IDEComboBox(ideComboBoxModel).apply { renderer = IDECellRenderer() addActionListener { + enableNextButton(this.selectedItem != null) ApplicationManager.getApplication().invokeLater { logger.info("Selected IDE: ${this.selectedItem}") when (this.selectedItem?.status) { @@ -177,7 +178,7 @@ class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit is SshException -> { logger.error("Can't connect to workspace ${selectedWorkspace.name}. Reason: $e") withContext(Dispatchers.Main) { - disableNextAction() + enableNextButton(false) cbIDE.renderer = object : ColoredListCellRenderer() { override fun customizeCellRenderer(list: JList, value: IdeWithStatus?, index: Int, isSelected: Boolean, cellHasFocus: Boolean) { background = UIUtil.getListBackground(isSelected, cellHasFocus) @@ -191,7 +192,7 @@ class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit else -> { logger.error("Could not resolve any IDE for workspace ${selectedWorkspace.name}. Reason: $e") withContext(Dispatchers.Main) { - disableNextAction() + enableNextButton(false) cbIDE.renderer = object : ColoredListCellRenderer() { override fun customizeCellRenderer(list: JList, value: IdeWithStatus?, index: Int, isSelected: Boolean, cellHasFocus: Boolean) { background = UIUtil.getListBackground(isSelected, cellHasFocus) From 6107e79eaf65ce01c9bd27f8df80d37866b218ef Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 29 Mar 2023 11:44:42 -0800 Subject: [PATCH 7/8] Use better name for disabling/enabling next button --- .../views/steps/CoderLocateRemoteProjectStepView.kt | 8 ++++---- .../coder/gateway/views/steps/CoderWorkspacesStepView.kt | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt b/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt index f6b447fe..2b8d44de 100644 --- a/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt +++ b/src/main/kotlin/com/coder/gateway/views/steps/CoderLocateRemoteProjectStepView.kt @@ -71,7 +71,7 @@ import javax.swing.ListCellRenderer import javax.swing.SwingConstants import javax.swing.event.DocumentEvent -class CoderLocateRemoteProjectStepView(private val enableNextButton: (Boolean) -> Unit) : CoderWorkspacesWizardStep, Disposable { +class CoderLocateRemoteProjectStepView(private val setNextButtonEnabled: (Boolean) -> Unit) : CoderWorkspacesWizardStep, Disposable { private val cs = CoroutineScope(Dispatchers.Main) private val coderClient: CoderRestClientService = ApplicationManager.getApplication().getService(CoderRestClientService::class.java) @@ -98,7 +98,7 @@ class CoderLocateRemoteProjectStepView(private val enableNextButton: (Boolean) - cbIDE = cell(IDEComboBox(ideComboBoxModel).apply { renderer = IDECellRenderer() addActionListener { - enableNextButton(this.selectedItem != null) + setNextButtonEnabled(this.selectedItem != null) ApplicationManager.getApplication().invokeLater { logger.info("Selected IDE: ${this.selectedItem}") when (this.selectedItem?.status) { @@ -178,7 +178,7 @@ class CoderLocateRemoteProjectStepView(private val enableNextButton: (Boolean) - is SshException -> { logger.error("Can't connect to workspace ${selectedWorkspace.name}. Reason: $e") withContext(Dispatchers.Main) { - enableNextButton(false) + setNextButtonEnabled(false) cbIDE.renderer = object : ColoredListCellRenderer() { override fun customizeCellRenderer(list: JList, value: IdeWithStatus?, index: Int, isSelected: Boolean, cellHasFocus: Boolean) { background = UIUtil.getListBackground(isSelected, cellHasFocus) @@ -192,7 +192,7 @@ class CoderLocateRemoteProjectStepView(private val enableNextButton: (Boolean) - else -> { logger.error("Could not resolve any IDE for workspace ${selectedWorkspace.name}. Reason: $e") withContext(Dispatchers.Main) { - enableNextButton(false) + setNextButtonEnabled(false) cbIDE.renderer = object : ColoredListCellRenderer() { override fun customizeCellRenderer(list: JList, value: IdeWithStatus?, index: Int, isSelected: Boolean, cellHasFocus: Boolean) { background = UIUtil.getListBackground(isSelected, cellHasFocus) diff --git a/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt b/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt index aaff7803..69b6e1cf 100644 --- a/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt +++ b/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt @@ -89,7 +89,7 @@ private const val SESSION_TOKEN = "session-token" private const val MOUSE_OVER_TEMPLATE_NAME_COLUMN_ON_ROW = "MOUSE_OVER_TEMPLATE_NAME_COLUMN_ON_ROW" -class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) : CoderWorkspacesWizardStep, Disposable { +class CoderWorkspacesStepView(val setNextButtonEnabled: (Boolean) -> Unit) : CoderWorkspacesWizardStep, Disposable { private val cs = CoroutineScope(Dispatchers.Main) private var localWizardModel = CoderWorkspacesWizardModel() private val coderClient: CoderRestClientService = service() @@ -122,7 +122,7 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) : rowHeight = 48 setSelectionMode(ListSelectionModel.SINGLE_SELECTION) selectionModel.addListSelectionListener { - enableNextButtonCallback(selectedObject != null && selectedObject?.agentStatus == RUNNING && selectedObject?.agentOS == OS.LINUX) + setNextButtonEnabled(selectedObject != null && selectedObject?.agentStatus == RUNNING && selectedObject?.agentOS == OS.LINUX) if (selectedObject?.agentStatus == RUNNING && selectedObject?.agentOS != OS.LINUX) { notificationBanner.apply { component.isVisible = true From 12f3956f6b263b4f143937bd73afac5b4eb651a2 Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 29 Mar 2023 11:54:04 -0800 Subject: [PATCH 8/8] Add help text and alignment fixes to changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3d6c1b5..34a1ecba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ ## Unreleased +### Fixed +- the help text under the IDE dropdown now takes into account whether the IDE is + already installed +- various minor alignment issues + ### Fixed - reading an existing config would sometimes use the wrong directory on Linux - two separate SSH sessions would spawn when connecting to a workspace through