Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions internal/ui/web/src/stores/sites.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,4 +247,29 @@ describe('sites store', () => {
expect(res.error).toBe('writing temp file: no space');
vi.unstubAllGlobals();
});

it('siteHasLogSources sees a proxy-only host site whose only source is a stripe listener', async () => {
const { siteHasLogSources } = await import('./sites');
const proxyOnly = {
domain: 'gonitro.test',
host_proxy: true,
host_has_dev_server: false,
has_app_logs: false,
uses_php: false,
stripe_running: true
} as unknown as import('./sites').Site;
expect(siteHasLogSources(proxyOnly)).toBe(true);
});

it('siteHasLogSources covers running and failing workers, and is false with no source', async () => {
const { siteHasLogSources } = await import('./sites');
const base = { domain: 'x.test', host_proxy: true } as unknown as import('./sites').Site;
expect(siteHasLogSources(base)).toBe(false);
expect(siteHasLogSources({ ...base, queue_running: true })).toBe(true);
expect(siteHasLogSources({ ...base, schedule_failing: true })).toBe(true);
expect(siteHasLogSources({ ...base, host_has_dev_server: true })).toBe(true);
expect(
siteHasLogSources({ ...base, framework_workers: [{ name: 'vite', running: true }] })
).toBe(true);
});
});
22 changes: 22 additions & 0 deletions internal/ui/web/src/stores/sites.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,28 @@ export function siteWorkerFailing(s: Site): boolean {
);
}

// siteHasLogSources reports whether a site exposes any streamable log tab: app
// logs, a PHP-FPM/container runtime, a host dev server, or any running/failing
// worker (queue, horizon, stripe, schedule, reverb, or a framework worker).
// Kept in sync with the tab list SiteLogs builds so the Logs tab is offered iff
// SiteLogs has something to show; a proxy-only host site whose sole source is a
// stripe listener would otherwise never get the tab.
export function siteHasLogSources(s: Site): boolean {
return Boolean(
s.has_app_logs ||
s.uses_php ||
s.custom_container ||
s.host_has_dev_server ||
s.queue_running ||
s.horizon_running ||
s.stripe_running ||
s.schedule_running ||
s.reverb_running ||
(s.framework_workers || []).some((w) => w.running) ||
siteWorkerFailing(s)
);
}

export type WorkerDotColor = 'amber' | 'violet' | 'emerald' | 'sky' | 'indigo';

// Colors for each running worker, used as little status dots in list rows and
Expand Down
9 changes: 4 additions & 5 deletions internal/ui/web/src/tabs/sites/SiteDetail.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import SiteEnvTab from './SiteEnvTab.svelte';
import SiteNginxModal from '../../modals/SiteNginxModal.svelte';
import SiteDebugTab from '$tabs/sites/SiteDebugTab.svelte';
import { resumeSite, loadSites, activeWorktreeDomain, type Site } from '$stores/sites';
import { resumeSite, loadSites, activeWorktreeDomain, siteHasLogSources, type Site } from '$stores/sites';
import { routeRest, goToTab } from '$stores/route';
import { m } from '../../paraglide/messages.js';

Expand Down Expand Up @@ -44,10 +44,9 @@
const canDumps = $derived(Boolean(site.uses_php));
const canEnv = $derived(Boolean(site.has_env));
// Logs get their own tab in the resource layout rather than living under the
// overview. Offer it whenever the site exposes any log source.
const canLogs = $derived(
Boolean(site.has_app_logs || site.uses_php || site.custom_container || site.host_has_dev_server)
);
// overview. Offer it whenever the site exposes any log source, including a
// worker-only source like a stripe listener on a proxy-only host site.
const canLogs = $derived(siteHasLogSources(site));
// A lone Overview tab can't be switched to anything, so don't render the tab
// row at all when no other tab is available (e.g. static sites).
const hasExtraTabs = $derived(canLogs || canEnv || canTinker || canDumps);
Expand Down
Loading