using Insight.Infrastructure; using Insight.Infrastructure.Entities; using Insight.Web.Components.Containers; using Insight.Web.Constants; using Microsoft.AspNetCore.Components; using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; using MongoDB.Driver; using MudBlazor; using System.Text.RegularExpressions; using SortDirection = MudBlazor.SortDirection; namespace Insight.Web.Pages.Management.Agents; [Route(Navigation.Management.Agents.Index)] public partial class Index { [Inject] private IMongoDatabase Database { get; init; } = default!; [Inject] private ISnackbar Snackbar { get; init; } = default!; private TableContainer? Container { get; set; } private string Title { get; set; } = Global.Name; private List Breadcrumbs { get; } = new(); private string? Search { get; set; } private ViewModel? Model { get; set; } protected override void OnInitialized() { Title = "Agents|Insight"; Breadcrumbs.Add(new BreadcrumbItem("Home", href: Navigation.Home)); Breadcrumbs.Add(new BreadcrumbItem("Agents", href: Navigation.Management.Agents.Index, true)); } private async Task> LoadDataAsync(TableState state) { try { var filter = Builders.Filter.Empty; if (FilterUnassignedHost) { filter &= Builders.Filter.Size("hosts", 0); } var search = Builders.Filter.Empty; if (string.IsNullOrWhiteSpace(Search) is false) { var regex = new BsonRegularExpression(new Regex(Search, RegexOptions.IgnoreCase)); search &= Builders.Filter.Regex("serial", regex) | Builders.Filter.Regex("hostname", regex) | Builders.Filter.Regex("version", regex); } var query = Database.Agent() .Aggregate() .AppendStage(new BsonDocument("$lookup", new BsonDocument { { "from", "host" }, { "localField", "_id" }, { "foreignField", "_agent" }, { "as", "hosts" } })) .AppendStage(new BsonDocument("$addFields", new BsonDocument("host", new BsonDocument("$first", "$hosts")))) .Match(filter) .Match(search) .AppendStage(new BsonDocument("$addFields", new BsonDocument("online_diff", new BsonDocument("$subtract", new BsonArray { DateTime.Now, "$activity" })) )) .AppendStage(new BsonDocument("$addFields", new BsonDocument("online", new BsonDocument("$and", new BsonArray { new BsonDocument("$cond", new BsonArray { new BsonDocument("$isNumber", new BsonArray { "$online_diff" }), 1, 0 }), new BsonDocument("$lt", new BsonArray { "$online_diff", 60000 }) })))) .Sort(state.SortDirection switch { SortDirection.Ascending => state.SortLabel switch { "Serial" => Builders.Sort.Ascending("serial"), "Hostname" => Builders.Sort.Ascending("hostname"), "Version" => Builders.Sort.Ascending("version"), "Assigned" => Builders.Sort.Ascending("hosts"), "Online" => Builders.Sort.Ascending("online"), _ => null }, SortDirection.Descending => state.SortLabel switch { "Serial" => Builders.Sort.Descending("serial"), "Hostname" => Builders.Sort.Descending("hostname"), "Version" => Builders.Sort.Descending("version"), "Assigned" => Builders.Sort.Descending("hosts"), "Online" => Builders.Sort.Descending("online"), _ => null }, _ => Builders.Sort.Ascending("serial") }); var result = await Database.Agent().GetPagedAsync(query, state.Page * state.PageSize, state.PageSize); return new TableData() { TotalItems = (int)result.Meta.Total, Items = result.Data }; } catch (Exception) { Notification.Error(Snackbar); return new TableData(); } } private async Task OnRefreshAsync() { if (Container is null) return; await Container.RefreshAsync().ConfigureAwait(false); } private void OnDelete(ViewModel model) { Model = new ViewModel { Id = model.Id, Serial = model?.Serial }; _deleteDialog?.Toggle(); } private bool _filter; private bool Filter { get { return _filter; } set { if (value != _filter) { _filter = value; StateHasChanged(); } } } private bool Filtered => FilterUnassignedHost; private void OnFilterReset() { FilterUnassignedHost = false; } private bool _filterUnassignedHost; public bool FilterUnassignedHost { get { return _filterUnassignedHost; } set { if (value != _filterUnassignedHost) { _filterUnassignedHost = value; if (Container is not null) { _ = Container.RefreshAsync(); } if (value) { Notification.Warning(Snackbar, "Filtered"); } } } } } [BsonIgnoreExtraElements] public class ViewModel { [BsonId, BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } [BsonElement("serial")] public string? Serial { get; set; } [BsonElement("hostname")] public string? Hostname { get; set; } [BsonElement("version"), BsonRepresentation(BsonType.String)] public Version? Version { get; set; } [BsonElement("host")] public HostEntity? Host { get; set; } [BsonElement("hosts")] public List? Hosts { get; set; } [BsonElement("online")] public bool Online { get; set; } }