diff --git a/webui/src/pages/Dashboard.jsx b/webui/src/pages/Dashboard.jsx index 9ef95cb..60f36d5 100644 --- a/webui/src/pages/Dashboard.jsx +++ b/webui/src/pages/Dashboard.jsx @@ -24,14 +24,16 @@ function Dashboard({ isOnline }) { const { domain = 'cell', cell_name = 'mycell', effective_domain, domain_mode = 'lan' } = useConfig(); const svcDomain = (domain_mode !== 'lan' && effective_domain) ? effective_domain : domain; const proto = domain_mode === 'lan' ? 'http' : 'https'; - const SERVICES = [ - { name: 'Cell Home', url: domain_mode === 'lan' ? `http://${cell_name}.${domain}` : `https://${svcDomain}`, desc: 'Main UI — no login needed' }, - { name: 'Calendar', url: `${proto}://calendar.${svcDomain}`, desc: 'Use your configured account credentials' }, - { name: 'Files', url: `${proto}://files.${svcDomain}`, desc: 'Use your configured account credentials' }, - { name: 'Webmail', url: `${proto}://mail.${svcDomain}`, desc: 'Use your configured account credentials' }, + const ALL_SERVICE_LINKS = [ + { id: null, name: 'Cell Home', url: domain_mode === 'lan' ? `http://${cell_name}.${domain}` : `https://${svcDomain}`, desc: 'Main UI — no login needed' }, + { id: 'calendar', name: 'Calendar', url: `${proto}://calendar.${svcDomain}`, desc: 'Use your configured account credentials' }, + { id: 'files', name: 'Files', url: `${proto}://files.${svcDomain}`, desc: 'Use your configured account credentials' }, + { id: 'email', name: 'Webmail', url: `${proto}://mail.${svcDomain}`, desc: 'Use your configured account credentials' }, ]; + const SERVICES = ALL_SERVICE_LINKS.filter(s => s.id === null || activeServiceIds.has(s.id)); const [cellStatus, setCellStatus] = useState(null); const [servicesStatus, setServicesStatus] = useState(null); + const [activeServiceIds, setActiveServiceIds] = useState(new Set()); const [isLoading, setIsLoading] = useState(true); const [serviceControls, setServiceControls] = useState({}); @@ -177,24 +179,27 @@ function Dashboard({ isOnline }) { } try { - const [statusResponse, servicesResponse] = await Promise.all([ + const [statusResponse, servicesResponse, activeResponse] = await Promise.all([ cellAPI.getStatus(), - servicesAPI.getAllStatus() + servicesAPI.getAllStatus(), + servicesAPI.listActive().catch(() => ({ data: [] })), ]); - + setCellStatus(statusResponse.data); - - // Transform services data to match expected structure + + const installed = new Set((activeResponse.data || []).map(s => s.id)); + setActiveServiceIds(installed); + const servicesData = servicesResponse.data; const transformedServices = { wireguard: servicesData.wireguard || { running: false, status: 'offline' }, - email: servicesData.email || { running: false, status: 'offline' }, - calendar: servicesData.calendar || { running: false, status: 'offline' }, - files: servicesData.files || { running: false, status: 'offline' }, routing: servicesData.routing || { running: false, status: 'offline' }, - network: servicesData.network || { running: false, status: 'offline' } + network: servicesData.network || { running: false, status: 'offline' }, + ...(installed.has('email') && { email: servicesData.email || { running: false, status: 'offline' } }), + ...(installed.has('calendar') && { calendar: servicesData.calendar || { running: false, status: 'offline' } }), + ...(installed.has('files') && { files: servicesData.files || { running: false, status: 'offline' } }), }; - + setServicesStatus(transformedServices); } catch (error) { console.error('Failed to fetch dashboard data:', error); @@ -296,11 +301,11 @@ function Dashboard({ isOnline }) {