Skip to content

Commit a83b0bc

Browse files
committed
Preserve selection when workspaces starts or stops
When a workspace starts the workspace row is replaced with a row for the agent(s) and you have to select it again which is annoying (similarly for when the workspace stops). This preserves the selection when the workspace transitions.
1 parent f9c8573 commit a83b0bc

File tree

3 files changed

+88
-14
lines changed

3 files changed

+88
-14
lines changed

src/main/kotlin/com/coder/gateway/models/WorkspaceAgentModel.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,16 @@ import com.coder.gateway.sdk.v2.models.WorkspaceTransition
77
import java.util.UUID
88
import javax.swing.Icon
99

10+
// TODO: Refactor to have a list of workspaces that each have agents. We
11+
// present in the UI as a single flat list in the table (when there are no
12+
// agents we display a row for the workspace) but still, a list of workspaces
13+
// each with a list of agents might reflect reality more closely. When we
14+
// iterate over the list we can add the workspace row if it has no agents
15+
// otherwise iterate over the agents and then flatten the result.
1016
data class WorkspaceAgentModel(
1117
val workspaceID: UUID,
1218
val workspaceName: String,
13-
val name: String,
19+
val name: String, // Name of the workspace OR the agent if this is for an agent.
1420
val templateID: UUID,
1521
val templateName: String,
1622
val templateIconPath: String,

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

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -669,11 +669,9 @@ class CoderWorkspacesStepView(val setNextButtonEnabled: (Boolean) -> Unit) : Cod
669669
}
670670
}
671671
withContext(Dispatchers.Main) {
672-
val selectedWorkspace = tableOfWorkspaces.selectedObject?.name
672+
val selectedWorkspace = tableOfWorkspaces.selectedObject
673673
tableOfWorkspaces.listTableModel.items = ws.toList()
674-
if (selectedWorkspace != null) {
675-
tableOfWorkspaces.selectItem(selectedWorkspace)
676-
}
674+
tableOfWorkspaces.selectItem(selectedWorkspace)
677675
}
678676
}
679677

@@ -923,15 +921,31 @@ class WorkspacesTableModel : ListTableModel<WorkspaceAgentModel>(
923921
}
924922

925923
class WorkspacesTable : TableView<WorkspaceAgentModel>(WorkspacesTableModel()) {
926-
fun selectItem(workspaceName: String?) {
927-
if (workspaceName != null) {
928-
this.items.forEachIndexed { index, workspaceAgentModel ->
929-
if (workspaceAgentModel.name == workspaceName) {
930-
selectionModel.addSelectionInterval(convertRowIndexToView(index), convertRowIndexToView(index))
931-
// fix cell selection case
932-
columnModel.selectionModel.addSelectionInterval(0, columnCount - 1)
933-
}
934-
}
924+
/**
925+
* Given either a workspace or an agent select in order of preference:
926+
* 1. That same agent or workspace.
927+
* 2. The first match for the workspace (workspace itself or first agent).
928+
*/
929+
fun selectItem(workspace: WorkspaceAgentModel?) {
930+
val index = getNewSelection(workspace)
931+
if (index > -1) {
932+
selectionModel.addSelectionInterval(convertRowIndexToView(index), convertRowIndexToView(index))
933+
// Fix cell selection case.
934+
columnModel.selectionModel.addSelectionInterval(0, columnCount - 1)
935935
}
936936
}
937+
938+
private fun getNewSelection(oldSelection: WorkspaceAgentModel?): Int {
939+
if (oldSelection == null) {
940+
return -1
941+
}
942+
val index = listTableModel.items.indexOfFirst {
943+
it.name == oldSelection.name && it.workspaceName == oldSelection.workspaceName
944+
}
945+
if (index > -1) {
946+
return index
947+
}
948+
return listTableModel.items.indexOfFirst { it.workspaceName == oldSelection.workspaceName }
949+
}
950+
937951
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import com.coder.gateway.views.steps.WorkspacesTable
2+
import spock.lang.Specification
3+
import spock.lang.Unroll
4+
5+
@Unroll
6+
class CoderWorkspacesStepViewTest extends Specification {
7+
def "gets new selection"() {
8+
given:
9+
def table = new WorkspacesTable()
10+
table.listTableModel.items = List.of(
11+
// An off workspace.
12+
DataGen.workspace("ws1", "ws1"),
13+
14+
// On workspaces.
15+
DataGen.workspace("agent1", "ws2"),
16+
DataGen.workspace("agent2", "ws2"),
17+
DataGen.workspace("agent3", "ws3"),
18+
19+
// Another off workspace.
20+
DataGen.workspace("ws4", "ws4"),
21+
22+
// In practice we do not list both agents and workspaces
23+
// together but here test that anyway with an agent first and
24+
// then with a workspace first.
25+
DataGen.workspace("agent2", "ws5"),
26+
DataGen.workspace("ws5", "ws5"),
27+
DataGen.workspace("ws6", "ws6"),
28+
DataGen.workspace("agent3", "ws6"),
29+
)
30+
31+
expect:
32+
table.getNewSelection(selected) == expected
33+
34+
where:
35+
selected | expected
36+
null | -1 // No selection.
37+
DataGen.workspace("gone", "gone") | -1 // No workspace that matches.
38+
DataGen.workspace("ws1", "ws1") | 0 // Workspace exact match.
39+
DataGen.workspace("gone", "ws1") | 0 // Agent gone, select workspace.
40+
DataGen.workspace("ws2", "ws2") | 1 // Workspace gone, select first agent.
41+
DataGen.workspace("agent1", "ws2") | 1 // Agent exact match.
42+
DataGen.workspace("agent2", "ws2") | 2 // Agent exact match.
43+
DataGen.workspace("ws3", "ws3") | 3 // Workspace gone, select first agent.
44+
DataGen.workspace("agent3", "ws3") | 3 // Agent exact match.
45+
DataGen.workspace("gone", "ws4") | 4 // Agent gone, select workspace.
46+
DataGen.workspace("ws4", "ws4") | 4 // Workspace exact match.
47+
DataGen.workspace("agent2", "ws5") | 5 // Agent exact match.
48+
DataGen.workspace("gone", "ws5") | 5 // Agent gone, another agent comes first.
49+
DataGen.workspace("ws5", "ws5") | 6 // Workspace exact match.
50+
DataGen.workspace("ws6", "ws6") | 7 // Workspace exact match.
51+
DataGen.workspace("gone", "ws6") | 7 // Agent gone, workspace comes first.
52+
DataGen.workspace("agent3", "ws6") | 8 // Agent exact match.
53+
}
54+
}

0 commit comments

Comments
 (0)