Skip to content

Commit 11a102c

Browse files
committed
feat(web): show container for active SSH terminal sessions
1 parent 5741fd1 commit 11a102c

4 files changed

Lines changed: 57 additions & 39 deletions

File tree

packages/web/src/app/page.tsx

Lines changed: 45 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -533,9 +533,13 @@ export default function Home() {
533533

534534
useEffect(() => () => disposeTerminal(), [disposeTerminal])
535535

536-
const connectedLabel = activeProject?.displayName ?? "none"
536+
const activeTerminalSession = terminalSessions.find((session) => session.id === activeSessionId)
537+
const connectedContainerLabel = terminalStatus === "detached"
538+
? "none"
539+
: activeTerminalSession?.containerName ?? activeProject?.containerName ?? "unknown"
537540
const statusLabel = activeProject?.statusLabel ?? "unknown"
538541
const sshLabel = activeProject?.ssh ?? "-"
542+
const containerLabel = activeProject?.containerName ?? "-"
539543
const repoLabel = activeProject?.displayName ?? "-"
540544
const refLabel = activeProject?.repoRef ?? "-"
541545
const recreateStatus = activeProject?.recreateStatus
@@ -558,7 +562,7 @@ export default function Home() {
558562
<div className="brand">docker-git</div>
559563
<div className="status-chip">
560564
<span className="status-dot" />
561-
Connected · {connectedLabel}
565+
Connected SSH · {connectedContainerLabel}
562566
</div>
563567
</header>
564568

@@ -603,6 +607,7 @@ export default function Home() {
603607
<div className="topbar">
604608
<div className="topbar-meta">
605609
<span className="pill">SSH: {sshLabel}</span>
610+
<span className="pill">Container: {containerLabel}</span>
606611
<span className="pill">Repo: {repoLabel}</span>
607612
<span className="pill">Ref: {refLabel}</span>
608613
<span className="pill">Status: {statusLabel}</span>
@@ -685,43 +690,46 @@ export default function Home() {
685690
{showDetails ? "No active terminals" : "None"}
686691
</div>
687692
) : (
688-
terminalSessions.map((session) => (
689-
<div
690-
key={session.id}
691-
className={`list-item ${session.id === activeSessionId ? "active" : ""}`}
692-
role="button"
693-
tabIndex={0}
694-
onClick={() => handleSessionSelect(session)}
695-
onKeyDown={(event) => {
696-
if (event.key === "Enter" || event.key === " ") {
697-
event.preventDefault()
698-
handleSessionSelect(session)
699-
}
700-
}}
701-
>
702-
<div className="list-item-row">
703-
<strong>{session.displayName}</strong>
704-
<div className="list-item-actions">
705-
<span className={session.status === "connected" ? "badge" : "badge warn"}>
706-
{session.status}
707-
</span>
708-
<button
709-
className="icon-button"
710-
type="button"
711-
onClick={(event) => {
712-
event.stopPropagation()
713-
handleSessionClose(session)
714-
}}
715-
>
716-
delete
717-
</button>
693+
terminalSessions.map((session) => {
694+
const sessionContainer = session.containerName ?? session.projectId
695+
return (
696+
<div
697+
key={session.id}
698+
className={`list-item ${session.id === activeSessionId ? "active" : ""}`}
699+
role="button"
700+
tabIndex={0}
701+
onClick={() => handleSessionSelect(session)}
702+
onKeyDown={(event) => {
703+
if (event.key === "Enter" || event.key === " ") {
704+
event.preventDefault()
705+
handleSessionSelect(session)
706+
}
707+
}}
708+
>
709+
<div className="list-item-row">
710+
<strong>{session.displayName}</strong>
711+
<div className="list-item-actions">
712+
<span className={session.status === "connected" ? "badge" : "badge warn"}>
713+
{session.status}
714+
</span>
715+
<button
716+
className="icon-button"
717+
type="button"
718+
onClick={(event) => {
719+
event.stopPropagation()
720+
handleSessionClose(session)
721+
}}
722+
>
723+
delete
724+
</button>
725+
</div>
718726
</div>
727+
<small>
728+
{session.source} · {session.mode} · {sessionContainer}
729+
</small>
719730
</div>
720-
<small>
721-
{session.source} · {session.mode} · {session.projectId}
722-
</small>
723-
</div>
724-
))
731+
)
732+
})
725733
)}
726734
</div>
727735
</div>

packages/web/src/lib/api-schema.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ const TerminalSessionSchema = Schema.Struct({
108108
id: Schema.String,
109109
projectId: Schema.String,
110110
displayName: Schema.String,
111+
containerName: Schema.optional(Schema.String),
111112
mode: TerminalSessionModeSchema,
112113
source: Schema.String,
113114
status: TerminalSessionStatusSchema,

packages/web/src/lib/api-types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export type TerminalSession = {
6565
readonly id: string
6666
readonly projectId: string
6767
readonly displayName: string
68+
readonly containerName?: string
6869
readonly mode: TerminalSessionMode
6970
readonly source: string
7071
readonly status: TerminalSessionStatus

packages/web/src/server/terminal-ws.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type TerminalSessionRegistry = {
2323
readonly id: string
2424
readonly projectId: string
2525
readonly displayName: string
26+
readonly containerName?: string
2627
readonly mode: TerminalSessionMode
2728
readonly source: string
2829
readonly status: TerminalSessionStatus
@@ -181,8 +182,15 @@ export const attachTerminalWs = (wss: WebSocketServer) => {
181182
const privateKey = fs.readFileSync(target.identityPath)
182183

183184
client.on("ready", () => {
184-
updateSession(sessionId, { status: "connected", displayName: details.displayName })
185-
sendMessage(socket, { type: "info", data: `[docker-git] attached to ${details.displayName}` })
185+
updateSession(sessionId, {
186+
status: "connected",
187+
displayName: details.displayName,
188+
containerName: details.containerName
189+
})
190+
sendMessage(socket, {
191+
type: "info",
192+
data: `[docker-git] attached to ${details.displayName} (${details.containerName})`
193+
})
186194

187195
client.shell(
188196
{

0 commit comments

Comments
 (0)