feat: integrate reports into Campaign navigation

This commit is contained in:
2026-07-29 22:19:24 +02:00
parent 101f3ccd7d
commit cc93945f79
7 changed files with 123 additions and 28 deletions
+16 -5
View File
@@ -2,6 +2,7 @@ import { createElement, lazy, useCallback } from "react";
import { Navigate, useParams } from "react-router-dom";
import {
ResourceAccessBoundary,
hasAnyScope,
type ApiSettings,
type AuthInfo,
type DashboardWidgetsUiCapability,
@@ -15,12 +16,15 @@ import "./styles/campaign-workspace.css";
const CampaignModulePage = lazy(() => import("./features/campaigns/CampaignModulePage"));
const CampaignWorkspace = lazy(() => import("./features/campaigns/CampaignWorkspace"));
const AggregateReportsPage = lazy(() => import("./features/reports/AggregateReportsPage"));
const TemplatesPage = lazy(() => import("./features/templates/TemplatesPage"));
const campaignRead = ["campaigns:campaign:read"];
const reportRead = ["campaigns:report:read"];
const campaignModuleRead = [...campaignRead, ...reportRead];
// Preserve the former /operator route identity for saved View projections.
const operatorQueueSurface = "campaigns.route.operator";
// Preserve the former /reports route identity for saved View projections.
const reportsSurface = "campaigns.route.reports";
const translations = {
en: generatedTranslations.en,
de: generatedTranslations.de
@@ -87,16 +91,16 @@ export const campaignModule: PlatformWebModule = {
}
],
navItems: [
{ to: "/campaigns", label: "i18n:govoplan-campaign.campaigns.01a23a28", iconName: "campaign", anyOf: campaignRead, order: 20 },
{ to: "/reports", label: "i18n:govoplan-campaign.reports.88bc3fe3", iconName: "clipboard-pen-line", anyOf: ["campaigns:report:read"], order: 70 },
{ to: "/campaigns", label: "i18n:govoplan-campaign.campaigns.01a23a28", iconName: "campaign", anyOf: campaignModuleRead, order: 20 },
{ to: "/templates", label: "i18n:govoplan-campaign.templates.f25b700e", iconName: "layout-template", order: 90 }],
routes: [
{ path: "/campaigns", anyOf: campaignRead, order: 20, render: ({ settings, auth }) => createElement(CampaignModulePage, { active: "campaigns", settings, auth }) },
{ path: "/campaigns", anyOf: campaignModuleRead, order: 20, render: ({ settings, auth }) => createElement(CampaignModuleLandingRoute, { settings, auth }) },
{ path: "/operator", anyOf: OPERATOR_QUEUE_ROUTE_SCOPES, allOf: campaignRead, order: 21, surfaceId: operatorQueueSurface, render: () => createElement(Navigate, { to: "/campaigns/queue", replace: true }) },
{ path: "/campaigns/queue", anyOf: OPERATOR_QUEUE_ROUTE_SCOPES, allOf: campaignRead, order: 21, surfaceId: operatorQueueSurface, render: ({ settings, auth }) => createElement(CampaignModulePage, { active: "queue", settings, auth }) },
{ path: "/reports", anyOf: reportRead, order: 22, surfaceId: reportsSurface, render: () => createElement(Navigate, { to: "/campaigns/reports", replace: true }) },
{ path: "/campaigns/reports", anyOf: reportRead, order: 22, surfaceId: reportsSurface, render: ({ settings, auth }) => createElement(CampaignModulePage, { active: "reports", settings, auth }) },
{ path: "/campaigns/:campaignId/*", anyOf: campaignRead, order: 22, render: ({ settings, auth }) => createElement(CampaignResourceRoute, { settings, auth }) },
{ path: "/reports", anyOf: ["campaigns:report:read"], order: 70, render: ({ settings }) => createElement(AggregateReportsPage, { settings }) },
{ path: "/templates", order: 90, render: () => createElement(TemplatesPage) }],
uiCapabilities: {
"dashboard.widgets": campaignDashboardWidgets
@@ -104,6 +108,13 @@ export const campaignModule: PlatformWebModule = {
};
function CampaignModuleLandingRoute({ settings, auth }: {settings: ApiSettings;auth: AuthInfo;}) {
if (!hasAnyScope(auth, campaignRead)) {
return createElement(Navigate, { to: "/campaigns/reports", replace: true });
}
return createElement(CampaignModulePage, { active: "campaigns", settings, auth });
}
function CampaignResourceRoute({ settings, auth }: {settings: ApiSettings;auth: AuthInfo;}) {
const { campaignId = "" } = useParams();
const tenantId = (auth.active_tenant ?? auth.tenant).id;