diff --git a/src/pages/ConfigPage.test.ts b/src/pages/ConfigPage.test.ts new file mode 100644 index 000000000..18d88617c --- /dev/null +++ b/src/pages/ConfigPage.test.ts @@ -0,0 +1,34 @@ +import { describe, expect, it } from 'vitest'; +import { getUsageServiceBootstrapToSync } from './ConfigPage'; + +describe('getUsageServiceBootstrapToSync', () => { + it('returns the normalized service base after a successful auto-load', () => { + expect( + getUsageServiceBootstrapToSync({ + serviceBase: 'http://usage.local:18317/', + usageServiceEnabled: false, + usageServiceBase: '', + }) + ).toBe('http://usage.local:18317'); + }); + + it('skips syncing when the bootstrap address is already current', () => { + expect( + getUsageServiceBootstrapToSync({ + serviceBase: 'http://usage.local:18317/', + usageServiceEnabled: true, + usageServiceBase: 'http://usage.local:18317', + }) + ).toBe(''); + }); + + it('skips syncing when the loaded service base is empty', () => { + expect( + getUsageServiceBootstrapToSync({ + serviceBase: ' ', + usageServiceEnabled: false, + usageServiceBase: '', + }) + ).toBe(''); + }); +}); diff --git a/src/pages/ConfigPage.tsx b/src/pages/ConfigPage.tsx index eca1ea53f..861e368f1 100644 --- a/src/pages/ConfigPage.tsx +++ b/src/pages/ConfigPage.tsx @@ -52,6 +52,22 @@ const MANAGER_COLLECTOR_DEFAULT = { tlsSkipVerify: false, }; +// eslint-disable-next-line react-refresh/only-export-components +export function getUsageServiceBootstrapToSync({ + serviceBase, + usageServiceEnabled, + usageServiceBase, +}: { + serviceBase: string; + usageServiceEnabled: boolean; + usageServiceBase: string; +}): string { + const normalized = normalizeUsageServiceBase(serviceBase); + if (!normalized) return ''; + if (usageServiceEnabled && usageServiceBase === normalized) return ''; + return normalized; +} + const LazyConfigSourceEditor = lazy(() => import('@/components/config/ConfigSourceEditor')); function readCommercialModeFromYaml(yamlContent: string): boolean { @@ -235,6 +251,22 @@ export function ConfigPage() { return normalizeUsageServiceBase(preferred || ''); }, [detectedPanelBase, managerServiceBase, panelHostedByUsageService, usageServiceBase, usageServiceEnabled]); + const syncUsageServiceBootstrap = useCallback( + (serviceBase: string) => { + const normalized = getUsageServiceBootstrapToSync({ + serviceBase, + usageServiceEnabled, + usageServiceBase, + }); + if (!normalized) return; + setUsageServiceConfig({ + enabled: true, + serviceBase: normalized, + }); + }, + [setUsageServiceConfig, usageServiceBase, usageServiceEnabled] + ); + const applyManagerConfigResponse = useCallback( (response: ManagerConfigResponse, fallbackBase: string) => { const nextConfig = response.config; @@ -271,6 +303,7 @@ export function ConfigPage() { try { const response = await usageServiceApi.getManagerConfig(serviceBase, managementKey); applyManagerConfigResponse(response, serviceBase); + syncUsageServiceBootstrap(serviceBase); } catch (error: unknown) { setManagerError(getUsageServiceDisplayError(error, 'config_management.manager.load_failed')); } finally { @@ -281,6 +314,7 @@ export function ConfigPage() { getUsageServiceDisplayError, managementKey, resolveManagerServiceBase, + syncUsageServiceBootstrap, ]); const setManagerFieldDirty = useCallback(() => {