53 lines
1.7 KiB
TypeScript
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)));
|
|
}
|