AutoMate Technisch Help

OrgModel Portal UI

Concept

De OrgModel-pagina in de ManagementPortal (/usertypes/org-model) is het centrale beheerscherm voor gebruikersattributen. De pagina combineert drie verantwoordelijkheden:

  1. Attribuutbeheer — attributen toevoegen, hernoemen en verwijderen als conceptwijziging.

  2. Conceptbeheer — conceptwijzigingen reviewen, terugdraaien, publiceren of resetten.

  3. 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

Ja, door huidige gebruiker

Ja, door andere gebruiker

Nee

Geslaagd

Mislukt - race

Ja

Nee

Pagina openen

Is al vergrendeld?

Toon 'open in andere sessie'-banner\nAlle invoer uitgeschakeld

Toon naam van vergrendelende gebruiker\nAlle invoer uitgeschakeld\nSubscribe op ObjectReleased

TryAcquireLock

Pagina is bewerkbaar\nLaad attribuutdata

Pagina geladen

Pagina sluiten / navigeren

Hield huidige gebruiker de lock?

ReleaseLock → SignalR stuurt ObjectReleased naar andere sessies

Uitschrijven van ObjectReleased

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():

var displayName = info.UserTenantId.HasValue && info.UserTenantId != applicationUser.UserTenantId ? $"{info.DisplayName} ({applicationUser.Tenants.GetValueOrDefault(info.UserTenantId.Value, info.UserTenantId.Value.ToString())})" : info.DisplayName;

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

userId

Unieke gebruikers-ID (object-ID uit het identiteitssysteem).

displayName

Weergavenaam voor tonen in de UI-banner.

userTenantId

Tenant waartoe de vergrendelende gebruiker behoort.

connectionId

SignalR-verbindings-ID voor automatisch vrijgeven bij disconnect.

De LockHub biedt de volgende methoden aan portals:

Hub-methode

Beschrijving

AcquireLockAsync

Probeert de lock te verkrijgen. Retourneert true bij succes.

ReleaseLockAsync

Geeft de lock vrij en stuurt ObjectReleased naar andere clients.

IsLockedAsync

Controleert of een object vergrendeld is.

IsLockedByCurrentUserAsync

Controleert of de huidige gebruiker de lock houdt.

GetLockingUserAsync

Geeft het userId van de vergrendelaar terug.

GetLockingUserInfoAsync

Geeft LockUserInfo (displayName + userTenantId) terug.

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 Rename-wijzigingen.

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

Last modified: 23 March 2026