Files
govoplan-dashboard/webui/src/features/dashboard/widgets/InstalledModulesWidget.tsx

53 lines
1.7 KiB
TypeScript

import {
StatusBadge,
type DashboardWidgetConfiguration,
type PlatformWebModule
} from "@govoplan/core-webui";
export default function InstalledModulesWidget({
modules,
configuration
}: {
modules: PlatformWebModule[];
configuration: DashboardWidgetConfiguration;
}) {
if (!modules.length) return <p className="muted">No WebUI modules are active.</p>;
const maxItems = clampNumber(configuration.maxItems, 1, 50, 8);
const showVersions = configuration.showVersions !== false;
const sortBy = configuration.sortBy === "label" ? "label" : "module";
const visibleModules = [...modules]
.sort((left, right) => {
const leftValue = sortBy === "label" ? left.label : left.id;
const rightValue = sortBy === "label" ? right.label : right.id;
return String(leftValue).localeCompare(String(rightValue));
})
.slice(0, maxItems);
const remaining = Math.max(modules.length - visibleModules.length, 0);
return (
<>
<dl className="detail-list dashboard-compact-list">
{visibleModules.map((module) =>
<div key={module.id}>
<dt><StatusBadge status="success" label={module.id} /></dt>
<dd>
<strong>{module.label}</strong>
{showVersions && <span className="muted"> v{module.version}</span>}
</dd>
</div>
)}
</dl>
{remaining > 0 && <p className="muted dashboard-widget-overflow">+{remaining} more active modules</p>}
</>);
}
function clampNumber(
value: DashboardWidgetConfiguration[string],
minimum: number,
maximum: number,
fallback: number
): number {
if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
return Math.min(maximum, Math.max(minimum, Math.round(value)));
}