Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd2f50f1

Browse files
authored
revise recent projects flow to be less confusing (#464)
1 parentcae0cb4 commitd2f50f1

File tree

2 files changed

+48
-89
lines changed

2 files changed

+48
-89
lines changed

‎CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@
44

55
##Unreleased
66

7+
- The "Recents" view has been updated to have a new flow.
8+
Before, there were separate controls for managing the workspace and then you
9+
could click a link to launch a project (clicking a link would also start a stopped workspace automatically).
10+
Now, there are no workspace controls, just links which start the workspace automatically when needed.
11+
The links are enabled when the workspace is STOPPED, CANCELED, FAILED, STARTING, RUNNING. These states represent
12+
valid times to start a workspace and connect, or to simply connect to a running one or one that's already starting.
13+
We also use a spinner icon when workspaces are in a transition state (STARTING, CANCELING, DELETING, STOPPING)
14+
to give context for why a link might be disabled or a connection might take longer than usual to establish.
15+
716
##2.13.1 - 2024-07-19
817

918
###Changed

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

Lines changed: 39 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,8 @@ import com.coder.gateway.services.CoderRestClientService
1717
importcom.coder.gateway.services.CoderSettingsService
1818
importcom.coder.gateway.util.humanizeConnectionError
1919
importcom.coder.gateway.util.toURL
20-
importcom.coder.gateway.util.withPath
2120
importcom.coder.gateway.util.withoutNull
2221
importcom.intellij.icons.AllIcons
23-
importcom.intellij.ide.BrowserUtil
2422
importcom.intellij.openapi.Disposable
2523
importcom.intellij.openapi.actionSystem.AnActionEvent
2624
importcom.intellij.openapi.application.ModalityState
@@ -56,6 +54,7 @@ import kotlinx.coroutines.delay
5654
importkotlinx.coroutines.isActive
5755
importkotlinx.coroutines.launch
5856
importkotlinx.coroutines.withContext
57+
importjava.awt.Color
5958
importjava.awt.Component
6059
importjava.awt.Dimension
6160
importjava.util.Locale
@@ -175,15 +174,21 @@ class CoderGatewayRecentWorkspaceConnectionsView(private val setContentCallback:
175174
val workspaceWithAgent= deployment?.items?.firstOrNull { it.workspace.name== workspaceName }
176175
val status=
177176
if (deploymentError!=null) {
178-
Triple(UIUtil.getBalloonErrorIcon(),UIUtil.getErrorForeground(), deploymentError)
177+
Triple(UIUtil.getErrorForeground(),deploymentError,UIUtil.getBalloonErrorIcon())
179178
}elseif (workspaceWithAgent!=null) {
179+
val inLoadingState=listOf(WorkspaceStatus.STARTING,WorkspaceStatus.CANCELING,WorkspaceStatus.DELETING,WorkspaceStatus.STOPPING).contains(workspaceWithAgent?.workspace?.latestBuild?.status)
180+
180181
Triple(
181-
workspaceWithAgent.status.icon,
182182
workspaceWithAgent.status.statusColor(),
183183
workspaceWithAgent.status.description,
184+
if (inLoadingState) {
185+
AnimatedIcon.Default()
186+
}else {
187+
null
188+
},
184189
)
185190
}else {
186-
Triple(AnimatedIcon.Default.INSTANCE,UIUtil.getContextHelpForeground(),"Querying workspace status...")
191+
Triple(UIUtil.getContextHelpForeground(),"Querying workspace status...",AnimatedIcon.Default())
187192
}
188193
val gap=
189194
if (top) {
@@ -193,11 +198,6 @@ class CoderGatewayRecentWorkspaceConnectionsView(private val setContentCallback:
193198
TopGap.MEDIUM
194199
}
195200
row {
196-
icon(status.first).applyToComponent {
197-
foreground= status.second
198-
}.align(AlignX.LEFT).gap(RightGap.SMALL).applyToComponent {
199-
size=Dimension(JBUI.scale(16),JBUI.scale(16))
200-
}
201201
label(workspaceName).applyToComponent {
202202
font=JBFont.h3().asBold()
203203
}.align(AlignX.LEFT).gap(RightGap.SMALL)
@@ -206,94 +206,44 @@ class CoderGatewayRecentWorkspaceConnectionsView(private val setContentCallback:
206206
font=ComponentPanelBuilder.getCommentFont(font)
207207
}
208208
label("").resizableColumn().align(AlignX.FILL)
209-
actionButton(
210-
object:DumbAwareAction(
211-
CoderGatewayBundle.message("gateway.connector.recent-connections.start.button.tooltip"),
212-
"",
213-
CoderIcons.RUN,
214-
) {
215-
overridefunactionPerformed(e:AnActionEvent) {
216-
withoutNull(workspaceWithAgent?.workspace, deployment?.client) { workspace, client->
217-
jobs[workspace.id]?.cancel()
218-
jobs[workspace.id]=
219-
cs.launch(ModalityState.current().asContextElement()) {
220-
withContext(Dispatchers.IO) {
221-
try {
222-
client.startWorkspace(workspace)
223-
fetchWorkspaces()
224-
}catch (e:Exception) {
225-
logger.error("Could not start workspace${workspace.name}", e)
226-
}
227-
}
228-
}
229-
}
230-
}
231-
},
232-
).applyToComponent {
233-
isEnabled=
234-
listOf(
235-
WorkspaceStatus.STOPPED,
236-
WorkspaceStatus.FAILED,
237-
).contains(workspaceWithAgent?.workspace?.latestBuild?.status)
238-
}
239-
.gap(RightGap.SMALL)
240-
actionButton(
241-
object:DumbAwareAction(
242-
CoderGatewayBundle.message("gateway.connector.recent-connections.stop.button.tooltip"),
243-
"",
244-
CoderIcons.STOP,
245-
) {
246-
overridefunactionPerformed(e:AnActionEvent) {
247-
withoutNull(workspaceWithAgent?.workspace, deployment?.client) { workspace, client->
248-
jobs[workspace.id]?.cancel()
249-
jobs[workspace.id]=
250-
cs.launch(ModalityState.current().asContextElement()) {
251-
withContext(Dispatchers.IO) {
252-
try {
253-
client.stopWorkspace(workspace)
254-
fetchWorkspaces()
255-
}catch (e:Exception) {
256-
logger.error("Could not stop workspace${workspace.name}", e)
257-
}
258-
}
259-
}
260-
}
261-
}
262-
},
263-
).applyToComponent { isEnabled= workspaceWithAgent?.workspace?.latestBuild?.status==WorkspaceStatus.RUNNING }
264-
.gap(RightGap.SMALL)
265-
actionButton(
266-
object:DumbAwareAction(
267-
CoderGatewayBundle.message("gateway.connector.recent-connections.terminal.button.tooltip"),
268-
"",
269-
CoderIcons.OPEN_TERMINAL,
270-
) {
271-
overridefunactionPerformed(e:AnActionEvent) {
272-
withoutNull(workspaceWithAgent, deployment?.client) { ws, client->
273-
val link= client.url.withPath("/me/${ws.name}/terminal")
274-
BrowserUtil.browse(link.toString())
275-
}
276-
}
277-
},
278-
)
279209
}.topGap(gap)
210+
211+
val enableLinks=listOf(WorkspaceStatus.STOPPED,WorkspaceStatus.CANCELED,WorkspaceStatus.FAILED,WorkspaceStatus.STARTING,WorkspaceStatus.RUNNING).contains(workspaceWithAgent?.workspace?.latestBuild?.status)
212+
213+
// We only display an API error on the first workspace rather than duplicating it on each workspace.
280214
if (deploymentError==null|| showError) {
281215
row {
282-
// There must be a way to make this properly wrap?
283-
label("<html><body style='width:350px;'>"+ status.third+"</html>").applyToComponent {
284-
foreground= status.second
216+
status.third?.let {
217+
icon(it)
218+
}
219+
label("<html><body style='width:350px;'>"+ status.second+"</html>").applyToComponent {
220+
foreground= status.first
285221
}
286222
}
287223
}
224+
288225
connections.forEach { workspaceProjectIDE->
289226
row {
290227
icon(workspaceProjectIDE.ideProduct.icon)
291-
cell(
292-
ActionLink(workspaceProjectIDE.projectPathDisplay) {
293-
CoderRemoteConnectionHandle().connect { workspaceProjectIDE }
294-
GatewayUI.getInstance().reset()
295-
},
296-
)
228+
if (enableLinks) {
229+
cell(
230+
ActionLink(workspaceProjectIDE.projectPathDisplay) {
231+
withoutNull(deployment?.client, workspaceWithAgent?.workspace) { client, workspace->
232+
CoderRemoteConnectionHandle().connect {
233+
if (listOf(WorkspaceStatus.STOPPED,WorkspaceStatus.CANCELED,WorkspaceStatus.FAILED).contains(workspace.latestBuild.status)) {
234+
client.startWorkspace(workspace)
235+
}
236+
workspaceProjectIDE
237+
}
238+
GatewayUI.getInstance().reset()
239+
}
240+
},
241+
)
242+
}else {
243+
label(workspaceProjectIDE.projectPathDisplay).applyToComponent {
244+
foreground=Color.GRAY
245+
}
246+
}
297247
label("").resizableColumn().align(AlignX.FILL)
298248
label(workspaceProjectIDE.ideName).applyToComponent {
299249
foreground=JBUI.CurrentTheme.ContextHelp.FOREGROUND

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp