Files
govoplan-campaign/webui/src/module.ts
T
zemion 2630498026
Module Package Release / publish-packages (push) Successful in 14s
feat(campaigns): add accountable work assignments
2026-08-22 00:50:03 +02:00

154 lines
5.6 KiB
TypeScript

import { createElement, lazy, useCallback } from "react";
import { Navigate, useParams } from "react-router";
import {
ResourceAccessBoundary,
hasAnyScope,
type ApiSettings,
type AuthInfo,
type DashboardWidgetsUiCapability,
type PlatformWebModule,
type QuickAccessToolsUiCapability
} from "@govoplan/core-webui";
import { getCampaign } from "./api/campaigns";
import CampaignActivityWidget from "./features/campaigns/CampaignActivityWidget";
import CampaignQuickAccess from "./features/campaigns/CampaignQuickAccess";
import { OPERATOR_QUEUE_ROUTE_SCOPES } from "./features/operator/operatorQueueAccess";
import { generatedTranslations } from "./i18n/generatedTranslations";
import { campaignWizardDirectories } from "./features/campaigns/wizard/directory";
import "./styles/campaign-workspace.css";
const CampaignModulePage = lazy(() => import("./features/campaigns/CampaignModulePage"));
const CampaignWorkspace = lazy(() => import("./features/campaigns/CampaignWorkspace"));
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";
const reportsSurface = "campaigns.route.reports";
const translations = {
en: generatedTranslations.en,
de: generatedTranslations.de
};
const campaignDashboardWidgets: DashboardWidgetsUiCapability = {
widgets: [
{
id: "campaigns.activity",
surfaceId: "campaigns.widget.activity",
title: "Campaign activity",
description: "Recently changed campaigns and delivery state.",
moduleId: "campaigns",
category: "Communication",
order: 50,
defaultVisible: false,
defaultSize: "medium",
supportedSizes: ["medium", "wide"],
anyOf: campaignRead,
refreshIntervalMs: 30_000,
defaultConfiguration: {
maxItems: 5,
showCompleted: false
},
configurationFields: [
{
id: "maxItems",
label: "Maximum campaigns",
kind: "number",
min: 1,
max: 12,
step: 1,
required: true
},
{
id: "showCompleted",
label: "Include completed campaigns",
kind: "boolean"
}
],
render: ({ settings, refreshKey, configuration }) =>
createElement(CampaignActivityWidget, {
settings,
refreshKey,
configuration
})
}
]
};
const campaignQuickAccessTools: QuickAccessToolsUiCapability = {
tools: [
{
id: "campaigns.select",
render: (context) => createElement(CampaignQuickAccess, context)
}
]
};
export const campaignModule: PlatformWebModule = {
id: "campaigns",
label: "i18n:govoplan-campaign.campaigns.01a23a28",
version: "1.0.0",
dependencies: ["access"],
optionalDependencies: ["files", "mail", "notifications", "organizations", "idm", "tasks"],
translations,
viewSurfaces: [
{
id: "campaigns.page.work",
moduleId: "campaigns",
kind: "page",
label: "Campaign work",
order: 44
},
{
id: "campaigns.page.activity",
moduleId: "campaigns",
kind: "page",
label: "Campaign collaboration",
order: 45
},
{
id: "campaigns.widget.activity",
moduleId: "campaigns",
kind: "section",
label: "Campaign activity widget",
order: 50
}
],
navItems: [
{ to: "/campaigns", label: "i18n:govoplan-campaign.campaigns.01a23a28", iconName: "campaign", anyOf: campaignModuleRead, order: 20 }],
routes: [
{ 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: "/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 }) }],
uiCapabilities: {
"dashboard.widgets": campaignDashboardWidgets,
"quickAccess.tools": campaignQuickAccessTools,
"wizard.directories": campaignWizardDirectories
}
};
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;
const probe = useCallback(() => getCampaign(settings, campaignId), [settings.apiBaseUrl, settings.apiKey, settings.accessToken, campaignId, tenantId]);
return createElement(ResourceAccessBoundary, {
probe,
resetKey: `${tenantId}:${campaignId}`,
fallback: "/campaigns",
children: createElement(CampaignWorkspace, { settings, auth })
});
}
export default campaignModule;