fix(web): resolve dashboard widget errors and deployment config #530

Merged
jason.woltje merged 1 commits from fix/web-deployment-issues into main 2026-02-27 03:49:58 +00:00
4 changed files with 25 additions and 11 deletions

View File

@@ -79,7 +79,7 @@ OIDC_CLIENT_ID=your-client-id-here
OIDC_CLIENT_SECRET=your-client-secret-here OIDC_CLIENT_SECRET=your-client-secret-here
# Redirect URI must match what's configured in Authentik # Redirect URI must match what's configured in Authentik
# Development: http://localhost:3001/auth/oauth2/callback/authentik # Development: http://localhost:3001/auth/oauth2/callback/authentik
# Production: https://api.mosaicstack.dev/auth/oauth2/callback/authentik # Production: https://mosaic-api.woltje.com/auth/oauth2/callback/authentik
OIDC_REDIRECT_URI=http://localhost:3001/auth/oauth2/callback/authentik OIDC_REDIRECT_URI=http://localhost:3001/auth/oauth2/callback/authentik
# Authentik PostgreSQL Database # Authentik PostgreSQL Database
@@ -361,17 +361,17 @@ RATE_LIMIT_STORAGE=redis
# a single workspace. # a single workspace.
MATRIX_HOMESERVER_URL=http://synapse:8008 MATRIX_HOMESERVER_URL=http://synapse:8008
MATRIX_ACCESS_TOKEN= MATRIX_ACCESS_TOKEN=
MATRIX_BOT_USER_ID=@mosaic-bot:matrix.example.com MATRIX_BOT_USER_ID=@mosaic-bot:matrix.woltje.com
MATRIX_SERVER_NAME=matrix.example.com MATRIX_SERVER_NAME=matrix.woltje.com
# MATRIX_CONTROL_ROOM_ID=!roomid:matrix.example.com # MATRIX_CONTROL_ROOM_ID=!roomid:matrix.woltje.com
# MATRIX_WORKSPACE_ID=your-workspace-uuid # MATRIX_WORKSPACE_ID=your-workspace-uuid
# ====================== # ======================
# Matrix / Synapse Deployment # Matrix / Synapse Deployment
# ====================== # ======================
# Domains for Traefik routing to Matrix services # Domains for Traefik routing to Matrix services
MATRIX_DOMAIN=matrix.example.com MATRIX_DOMAIN=matrix.woltje.com
ELEMENT_DOMAIN=chat.example.com ELEMENT_DOMAIN=chat.woltje.com
# Synapse database (created automatically by synapse-db-init in the swarm compose) # Synapse database (created automatically by synapse-db-init in the swarm compose)
SYNAPSE_POSTGRES_DB=synapse SYNAPSE_POSTGRES_DB=synapse

View File

@@ -326,7 +326,7 @@ function LoginPageContent(): ReactElement {
</div> </div>
<div className="mt-6 flex justify-center"> <div className="mt-6 flex justify-center">
<AuthStatusPill label="Mosaic v0.1" tone="neutral" /> <AuthStatusPill label="Mosaic v0.0.20" tone="neutral" />
</div> </div>
</AuthCard> </AuthCard>
</AuthShell> </AuthShell>

View File

@@ -7,6 +7,7 @@ import { useState, useEffect } from "react";
import { FolderOpen, Bot, Activity, Clock, AlertCircle, CheckCircle2 } from "lucide-react"; import { FolderOpen, Bot, Activity, Clock, AlertCircle, CheckCircle2 } from "lucide-react";
import type { WidgetProps } from "@mosaic/shared"; import type { WidgetProps } from "@mosaic/shared";
import { apiPost } from "@/lib/api/client"; import { apiPost } from "@/lib/api/client";
import { useWorkspaceId } from "@/lib/hooks";
interface ActiveProject { interface ActiveProject {
id: string; id: string;
@@ -34,6 +35,7 @@ interface AgentSession {
} }
export function ActiveProjectsWidget({ id: _id, config: _config }: WidgetProps): React.JSX.Element { export function ActiveProjectsWidget({ id: _id, config: _config }: WidgetProps): React.JSX.Element {
const workspaceId = useWorkspaceId();
const [projects, setProjects] = useState<ActiveProject[]>([]); const [projects, setProjects] = useState<ActiveProject[]>([]);
const [agentSessions, setAgentSessions] = useState<AgentSession[]>([]); const [agentSessions, setAgentSessions] = useState<AgentSession[]>([]);
const [isLoadingProjects, setIsLoadingProjects] = useState(true); const [isLoadingProjects, setIsLoadingProjects] = useState(true);
@@ -48,7 +50,11 @@ export function ActiveProjectsWidget({ id: _id, config: _config }: WidgetProps):
try { try {
setProjectsError(null); setProjectsError(null);
// Use API client to ensure CSRF token is included // Use API client to ensure CSRF token is included
const data = await apiPost<ActiveProject[]>("/api/widgets/data/active-projects"); const data = await apiPost<ActiveProject[]>(
"/api/widgets/data/active-projects",
undefined,
workspaceId ?? undefined
);
setProjects(data); setProjects(data);
} catch (error) { } catch (error) {
console.error("Failed to fetch active projects:", error); console.error("Failed to fetch active projects:", error);
@@ -67,7 +73,7 @@ export function ActiveProjectsWidget({ id: _id, config: _config }: WidgetProps):
return (): void => { return (): void => {
clearInterval(interval); clearInterval(interval);
}; };
}, []); }, [workspaceId]);
// Fetch agent chains // Fetch agent chains
useEffect(() => { useEffect(() => {
@@ -75,7 +81,11 @@ export function ActiveProjectsWidget({ id: _id, config: _config }: WidgetProps):
try { try {
setAgentsError(null); setAgentsError(null);
// Use API client to ensure CSRF token is included // Use API client to ensure CSRF token is included
const data = await apiPost<AgentSession[]>("/api/widgets/data/agent-chains"); const data = await apiPost<AgentSession[]>(
"/api/widgets/data/agent-chains",
undefined,
workspaceId ?? undefined
);
setAgentSessions(data); setAgentSessions(data);
} catch (error) { } catch (error) {
console.error("Failed to fetch agent sessions:", error); console.error("Failed to fetch agent sessions:", error);
@@ -94,7 +104,7 @@ export function ActiveProjectsWidget({ id: _id, config: _config }: WidgetProps):
return (): void => { return (): void => {
clearInterval(interval); clearInterval(interval);
}; };
}, []); }, [workspaceId]);
const getStatusIcon = (status: string): React.JSX.Element => { const getStatusIcon = (status: string): React.JSX.Element => {
const statusUpper = status.toUpperCase(); const statusUpper = status.toUpperCase();

View File

@@ -176,6 +176,9 @@ services:
NODE_ENV: production NODE_ENV: production
PORT: ${WEB_PORT:-3000} PORT: ${WEB_PORT:-3000}
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL} NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL}
# Server-side orchestrator proxy (API routes forward to orchestrator service)
ORCHESTRATOR_URL: http://orchestrator:3001
ORCHESTRATOR_API_KEY: ${ORCHESTRATOR_API_KEY}
healthcheck: healthcheck:
test: test:
[ [
@@ -187,6 +190,7 @@ services:
retries: 3 retries: 3
start_period: 40s start_period: 40s
networks: networks:
- internal
- traefik-public - traefik-public
deploy: deploy:
restart_policy: restart_policy: