diff --git a/frontend/src/pages/IntegrationHub.tsx b/frontend/src/pages/IntegrationHub.tsx
index 0241661..4ff6f92 100644
--- a/frontend/src/pages/IntegrationHub.tsx
+++ b/frontend/src/pages/IntegrationHub.tsx
@@ -276,16 +276,23 @@ const IntegrationHub: React.FC = () => {
All API calls require authentication via API Key . Include the header X-API-Key: fk_your_key in every request.
- Go to Settings and open the API Keys tab
+ Go to Settings > API Keys
Click Generate New API Key and give it a descriptive name (e.g. "azure-devops-pipeline")
Copy the generated key (starts with fk_ ) and store it securely in your CI/CD platform's secrets/variables
-
+
+
+
}>
+ Generate API Key
+
+
+
+
);
@@ -626,23 +633,82 @@ const IntegrationHub: React.FC = () => {
)}
{integrationType === 'dependency' && currentStep === 2 && summaryData?.success && (
-
-
-
- }>
- {summaryData.service.name}
- {summaryData.service.namespace}
- {summaryData.service.kind && {summaryData.service.kind} }
-
-
-
-
- Downstream>} value={summaryData.summary?.total_downstream_unique ?? 0} valueStyle={{ fontSize: 18 }} />
- Callers>} value={summaryData.summary?.total_callers_unique ?? 0} valueStyle={{ fontSize: 18 }} />
-
-
-
-
+ {summaryData.multi_service && summaryData.matched_services ? (() => {
+ const namespaces = Array.from(new Set(summaryData.matched_services.map(s => s.namespace))).sort();
+ const critCount = summaryData.summary?.downstream_critical_count ?? 0;
+ return (
+
+
+
+
+
+
+
+
+
+ Downstream>}
+ value={summaryData.summary?.total_downstream_unique ?? 0}
+ valueStyle={{ fontSize: 28, fontWeight: 700 }}
+ />
+
+
+ Callers>}
+ value={summaryData.summary?.total_callers_unique ?? 0}
+ valueStyle={{ fontSize: 28, fontWeight: 700 }}
+ />
+
+ {critCount > 0 && (
+
+
+
+ )}
+
+ {namespaces.length > 0 && (
+
+ {namespaces.map(ns => (
+ {ns}
+ ))}
+
+ )}
+
+ );
+ })() : (
+
+
+
+ }>
+ {summaryData.service.name}
+ {summaryData.service.namespace}
+ {summaryData.service.kind && {summaryData.service.kind} }
+
+
+
+
+ Downstream>} value={summaryData.summary?.total_downstream_unique ?? 0} valueStyle={{ fontSize: 18 }} />
+ Callers>} value={summaryData.summary?.total_callers_unique ?? 0} valueStyle={{ fontSize: 18 }} />
+
+
+
+
+ )}
{summaryData.multi_service && summaryData.matched_services && summaryData.matched_services.length > 0 && (
diff --git a/frontend/src/pages/Settings.tsx b/frontend/src/pages/Settings.tsx
index 2e1a25a..0a668fa 100644
--- a/frontend/src/pages/Settings.tsx
+++ b/frontend/src/pages/Settings.tsx
@@ -4,6 +4,7 @@
*/
import React, { useState, useEffect, useCallback } from 'react';
+import { useSearchParams } from 'react-router-dom';
import { useTheme } from '../contexts/ThemeContext';
import {
Card,
@@ -223,8 +224,14 @@ interface IntegrationSettings {
// ================== MAIN COMPONENT ==================
const Settings: React.FC = () => {
- const [activeTab, setActiveTab] = useState('general');
+ const [searchParams, setSearchParams] = useSearchParams();
+ const [activeTab, setActiveTab] = useState(() => searchParams.get('tab') || 'general');
const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ const tab = searchParams.get('tab') || 'general';
+ setActiveTab(prev => prev !== tab ? tab : prev);
+ }, [searchParams]);
const [saving, setSaving] = useState(null);
const [isAdmin, setIsAdmin] = useState(false);
const [lastUpdated, setLastUpdated] = useState(null);
@@ -1337,7 +1344,7 @@ const Settings: React.FC = () => {
{/* Admin Warning - not shown for API Keys tab (users can manage their own keys) */}
- {!isAdmin && activeTab !== 'api-keys' && (
+ {!isAdmin && activeTab !== 'api-tokens' && (
{
{/* Settings Tabs */}
{
+ setActiveTab(key);
+ setSearchParams(key === 'general' ? {} : { tab: key }, { replace: true });
+ }}
type="card"
size="large"
>