Passa al contenuto principale

Architettura

Cosa fa

TrainingHub è una piattaforma .NET 10 / Blazor Server multi-tenant per la gestione della formazione sulla sicurezza sul lavoro.

Componenti principali

  • TrainingHub.BackOffice — Blazor Server web app (UI principale)
  • TrainingHub.Database — progetto SQL Server (DACPAC deployment)
  • TrainingHub.Import — console app per import massivi da Excel
  • TrainingHub.Shared — shared project (models/costanti)

Framework 3SD

L'app usa l'ecosistema interno 3SD: Scarnas, Brighela, Oss, Servel, Ploc, Oster, Mulet, DeFa, KSet, Mola, Tabiot.

Pattern ricorrenti

View SQL → CRUD auto-generato (read-only)

Per esporre dati aggregati o derivati senza scrivere componenti UI custom si usa il pattern vista SQL + CRUD generato:

  1. Creare una vista in TrainingHub.Database/<schema>/Views/vw_<nome>.sql, esponendo le colonne con i loro identificatori *Id (no *Label: il generator costruisce le FK).
  2. Allineare il database (deploy DACPAC).
  3. MCP 3sd-generator (generator_run con defaultsCompiler) produce il model.conf.json e il dxgrid.conf.json partendo dalla view.
  4. Configurare a mano nel dxgrid.conf.json:
    • FK manuali sulle colonne *Id (la view non ha vincoli FK): FkSchema, FkTableName, FkClassName, eventuale CellLink + CellPolicy.
    • AllowInsert, AllowUpdate, AllowDelete, AllowClone = false.
    • IgnoreFormPopup = true + IgnoreForm = true (evita di generare popup/form per un'entità non scrivibile).
  5. Rigenerare: si ottiene un <Entity>.razor standard usabile come grid stand-alone o come step nei wizard.

Esempi attuali:

  • edu.vw_workerTrainingStatus — stato per-formazione di ogni lavoratore.
  • job.vw_workerComplianceSummary — rollup per-lavoratore (stato peggiore + conteggi). Usata come step "Conformità formativa" nel wizard azienda.

Persistenza markup custom in conf.json

Il generator rigenera .razor e .razor.tt.cs ad ogni run: ciò che viene scritto a mano nel .razor viene perso. I dxgrid.conf.json offrono diversi hook per persistere markup custom:

HookPosizione resaQuando usarlo
FormPopup.MarkupBeforeForm / MarkupAfterFormPrima/dopo <EditForm> nel popupWizard, banner contestuali
FormPopup.MarkupEndDopo </DxPopup>Popup secondari (anteprima, conferme)
Columns.{name}.RenderFragmentParameters.CellDisplayTemplateCella della gridBadge stato, link condizionali
Form.TabPages.Tabs.{tab}.Groups.{group}.Columns.{col}.TemplateSostituisce l'editor del campo nel formWrap con badge, override editor

Regola pratica: prima di scrivere markup custom direttamente nel .razor, verificare se esiste un hook in conf.json; se manca, va aggiunto al generator piuttosto che accettare la perdita su regen.

⚠️ Domande aperte / debito tecnico

  • (Da popolare durante la scrittura della doc dominio inv)