From 950ec26b11c4fab5135c01610d6329239a1c2be6 Mon Sep 17 00:00:00 2001 From: Pascal Breuninger Date: Wed, 8 May 2024 13:04:56 +0200 Subject: [PATCH] fix(desktop): resolve options for pro provider properly --- desktop/src/contexts/SettingsContext.tsx | 6 +- .../views/ProInstances/useLoginProModal.tsx | 24 +++++--- .../ConfigureProviderOptionsForm.tsx | 58 ++++++++++++------- .../Providers/AddProvider/OptionFormField.tsx | 8 +-- desktop/src/views/Settings/Settings.tsx | 2 +- 5 files changed, 59 insertions(+), 39 deletions(-) diff --git a/desktop/src/contexts/SettingsContext.tsx b/desktop/src/contexts/SettingsContext.tsx index 7658ace03..7cefd996d 100644 --- a/desktop/src/contexts/SettingsContext.tsx +++ b/desktop/src/contexts/SettingsContext.tsx @@ -8,11 +8,9 @@ import { useState, } from "react" import { client } from "../client" -import { getKeys } from "../lib" -import { LocalStorageToFileMigrationBackend, Store } from "../lib" -import { TUnsubscribeFn } from "../types" import { Settings } from "../gen" -import { Command } from "@/client/command" +import { getKeys, LocalStorageToFileMigrationBackend, Store } from "../lib" +import { TUnsubscribeFn } from "../types" export type TSettings = Settings type TSetting = keyof TSettings diff --git a/desktop/src/views/ProInstances/useLoginProModal.tsx b/desktop/src/views/ProInstances/useLoginProModal.tsx index 53469ad29..198c6d571 100644 --- a/desktop/src/views/ProInstances/useLoginProModal.tsx +++ b/desktop/src/views/ProInstances/useLoginProModal.tsx @@ -113,14 +113,20 @@ export function useLoginProModal() { } }, [completeSetupProvider, login.provider, login.status, suggestedOptions]) - const resetModal = useCallback(() => { - reset() - login.reset() - if (state.currentStep !== "done" && state.providerID) { - disconnect.run({ id: state.providerID }) - } - onClose() - }, [disconnect, login, onClose, reset, state.currentStep, state.providerID]) + const resetModal = useCallback( + (checkDanglingProInstance: boolean = false) => { + reset() + login.reset() + if (checkDanglingProInstance) { + const proInstanceID = proInstances?.find((pro) => pro.provider === state.providerID)?.host + if (proInstanceID) { + disconnect.run({ id: proInstanceID }) + } + } + onClose() + }, + [disconnect, login, onClose, proInstances, reset, state.providerID] + ) useEffect(() => { if (state.currentStep === "done") { @@ -144,7 +150,7 @@ export function useLoginProModal() { const modal = useMemo(() => { return ( resetModal(true)} isOpen={isOpen} closeOnEsc={login.status !== "loading"} closeOnOverlayClick={login.status !== "loading"} diff --git a/desktop/src/views/Providers/AddProvider/ConfigureProviderOptionsForm.tsx b/desktop/src/views/Providers/AddProvider/ConfigureProviderOptionsForm.tsx index 3dbc34528..e2ba1dbb5 100644 --- a/desktop/src/views/Providers/AddProvider/ConfigureProviderOptionsForm.tsx +++ b/desktop/src/views/Providers/AddProvider/ConfigureProviderOptionsForm.tsx @@ -22,7 +22,12 @@ import { client } from "../../../client" import { useProvider } from "../../../contexts" import { exists, useFormErrors } from "../../../lib" import { QueryKeys } from "../../../queryKeys" -import { TConfigureProviderConfig, TProviderID, TProviderOptions } from "../../../types" +import { + TConfigureProviderConfig, + TProviderID, + TProviderOption, + TProviderOptions, +} from "../../../types" import { canCreateMachine } from "../helpers" import { OptionFormField } from "./OptionFormField" import { useProviderOptions } from "./useProviderOptions" @@ -63,7 +68,7 @@ export function ConfigureProviderOptionsForm({ addProvider = false, isModal = false, showBottomActionBar = true, - suggestedOptions = {}, + suggestedOptions, }: TConfigureProviderOptionsFormProps) { const queryClient = useQueryClient() const [provider] = useProvider(providerID) @@ -116,10 +121,17 @@ export function ConfigureProviderOptionsForm({ } = useMutation< TProviderOptions | undefined, Error, - Readonly<{ providerID: TProviderID; config: TConfigureProviderConfig }> + Readonly<{ targetOptionID?: string; options?: TProviderOptions }> >({ - mutationFn: async ({ providerID, config }) => { - return (await client.providers.setOptionsDry(providerID, config)).unwrap() + mutationFn: async ({ targetOptionID, options }) => { + const filteredOptions = filterOptions(formMethods.getValues(), options ?? currentOptions) + if (targetOptionID) { + stripOptionChildren(filteredOptions, currentOptions, targetOptionID) + } + + return ( + await client.providers.setOptionsDry(providerID, { options: filteredOptions }) + ).unwrap() }, onSuccess(data) { if (!data) { @@ -138,16 +150,28 @@ export function ConfigureProviderOptionsForm({ }) useEffect(() => { - if (Object.keys(suggestedOptions).length > 0) { + if (Object.keys(suggestedOptions ?? {}).length > 0) { + const opts = suggestedOptions ?? {} + const changedOptions = [] for (const option in suggestedOptions) { const { isDirty } = formMethods.getFieldState(option) if (!isDirty) { - formMethods.setValue(option, suggestedOptions[option], { + formMethods.setValue(option, opts[option], { shouldDirty: true, shouldValidate: true, shouldTouch: true, }) } + changedOptions.push(option) + } + if (changedOptions.length > 0) { + refreshSubOptionsMutation({ + options: changedOptions.reduce((acc, o) => { + const option = { value: opts[o] } as unknown as TProviderOption + + return { ...acc, [o]: option } + }, {} as TProviderOptions), + }) } } // only rerun when suggestedOptions changes @@ -202,19 +226,11 @@ export function ConfigureProviderOptionsForm({ const backgroundColor = useColorModeValue("gray.50", "gray.800") const borderColor = useBorderColor() - const refreshSubOptions = useCallback( + const handleRefreshSubOptions = useCallback( (id: string) => { - const filteredOptions = filterOptions(formMethods.getValues(), currentOptions) - stripOptionChildren(filteredOptions, currentOptions, id) - - refreshSubOptionsMutation({ - providerID, - config: { - options: filteredOptions, - }, - }) + refreshSubOptionsMutation({ targetOptionID: id }) }, - [formMethods, currentOptions, providerID, refreshSubOptionsMutation] + [refreshSubOptionsMutation] ) const handleSubmit: FormEventHandler = (event) => { @@ -256,7 +272,7 @@ export function ConfigureProviderOptionsForm({ {options.required.map((option) => ( @@ -277,7 +293,7 @@ export function ConfigureProviderOptionsForm({ {group.options.map((option) => ( @@ -295,7 +311,7 @@ export function ConfigureProviderOptionsForm({ {options.other.map((option) => ( ))} diff --git a/desktop/src/views/Providers/AddProvider/OptionFormField.tsx b/desktop/src/views/Providers/AddProvider/OptionFormField.tsx index b96307fb0..72d31a683 100644 --- a/desktop/src/views/Providers/AddProvider/OptionFormField.tsx +++ b/desktop/src/views/Providers/AddProvider/OptionFormField.tsx @@ -15,7 +15,7 @@ import { } from "@chakra-ui/react" type TOptionFormField = TOptionWithID & - Readonly<{ isRequired?: boolean; refreshSubOptions?: (id: string) => void }> + Readonly<{ isRequired?: boolean; onRefresh?: (id: string) => void }> export function OptionFormField({ id, @@ -27,7 +27,7 @@ export function OptionFormField({ displayName, suggestions, enum: enumProp, - refreshSubOptions, + onRefresh, subOptionsCommand, isRequired = false, }: TOptionFormField) { @@ -40,7 +40,7 @@ export function OptionFormField({ const defaultValueProp = exists(defaultValue) ? { defaultValue } : {} const props = { ...defaultValueProp, ...valueProp, ...registerProps } const refresh = () => { - refreshSubOptions?.(id) + onRefresh?.(id) } if (exists(suggestions)) { @@ -155,7 +155,7 @@ export function OptionFormField({ suggestions, enumProp, type, - refreshSubOptions, + onRefresh, subOptionsCommand, displayName, password, diff --git a/desktop/src/views/Settings/Settings.tsx b/desktop/src/views/Settings/Settings.tsx index 7f587fadd..4db679d1e 100644 --- a/desktop/src/views/Settings/Settings.tsx +++ b/desktop/src/views/Settings/Settings.tsx @@ -389,7 +389,7 @@ function ExperimentalSettings() {