From b191173ae13ac6441ac3803533b349cc1ffbf195 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 17 May 2026 10:44:36 +0000 Subject: [PATCH] Fix Providers empty state blocking first provider setup --- .../(dashboard)/dashboard/providers/page.tsx | 102 +++++++++--------- .../dashboard/providers/providerPageUtils.ts | 14 +++ tests/unit/providers-page-utils.test.ts | 13 +++ 3 files changed, 81 insertions(+), 48 deletions(-) diff --git a/src/app/(dashboard)/dashboard/providers/page.tsx b/src/app/(dashboard)/dashboard/providers/page.tsx index 00d6c2c8d5..64446faaa4 100644 --- a/src/app/(dashboard)/dashboard/providers/page.tsx +++ b/src/app/(dashboard)/dashboard/providers/page.tsx @@ -31,6 +31,8 @@ import { buildMergedOAuthProviderEntries, buildStaticProviderEntries, filterConfiguredProviderEntries, + shouldApplyConfiguredOnlyFilter, + shouldShowFirstProviderHint, } from "./providerPageUtils"; import type { ProviderEntry } from "./providerPageUtils"; import { readConfiguredOnlyPreference, writeConfiguredOnlyPreference } from "./providerPageStorage"; @@ -423,6 +425,11 @@ export default function ProvidersPage() { textIcon: "CC", })); + const effectiveShowConfiguredOnly = shouldApplyConfiguredOnlyFilter( + showConfiguredOnly, + connections.length + ); + const oauthProviderEntriesAll = buildMergedOAuthProviderEntries( OAUTH_PROVIDERS, FREE_PROVIDERS, @@ -430,7 +437,7 @@ export default function ProvidersPage() { ); const oauthProviderEntries = filterConfiguredProviderEntries( oauthProviderEntriesAll, - showConfiguredOnly, + effectiveShowConfiguredOnly, searchQuery, showFreeOnly ); @@ -445,37 +452,37 @@ export default function ProvidersPage() { !VIDEO_PROVIDER_IDS.has(entry.providerId) && !EMBEDDING_RERANK_PROVIDER_IDS.has(entry.providerId) ), - showConfiguredOnly, + effectiveShowConfiguredOnly, searchQuery, showFreeOnly ); const aggregatorProviderEntries = filterConfiguredProviderEntries( apiKeyProviderEntriesAll.filter((entry) => AGGREGATOR_PROVIDER_IDS.has(entry.providerId)), - showConfiguredOnly, + effectiveShowConfiguredOnly, searchQuery, showFreeOnly ); const imageProviderEntries = filterConfiguredProviderEntries( apiKeyProviderEntriesAll.filter((entry) => IMAGE_ONLY_PROVIDER_IDS.has(entry.providerId)), - showConfiguredOnly, + effectiveShowConfiguredOnly, searchQuery, showFreeOnly ); const enterpriseProviderEntries = filterConfiguredProviderEntries( apiKeyProviderEntriesAll.filter((entry) => ENTERPRISE_CLOUD_PROVIDER_IDS.has(entry.providerId)), - showConfiguredOnly, + effectiveShowConfiguredOnly, searchQuery, showFreeOnly ); const videoProviderEntries = filterConfiguredProviderEntries( apiKeyProviderEntriesAll.filter((entry) => VIDEO_PROVIDER_IDS.has(entry.providerId)), - showConfiguredOnly, + effectiveShowConfiguredOnly, searchQuery, showFreeOnly ); const embeddingRerankProviderEntries = filterConfiguredProviderEntries( apiKeyProviderEntriesAll.filter((entry) => EMBEDDING_RERANK_PROVIDER_IDS.has(entry.providerId)), - showConfiguredOnly, + effectiveShowConfiguredOnly, searchQuery, showFreeOnly ); @@ -483,7 +490,7 @@ export default function ProvidersPage() { const webCookieProviderEntriesAll = buildStaticProviderEntries("web-cookie", getProviderStats); const webCookieProviderEntries = filterConfiguredProviderEntries( webCookieProviderEntriesAll, - showConfiguredOnly, + effectiveShowConfiguredOnly, searchQuery, showFreeOnly ); @@ -491,7 +498,7 @@ export default function ProvidersPage() { const localProviderEntriesAll = buildStaticProviderEntries("local", getProviderStats); const localProviderEntries = filterConfiguredProviderEntries( localProviderEntriesAll, - showConfiguredOnly, + effectiveShowConfiguredOnly, searchQuery, showFreeOnly ); @@ -499,7 +506,7 @@ export default function ProvidersPage() { const searchProviderEntriesAll = buildStaticProviderEntries("search", getProviderStats); const searchProviderEntries = filterConfiguredProviderEntries( searchProviderEntriesAll, - showConfiguredOnly, + effectiveShowConfiguredOnly, searchQuery, showFreeOnly ); @@ -507,7 +514,7 @@ export default function ProvidersPage() { const audioProviderEntriesAll = buildStaticProviderEntries("audio", getProviderStats); const audioProviderEntries = filterConfiguredProviderEntries( audioProviderEntriesAll, - showConfiguredOnly, + effectiveShowConfiguredOnly, searchQuery, showFreeOnly ); @@ -515,7 +522,7 @@ export default function ProvidersPage() { const cloudAgentProviderEntriesAll = buildStaticProviderEntries("cloud-agent", getProviderStats); const cloudAgentProviderEntries = filterConfiguredProviderEntries( cloudAgentProviderEntriesAll, - showConfiguredOnly, + effectiveShowConfiguredOnly, searchQuery, showFreeOnly ); @@ -523,7 +530,7 @@ export default function ProvidersPage() { const upstreamProxyEntriesAll = buildStaticProviderEntries("upstream-proxy", getProviderStats); const upstreamProxyEntries = filterConfiguredProviderEntries( upstreamProxyEntriesAll, - showConfiguredOnly, + effectiveShowConfiguredOnly, searchQuery, showFreeOnly ); @@ -553,7 +560,7 @@ export default function ProvidersPage() { ]; const compatibleProviderEntries = filterConfiguredProviderEntries( compatibleProviderEntriesAll, - showConfiguredOnly, + effectiveShowConfiguredOnly, searchQuery, showFreeOnly ); @@ -592,7 +599,7 @@ export default function ProvidersPage() { ); const freeSectionEntries = filterConfiguredProviderEntries( freeSectionEntriesAll, - showConfiguredOnly, + effectiveShowConfiguredOnly, searchQuery ); @@ -618,40 +625,37 @@ export default function ProvidersPage() { ); } - const totalConfigured = - oauthProviderEntriesAll.filter((e) => Number(e.stats?.total || 0) > 0).length + - apiKeyProviderEntriesAll.filter((e) => Number(e.stats?.total || 0) > 0).length + - webCookieProviderEntriesAll.filter((e) => Number(e.stats?.total || 0) > 0).length + - localProviderEntriesAll.filter((e) => Number(e.stats?.total || 0) > 0).length; - - if (totalConfigured === 0 && !searchQuery && !showAllProviders) { - return ( -
-
- dns -
-

{t("addFirstProvider")}

-

{t("addFirstProviderDesc")}

-
- - - help - {t("learnMore")} - -
-
- ); - } + const showFirstProviderHint = + shouldShowFirstProviderHint(connections.length, searchQuery) && !showAllProviders; return (
+ {showFirstProviderHint && ( + +
+
+ dns +
+

+ {t("addFirstProvider") || "Add your first provider"} +

+

+ {t("addFirstProviderDesc") || + "Connect an AI provider to start routing requests through OmniRoute. You can use free providers, API keys, or OAuth accounts."} +

+ + help + {t("learnMore") || "Learn more"} + +
+
+ )} + {/* Provider Summary Card */}
@@ -678,9 +682,10 @@ export default function ProvidersPage() {