@namespace OpenArchival.Blazor.AdminPages @using Microsoft.AspNetCore.Components.Web @using MudBlazor @using MudExtensions @using OpenArchival.Blazor.ArchiveSearch @using OpenArchival.DataAccess @using OpenArchival.Blazor.AdminPages.Shared; @using OpenArchival.Blazor.AdminPages; @using OpenArchival.Blazor; Delete Edit @inject IArtifactGroupingProvider GroupingProvider; @inject IDialogService DialogService; @inject IArtifactGroupingProvider GroupingProvider; @inject ArtifactEntrySharedHelpers Helpers; @inject ArtifactGroupingSearch SearchProvider; @code { public class ArtifactGroupingRowElementComparer : IEqualityComparer { public bool Equals(ArtifactGroupingRowElement? x, ArtifactGroupingRowElement? y) { if (ReferenceEquals(x, y)) return true; if (x is null || y is null) return false; return x.Id == y.Id; } public int GetHashCode(ArtifactGroupingRowElement obj) { return obj.Id.GetHashCode(); } } public List ArtifactGroupingRows { get; set; } = new(); public MudDataGrid DataGrid { get; set; } = default!; private ArtifactGroupingRowElementComparer _comparer = new(); private string _searchString { get; set; } = ""; private ArchiveSearchBar _searchBar { get; set; } = default!; private HashSet _selectedGroupings { get; set; } = []; protected override async Task OnInitializedAsync() { // Load inital data List groupings = await GroupingProvider.GetGroupingsPaged(1, 25); SetGroupingRows(groupings); await base.OnInitializedAsync(); StateHasChanged(); } private void SetGroupingRows(IEnumerable groupings) { ArtifactGroupingRows.Clear(); foreach (var grouping in groupings) { ArtifactGroupingRows.Add(new ArtifactGroupingRowElement() { ArtifactGroupingIdentifier=grouping.ArtifactGroupingIdentifier ?? throw new ArgumentNullException(nameof(grouping), "Got a null grouping identifier"), CategoryName=grouping.Category.Name, Title=grouping.Title, IsPublicallyVisible=grouping.IsPublicallyVisible, Id=grouping.Id } ); } } private async Task OnRowEditClick(ArtifactGroupingRowElement row) { var parameters = new DialogParameters(); var model = await GroupingProvider.GetGroupingAsync(row.Id); parameters.Add("Model", ArtifactGroupingValidationModel.ToValidationModel(model)); var options = new DialogOptions() { MaxWidth = MaxWidth.ExtraExtraLarge, FullWidth = true }; var dialog = await DialogService.ShowAsync("Edit Grouping", parameters, options); var result = await dialog.Result; if (result is not null && !result.Canceled) { var validationModel = (ArtifactGroupingValidationModel)result.Data!; await Helpers.OnGroupingPublished(validationModel); await DataGrid.ReloadServerData(); } } private async Task OnDeleteClicked(MouseEventArgs args) { HashSet selected = DataGrid.SelectedItems; bool? confirmed = await DialogService.ShowMessageBox ( new MessageBoxOptions(){ Message=$"Are you sure you want to delete {selected.Count} groupings?", Title="Delete Groupings", CancelText="Cancel", YesText="Delete" }); if (confirmed is not null && (confirmed ?? throw new ArgumentNullException("confirmed was null"))) { foreach (var grouping in selected) { await GroupingProvider.DeleteGroupingAsync(grouping.Id); } } await DataGrid.ReloadServerData(); StateHasChanged(); } private async Task> ServerReload(GridState state) { int totalItems = await GroupingProvider.GetTotalCount(); SearchProvider.PageSize = state.PageSize; IEnumerable groupings; if (string.IsNullOrEmpty(_searchString)) { groupings = await GroupingProvider.GetGroupingsPaged(state.Page + 1, state.PageSize); totalItems = await GroupingProvider.GetTotalCount(); } else { await SearchProvider.Search(_searchString, _searchBar.SelectedFilter, state.Page + 1); groupings = SearchProvider.SearchResults; } var pagedItems = groupings.Select(grouping => new ArtifactGroupingRowElement() { Id = grouping.Id, Title = grouping.Title, ArtifactGroupingIdentifier = grouping.ArtifactGroupingIdentifier ?? throw new ArgumentNullException(nameof(grouping), "Got a null ArtifactGroupingIdentifier"), CategoryName = grouping.Category.Name, IsPublicallyVisible = grouping.IsPublicallyVisible, }); StateHasChanged(); return new GridData() { TotalItems = totalItems, Items = pagedItems }; } private async Task OnSearchTermsChanged(string args) { _searchString = args; await DataGrid.ReloadServerData(); } public async Task> SelectedItems() { List selectedGroupings = []; foreach (ArtifactGroupingRowElement row in DataGrid.SelectedItems) { selectedGroupings.Add(await GroupingProvider.GetGroupingAsync(row.Id)); } return selectedGroupings; } public void ClearSelected() { // OLD: _selectedGroupings = new HashSet(); // NEW: Initialize with the comparer _selectedGroupings = new HashSet(_comparer); } // 6. ADD THIS NEW PUBLIC METHOD public Task SetSelectedItemsAsync(IEnumerable groupingsToSelect) { // Convert from the full ArtifactGrouping entity to the RowElement. // We only *really* need the Id for the comparer, but populating // the other fields is good practice. var rowElementsToSelect = groupingsToSelect.Select(grouping => new ArtifactGroupingRowElement { Id = grouping.Id, Title = grouping.Title, ArtifactGroupingIdentifier = grouping.ArtifactGroupingIdentifier ?? string.Empty, CategoryName = grouping.Category?.Name ?? string.Empty, IsPublicallyVisible = grouping.IsPublicallyVisible }); // Create a new HashSet from the list, using the comparer. // Assigning this to the bound variable will update the grid's UI. _selectedGroupings = new HashSet(rowElementsToSelect, _comparer); StateHasChanged(); return Task.CompletedTask; } }