@page "/user/saved-queries" @page "/user/saved-queries/{DatabaseStr}" @page "/user/saved-queries/{DatabaseStr}/{DatabaseInstanceStr}" @attribute [Authorize] @inject NavigationManager NavigationManager @inject IUserSession UserSession @inject IJSRuntime JsRuntime @* * dbMango * * Copyright 2025 Deutsche Bank AG * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *@

Saved queries

@code { [CascadingParameter] public IModalService Modal { get; set; } = null!; [Parameter] public string? DatabaseStr { get; set; } [Parameter] public string? DatabaseInstanceStr { get; set; } private readonly List> _rootNodes = []; private Navigation _navigation = null!; private Dictionary _groupedCollections = new(); private bool IsRefreshEnabled => SelectedPivotNode != null && SelectedPivotNode.Data != null; private bool IsExportEnabled { get; set; } = true; private DateTime LastRefresh { get; set; } private TimeSpan LastRefreshElapsed { get; set; } private PivotTableComponent PivotTable { get; set; } = null!; private bool UseCache { get; set; } = true; private IPivotedData? PivotData { get; set; } private PivotDefinition? CurrentPivot { get; set; } private int Rows { get; set; } = 35; private string Database { get => UserSession.Database; set { if (UserSession.Database == value) return; UserSession.Database = value; SyncUrl(); } } public TreeNode? SelectedPivotNode { get; set { if (field == value) return; field = value; //if (field?.Data != null) //{ // // If a pivot is selected, navigate to the pivot page // var url = NavigationManager.BaseUri + $"user/pivot/{Database}/{field.Data.Collection}/{field.Data.Name}/{UserSession.Department}"; // JsRuntime.InvokeAsync("DashboardUtils.ChangeUrl", url); //} //else //{ // // If no pivot is selected, just update the state // StateHasChanged(); //} } } // Extracts the name of the direct descendant of the root parent (Base) private TreeNode? BaseNode { get { var node = SelectedPivotNode; if (node == null) return null; // Traverse up to the root while (node.Parent != null && node.Parent.Parent != null) { node = node.Parent; } // node is now the direct child of root (i.e., Base) return node.Parent != null ? node : null; } } private string? Base => BaseNode?.Label.Split(":").FirstOrDefault(); private string? Collection => BaseNode?.Label.Split(":").LastOrDefault(); private List _collections = []; // Concatenation of names of nodes between Collection and SelectedPivotNode, excluding both private string Path { get { // Now, walk from SelectedPivotNode up to Collection, excluding both var names = new List(); var temp = SelectedPivotNode; var baseNode = BaseNode; while (temp != null && temp != baseNode) { if (temp != SelectedPivotNode) // Exclude SelectedPivotNode itself names.Insert(0, temp.Label); temp = temp.Parent; } return string.Join("/", names); } } private GroupedCollection? SelectedCollectionNode { get { if (SelectedPivotNode == null || BaseNode == null) return null; // Find the grouped collection that matches the current collection name _groupedCollections.TryGetValue(BaseNode.Label, out var groupedCollection); return groupedCollection; } } protected override async Task OnAfterRenderAsync(bool firstRender) { if (!firstRender) return; _navigation = new(PivotTable.Navigate); if (string.IsNullOrWhiteSpace(DatabaseStr)) DatabaseStr = UserSession.Database; else UserSession.Database = DatabaseStr; if (string.IsNullOrWhiteSpace(DatabaseInstanceStr)) DatabaseInstanceStr = UserSession.DatabaseInstance; else UserSession.DatabaseInstance = DatabaseInstanceStr; var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10)); var ds = UserSession.PivotDataSource; _collections = await ds.GetAllMeta(token: cts.Token); if (_collections.Count == 0) { await ModalDialogUtils.ShowInfoDialog(Modal, "Problem", "No collections found that have corresponding -Meta collections."); return; } _groupedCollections = _collections .Where(x => !x.IsGroup) .ToDictionary(x => x.CollectionNameWithPrefix, x => x); var root = new TreeNode() { Label = "Saved queries", Data = null, Parent = null, IsExpanded = true }; PopulateRootNodes(ds, root, _collections, cts.Token); _rootNodes.Add(root); SyncUrl(); StateHasChanged(); } private static void PopulateRootNodes(IPivotTableDataSource ds, TreeNode root, List collections, CancellationToken token) { // Clear any existing children root.Children.Clear(); foreach (var collection in collections.Where( x => !x.IsGroup)) { // Each collection becomes a child node under the root var node = new TreeNode { Label = collection.CollectionNameWithoutPrefix, Data = null, Parent = root, IsExpanded = false }; root.Children.Add(node); // Group pivots by GroupName (null or empty group names go under "Ungrouped") var groupedPivots = collection.Pivots .Where(x => !x.IsGroup) .GroupBy(p => string.IsNullOrWhiteSpace(p.Pivot.Group) ? "Ungrouped" : p.Pivot.Group) .OrderBy(g => g.Key); foreach (var group in groupedPivots) { // Create a group node under the collection node var groupNode = new TreeNode { Label = group.Key, Data = null, Parent = root.Children.Last(), // The collection node just added IsExpanded = false }; root.Children.Last().Children.Add(groupNode); // Add all pivots in this group as children of the group node foreach (var pivot in group.OrderBy(x => x.Pivot.Name)) { var childNode = new TreeNode { Label = pivot.Pivot.Name, Data = pivot, Parent = groupNode, IsExpanded = false }; groupNode.Children.Add(childNode); } } } } private async Task HandleNodeChanged(TreeNode node) { if (node.Data == null) { // If the node has no data, it means it's a collection or group node, so we don't do anything return; } node.Data.Pivot.Name = node.Label; // Update the pivot name to match the node label await InvokeAsync(StateHasChanged); // Refresh the UI } private void SyncUrl() { var url = NavigationManager.BaseUri + $"user/saved-queries/{Database}"; if (!string.IsNullOrWhiteSpace(UserSession.DatabaseInstance)) url += $"/{UserSession.DatabaseInstance}"; JsRuntime.InvokeAsync("DashboardUtils.ChangeUrl", url); } private readonly FilterExpressionTree.ExpressionGroup _noFilter = new (); private FilterExpressionTree.ExpressionGroup GetExtraFilter() => _noFilter; private Task OnRefreshPivot() => PivotTable.RunPivot(); private Task OnCopyCsv() => PivotTable.CopyCsv(); private Task OnExportCsv() => Task.CompletedTask; //PivotTable.ExportCsv(Uri.EscapeDataString($"{CobStr}-{Department}-{Pivot?.Pivot.Name}.csv")); }