fix: Use command property when launching an application (#3998)

Fixes #3777.
This commit is contained in:
Kyle Carberry
2022-09-12 16:46:13 +00:00
committed by GitHub
parent 07e2565a4f
commit 2b8223bdd5
4 changed files with 20 additions and 9 deletions
+8 -1
View File
@@ -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}
+5 -5
View File
@@ -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)