fix: dashboard only shows email/calendar/files if installed
Unit Tests / test (push) Successful in 11m25s
Unit Tests / test (push) Successful in 11m25s
Fetches /api/services/active on load; service status cards and quick- access links for email, calendar, files, and webmail are suppressed until the service is installed via the Store. Core services (WireGuard, Routing, Network) always show. Fixes #setup_complete gate on dev stack. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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,22 +179,25 @@ 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);
|
||||
@@ -296,11 +301,11 @@ function Dashboard({ isOnline }) {
|
||||
<h2 className="text-lg font-semibold text-gray-900 mb-4">Services Status</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{renderServiceCard('wireguard', <Shield className="h-6 w-6 text-primary-500" />, 'WireGuard', servicesStatus.wireguard)}
|
||||
{renderServiceCard('email', <Mail className="h-6 w-6 text-primary-500" />, 'Email', servicesStatus.email)}
|
||||
{renderServiceCard('calendar', <Calendar className="h-6 w-6 text-primary-500" />, 'Calendar', servicesStatus.calendar)}
|
||||
{renderServiceCard('files', <FolderOpen className="h-6 w-6 text-primary-500" />, 'Files', servicesStatus.files)}
|
||||
{renderServiceCard('routing', <Wifi className="h-6 w-6 text-primary-500" />, 'Routing', servicesStatus.routing)}
|
||||
{renderServiceCard('network', <Server className="h-6 w-6 text-primary-500" />, 'Network', servicesStatus.network)}
|
||||
{servicesStatus.email && renderServiceCard('email', <Mail className="h-6 w-6 text-primary-500" />, 'Email', servicesStatus.email)}
|
||||
{servicesStatus.calendar && renderServiceCard('calendar', <Calendar className="h-6 w-6 text-primary-500" />, 'Calendar', servicesStatus.calendar)}
|
||||
{servicesStatus.files && renderServiceCard('files', <FolderOpen className="h-6 w-6 text-primary-500" />, 'Files', servicesStatus.files)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user