OrgModel Portal UI
Concept
De OrgModel-pagina in de ManagementPortal (/usertypes/org-model) is het centrale beheerscherm voor gebruikersattributen. De pagina combineert drie verantwoordelijkheden:
Attribuutbeheer — attributen toevoegen, hernoemen en verwijderen als conceptwijziging.
Conceptbeheer — conceptwijzigingen reviewen, terugdraaien, publiceren of resetten.
Versiegeschiedenis — eerder gepubliceerde versies inzien.
Alle schrijfacties zijn uitgeschakeld wanneer een andere gebruiker de pagina vergrendeld heeft. De vergrendeling verloopt via een SignalR-hub en is daarmee zichtbaar in realtime voor alle geopende sessies.
Paginabeheer — levenscyclus bij openen en sluiten
Bij het laden (OnInitializedAsync) vraagt de component een lock op via IUsageService.TryAcquireLock("org-model"). De IUsageService communiceert hiervoor via een SignalR-verbinding met de LockHub op de API.
Bij het sluiten (Dispose) wordt de lock vrijgegeven via ReleaseLock. De LockHub stuurt vervolgens een ObjectReleased-event naar alle andere verbonden clients.
Paginavergrendeling — weergave
Scenario 1: vergrendeld door de huidige gebruiker (andere sessie)
Tekst in de banner:
Dit treedt op wanneer IsLockedByCurrentUser("org-model") bij het laden true retourneert.
Scenario 2: vergrendeld door een andere gebruiker
Tekst in de banner (wanneer naam beschikbaar is):
Wanneer de vergrendelende gebruiker tot een andere tenant behoort, wordt de tenantnaam tussen haakjes toegevoegd aan de weergavenaam:
De logica daarvoor zit in OrgModelPage.FormatLockedByOtherUser():
Als de naam niet beschikbaar is (bijv. wanneer de GetLockInfo-aanroep mislukt), valt de banner terug op de generieke tekst:
Melding bij vrijgeven lock — popup-dialoog
Wanneer de wachtende sessie een ObjectReleased-event ontvangt en vervolgens de lock succesvol overneemt (TryAcquireLock slaagt), verschijnt een pop-upvenster via DialogService.Alert:
Titel: Pagina beschikbaar
Tekst: De pagina is nu beschikbaar voor bewerking.
De gebruiker bevestigt de melding door op de knop te klikken, waarna de pagina direct bewerkbaar is. Het gaat hier uitdrukkelijk om een DialogService.Alert-venster en niet om een toast-melding.
Wanneer TryAcquireLock mislukt nadat ObjectReleased is ontvangen (race condition: een derde sessie was sneller), wordt de bannertekst bijgewerkt met de naam van de nieuwe vergrendelaar en blijft bewerken uitgeschakeld.
Technische architectuur — SignalR lock-coördinatie
API-zijde: LockCoordinator en LockHub
De API houdt in-memory bij welke gebruiker een object vergrendeld heeft via LockCoordinator. Per tenant en per object-ID wordt opgeslagen:
Gegeven | Beschrijving |
|---|---|
| Unieke gebruikers-ID (object-ID uit het identiteitssysteem). |
| Weergavenaam voor tonen in de UI-banner. |
| Tenant waartoe de vergrendelende gebruiker behoort. |
| SignalR-verbindings-ID voor automatisch vrijgeven bij disconnect. |
De LockHub biedt de volgende methoden aan portals:
Hub-methode | Beschrijving |
|---|---|
| Probeert de lock te verkrijgen. Retourneert |
| Geeft de lock vrij en stuurt |
| Controleert of een object vergrendeld is. |
| Controleert of de huidige gebruiker de lock houdt. |
| Geeft het userId van de vergrendelaar terug. |
| Geeft |
Bij een verbroken verbinding (OnDisconnectedAsync) geeft de hub automatisch alle locks van die verbinding vrij en stuurt voor elk vrijgegeven object een ObjectReleased-event.
Portal-zijde: UsageService
IUsageService is de portal-abstractie over de SignalR-verbinding. De implementatie (UsageService) bouwt lazy een HubConnection op naar /hubs/locks en roept de bovenstaande hub-methoden aan. Wanneer de verbinding mislukt, degradeert de service graceful (geen lock verkregen, geen foutmelding naar de gebruiker).
De service luistert op het ObjectReleased-event van de hub en roept de ObjectReleased-event-handler aan in de portal. OrgModelPage schrijft zich in op dit event om de lock-status bij te werken.
Attribuutbeheer
Attribuut toevoegen
Klik op Attribuut toevoegen opent een dialoogvenster (OrgModelCreateAttributeDialog) met:
Een verplicht attribuuttype (dropdown, geladen uit
IAttributeTypeState).Een verplichte attribuutnaam (tekstinvoer).
Na bevestiging wordt het attribuut via IOrgModelState.CreateAttributeAsync aangemaakt als conceptwijziging (ChangeType = Add). Het attribuut is pas actief na publicatie.
Attribuut hernoemen
Klik op het potlood-icoon bij een attribuut opent OrgModelEditAttributeDialog met:
De huidige live naam (alleen-lezen ter referentie).
Een invoerveld voor de nieuwe conceptnaam.
Na bevestiging wordt de wijziging opgeslagen via IOrgModelState.UpdateAttributeAsync als een Rename-changerecord.
Attribuut verwijderen (staged deletion)
Klik op het prullenbak-icoon toont een bevestigingsdialoog. Na bevestiging wordt het attribuut niet direct verwijderd maar als conceptwijziging gemarkeerd (ChangeType = Remove). In de attribuutlijst verschijnt het attribuut vervolgens met de badge Gepland voor verwijdering. De verwijdering wordt pas doorgevoerd bij publicatie.
Conceptbeheer
Overzicht geplande wijzigingen
De sectie Geplande wijzigingen toont alle openstaande changerecords als tabel met:
Kolom | Beschrijving |
|---|---|
Attribuutnaam | Naam van het betrokken attribuut. |
Type | Attribuuttype. |
Wijzigingstype | Badge: Toevoegen (groen), Hernoemen (blauw), Verwijderen (rood). |
Nieuwe naam | Gevuld bij |
Actie | Knop om de individuele wijziging terug te draaien. |
Individuele wijziging terugdraaien
Klik op Wijziging terugdraaien naast een changerecord toont een bevestigingsdialoog. Na bevestiging wordt het specifieke changerecord verwijderd via IOrgModelState.RevertDraftChangeAsync. De overige changerecords blijven intact.
Concept publiceren (activeren)
Klik op Publiceren toont een bevestigingsdialoog met het aantal geplande wijzigingen. Na bevestiging activeert IOrgModelState.ActivateDraftAsync het concept. De API voert voor activatie altijd opnieuw een impact-evaluatie uit (zie OrgModel-Versioning.md). Bij blokkerende impactproblemen mislukt de activatie met HTTP 422.
Concept resetten
Klik op Concept resetten toont een bevestigingsdialoog. Na bevestiging verwijdert IOrgModelState.DeleteDraftAsync alle openstaande changerecords. Attributen die uitsluitend als Add-changerecord bestaan (nooit actief geweest) worden soft-deleted.
Versiegeschiedenis
Klik op Versiegeschiedenis opent een dialoogvenster (OrgModelVersionHistoryDialog) met alle eerder gepubliceerde versies. Per versie worden getoond:
Het versienummer.
De publicatiedatum (
ActivatedAt).De gebruiker die publiceerde (
ActivatedBy).De changerecords van die versie (attribuutnaam, type, wijzigingstype, nieuwe naam bij hernoemen).
De versiegeschiedenis wordt geladen via IOrgModelState.LoadChangelogAsync bij elke paginalading.
Gerelateerde pagina's
OrgModel-Versioning.md — Versielifecycle, impact-evaluatie en activatielogica (API/domein).
OrgModel-Draft-Resolutions.md — Resolutieflow voor blokkerende impactproblemen.