Skip to content

Commit 83cf3e2

Browse files
authored
Merge pull request #50 from coder/stabilize-flows
Fix bugs and stabilize flows Fix overlapping components in the Connections view - `Recent Coder Workspaces` overlaps with the search bar. - reworked the first row to workaround the DSL limitations. - resolves #44 Change links to documentation - to point at latest Coder OSS instead of V1 - resolve #48 Change main action link - from `Connect to Coder Workspaces` to `Connect to Coder` - the wording was too long, and a bit confusing. - main documentation link now points to the general documentation about Coder, not only specifics for Workspaces - resolves #49 Show working workspaces when there are issues with resolving agents - finer grained error handling when resolving agents - resolves #51 Fix: list only workspaces owned by the logged user - right now all workspaces are listed to which a user has access to. Which means the user can open a project on a workspace he does not own. - resolves #53
2 parents a64ed3f + 382f363 commit 83cf3e2

9 files changed

+86
-61
lines changed

CHANGELOG.md

+19-11
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
<!-- Keep a Changelog guide -> https://keepachangelog.com -->
22

3-
# coder-gateway Changelog
4-
5-
## [Unreleased]
6-
7-
## [2.0.0]
3+
# coder-gateway Changelog
4+
5+
## [Unreleased]
6+
### Fixed
7+
- `Recent Coder Workspaces` label overlaps with the search bar in the `Connections` view
8+
- working Workspaces are now listed when there are issues with resolving agents
9+
- list only workspaces owned by the logged user
10+
11+
### Changed
12+
- links to documentation now point to the latest Coder OSS
13+
- simplified main action link text from `Connect to Coder Workspaces` to `Connect to Coder`
14+
15+
## [2.0.0]
816
### Added
917
- support for Gateway 2022.2
10-
11-
18+
19+
1220
### Changed
1321
- Java 17 is now required to run the plugin
14-
- adapted the code to the new SSH API provided by Gateway
15-
16-
## [1.0.0]
17-
### Added
22+
- adapted the code to the new SSH API provided by Gateway
23+
24+
## [1.0.0]
25+
### Added
1826
- initial scaffold for Gateway plugin
1927
- browser based authentication on Coder environments
2028
- REST client for Coder V2 public API

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Follow](https://img.shields.io/twitter/follow/CoderHQ?label=%40CoderHQ&style=soc
77
[![Coder Gateway Plugin Build](https://github.com/coder/coder-jetbrains/actions/workflows/build.yml/badge.svg)](https://github.com/coder/coder-jetbrains/actions/workflows/build.yml)
88

99
<!-- Plugin description -->
10-
**Coder Gateway** connects your Jetbrains IDE to your [Coder Workspaces](https://coder.com/docs/coder/latest/workspaces) so that you can develop from anywhere.
10+
**Coder Gateway** connects your Jetbrains IDE to your [Coder Workspaces](https://coder.com/docs/coder-oss/latest/workspaces) so that you can develop from anywhere.
1111

1212
**Manage less**
1313

src/main/kotlin/com/coder/gateway/CoderGatewayMainView.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class CoderGatewayMainView : GatewayConnector {
3232
}
3333

3434
override fun getDocumentationLink(): ActionLink {
35-
return BrowserLink("Learn more about Coder Workspaces", "https://coder.com/docs/coder/latest/workspaces")
35+
return BrowserLink("Learn more", "https://coder.com/docs/coder-oss/latest")
3636
}
3737

3838
override fun getRecentConnections(setContentCallback: (Component) -> Unit): GatewayRecentConnections {

src/main/kotlin/com/coder/gateway/sdk/CoderRestClientService.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class CoderRestClientService {
8080
* @throws WorkspaceResponseException if workspaces could not be retrieved.
8181
*/
8282
fun workspaces(): List<Workspace> {
83-
val workspacesResponse = retroRestClient.workspaces().execute()
83+
val workspacesResponse = retroRestClient.workspaces("owner:me").execute()
8484
if (!workspacesResponse.isSuccessful) {
8585
throw WorkspaceResponseException("Could not retrieve Coder Workspaces:${workspacesResponse.code()}, reason: ${workspacesResponse.message()}")
8686
}

src/main/kotlin/com/coder/gateway/sdk/v2/CoderV2RestFacade.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import com.coder.gateway.sdk.v2.models.WorkspaceResource
77
import retrofit2.Call
88
import retrofit2.http.GET
99
import retrofit2.http.Path
10+
import retrofit2.http.Query
1011
import java.util.UUID
1112

1213
interface CoderV2RestFacade {
@@ -21,7 +22,7 @@ interface CoderV2RestFacade {
2122
* Retrieves all workspaces the authenticated user has access to.
2223
*/
2324
@GET("api/v2/workspaces")
24-
fun workspaces(): Call<List<Workspace>>
25+
fun workspaces(@Query("q") searchParams: String): Call<List<Workspace>>
2526

2627
@GET("api/v2/buildinfo")
2728
fun buildInfo(): Call<BuildInfo>

src/main/kotlin/com/coder/gateway/views/CoderGatewayRecentWorkspaceConnectionsView.kt

+34-27
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import kotlinx.coroutines.cancel
3939
import kotlinx.coroutines.launch
4040
import java.awt.Dimension
4141
import javax.swing.JComponent
42+
import javax.swing.JLabel
4243
import javax.swing.event.DocumentEvent
4344

4445
class CoderGatewayRecentWorkspaceConnectionsView : GatewayRecentConnections, Disposable {
@@ -62,36 +63,42 @@ class CoderGatewayRecentWorkspaceConnectionsView : GatewayRecentConnections, Dis
6263
label(CoderGatewayBundle.message("gateway.connector.recentconnections.title")).applyToComponent {
6364
font = JBFont.h3().asBold()
6465
}
65-
label("").resizableColumn().horizontalAlign(HorizontalAlign.FILL)
66-
searchBar = cell(SearchTextField(false)).applyToComponent {
67-
minimumSize = Dimension(350, -1)
68-
textEditor.border = JBUI.Borders.empty(2, 5, 2, 0)
69-
addDocumentListener(object : DocumentAdapter() {
70-
override fun textChanged(e: DocumentEvent) {
71-
val toSearchFor = this@applyToComponent.text
72-
val filteredConnections = recentConnectionsService.getAllRecentConnections().filter { it.coderWorkspaceHostname?.toLowerCase()?.contains(toSearchFor) ?: false || it.projectPath?.toLowerCase()?.contains(toSearchFor) ?: false }
73-
updateContentView(filteredConnections.groupBy { it.coderWorkspaceHostname })
74-
}
75-
})
76-
}.component
66+
panel {
67+
indent {
68+
row {
69+
cell(JLabel()).resizableColumn().horizontalAlign(HorizontalAlign.FILL)
70+
searchBar = cell(SearchTextField(false)).resizableColumn().horizontalAlign(HorizontalAlign.FILL).applyToComponent {
71+
minimumSize = Dimension(350, -1)
72+
textEditor.border = JBUI.Borders.empty(2, 5, 2, 0)
73+
addDocumentListener(object : DocumentAdapter() {
74+
override fun textChanged(e: DocumentEvent) {
75+
val toSearchFor = this@applyToComponent.text
76+
val filteredConnections = recentConnectionsService.getAllRecentConnections().filter { it.coderWorkspaceHostname?.toLowerCase()?.contains(toSearchFor) ?: false || it.projectPath?.toLowerCase()?.contains(toSearchFor) ?: false }
77+
updateContentView(filteredConnections.groupBy { it.coderWorkspaceHostname })
78+
}
79+
})
80+
}.component
7781

78-
actionButton(
79-
object : DumbAwareAction(CoderGatewayBundle.message("gateway.connector.recentconnections.new.wizard.button.tooltip"), null, AllIcons.General.Add) {
80-
override fun actionPerformed(e: AnActionEvent) {
81-
rootPanel.apply {
82-
removeAll()
83-
addToCenter(CoderGatewayConnectorWizardWrapperView {
84-
rootPanel.apply {
85-
removeAll()
86-
addToCenter(contentPanel)
87-
updateUI()
82+
actionButton(
83+
object : DumbAwareAction(CoderGatewayBundle.message("gateway.connector.recentconnections.new.wizard.button.tooltip"), null, AllIcons.General.Add) {
84+
override fun actionPerformed(e: AnActionEvent) {
85+
rootPanel.apply {
86+
removeAll()
87+
addToCenter(CoderGatewayConnectorWizardWrapperView {
88+
rootPanel.apply {
89+
removeAll()
90+
addToCenter(contentPanel)
91+
updateUI()
92+
}
93+
}.component)
94+
updateUI()
95+
}
8896
}
89-
}.component)
90-
updateUI()
91-
}
97+
},
98+
).gap(RightGap.SMALL)
9299
}
93-
},
94-
).gap(RightGap.SMALL)
100+
}
101+
}
95102
}.bottomGap(BottomGap.MEDIUM)
96103
separator(background = WelcomeScreenUIManager.getSeparatorColor())
97104
row {

src/main/kotlin/com/coder/gateway/views/steps/CoderAuthStepView.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class CoderAuthStepView(private val nextAction: () -> Unit) : CoderWorkspacesWiz
5757
cell(ComponentPanelBuilder.createCommentComponent(CoderGatewayBundle.message("gateway.connector.view.login.comment.text"), false, -1, true))
5858
}
5959
row {
60-
browserLink(CoderGatewayBundle.message("gateway.connector.view.login.documentation.action"), "https://coder.com/docs/coder/latest/workspaces")
60+
browserLink(CoderGatewayBundle.message("gateway.connector.view.login.documentation.action"), "https://coder.com/docs/coder-oss/latest/workspaces")
6161
}.bottomGap(BottomGap.MEDIUM)
6262
row(CoderGatewayBundle.message("gateway.connector.view.login.url.label")) {
6363
textField().resizableColumn().horizontalAlign(HorizontalAlign.FILL).gap(RightGap.SMALL).bindText(model::coderURL).applyToComponent {

src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt

+26-17
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import com.coder.gateway.sdk.Arch
88
import com.coder.gateway.sdk.CoderRestClientService
99
import com.coder.gateway.sdk.OS
1010
import com.coder.gateway.sdk.v2.models.ProvisionerJobStatus
11+
import com.coder.gateway.sdk.v2.models.Workspace
1112
import com.coder.gateway.sdk.v2.models.WorkspaceBuildTransition
1213
import com.intellij.ide.IdeBundle
1314
import com.intellij.openapi.Disposable
@@ -87,23 +88,7 @@ class CoderWorkspacesStepView : CoderWorkspacesWizardStep, Disposable {
8788
cs.launch {
8889
val workspaceList = withContext(Dispatchers.IO) {
8990
try {
90-
val workspaces = coderClient.workspaces()
91-
return@withContext workspaces.flatMap { workspace ->
92-
val agents = coderClient.workspaceAgents(workspace)
93-
val shouldContainAgentName = agents.size > 1
94-
agents.map { agent ->
95-
val workspaceName = if (shouldContainAgentName) "${workspace.name}.${agent.name}" else workspace.name
96-
WorkspaceAgentModel(
97-
workspaceName,
98-
workspace.templateName,
99-
workspace.latestBuild.job.status,
100-
workspace.latestBuild.workspaceTransition,
101-
OS.from(agent.operatingSystem),
102-
Arch.from(agent.architecture),
103-
agent.directory
104-
)
105-
}
106-
}
91+
return@withContext coderClient.workspaces().collectAgents()
10792
} catch (e: Exception) {
10893
logger.error("Could not retrieve workspaces for ${coderClient.me.username} on ${coderClient.coderURL}. Reason: $e")
10994
emptyList()
@@ -115,6 +100,30 @@ class CoderWorkspacesStepView : CoderWorkspacesWizardStep, Disposable {
115100
}
116101
}
117102

103+
private fun List<Workspace>.collectAgents(): List<WorkspaceAgentModel> {
104+
return this.flatMap { workspace ->
105+
try {
106+
val agents = coderClient.workspaceAgents(workspace)
107+
val shouldContainAgentName = agents.size > 1
108+
return@flatMap agents.map { agent ->
109+
val workspaceName = if (shouldContainAgentName) "${workspace.name}.${agent.name}" else workspace.name
110+
WorkspaceAgentModel(
111+
workspaceName,
112+
workspace.templateName,
113+
workspace.latestBuild.job.status,
114+
workspace.latestBuild.workspaceTransition,
115+
OS.from(agent.operatingSystem),
116+
Arch.from(agent.architecture),
117+
agent.directory
118+
)
119+
}
120+
} catch (e: Exception) {
121+
logger.error("Skipping workspace ${workspace.name} because we could not retrieve the agent(s). Reason: $e")
122+
emptyList()
123+
}
124+
}
125+
}
126+
118127
override fun onNext(wizardModel: CoderWorkspacesWizardModel): Boolean {
119128
val workspace = tableOfWorkspaces.selectedObject
120129
if (workspace != null) {

src/main/resources/messages/CoderGatewayBundle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
gateway.connector.title=Coder
22
gateway.connector.description=Connects to a Coder Workspace dev environment so that you can develop from anywhere
3-
gateway.connector.action.text=Connect to Coder Workspaces
3+
gateway.connector.action.text=Connect to Coder
44
gateway.connector.view.login.header.text=Coder Workspaces
55
gateway.connector.view.login.comment.text=Self-hosted developer workspaces in the cloud or on premise. Coder Workspaces empower developers with secure, consistent, and fast developer workspaces.
66
gateway.connector.view.login.documentation.action=Explore Coder Workspaces

0 commit comments

Comments
 (0)