@@ -4,12 +4,15 @@ import com.coder.gateway.models.WorkspaceAndAgentStatus
44import com.coder.gateway.sdk.CoderRestClient
55import com.coder.gateway.sdk.v2.models.Workspace
66import com.coder.gateway.sdk.v2.models.WorkspaceAgent
7+ import com.coder.gateway.util.withPath
8+ import com.coder.gateway.views.Action
79import com.coder.gateway.views.EnvironmentView
810import com.jetbrains.toolbox.gateway.AbstractRemoteProviderEnvironment
911import com.jetbrains.toolbox.gateway.EnvironmentVisibilityState
1012import com.jetbrains.toolbox.gateway.environments.EnvironmentContentsView
1113import com.jetbrains.toolbox.gateway.states.EnvironmentStateConsumer
1214import com.jetbrains.toolbox.gateway.ui.ObservablePropertiesFactory
15+ import com.jetbrains.toolbox.gateway.ui.ToolboxUi
1316import java.util.concurrent.CompletableFuture
1417
1518/* *
@@ -19,18 +22,60 @@ import java.util.concurrent.CompletableFuture
1922 */
2023class CoderRemoteEnvironment (
2124 private val client : CoderRestClient ,
22- private val workspace : Workspace ,
23- private val agent : WorkspaceAgent ,
25+ private var workspace : Workspace ,
26+ private var agent : WorkspaceAgent ,
27+ private val ui : ToolboxUi ,
2428 observablePropertiesFactory : ObservablePropertiesFactory ,
2529) : AbstractRemoteProviderEnvironment(observablePropertiesFactory) {
2630 override fun getId (): String = " ${workspace.name} .${agent.name} "
2731 override fun getName (): String = " ${workspace.name} .${agent.name} "
2832 private var status = WorkspaceAndAgentStatus .from(workspace, agent)
2933
34+ init {
35+ actionsList.add(
36+ Action (" Open web terminal" ) {
37+ ui.openUrl(client.url.withPath(" /${workspace.ownerName} /$name /terminal" ).toString())
38+ },
39+ )
40+ actionsList.add(
41+ Action (" Open in dashboard" ) {
42+ ui.openUrl(client.url.withPath(" /@${workspace.ownerName} /${workspace.name} " ).toString())
43+ },
44+ )
45+ actionsList.add(
46+ Action (" View template" ) {
47+ ui.openUrl(client.url.withPath(" /templates/${workspace.templateName} " ).toString())
48+ },
49+ )
50+ actionsList.add(
51+ Action (" Start" , enabled = { status.canStart() }) {
52+ val build = client.startWorkspace(workspace)
53+ workspace = workspace.copy(latestBuild = build)
54+ update(workspace, agent)
55+ },
56+ )
57+ actionsList.add(
58+ Action (" Stop" , enabled = { status.ready() || status.pending() }) {
59+ val build = client.stopWorkspace(workspace)
60+ workspace = workspace.copy(latestBuild = build)
61+ update(workspace, agent)
62+ },
63+ )
64+ actionsList.add(
65+ Action (" Update" , enabled = { workspace.outdated }) {
66+ val build = client.updateWorkspace(workspace)
67+ workspace = workspace.copy(latestBuild = build)
68+ update(workspace, agent)
69+ },
70+ )
71+ }
72+
3073 /* *
3174 * Update the workspace/agent status to the listeners, if it has changed.
3275 */
3376 fun update (workspace : Workspace , agent : WorkspaceAgent ) {
77+ this .workspace = workspace
78+ this .agent = agent
3479 val newStatus = WorkspaceAndAgentStatus .from(workspace, agent)
3580 if (newStatus != status) {
3681 status = newStatus
@@ -58,6 +103,11 @@ class CoderRemoteEnvironment(
58103 * Immediately send the state to the listener and store for updates.
59104 */
60105 override fun addStateListener (consumer : EnvironmentStateConsumer ): Boolean {
106+ // TODO@JB: It would be ideal if we could have the workspace state and
107+ // the connected state listed separately, since right now the
108+ // connected state can mask the workspace state.
109+ // TODO@JB: You can still press connect if the environment is
110+ // unreachable. Is that expected?
61111 consumer.consume(status.toRemoteEnvironmentState())
62112 return super .addStateListener(consumer)
63113 }
0 commit comments