metis-desk/modules/resources/src/api/application/global-resource-specification.ts
David d2bf856c97 feat(global-operating-systems): implement global operating systems management features
- Add softwareReferenceHref helper function for generating resource links.
- Create useGlobalResourceEditor hook for managing global application resources.
- Implement useGlobalResourceForm hook for handling global resource forms.
- Introduce GlobalSoftwareCatalogProvider for context management of global applications.
- Develop GlobalOperatingSystemsPage to render global operating systems using the existing GlobalApplicationsPage.
- Add operating system form identity helpers for managing OS-specific fields.
- Create operating system specification labels for better localization.
- Implement OperatingSystemIdentityReview component for reviewing OS identities.
- Add OperatingSystemProductFields component for displaying OS product details.
- Write tests for resource characteristic control to ensure proper translation and value handling.
- Create a Python script for auditing global operating systems UI interactions.
- Add tests for expanded workstation profiles to ensure proper functionality and responsiveness.
2026-10-25 20:39:06 +01:00

69 lines
2.5 KiB
TypeScript

import { Result } from "@repo/rdx-utils";
import type { ResourceCatalog } from "../domain/resource-catalog.aggregate";
import { ResourceCatalogError } from "../domain/resource-definition";
import { ResourceSpecification } from "../domain/value-objects/resource-values.vo";
/** Captura exclusivamente la plantilla de serie y campos de propietario global. */
export function captureGlobalResourceSpecification(
catalog: ResourceCatalog,
templateId: string,
options: { existing: boolean; kind?: "application" | "os" }
) {
const template = catalog.definitions.find(
(item) => item.id.toPrimitive() === templateId.toLowerCase()
);
if (
!template ||
template.stockKey.getOrUndefined() !== `template:${options.kind ?? "application"}` ||
template.companyId.getOrUndefined() ||
template.values.data.kind !== "template"
) {
return Result.fail(new ResourceCatalogError("RESOURCE_GLOBAL_TEMPLATE_NOT_ALLOWED"));
}
if (!(options.existing || template.active)) {
return Result.fail(new ResourceCatalogError("TEMPLATE_UNAVAILABLE"));
}
const fields: ReturnType<ResourceSpecification["toPrimitive"]>["fields"] = [];
for (const binding of template.values.data.fields) {
const field = catalog.definitions.find((item) => item.id.toPrimitive() === binding.fieldId);
if (!field || field.companyId.getOrUndefined() || field.values.data.kind !== "field") {
return Result.fail(new ResourceCatalogError("RESOURCE_GLOBAL_TEMPLATE_NOT_ALLOWED"));
}
fields.push({
fieldId: field.id.toPrimitive(),
name: field.values.data.name,
type: field.values.data.type,
unit: field.values.data.unit,
choices: [...field.values.data.choices],
required: binding.required,
...(binding.sectionId ? { sectionId: binding.sectionId } : {}),
});
}
if (
options.kind === "os" &&
["provider", "os_family", "os_product_version", "os_edition_state", "software_edition"].some(
(key) => {
const field = catalog.definitions.find(
(item) => item.stockKey.getOrUndefined() === `field:${key}`
);
return !(field && fields.some((binding) => binding.fieldId === field.id.toPrimitive()));
}
)
) {
return Result.fail(new ResourceCatalogError("RESOURCE_GLOBAL_TEMPLATE_NOT_ALLOWED"));
}
return ResourceSpecification.create({
templateId: template.id.toPrimitive(),
templateName: template.values.data.name,
...(template.values.data.sections ? { sections: [...template.values.data.sections] } : {}),
fields,
});
}