Skip to content

Commit c81f36c

Browse files
committed
impl: ability to customize the link to workspace details in Dashboard
For `Open in dashboard` we now have a config that can be replaced with a complete new URL to another custom hostname and path. This new setting supports `$workspaceOwner` and `$workspaceName` as placeholders.
1 parent c312ea0 commit c81f36c

File tree

6 files changed

+101
-1
lines changed

6 files changed

+101
-1
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,10 @@ storage paths. The options can be configured from the plugin's main Workspaces p
362362

363363
- `lastDeploymentURL` the last Coder deployment URL that Coder Toolbox successfully authenticated to.
364364

365+
- `workspaceViewUrl` specifies the dashboard page full URL where users can view details about a workspace.
366+
Helpful for customers that have their own in-house dashboards. Defaults to the Coder deployment workspace page.
367+
This setting supports `$workspaceOwner` and `$workspaceName` as placeholders.
368+
365369
- `workspaceCreateUrl` specifies the dashboard page full URL where users can create new workspaces.
366370
Helpful for customers that have their own in-house dashboards. Defaults to the Coder deployment templates page.
367371

playground.ipynb

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
{
2+
"cells": [
3+
{
4+
"metadata": {
5+
"ExecuteTime": {
6+
"end_time": "2025-10-13T19:21:18.748657Z",
7+
"start_time": "2025-10-13T19:21:18.421817Z"
8+
}
9+
},
10+
"cell_type": "code",
11+
"source": [
12+
"import java.net.URLEncoder\n",
13+
"import java.nio.charset.StandardCharsets\n",
14+
"\n",
15+
"data class Inner(var txt: String?)\n",
16+
"data class Outer(val inner: Inner)\n",
17+
"\n",
18+
"fun firstApproach() {\n",
19+
" val o = Outer(Inner(null))\n",
20+
" val res = listOf<String?>(\n",
21+
" \"--begin\",\n",
22+
" \"--acs\",\n",
23+
" if (!o.inner.txt.isNullOrBlank()) \"--header-command\" else null,\n",
24+
" \"--end\"\n",
25+
" )\n",
26+
"\n",
27+
" println(res)\n",
28+
"}\n",
29+
"\n",
30+
"fun secondApproach() {\n",
31+
" val o = Outer(Inner(null))\n",
32+
" val res = listOf<String?>(\n",
33+
" \"--begin\",\n",
34+
" \"--acs\",\n",
35+
" o.inner.txt?.takeIf { it.isNotBlank() }?.let { \"--header-command\" },\n",
36+
" \"--end\"\n",
37+
" )\n",
38+
"\n",
39+
" println(res)\n",
40+
"}\n",
41+
"\n",
42+
"firstApproach()\n",
43+
"secondApproach()\n",
44+
"\n",
45+
"// https://dev.coder.com/oauth2/authorize?client_id=f8088cf1-6c3f-454a-8d48-9f86d161e845&response_type=code&code_challenge=kKhqZ3rTJwm5J1K5TSjWJ1meJXSr5Bd-fPzVBsqXdHY&redirect_uri=jetbrains://gateway/com.coder.toolbox/auth&state=d29de88b-c54d-4e2a-9de0-685b554895ed&code_challenge_method=S256\n",
46+
"\n",
47+
"\"jetbrains://gateway/com.coder.toolbox/oauth\"\n",
48+
"println(URLEncoder.encode(\"jetbrains://gateway/com.coder.toolbox/oauth\", StandardCharsets.UTF_8.toString()))"
49+
],
50+
"outputs": [
51+
{
52+
"name": "stdout",
53+
"output_type": "stream",
54+
"text": [
55+
"[--begin, --acs, null, --end]\n",
56+
"[--begin, --acs, null, --end]\n",
57+
"jetbrains%3A%2F%2Fgateway%2Fcom.coder.toolbox%2Foauth\n"
58+
]
59+
}
60+
],
61+
"execution_count": 1
62+
}
63+
],
64+
"metadata": {
65+
"kernelspec": {
66+
"display_name": "Kotlin",
67+
"language": "kotlin",
68+
"name": "kotlin"
69+
},
70+
"language_info": {
71+
"name": "kotlin",
72+
"version": "1.9.23",
73+
"mimetype": "text/x-kotlin",
74+
"file_extension": ".kt",
75+
"pygments_lexer": "kotlin",
76+
"codemirror_mode": "text/x-kotlin",
77+
"nbconvert_exporter": ""
78+
}
79+
},
80+
"nbformat": 4,
81+
"nbformat_minor": 0
82+
}

src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,13 @@ class CoderRemoteEnvironment(
9191
}
9292
actions.add(
9393
Action(context, "Open in dashboard") {
94+
val urlTemplate = context.settingsStore.workspaceViewUrl
95+
?: client.url.withPath("/@${workspace.ownerName}/${workspace.name}").toString()
96+
val url = urlTemplate
97+
.replace("\$workspaceOwner", "@${workspace.ownerName}")
98+
.replace("\$workspaceName", workspace.name)
9499
context.desktop.browse(
95-
client.url.withPath("/@${workspace.ownerName}/${workspace.name}").toString()
100+
url
96101
) {
97102
context.ui.showErrorInfoPopup(it)
98103
}

src/main/kotlin/com/coder/toolbox/settings/ReadOnlyCoderSettings.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,12 @@ interface ReadOnlyCoderSettings {
137137
*/
138138
val sshConfigOptions: String?
139139

140+
/**
141+
* A custom full URL to the dashboard page used for viewing details about a workspace.
142+
* Supports `$workspaceOwner` and `$workspaceName` as placeholders.
143+
*/
144+
val workspaceViewUrl: String?
145+
140146
/**
141147
* A custom full URL to the dashboard page used for creating workspaces.
142148
*/

src/main/kotlin/com/coder/toolbox/store/CoderSettingsStore.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ class CoderSettingsStore(
8080
.normalize()
8181
.toString()
8282

83+
override val workspaceViewUrl: String?
84+
get() = store[WORKSPACE_VIEW_URL]
8385
override val workspaceCreateUrl: String?
8486
get() = store[WORKSPACE_CREATE_URL]
8587

src/main/kotlin/com/coder/toolbox/store/StoreKeys.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ internal const val SSH_CONFIG_OPTIONS = "sshConfigOptions"
4646

4747
internal const val NETWORK_INFO_DIR = "networkInfoDir"
4848

49+
internal const val WORKSPACE_VIEW_URL = "workspaceViewUrl"
4950
internal const val WORKSPACE_CREATE_URL = "workspaceCreateUrl"
5051

5152
internal const val SSH_AUTO_CONNECT_PREFIX = "ssh_auto_connect_"

0 commit comments

Comments
 (0)