diff --git a/CHANGELOG.md b/CHANGELOG.md index adf978a2..690093b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - warning system when plugin might not be compatible with Coder REST API - a `Create workspace` button which links to Coder's templates page - workspace icons +- quick toolbar action to open Coder Dashboard in the browser ### Changed - redesigned the information&warning banner. Messages can now include hyperlinks diff --git a/src/main/kotlin/com/coder/gateway/icons/CoderIcons.kt b/src/main/kotlin/com/coder/gateway/icons/CoderIcons.kt index dbf2b4d8..c2199a41 100644 --- a/src/main/kotlin/com/coder/gateway/icons/CoderIcons.kt +++ b/src/main/kotlin/com/coder/gateway/icons/CoderIcons.kt @@ -8,6 +8,7 @@ object CoderIcons { val OPEN_TERMINAL = IconLoader.getIcon("open_terminal.svg", javaClass) + val HOME = IconLoader.getIcon("homeFolder.svg", javaClass) val CREATE = IconLoader.getIcon("create.svg", javaClass) val RUN = IconLoader.getIcon("run.svg", javaClass) val STOP = IconLoader.getIcon("stop.svg", javaClass) diff --git a/src/main/kotlin/com/coder/gateway/sdk/CoderRestClientService.kt b/src/main/kotlin/com/coder/gateway/sdk/CoderRestClientService.kt index c8b2102d..485d3596 100644 --- a/src/main/kotlin/com/coder/gateway/sdk/CoderRestClientService.kt +++ b/src/main/kotlin/com/coder/gateway/sdk/CoderRestClientService.kt @@ -28,6 +28,8 @@ import java.util.UUID @Service(Service.Level.APP) class CoderRestClientService { + var isReady: Boolean = false + private set private lateinit var httpClient: OkHttpClient private lateinit var retroRestClient: CoderV2RestFacade private lateinit var sessionToken: String @@ -40,21 +42,10 @@ class CoderRestClientService { * @throws [AuthenticationResponseException] if authentication failed. */ fun initClientSession(url: URL, token: String): User { - val gson: Gson = GsonBuilder() - .registerTypeAdapter(Instant::class.java, InstantConverter()) - .setPrettyPrinting() - .create() - httpClient = OkHttpClient.Builder() - .addInterceptor { it.proceed(it.request().newBuilder().addHeader("Coder-Session-Token", token).build()) } - .addInterceptor(HttpLoggingInterceptor().apply { setLevel(HttpLoggingInterceptor.Level.BASIC) }) - .build() - - retroRestClient = Retrofit.Builder() - .baseUrl(url.toString()) - .client(httpClient) - .addConverterFactory(GsonConverterFactory.create(gson)) - .build() - .create(CoderV2RestFacade::class.java) + val gson: Gson = GsonBuilder().registerTypeAdapter(Instant::class.java, InstantConverter()).setPrettyPrinting().create() + httpClient = OkHttpClient.Builder().addInterceptor { it.proceed(it.request().newBuilder().addHeader("Coder-Session-Token", token).build()) }.addInterceptor(HttpLoggingInterceptor().apply { setLevel(HttpLoggingInterceptor.Level.BASIC) }).build() + + retroRestClient = Retrofit.Builder().baseUrl(url.toString()).client(httpClient).addConverterFactory(GsonConverterFactory.create(gson)).build().create(CoderV2RestFacade::class.java) val userResponse = retroRestClient.me().execute() if (!userResponse.isSuccessful) { @@ -65,7 +56,7 @@ class CoderRestClientService { sessionToken = token me = userResponse.body()!! buildVersion = buildInfo().version - + isReady = true return me } 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 fdb7dc8e..fd6a5874 100644 --- a/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt +++ b/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt @@ -125,6 +125,7 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) : } } + private val goToDashboardAction = GoToDashboardAction() private val startWorkspaceAction = StartWorkspaceAction() private val stopWorkspaceAction = StopWorkspaceAction() private val updateWorkspaceTemplateAction = UpdateWorkspaceTemplateAction() @@ -134,6 +135,7 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) : .disableAddAction() .disableRemoveAction() .disableUpDownActions() + .addExtraAction(goToDashboardAction) .addExtraAction(startWorkspaceAction) .addExtraAction(stopWorkspaceAction) .addExtraAction(updateWorkspaceTemplateAction) @@ -183,6 +185,12 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) : override val previousActionText = IdeBundle.message("button.back") override val nextActionText = CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.next.text") + private inner class GoToDashboardAction : AnActionButton(CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.dashboard.text"), CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.dashboard.text"), CoderIcons.HOME) { + override fun actionPerformed(p0: AnActionEvent) { + BrowserUtil.browse(coderClient.coderURL) + } + } + private inner class StartWorkspaceAction : AnActionButton(CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.start.text"), CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.start.text"), CoderIcons.RUN) { override fun actionPerformed(p0: AnActionEvent) { if (tableOfWorkspaces.selectedObject != null) { @@ -221,12 +229,6 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) : } } - private inner class CreateWorkspaceAction : AnActionButton(CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.create.text"), CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.create.text"), CoderIcons.CREATE) { - override fun actionPerformed(p0: AnActionEvent) { - BrowserUtil.browse(coderClient.coderURL.toURI().resolve("/templates")) - } - } - private inner class StopWorkspaceAction : AnActionButton(CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.stop.text"), CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.stop.text"), CoderIcons.STOP) { override fun actionPerformed(p0: AnActionEvent) { if (tableOfWorkspaces.selectedObject != null) { @@ -245,6 +247,12 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) : } } + private inner class CreateWorkspaceAction : AnActionButton(CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.create.text"), CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.create.text"), CoderIcons.CREATE) { + override fun actionPerformed(p0: AnActionEvent) { + BrowserUtil.browse(coderClient.coderURL.toURI().resolve("/templates")) + } + } + override fun onInit(wizardModel: CoderWorkspacesWizardModel) { enableNextButtonCallback(false) if (localWizardModel.coderURL.isNotBlank() && localWizardModel.token.isNotBlank()) { @@ -265,8 +273,8 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) : } private fun updateWorkspaceActions() { - createWorkspaceAction.isEnabled = true - + goToDashboardAction.isEnabled = coderClient.isReady + createWorkspaceAction.isEnabled = coderClient.isReady when (tableOfWorkspaces.selectedObject?.agentStatus) { RUNNING -> { startWorkspaceAction.isEnabled = false @@ -380,6 +388,7 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) : cs.launch { ProgressManager.getInstance().run(authTask) } + updateWorkspaceActions() triggerWorkspacePolling() } diff --git a/src/main/resources/homeFolder.svg b/src/main/resources/homeFolder.svg new file mode 100644 index 00000000..2d482b28 --- /dev/null +++ b/src/main/resources/homeFolder.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/main/resources/homeFolder_dark.svg b/src/main/resources/homeFolder_dark.svg new file mode 100644 index 00000000..b7ba16ba --- /dev/null +++ b/src/main/resources/homeFolder_dark.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/main/resources/messages/CoderGatewayBundle.properties b/src/main/resources/messages/CoderGatewayBundle.properties index 8611e344..784f84cb 100644 --- a/src/main/resources/messages/CoderGatewayBundle.properties +++ b/src/main/resources/messages/CoderGatewayBundle.properties @@ -11,6 +11,7 @@ gateway.connector.view.coder.workspaces.connect.text=Connect gateway.connector.view.coder.workspaces.cli.downloader.dialog.title=Authenticate and setup Coder gateway.connector.view.coder.workspaces.cli.configssh.dialog.title=Coder Config SSH gateway.connector.view.coder.workspaces.next.text=Select IDE and Project +gateway.connector.view.coder.workspaces.dashboard.text=Open Dashboard gateway.connector.view.coder.workspaces.start.text=Start Workspace gateway.connector.view.coder.workspaces.stop.text=Stop Workspace gateway.connector.view.coder.workspaces.update.text=Update Workspace Template