From 1cdd7aa459d6e96905324b452600ff56369d8a4e Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Tue, 15 Sep 2026 22:51:15 -0400 Subject: [PATCH] refac --- .../components/AddTerminalServerModal.svelte | 172 ++++++++++-------- 1 file changed, 97 insertions(+), 75 deletions(-) diff --git a/src/lib/components/AddTerminalServerModal.svelte b/src/lib/components/AddTerminalServerModal.svelte index 15a1f1b00c..eba77c8f97 100644 --- a/src/lib/components/AddTerminalServerModal.svelte +++ b/src/lib/components/AddTerminalServerModal.svelte @@ -4,6 +4,7 @@ const i18n = getContext('i18n'); import Modal from '$lib/components/common/Modal.svelte'; + import Spinner from '$lib/components/common/Spinner.svelte'; import SensitiveInput from '$lib/components/common/SensitiveInput.svelte'; import Switch from '$lib/components/common/Switch.svelte'; import XMark from '$lib/components/icons/XMark.svelte'; @@ -30,6 +31,7 @@ export let onSubmit: Function = () => {}; export let onDelete: () => void = () => {}; + let loading = false; let url = ''; let key = ''; let name = ''; @@ -329,84 +331,98 @@ }; const submitHandler = async () => { - if (url === '') { - toast.error($i18n.t('Please enter a valid URL')); - return; - } + if (loading) return; + loading = true; - // Remove trailing slash - url = url.replace(/\/$/, ''); - // Bearer key whitespace breaks the terminal WebSocket auth (HTTP headers strip it, JSON doesn't) - key = key.trim(); - if (loadingPolicy) { - toast.error($i18n.t('Policy is still loading')); - return; - } - if (policyLoadError) { - toast.error($i18n.t('Failed to load policy: {{error}}', { error: policyLoadError })); - return; - } - - // Save policy to orchestrator if applicable - let policyData = {}; - let lifecycleData = {}; - if (serverType === 'orchestrator' && !direct && policyId) { - const parsedLifecycle = parseJson('Lifecycle JSON', lifecycleJson); - if (!parsedLifecycle) return; - policyData = buildPolicyData(); - lifecycleData = parsedLifecycle; - - try { - await putOrchestratorPolicy(localStorage.token, url, key, policyId, policyData, auth_type); - await putOrchestratorLifecycle( - localStorage.token, - url, - key, - policyId, - lifecycleData, - auth_type - ); - } catch (err) { - toast.error($i18n.t('Failed to save policy: {{error}}', { error: err })); + try { + if (url === '') { + toast.error($i18n.t('Please enter a valid URL')); return; } + + // Remove trailing slash + url = url.replace(/\/$/, ''); + // Bearer key whitespace breaks the terminal WebSocket auth (HTTP headers strip it, JSON doesn't) + key = key.trim(); + if (loadingPolicy) { + toast.error($i18n.t('Policy is still loading')); + return; + } + if (policyLoadError) { + toast.error($i18n.t('Failed to load policy: {{error}}', { error: policyLoadError })); + return; + } + + // Save policy to orchestrator if applicable + let policyData = {}; + let lifecycleData = {}; + if (serverType === 'orchestrator' && !direct && policyId) { + const parsedLifecycle = parseJson('Lifecycle JSON', lifecycleJson); + if (!parsedLifecycle) return; + policyData = buildPolicyData(); + lifecycleData = parsedLifecycle; + + try { + await putOrchestratorPolicy( + localStorage.token, + url, + key, + policyId, + policyData, + auth_type + ); + await putOrchestratorLifecycle( + localStorage.token, + url, + key, + policyId, + lifecycleData, + auth_type + ); + } catch (err) { + toast.error($i18n.t('Failed to save policy: {{error}}', { error: err })); + return; + } + } + + const contexts: Record = {}; + if (chatContextMode === 'off') contexts.chat = false; + else if (chatContextMode === 'chat_id') contexts.chat = { context_id: 'chat_id' }; + if (automationContextMode === 'off') contexts.automation = false; + else if (automationContextMode === 'automation_id') { + contexts.automation = { context_id: 'automation_id' }; + } + const useContexts = + !direct && serverType === 'orchestrator' && Object.keys(contexts).length > 0; + const connectionConfig: Record = + connection?.config && typeof connection.config === 'object' ? { ...connection.config } : {}; + if (!direct) connectionConfig.access_grants = accessGrants; + else delete connectionConfig.access_grants; + if (useContexts) connectionConfig.contexts = contexts; + else delete connectionConfig.contexts; + if (chatUploads === 'filesystem') connectionConfig.chat_uploads = 'filesystem'; + else delete connectionConfig.chat_uploads; + + const result = { + ...(!direct && id.trim() ? { id: id.trim() } : {}), + url, + key, + name, + path, + auth_type, + ...(!direct ? { forward_cookies: forwardCookies } : {}), + enabled: enabled, + config: connectionConfig, + // Policy fields + ...(serverType ? { server_type: serverType } : {}), + ...(serverType === 'orchestrator' && policyId ? { policy_id: policyId } : {}) + }; + + await onSubmit(result); + show = false; + } finally { + loading = false; } - - const contexts: Record = {}; - if (chatContextMode === 'off') contexts.chat = false; - else if (chatContextMode === 'chat_id') contexts.chat = { context_id: 'chat_id' }; - if (automationContextMode === 'off') contexts.automation = false; - else if (automationContextMode === 'automation_id') { - contexts.automation = { context_id: 'automation_id' }; - } - const useContexts = - !direct && serverType === 'orchestrator' && Object.keys(contexts).length > 0; - const connectionConfig: Record = - connection?.config && typeof connection.config === 'object' ? { ...connection.config } : {}; - if (!direct) connectionConfig.access_grants = accessGrants; - else delete connectionConfig.access_grants; - if (useContexts) connectionConfig.contexts = contexts; - else delete connectionConfig.contexts; - if (chatUploads === 'filesystem') connectionConfig.chat_uploads = 'filesystem'; - else delete connectionConfig.chat_uploads; - - const result = { - ...(!direct && id.trim() ? { id: id.trim() } : {}), - url, - key, - name, - path, - auth_type, - ...(!direct ? { forward_cookies: forwardCookies } : {}), - enabled: enabled, - config: connectionConfig, - // Policy fields - ...(serverType ? { server_type: serverType } : {}), - ...(serverType === 'orchestrator' && policyId ? { policy_id: policyId } : {}) - }; - - onSubmit(result); - show = false; }; @@ -1002,9 +1018,15 @@