Skip to content

Commit

Permalink
Merge pull request #645 from pascalbreuninger/main
Browse files Browse the repository at this point in the history
fix(ui): devpod pro login
  • Loading branch information
pascalbreuninger authored Aug 25, 2023
2 parents a563ff0 + 0d343aa commit 2d5c632
Show file tree
Hide file tree
Showing 10 changed files with 61 additions and 93 deletions.
4 changes: 2 additions & 2 deletions cmd/pro/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ func (cmd *DeleteCmd) Run(ctx context.Context, args []string) error {

err = os.RemoveAll(proInstanceDir)
if err != nil {
return errors.Wrap(err, "delete pro instace dir")
return errors.Wrap(err, "delete pro instance dir")
}

log.Default.Donef("Successfully deleted pro instace '%s'", proInstanceName)
log.Default.Donef("Successfully deleted pro instance '%s'", proInstanceName)
return nil
}
11 changes: 3 additions & 8 deletions desktop/src/client/pro/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Result, ResultError } from "../../lib"
import { TImportWorkspaceConfig, TProID, TProInstance } from "../../types"
import { TDebuggable, TStreamEventListenerFn } from "../types"
import { ProCommands } from "./proCommands"
import { ProviderCommands } from "@/client/providers/providerCommands"

export class ProClient implements TDebuggable {
constructor() {}
Expand All @@ -11,16 +10,12 @@ export class ProClient implements TDebuggable {
ProCommands.DEBUG = isEnabled
}

public async newID(url: string): Promise<Result<string>> {
return ProCommands.GetProInstanceID(url)
}

public async login(
url: string,
name?: string,
host: string,
providerName?: string,
listener?: TStreamEventListenerFn
): Promise<ResultError> {
return ProCommands.Login(url, name, listener)
return ProCommands.Login(host, providerName, listener)
}

public async listAll(): Promise<Result<readonly TProInstance[]>> {
Expand Down
44 changes: 13 additions & 31 deletions desktop/src/client/pro/proCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,14 @@ import { TImportWorkspaceConfig, TProID, TProInstance } from "@/types"
import { Command, isOk, serializeRawOptions, toFlagArg } from "../command"
import {
DEVPOD_COMMAND_DELETE,
DEVPOD_COMMAND_GET_PRO_NAME,
DEVPOD_COMMAND_HELPER,
DEVPOD_COMMAND_IMPORT_WORKSPACE,
DEVPOD_COMMAND_LIST,
DEVPOD_COMMAND_LOGIN,
DEVPOD_COMMAND_PRO,
DEVPOD_COMMAND_PROVIDER,
DEVPOD_FLAG_DEBUG,
DEVPOD_FLAG_JSON_LOG_OUTPUT,
DEVPOD_FLAG_JSON_OUTPUT,
DEVPOD_FLAG_NAME,
DEVPOD_FLAG_PROVIDER,
DEVPOD_FLAG_USE,
DEVPOD_FLAG_WORKSPACE_ID,
DEVPOD_FLAG_WORKSPACE_UID,
Expand All @@ -27,38 +24,23 @@ export class ProCommands {
return new Command([...args, ...(ProCommands.DEBUG ? [DEVPOD_FLAG_DEBUG] : [])])
}

static async GetProInstanceID(url: string) {
const result = await new Command([
DEVPOD_COMMAND_HELPER,
DEVPOD_COMMAND_GET_PRO_NAME,
url,
]).run()
if (result.err) {
return result
}

if (!isOk(result.val)) {
return getErrorFromChildProcess(result.val)
}

return Return.Value(result.val.stdout)
}

static async Login(
url: string,
name?: string,
host: string,
providerName?: string,
listener?: TStreamEventListenerFn
): Promise<ResultError> {
const maybeNameFlag = name ? [toFlagArg(DEVPOD_FLAG_NAME, name)] : []
const maybeProviderNameFlag = providerName
? [toFlagArg(DEVPOD_FLAG_PROVIDER, providerName)]
: []
const useFlag = toFlagArg(DEVPOD_FLAG_USE, "false")

const cmd = await ProCommands.newCommand([
const cmd = ProCommands.newCommand([
DEVPOD_COMMAND_PRO,
DEVPOD_COMMAND_LOGIN,
url,
DEVPOD_FLAG_JSON_LOG_OUTPUT,
host,
useFlag,
...maybeNameFlag,
DEVPOD_FLAG_JSON_LOG_OUTPUT,
...maybeProviderNameFlag,
])
if (listener) {
return cmd.stream(listener)
Expand Down Expand Up @@ -118,11 +100,11 @@ export class ProCommands {
const result = await new Command([
DEVPOD_COMMAND_PRO,
DEVPOD_COMMAND_IMPORT_WORKSPACE,
config.devpod_pro_host,
config.devPodProHost,
DEVPOD_FLAG_WORKSPACE_ID,
config.workspace_id,
config.workspaceID,
DEVPOD_FLAG_WORKSPACE_UID,
config.workspace_uid,
config.workspaceUID,
...optionsFlag,
DEVPOD_FLAG_JSON_LOG_OUTPUT,
]).run()
Expand Down
4 changes: 0 additions & 4 deletions desktop/src/client/providers/providerCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { exists, getErrorFromChildProcess, Result, ResultError, Return } from ".
import {
TAddProviderConfig,
TCheckProviderUpdateResult,
TImportWorkspaceConfig,
TProviderID,
TProviderOptions,
TProviders,
Expand All @@ -13,7 +12,6 @@ import {
DEVPOD_COMMAND_ADD,
DEVPOD_COMMAND_DELETE,
DEVPOD_COMMAND_GET_PROVIDER_NAME,
DEVPOD_COMMAND_IMPORT_WORKSPACE,
DEVPOD_COMMAND_LIST,
DEVPOD_COMMAND_OPTIONS,
DEVPOD_COMMAND_PROVIDER,
Expand All @@ -27,8 +25,6 @@ import {
DEVPOD_FLAG_NAME,
DEVPOD_FLAG_SINGLE_MACHINE,
DEVPOD_FLAG_USE,
DEVPOD_FLAG_WORKSPACE_ID,
DEVPOD_FLAG_WORKSPACE_UID,
} from "../constants"
import { DEVPOD_COMMAND_CHECK_PROVIDER_UPDATE, DEVPOD_COMMAND_HELPER } from "./../constants"

Expand Down
6 changes: 3 additions & 3 deletions desktop/src/components/Layout/Pro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,11 @@ export function Pro() {
) : (
proInstances.map(
(proInstance) =>
proInstance.id && (
proInstance.host && (
<ProInstaceRow
key={proInstance.id}
key={proInstance.host}
{...proInstance}
id={proInstance.id}
id={proInstance.host}
onIsDeletingChanged={setIsDeleting}
/>
)
Expand Down
21 changes: 8 additions & 13 deletions desktop/src/contexts/DevPodContext/useProInstanceManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,25 @@ import { TProInstanceLoginConfig, TProInstanceManager, TProvider, TWithProID } f
export function useProInstanceManager(): TProInstanceManager {
const queryClient = useQueryClient()
const loginMutation = useMutation<TProvider | undefined, Error, TProInstanceLoginConfig>({
mutationFn: async ({ url, name, streamListener }) => {
if (!name) {
name = (await client.pro.newID(url)).unwrap()
}
if (!name) {
throw new Error("No name provided")
}

;(await client.pro.login(url, name, streamListener)).unwrap()
mutationFn: async ({ host, providerName, streamListener }) => {
;(await client.pro.login(host, providerName, streamListener)).unwrap()

try {
const providers = (await client.providers.listAll()).unwrap()
if (providers === undefined || Object.keys(providers).length === 0) {
throw new Error("No providers found")
}

const maybeProvider = providers[name]
if (providerName === undefined || providerName === "") {
providerName = "devpod-pro"
}
const maybeProvider = providers[providerName]
if (!maybeProvider) {
throw new Error(`Provider ${name} not found`)
throw new Error(`Provider ${providerName} not found`)
}

return maybeProvider
} catch (e) {
;(await client.pro.remove(name)).unwrap()
;(await client.pro.remove(host)).unwrap()

throw e
}
Expand Down
16 changes: 8 additions & 8 deletions desktop/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export type TDeepNonNullable<T> = {
export type TLogOutput = Readonly<{ time: Date; message?: string; level: string }>
export type TQueryResult<TData extends Readonly<object>> = [
TData | undefined,
Pick<UseMutationResult, "status" | "error">,
Pick<UseMutationResult, "status" | "error">
]
export type TRunnable<TRunConfig> = Readonly<{ run(config: TRunConfig): void }>
//#endregion
Expand Down Expand Up @@ -120,9 +120,9 @@ export type TCheckProviderUpdateResult = Readonly<{
}>

export type TImportWorkspaceConfig = Readonly<{
workspace_id: string
workspace_uid: string
devpod_pro_host: string
workspaceID: string
workspaceUID: string
devPodProHost: string
options: { [key: string]: string } | null
}>

Expand Down Expand Up @@ -189,8 +189,8 @@ export type TContextOption = Readonly<{
export type TProID = string
export type TWithProID = Readonly<{ id: TProID }>
export type TProInstance = Readonly<{
id: TMaybe<string>
url: TMaybe<string>
host: TMaybe<string>
provider: TMaybe<string>
creationTimestamp: TMaybe<string>
}>
export type TProInstances = readonly TProInstance[]
Expand All @@ -203,8 +203,8 @@ export type TProInstanceManager = Readonly<{
Pick<UseMutationResult, "status" | "error"> & { target: TWithProID | undefined }
}>
export type TProInstanceLoginConfig = Readonly<{
url: string
name?: string
host: string
providerName?: string
streamListener?: TStreamEventListenerFn
}>
//#endregion
Expand Down
8 changes: 4 additions & 4 deletions desktop/src/useAppReady.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { useNavigate } from "react-router"
import { client } from "./client"
import { ErrorMessageBox } from "./components"
import { WORKSPACE_SOURCE_BRANCH_DELIMITER, WORKSPACE_SOURCE_COMMIT_DELIMITER } from "./constants"
import { startWorkspaceAction, useWorkspace } from "./contexts"
import { startWorkspaceAction } from "./contexts"
import { Release } from "./gen"
import { exists, useReleases, useVersion } from "./lib"
import { Routes } from "./routes"
Expand Down Expand Up @@ -168,9 +168,9 @@ export function useAppReady() {

if (event.type === "ImportWorkspace") {
const importResult = await client.pro.importWorkspace({
workspace_id: event.workspace_id,
workspace_uid: event.workspace_uid,
devpod_pro_host: event.devpod_pro_host,
workspaceID: event.workspace_id,
workspaceUID: event.workspace_uid,
devPodProHost: event.devpod_pro_host,
options: event.options,
})
if (importResult.err) {
Expand Down
38 changes: 19 additions & 19 deletions desktop/src/views/ProInstances/useLoginProModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BottomActionBar, BottomActionBarError, Form, useStreamingTerminal } from "@/components"
import { useProInstances } from "@/contexts"
import { useProInstances, useProviders } from "@/contexts"
import { exists, useFormErrors } from "@/lib"
import { Routes } from "@/routes"
import {
Expand Down Expand Up @@ -32,17 +32,18 @@ import { ConfigureProviderOptionsForm } from "../Providers/AddProvider"
import { useSetupProvider } from "../Providers/AddProvider/useSetupProvider"

type TFormValues = {
[FieldName.PRO_URL]: string
[FieldName.PRO_NAME]: string | undefined
[FieldName.PRO_HOST]: string
[FieldName.PROVIDER_NAME]: string | undefined
}
const FieldName = {
PRO_URL: "proURL",
PRO_NAME: "proName",
PRO_HOST: "proURL",
PROVIDER_NAME: "proName",
} as const

export function useLoginProModal() {
const { terminal, connectStream } = useStreamingTerminal({ fontSize: "sm" })
const [[proInstances], { login, disconnect }] = useProInstances()
const [[providers]] = useProviders()
const { isOpen, onClose, onOpen } = useDisclosure()
const { handleSubmit, formState, register, reset } = useForm<TFormValues>({
mode: "onBlur",
Expand All @@ -51,8 +52,8 @@ export function useLoginProModal() {
const onSubmit = useCallback<SubmitHandler<TFormValues>>(
(data) => {
login.run({
url: data[FieldName.PRO_URL],
name: data[FieldName.PRO_NAME],
host: data[FieldName.PRO_HOST],
providerName: data[FieldName.PROVIDER_NAME],
streamListener: connectStream,
})
},
Expand Down Expand Up @@ -154,7 +155,7 @@ export function useLoginProModal() {
<Input
type="text"
placeholder="my-pro.my-domain.com"
{...register(FieldName.PRO_URL, {
{...register(FieldName.PRO_HOST, {
required: true,
validate: {
url: (value) => {
Expand All @@ -167,12 +168,12 @@ export function useLoginProModal() {
}
},
unique: (value) => {
const isURLTaken = proInstances?.some(
(instance) => instance.url === `https://${value}`
const isHostTaken = proInstances?.some(
(instance) => instance.host === value
)

return isURLTaken
? `URL must be unique, an instance with the URL ${value} already exists`
return isHostTaken
? `URL must be unique, an instance with the URL https://${value} already exists`
: true
},
},
Expand All @@ -193,22 +194,20 @@ export function useLoginProModal() {
flexBasis="33%"
isInvalid={exists(proNameError)}
isDisabled={areInputsDisabled}>
<FormLabel>Instance Name</FormLabel>
<FormLabel>Provider Name</FormLabel>
<InputGroup>
<Input
type="text"
placeholder="Loft"
{...register(FieldName.PRO_NAME, {
{...register(FieldName.PROVIDER_NAME, {
required: false,
validate: {
unique: (value) => {
if (value === undefined) return true
const isNameTaken = proInstances?.some(
(instance) => instance.id === value
)
const isNameTaken = providers?.[value] !== undefined

return isNameTaken
? `Name must be unique, an instance named ${value} already exists`
? `Name must be unique, a provider named ${value} already exists`
: true
},
},
Expand All @@ -218,7 +217,7 @@ export function useLoginProModal() {
{proNameError && proNameError.message ? (
<FormErrorMessage>{proNameError.message}</FormErrorMessage>
) : (
<FormHelperText>Optionally give your instance a name</FormHelperText>
<FormHelperText>Optionally give the pro provider a name</FormHelperText>
)}
</FormControl>
</Container>
Expand Down Expand Up @@ -284,6 +283,7 @@ export function useLoginProModal() {
proInstances,
proNameError,
proURLError,
providers,
register,
state.currentStep,
state.providerID,
Expand Down
2 changes: 1 addition & 1 deletion pkg/provider/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ type ProInstance struct {
Provider string `json:"provider,omitempty"`

// Host is the Loft DevPod Pro host to use
Host string `json:"url,omitempty"`
Host string `json:"host,omitempty"`

// CreationTimestamp is the timestamp when this pro instance was created
CreationTimestamp types.Time `json:"creationTimestamp,omitempty"`
Expand Down

0 comments on commit 2d5c632

Please sign in to comment.