@page "/admin/sites" @using ScadaLink.Security @using ScadaLink.Commons.Entities.Sites @using ScadaLink.Commons.Interfaces.Repositories @using ScadaLink.Communication @using ScadaLink.DeploymentManager @attribute [Authorize(Policy = AuthorizationPolicies.RequireAdmin)] @inject ISiteRepository SiteRepository @inject ArtifactDeploymentService ArtifactDeploymentService @inject CommunicationService CommunicationService @inject AuthenticationStateProvider AuthStateProvider

Site Management

@if (_loading) { } else if (_errorMessage != null) {
@_errorMessage
} else { @if (_showForm) {
@(_editingSite == null ? "Add New Site" : "Edit Site")
@if (_formError != null) {
@_formError
}
} @if (_sites.Count == 0) { } @foreach (var site in _sites) { }
ID Name Identifier Description Node A Node B Data Connections Actions
No sites configured.
@site.Id @site.Name @site.SiteIdentifier @(site.Description ?? "—") @(site.NodeAAddress ?? "—") @(site.NodeBAddress ?? "—") @{ var conns = _siteConnections.GetValueOrDefault(site.Id); } @if (conns != null && conns.Count > 0) { @foreach (var conn in conns) { @conn.Name (@conn.Protocol) } } else { None }
}
@code { private async Task GetCurrentUserAsync() { var authState = await AuthStateProvider.GetAuthenticationStateAsync(); return authState.User.FindFirst("Username")?.Value ?? "unknown"; } private List _sites = new(); private Dictionary> _siteConnections = new(); private bool _loading = true; private string? _errorMessage; private bool _showForm; private Site? _editingSite; private string _formName = string.Empty; private string _formIdentifier = string.Empty; private string? _formDescription; private string? _formNodeAAddress; private string? _formNodeBAddress; private string? _formError; private bool _deploying; private ToastNotification _toast = default!; private ConfirmDialog _confirmDialog = default!; protected override async Task OnInitializedAsync() { await LoadDataAsync(); } private async Task LoadDataAsync() { _loading = true; _errorMessage = null; try { _sites = (await SiteRepository.GetAllSitesAsync()).ToList(); _siteConnections.Clear(); foreach (var site in _sites) { var connections = await SiteRepository.GetDataConnectionsBySiteIdAsync(site.Id); if (connections.Count > 0) { _siteConnections[site.Id] = connections.ToList(); } } } catch (Exception ex) { _errorMessage = $"Failed to load sites: {ex.Message}"; } _loading = false; } private void ShowAddForm() { _editingSite = null; _formName = string.Empty; _formIdentifier = string.Empty; _formDescription = null; _formNodeAAddress = null; _formNodeBAddress = null; _formError = null; _showForm = true; } private void EditSite(Site site) { _editingSite = site; _formName = site.Name; _formIdentifier = site.SiteIdentifier; _formDescription = site.Description; _formNodeAAddress = site.NodeAAddress; _formNodeBAddress = site.NodeBAddress; _formError = null; _showForm = true; } private void CancelForm() { _showForm = false; _editingSite = null; _formError = null; } private async Task SaveSite() { _formError = null; if (string.IsNullOrWhiteSpace(_formName)) { _formError = "Name is required."; return; } try { if (_editingSite != null) { _editingSite.Name = _formName.Trim(); _editingSite.Description = _formDescription?.Trim(); _editingSite.NodeAAddress = _formNodeAAddress?.Trim(); _editingSite.NodeBAddress = _formNodeBAddress?.Trim(); await SiteRepository.UpdateSiteAsync(_editingSite); } else { if (string.IsNullOrWhiteSpace(_formIdentifier)) { _formError = "Identifier is required."; return; } var site = new Site(_formName.Trim(), _formIdentifier.Trim()) { Description = _formDescription?.Trim(), NodeAAddress = _formNodeAAddress?.Trim(), NodeBAddress = _formNodeBAddress?.Trim() }; await SiteRepository.AddSiteAsync(site); } await SiteRepository.SaveChangesAsync(); CommunicationService.RefreshSiteAddresses(); _showForm = false; _editingSite = null; _toast.ShowSuccess(_editingSite == null ? "Site created." : "Site updated."); await LoadDataAsync(); } catch (Exception ex) { _formError = $"Save failed: {ex.Message}"; } } private async Task DeleteSite(Site site) { var confirmed = await _confirmDialog.ShowAsync( $"Delete site '{site.Name}' ({site.SiteIdentifier})? This cannot be undone.", "Delete Site"); if (!confirmed) return; try { await SiteRepository.DeleteSiteAsync(site.Id); await SiteRepository.SaveChangesAsync(); CommunicationService.RefreshSiteAddresses(); _toast.ShowSuccess($"Site '{site.Name}' deleted."); await LoadDataAsync(); } catch (Exception ex) { _toast.ShowError($"Delete failed: {ex.Message}"); } } private async Task DeployArtifacts(Site site) { _deploying = true; try { var command = await ArtifactDeploymentService.BuildDeployArtifactsCommandAsync(); var user = await GetCurrentUserAsync(); var result = await ArtifactDeploymentService.RetryForSiteAsync( site.SiteIdentifier, command, user); if (result.IsSuccess) _toast.ShowSuccess($"Artifacts deployed to '{site.Name}'."); else _toast.ShowError($"Deploy to '{site.Name}' failed: {result.Error}"); } catch (Exception ex) { _toast.ShowError($"Deploy to '{site.Name}' failed: {ex.Message}"); } finally { _deploying = false; } } private async Task DeployArtifactsToAllSites() { _deploying = true; try { var command = await ArtifactDeploymentService.BuildDeployArtifactsCommandAsync(); var user = await GetCurrentUserAsync(); var result = await ArtifactDeploymentService.DeployToAllSitesAsync(command, user); if (result.IsSuccess) { var summary = result.Value!; _toast.ShowSuccess( $"Artifacts deployed: {summary.SuccessCount} succeeded, {summary.FailureCount} failed."); } else { _toast.ShowError($"Artifact deployment failed: {result.Error}"); } } catch (Exception ex) { _toast.ShowError($"Artifact deployment failed: {ex.Message}"); } finally { _deploying = false; } } }