@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"));
}