@page "/admin/{TableDisplayName}" @layout HopFrameLayout @rendermode InteractiveServer @implements IDisposable @using HopFrame.Core.Config @using HopFrame.Core.Callbacks @using HopFrame.Core.Services @using HopFrame.Web.Models @using HopFrame.Web.Plugins @using HopFrame.Web.Plugins.Events @using Microsoft.JSInterop @using Microsoft.EntityFrameworkCore @if (!DisplaySelection) { @_config?.DisplayName }

@_config?.DisplayName

@if (!DisplaySelection && _buttonToggles.ShowRefreshButton) { Refresh } @foreach (var button in _pluginButtons.Where(pb => pb.IsForTable(_config)).Where(pb => pb.Position == PluginButtonPosition.TopLeft)) { @button.Title } @if (_hasCreatePolicy && DisplayActions && _buttonToggles.ShowAddEntityButton) { Add Entity } @foreach (var button in _pluginButtons.Where(pb => pb.IsForTable(_config)).Where(pb => pb.Position == PluginButtonPosition.TopRight)) { @button.Title }
@if (DisplaySelection) { } @foreach (var property in _config!.Properties.Where(prop => prop.List).OrderBy(prop => prop.Order)) { } @if (DisplayActions && (_hasDeletePolicy || _hasUpdatePolicy)) { @foreach (var button in _pluginButtons.Where(pb => pb.IsForTable(_config)).Where(pb => pb.Position == PluginButtonPosition.OnEntry)) { } @if (_hasUpdatePolicy && _buttonToggles.ShowEditButton) { } @if (_hasDeletePolicy && _buttonToggles.ShowDeleteButton) { } }
@if (_totalPages > 1) {
Page of @_totalPages
}
@inject IContextExplorer Explorer @inject NavigationManager Navigator @inject IJSRuntime Js @inject IDialogService Dialogs @inject IHopFrameAuthHandler Handler @inject ICallbackEmitter Emitter @inject IPluginOrchestrator PluginOrchestrator @code { [Parameter] public required string TableDisplayName { get; set; } [Parameter] public bool DisplaySelection { get; set; } [Parameter] public bool DisplayActions { get; set; } = true; [Parameter] public RelationPickerDialogData? DialogData { get; set; } [Parameter] public DataGridSelectMode SelectionMode { get; set; } = DataGridSelectMode.Single; [Parameter] public int PerPage { get; set; } = 20; private TableConfig? _config; private ITableManager? _manager; public object[] CurrentlyDisplayedModels = []; private int _currentPage; private int _totalPages; private string? _searchTerm; private bool _loading; private bool _hasUpdatePolicy; private bool _hasDeletePolicy; private bool _hasCreatePolicy; private bool _allSelected; private readonly CancellationTokenSource _tokenSource = new(); private List _pluginButtons = new(); private DefaultButtonToggles _buttonToggles = new(); protected override void OnInitialized() { _config ??= Explorer.GetTable(TableDisplayName); if (_config is null || (_config.Ignored && DialogData is null)) { Navigator.NavigateTo("/admin", true); } } protected override async Task OnInitializedAsync() { if (!await Handler.IsAuthenticatedAsync(_config?.ViewPolicy)) { Navigator.NavigateTo("/admin", true); return; } var eventResult = await PluginOrchestrator.DispatchEvent(new TableInitializedEvent(this) { Table = _config! }); if (eventResult.IsCanceled) return; _pluginButtons = eventResult.PluginButtons; _buttonToggles = eventResult.DefaultButtons; _hasUpdatePolicy = await Handler.IsAuthenticatedAsync(_config?.UpdatePolicy); _hasDeletePolicy = await Handler.IsAuthenticatedAsync(_config?.DeletePolicy); _hasCreatePolicy = await Handler.IsAuthenticatedAsync(_config?.CreatePolicy); _manager ??= Explorer.GetTableManager(_config!.PropertyName); CurrentlyDisplayedModels = await _manager!.LoadPage(_currentPage, PerPage).ToArrayAsync(); _totalPages = await _manager.TotalPages(PerPage); } protected override async Task OnAfterRenderAsync(bool firstRender) { try { await Js.InvokeVoidAsync("removeBg"); } catch (Exception) { // ignored } } public void Dispose() { _searchCancel.Dispose(); _tokenSource.Dispose(); } private CancellationTokenSource _searchCancel = new(); private async Task OnSearch(ChangeEventArgs eventArgs) { await _searchCancel.CancelAsync(); _searchTerm = eventArgs.Value?.ToString(); if (_searchTerm is null) return; _searchCancel = new(); await Task.Delay(500, _searchCancel.Token); var eventResult = await PluginOrchestrator.DispatchEvent(new SearchEvent(this) { SearchTerm = _searchTerm, Table = _config! }, _tokenSource.Token); if (eventResult.IsCanceled) return; _searchTerm = eventResult.SearchTerm; await Reload(); } private async Task Reload() { _loading = true; var eventResult = await PluginOrchestrator.DispatchEvent(new ReloadEvent(this) { Table = _config! }, _tokenSource.Token); if (eventResult.IsCanceled) { _loading = false; return; } if (!string.IsNullOrEmpty(_searchTerm)) { (var query, _totalPages) = await _manager!.Search(_searchTerm, 0, PerPage); CurrentlyDisplayedModels = query.ToArray(); } else { await OnInitializedAsync(); } _loading = false; } private async Task ChangePage(int page) { var eventResult = await PluginOrchestrator.DispatchEvent(new PageChangeEvent(this) { CurrentPage = _currentPage, NewPage = page, TotalPages = _totalPages, Table = _config! }, _tokenSource.Token); if (eventResult.IsCanceled) return; page = eventResult.NewPage; if (page < 0 || page > _totalPages - 1) return; _currentPage = page; await Reload(); } private async Task DeleteEntry(object element) { if (!await Handler.IsAuthenticatedAsync(_config?.DeletePolicy)) { Navigator.NavigateTo("/admin", true); return; } var eventResult = await PluginOrchestrator.DispatchEvent(new DeleteEntryEvent(this) { Entity = element, Table = _config! }, _tokenSource.Token); if (eventResult.IsCanceled) return; var dialog = await Dialogs.ShowConfirmationAsync("Do you really want to delete this entry?"); var result = await dialog.Result; if (result.Cancelled) return; await _manager!.DeleteItem(element); await Emitter.DispatchCallback(CallbackTypes.DeleteEntry(_config!), element); await Reload(); } private async Task CreateOrEdit(object? element) { if (!await Handler.IsAuthenticatedAsync(element is null ? _config?.CreatePolicy : _config?.UpdatePolicy)) { Navigator.NavigateTo("/admin", true); return; } HopFrameTablePageEventArgs eventArgs; if (element is null) { eventArgs = new CreateEntryEvent(this) { Table = _config! }; } else { eventArgs = new UpdateEntryEvent(this) { Table = _config!, Entity = element }; } var eventResult = await PluginOrchestrator.DispatchEvent(eventArgs, _tokenSource.Token); if (eventResult.IsCanceled) return; var panel = await Dialogs.ShowPanelAsync(new EditorDialogData(_config!, element), new DialogParameters { TrapFocus = false }); var result = await panel.Result; var data = result.Data as EditorDialogData; if (result.Cancelled) return; if (element is null) { await _manager!.AddItem(data!.CurrentObject!); await Emitter.DispatchCallback(CallbackTypes.CreateEntry(_config!), data.CurrentObject!); } else { await _manager!.EditItem(data!.CurrentObject!); await Emitter.DispatchCallback(CallbackTypes.UpdateEntry(_config!), data.CurrentObject!); } await Reload(); } private void SelectItem(object item, bool selected) { var eventResult = PluginOrchestrator.DispatchEvent(new SelectEntryEvent(this) { Entity = item, Selected = selected, Table = _config! }, _tokenSource.Token).Result; if (eventResult.IsCanceled) return; selected = eventResult.Selected; if (!selected) DialogData!.SelectedObjects.Remove(item); else DialogData!.SelectedObjects.Add(item); } private void SelectAll() { var selected = CurrentlyDisplayedModels.All(DialogData!.SelectedObjects.Contains); foreach (var displayedModel in CurrentlyDisplayedModels) { SelectItem(displayedModel, !selected); } _allSelected = selected; } private async Task DisplayProperty(PropertyConfig config, object entry) { var display = await _manager!.DisplayProperty(entry, config); if (display.Length > config.DisplayLength) display = display[..config.DisplayLength] + "..."; return display; } }