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.
    -
  1. Go to Settings and open the API Keys tab
  2. +
  3. Go to Settings > API Keys
  4. Click Generate New API Key and give it a descriptive name (e.g. "azure-devops-pipeline")
  5. Copy the generated key (starts with fk_) and store it securely in your CI/CD platform's secrets/variables
- +
+ + + + +
); @@ -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" >