Skip to content

Commit

Permalink
Merge pull request #247 from pascalbreuninger/main
Browse files Browse the repository at this point in the history
feat(ui): trigger `check status` action if workspace status is unknow…
  • Loading branch information
pascalbreuninger authored May 15, 2023
2 parents 14cd68f + 9574681 commit e2f99c7
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 56 deletions.
27 changes: 21 additions & 6 deletions desktop/src/client/workspaces/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ export class WorkspacesClient implements TDebuggable {
if (result.err) {
return result
}

return result
}

public setDebug(isEnabled: boolean): void {
Expand All @@ -93,7 +95,7 @@ export class WorkspacesClient implements TDebuggable {
}

public async getStatus(id: TWorkspaceID): Promise<Result<TWorkspace["status"]>> {
const result = await WorkspaceCommands.GetWorkspaceStatus(id)
const result = await WorkspaceCommands.FetchWorkspaceStatus(id)
if (result.err) {
return result
}
Expand All @@ -114,7 +116,7 @@ export class WorkspacesClient implements TDebuggable {
): Promise<Result<TWorkspace["status"]>> {
const cmd = WorkspaceCommands.StartWorkspace(ctx.id, config)
const result = await this.execActionCmd(cmd, { ...ctx, listener, actionName: "start" })
if (result?.err) {
if (result.err) {
return result
}

Expand All @@ -127,7 +129,7 @@ export class WorkspacesClient implements TDebuggable {
): Promise<Result<TWorkspace["status"]>> {
const cmd = WorkspaceCommands.StopWorkspace(ctx.id)
const result = await this.execActionCmd(cmd, { ...ctx, listener, actionName: "stop" })
if (result?.err) {
if (result.err) {
return result
}

Expand All @@ -140,7 +142,7 @@ export class WorkspacesClient implements TDebuggable {
): Promise<Result<TWorkspace["status"]>> {
const cmd = WorkspaceCommands.RebuildWorkspace(ctx.id)
const result = await this.execActionCmd(cmd, { ...ctx, listener, actionName: "rebuild" })
if (result?.err) {
if (result.err) {
return result
}

Expand All @@ -151,10 +153,23 @@ export class WorkspacesClient implements TDebuggable {
force: boolean,
listener: TStreamEventListenerFn | undefined,
ctx: TWorkspaceClientContext
): Promise<ResultError> {
): Promise<Result<TWorkspace["status"]>> {
const cmd = WorkspaceCommands.RemoveWorkspace(ctx.id, force)
const result = await this.execActionCmd(cmd, { ...ctx, listener, actionName: "remove" })
if (result?.err) {
if (result.err) {
return result
}

return result
}

public async checkStatus(
listener: TStreamEventListenerFn | undefined,
ctx: TWorkspaceClientContext
): Promise<ResultError> {
const cmd = WorkspaceCommands.GetStatusLogs(ctx.id)
const result = await this.execActionCmd(cmd, { ...ctx, listener, actionName: "checkStatus" })
if (result.err) {
return result
}

Expand Down
8 changes: 7 additions & 1 deletion desktop/src/client/workspaces/workspaceCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ export class WorkspaceCommands {
)
}

static async GetWorkspaceStatus(id: string): Promise<Result<Pick<TWorkspace, "id" | "status">>> {
static async FetchWorkspaceStatus(
id: string
): Promise<Result<Pick<TWorkspace, "id" | "status">>> {
const result = await new Command([DEVPOD_COMMAND_STATUS, id, DEVPOD_FLAG_JSON_OUTPUT]).run()
if (result.err) {
return result
Expand Down Expand Up @@ -83,6 +85,10 @@ export class WorkspaceCommands {
return Return.Value(result.val.stdout)
}

static GetStatusLogs(id: string) {
return new Command([DEVPOD_COMMAND_STATUS, id, DEVPOD_FLAG_JSON_LOG_OUTPUT])
}

static StartWorkspace(id: TWorkspaceID, config: TWorkspaceStartConfig) {
const maybeSource = config.sourceConfig?.source
const maybeIDFlag = exists(maybeSource) ? [toFlagArg(DEVPOD_FLAG_ID, id)] : []
Expand Down
2 changes: 1 addition & 1 deletion desktop/src/contexts/DevPodContext/action/action.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Result, SingleEventManager, EventManager } from "../../../lib"

export type TActionName = "start" | "stop" | "rebuild" | "remove"
export type TActionName = "start" | "stop" | "rebuild" | "remove" | "checkStatus"
export type TActionFn = (context: TActionContext) => Promise<Result<unknown>>
export type TActionStatus = "pending" | "success" | "error" | "cancelled"
export type TActionID = Action["id"]
Expand Down
31 changes: 30 additions & 1 deletion desktop/src/contexts/DevPodContext/workspaces/useWorkspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export type TWorkspaceResult = Readonly<{
stop: (onStream?: TStreamEventListenerFn) => TActionID | undefined
remove: (force: boolean, onStream?: TStreamEventListenerFn) => TActionID | undefined
rebuild: (onStream?: TStreamEventListenerFn) => TActionID | undefined
checkStatus: (onStream?: TStreamEventListenerFn) => TActionID | undefined
}>

export function useWorkspaceActions(
Expand Down Expand Up @@ -107,6 +108,33 @@ export function useWorkspace(workspaceID: TWorkspaceID | undefined): TWorkspaceR
[viewID, workspaceID]
)

const checkStatus = useCallback<TWorkspaceResult["stop"]>(
(onStream) => {
if (workspaceID === undefined) {
return
}

return devPodStore.startAction({
actionName: "checkStatus",
workspaceID,
actionFn: async (ctx) => {
const result = await client.workspaces.checkStatus(onStream, {
id: workspaceID,
actionID: ctx.id,
streamID: viewID,
})
if (result.err) {
return result
}
devPodStore.setStatus(workspaceID, result.val)

return result
},
})
},
[viewID, workspaceID]
)

const stop = useCallback<TWorkspaceResult["stop"]>(
(onStream) => {
if (workspaceID === undefined) {
Expand Down Expand Up @@ -222,8 +250,9 @@ export function useWorkspace(workspaceID: TWorkspaceID | undefined): TWorkspaceR
stop,
rebuild,
remove,
checkStatus,
}),
[data, isLoading, current, history, create, start, stop, rebuild, remove]
[data, isLoading, current, history, create, start, stop, rebuild, remove, checkStatus]
)
}

Expand Down
4 changes: 4 additions & 0 deletions desktop/src/lib/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ export function sleep(ms: number): Promise<void> {
}

export function getActionDisplayName(action: TActionObj): string {
if (action.name === "checkStatus") {
return `check status ${action.targetID}`
}

return `${action.name} ${action.targetID}`
}

Expand Down
29 changes: 16 additions & 13 deletions desktop/src/lib/useHover.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
import { MutableRefObject, useEffect, useRef, useState } from "react"
import { LegacyRef, useEffect, useRef, useState } from "react"

export function useHover<T extends HTMLElement>(): [boolean, MutableRefObject<T | null>] {
export function useHover<T extends HTMLButtonElement>(): [boolean, LegacyRef<T>] {
const [isHovering, setIsHovering] = useState<boolean>(false)

const ref = useRef<T | null>(null)
const ref = useRef<T>(null)

useEffect(
() => {
const node = ref.current
const handleMouseOver = (): void => setIsHovering(true)
const handleMouseOut = (): void => setIsHovering(false)
if (node) {
node.addEventListener("mouseover", handleMouseOver)
node.addEventListener("mouseout", handleMouseOut)
const handleMouseOver = () => setIsHovering(true)
const handleMouseOut = () => setIsHovering(false)

return () => {
node.removeEventListener("mouseover", handleMouseOver)
node.removeEventListener("mouseout", handleMouseOut)
setTimeout(() => {
const node = ref.current
if (node) {
node.addEventListener("mouseover", handleMouseOver)
node.addEventListener("mouseout", handleMouseOut)

return () => {
node.removeEventListener("mouseover", handleMouseOver)
node.removeEventListener("mouseout", handleMouseOut)
}
}
}
})
},
// rerun if ref changes!
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,18 +312,7 @@ export function ConfigureProviderOptionsForm({
)}
</HStack>

<HStack>
{addProvider && (
<Text
position="absolute"
left="50%"
fontWeight="medium"
fontFamily="monospace"
color="gray.700">
{provider?.config?.name}
</Text>
)}
</HStack>
<HStack />

<Popover placement="top" computePositionOnMount>
<PopoverTrigger>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,6 @@ export function SetupProviderSourceForm({
preferredProviderName = providerIDRes.val
}

console.log(maybeProviderName, providerSource, preferredProviderName)

removeDanglingProviders()
// custom name taken
if (maybeProviderName !== undefined && providers?.[maybeProviderName] !== undefined) {
Expand All @@ -178,7 +176,10 @@ export function SetupProviderSourceForm({
}
} else {
setValue(FieldName.PROVIDER_NAME, undefined, opts)
addProvider({ rawProviderSource: providerSource, config: { name: maybeProviderName } })
addProvider({
rawProviderSource: providerSource,
config: { name: maybeProviderName ?? preferredProviderName },
})
}
},
[addProvider, providers, removeDanglingProviders, setValue]
Expand Down Expand Up @@ -209,9 +210,8 @@ export function SetupProviderSourceForm({
shouldValidate: true,
}
setValue(FieldName.PROVIDER_SOURCE, sourceName, opts)
setValue(FieldName.PROVIDER_NAME, undefined, opts)
if (providerSource === sourceName) {
setValue(FieldName.PROVIDER_NAME, undefined, opts)

return
}

Expand Down Expand Up @@ -247,8 +247,9 @@ export function SetupProviderSourceForm({
}
setValue(FieldName.PROVIDER_SOURCE, "", opts)
setValue(FieldName.PROVIDER_NAME, undefined, opts)
removeDanglingProviders()
reset()
}, [reset, setValue])
}, [removeDanglingProviders, reset, setValue])

const isLoading = formState.isSubmitting || status === "loading"
const exampleCardSize = useBreakpointValue<"md" | "lg">({ base: "md", xl: "lg" })
Expand All @@ -259,7 +260,7 @@ export function SetupProviderSourceForm({
return (
<>
<Form onSubmit={handleSubmit(onSubmit)} spellCheck={false}>
<Stack spacing={6} width="full" alignItems="center" paddingBottom="8">
<Stack spacing={6} width="full" alignItems="center" paddingBottom={8}>
<FormControl
isRequired
isInvalid={exists(providerSourceError)}
Expand Down
19 changes: 17 additions & 2 deletions desktop/src/views/Providers/AddProvider/SetupProviderSteps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@ import { ConfigureProviderOptionsForm } from "./ConfigureProviderOptionsForm"
import { SetupProviderSourceForm } from "./SetupProviderSourceForm"
import { useSetupProvider } from "./useSetupProvider"

type TSetupProviderStepsProps = Readonly<{
onFinish?: () => void
suggestedProvider?: TProviderID
isModal?: boolean
onProviderIDChanged?: (id: string | null) => void
}>
export function SetupProviderSteps({
onFinish,
suggestedProvider,
onProviderIDChanged,
isModal = false,
}: Readonly<{ onFinish?: () => void; suggestedProvider?: TProviderID; isModal?: boolean }>) {
}: TSetupProviderStepsProps) {
const openLockRef = useRef(false)
const configureProviderRef = useRef<HTMLDivElement>(null)
const {
Expand All @@ -26,6 +33,14 @@ export function SetupProviderSteps({
}
}, [onFinish, state.currentStep])

useEffect(() => {
if (state.providerID) {
onProviderIDChanged?.(state.providerID)

return () => onProviderIDChanged?.(null)
}
}, [onProviderIDChanged, state.providerID])

const scrollToElement = useCallback((el: HTMLElement | null) => {
if (!openLockRef.current) {
openLockRef.current = true
Expand Down Expand Up @@ -53,7 +68,7 @@ export function SetupProviderSteps({
/>
</VStack>

<VStack align="start" spacing={8} marginTop={6} width="full">
<VStack align="start" spacing={8} marginTop={4} width="full">
<Box width="full" ref={configureProviderRef}>
{state.currentStep === "configure-provider" && (
<VStack align="start" width="full">
Expand Down
5 changes: 4 additions & 1 deletion desktop/src/views/Providers/AddProvider/useSetupProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,14 @@ export function useSetupProvider() {

const removeDanglingProviders = useCallback(() => {
const danglingProviderIDs = client.providers.popAllDangling()
console.log(danglingProviderIDs)
for (const danglingProviderID of danglingProviderIDs) {
remove.run({ providerID: danglingProviderID })
}
}, [remove])

useEffect(() => {
console.log(state)
if (state.currentStep === "done") {
client.providers.popDangling()

Expand All @@ -94,10 +96,11 @@ export function useSetupProvider() {
}

client.providers.setDangling(state.providerID)
}, [remove, removeDanglingProviders, state])
}, [state])

useEffect(() => {
return () => {
console.log("unmounting")
removeDanglingProviders()
}
// We need to ensure this effect only runs when the hook unmounts at the cost of potentially stale dependencies
Expand Down
Loading

0 comments on commit e2f99c7

Please sign in to comment.