mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix: Use command property when launching an application (#3998)
Fixes #3777.
This commit is contained in:
@@ -16,6 +16,7 @@ export interface AppLinkProps {
|
||||
agentName: TypesGen.WorkspaceAgent["name"]
|
||||
appName: TypesGen.WorkspaceApp["name"]
|
||||
appIcon?: TypesGen.WorkspaceApp["icon"]
|
||||
appCommand?: TypesGen.WorkspaceApp["command"]
|
||||
}
|
||||
|
||||
export const AppLink: FC<PropsWithChildren<AppLinkProps>> = ({
|
||||
@@ -24,9 +25,15 @@ export const AppLink: FC<PropsWithChildren<AppLinkProps>> = ({
|
||||
agentName,
|
||||
appName,
|
||||
appIcon,
|
||||
appCommand,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
const href = `/@${userName}/${workspaceName}.${agentName}/apps/${encodeURIComponent(appName)}`
|
||||
let href = `/@${userName}/${workspaceName}.${agentName}/apps/${encodeURIComponent(appName)}`
|
||||
if (appCommand) {
|
||||
href = `/@${userName}/${workspaceName}.${agentName}/terminal?command=${encodeURIComponent(
|
||||
appCommand,
|
||||
)}`
|
||||
}
|
||||
|
||||
return (
|
||||
<Link
|
||||
|
||||
@@ -160,6 +160,7 @@ export const Resources: FC<React.PropsWithChildren<ResourcesProps>> = ({
|
||||
key={app.name}
|
||||
appIcon={app.icon}
|
||||
appName={app.name}
|
||||
appCommand={app.command}
|
||||
userName={workspace.owner_name}
|
||||
workspaceName={workspace.name}
|
||||
agentName={agent.name}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { makeStyles } from "@material-ui/core/styles"
|
||||
import { useMachine } from "@xstate/react"
|
||||
import { FC, useEffect, useRef, useState } from "react"
|
||||
import { Helmet } from "react-helmet-async"
|
||||
import { useLocation, useNavigate, useParams } from "react-router-dom"
|
||||
import { useLocation, useNavigate, useParams, useSearchParams } from "react-router-dom"
|
||||
import { colors } from "theme/colors"
|
||||
import { v4 as uuidv4 } from "uuid"
|
||||
import * as XTerm from "xterm"
|
||||
@@ -31,13 +31,12 @@ const TerminalPage: FC<
|
||||
const xtermRef = useRef<HTMLDivElement>(null)
|
||||
const [terminal, setTerminal] = useState<XTerm.Terminal | null>(null)
|
||||
const [fitAddon, setFitAddon] = useState<FitAddon | null>(null)
|
||||
const [searchParams] = useSearchParams()
|
||||
// The reconnection token is a unique token that identifies
|
||||
// a terminal session. It's generated by the client to reduce
|
||||
// a round-trip, and must be a UUIDv4.
|
||||
const [reconnectionToken] = useState<string>(() => {
|
||||
const search = new URLSearchParams(location.search)
|
||||
return search.get("reconnect") ?? uuidv4()
|
||||
})
|
||||
const reconnectionToken = searchParams.get("reconnect") ?? uuidv4()
|
||||
const command = searchParams.get("command") || undefined
|
||||
// The workspace name is in the format:
|
||||
// <workspace name>[.<agent name>]
|
||||
const workspaceNameParts = workspace?.split(".")
|
||||
@@ -47,6 +46,7 @@ const TerminalPage: FC<
|
||||
reconnection: reconnectionToken,
|
||||
workspaceName: workspaceNameParts?.[0],
|
||||
username: username,
|
||||
command: command,
|
||||
},
|
||||
actions: {
|
||||
readMessage: (_, event) => {
|
||||
|
||||
@@ -18,6 +18,7 @@ export interface TerminalContext {
|
||||
username?: string
|
||||
workspaceName?: string
|
||||
reconnection?: string
|
||||
command?: string
|
||||
}
|
||||
|
||||
export type TerminalEvent =
|
||||
@@ -170,9 +171,11 @@ export const terminalMachine =
|
||||
return reject("workspace agent is not set")
|
||||
}
|
||||
const proto = location.protocol === "https:" ? "wss:" : "ws:"
|
||||
const socket = new WebSocket(
|
||||
`${proto}//${location.host}/api/v2/workspaceagents/${context.workspaceAgent.id}/pty?reconnect=${context.reconnection}`,
|
||||
)
|
||||
const commandQuery = context.command
|
||||
? `&command=${encodeURIComponent(context.command)}`
|
||||
: ""
|
||||
const url = `${proto}//${location.host}/api/v2/workspaceagents/${context.workspaceAgent.id}/pty?reconnect=${context.reconnection}${commandQuery}`
|
||||
const socket = new WebSocket(url)
|
||||
socket.binaryType = "arraybuffer"
|
||||
socket.addEventListener("open", () => {
|
||||
resolve(socket)
|
||||
|
||||
Reference in New Issue
Block a user