Sync GovOPlaN module state

This commit is contained in:
2026-07-10 21:57:21 +02:00
parent 30a0281c66
commit f362f3806b
6 changed files with 340 additions and 0 deletions

View File

@@ -416,6 +416,8 @@ export default function ModuleManagementPanel({ settings, canWrite, canAccessMai
{item.tags.length > 0 && <span>{item.tags.join(", ")}</span>}
{item.license_features.length > 0 && <span>i18n:govoplan-admin.license.de13bf1a {item.license_features.join(", ")}</span>}
{item.license_missing_features.length > 0 && <span>i18n:govoplan-admin.missing.feb2bbaa {item.license_missing_features.join(", ")}</span>}
{item.provides_interfaces.length > 0 && <span>i18n:govoplan-admin.provides.221b70d9 {providedInterfacesLabel(item)}</span>}
{item.requires_interfaces.length > 0 && <span>i18n:govoplan-admin.requires.a4fc9357 {requiredInterfacesLabel(item)}</span>}
</div>
{item.description && <p className="module-package-catalog-description">{item.description}</p>}
{item.license_reason && <p className={`module-package-catalog-description${item.license_allowed ? "" : " alert warning"}`}>{item.license_reason}</p>}
@@ -471,6 +473,12 @@ export default function ModuleManagementPanel({ settings, canWrite, canAccessMai
{draftPlanItems.length === 0 && <div className="module-install-plan-empty">i18n:govoplan-admin.no_package_changes_planned.f12d8b33</div>}
{draftPlanItems.map((item, index) =>
<div className="module-install-plan-row" key={`${item.module_id}-${index}`}>
<div className="module-install-plan-row-meta">
<StatusBadge status={item.source === "catalog" ? "success" : "inactive"} label={item.source === "catalog" ? "i18n:govoplan-admin.catalog.4a88d27b" : "i18n:govoplan-admin.manual.17a486ca"} />
{item.catalog?.channel && <StatusBadge status="inactive" label={i18nMessage("i18n:govoplan-admin.channel_value.d3894efe", { value0: String(item.catalog.channel) })} />}
{item.catalog?.sequence !== null && item.catalog?.sequence !== undefined && <StatusBadge status="inactive" label={i18nMessage("i18n:govoplan-admin.seq_value.0ae5fa47", { value0: item.catalog.sequence })} />}
{item.catalog?.key_id && <StatusBadge status="inactive" label={i18nMessage("i18n:govoplan-admin.key_value.847b914f", { value0: String(item.catalog.key_id) })} />}
</div>
<label><span>i18n:govoplan-admin.action.97c89a4d</span><select value={item.action} disabled={!canWrite || planBusy} onChange={(event) => updatePlanItem(index, { action: event.target.value as ModuleInstallPlanItem["action"] })}><option value="install">i18n:govoplan-admin.install.fd6c3ebf</option><option value="uninstall">i18n:govoplan-admin.uninstall.a735da1d</option></select></label>
<label><span>i18n:govoplan-admin.module.b8ff0289</span><input value={item.module_id} disabled={!canWrite || planBusy} onChange={(event) => updatePlanItem(index, { module_id: event.target.value })} placeholder="files" /></label>
<label><span>i18n:govoplan-admin.python_package.34591c71</span><input value={item.python_package ?? ""} disabled={!canWrite || planBusy} onChange={(event) => updatePlanItem(index, { python_package: event.target.value })} placeholder="govoplan-files" /></label>
@@ -621,6 +629,21 @@ function LicenseStatus({ license }: {license: ModuleLicenseDiagnostics;}) {
}
function providedInterfacesLabel(item: ModulePackageCatalogItem): string {
return item.provides_interfaces.map((provided) => `${provided.name}@${provided.version}`).join(", ");
}
function requiredInterfacesLabel(item: ModulePackageCatalogItem): string {
return item.requires_interfaces.map((required) => {
const range = [
required.version_min ? `>=${required.version_min}` : "",
required.version_max_exclusive ? `<${required.version_max_exclusive}` : "",
].filter(Boolean).join(" ");
const suffix = range ? ` ${range}` : "";
return `${required.optional ? "optional " : ""}${required.name}${suffix}`;
}).join(", ");
}
function ModuleStatus({ module, desiredEnabled }: {module: ModuleCatalogItem;desiredEnabled: boolean;}) {
if (module.current_enabled && !desiredEnabled) return <StatusBadge status="warning" label="i18n:govoplan-admin.will_disable.14bb193a" />;
if (!module.current_enabled && desiredEnabled) return <StatusBadge status="warning" label="i18n:govoplan-admin.will_enable.5d52d70b" />;
@@ -640,6 +663,8 @@ function emptyPlanItem(): ModuleInstallPlanItem {
return {
module_id: "",
action: "install",
source: "manual",
catalog: null,
python_package: "",
python_ref: "",
webui_package: "",
@@ -655,6 +680,8 @@ function normalizePlanItems(items: ModuleInstallPlanItem[]): ModuleInstallPlanIt
map((item) => ({
module_id: item.module_id.trim(),
action: item.action,
source: item.source === "catalog" ? "catalog" : "manual",
catalog: item.source === "catalog" ? item.catalog ?? null : null,
python_package: cleanOptional(item.python_package),
python_ref: item.action === "install" ? cleanOptional(item.python_ref) : null,
webui_package: cleanOptional(item.webui_package),