optimization update, web scheduler test-integration
This commit is contained in:
parent
3c9ccaafeb
commit
1591618c2c
103 changed files with 4826 additions and 1502 deletions
|
|
@ -6,7 +6,7 @@
|
||||||
<RootNamespace>Insight.Agent</RootNamespace>
|
<RootNamespace>Insight.Agent</RootNamespace>
|
||||||
<Product>Insight</Product>
|
<Product>Insight</Product>
|
||||||
<AssemblyName>agent</AssemblyName>
|
<AssemblyName>agent</AssemblyName>
|
||||||
<AssemblyVersion>2023.11.17.0</AssemblyVersion>
|
<AssemblyVersion>2023.12.14.0</AssemblyVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
@ -23,10 +23,10 @@
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="7.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.3.10" />
|
||||||
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
|
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
|
||||||
<PackageReference Include="System.Management" Version="7.0.2" />
|
<PackageReference Include="System.Management" Version="7.0.2" />
|
||||||
<PackageReference Include="System.ServiceProcess.ServiceController" Version="7.0.1" />
|
<PackageReference Include="System.ServiceProcess.ServiceController" Version="7.0.1" />
|
||||||
<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.3.9" />
|
|
||||||
<PackageReference Include="Vaitr.Snmp" Version="2023.3.3" />
|
<PackageReference Include="Vaitr.Snmp" Version="2023.3.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<Product>Insight</Product>
|
<Product>Insight</Product>
|
||||||
<AssemblyName>api</AssemblyName>
|
<AssemblyName>api</AssemblyName>
|
||||||
<AssemblyVersion>2023.11.17.0</AssemblyVersion>
|
<AssemblyVersion>2023.12.14.0</AssemblyVersion>
|
||||||
<RootNamespace>Insight.Api</RootNamespace>
|
<RootNamespace>Insight.Api</RootNamespace>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,12 @@
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<RootNamespace>Insight.Domain</RootNamespace>
|
<RootNamespace>Insight.Domain</RootNamespace>
|
||||||
<Product>Insight</Product>
|
<Product>Insight</Product>
|
||||||
<AssemblyVersion>2023.11.17.0</AssemblyVersion>
|
<AssemblyVersion>2023.12.14.0</AssemblyVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Vaitr.Network" Version="2023.10.22" />
|
<PackageReference Include="Vaitr.Bus" Version="2023.12.13" />
|
||||||
|
<PackageReference Include="Vaitr.Network" Version="2023.12.14" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
|
|
||||||
43
src/Core/Insight.Infrastructure/Entities/Scheduler/Job.cs
Normal file
43
src/Core/Insight.Infrastructure/Entities/Scheduler/Job.cs
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Vaitr.Scheduler;
|
||||||
|
|
||||||
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
public static partial class MongoDatabaseExtensions
|
||||||
|
{
|
||||||
|
public static IMongoCollection<JobEntity> Job(this IMongoDatabase database) => database.GetCollection<JobEntity>("job");
|
||||||
|
}
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class JobEntity
|
||||||
|
{
|
||||||
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
|
public string? Id { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("insert")]
|
||||||
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("update")]
|
||||||
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("name")]
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("description")]
|
||||||
|
public string? Description { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("state"), BsonRepresentation(BsonType.String)]
|
||||||
|
public TaskState State { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("timeout")]
|
||||||
|
public TimeSpan Timeout { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("executed")]
|
||||||
|
public DateTime Executed { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("disabled")]
|
||||||
|
public bool Disabled { get; set; }
|
||||||
|
}
|
||||||
38
src/Core/Insight.Infrastructure/Entities/Scheduler/JobLog.cs
Normal file
38
src/Core/Insight.Infrastructure/Entities/Scheduler/JobLog.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Vaitr.Scheduler;
|
||||||
|
using static Insight.Infrastructure.Entities.TriggerEntity;
|
||||||
|
|
||||||
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
public static partial class MongoDatabaseExtensions
|
||||||
|
{
|
||||||
|
public static IMongoCollection<AgentLogEntity> JobLog(this IMongoDatabase database) => database.GetCollection<AgentLogEntity>("job_log");
|
||||||
|
}
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class JobLogEntity
|
||||||
|
{
|
||||||
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
|
public string? Id { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("_job"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("job")]
|
||||||
|
public string? Job { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("insert")]
|
||||||
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("timestamp")]
|
||||||
|
public DateTime? Timestamp { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("status"), BsonRepresentation(BsonType.String)]
|
||||||
|
public TaskState? Status { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("mode"), BsonRepresentation(BsonType.String)]
|
||||||
|
public ScheduleMode? Mode { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("message")]
|
||||||
|
public string? Message { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
public static partial class MongoDatabaseExtensions
|
||||||
|
{
|
||||||
|
public static IMongoCollection<JobTaskEntity> JobTask(this IMongoDatabase database) => database.GetCollection<JobTaskEntity>("job_task");
|
||||||
|
}
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class JobTaskEntity
|
||||||
|
{
|
||||||
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
|
public string? Id { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("_job"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("job")]
|
||||||
|
public string? Job { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("_task"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("task")]
|
||||||
|
public string? Task { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("insert")]
|
||||||
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("update")]
|
||||||
|
public DateTime? Update { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
public static partial class MongoDatabaseExtensions
|
||||||
|
{
|
||||||
|
public static IMongoCollection<JobTriggerEntity> JobTrigger(this IMongoDatabase database) => database.GetCollection<JobTriggerEntity>("job_trigger");
|
||||||
|
}
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class JobTriggerEntity
|
||||||
|
{
|
||||||
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
|
public string? Id { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("_job"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("job")]
|
||||||
|
public string? Job { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("_trigger"), BsonRepresentation(BsonType.ObjectId), JsonPropertyName("trigger")]
|
||||||
|
public string? Trigger { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("insert")]
|
||||||
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("update")]
|
||||||
|
public DateTime? Update { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
public static partial class MongoDatabaseExtensions
|
||||||
|
{
|
||||||
|
public static IMongoCollection<TaskEntity> Task(this IMongoDatabase database) => database.GetCollection<TaskEntity>("task");
|
||||||
|
}
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
public class TaskEntity
|
||||||
|
{
|
||||||
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
|
public string? Id { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("insert")]
|
||||||
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("update")]
|
||||||
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("name")]
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("description")]
|
||||||
|
public string? Description { get; set; }
|
||||||
|
|
||||||
|
[BsonIgnore]
|
||||||
|
public Func<CancellationToken, Task>? Action { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
public static partial class MongoDatabaseExtensions
|
||||||
|
{
|
||||||
|
public static IMongoCollection<TriggerEntity> Trigger(this IMongoDatabase database) => database.GetCollection<TriggerEntity>("trigger");
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TriggerEntity
|
||||||
|
{
|
||||||
|
[BsonId, BsonRepresentation(BsonType.ObjectId), JsonPropertyName("id")]
|
||||||
|
public string? Id { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("insert")]
|
||||||
|
public DateTime? Insert { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("update")]
|
||||||
|
public DateTime? Update { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("name")]
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("description")]
|
||||||
|
public string? Description { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("mode")]
|
||||||
|
public ScheduleMode Mode { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("date_start")]
|
||||||
|
public DateTime StartTime { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("date_end")]
|
||||||
|
public DateTime? EndTime { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("interval")]
|
||||||
|
public TimeSpan? Interval { get; set; }
|
||||||
|
|
||||||
|
public enum ScheduleMode
|
||||||
|
{
|
||||||
|
Single, Loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<RootNamespace>Insight.Infrastructure</RootNamespace>
|
<RootNamespace>Insight.Infrastructure</RootNamespace>
|
||||||
<Product>Insight</Product>
|
<Product>Insight</Product>
|
||||||
<AssemblyVersion>2023.11.17.0</AssemblyVersion>
|
<AssemblyVersion>2023.12.14.0</AssemblyVersion>
|
||||||
<ImplicitUsings>true</ImplicitUsings>
|
<ImplicitUsings>true</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
@ -19,9 +19,10 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.13" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.13" />
|
||||||
<PackageReference Include="MongoDB.Driver" Version="2.22.0" />
|
<PackageReference Include="MongoDB.Driver" Version="2.23.0" />
|
||||||
<PackageReference Include="AspNetCore.Identity.MongoDbCore" Version="3.1.2" />
|
<PackageReference Include="AspNetCore.Identity.MongoDbCore" Version="3.1.2" />
|
||||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.0.3" />
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.0.3" />
|
||||||
|
<PackageReference Include="Vaitr.Scheduler" Version="2023.12.6" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<RootNamespace>Insight.Remote.Shared</RootNamespace>
|
<RootNamespace>Insight.Remote.Shared</RootNamespace>
|
||||||
<Product>Insight</Product>
|
<Product>Insight</Product>
|
||||||
<AssemblyName>Insight.Remote.Shared</AssemblyName>
|
<AssemblyName>Insight.Remote.Shared</AssemblyName>
|
||||||
<AssemblyVersion>2023.11.17.0</AssemblyVersion>
|
<AssemblyVersion>2023.12.14.0</AssemblyVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
|
|
@ -13,10 +13,9 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
|
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.0" />
|
||||||
<PackageReference Include="System.ServiceProcess.ServiceController" Version="7.0.1" />
|
<PackageReference Include="System.ServiceProcess.ServiceController" Version="7.0.1" />
|
||||||
<PackageReference Include="SkiaSharp.Views.Desktop.Common" Version="2.88.6" />
|
<PackageReference Include="SkiaSharp.Views.Desktop.Common" Version="2.88.6" />
|
||||||
<PackageReference Include="Vaitr.Bus" Version="0.1.3" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<UseWindowsForms>true</UseWindowsForms>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
<Product>Remote Control</Product>
|
<Product>Remote Control</Product>
|
||||||
<AssemblyName>remote</AssemblyName>
|
<AssemblyName>remote</AssemblyName>
|
||||||
<AssemblyVersion>2023.11.17.0</AssemblyVersion>
|
<AssemblyVersion>2023.12.14.0</AssemblyVersion>
|
||||||
<RootNamespace>Insight.Remote.Windows</RootNamespace>
|
<RootNamespace>Insight.Remote.Windows</RootNamespace>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<Product>Insight</Product>
|
<Product>Insight</Product>
|
||||||
<AssemblyName>server</AssemblyName>
|
<AssemblyName>server</AssemblyName>
|
||||||
<AssemblyVersion>2023.11.17.0</AssemblyVersion>
|
<AssemblyVersion>2023.12.14.0</AssemblyVersion>
|
||||||
<RootNamespace>Insight.Server</RootNamespace>
|
<RootNamespace>Insight.Server</RootNamespace>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
@ -42,7 +42,6 @@
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" />
|
||||||
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
|
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
|
||||||
<!--Unix Serilog stuff-->
|
<!--Unix Serilog stuff-->
|
||||||
<PackageReference Include="Vaitr.Bus" Version="0.1.3" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ internal class JobService : BackgroundService
|
||||||
var jobs = new List<Task>
|
var jobs = new List<Task>
|
||||||
{
|
{
|
||||||
RunInventoryAsync(cancellationToken),
|
RunInventoryAsync(cancellationToken),
|
||||||
RunCustomsAsync(cancellationToken)
|
//RunCustomsAsync(cancellationToken)
|
||||||
};
|
};
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
<AssemblyName>setup</AssemblyName>
|
<AssemblyName>setup</AssemblyName>
|
||||||
<RootNamespace>Insight.Setup</RootNamespace>
|
<RootNamespace>Insight.Setup</RootNamespace>
|
||||||
<Product>Insight</Product>
|
<Product>Insight</Product>
|
||||||
<AssemblyVersion>2023.11.17.0</AssemblyVersion>
|
<AssemblyVersion>2023.12.14.0</AssemblyVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<Product>Insight</Product>
|
<Product>Insight</Product>
|
||||||
<RootNamespace>Insight.Updater</RootNamespace>
|
<RootNamespace>Insight.Updater</RootNamespace>
|
||||||
<AssemblyName>updater</AssemblyName>
|
<AssemblyName>updater</AssemblyName>
|
||||||
<AssemblyVersion>2023.11.17.0</AssemblyVersion>
|
<AssemblyVersion>2023.12.14.0</AssemblyVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
<MudLink Href="@Href" OnClick="OnClick" Underline="Underline.None">
|
@inherits ComponentBase
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
|
<MudLink Href="@Href" OnClick="OnClick" Underline="Underline.None">
|
||||||
<MudPaper Elevation="25">
|
<MudPaper Elevation="25">
|
||||||
<MudCard Elevation="0">
|
<MudCard Elevation="0">
|
||||||
<MudCardHeader>
|
<MudCardHeader>
|
||||||
|
|
@ -21,27 +24,35 @@
|
||||||
</MudLink>
|
</MudLink>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[Parameter]
|
[Parameter] public string? Href { get; set; }
|
||||||
public string? Href { get; set; }
|
[Parameter] public EventCallback OnClick { get; set; }
|
||||||
|
[Parameter] public string? Icon { get; set; }
|
||||||
|
[Parameter] public Color? IconColor { get; set; }
|
||||||
|
[Parameter] public string? Key { get; set; }
|
||||||
|
[Parameter] public Color? KeyColor { get; set; }
|
||||||
|
[Parameter] public string? Text { get; set; }
|
||||||
|
[Parameter] public int Lines { get; set; } = 1;
|
||||||
|
|
||||||
[Parameter]
|
private bool _disposed;
|
||||||
public EventCallback OnClick { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
public void Dispose()
|
||||||
public string? Icon { get; set; }
|
{
|
||||||
|
Dispose(true);
|
||||||
[Parameter]
|
GC.SuppressFinalize(this);
|
||||||
public Color? IconColor { get; set; }
|
}
|
||||||
|
|
||||||
[Parameter]
|
private void Dispose(bool disposing)
|
||||||
public string? Key { get; set; }
|
{
|
||||||
|
if (_disposed is false) return;
|
||||||
[Parameter]
|
if (disposing is false) return;
|
||||||
public Color? KeyColor { get; set; }
|
|
||||||
|
try
|
||||||
[Parameter]
|
{
|
||||||
public string? Text { get; set; }
|
|
||||||
|
}
|
||||||
[Parameter]
|
finally
|
||||||
public int Lines { get; set; } = 1;
|
{
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
@typeparam T
|
@typeparam T
|
||||||
|
|
||||||
|
@inherits ComponentBase
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
<MudLink Href="@Href" OnClick="OnClick" Underline="Underline.None">
|
<MudLink Href="@Href" OnClick="OnClick" Underline="Underline.None">
|
||||||
<MudPaper Elevation="25">
|
<MudPaper Elevation="25">
|
||||||
<MudCard Elevation="0">
|
<MudCard Elevation="0">
|
||||||
|
|
@ -31,27 +34,35 @@
|
||||||
</MudLink>
|
</MudLink>
|
||||||
|
|
||||||
@code{
|
@code{
|
||||||
[Parameter]
|
[Parameter] public string? Href { get; set; }
|
||||||
public string? Href { get; set; }
|
[Parameter] public EventCallback OnClick { get; set; }
|
||||||
|
[Parameter] public string? Icon { get; set; }
|
||||||
|
[Parameter] public Color? IconColor { get; set; }
|
||||||
|
[Parameter] public string? Key { get; set; }
|
||||||
|
[Parameter] public Color? KeyColor { get; set; }
|
||||||
|
[Parameter] public T? Value { get; set; }
|
||||||
|
[Parameter] public Color? ValueColor { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
private bool _disposed;
|
||||||
public EventCallback OnClick { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
public void Dispose()
|
||||||
public string? Icon { get; set; }
|
{
|
||||||
|
Dispose(true);
|
||||||
[Parameter]
|
GC.SuppressFinalize(this);
|
||||||
public Color? IconColor { get; set; }
|
}
|
||||||
|
|
||||||
[Parameter]
|
private void Dispose(bool disposing)
|
||||||
public string? Key { get; set; }
|
{
|
||||||
|
if (_disposed is false) return;
|
||||||
[Parameter]
|
if (disposing is false) return;
|
||||||
public Color? KeyColor { get; set; }
|
|
||||||
|
try
|
||||||
[Parameter]
|
{
|
||||||
public T? Value { get; set; }
|
|
||||||
|
}
|
||||||
[Parameter]
|
finally
|
||||||
public Color? ValueColor { get; set; }
|
{
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,28 +1,11 @@
|
||||||
<PageTitle>@Title</PageTitle>
|
@inherits ComponentBase
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
@*@if (Loading)
|
<PageTitle>@Title</PageTitle>
|
||||||
{
|
|
||||||
<MudProgressLinear Color="Color.Primary" Indeterminate="true" />
|
|
||||||
|
|
||||||
<div class="center-screen" style="height: calc(100vh - 70px);">
|
<div class="mt-4 ml-0">
|
||||||
<MudProgressCircular Color="Color.Primary" Size="Size.Large" Indeterminate="true" />
|
<div class="d-flex">
|
||||||
</div>
|
|
||||||
|
|
||||||
return;
|
|
||||||
}*@
|
|
||||||
|
|
||||||
<div class="mt-7 mb-7 ml-4">
|
|
||||||
<div class="d-flex mb-3">
|
|
||||||
<div>
|
<div>
|
||||||
@* <MudStack Row="true">
|
|
||||||
<MudBreadcrumbs Items="Breadcrumbs" Separator="" Style="padding: 0px;">
|
|
||||||
<ItemTemplate Context="item">
|
|
||||||
<MudChip Href="@(item.Href)" Disabled="@(item.Disabled)" Size="Size.Medium" Variant="Variant.Outlined" SelectedColor="Color.Inherit" Color="Color.Transparent">
|
|
||||||
@item.Text
|
|
||||||
</MudChip>
|
|
||||||
</ItemTemplate>
|
|
||||||
</MudBreadcrumbs>
|
|
||||||
</MudStack>*@
|
|
||||||
<MudStack Row="true">
|
<MudStack Row="true">
|
||||||
<MudBreadcrumbs Items="Breadcrumbs" Style="padding: 0px;" />
|
<MudBreadcrumbs Items="Breadcrumbs" Style="padding: 0px;" />
|
||||||
</MudStack>
|
</MudStack>
|
||||||
|
|
@ -43,9 +26,75 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-7">
|
<div class="mt-5">
|
||||||
@if (Content is not null)
|
@if (Content is not null)
|
||||||
{
|
{
|
||||||
@Content
|
@Content
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@code{
|
||||||
|
[Parameter] public string Title { get; set; } = Global.Name;
|
||||||
|
[Parameter] public List<BreadcrumbItem>? Breadcrumbs { get; set; }
|
||||||
|
[Parameter] public RenderFragment? BreadcrumbAction { get; set; }
|
||||||
|
[Parameter] public RenderFragment? Content { get; set; }
|
||||||
|
[Parameter] public Func<Task>? LoadData { get; set; }
|
||||||
|
[Parameter] public bool DisableReload { get; set; }
|
||||||
|
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
private bool _loading;
|
||||||
|
private bool Loading
|
||||||
|
{
|
||||||
|
get => _loading;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _loading)
|
||||||
|
{
|
||||||
|
_loading = value;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender) await OnRefreshAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnRefreshAsync()
|
||||||
|
{
|
||||||
|
if (LoadData is null || Loading) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Loading = true;
|
||||||
|
await LoadData();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Loading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_disposed is false) return;
|
||||||
|
if (disposing is false) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
using Insight.Web.Constants;
|
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
using MudBlazor;
|
|
||||||
|
|
||||||
namespace Insight.Web.Components.Containers;
|
|
||||||
|
|
||||||
public partial class BaseContainer
|
|
||||||
{
|
|
||||||
[Parameter]
|
|
||||||
public string Title { get; set; } = Global.Name;
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public List<BreadcrumbItem>? Breadcrumbs { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public RenderFragment? BreadcrumbAction { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public RenderFragment? Content { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public Func<Task>? LoadData { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public bool DisableReload { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
private bool _loading;
|
|
||||||
private bool Loading
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _loading;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value != _loading)
|
|
||||||
{
|
|
||||||
_loading = value;
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
||||||
{
|
|
||||||
if (firstRender)
|
|
||||||
{
|
|
||||||
await OnRefreshAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task OnRefreshAsync()
|
|
||||||
{
|
|
||||||
if (LoadData is null || Loading) return;
|
|
||||||
|
|
||||||
Loading = true;
|
|
||||||
StateHasChanged();
|
|
||||||
|
|
||||||
//var start = Stopwatch.GetTimestamp();
|
|
||||||
|
|
||||||
await LoadData();
|
|
||||||
|
|
||||||
//var time = Stopwatch.GetElapsedTime(start);
|
|
||||||
|
|
||||||
//if (time <= TimeSpan.FromSeconds(1))
|
|
||||||
//{
|
|
||||||
// await Task.Delay(TimeSpan.FromSeconds(1).Subtract(time));
|
|
||||||
//}
|
|
||||||
|
|
||||||
Loading = false;
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +1,24 @@
|
||||||
@typeparam T
|
@using Insight.Web.Extensions
|
||||||
|
|
||||||
|
@typeparam T
|
||||||
|
|
||||||
|
@inherits ComponentBase
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
<PageTitle>@Title</PageTitle>
|
<PageTitle>@Title</PageTitle>
|
||||||
|
|
||||||
<div class="mt-7 mb-6 ml-4">
|
<div class="mt-4 mb-6 ml-0">
|
||||||
<div class="d-flex mb-3">
|
<div class="d-flex mb-3">
|
||||||
<div>
|
<div>
|
||||||
<MudStack Row="true">
|
<MudStack Row="true">
|
||||||
<MudBreadcrumbs Items="Breadcrumbs" Style="padding: 0px;" />
|
<MudBreadcrumbs Items="Breadcrumbs" Style="padding: 0px;" />
|
||||||
@if (OnAdd.HasDelegate)
|
@if (OnAdd.HasDelegate)
|
||||||
{
|
{
|
||||||
@if (AddBreadcrumbs is not null)
|
@if (_optionalBreadcrumbs is not null)
|
||||||
{
|
{
|
||||||
<MudBreadcrumbs Items="AddBreadcrumbs" Class="ml-n3" Style="padding: 0px;" />
|
<MudBreadcrumbs Items="_optionalBreadcrumbs" Class="ml-n3" Style="padding: 0px;" />
|
||||||
}
|
}
|
||||||
|
|
||||||
<MudIconButton OnClick="OnAddClick" Icon="@Icons.Material.Filled.Add" Size="Size.Small" Color="Color.Primary" Class="ml-n4" />
|
<MudIconButton OnClick="OnAddClick" Icon="@Icons.Material.Filled.Add" Size="Size.Small" Color="Color.Primary" Class="ml-n4" />
|
||||||
|
|
@ -25,7 +32,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MudTable T="T" @ref="Table" ServerData="OnLoadDataAsync" RowsPerPage="50" Loading="Loading" Elevation="0" Dense Square FixedHeader="true" FixedFooter="true" Height="calc(100vh - 205px)">
|
<MudTable T="T" @ref="_table" ServerData="OnLoadDataAsync" RowsPerPage="50" Loading="_loading" Elevation="0" Dense Square FixedHeader="true" FixedFooter="true" Height="calc(100vh - 205px)">
|
||||||
<HeaderContent>
|
<HeaderContent>
|
||||||
@if (Header is not null)
|
@if (Header is not null)
|
||||||
{
|
{
|
||||||
|
|
@ -36,7 +43,7 @@
|
||||||
<MudButton OnClick="OnFilterClick" Variant="Variant.Text" Size="Size.Small" Color="@(Filtered ? Color.Warning : Color.Inherit)" DisableElevation Disabled="@(!OnFilter.HasDelegate)">
|
<MudButton OnClick="OnFilterClick" Variant="Variant.Text" Size="Size.Small" Color="@(Filtered ? Color.Warning : Color.Inherit)" DisableElevation Disabled="@(!OnFilter.HasDelegate)">
|
||||||
Filter
|
Filter
|
||||||
</MudButton>
|
</MudButton>
|
||||||
<MudButton OnClick="RefreshAsync" Variant="Variant.Text" Size="Size.Small" DisableElevation Disabled="@(DisableRefresh || Loading)">
|
<MudButton OnClick="RefreshAsync" Variant="Variant.Text" Size="Size.Small" DisableElevation Disabled="@(DisableRefresh || _loading)">
|
||||||
Refresh
|
Refresh
|
||||||
</MudButton>
|
</MudButton>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
|
|
@ -64,3 +71,136 @@
|
||||||
<MudTablePager RowsPerPageString="" />
|
<MudTablePager RowsPerPageString="" />
|
||||||
</PagerContent>
|
</PagerContent>
|
||||||
</MudTable>
|
</MudTable>
|
||||||
|
|
||||||
|
@code{
|
||||||
|
[Parameter] public string Title { get; set; } = Global.Name;
|
||||||
|
[Parameter] public List<BreadcrumbItem>? Breadcrumbs { get; set; }
|
||||||
|
[Parameter] public Func<TableState, Task<TableData<T>>>? Data { get; set; }
|
||||||
|
[Parameter] public RenderFragment? Header { get; set; }
|
||||||
|
[Parameter] public RenderFragment<T>? RowTemplate { get; set; }
|
||||||
|
[Parameter] public RenderFragment<T>? ActionTemplate { get; set; }
|
||||||
|
[Parameter] public bool DisableAction { get; set; }
|
||||||
|
[Parameter] public bool DisableRefresh { get; set; }
|
||||||
|
[Parameter] public string? Search
|
||||||
|
{
|
||||||
|
get => _search;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_search == value) return;
|
||||||
|
_search = value;
|
||||||
|
|
||||||
|
SearchChanged.InvokeAsync(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Parameter] public bool Filtered { get; set; }
|
||||||
|
[Parameter] public EventCallback<string?> SearchChanged { get; set; }
|
||||||
|
[Parameter] public EventCallback OnFilter { get; set; }
|
||||||
|
[Parameter] public EventCallback OnAdd { get; set; }
|
||||||
|
|
||||||
|
private List<BreadcrumbItem>? _optionalBreadcrumbs;
|
||||||
|
private MudTable<T>? _table;
|
||||||
|
private string? _search;
|
||||||
|
private bool _loading;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
private bool Loading
|
||||||
|
{
|
||||||
|
get => _loading;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _loading)
|
||||||
|
{
|
||||||
|
_loading = value;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
if (OnAdd.HasDelegate)
|
||||||
|
{
|
||||||
|
_optionalBreadcrumbs = new List<BreadcrumbItem>()
|
||||||
|
{
|
||||||
|
new("", "#", true),
|
||||||
|
new("", "#", true)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NavigationManager.GetQueryString().TryGetValue("search", out var search))
|
||||||
|
{
|
||||||
|
Search = search.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<TableData<T>> OnLoadDataAsync(TableState state)
|
||||||
|
{
|
||||||
|
if (Data is null) throw new MissingMethodException(nameof(Data));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Loading = true;
|
||||||
|
return await Data(state);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Loading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RefreshAsync()
|
||||||
|
{
|
||||||
|
if (Loading || _table is null) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Loading = true;
|
||||||
|
await _table.ReloadServerData();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Loading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SearchAsync(string? text)
|
||||||
|
{
|
||||||
|
Search = text;
|
||||||
|
|
||||||
|
if (Loading) return;
|
||||||
|
await RefreshAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSearchReleased() => NavigationManager.ChangeQueryStringValue("search", Search);
|
||||||
|
|
||||||
|
private async Task OnFilterClick()
|
||||||
|
{
|
||||||
|
if (OnFilter.HasDelegate) await OnFilter.InvokeAsync(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnAddClick()
|
||||||
|
{
|
||||||
|
if (OnAdd.HasDelegate) await OnAdd.InvokeAsync(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_disposed is false) return;
|
||||||
|
if (disposing is false) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,194 +0,0 @@
|
||||||
using Insight.Web.Constants;
|
|
||||||
using Insight.Web.Extensions;
|
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
using MudBlazor;
|
|
||||||
|
|
||||||
namespace Insight.Web.Components.Containers;
|
|
||||||
|
|
||||||
public partial class TableContainer<T>
|
|
||||||
{
|
|
||||||
[Inject] private NavigationManager NavigationManager { get; init; } = default!;
|
|
||||||
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string Title { get; set; } = Global.Name;
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public List<BreadcrumbItem>? Breadcrumbs { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public Func<TableState, Task<TableData<T>>>? Data { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public RenderFragment? Header { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public RenderFragment<T>? RowTemplate { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public RenderFragment<T>? ActionTemplate { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public bool DisableAction { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
private List<BreadcrumbItem>? AddBreadcrumbs { get; set; }
|
|
||||||
private MudTable<T>? Table { get; set; }
|
|
||||||
private bool Loading { get; set; }
|
|
||||||
|
|
||||||
private int CurrentPage { get; set; }
|
|
||||||
private int CurrentSize { get; set; }
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
if (OnAdd.HasDelegate)
|
|
||||||
{
|
|
||||||
AddBreadcrumbs = new List<BreadcrumbItem>()
|
|
||||||
{
|
|
||||||
new BreadcrumbItem("", "#", true),
|
|
||||||
new BreadcrumbItem("", "#", true)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NavigationManager.GetQueryString().TryGetValue("search", out var search))
|
|
||||||
{
|
|
||||||
Search = search.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (NavigationManager.GetQueryString().TryGetValue("page", out var pageRaw))
|
|
||||||
//{
|
|
||||||
// if (int.TryParse(pageRaw, out var page))
|
|
||||||
// {
|
|
||||||
// CurrentPage = page;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//if (NavigationManager.GetQueryString().TryGetValue("size", out var sizeRaw))
|
|
||||||
//{
|
|
||||||
// if (int.TryParse(sizeRaw, out var size))
|
|
||||||
// {
|
|
||||||
// CurrentSize = size == 0 ? 100 : size;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<TableData<T>> OnLoadDataAsync(TableState state)
|
|
||||||
{
|
|
||||||
if (Data is null)
|
|
||||||
{
|
|
||||||
throw new MissingMethodException(nameof(Data));
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Loading = true;
|
|
||||||
|
|
||||||
//state.Page = CurrentPage;
|
|
||||||
//Table.SetRowsPerPage(CurrentSize);
|
|
||||||
|
|
||||||
var data = await Data(state);
|
|
||||||
|
|
||||||
//CurrentPage = state.Page;
|
|
||||||
//CurrentSize = state.PageSize;
|
|
||||||
|
|
||||||
//NavigationManager.ChangeQueryStringValue("page", state.Page.ToString());
|
|
||||||
//NavigationManager.ChangeQueryStringValue("size", state.PageSize.ToString());
|
|
||||||
|
|
||||||
//if (state.SortLabel is not null) NavigationManager.ChangeQueryStringValue("sort", state.SortLabel.ToString());
|
|
||||||
//if (state.SortDirection) NavigationManager.ChangeQueryStringValue("direction", state.SortDirection.ToString());
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Loading = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public bool DisableRefresh { get; set; }
|
|
||||||
|
|
||||||
private string? _search;
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string? Search
|
|
||||||
{
|
|
||||||
get => _search;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_search == value) return;
|
|
||||||
_search = value;
|
|
||||||
|
|
||||||
SearchChanged.InvokeAsync(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public EventCallback<string?> SearchChanged { get; set; }
|
|
||||||
|
|
||||||
private async Task SearchAsync(string? text)
|
|
||||||
{
|
|
||||||
Search = text;
|
|
||||||
|
|
||||||
if (Loading) return;
|
|
||||||
await RefreshAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task RefreshAsync()
|
|
||||||
{
|
|
||||||
if (Loading || Table is null) return;
|
|
||||||
|
|
||||||
Loading = true;
|
|
||||||
StateHasChanged();
|
|
||||||
|
|
||||||
//var start = Stopwatch.GetTimestamp();
|
|
||||||
|
|
||||||
await Table.ReloadServerData();
|
|
||||||
|
|
||||||
//var time = Stopwatch.GetElapsedTime(start);
|
|
||||||
|
|
||||||
//if (time <= TimeSpan.FromSeconds(1))
|
|
||||||
//{
|
|
||||||
// await Task.Delay(TimeSpan.FromSeconds(1).Subtract(time));
|
|
||||||
//}
|
|
||||||
|
|
||||||
Loading = false;
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSearchReleased()
|
|
||||||
{
|
|
||||||
NavigationManager.ChangeQueryStringValue("search", Search);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
[Parameter] public EventCallback OnFilter { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public bool Filtered { get; set; }
|
|
||||||
|
|
||||||
private async Task OnFilterClick()
|
|
||||||
{
|
|
||||||
if (OnFilter.HasDelegate)
|
|
||||||
{
|
|
||||||
await OnFilter.InvokeAsync(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public EventCallback OnAdd { get; set; }
|
|
||||||
|
|
||||||
private async Task OnAddClick()
|
|
||||||
{
|
|
||||||
if (OnAdd.HasDelegate)
|
|
||||||
{
|
|
||||||
await OnAdd.InvokeAsync(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
@if (@Actions is not null)
|
@inherits ComponentBase
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
|
@if (@Actions is not null)
|
||||||
{
|
{
|
||||||
<MudDialog @bind-IsVisible="Visible" Style="max-width: inherit !important;">
|
<MudDialog @bind-IsVisible="Visible" Style="max-width: inherit !important;">
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
|
|
@ -23,3 +26,51 @@ else
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</MudDialog>
|
</MudDialog>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@code{
|
||||||
|
[CascadingParameter] public MudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
|
[Parameter] public bool Visible
|
||||||
|
{
|
||||||
|
get => _visible;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_visible == value) return;
|
||||||
|
_visible = value;
|
||||||
|
|
||||||
|
VisibleChanged.InvokeAsync(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Parameter] public EventCallback<bool> VisibleChanged { get; set; }
|
||||||
|
[Parameter] public RenderFragment? Content { get; set; }
|
||||||
|
[Parameter] public RenderFragment? Actions { get; set; }
|
||||||
|
|
||||||
|
private bool _visible;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
protected override void OnAfterRender(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender is false) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_disposed is false) return;
|
||||||
|
if (disposing is false) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
|
|
||||||
namespace Insight.Web.Components.Dialogs;
|
|
||||||
|
|
||||||
public partial class ActionDialog
|
|
||||||
{
|
|
||||||
private bool _visible;
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public bool Visible
|
|
||||||
{
|
|
||||||
get => _visible;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_visible == value) return;
|
|
||||||
_visible = value;
|
|
||||||
|
|
||||||
VisibleChanged.InvokeAsync(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public EventCallback<bool> VisibleChanged { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public RenderFragment? Content { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public RenderFragment? Actions { get; set; }
|
|
||||||
}
|
|
||||||
|
|
@ -11,11 +11,6 @@
|
||||||
</MudText>
|
</MudText>
|
||||||
</MudDrawerHeader>
|
</MudDrawerHeader>
|
||||||
|
|
||||||
@* <MudToolBar Dense="true">
|
|
||||||
<MudText Typo="Typo.h6" Inline="true" Class="mr-2">#</MudText>
|
|
||||||
<MudText Typo="Typo.h6">contacts</MudText>
|
|
||||||
</MudToolBar> *@
|
|
||||||
|
|
||||||
<MudStack Justify="Justify.Center" Class="px-6">
|
<MudStack Justify="Justify.Center" Class="px-6">
|
||||||
<MudList Clickable="true" Style="max-height: calc(100vh - 220px); overflow-y: scroll;">
|
<MudList Clickable="true" Style="max-height: calc(100vh - 220px); overflow-y: scroll;">
|
||||||
@foreach (var user in ChatService.Users.Keys.Where(p => p.Uid != SessionHandler.State.Uid).OrderByDescending(p => p.Online))
|
@foreach (var user in ChatService.Users.Keys.Where(p => p.Uid != SessionHandler.State.Uid).OrderByDescending(p => p.Online))
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ using static Insight.Web.Constants.Events.Chat;
|
||||||
|
|
||||||
namespace Insight.Web.Components.Dialogs;
|
namespace Insight.Web.Components.Dialogs;
|
||||||
|
|
||||||
public partial class ChatDialog
|
public partial class ChatDialog : IDisposable
|
||||||
{
|
{
|
||||||
[Inject] private Bus Bus { get; init; } = default!;
|
[Inject] private Bus Bus { get; init; } = default!;
|
||||||
[Inject] private ChatService ChatService { get; init; } = default!;
|
[Inject] private ChatService ChatService { get; init; } = default!;
|
||||||
|
|
@ -45,10 +45,10 @@ public partial class ChatDialog
|
||||||
|
|
||||||
private enum Content { Contacts, Chat }
|
private enum Content { Contacts, Chat }
|
||||||
private Content _content = Content.Contacts;
|
private Content _content = Content.Contacts;
|
||||||
|
|
||||||
private ChatUser? _currentUser;
|
private ChatUser? _currentUser;
|
||||||
private ChatSession? _currentSession;
|
private ChatSession? _currentSession;
|
||||||
private string? _currentMessage;
|
private string? _currentMessage;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
private readonly List<IDisposable> _subscriptions = new();
|
private readonly List<IDisposable> _subscriptions = new();
|
||||||
|
|
||||||
|
|
@ -194,4 +194,25 @@ public partial class ChatDialog
|
||||||
|
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_disposed is false) return;
|
||||||
|
if (disposing is false) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,34 @@
|
||||||
@inherits LayoutComponentBase
|
@inherits LayoutComponentBase
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
|
<MudThemeProvider Theme="Themes.Default()" IsDarkMode="false" />
|
||||||
<MudSnackbarProvider />
|
<MudSnackbarProvider />
|
||||||
<ThemeProvider DisableIcon />
|
|
||||||
|
|
||||||
<MudLayout>
|
<MudLayout>
|
||||||
@Body
|
@Body
|
||||||
</MudLayout>
|
</MudLayout>
|
||||||
|
|
||||||
|
@code{
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_disposed is false) return;
|
||||||
|
if (disposing is false) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,19 @@
|
||||||
@using Vaitr.Bus;
|
@using Vaitr.Bus;
|
||||||
|
@using Blazored.LocalStorage;
|
||||||
|
@using Microsoft.AspNetCore.Identity;
|
||||||
|
@using MongoDB.Driver;
|
||||||
|
@using Insight.Infrastructure
|
||||||
|
|
||||||
@inherits LayoutComponentBase
|
@inherits LayoutComponentBase
|
||||||
@implements IDisposable
|
@implements IDisposable
|
||||||
|
|
||||||
|
@inject AuthenticationStateProvider AuthenticationStateProvider
|
||||||
|
@inject IServiceScopeFactory ServiceScopeFactory
|
||||||
|
@inject ILocalStorageService LocalStorageService
|
||||||
|
@inject IMongoDatabase Database
|
||||||
@inject Bus Bus
|
@inject Bus Bus
|
||||||
|
|
||||||
|
<MudThemeProvider Theme="_currentTheme" IsDarkMode="_darkMode" />
|
||||||
<MudSnackbarProvider />
|
<MudSnackbarProvider />
|
||||||
<MudDialogProvider />
|
<MudDialogProvider />
|
||||||
|
|
||||||
|
|
@ -19,8 +28,11 @@
|
||||||
</Authorized>
|
</Authorized>
|
||||||
</AuthorizeView>
|
</AuthorizeView>
|
||||||
<MudSpacer />
|
<MudSpacer />
|
||||||
|
@if (_darkModeSwitch is false)
|
||||||
|
{
|
||||||
|
<MudIconButton OnClick="@OnDarkModeToggleAsync" Icon="@(_darkMode ? Icons.Material.Filled.Brightness5 : Icons.Material.Filled.Brightness4)" Color="Color.Inherit" />
|
||||||
|
}
|
||||||
<ChatProvider />
|
<ChatProvider />
|
||||||
<ThemeProvider />
|
|
||||||
<ProfileProvider />
|
<ProfileProvider />
|
||||||
</MudAppBar>
|
</MudAppBar>
|
||||||
<AuthorizeView>
|
<AuthorizeView>
|
||||||
|
|
@ -40,7 +52,10 @@
|
||||||
@code{
|
@code{
|
||||||
public IReadOnlyDictionary<string, object>? RouteValues { get; set; }
|
public IReadOnlyDictionary<string, object>? RouteValues { get; set; }
|
||||||
|
|
||||||
|
private MudTheme _currentTheme = Themes.Default();
|
||||||
private DrawerProvider? _drawer;
|
private DrawerProvider? _drawer;
|
||||||
|
private bool _darkMode;
|
||||||
|
private bool _darkModeSwitch;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
protected override void OnParametersSet()
|
||||||
|
|
@ -50,6 +65,11 @@
|
||||||
base.OnParametersSet();
|
base.OnParametersSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
await LoadDarkModeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
|
|
@ -60,22 +80,85 @@
|
||||||
await Bus.PublishAsync(Events.Layout.Rendered).ConfigureAwait(false);
|
await Bus.PublishAsync(Events.Layout.Rendered).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task LoadDarkModeAsync()
|
||||||
|
{
|
||||||
|
// local storage
|
||||||
|
var storageDarkMode = await LocalStorageService.GetItemAsync<bool?>("darkmode");
|
||||||
|
if (storageDarkMode is bool darkmodeValue) _darkMode = darkmodeValue;
|
||||||
|
|
||||||
|
// database override
|
||||||
|
var state = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
||||||
|
|
||||||
|
if (state?.User.Identity is not null && state.User.Identity.IsAuthenticated)
|
||||||
|
{
|
||||||
|
using var scope = ServiceScopeFactory.CreateScope();
|
||||||
|
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<InsightUser>>();
|
||||||
|
|
||||||
|
if (await userManager.FindByNameAsync(state.User.Identity.Name) is not InsightUser user) return;
|
||||||
|
|
||||||
|
var userPrefs = await Database.UserPreference()
|
||||||
|
.Find(p => p.User == user.Id.ToString())
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (userPrefs is null) return;
|
||||||
|
|
||||||
|
_darkMode = userPrefs.DarkMode;
|
||||||
|
|
||||||
|
await LocalStorageService.SetItemAsync("darkmode", _darkMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnDarkModeToggleAsync()
|
||||||
|
{
|
||||||
|
// update current
|
||||||
|
_darkMode = !_darkMode;
|
||||||
|
|
||||||
|
// update local storage
|
||||||
|
await LocalStorageService.SetItemAsync("darkmode", _darkMode);
|
||||||
|
|
||||||
|
// update database
|
||||||
|
var state = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
||||||
|
|
||||||
|
if (state?.User.Identity is not null && state.User.Identity.IsAuthenticated)
|
||||||
|
{
|
||||||
|
using var scope = ServiceScopeFactory.CreateScope();
|
||||||
|
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<InsightUser>>();
|
||||||
|
|
||||||
|
if (await userManager.FindByNameAsync(state.User.Identity.Name) is not InsightUser user) return;
|
||||||
|
|
||||||
|
var date = DateTime.Now;
|
||||||
|
|
||||||
|
var userPrefs = await Database.UserPreference()
|
||||||
|
.UpdateOneAsync(p => p.User == user.Id.ToString(), Builders<InsightUserPreferences>.Update
|
||||||
|
.SetOnInsert(p => p.User, user.Id.ToString())
|
||||||
|
.SetOnInsert(p => p.Insert, date)
|
||||||
|
.Set(p => p.Update, date)
|
||||||
|
.Set(p => p.DarkMode, _darkMode), new UpdateOptions
|
||||||
|
{
|
||||||
|
IsUpsert = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(disposing: true);
|
Dispose(true);
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
private void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
// auto disposed when starved circuit timeouts (disconnects)
|
if (_disposed is false) return;
|
||||||
if (_disposed is false)
|
if (disposing is false) return;
|
||||||
{
|
|
||||||
if (disposing)
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,36 @@
|
||||||
@inherits ComponentBase
|
@inherits ComponentBase
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
<MudNavLink Icon="@Icons.Material.Filled.Person" IconColor="Color.Inherit" Match="NavLinkMatch.All" Class="pl-3">
|
<MudNavLink Icon="@Icons.Material.Filled.Person" IconColor="Color.Inherit" Match="NavLinkMatch.All" Class="pl-3">
|
||||||
Account
|
Account
|
||||||
</MudNavLink>
|
</MudNavLink>
|
||||||
|
|
||||||
<MudNavLink Href=@Navigation.Account.Profile Match="NavLinkMatch.Prefix">Profile</MudNavLink>
|
<MudNavLink Href=@Navigation.Account.Profile Match="NavLinkMatch.Prefix">Profile</MudNavLink>
|
||||||
|
|
||||||
|
@code{
|
||||||
|
[CascadingParameter] public IReadOnlyDictionary<string, object>? RouteValues { get; set; }
|
||||||
|
|
||||||
|
private string _title = "Account";
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_disposed is false) return;
|
||||||
|
if (disposing is false) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
using Microsoft.AspNetCore.Components.Authorization;
|
|
||||||
|
|
||||||
namespace Insight.Web.Components.Navbars;
|
|
||||||
|
|
||||||
public partial class Account
|
|
||||||
{
|
|
||||||
[CascadingParameter] public IReadOnlyDictionary<string, object>? RouteValues { get; set; }
|
|
||||||
|
|
||||||
[Inject] private NavigationManager NavigationManager { get; init; } = default!;
|
|
||||||
[Inject] private AuthenticationStateProvider AuthenticationStateProvider { get; init; } = default!;
|
|
||||||
|
|
||||||
private string Uri { get; set; } = string.Empty;
|
|
||||||
private string Title { get; set; } = "Account";
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
var cp = (await AuthenticationStateProvider.GetAuthenticationStateAsync()).User;
|
|
||||||
//Title = $"Account: {cp?.Identity?.Name}";
|
|
||||||
|
|
||||||
Uri = NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnAfterRender(bool firstRender)
|
|
||||||
{
|
|
||||||
Uri = NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +1,70 @@
|
||||||
@inherits ComponentBase
|
@using MongoDB.Driver
|
||||||
|
@using Vaitr.Bus
|
||||||
|
|
||||||
@*<MudNavLink Icon="@Icons.Material.Outlined.Business" IconColor="Color.Secondary" Match="NavLinkMatch.All" Class="pl-2">
|
@inherits ComponentBase
|
||||||
@Title
|
@implements IDisposable
|
||||||
</MudNavLink>*@
|
|
||||||
|
|
||||||
<MudNavLink Href=@Navigation.Management.Customers.DetailsHref(Id) Icon="@Icons.Material.Outlined.Business" IconColor="Color.Inherit" Match="NavLinkMatch.All" Class="pl-3">
|
@inject IMongoDatabase Database
|
||||||
@Title
|
@inject Bus Bus
|
||||||
|
|
||||||
|
<MudNavLink Href=@Navigation.Management.Customers.DetailsHref(_id) Icon="@Icons.Material.Outlined.Business" IconColor="Color.Inherit" Match="NavLinkMatch.All" Class="pl-3">
|
||||||
|
@_title
|
||||||
</MudNavLink>
|
</MudNavLink>
|
||||||
|
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<MudNavLink Href=@Navigation.Management.Customers.HostsHref(Id) Match="NavLinkMatch.All">Hosts</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Customers.HostsHref(_id) Match="NavLinkMatch.All">Hosts</MudNavLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@code{
|
||||||
|
[CascadingParameter] public IReadOnlyDictionary<string, object>? RouteValues { get; set; }
|
||||||
|
|
||||||
|
private string? _id;
|
||||||
|
private string _title = "Customer";
|
||||||
|
private IDisposable? _token;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
_token = Bus.Subscribe<string>(OnRefresh, p => p == Events.Layout.Rendered);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (RouteValues is not null && _id is null)
|
||||||
|
{
|
||||||
|
if (RouteValues.TryGetValue("customerId", out object? rawId) == false) return;
|
||||||
|
_id = rawId?.ToString();
|
||||||
|
|
||||||
|
var entity = await Database.Customer()
|
||||||
|
.Find(p => p.Id == _id)
|
||||||
|
.FirstOrDefaultAsync(default);
|
||||||
|
|
||||||
|
_title = $"{entity?.Name}";
|
||||||
|
|
||||||
|
await InvokeAsync(() => StateHasChanged());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnRefresh(string? message) => InvokeAsync(StateHasChanged);
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_disposed) return;
|
||||||
|
if (disposing is false) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_token?.Dispose();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
using Insight.Infrastructure.Entities;
|
|
||||||
using Insight.Web.Constants;
|
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
using MongoDB.Driver;
|
|
||||||
using Vaitr.Bus;
|
|
||||||
|
|
||||||
namespace Insight.Web.Components.Navbars;
|
|
||||||
|
|
||||||
public partial class Customer
|
|
||||||
{
|
|
||||||
[CascadingParameter] public IReadOnlyDictionary<string, object>? RouteValues { get; set; }
|
|
||||||
|
|
||||||
[Inject] private IMongoDatabase Database { get; set; } = default!;
|
|
||||||
[Inject] private Bus Bus { get; init; } = default!;
|
|
||||||
|
|
||||||
private string Title { get; set; } = "Customer";
|
|
||||||
private string? Id { get; set; }
|
|
||||||
|
|
||||||
private IDisposable? Token { get; set; }
|
|
||||||
public bool Disposed { get; set; } = false;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
Token = Bus.Subscribe<string>(OnRefresh, p => p == Events.Layout.Rendered);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
||||||
{
|
|
||||||
if (RouteValues is not null && Id is null)
|
|
||||||
{
|
|
||||||
if (RouteValues.TryGetValue("customerId", out object? rawId) == false) return;
|
|
||||||
Id = rawId?.ToString();
|
|
||||||
|
|
||||||
var entity = await Database.Customer()
|
|
||||||
.Find(p => p.Id == Id)
|
|
||||||
.FirstOrDefaultAsync(default);
|
|
||||||
|
|
||||||
Title = $"{entity?.Name}";
|
|
||||||
|
|
||||||
await InvokeAsync(() => StateHasChanged());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnRefresh(string? message)
|
|
||||||
{
|
|
||||||
InvokeAsync(() => StateHasChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (Disposed) return;
|
|
||||||
if (disposing is false) return;
|
|
||||||
|
|
||||||
Token?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,60 +1,127 @@
|
||||||
@inherits ComponentBase
|
@using MongoDB.Driver
|
||||||
|
@using Vaitr.Bus
|
||||||
|
|
||||||
@*@if (CustomerEntity is not null)
|
@inherits ComponentBase
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
|
@inject IMongoDatabase Database
|
||||||
|
@inject Bus Bus
|
||||||
|
|
||||||
|
@*@if (_customer is not null)
|
||||||
{
|
{
|
||||||
<MudNavLink Icon="@Icons.Material.Outlined.Business" Href="@Navigation.Management.Customers.DetailsHref(CustomerEntity.DocumentId.ToString())" Class="pl-2">
|
<MudNavLink Icon="@Icons.Material.Outlined.Business" Href="@Navigation.Management.Customers.DetailsHref(CustomerEntity.DocumentId.ToString())" Class="pl-2">
|
||||||
@CustomerEntity.Name
|
@_customer.Name
|
||||||
</MudNavLink>
|
</MudNavLink>
|
||||||
}*@
|
}*@
|
||||||
|
|
||||||
@if (HostEntity is not null)
|
@if (_host is not null)
|
||||||
{
|
{
|
||||||
<MudNavLink Icon="@Icons.Material.Outlined.Devices" IconColor="Color.Inherit" Href=@Navigation.Management.Hosts.DetailsHref(Id) Match="NavLinkMatch.All" Class="pl-3">
|
<MudNavLink Icon="@Icons.Material.Outlined.Devices" IconColor="Color.Inherit" Href=@Navigation.Management.Hosts.DetailsHref(_id) Match="NavLinkMatch.All" Class="pl-3">
|
||||||
@HostEntity.Name
|
@_host.Name
|
||||||
</MudNavLink>
|
</MudNavLink>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<MudNavGroup Title="Actions">
|
<MudNavGroup Title="Actions">
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Actions.Console.IndexHref(Id) Match="NavLinkMatch.Prefix">Console</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Actions.Console.IndexHref(_id) Match="NavLinkMatch.Prefix">Console</MudNavLink>
|
||||||
</MudNavGroup>
|
</MudNavGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-1">
|
<div class="mt-1">
|
||||||
<MudNavGroup Title="Inventory">
|
<MudNavGroup Title="Inventory">
|
||||||
<MudNavGroup Title="System">
|
<MudNavGroup Title="System">
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Os.DetailsHref(Id) Match="NavLinkMatch.Prefix">Os</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Os.DetailsHref(_id) Match="NavLinkMatch.Prefix">Os</MudNavLink>
|
||||||
<MudNavGroup Title="Updates">
|
<MudNavGroup Title="Updates">
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Updates.Installed.IndexHref(Id) Match="NavLinkMatch.Prefix">Installed</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Updates.Installed.IndexHref(_id) Match="NavLinkMatch.Prefix">Installed</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Updates.Pending.IndexHref(Id) Match="NavLinkMatch.Prefix">Pending</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Updates.Pending.IndexHref(_id) Match="NavLinkMatch.Prefix">Pending</MudNavLink>
|
||||||
</MudNavGroup>
|
</MudNavGroup>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Sessions.IndexHref(Id) Match="NavLinkMatch.Prefix">Sessions</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Sessions.IndexHref(_id) Match="NavLinkMatch.Prefix">Sessions</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Software.IndexHref(Id) Match="NavLinkMatch.Prefix">Software</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Software.IndexHref(_id) Match="NavLinkMatch.Prefix">Software</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Services.IndexHref(Id) Match="NavLinkMatch.Prefix">Services</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Services.IndexHref(_id) Match="NavLinkMatch.Prefix">Services</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Printers.IndexHref(Id) Match="NavLinkMatch.Prefix">Printers</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Printers.IndexHref(_id) Match="NavLinkMatch.Prefix">Printers</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Volumes.IndexHref(Id) Match="NavLinkMatch.Prefix">Volumes</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Volumes.IndexHref(_id) Match="NavLinkMatch.Prefix">Volumes</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Users.IndexHref(Id) Match="NavLinkMatch.Prefix">Users</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Users.IndexHref(_id) Match="NavLinkMatch.Prefix">Users</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Groups.IndexHref(Id) Match="NavLinkMatch.Prefix">Groups</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Systems.Groups.IndexHref(_id) Match="NavLinkMatch.Prefix">Groups</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Systems.StoragePools.IndexHref(Id) Match="NavLinkMatch.Prefix">Storage Pools</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Systems.StoragePools.IndexHref(_id) Match="NavLinkMatch.Prefix">Storage Pools</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Systems.VirtualMaschines.IndexHref(Id) Match="NavLinkMatch.Prefix">Virtual Maschines</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Systems.VirtualMaschines.IndexHref(_id) Match="NavLinkMatch.Prefix">Virtual Maschines</MudNavLink>
|
||||||
</MudNavGroup>
|
</MudNavGroup>
|
||||||
<MudNavGroup Title="Network">
|
<MudNavGroup Title="Network">
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Network.Interfaces.IndexHref(Id) Match="NavLinkMatch.Prefix">Interfaces</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Network.Interfaces.IndexHref(_id) Match="NavLinkMatch.Prefix">Interfaces</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Network.Addresses.IndexHref(Id) Match="NavLinkMatch.Prefix">Addresses</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Network.Addresses.IndexHref(_id) Match="NavLinkMatch.Prefix">Addresses</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Network.Nameservers.IndexHref(Id) Match="NavLinkMatch.Prefix">Nameservers</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Network.Nameservers.IndexHref(_id) Match="NavLinkMatch.Prefix">Nameservers</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Network.Gateways.IndexHref(Id) Match="NavLinkMatch.Prefix">Gateways</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Network.Gateways.IndexHref(_id) Match="NavLinkMatch.Prefix">Gateways</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Network.Routes.IndexHref(Id) Match="NavLinkMatch.Prefix">Routes</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Network.Routes.IndexHref(_id) Match="NavLinkMatch.Prefix">Routes</MudNavLink>
|
||||||
</MudNavGroup>
|
</MudNavGroup>
|
||||||
<MudNavGroup Title="Hardware">
|
<MudNavGroup Title="Hardware">
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Hardware.Mainboard.DetailsHref(Id) Match="NavLinkMatch.Prefix">Mainboard</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Hardware.Mainboard.DetailsHref(_id) Match="NavLinkMatch.Prefix">Mainboard</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Hardware.Processors.DetailsHref(Id) Match="NavLinkMatch.Prefix">Processors</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Hardware.Processors.DetailsHref(_id) Match="NavLinkMatch.Prefix">Processors</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Hardware.Memory.IndexHref(Id) Match="NavLinkMatch.Prefix">Memory</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Hardware.Memory.IndexHref(_id) Match="NavLinkMatch.Prefix">Memory</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Hardware.Drives.IndexHref(Id) Match="NavLinkMatch.Prefix">Drives</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Hardware.Drives.IndexHref(_id) Match="NavLinkMatch.Prefix">Drives</MudNavLink>
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.Hardware.Videocards.IndexHref(Id) Match="NavLinkMatch.Prefix">Videocards</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.Hardware.Videocards.IndexHref(_id) Match="NavLinkMatch.Prefix">Videocards</MudNavLink>
|
||||||
</MudNavGroup>
|
</MudNavGroup>
|
||||||
</MudNavGroup>
|
</MudNavGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-1">
|
<div class="mt-1">
|
||||||
<MudNavLink Href=@Navigation.Management.Hosts.LogsHref(Id) Match="NavLinkMatch.Prefix">Logs</MudNavLink>
|
<MudNavLink Href=@Navigation.Management.Hosts.LogsHref(_id) Match="NavLinkMatch.Prefix">Logs</MudNavLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@code{
|
||||||
|
[CascadingParameter] public IReadOnlyDictionary<string, object>? RouteValues { get; set; }
|
||||||
|
|
||||||
|
private string? _id;
|
||||||
|
private CustomerEntity? _customer;
|
||||||
|
private HostEntity? _host;
|
||||||
|
private IDisposable? _token;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
_token = Bus?.Subscribe<string>(OnRefresh, p => p == Events.Layout.Rendered);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (RouteValues is not null && _id is null)
|
||||||
|
{
|
||||||
|
if (RouteValues.TryGetValue("hostId", out object? rawId) == false) return;
|
||||||
|
_id = rawId?.ToString();
|
||||||
|
|
||||||
|
_host = await Database.Host()
|
||||||
|
.Find(p => p.Id == _id)
|
||||||
|
.FirstOrDefaultAsync(default);
|
||||||
|
|
||||||
|
if (_host is not null)
|
||||||
|
{
|
||||||
|
_customer = await Database.Customer()
|
||||||
|
.Find(p => p.Id == _host.Customer)
|
||||||
|
.FirstOrDefaultAsync(default);
|
||||||
|
}
|
||||||
|
|
||||||
|
await InvokeAsync(() => StateHasChanged());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnRefresh(string? message) => InvokeAsync(StateHasChanged);
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_disposed) return;
|
||||||
|
if (disposing is false) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_token?.Dispose();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
using Insight.Infrastructure.Entities;
|
|
||||||
using Insight.Web.Constants;
|
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
using MongoDB.Driver;
|
|
||||||
using Vaitr.Bus;
|
|
||||||
|
|
||||||
namespace Insight.Web.Components.Navbars;
|
|
||||||
|
|
||||||
public partial class Host : IDisposable
|
|
||||||
{
|
|
||||||
[CascadingParameter] public IReadOnlyDictionary<string, object>? RouteValues { get; set; }
|
|
||||||
|
|
||||||
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
|
||||||
[Inject] private Bus Bus { get; init; } = default!;
|
|
||||||
|
|
||||||
private CustomerEntity? CustomerEntity { get; set; }
|
|
||||||
private HostEntity HostEntity { get; set; }
|
|
||||||
private string? Id { get; set; }
|
|
||||||
|
|
||||||
private IDisposable? Token { get; set; }
|
|
||||||
public bool Disposed { get; set; } = false;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
Token = Bus?.Subscribe<string>(OnRefresh, p => p == Events.Layout.Rendered);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
||||||
{
|
|
||||||
if (RouteValues is not null && Id is null)
|
|
||||||
{
|
|
||||||
if (RouteValues.TryGetValue("hostId", out object? rawId) == false) return;
|
|
||||||
Id = rawId?.ToString();
|
|
||||||
|
|
||||||
HostEntity = await Database.Host()
|
|
||||||
.Find(p => p.Id == Id)
|
|
||||||
.FirstOrDefaultAsync(default);
|
|
||||||
|
|
||||||
if (HostEntity is not null)
|
|
||||||
{
|
|
||||||
CustomerEntity = await Database.Customer()
|
|
||||||
.Find(p => p.Id == HostEntity.Customer)
|
|
||||||
.FirstOrDefaultAsync(default);
|
|
||||||
}
|
|
||||||
|
|
||||||
await InvokeAsync(() => StateHasChanged());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnRefresh(string? message)
|
|
||||||
{
|
|
||||||
InvokeAsync(() => StateHasChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (Disposed) return;
|
|
||||||
if (disposing is false) return;
|
|
||||||
|
|
||||||
Token?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,14 @@
|
||||||
@inherits ComponentBase
|
@using MongoDB.Driver
|
||||||
|
@using Vaitr.Bus
|
||||||
|
|
||||||
<MudNavGroup Title="Monitoring" Expanded="ExpandMonitoringGroup">
|
@inherits ComponentBase
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
@inject IMongoDatabase Database
|
||||||
|
@inject Bus Bus
|
||||||
|
|
||||||
|
<MudNavGroup Title="Monitoring" Expanded="ExpandMonitoring">
|
||||||
@*<MudNavLink Href=@Navigation.Monitoring.Index Match="NavLinkMatch.Prefix">
|
@*<MudNavLink Href=@Navigation.Monitoring.Index Match="NavLinkMatch.Prefix">
|
||||||
Dashboard
|
Dashboard
|
||||||
</MudNavLink>*@
|
</MudNavLink>*@
|
||||||
|
|
@ -12,7 +20,7 @@
|
||||||
</MudNavLink>*@
|
</MudNavLink>*@
|
||||||
</MudNavGroup>
|
</MudNavGroup>
|
||||||
|
|
||||||
<MudNavGroup Title="Inventory" Expanded="ExpandInventoryGroup">
|
<MudNavGroup Title="Inventory" Expanded="ExpandInventory">
|
||||||
<MudNavGroup Title="System" Expanded="ExpandInventorySystem">
|
<MudNavGroup Title="System" Expanded="ExpandInventorySystem">
|
||||||
<MudNavLink Href=@Navigation.Inventory.Systems.Os.Index Match="NavLinkMatch.Prefix">
|
<MudNavLink Href=@Navigation.Inventory.Systems.Os.Index Match="NavLinkMatch.Prefix">
|
||||||
Os
|
Os
|
||||||
|
|
@ -84,10 +92,7 @@
|
||||||
</MudNavGroup>
|
</MudNavGroup>
|
||||||
</MudNavGroup>
|
</MudNavGroup>
|
||||||
|
|
||||||
<MudNavGroup Title="Management" Expanded="ExpandManagementGroup">
|
<MudNavGroup Title="Management" Expanded="ExpandManagement">
|
||||||
<MudNavLink Href=@Navigation.Management.Overview.Index Match="NavLinkMatch.Prefix">
|
|
||||||
Overview
|
|
||||||
</MudNavLink>
|
|
||||||
<MudNavLink Href=@Navigation.Management.Accounts.Index Match="NavLinkMatch.Prefix">
|
<MudNavLink Href=@Navigation.Management.Accounts.Index Match="NavLinkMatch.Prefix">
|
||||||
Accounts
|
Accounts
|
||||||
</MudNavLink>
|
</MudNavLink>
|
||||||
|
|
@ -103,10 +108,52 @@
|
||||||
<MudNavLink Href=@Navigation.Management.Agents.Index Match="NavLinkMatch.Prefix">
|
<MudNavLink Href=@Navigation.Management.Agents.Index Match="NavLinkMatch.Prefix">
|
||||||
Agents
|
Agents
|
||||||
</MudNavLink>
|
</MudNavLink>
|
||||||
|
<MudNavLink Href=@Navigation.Management.Scheduler.Jobs.Index Match="NavLinkMatch.Prefix" Style="text-decoration: line-through;">
|
||||||
|
Scheduler
|
||||||
|
</MudNavLink>
|
||||||
</MudNavGroup>
|
</MudNavGroup>
|
||||||
|
|
||||||
@*<MudNavGroup Title="Test">
|
@code{
|
||||||
<MudNavLink Href="chat" Match="NavLinkMatch.Prefix">
|
private bool ExpandMonitoring => _uri.StartsWith(Navigation.Monitoring.Index);
|
||||||
Chat
|
private bool ExpandManagement => _uri.StartsWith(Navigation.Management.Index);
|
||||||
</MudNavLink>
|
private bool ExpandInventory => _uri.StartsWith(Navigation.Inventory.Index);
|
||||||
</MudNavGroup>*@
|
private bool ExpandInventorySystem => _uri.StartsWith(Navigation.Inventory.Systems.Index);
|
||||||
|
private bool ExpandInventoryNetwork => _uri.StartsWith(Navigation.Inventory.Network.Index);
|
||||||
|
private bool ExpandInventoryHardware => _uri.StartsWith(Navigation.Inventory.Hardware.Index);
|
||||||
|
private string _uri = string.Empty;
|
||||||
|
private IDisposable? _token;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
_token = Bus?.Subscribe<string>(OnRefresh, p => p == Events.Layout.Rendered);
|
||||||
|
OnRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnRefresh(string? message = null)
|
||||||
|
{
|
||||||
|
_uri = NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
|
||||||
|
InvokeAsync(() => StateHasChanged());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_disposed is false) return;
|
||||||
|
if (disposing is false) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_token?.Dispose();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,136 +0,0 @@
|
||||||
using Insight.Web.Constants;
|
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
using Vaitr.Bus;
|
|
||||||
|
|
||||||
namespace Insight.Web.Components.Navbars;
|
|
||||||
|
|
||||||
public partial class Main : IDisposable
|
|
||||||
{
|
|
||||||
[Inject] private Bus Bus { get; init; } = default!;
|
|
||||||
[Inject] private NavigationManager NavigationManager { get; init; } = default!;
|
|
||||||
|
|
||||||
private string Uri { get; set; } = string.Empty;
|
|
||||||
private IDisposable? Token { get; set; }
|
|
||||||
public bool Disposed { get; set; } = false;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
Token = Bus?.Subscribe<string>(OnRefresh, p => p == Events.Layout.Rendered);
|
|
||||||
OnRefresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnRefresh(string? message = null)
|
|
||||||
{
|
|
||||||
Uri = NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
|
|
||||||
InvokeAsync(() => StateHasChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ExpandMonitoringGroup
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (Uri.StartsWith(Navigation.Monitoring.Index)) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ExpandManagementGroup
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (Uri.StartsWith(Navigation.Management.Overview.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Management.Accounts.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Management.Customers.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Management.Hosts.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Management.HostGroups.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Management.Agents.Index)) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ExpandInventoryGroup
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (ExpandInventorySystem) return true;
|
|
||||||
if (ExpandInventoryNetwork) return true;
|
|
||||||
if (ExpandInventoryHardware) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ExpandInventorySystem
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.Os.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.Os.Hosts)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.Os.Guests)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.Updates.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.Updates.Hosts)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.Software.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.Software.Hosts)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.Services.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.Services.Hosts)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.Sessions.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.Printers.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.Volumes.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.Users.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.Users.Hosts)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.Groups.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.Groups.Hosts)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.StoragePools.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Systems.VirtualMaschines.Index)) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ExpandInventoryNetwork
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Network.Interfaces.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Network.Addresses.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Network.Addresses.Hosts)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Network.Nameservers.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Network.Nameservers.Hosts)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Network.Gateways.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Network.Gateways.Hosts)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Network.Routes.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Network.Routes.Hosts)) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ExpandInventoryHardware
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Hardware.Mainboards.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Hardware.Mainboards.Hosts)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Hardware.Processors.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Hardware.Processors.Hosts)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Hardware.Memory.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Hardware.Memory.Hosts)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Hardware.Drives.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Hardware.Drives.Hosts)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Hardware.Videocards.Index)) return true;
|
|
||||||
if (Uri.StartsWith(Navigation.Inventory.Hardware.Videocards.Hosts)) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (Disposed) return;
|
|
||||||
if (disposing is false) return;
|
|
||||||
|
|
||||||
Token?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
@using System.Reflection;
|
|
||||||
@inherits ComponentBase
|
|
||||||
|
|
||||||
<div class="mt-5">
|
|
||||||
<MudNavMenu>
|
|
||||||
<CascadingValue Value="RouteValues">
|
|
||||||
@if (_content == Content.Account)
|
|
||||||
{
|
|
||||||
<Account />
|
|
||||||
}
|
|
||||||
else if (_content == Content.Host)
|
|
||||||
{
|
|
||||||
<Host />
|
|
||||||
}
|
|
||||||
else if (_content == Content.Customer)
|
|
||||||
{
|
|
||||||
<Customer />
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<Main />
|
|
||||||
}
|
|
||||||
</CascadingValue>
|
|
||||||
</MudNavMenu>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<MudText Typo="Typo.subtitle1" Class="d-flex flex-wrap flex-grow-1 align-content-end justify-center mb-2" Style="opacity: 0.2;">
|
|
||||||
@(Assembly.GetEntryAssembly()?.GetName().Version)
|
|
||||||
</MudText>
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
using Insight.Web.Constants;
|
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
using Vaitr.Bus;
|
|
||||||
|
|
||||||
namespace Insight.Web.Components.Navbars;
|
|
||||||
|
|
||||||
public partial class NavSwitch : IDisposable
|
|
||||||
{
|
|
||||||
[CascadingParameter] public IReadOnlyDictionary<string, object>? RouteValues { get; set; }
|
|
||||||
|
|
||||||
[Inject] private NavigationManager NavigationManager { get; init; } = default!;
|
|
||||||
[Inject] private Bus Bus { get; init; } = default!;
|
|
||||||
|
|
||||||
public string Url { get; set; } = string.Empty;
|
|
||||||
private IDisposable? Token { get; set; }
|
|
||||||
public bool Disposed { get; set; } = false;
|
|
||||||
|
|
||||||
private enum Content { Main, Account, Customer, Host }
|
|
||||||
private Content _content = Content.Main;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
Token = Bus?.SubscribeAsync<string>(OnRefreshAsync, p => p == Events.Layout.Rendered);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
||||||
{
|
|
||||||
if (firstRender)
|
|
||||||
{
|
|
||||||
await OnRefreshAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async ValueTask OnRefreshAsync(string? message = null, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
Url = NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
|
|
||||||
|
|
||||||
if (Url is null) return;
|
|
||||||
|
|
||||||
if (Url.StartsWith($"{Navigation.Account.Index}/")) _content = Content.Account;
|
|
||||||
else if (Url.StartsWith($"{Navigation.Management.Customers.Index}/")) _content = Content.Customer;
|
|
||||||
else if (Url.StartsWith($"{Navigation.Management.Hosts.Index}/")) _content = Content.Host;
|
|
||||||
else _content = Content.Main;
|
|
||||||
|
|
||||||
await InvokeAsync(StateHasChanged).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (Disposed) return;
|
|
||||||
Token?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
37
src/Web/Insight.Web/Components/Navbars/Scheduler.razor
Normal file
37
src/Web/Insight.Web/Components/Navbars/Scheduler.razor
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
@inherits ComponentBase
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
|
<MudNavLink Icon="@Icons.Material.Filled.Task" IconColor="Color.Inherit" Match="NavLinkMatch.All" Class="pl-3">
|
||||||
|
Scheduler
|
||||||
|
</MudNavLink>
|
||||||
|
|
||||||
|
<MudNavLink Href=@Navigation.Management.Scheduler.Jobs.Index Match="NavLinkMatch.Prefix">Jobs</MudNavLink>
|
||||||
|
<MudNavLink Href=@Navigation.Management.Scheduler.Tasks.Index Match="NavLinkMatch.Prefix">Tasks</MudNavLink>
|
||||||
|
<MudNavLink Href=@Navigation.Management.Scheduler.Triggers.Index Match="NavLinkMatch.Prefix">Triggers</MudNavLink>
|
||||||
|
|
||||||
|
@code{
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_disposed is false) return;
|
||||||
|
if (disposing is false) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,11 +2,12 @@
|
||||||
@using Vaitr.Bus;
|
@using Vaitr.Bus;
|
||||||
@using static Insight.Web.Constants.Events.Chat;
|
@using static Insight.Web.Constants.Events.Chat;
|
||||||
|
|
||||||
|
@inherits ComponentBase
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
@inject Bus Bus
|
@inject Bus Bus
|
||||||
@inject SessionHandler SessionHandler
|
@inject SessionHandler SessionHandler
|
||||||
|
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
<AuthorizeView>
|
<AuthorizeView>
|
||||||
<Authorized>
|
<Authorized>
|
||||||
<MudIconButton OnClick="()=>_chatDialog?.Toggle()" Icon="@(_chatDialog?.NewMessages > 0 ? Icons.Material.Filled.MarkUnreadChatAlt : Icons.Material.Filled.Chat)" Color="Color.Inherit" />
|
<MudIconButton OnClick="()=>_chatDialog?.Toggle()" Icon="@(_chatDialog?.NewMessages > 0 ? Icons.Material.Filled.MarkUnreadChatAlt : Icons.Material.Filled.Chat)" Color="Color.Inherit" />
|
||||||
|
|
@ -20,7 +21,7 @@
|
||||||
|
|
||||||
private readonly ConcurrentBag<IDisposable> _subscriptions = new();
|
private readonly ConcurrentBag<IDisposable> _subscriptions = new();
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
_subscriptions.Add(Bus.SubscribeAsync<string>(async (x, c) => await InvokeAsync(StateHasChanged), p => p == Events.Sessions.Changed));
|
_subscriptions.Add(Bus.SubscribeAsync<string>(async (x, c) => await InvokeAsync(StateHasChanged), p => p == Events.Sessions.Changed));
|
||||||
_subscriptions.Add(Bus.SubscribeAsync<ChatMessageReceived>(async (x, c) => await InvokeAsync(StateHasChanged), p => p.Message.SenderId != SessionHandler.State.Uid));
|
_subscriptions.Add(Bus.SubscribeAsync<ChatMessageReceived>(async (x, c) => await InvokeAsync(StateHasChanged), p => p.Message.SenderId != SessionHandler.State.Uid));
|
||||||
|
|
@ -28,21 +29,24 @@
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(disposing: true);
|
Dispose(true);
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
private void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
// auto disposed when starved circuit timeouts (disconnects)
|
// auto disposed when starved circuit timeouts (disconnects)
|
||||||
if (_disposed is false)
|
|
||||||
{
|
if (_disposed is false) return;
|
||||||
if (disposing)
|
if (disposing is false) return;
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
foreach (var sub in _subscriptions) sub.Dispose();
|
foreach (var sub in _subscriptions) sub.Dispose();
|
||||||
_subscriptions.Clear();
|
_subscriptions.Clear();
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,47 @@
|
||||||
<CascadingValue Value="RouteValues">
|
@using System.Reflection;
|
||||||
|
@using MongoDB.Driver
|
||||||
|
@using Vaitr.Bus
|
||||||
|
|
||||||
|
@inherits ComponentBase
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
@inject IMongoDatabase Database
|
||||||
|
@inject Bus Bus
|
||||||
|
|
||||||
|
<CascadingValue Value="RouteValues">
|
||||||
<MudDrawer @bind-Open="@_open" ClipMode="DrawerClipMode.Docked" Variant="DrawerVariant.Responsive" Breakpoint="Breakpoint.Md" Elevation="2">
|
<MudDrawer @bind-Open="@_open" ClipMode="DrawerClipMode.Docked" Variant="DrawerVariant.Responsive" Breakpoint="Breakpoint.Md" Elevation="2">
|
||||||
<AuthorizeView>
|
<AuthorizeView>
|
||||||
<Authorized>
|
<Authorized>
|
||||||
<NavSwitch />
|
<div class="mt-5">
|
||||||
|
<MudNavMenu>
|
||||||
|
<CascadingValue Value="RouteValues">
|
||||||
|
@if (_content == Content.Account)
|
||||||
|
{
|
||||||
|
<Account />
|
||||||
|
}
|
||||||
|
else if (_content == Content.Customer)
|
||||||
|
{
|
||||||
|
<Customer />
|
||||||
|
}
|
||||||
|
else if (_content == Content.Host)
|
||||||
|
{
|
||||||
|
<Host />
|
||||||
|
}
|
||||||
|
else if (_content == Content.Scheduler)
|
||||||
|
{
|
||||||
|
<Scheduler />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<Main />
|
||||||
|
}
|
||||||
|
</CascadingValue>
|
||||||
|
</MudNavMenu>
|
||||||
|
</div>
|
||||||
|
<MudText Typo="Typo.subtitle1" Class="d-flex flex-wrap flex-grow-1 align-content-end justify-center mb-2" Style="opacity: 0.2;">
|
||||||
|
@(Assembly.GetEntryAssembly()?.GetName().Version)
|
||||||
|
</MudText>
|
||||||
</Authorized>
|
</Authorized>
|
||||||
</AuthorizeView>
|
</AuthorizeView>
|
||||||
</MudDrawer>
|
</MudDrawer>
|
||||||
|
|
@ -11,6 +50,57 @@
|
||||||
@code {
|
@code {
|
||||||
[CascadingParameter] public IReadOnlyDictionary<string, object>? RouteValues { get; set; }
|
[CascadingParameter] public IReadOnlyDictionary<string, object>? RouteValues { get; set; }
|
||||||
|
|
||||||
|
private string _uri = string.Empty;
|
||||||
|
private enum Content { Main, Account, Customer, Host, Scheduler }
|
||||||
|
private Content _content = Content.Main;
|
||||||
|
private IDisposable? _token;
|
||||||
private bool _open = true;
|
private bool _open = true;
|
||||||
public void Toggle() => _open = !_open;
|
private bool _disposed;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
_token = Bus?.SubscribeAsync<string>(OnRefreshAsync, p => p == Events.Layout.Rendered);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender) await OnRefreshAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Toggle() => _open = !_open;
|
||||||
|
|
||||||
|
public async ValueTask OnRefreshAsync(string? message = null, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
_uri = NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
|
||||||
|
if (_uri is null) return;
|
||||||
|
|
||||||
|
if (_uri.StartsWith($"{Navigation.Account.Index}/")) _content = Content.Account;
|
||||||
|
else if (_uri.StartsWith($"{Navigation.Management.Customers.Index}/")) _content = Content.Customer;
|
||||||
|
else if (_uri.StartsWith($"{Navigation.Management.Hosts.Index}/")) _content = Content.Host;
|
||||||
|
else if (_uri.StartsWith($"{Navigation.Management.Scheduler.Index}/")) _content = Content.Scheduler;
|
||||||
|
else _content = Content.Main;
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_disposed is false) return;
|
||||||
|
if (disposing is false) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_token?.Dispose();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
@inject NavigationManager NavigationManager
|
@inherits ComponentBase
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
<AuthorizeView>
|
<AuthorizeView>
|
||||||
<Authorized>
|
<Authorized>
|
||||||
|
|
@ -49,6 +52,7 @@
|
||||||
|
|
||||||
@code{
|
@code{
|
||||||
private MudMenu? _menu;
|
private MudMenu? _menu;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
private void OnLogin()
|
private void OnLogin()
|
||||||
{
|
{
|
||||||
|
|
@ -67,4 +71,25 @@
|
||||||
_menu?.CloseMenu();
|
_menu?.CloseMenu();
|
||||||
NavigationManager.NavigateTo(Navigation.Account.Profile, false);
|
NavigationManager.NavigateTo(Navigation.Account.Profile, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_disposed is false) return;
|
||||||
|
if (disposing is false) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,14 +1,37 @@
|
||||||
@using Vaitr.Bus;
|
@using Vaitr.Bus;
|
||||||
|
|
||||||
|
@inherits ComponentBase
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
@inject SessionHandler SessionHandler
|
@inject SessionHandler SessionHandler
|
||||||
@inject Bus Bus
|
@inject Bus Bus
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
if (firstRender)
|
if (firstRender) await SessionHandler.UpdateStateAsync(default);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
{
|
{
|
||||||
await SessionHandler.UpdateStateAsync(default);
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_disposed is false) return;
|
||||||
|
if (disposing is false) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
@using Blazored.LocalStorage;
|
|
||||||
@using Microsoft.AspNetCore.Identity;
|
|
||||||
@using MongoDB.Driver;
|
|
||||||
@using Insight.Infrastructure
|
|
||||||
|
|
||||||
@inject IServiceScopeFactory ServiceScopeFactory
|
|
||||||
@inject ILocalStorageService LocalStorageService
|
|
||||||
@inject IMongoDatabase Database
|
|
||||||
@inject AuthenticationStateProvider AuthenticationStateProvider
|
|
||||||
|
|
||||||
<MudThemeProvider Theme="CurrentTheme" IsDarkMode="DarkMode" />
|
|
||||||
|
|
||||||
@if (DisableIcon is false)
|
|
||||||
{
|
|
||||||
<MudIconButton OnClick="@OnDarkModeToggleAsync" Icon="@(DarkMode ? Icons.Material.Filled.Brightness5 : Icons.Material.Filled.Brightness4)" Color="Color.Inherit" />
|
|
||||||
}
|
|
||||||
|
|
||||||
@code {
|
|
||||||
[Parameter] public bool DisableIcon { get; set; }
|
|
||||||
|
|
||||||
private MudTheme CurrentTheme { get; } = Themes.Default();
|
|
||||||
private bool DarkMode { get; set; }
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
await LoadDarkModeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task LoadDarkModeAsync()
|
|
||||||
{
|
|
||||||
// local storage
|
|
||||||
var storageDarkMode = await LocalStorageService.GetItemAsync<bool?>("darkmode");
|
|
||||||
if (storageDarkMode is bool darkmodeValue) DarkMode = darkmodeValue;
|
|
||||||
|
|
||||||
// database override
|
|
||||||
var state = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
|
||||||
|
|
||||||
if (state?.User.Identity is not null && state.User.Identity.IsAuthenticated)
|
|
||||||
{
|
|
||||||
using var scope = ServiceScopeFactory.CreateScope();
|
|
||||||
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<InsightUser>>();
|
|
||||||
|
|
||||||
if (await userManager.FindByNameAsync(state.User.Identity.Name) is not InsightUser user) return;
|
|
||||||
|
|
||||||
var userPrefs = await Database.UserPreference()
|
|
||||||
.Find(p => p.User == user.Id.ToString())
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
if (userPrefs is null) return;
|
|
||||||
|
|
||||||
DarkMode = userPrefs.DarkMode;
|
|
||||||
|
|
||||||
await LocalStorageService.SetItemAsync("darkmode", DarkMode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task OnDarkModeToggleAsync()
|
|
||||||
{
|
|
||||||
// update current
|
|
||||||
DarkMode = !DarkMode;
|
|
||||||
|
|
||||||
// update local storage
|
|
||||||
await LocalStorageService.SetItemAsync("darkmode", DarkMode);
|
|
||||||
|
|
||||||
// update database
|
|
||||||
var state = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
|
||||||
|
|
||||||
if (state?.User.Identity is not null && state.User.Identity.IsAuthenticated)
|
|
||||||
{
|
|
||||||
using var scope = ServiceScopeFactory.CreateScope();
|
|
||||||
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<InsightUser>>();
|
|
||||||
|
|
||||||
if (await userManager.FindByNameAsync(state.User.Identity.Name) is not InsightUser user) return;
|
|
||||||
|
|
||||||
var date = DateTime.Now;
|
|
||||||
|
|
||||||
var userPrefs = await Database.UserPreference()
|
|
||||||
.UpdateOneAsync(p => p.User == user.Id.ToString(), Builders<InsightUserPreferences>.Update
|
|
||||||
.SetOnInsert(p => p.User, user.Id.ToString())
|
|
||||||
.SetOnInsert(p => p.Insert, date)
|
|
||||||
.Set(p => p.Update, date)
|
|
||||||
.Set(p => p.DarkMode, DarkMode), new UpdateOptions
|
|
||||||
{
|
|
||||||
IsUpsert = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await InvokeAsync(StateHasChanged);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
namespace Insight.Web.Constants;
|
using static Insight.Web.Constants.Navigation.Monitoring;
|
||||||
|
|
||||||
|
namespace Insight.Web.Constants;
|
||||||
|
|
||||||
public static class Navigation
|
public static class Navigation
|
||||||
{
|
{
|
||||||
|
|
@ -13,44 +15,22 @@ public static class Navigation
|
||||||
public static class Account
|
public static class Account
|
||||||
{
|
{
|
||||||
public const string Index = "account";
|
public const string Index = "account";
|
||||||
public const string Login = "account/login";
|
public const string Login = Index + "/login";
|
||||||
public const string LoginTFA = "account/login/{key:guid}";
|
public const string LoginTFA = Login + "/{key:guid}";
|
||||||
public const string SignIn = "account/signin";
|
public const string SignIn = Index + "/signin";
|
||||||
public const string SignInTFA = "account/signin/2fa";
|
public const string SignInTFA = SignIn + "/2fa";
|
||||||
public const string Logout = "account/logout";
|
public const string Logout = Index + "/logout";
|
||||||
public const string Lockout = "account/lockout";
|
public const string Lockout = Index + "/lockout";
|
||||||
public const string Profile = "account/profile";
|
public const string Profile = Index + "/profile";
|
||||||
public const string ChangePassword = "account/changepassword";
|
public const string ChangePassword = Index + "/changepassword";
|
||||||
|
|
||||||
public static string LoginHref(string redirect)
|
public static string LoginHref(string redirect) => string.IsNullOrWhiteSpace(redirect) ? Login : $"{Login}?redirect={redirect}";
|
||||||
{
|
public static string LoginTFAHref(Guid key) => LoginTFA.Replace("{key:guid}", key.ToString());
|
||||||
if (string.IsNullOrWhiteSpace(redirect))
|
|
||||||
{
|
|
||||||
return Login;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"{Login}?redirect={redirect}";
|
public static string SignInHref(Guid key) => $"{SignIn}?key={key}";
|
||||||
}
|
public static string SignInTFAHref(Guid key) => $"{SignInTFA}?key={key}";
|
||||||
|
|
||||||
public static string LoginTFAHref(Guid key)
|
public static string ChangePasswordHref(Guid key) => $"{ChangePassword}?key={key}";
|
||||||
{
|
|
||||||
return LoginTFA.Replace("{key:guid}", key.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string SignInHref(Guid key)
|
|
||||||
{
|
|
||||||
return $"{SignIn}?key={key}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string SignInTFAHref(Guid key)
|
|
||||||
{
|
|
||||||
return $"{SignInTFA}?key={key}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ChangePasswordHref(Guid key)
|
|
||||||
{
|
|
||||||
return $"{ChangePassword}?key={key}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Monitoring
|
public static class Monitoring
|
||||||
|
|
@ -59,36 +39,36 @@ public static class Navigation
|
||||||
|
|
||||||
public static class Maintenance
|
public static class Maintenance
|
||||||
{
|
{
|
||||||
public const string Index = "monitoring/maintenance";
|
public const string Index = Monitoring.Index + "/maintenance";
|
||||||
|
|
||||||
public static class Drives
|
public static class Drives
|
||||||
{
|
{
|
||||||
public const string Index = "monitoring/maintenance/drives";
|
public const string Index = Monitoring.Index + "/drives";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class StoragePools
|
public static class StoragePools
|
||||||
{
|
{
|
||||||
public const string Index = "monitoring/maintenance/storagepools";
|
public const string Index = Monitoring.Index + "/storagepools";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Volumes
|
public static class Volumes
|
||||||
{
|
{
|
||||||
public const string Index = "monitoring/maintenance/volumes";
|
public const string Index = Monitoring.Index + "/volumes";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Guests
|
public static class Guests
|
||||||
{
|
{
|
||||||
public const string Index = "monitoring/maintenance/guests";
|
public const string Index = Monitoring.Index + "/guests";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Snapshots
|
public static class Snapshots
|
||||||
{
|
{
|
||||||
public const string Index = "monitoring/maintenance/snapshots";
|
public const string Index = Monitoring.Index + "/snapshots";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Updates
|
public static class Updates
|
||||||
{
|
{
|
||||||
public const string Index = "monitoring/maintenance/updates";
|
public const string Index = Monitoring.Index + "/updates";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -97,106 +77,58 @@ public static class Navigation
|
||||||
{
|
{
|
||||||
public const string Index = "management";
|
public const string Index = "management";
|
||||||
|
|
||||||
public static class Overview
|
|
||||||
{
|
|
||||||
public const string Index = "management/overview";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Accounts
|
public static class Accounts
|
||||||
{
|
{
|
||||||
public const string Index = "management/accounts";
|
public const string Index = Management.Index + "/accounts";
|
||||||
public const string Details = "management/accounts/{accountId}";
|
public const string Details = Index + "/{accountId}";
|
||||||
|
|
||||||
public static string DetailsHref(string? accountId)
|
public static string DetailsHref(string? accountId) => Details.Replace("{accountId}", accountId);
|
||||||
{
|
|
||||||
return Details.Replace("{accountId}", accountId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Customers
|
public static class Customers
|
||||||
{
|
{
|
||||||
public const string Index = "management/customers";
|
public const string Index = Management.Index + "/customers";
|
||||||
public const string Details = "management/customers/{customerId}";
|
public const string Details = Index + "/{customerId}";
|
||||||
public const string Hosts = "management/customers/{customerId}/hosts";
|
public const string Hosts = Details + "/hosts";
|
||||||
public const string HostsAssign = "management/customers/{customerId}/hosts/assign";
|
public const string HostsAssign = Hosts + "/assign";
|
||||||
|
|
||||||
public static string DetailsHref(string? customerId)
|
public static string DetailsHref(string? customerId) => Details.Replace("{customerId}", customerId);
|
||||||
{
|
public static string HostsHref(string? customerId) => Hosts.Replace("{customerId}", customerId);
|
||||||
return Details.Replace("{customerId}", customerId);
|
public static string HostsAssignHref(string? customerId) => HostsAssign.Replace("{customerId}", customerId);
|
||||||
}
|
|
||||||
|
|
||||||
public static string HostsHref(string? customerId)
|
|
||||||
{
|
|
||||||
return Hosts.Replace("{customerId}", customerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string HostsAssignHref(string? customerId)
|
|
||||||
{
|
|
||||||
return HostsAssign.Replace("{customerId}", customerId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Agents
|
public static class Agents
|
||||||
{
|
{
|
||||||
public const string Index = "management/agents";
|
public const string Index = Management.Index + "/agents";
|
||||||
public const string Details = "management/agents/{agentId}";
|
public const string Details = Index + "/{agentId}";
|
||||||
public const string Logs = "management/agents/{agentId}/logs";
|
public const string Logs = Details + "/logs";
|
||||||
public const string HostAssign = "management/agents/{agentId}/assign";
|
public const string HostAssign = Details + "/assign";
|
||||||
|
|
||||||
public static string DetailsHref(string? agentId)
|
public static string DetailsHref(string? agentId) => Details.Replace("{agentId}", agentId);
|
||||||
{
|
public static string LogsHref(string? agentId) => Logs.Replace("{agentId}", agentId);
|
||||||
return Details.Replace("{agentId}", agentId);
|
public static string HostAssingHref(string? agentId) => HostAssign.Replace("{agentId}", agentId);
|
||||||
}
|
|
||||||
|
|
||||||
public static string LogsHref(string? agentId)
|
|
||||||
{
|
|
||||||
return Logs.Replace("{agentId}", agentId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string HostAssingHref(string? agentId)
|
|
||||||
{
|
|
||||||
return HostAssign.Replace("{agentId}", agentId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Hosts
|
public static class Hosts
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts";
|
public const string Index = Management.Index + "/hosts";
|
||||||
public const string Details = "management/hosts/{hostId}";
|
public const string Details = Index + "/{hostId}";
|
||||||
public const string Logs = "management/hosts/{hostId}/logs";
|
public const string Logs = Details + "/logs";
|
||||||
public const string CustomerAssign = "management/hosts/{hostId}/customer/assign";
|
public const string CustomerAssign = Details + "/customer/assign";
|
||||||
public const string AgentAssign = "management/hosts/{hostId}/agent/assign";
|
public const string AgentAssign = Details + "/agent/assign";
|
||||||
|
|
||||||
public static string DetailsHref(string? hostId)
|
public static string DetailsHref(string? hostId) => Details.Replace("{hostId}", hostId);
|
||||||
{
|
public static string LogsHref(string? hostId) => Logs.Replace("{hostId}", hostId);
|
||||||
return Details.Replace("{hostId}", hostId);
|
public static string CustomerAssingHref(string? hostId) => CustomerAssign.Replace("{hostId}", hostId);
|
||||||
}
|
public static string AgentAssingHref(string? hostId) => AgentAssign.Replace("{hostId}", hostId);
|
||||||
|
|
||||||
public static string LogsHref(string? hostId)
|
|
||||||
{
|
|
||||||
return Logs.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string CustomerAssingHref(string? hostId)
|
|
||||||
{
|
|
||||||
return CustomerAssign.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string AgentAssingHref(string? hostId)
|
|
||||||
{
|
|
||||||
return AgentAssign.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Actions
|
public static class Actions
|
||||||
{
|
{
|
||||||
public static class Console
|
public static class Console
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/console";
|
public const string Index = Hosts.Details + "/console";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,190 +136,121 @@ public static class Navigation
|
||||||
{
|
{
|
||||||
public static class Os
|
public static class Os
|
||||||
{
|
{
|
||||||
public const string Details = "management/hosts/{hostId}/os";
|
public const string Details = Hosts.Details + "/os";
|
||||||
|
|
||||||
public static string DetailsHref(string? hostId)
|
public static string DetailsHref(string? hostId) => Details.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Details.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Updates
|
public static class Updates
|
||||||
{
|
{
|
||||||
public static class Installed
|
public static class Installed
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/updates/installed";
|
public const string Index = Hosts.Details + "/updates/installed";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Pending
|
public static class Pending
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/updates/pending";
|
public const string Index = Hosts.Details + "/updates/pending";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Sessions
|
public static class Sessions
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/sessions";
|
public const string Index = Hosts.Details + "/sessions";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Software
|
public static class Software
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/software";
|
public const string Index = Hosts.Details + "/software";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Services
|
public static class Services
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/services";
|
public const string Index = Hosts.Details + "/services";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Printers
|
public static class Printers
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/printers";
|
public const string Index = Hosts.Details + "/printers";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Volumes
|
public static class Volumes
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/volumes";
|
public const string Index = Hosts.Details + "/volumes";
|
||||||
public const string Details = "management/hosts/{hostId}/volumes/{volumeId}";
|
public const string Details = Index + "/{volumeId}";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
public static string DetailsHref(string? hostId, string? volumeId) => Details.Replace("{hostId}", hostId).Replace("{volumeId}", volumeId);
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string DetailsHref(string? hostId, string? volumeId)
|
|
||||||
{
|
|
||||||
return Details.Replace("{hostId}", hostId).Replace("{volumeId}", volumeId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Users
|
public static class Users
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/users";
|
public const string Index = Hosts.Details + "/users";
|
||||||
public const string Details = "management/hosts/{hostId}/users/{userId}";
|
public const string Details = Index + "/{userId}";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
public static string DetailsHref(string? hostId, string? userId) => Details.Replace("{hostId}", hostId).Replace("{userId}", userId);
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string DetailsHref(string? hostId, string? userId)
|
|
||||||
{
|
|
||||||
return Details.Replace("{hostId}", hostId).Replace("{userId}", userId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Groups
|
public static class Groups
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/groups";
|
public const string Index = Hosts.Details + "/groups";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class StoragePools
|
public static class StoragePools
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/storagepools";
|
public const string Index = Hosts.Details + "/storagepools";
|
||||||
public const string Details = "management/hosts/{hostId}/storagepools/{storagePoolId}";
|
public const string Details = Index + "/{storagePoolId}";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
public static string DetailsHref(string? hostId, string? storagePoolId) => Details.Replace("{hostId}", hostId).Replace("{storagePoolId}", storagePoolId);
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string DetailsHref(string? hostId, string? storagePoolId)
|
|
||||||
{
|
|
||||||
return Details.Replace("{hostId}", hostId).Replace("{storagePoolId}", storagePoolId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class VirtualDisks
|
public static class VirtualDisks
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/storagepools/{storagePoolId}/virtualdisks";
|
public const string Index = StoragePools.Details + "/virtualdisks";
|
||||||
public const string Details = "management/hosts/{hostId}/storagepools/{storagePoolId}/virtualdisks/{virtualDiskId}";
|
public const string Details = Index + "/{virtualDiskId}";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId, string? storagePoolId)
|
public static string IndexHref(string? hostId, string? storagePoolId) => Index.Replace("{hostId}", hostId).Replace("{storagePoolId}", storagePoolId);
|
||||||
{
|
public static string DetailsHref(string? hostId, string? storagePoolId, string? virtualDiskId) => Details.Replace("{hostId}", hostId).Replace("{storagePoolId}", storagePoolId).Replace("{virtualDiskId}", virtualDiskId);
|
||||||
return Index.Replace("{hostId}", hostId).Replace("{storagePoolId}", storagePoolId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string DetailsHref(string? hostId, string? storagePoolId, string? virtualDiskId)
|
|
||||||
{
|
|
||||||
return Details.Replace("{hostId}", hostId).Replace("{storagePoolId}", storagePoolId).Replace("{virtualDiskId}", virtualDiskId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PhysicalDisks
|
public static class PhysicalDisks
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/storagepools/{storagePoolId}/physicaldisks";
|
public const string Index = StoragePools.Details + "/physicaldisks";
|
||||||
public const string Details = "management/hosts/{hostId}/storagepools/{storagePoolId}/physicaldisks/{physicalDiskId}";
|
public const string Details = Index + "/{physicalDiskId}";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId, string? storagePoolId)
|
public static string IndexHref(string? hostId, string? storagePoolId) => Index.Replace("{hostId}", hostId).Replace("{storagePoolId}", storagePoolId);
|
||||||
{
|
public static string DetailsHref(string? hostId, string? storagePoolId, string? physicalDiskId) => Details.Replace("{hostId}", hostId).Replace("{storagePoolId}", storagePoolId).Replace("{physicalDiskId}", physicalDiskId);
|
||||||
return Index.Replace("{hostId}", hostId).Replace("{storagePoolId}", storagePoolId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string DetailsHref(string? hostId, string? storagePoolId, string? physicalDiskId)
|
|
||||||
{
|
|
||||||
return Details.Replace("{hostId}", hostId).Replace("{storagePoolId}", storagePoolId).Replace("{physicalDiskId}", physicalDiskId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class VirtualMaschines
|
public static class VirtualMaschines
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/virtualmaschines";
|
public const string Index = Hosts.Details + "/virtualmaschines";
|
||||||
public const string Details = "management/hosts/{hostId}/virtualmaschines/{virtualMaschineId}";
|
public const string Details = Index + "/{virtualMaschineId}";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
public static string DetailsHref(string? hostId, string? virtualMaschineId) => Details.Replace("{hostId}", hostId).Replace("{virtualMaschineId}", virtualMaschineId);
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string DetailsHref(string? hostId, string? virtualMaschineId)
|
|
||||||
{
|
|
||||||
return Details.Replace("{hostId}", hostId).Replace("{virtualMaschineId}", virtualMaschineId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Snapshots
|
public static class Snapshots
|
||||||
{
|
{
|
||||||
public const string Details = "management/hosts/{hostId}/virtualmaschines/{virtualMaschineId}/snapshots/{snapshotId}";
|
public const string Details = VirtualMaschines.Details + "/snapshots/{snapshotId}";
|
||||||
|
|
||||||
public static string DetailsHref(string? hostId, string? virtualMaschineId, string? snapshotId)
|
public static string DetailsHref(string? hostId, string? virtualMaschineId, string? snapshotId) => Details.Replace("{hostId}", hostId).Replace("{virtualMaschineId}", virtualMaschineId).Replace("{snapshotId}", snapshotId);
|
||||||
{
|
|
||||||
return Details.Replace("{hostId}", hostId).Replace("{virtualMaschineId}", virtualMaschineId).Replace("{snapshotId}", snapshotId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -396,63 +259,44 @@ public static class Navigation
|
||||||
{
|
{
|
||||||
public static class Interfaces
|
public static class Interfaces
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/interfaces";
|
public const string Index = Hosts.Details + "/interfaces";
|
||||||
public const string Details = "management/hosts/{hostId}/interfaces/{interfaceId}";
|
public const string Details = Index + "/{interfaceId}";
|
||||||
|
|
||||||
public const string Addresses = "management/hosts/{hostId}/interfaces/{interfaceId}/addresses";
|
public const string Addresses = Details + "/addresses";
|
||||||
public const string Nameservers = "management/hosts/{hostId}/interfaces/{interfaceId}/nameservers";
|
public const string Nameservers = Details + "/nameservers";
|
||||||
public const string Gateways = "management/hosts/{hostId}/interfaces/{interfaceId}/gateways";
|
public const string Gateways = Details + "/gateways";
|
||||||
public const string Routes = "management/hosts/{hostId}/interfaces/{interfaceId}/routes";
|
public const string Routes = Details + "/routes";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
public static string DetailsHref(string? hostId, string? interfaceId) => Details.Replace("{hostId}", hostId).Replace("{interfaceId}", interfaceId);
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string DetailsHref(string? hostId, string? interfaceId)
|
|
||||||
{
|
|
||||||
return Details.Replace("{hostId}", hostId).Replace("{interfaceId}", interfaceId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Addresses
|
public static class Addresses
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/addresses";
|
public const string Index = Hosts.Details + "/addresses";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Gateways
|
public static class Gateways
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/gateways";
|
public const string Index = Details + "/gateways";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Nameservers
|
public static class Nameservers
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/nameservers";
|
public const string Index = Hosts.Details + "/nameservers";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Routes
|
public static class Routes
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/routes";
|
public const string Index = Hosts.Details + "/routes";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -460,300 +304,264 @@ public static class Navigation
|
||||||
{
|
{
|
||||||
public static class Mainboard
|
public static class Mainboard
|
||||||
{
|
{
|
||||||
public const string Details = "management/hosts/{hostId}/mainboard";
|
public const string Details = Hosts.Details + "/mainboard";
|
||||||
|
|
||||||
public static string DetailsHref(string? hostId)
|
public static string DetailsHref(string? hostId) => Details.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Details.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Processors
|
public static class Processors
|
||||||
{
|
{
|
||||||
public const string Details = "management/hosts/{hostId}/processors";
|
public const string Details = Hosts.Details + "/processors";
|
||||||
|
|
||||||
public static string DetailsHref(string? hostId)
|
public static string DetailsHref(string? hostId) => Details.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Details.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Memory
|
public static class Memory
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/memory";
|
public const string Index = Hosts.Details + "/memory";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Drives
|
public static class Drives
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/drives";
|
public const string Index = Hosts.Details + "/drives";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Videocards
|
public static class Videocards
|
||||||
{
|
{
|
||||||
public const string Index = "management/hosts/{hostId}/videocards";
|
public const string Index = Hosts.Details + "/videocards";
|
||||||
|
|
||||||
public static string IndexHref(string? hostId)
|
public static string IndexHref(string? hostId) => Index.Replace("{hostId}", hostId);
|
||||||
{
|
|
||||||
return Index.Replace("{hostId}", hostId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class HostGroups
|
public static class HostGroups
|
||||||
{
|
{
|
||||||
public const string Index = "management/hostgroups";
|
public const string Index = Management.Index + "/hostgroups";
|
||||||
public const string Details = "management/hostgroups/{groupId}";
|
public const string Details = Index + "/{groupId}";
|
||||||
public const string Hosts = "management/hostgroups/{groupId}/hosts";
|
public const string Hosts = Details + "/hosts";
|
||||||
public const string HostsAssign = "management/hostgroups/{groupId}/hosts/assign";
|
public const string HostsAssign = Details + "/assign";
|
||||||
|
|
||||||
public static string DetailsHref(string? groupId)
|
public static string DetailsHref(string? groupId) => Details.Replace("{groupId}", groupId);
|
||||||
{
|
public static string HostsHref(string? groupId) => Hosts.Replace("{groupId}", groupId);
|
||||||
return Details.Replace("{groupId}", groupId);
|
public static string HostsAssignHref(string? groupId) => HostsAssign.Replace("{groupId}", groupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string HostsHref(string? groupId)
|
public static class Scheduler
|
||||||
{
|
{
|
||||||
return Hosts.Replace("{groupId}", groupId);
|
public const string Index = Management.Index + "/scheduler";
|
||||||
|
|
||||||
|
public static class Jobs
|
||||||
|
{
|
||||||
|
public const string Index = Scheduler.Index + "/jobs";
|
||||||
|
public const string Details = Index + "/{jobId}";
|
||||||
|
public const string Tasks = Details + "/tasks";
|
||||||
|
public const string TasksAssign = Tasks + "/assign";
|
||||||
|
public const string Triggers = Details + "/triggers";
|
||||||
|
public const string TriggersAssign = Triggers + "/assign";
|
||||||
|
|
||||||
|
public static string DetailsHref(string? jobId) => Details.Replace("{jobId}", jobId);
|
||||||
|
public static string TasksHref(string? jobId) => Tasks.Replace("{jobId}", jobId);
|
||||||
|
public static string TasksAssignHref(string? jobId) => TasksAssign.Replace("{jobId}", jobId);
|
||||||
|
public static string TriggersHref(string? jobId) => Triggers.Replace("{jobId}", jobId);
|
||||||
|
public static string TriggersAssignHref(string? jobId) => TriggersAssign.Replace("{jobId}", jobId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string HostsAssignHref(string? groupId)
|
public static class Tasks
|
||||||
{
|
{
|
||||||
return HostsAssign.Replace("{groupId}", groupId);
|
public const string Index = Scheduler.Index + "/tasks";
|
||||||
|
public const string Details = Index + "/{taskId}";
|
||||||
|
public const string Jobs = Details + "/jobs";
|
||||||
|
|
||||||
|
public static string DetailsHref(string? taskId) => Details.Replace("{taskId}", taskId);
|
||||||
|
public static string JobsHref(string? taskId) => Jobs.Replace("{taskId}", taskId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Triggers
|
||||||
|
{
|
||||||
|
public const string Index = Scheduler.Index + "/triggers";
|
||||||
|
public const string Details = Index + "/{triggerId}";
|
||||||
|
public const string Jobs = Details + "/jobs";
|
||||||
|
|
||||||
|
public static string DetailsHref(string? triggerId) => Details.Replace("{triggerId}", triggerId);
|
||||||
|
public static string JobsHref(string? triggerId) => Jobs.Replace("{triggerId}", triggerId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Inventory
|
public static class Inventory
|
||||||
{
|
{
|
||||||
|
public const string Index = "inventory";
|
||||||
|
|
||||||
public static class Systems
|
public static class Systems
|
||||||
{
|
{
|
||||||
|
public const string Index = Inventory.Index + "/system";
|
||||||
|
|
||||||
public static class Os
|
public static class Os
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/os";
|
public const string Index = Systems.Index + "/os";
|
||||||
public const string Hosts = "inventory/os/{osName}/hosts";
|
public const string Hosts = Index + "/{osName}/hosts";
|
||||||
public const string Guests = "inventory/os/{osName}/guests";
|
public const string Guests = Index + "/{osName}/guests";
|
||||||
|
|
||||||
public static string HostsHref(string? osName)
|
public static string HostsHref(string? osName) => Hosts.Replace("{osName}", osName);
|
||||||
{
|
public static string GuestsHref(string? osName) => Guests.Replace("{osName}", osName);
|
||||||
return Hosts.Replace("{osName}", osName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GuestsHref(string? osName)
|
|
||||||
{
|
|
||||||
return Guests.Replace("{osName}", osName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Updates
|
public static class Updates
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/updates";
|
public const string Index = Systems.Index + "/updates";
|
||||||
public const string Hosts = "inventory/updates/{updateName}/hosts";
|
public const string Hosts = Index + "/{updateName}/hosts";
|
||||||
|
|
||||||
public static string HostsHref(string? updateName)
|
public static string HostsHref(string? updateName) => Hosts.Replace("{updateName}", updateName);
|
||||||
{
|
|
||||||
return Hosts.Replace("{updateName}", updateName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Software
|
public static class Software
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/software";
|
public const string Index = Systems.Index + "/software";
|
||||||
public const string Hosts = "inventory/software/{softwareName}/hosts";
|
public const string Hosts = Index + "/{softwareName}/hosts";
|
||||||
|
|
||||||
public static string HostsHref(string? software)
|
public static string HostsHref(string? software) => Hosts.Replace("{softwareName}", software);
|
||||||
{
|
|
||||||
return Hosts.Replace("{softwareName}", software);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Services
|
public static class Services
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/services";
|
public const string Index = Systems.Index + "/services";
|
||||||
public const string Hosts = "inventory/services/{serviceName}/hosts";
|
public const string Hosts = Index + "/{serviceName}/hosts";
|
||||||
|
|
||||||
public static string HostsHref(string? serviceName)
|
public static string HostsHref(string? serviceName) => Hosts.Replace("{serviceName}", serviceName);
|
||||||
{
|
|
||||||
return Hosts.Replace("{serviceName}", serviceName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Sessions
|
public static class Sessions
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/sessions";
|
public const string Index = Systems.Index + "/sessions";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Printers
|
public static class Printers
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/printers";
|
public const string Index = Systems.Index + "/printers";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Volumes
|
public static class Volumes
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/volumes";
|
public const string Index = Systems.Index + "/volumes";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Users
|
public static class Users
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/users";
|
public const string Index = Systems.Index + "/users";
|
||||||
public const string Hosts = "inventory/users/{userName}/hosts";
|
public const string Hosts = Index + "/{userName}/hosts";
|
||||||
|
|
||||||
public static string HostsHref(string? userName)
|
public static string HostsHref(string? userName) => Hosts.Replace("{userName}", userName);
|
||||||
{
|
|
||||||
return Hosts.Replace("{userName}", userName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Groups
|
public static class Groups
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/groups";
|
public const string Index = Systems.Index + "/groups";
|
||||||
public const string Hosts = "inventory/groups/{groupName}/hosts";
|
public const string Hosts = Index + "/{groupName}/hosts";
|
||||||
|
|
||||||
public static string HostsHref(string? groupName)
|
public static string HostsHref(string? groupName) => Hosts.Replace("{groupName}", groupName);
|
||||||
{
|
|
||||||
return Hosts.Replace("{groupName}", groupName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class StoragePools
|
public static class StoragePools
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/storagepools";
|
public const string Index = Systems.Index + "/storagepools";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class VirtualMaschines
|
public static class VirtualMaschines
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/virtualmaschines";
|
public const string Index = Systems.Index + "/virtualmaschines";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Network
|
public static class Network
|
||||||
{
|
{
|
||||||
|
public const string Index = Inventory.Index + "/network";
|
||||||
|
|
||||||
public static class Interfaces
|
public static class Interfaces
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/interfaces";
|
public const string Index = Network.Index + "/interfaces";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Addresses
|
public static class Addresses
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/addresses";
|
public const string Index = Network.Index + "/addresses";
|
||||||
public const string Hosts = "inventory/addresses/{address}/hosts";
|
public const string Hosts = Index + "/{address}/hosts";
|
||||||
|
|
||||||
public static string HostsHref(string? address)
|
public static string HostsHref(string? address) => Hosts.Replace("{address}", address);
|
||||||
{
|
|
||||||
return Hosts.Replace("{address}", address);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Nameservers
|
public static class Nameservers
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/nameservers";
|
public const string Index = Network.Index + "/nameservers";
|
||||||
public const string Hosts = "inventory/nameservers/{nameserverAddress}/hosts";
|
public const string Hosts = Index + "/{nameserverAddress}/hosts";
|
||||||
|
|
||||||
public static string HostsHref(string? nameserverAddress)
|
public static string HostsHref(string? nameserverAddress) => Hosts.Replace("{nameserverAddress}", nameserverAddress);
|
||||||
{
|
|
||||||
return Hosts.Replace("{nameserverAddress}", nameserverAddress);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Gateways
|
public static class Gateways
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/gateways";
|
public const string Index = Network.Index + "/gateways";
|
||||||
public const string Hosts = "inventory/gateways/{gatewayAddress}/hosts";
|
public const string Hosts = Index + "/{gatewayAddress}/hosts";
|
||||||
|
|
||||||
public static string HostsHref(string? gatewayAddress)
|
public static string HostsHref(string? gatewayAddress) => Hosts.Replace("{gatewayAddress}", gatewayAddress);
|
||||||
{
|
|
||||||
return Hosts.Replace("{gatewayAddress}", gatewayAddress);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Routes
|
public static class Routes
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/routes";
|
public const string Index = Network.Index + "/routes";
|
||||||
public const string Hosts = "inventory/routes/{routeAddress}/hosts";
|
public const string Hosts = Index + "/{routeAddress}/hosts";
|
||||||
|
|
||||||
public static string HostsHref(string? routeAddress)
|
public static string HostsHref(string? routeAddress) => Hosts.Replace("{routeAddress}", routeAddress);
|
||||||
{
|
|
||||||
return Hosts.Replace("{routeAddress}", routeAddress);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Hardware
|
public static class Hardware
|
||||||
{
|
{
|
||||||
|
public const string Index = Inventory.Index + "/hardware";
|
||||||
|
|
||||||
public static class Mainboards
|
public static class Mainboards
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/mainboards";
|
public const string Index = Hardware.Index + "/mainboards";
|
||||||
public const string Hosts = "inventory/mainboards/{mainboardName}/hosts";
|
public const string Hosts = Index + "/{mainboardName}/hosts";
|
||||||
|
|
||||||
public static string HostsHref(string? mainboardName)
|
public static string HostsHref(string? mainboardName) => Hosts.Replace("{mainboardName}", mainboardName);
|
||||||
{
|
|
||||||
return Hosts.Replace("{mainboardName}", mainboardName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Processors
|
public static class Processors
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/processors";
|
public const string Index = Hardware.Index + "/processors";
|
||||||
public const string Hosts = "inventory/processors/{processorName}/hosts";
|
public const string Hosts = Index + "/{processorName}/hosts";
|
||||||
|
|
||||||
public static string HostsHref(string? processorName)
|
public static string HostsHref(string? processorName) => Hosts.Replace("{processorName}", processorName);
|
||||||
{
|
|
||||||
return Hosts.Replace("{processorName}", processorName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Memory
|
public static class Memory
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/memory";
|
public const string Index = Hardware.Index + "/memory";
|
||||||
public const string Hosts = "inventory/memory/{memoryName}/hosts";
|
public const string Hosts = Index + "/{memoryName}/hosts";
|
||||||
|
|
||||||
public static string HostsHref(string? memoryName)
|
public static string HostsHref(string? memoryName) => Hosts.Replace("{memoryName}", memoryName);
|
||||||
{
|
|
||||||
return Hosts.Replace("{memoryName}", memoryName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Drives
|
public static class Drives
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/drives";
|
public const string Index = Hardware.Index + "/drives";
|
||||||
public const string Hosts = "inventory/drives/{driveName}/hosts";
|
public const string Hosts = Index + "/{driveName}/hosts";
|
||||||
|
|
||||||
public static string HostsHref(string? driveName)
|
public static string HostsHref(string? driveName) => Hosts.Replace("{driveName}", driveName);
|
||||||
{
|
|
||||||
return Hosts.Replace("{driveName}", driveName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Videocards
|
public static class Videocards
|
||||||
{
|
{
|
||||||
public const string Index = "inventory/videocards";
|
public const string Index = Hardware.Index + "/videocards";
|
||||||
public const string Hosts = "inventory/videocards/{videocardName}/hosts";
|
public const string Hosts = Index + "/{videocardName}/hosts";
|
||||||
|
|
||||||
public static string HostsHref(string? videocardName)
|
public static string HostsHref(string? videocardName) => Hosts.Replace("{videocardName}", videocardName);
|
||||||
{
|
|
||||||
return Hosts.Replace("{videocardName}", videocardName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Communication
|
|
||||||
{
|
|
||||||
public const string Index = "communication";
|
|
||||||
|
|
||||||
public static class Chat
|
|
||||||
{
|
|
||||||
public const string Index = "communication/chat";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<Product>Insight</Product>
|
<Product>Insight</Product>
|
||||||
<AssemblyName>web</AssemblyName>
|
<AssemblyName>web</AssemblyName>
|
||||||
<AssemblyVersion>2023.11.17.0</AssemblyVersion>
|
<AssemblyVersion>2023.12.14.0</AssemblyVersion>
|
||||||
<RootNamespace>Insight.Web</RootNamespace>
|
<RootNamespace>Insight.Web</RootNamespace>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
|
@ -29,8 +29,7 @@
|
||||||
<PackageReference Include="Blazored.LocalStorage" Version="4.4.0" />
|
<PackageReference Include="Blazored.LocalStorage" Version="4.4.0" />
|
||||||
<PackageReference Include="Blazored.SessionStorage" Version="2.4.0" />
|
<PackageReference Include="Blazored.SessionStorage" Version="2.4.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.13" />
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.13" />
|
||||||
<PackageReference Include="MudBlazor" Version="6.11.0" />
|
<PackageReference Include="MudBlazor" Version="6.11.1" />
|
||||||
<PackageReference Include="Vaitr.Bus" Version="0.1.3" />
|
|
||||||
<!--Unix Serilog stuff-->
|
<!--Unix Serilog stuff-->
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,17 +9,11 @@
|
||||||
<MudStack Justify="Justify.Center" Class="px-6" Spacing="3">
|
<MudStack Justify="Justify.Center" Class="px-6" Spacing="3">
|
||||||
<div class="d-flex justify-center" style="height: @(!_showQrCode ? 0 : 272)px;">
|
<div class="d-flex justify-center" style="height: @(!_showQrCode ? 0 : 272)px;">
|
||||||
<span id="qrc" hidden="@(!_showQrCode)" style="border-style: solid; border-color: white; border-width: 1px;" />
|
<span id="qrc" hidden="@(!_showQrCode)" style="border-style: solid; border-color: white; border-width: 1px;" />
|
||||||
@*<div style="width:50px;" />
|
|
||||||
<MudText Align="Align.Left" Typo="Typo.h6" hidden="@(!_showQrCode)" Style="text-decoration:overline;">
|
|
||||||
@AuthenticatorFormatKey
|
|
||||||
</MudText>*@
|
|
||||||
</div>
|
</div>
|
||||||
<div hidden="@(!_showQrCode)">
|
<div hidden="@(!_showQrCode)">
|
||||||
@*<MudDivider />*@
|
|
||||||
<MudText Align="Align.Center" Typo="Typo.subtitle2" Style="text-decoration:none;">
|
<MudText Align="Align.Center" Typo="Typo.subtitle2" Style="text-decoration:none;">
|
||||||
@_authenticatorFormatKey
|
@_authenticatorFormatKey
|
||||||
</MudText>
|
</MudText>
|
||||||
@*<MudDivider />*@
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (_content == Content.Options)
|
@if (_content == Content.Options)
|
||||||
|
|
@ -29,13 +23,6 @@
|
||||||
_showQrCode = false;
|
_showQrCode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@*@if (false) // test
|
|
||||||
{
|
|
||||||
<MudButton OnClick="()=>OnChangeAsync(Content.UseRecovery)" Variant="Variant.Outlined" DisableElevation Size="Size.Large" Color="Color.Info">
|
|
||||||
Recovery
|
|
||||||
</MudButton>
|
|
||||||
}*@
|
|
||||||
|
|
||||||
@if (_enabled)
|
@if (_enabled)
|
||||||
{
|
{
|
||||||
<MudButton OnClick="()=>OnChangeAsync(Content.Validate)" Variant="Variant.Outlined" DisableElevation Size="Size.Large" Color="Color.Info">
|
<MudButton OnClick="()=>OnChangeAsync(Content.Validate)" Variant="Variant.Outlined" DisableElevation Size="Size.Large" Color="Color.Info">
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,27 @@
|
||||||
@page "/"
|
@inherits ComponentBase
|
||||||
@inject NavigationManager NavManager
|
|
||||||
|
<BaseContainer Title="@_title" Breadcrumbs="@_breadcrumbs" LoadData="LoadDataAsync">
|
||||||
|
<Content>
|
||||||
|
<MudGrid>
|
||||||
|
<MudItem xs="12" sm="6" md="3" lg="3">
|
||||||
|
<KeyValueCard T="long" Href="@Navigation.Management.Accounts.Index" Key="Accounts" Value="@_accounts" Icon="@Icons.Material.Filled.SupervisorAccount" IconColor="Color.Primary" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" sm="6" md="3" lg="3">
|
||||||
|
<KeyValueCard T="long" Href="@Navigation.Management.Customers.Index" Key="Customers" Value="@_customers" Icon="@Icons.Material.Outlined.Business" IconColor="Color.Primary" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" sm="6" md="3" lg="3">
|
||||||
|
<KeyValueCard T="long" Href="@Navigation.Management.Hosts.Index" Key="Hosts" Value="@_hosts" Icon="@Icons.Material.Outlined.Devices" IconColor="Color.Primary" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" sm="6" md="3" lg="3">
|
||||||
|
<KeyValueCard T="long" Href="@Navigation.Management.Agents.Index" Key="Agents" Value="@_agents" Icon="@Icons.Material.Outlined.SignalCellularAlt" IconColor="Color.Primary" />
|
||||||
|
</MudItem>
|
||||||
|
</MudGrid>
|
||||||
|
</Content>
|
||||||
|
</BaseContainer>
|
||||||
|
|
||||||
@code{
|
@code{
|
||||||
protected override void OnInitialized()
|
public long _accounts;
|
||||||
{
|
public long _customers;
|
||||||
NavManager.NavigateTo(Navigation.Monitoring.Maintenance.Index);
|
public long _hosts;
|
||||||
}
|
public long _agents;
|
||||||
}
|
}
|
||||||
|
|
@ -4,19 +4,18 @@ using Microsoft.AspNetCore.Components;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
using MudBlazor;
|
using MudBlazor;
|
||||||
|
|
||||||
namespace Insight.Web.Pages.Management.Overview;
|
namespace Insight.Web.Pages;
|
||||||
|
|
||||||
[Route(Navigation.Management.Overview.Index)]
|
[Route(Navigation.Home)]
|
||||||
public partial class Index
|
public partial class Index
|
||||||
{
|
{
|
||||||
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
|
||||||
private readonly string _title = "Management|Insight";
|
private readonly string _title = "Home|Insight";
|
||||||
private readonly List<BreadcrumbItem> _breadcrumbs = new()
|
private readonly List<BreadcrumbItem> _breadcrumbs = new()
|
||||||
{
|
{
|
||||||
new BreadcrumbItem("Home", href: Navigation.Home),
|
new BreadcrumbItem("Home", href: "#", true),
|
||||||
new BreadcrumbItem("Management", href: "#", true)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private async Task LoadDataAsync()
|
private async Task LoadDataAsync()
|
||||||
|
|
@ -0,0 +1,196 @@
|
||||||
|
@using MongoDB.Bson;
|
||||||
|
|
||||||
|
@inject ISnackbar Snackbar
|
||||||
|
@inject IDialogService Dialog
|
||||||
|
|
||||||
|
<MudDrawer @bind-Open="_visible" Anchor="Anchor.End" Elevation="0" Variant="@DrawerVariant.Temporary" ClipMode="DrawerClipMode.Always" Width="400px" Style="max-width:auto;">
|
||||||
|
<MudDrawerHeader>
|
||||||
|
<MudText Typo="Typo.h6">
|
||||||
|
Options
|
||||||
|
</MudText>
|
||||||
|
</MudDrawerHeader>
|
||||||
|
<MudStack Justify="Justify.Center" Class="px-6" Spacing="3">
|
||||||
|
@if (_content == Content.Menu)
|
||||||
|
{
|
||||||
|
<MudButton OnClick="()=>_browserVisible = !_browserVisible" Variant="Variant.Filled" DisableElevation Size="Size.Large" Color="Color.Success">
|
||||||
|
Browser
|
||||||
|
</MudButton>
|
||||||
|
<MudButton OnClick="()=>_content = Content.Save" Variant="Variant.Filled" DisableElevation Size="Size.Large" Color="Color.Success" Disabled>
|
||||||
|
Save
|
||||||
|
</MudButton>
|
||||||
|
<MudButton OnClick="()=>_content = Content.Load" Variant="Variant.Filled" DisableElevation Size="Size.Large" Color="Color.Error">
|
||||||
|
Load
|
||||||
|
</MudButton>
|
||||||
|
}
|
||||||
|
else if (_content == Content.Save)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (_content == Content.Load)
|
||||||
|
{
|
||||||
|
<MudList Clickable="true" Style="max-height: calc(100vh - 160px); overflow-y: scroll;">
|
||||||
|
@foreach (var entity in _loadables)
|
||||||
|
{
|
||||||
|
<MudListItem OnClick="@(async () => await OnSaveItemAsync(entity))">
|
||||||
|
<div class="d-flex flex-row mt-n1 mb-n1">
|
||||||
|
<div>
|
||||||
|
<MudText Typo="Typo.body1" Style="font-weight: normal;">
|
||||||
|
@entity.Key
|
||||||
|
</MudText>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</MudListItem>
|
||||||
|
}
|
||||||
|
</MudList>
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
|
</MudDrawer>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.mud-dialog .mud-dialog-content {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<MudDialog @bind-IsVisible="_browserVisible" Options="_browserOptions">
|
||||||
|
<DialogContent>
|
||||||
|
<MudToolBar Style="height: 48px; background-color:#666699;">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Dark" Edge="Edge.Start" OnClick="()=>_browserDrawer = !_browserDrawer" />
|
||||||
|
</MudToolBar>
|
||||||
|
<MudDrawer @bind-Open="_browserDrawer" ClipMode="DrawerClipMode.Never" Variant="DrawerVariant.Persistent" Elevation="2" Height="calc(50vh)">
|
||||||
|
<MudNavMenu>
|
||||||
|
<MudNavLink Match="NavLinkMatch.All">Store</MudNavLink>
|
||||||
|
<MudNavLink Match="NavLinkMatch.All">Library</MudNavLink>
|
||||||
|
<MudNavLink Match="NavLinkMatch.All">Community</MudNavLink>
|
||||||
|
</MudNavMenu>
|
||||||
|
</MudDrawer>
|
||||||
|
<MudList Clickable="true" DisablePadding Style="width: calc(50vw); height: calc(50vh); overflow-y: auto;">
|
||||||
|
<MudListItem Text="Item 1" Icon="@Icons.Material.Filled.Inbox" />
|
||||||
|
<MudListItem Text="Item 2" Icon="@Icons.Material.Filled.Send" />
|
||||||
|
<MudListItem Text="Item 1" Icon="@Icons.Material.Filled.Inbox" />
|
||||||
|
<MudListItem Text="Item 2" Icon="@Icons.Material.Filled.Send" />
|
||||||
|
<MudListItem Text="Item 1" Icon="@Icons.Material.Filled.Inbox" />
|
||||||
|
<MudListItem Text="Item 2" Icon="@Icons.Material.Filled.Send" />
|
||||||
|
<MudListItem Text="Item 1" Icon="@Icons.Material.Filled.Inbox" />
|
||||||
|
<MudListItem Text="Item 2" Icon="@Icons.Material.Filled.Send" />
|
||||||
|
<MudListItem Text="Item 1" Icon="@Icons.Material.Filled.Inbox" />
|
||||||
|
<MudListItem Text="Item 2" Icon="@Icons.Material.Filled.Send" />
|
||||||
|
<MudListItem Text="Item 1" Icon="@Icons.Material.Filled.Inbox" />
|
||||||
|
<MudListItem Text="Item 2" Icon="@Icons.Material.Filled.Send" />
|
||||||
|
<MudListItem Text="Item 1" Icon="@Icons.Material.Filled.Inbox" />
|
||||||
|
<MudListItem Text="Item 2" Icon="@Icons.Material.Filled.Send" />
|
||||||
|
<MudListItem Text="Item 1" Icon="@Icons.Material.Filled.Inbox" />
|
||||||
|
<MudListItem Text="Item 2" Icon="@Icons.Material.Filled.Send" />
|
||||||
|
</MudList>
|
||||||
|
|
||||||
|
|
||||||
|
@* <MudStack Row="true">
|
||||||
|
<MudPaper Width="300px">
|
||||||
|
<MudList Clickable="true">
|
||||||
|
<MudListItem Text="Neutral" Value="1" />
|
||||||
|
<MudListItem Text="Good">
|
||||||
|
<NestedList>
|
||||||
|
<MudListItem Text="Frodo Baggins" Value="2" />
|
||||||
|
<MudListItem Text="Harry Potter" Value="3" />
|
||||||
|
</NestedList>
|
||||||
|
</MudListItem>
|
||||||
|
<MudListItem Text="Evil">
|
||||||
|
<NestedList>
|
||||||
|
<MudListItem Text="Sauron" Value="5" />
|
||||||
|
<MudListItem Text="Voldemort" Value="6" />
|
||||||
|
<MudListItem Text="Mckaragoz" Value="7" />
|
||||||
|
<MudListItem Text="Sauron" Value="8" />
|
||||||
|
<MudListItem Text="Voldemort" Value="9" />
|
||||||
|
<MudListItem Text="Mckaragoz" Value="10" />
|
||||||
|
</NestedList>
|
||||||
|
</MudListItem>
|
||||||
|
</MudList>
|
||||||
|
</MudPaper>
|
||||||
|
<MudPaper Class="pe-4" Width="calc(100vw - 50px)">
|
||||||
|
<MudList Clickable="true">
|
||||||
|
<MudListItem Text="Item 1" Icon="@Icons.Material.Filled.Inbox" />
|
||||||
|
<MudListItem Text="Item 2" Icon="@Icons.Material.Filled.Send" />
|
||||||
|
<MudListItem Text="Item 3" />
|
||||||
|
<MudListItem Text="Item 4" />
|
||||||
|
<MudListItem Text="Item 5" />
|
||||||
|
<MudListItem Text="Item 6" />
|
||||||
|
<MudListItem Text="Item 7" />
|
||||||
|
<MudListItem Text="Item 8" />
|
||||||
|
</MudList>
|
||||||
|
</MudPaper>
|
||||||
|
</MudStack> *@
|
||||||
|
</DialogContent>
|
||||||
|
</MudDialog>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private DialogOptions _browserOptions = new() { FullWidth = false, MaxWidth = MaxWidth.Large, FullScreen = false, NoHeader = true };
|
||||||
|
private bool _browserVisible;
|
||||||
|
private bool _browserDrawer = true;
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
[Parameter] public EventCallback<ScriptItem> OnChanges { get; set; }
|
||||||
|
|
||||||
|
private Content _content = Content.Menu;
|
||||||
|
|
||||||
|
private enum Content { Menu = 0, Save = 1, Load = 3 }
|
||||||
|
private bool _visible;
|
||||||
|
private ScriptItem? _currentItem;
|
||||||
|
|
||||||
|
private List<ScriptItem> _loadables = new();
|
||||||
|
|
||||||
|
public async Task ToggleAsync(string? id)
|
||||||
|
{
|
||||||
|
_content = Content.Menu;
|
||||||
|
_visible = !_visible;
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ToggleBrowserAsync()
|
||||||
|
{
|
||||||
|
_visible = !_visible;
|
||||||
|
_browserVisible = !_browserVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnSaveItemAsync(ScriptItem item)
|
||||||
|
{
|
||||||
|
_currentItem = item;
|
||||||
|
_visible = false;
|
||||||
|
|
||||||
|
Notification.Information(Snackbar, $"Save Item ({item.Key})");
|
||||||
|
|
||||||
|
// base64 encode
|
||||||
|
var valueBytes = System.Text.Encoding.UTF8.GetBytes(item.Value);
|
||||||
|
var valueBase64 = System.Convert.ToBase64String(valueBytes);
|
||||||
|
|
||||||
|
// save to database
|
||||||
|
|
||||||
|
|
||||||
|
await OnChanges.InvokeAsync(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnLoadItemAsync(ScriptItem item)
|
||||||
|
{
|
||||||
|
_currentItem = item;
|
||||||
|
_visible = false;
|
||||||
|
|
||||||
|
Notification.Information(Snackbar, $"Load Item ({item.Key})");
|
||||||
|
|
||||||
|
await OnChanges.InvokeAsync(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
_loadables.Add(new ScriptItem { Key = "Date Test", Value = "Get-Date"});
|
||||||
|
|
||||||
|
var ipmi64 = "U3RhcnQtUHJvY2VzcyAtRmlsZVBhdGggIkM6XFxQcm9ncmFtRGF0YVxcV2VibWF0aWNcXEluc2lnaHRcXEFnZW50XFx0b29sc1xcaXBtaVxcaXBtaS5leGUiIC1Bcmd1bWVudExpc3QgIi1wbWluZm8iIC1XYWl0IC1Ob05ld1dpbmRvdyAtUmVkaXJlY3RTdGFuZGFyZE91dHB1dCAiQzpcdGVtcC50eHQiOyAKJGRhdGEgPSBHZXQtQ29udGVudCAiQzpcdGVtcC50eHQiCgokbGluZXMgPSAkZGF0YSAtc3BsaXQgJyxccypcbicgfCBXaGVyZS1PYmplY3QgeyAkXyAtbmUgIiIgfQoKJG1vZHVsZXMgPSBAe30KJGN1cnJlbnRNb2R1bGUgPSAkbnVsbAoKZm9yZWFjaCAoJGxpbmUgaW4gJGxpbmVzKSB7CiAgICBpZiAoJGxpbmUgLW1hdGNoICJcW1NsYXZlQWRkcmVzcyA9IChcdyspXF0iKSB7CiAgICAgICAgJHNsYXZlQWRkcmVzcyA9ICRtYXRjaGVzWzFdCiAgICAgICAgJG1vZHVsZU5hbWUgPSAkbGluZSAtcmVwbGFjZSAiLipcWyhNb2R1bGUgXGQrKVxdIiwgJyQxJwogICAgICAgICRjdXJyZW50TW9kdWxlID0gIiRzbGF2ZUFkZHJlc3MgJG1vZHVsZU5hbWUiCiAgICAgICAgJG1vZHVsZXNbJGN1cnJlbnRNb2R1bGVdID0gQHt9CiAgICB9IGVsc2VpZiAoJGxpbmUgLW5vdG1hdGNoICJeXHMqJHxeSXRlbXxeLS0tLSIgLWFuZCAkY3VycmVudE1vZHVsZSkgewogICAgICAgICRwYXJ0cyA9ICRsaW5lIC1zcGxpdCAnXHwnLCAyCiAgICAgICAgaWYgKCRwYXJ0cy5MZW5ndGggLWVxIDIpIHsKICAgICAgICAgICAgJGtleSA9ICRwYXJ0c1swXS5UcmltKCkKICAgICAgICAgICAgJHZhbHVlID0gJHBhcnRzWzFdLlRyaW0oKQogICAgICAgICAgICAkbW9kdWxlc1skY3VycmVudE1vZHVsZV1bJGtleV0gPSAkdmFsdWUKICAgICAgICB9CiAgICB9Cn0KCiMgQ29udmVydCB0byBKU09OCiRqc29uID0gJG1vZHVsZXMgfCBDb252ZXJ0VG8tSnNvbiAtRGVwdGggMwokanNvbg==";
|
||||||
|
_loadables.Add(new ScriptItem { Key = "IPMI (Power)", Value = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(ipmi64)) });
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ScriptItem
|
||||||
|
{
|
||||||
|
public string Key { get; set; }
|
||||||
|
public string Value { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,23 +4,65 @@
|
||||||
<Content>
|
<Content>
|
||||||
@if (_model is not null)
|
@if (_model is not null)
|
||||||
{
|
{
|
||||||
<MudGrid>
|
<MudToolBar Dense DisableGutters>
|
||||||
<MudItem xs="12" sm="12" md="12" lg="12">
|
<MudButton OnClick="()=>_activeWindow = 0" Variant="Variant.Filled" StartIcon="@Icons.Material.Filled.Build" Color="_activeWindow == 0 ? Color.Info : Color.Surface" Size="Size.Small" DisableElevation>Script</MudButton>
|
||||||
<MudTextField T="string" Label="Request" Variant="Variant.Outlined" @bind-Text="_model.Request.RequestData" Lines="10" />
|
<MudButton OnClick="()=>_activeWindow = 1" Variant="Variant.Filled" StartIcon="@Icons.Material.Filled.Api" Color="_activeWindow == 1 ? Color.Info : Color.Surface" Size="Size.Small" DisableElevation Class="ml-2">Result</MudButton>
|
||||||
</MudItem>
|
<MudSpacer />
|
||||||
|
<MudIconButton OnClick="()=>_optionDialog?.ToggleAsync(null)" Icon="@Icons.Material.Filled.Settings" Variant="Variant.Text" DisableElevation Class="mr-2"></MudIconButton>
|
||||||
|
<MudButton Disabled="@_running" OnClick="()=>RunAsync(default)" Variant="Variant.Filled" Color="Color.Success" Size="Size.Small" IconSize="Size.Small" DisableElevation EndIcon="@(_running ? "" : @Icons.Material.Filled.Send)">
|
||||||
|
@if (_running)
|
||||||
|
{
|
||||||
|
<MudProgressCircular Size="Size.Small" Indeterminate="true" Class="mr-2" Style="height:16px; width:16px;" />
|
||||||
|
<MudText>Processing</MudText>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudText>Execute</MudText>
|
||||||
|
}
|
||||||
|
</MudButton>
|
||||||
|
@if (_running)
|
||||||
|
{
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Error" Size="Size.Small" DisableElevation Class="ml-2">Abort</MudButton>
|
||||||
|
}
|
||||||
|
</MudToolBar>
|
||||||
|
|
||||||
<MudItem xs="12" sm="12" md="12" lg="12">
|
<MudPaper Outlined Height="calc(100vh - 200px)">
|
||||||
|
@if (_activeWindow == 0)
|
||||||
|
{
|
||||||
|
<MudTextField T="string" @bind-Text="_model.Request.RequestData" spellcheck="false"
|
||||||
|
Placeholder="Request"
|
||||||
|
Variant="Variant.Text"
|
||||||
|
AutoGrow
|
||||||
|
Disabled="@(_running ? true : false)"
|
||||||
|
DisableUnderLine
|
||||||
|
Class="px-3"
|
||||||
|
Style="height:calc(100vh - 210px); overflow:scroll; align-items:normal; margin-top:0px;" />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
@if (_model.Response.ResponseError ?? false)
|
@if (_model.Response.ResponseError ?? false)
|
||||||
{
|
{
|
||||||
<MudText>Response contains Errors</MudText>
|
<MudText>Response contains Errors</MudText>
|
||||||
}
|
}
|
||||||
<MudTextField T="string" Label="Response" Variant="Variant.Outlined" @bind-Text="_model.Response.ResponseData" Lines="10" />
|
<MudTextField T="string" @bind-Text="_model.Response.ResponseData" spellcheck="false"
|
||||||
</MudItem>
|
Placeholder="Response"
|
||||||
|
Variant="Variant.Text"
|
||||||
<MudItem xs="12" md="12" lg="12" Class="d-flex justify-center">
|
AutoGrow
|
||||||
<MudButton OnClick="SubmitAsync" Variant="Variant.Filled" Color="Color.Surface" Size="Size.Large" Style="width: 100%;">Query</MudButton>
|
ReadOnly
|
||||||
</MudItem>
|
DisableUnderLine
|
||||||
</MudGrid>
|
Class="px-3"
|
||||||
|
Style="height:calc(100vh - 210px); overflow:scroll; align-items:normal; margin-top:0px;" />
|
||||||
|
}
|
||||||
|
</MudPaper>
|
||||||
}
|
}
|
||||||
</Content>
|
</Content>
|
||||||
</BaseContainer>
|
</BaseContainer>
|
||||||
|
|
||||||
|
<ConsoleOptionDialog @ref="_optionDialog" OnChanges="(x) => OnRefreshAsync(x)" />
|
||||||
|
|
||||||
|
@code{
|
||||||
|
private ConsoleOptionDialog? _optionDialog;
|
||||||
|
|
||||||
|
private int _activeWindow = 0;
|
||||||
|
private bool _running = false;
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,8 @@ using Microsoft.AspNetCore.Components;
|
||||||
using MongoDB.Bson;
|
using MongoDB.Bson;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
using MudBlazor;
|
using MudBlazor;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Threading;
|
||||||
using Vaitr.Bus;
|
using Vaitr.Bus;
|
||||||
using Vaitr.Network;
|
using Vaitr.Network;
|
||||||
|
|
||||||
|
|
@ -27,13 +29,7 @@ public partial class Index
|
||||||
|
|
||||||
private readonly string _id = ObjectId.GenerateNewId().ToString();
|
private readonly string _id = ObjectId.GenerateNewId().ToString();
|
||||||
private readonly List<BreadcrumbItem> _breadcrumbs = new();
|
private readonly List<BreadcrumbItem> _breadcrumbs = new();
|
||||||
private readonly IndexViewModel _model = new();
|
private readonly ViewModel _model = new();
|
||||||
private readonly List<IDisposable> _subscriptions = new();
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
_subscriptions.Add(Bus.SubscribeAsync<Proxy<Response>>(OnQueryResultAsync, p => p.Message?.RequestId == _id));
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LoadDataAsync()
|
private async Task LoadDataAsync()
|
||||||
{
|
{
|
||||||
|
|
@ -72,12 +68,48 @@ public partial class Index
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SubmitAsync()
|
private async Task OnRefreshAsync(ConsoleOptionDialog.ScriptItem item)
|
||||||
{
|
{
|
||||||
if (_model.Request.RequestData is null || WebPool.Any() is false) return;
|
_model.Request.RequestData = item.Value;
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task RunAsync(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
if (_model.Request.RequestData is null)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Invalid Request Data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WebPool.Any() is false)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Client unreachable");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_running = true;
|
||||||
|
|
||||||
|
var timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||||
|
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(30), timeoutCts.Token);
|
||||||
|
|
||||||
|
// subscribe response
|
||||||
|
using var token = Bus.SubscribeAsync<Proxy<Response>>(async (response, ctc) =>
|
||||||
|
{
|
||||||
|
_model.Response.ResponseError = response.Message?.ResponseError;
|
||||||
|
_model.Response.ResponseData = response.Message?.ResponseData;
|
||||||
|
|
||||||
|
timeoutCts.Cancel();
|
||||||
|
|
||||||
|
_activeWindow = 1;
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}, p => p.Message?.RequestId == _id);
|
||||||
|
|
||||||
|
// send request
|
||||||
await WebPool.First().Value.SendAsync(new Proxy<Request>
|
await WebPool.First().Value.SendAsync(new Proxy<Request>
|
||||||
{
|
{
|
||||||
ProxyId = HostId,
|
ProxyId = HostId,
|
||||||
|
|
@ -88,23 +120,21 @@ public partial class Index
|
||||||
}
|
}
|
||||||
}, default);
|
}, default);
|
||||||
|
|
||||||
Notification.Information(Snackbar, "Sent Query Command");
|
Notification.Information(Snackbar, "Sent Script...");
|
||||||
|
|
||||||
|
await Task.WhenAny(timeoutTask);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Notification.Error(Snackbar, ex.Message);
|
Notification.Error(Snackbar, ex.Message);
|
||||||
}
|
}
|
||||||
}
|
finally
|
||||||
|
|
||||||
private async ValueTask OnQueryResultAsync(Proxy<Response> proxy, CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
_model.Response.ResponseError = proxy.Message?.ResponseError;
|
_running = false;
|
||||||
_model.Response.ResponseData = proxy.Message?.ResponseData;
|
}
|
||||||
|
|
||||||
await InvokeAsync(StateHasChanged);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class IndexViewModel
|
private class ViewModel
|
||||||
{
|
{
|
||||||
public readonly Request Request = new();
|
public readonly Request Request = new();
|
||||||
public readonly Response Response = new();
|
public readonly Response Response = new();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<MudDialog op>
|
||||||
|
<DialogContent>
|
||||||
|
Script Browser
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<MudButton OnClick="Cancel">Cancel</MudButton>
|
||||||
|
<MudButton Color="Color.Primary" OnClick="Submit">Ok</MudButton>
|
||||||
|
</DialogActions>
|
||||||
|
</MudDialog>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[CascadingParameter] MudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
|
void Submit() => MudDialog.Close(DialogResult.Ok(true));
|
||||||
|
void Cancel() => MudDialog.Cancel();
|
||||||
|
}
|
||||||
|
|
@ -87,7 +87,7 @@
|
||||||
</MudButton>
|
</MudButton>
|
||||||
</PickerActions>
|
</PickerActions>
|
||||||
</MudDateRangePicker>
|
</MudDateRangePicker>
|
||||||
<MudSelect @bind-Value="FilterCategory" Label="Category">
|
<MudSelect @bind-Value="FilterCategory" Label="Category" AnchorOrigin="Origin.BottomCenter" >
|
||||||
<MudSelectItem T="CategoryEnum?" Value="null">
|
<MudSelectItem T="CategoryEnum?" Value="null">
|
||||||
None
|
None
|
||||||
</MudSelectItem>
|
</MudSelectItem>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
<h3>Index</h3>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
|
|
||||||
namespace Insight.Web.Pages.Management;
|
|
||||||
|
|
||||||
//[Route(Navigation.Monitoring.Index)]
|
|
||||||
public partial class Index
|
|
||||||
{
|
|
||||||
[Inject] private NavigationManager NavManager { get; init; } = default!;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
//NavManager.NavigateTo(Navigation.Management.Overview.Index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
@inherits ComponentBase
|
|
||||||
|
|
||||||
<BaseContainer Title="@_title" Breadcrumbs="@_breadcrumbs" LoadData="LoadDataAsync">
|
|
||||||
<Content>
|
|
||||||
<MudGrid>
|
|
||||||
<MudItem xs="12" sm="6" md="3" lg="3">
|
|
||||||
<KeyValueCard T="long" Href="@Navigation.Management.Accounts.Index" Key="Accounts" Value="@_accounts" Icon="@Icons.Material.Filled.SupervisorAccount" IconColor="Color.Primary" />
|
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="12" sm="6" md="3" lg="3">
|
|
||||||
<KeyValueCard T="long" Href="@Navigation.Management.Customers.Index" Key="Customers" Value="@_customers" Icon="@Icons.Material.Outlined.Business" IconColor="Color.Primary" />
|
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="12" sm="6" md="3" lg="3">
|
|
||||||
<KeyValueCard T="long" Href="@Navigation.Management.Hosts.Index" Key="Hosts" Value="@_hosts" Icon="@Icons.Material.Outlined.Devices" IconColor="Color.Primary" />
|
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="12" sm="6" md="3" lg="3">
|
|
||||||
<KeyValueCard T="long" Href="@Navigation.Management.Agents.Index" Key="Agents" Value="@_agents" Icon="@Icons.Material.Outlined.SignalCellularAlt" IconColor="Color.Primary" />
|
|
||||||
</MudItem>
|
|
||||||
</MudGrid>
|
|
||||||
</Content>
|
|
||||||
</BaseContainer>
|
|
||||||
|
|
||||||
@code{
|
|
||||||
public long _accounts;
|
|
||||||
public long _customers;
|
|
||||||
public long _hosts;
|
|
||||||
public long _agents;
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
@inherits ComponentBase
|
||||||
|
|
||||||
|
@using Vaitr.Scheduler;
|
||||||
|
|
||||||
|
<BaseContainer Title="@Title" Breadcrumbs="@Breadcrumbs" LoadData="LoadDataAsync">
|
||||||
|
<Content>
|
||||||
|
@if (Job is not null)
|
||||||
|
{
|
||||||
|
<MudGrid>
|
||||||
|
<MudItem xs="12" sm="6" md="6" lg="3">
|
||||||
|
<KeyValueCard T="string" Key="Name" Value="@Job.Name" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" sm="6" md="6" lg="3">
|
||||||
|
<KeyValueCard T="TaskState" Key="State" Value="@Job.State" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" sm="6" md="6" lg="3">
|
||||||
|
<KeyValueCard T="TimeSpan?" Key="Timeout" Value="@Job.Timeout" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" sm="6" md="6" lg="3">
|
||||||
|
<KeyValueCard T="DateTime?" Key="Executed" Value="@Job.Executed" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" sm="6" md="6" lg="3">
|
||||||
|
<KeyValueCard T="string" Key="Status" Value="@(Job.Disabled ? "Disabled" : "Enabled")" ValueColor="@(Job.Disabled ? Color.Error : Color.Success)" />
|
||||||
|
</MudItem>
|
||||||
|
@* <MudItem xs="12" sm="6" md="6" lg="3">
|
||||||
|
<KeyValueCard T="int" Href="@Navigation.Management.Jobs.HostsHref(JobId)" Key="Hosts" Value="@(Job?.Hosts?.Count() ?? 0)" Icon="@Icons.Material.Outlined.Devices" IconColor="Color.Primary" />
|
||||||
|
</MudItem> *@
|
||||||
|
</MudGrid>
|
||||||
|
}
|
||||||
|
</Content>
|
||||||
|
</BaseContainer>
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
using static MudBlazor.CategoryTypes;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Jobs;
|
||||||
|
|
||||||
|
[Route(Navigation.Management.Scheduler.Jobs.Details)]
|
||||||
|
public partial class Details
|
||||||
|
{
|
||||||
|
[Parameter] public string? JobId { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private NavigationManager NavigationManager { get; init; } = default!;
|
||||||
|
|
||||||
|
private string Title { get; set; } = Global.Name;
|
||||||
|
private List<BreadcrumbItem> Breadcrumbs { get; } = new();
|
||||||
|
private JobEntity? Job { get; set; }
|
||||||
|
|
||||||
|
private async Task LoadDataAsync()
|
||||||
|
{
|
||||||
|
Breadcrumbs.Clear();
|
||||||
|
Job = null;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(JobId) || ObjectId.TryParse(JobId, out var jobId) is false)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Jobs.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Home", href: Navigation.Home));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Scheduler", href: Navigation.Management.Scheduler.Index));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Jobs", href: Navigation.Management.Scheduler.Jobs.Index));
|
||||||
|
|
||||||
|
StateHasChanged();
|
||||||
|
|
||||||
|
Job = await Database.Job()
|
||||||
|
.Aggregate()
|
||||||
|
.Match(Builders<JobEntity>.Filter.Eq(p => p.Id, JobId))
|
||||||
|
//.Lookup<CustomerEntity, HostEntity, CustomerEntity>(Database.Host(), p => p.Id, p => p.Customer, p => p.Hosts)
|
||||||
|
.FirstOrDefaultAsync(default);
|
||||||
|
|
||||||
|
if (Job is null)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Jobs.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Title = $"Job » {Job.Name ?? Job.Id}|Insight";
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem(Job.Name ?? Job.Id, href: "#", true));
|
||||||
|
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
@inherits ComponentBase
|
||||||
|
|
||||||
|
<TableContainer T="ViewModel"
|
||||||
|
@ref="_container"
|
||||||
|
@bind-Search="_search"
|
||||||
|
Title="@_title"
|
||||||
|
Breadcrumbs="@_breadcrumbs"
|
||||||
|
Data="LoadDataAsync"
|
||||||
|
OnAdd="()=>_createDialog?.ToggleAsync()">
|
||||||
|
<Header>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Name" T="ViewModel">
|
||||||
|
Name
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Tasks" T="ViewModel">
|
||||||
|
Tasks
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Triggers" T="ViewModel">
|
||||||
|
Triggers
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Executed" T="ViewModel">
|
||||||
|
Executed
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="State" T="ViewModel">
|
||||||
|
State
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Status" T="ViewModel">
|
||||||
|
Status
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
</Header>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd DataLabel="Name">
|
||||||
|
<MudLink Href="@Navigation.Management.Scheduler.Jobs.DetailsHref(context?.Id)" Typo="Typo.inherit" Underline="Underline.None">
|
||||||
|
@context?.Name
|
||||||
|
</MudLink>
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Tasks">
|
||||||
|
@{
|
||||||
|
<MudLink Href="@Navigation.Management.Scheduler.Jobs.TasksHref(context.Id)" Typo="Typo.inherit" Underline="Underline.None">
|
||||||
|
@(context.Tasks?.ToString() ?? "0")
|
||||||
|
</MudLink>
|
||||||
|
}
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Triggers">
|
||||||
|
@{
|
||||||
|
<MudLink Href="@Navigation.Management.Scheduler.Jobs.TriggersHref(context.Id)" Typo="Typo.inherit" Underline="Underline.None">
|
||||||
|
@(context.Triggers?.ToString() ?? "0")
|
||||||
|
</MudLink>
|
||||||
|
}
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Executed">
|
||||||
|
@context?.Executed.ToLocalTime()
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="State">
|
||||||
|
@context.State
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Status">
|
||||||
|
<MudText Color="(context.Disabled ? Color.Error : Color.Success)" Typo="Typo.inherit">
|
||||||
|
@(context.Disabled ? "Disabled" : "Enabled")
|
||||||
|
</MudText>
|
||||||
|
</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
<ActionTemplate>
|
||||||
|
<MudMenuItem OnClick="@(()=>_editDialog?.ToggleAsync(context.Id))">
|
||||||
|
Edit
|
||||||
|
</MudMenuItem>
|
||||||
|
<MudMenuItem OnClick="@(()=>_deleteDialog?.ToggleAsync(context.Id))">
|
||||||
|
Delete
|
||||||
|
</MudMenuItem>
|
||||||
|
</ActionTemplate>
|
||||||
|
</TableContainer>
|
||||||
|
|
||||||
|
<JobCreateDialog @ref="_createDialog" OnChanges="OnRefreshAsync" />
|
||||||
|
<JobEditDialog @ref="_editDialog" OnChanges="OnRefreshAsync" />
|
||||||
|
<JobDeleteDialog @ref="_deleteDialog" OnChanges="OnRefreshAsync" />
|
||||||
|
|
||||||
|
@code{
|
||||||
|
private JobCreateDialog? _createDialog;
|
||||||
|
private JobEditDialog? _editDialog;
|
||||||
|
private JobDeleteDialog? _deleteDialog;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Components.Containers;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Vaitr.Scheduler;
|
||||||
|
using SortDirection = MudBlazor.SortDirection;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Jobs;
|
||||||
|
|
||||||
|
[Route(Navigation.Management.Scheduler.Jobs.Index)]
|
||||||
|
public partial class Index
|
||||||
|
{
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
|
||||||
|
private readonly List<BreadcrumbItem> _breadcrumbs = new();
|
||||||
|
|
||||||
|
private TableContainer<ViewModel>? _container;
|
||||||
|
private string _title = Global.Name;
|
||||||
|
private string? _search;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
_title = "Jobs|Insight";
|
||||||
|
_breadcrumbs.Add(new BreadcrumbItem("Home", href: Navigation.Home));
|
||||||
|
_breadcrumbs.Add(new BreadcrumbItem("Scheduler", href: Navigation.Management.Scheduler.Index));
|
||||||
|
_breadcrumbs.Add(new BreadcrumbItem("Jobs", href: Navigation.Management.Scheduler.Jobs.Index, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<TableData<ViewModel>> LoadDataAsync(TableState state)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var search = Builders<JobEntity>.Filter.Empty;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(_search) is false)
|
||||||
|
{
|
||||||
|
var regex = new BsonRegularExpression(new Regex(_search, RegexOptions.IgnoreCase));
|
||||||
|
search &= Builders<JobEntity>.Filter.Regex(x => x.Name, regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = Database.Job()
|
||||||
|
.Aggregate()
|
||||||
|
.Match(search)
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$lookup", new BsonDocument
|
||||||
|
{
|
||||||
|
{ "from", "job_task" },
|
||||||
|
{ "localField", "_id" },
|
||||||
|
{ "foreignField", "_job" },
|
||||||
|
{ "as", "tasks" }
|
||||||
|
}))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$addFields",
|
||||||
|
new BsonDocument("tasks", new BsonDocument("$size", "$tasks"))
|
||||||
|
))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$lookup", new BsonDocument
|
||||||
|
{
|
||||||
|
{ "from", "job_trigger" },
|
||||||
|
{ "localField", "_id" },
|
||||||
|
{ "foreignField", "_job" },
|
||||||
|
{ "as", "triggers" }
|
||||||
|
}))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$addFields",
|
||||||
|
new BsonDocument("triggers", new BsonDocument("$size", "$triggers"))
|
||||||
|
))
|
||||||
|
.Sort(state.SortDirection switch
|
||||||
|
{
|
||||||
|
SortDirection.Ascending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Ascending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Ascending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
SortDirection.Descending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Descending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Descending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
_ => Builders<BsonDocument>.Sort.Ascending("name")
|
||||||
|
});
|
||||||
|
|
||||||
|
var countResult = await query.Count().FirstOrDefaultAsync(default);
|
||||||
|
var itemResult = await query.Skip(state.Page * state.PageSize).Limit(state.PageSize).ToListAsync(default);
|
||||||
|
|
||||||
|
return new TableData<ViewModel>()
|
||||||
|
{
|
||||||
|
TotalItems = countResult is null ? 0 : (int)countResult.Count,
|
||||||
|
Items = itemResult.Select(x => BsonSerializer.Deserialize<ViewModel>(x))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
return new TableData<ViewModel>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnRefreshAsync()
|
||||||
|
{
|
||||||
|
if (_container is null) return;
|
||||||
|
await _container.RefreshAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
private class ViewModel : JobEntity
|
||||||
|
{
|
||||||
|
[BsonElement("tasks")]
|
||||||
|
public int? Tasks { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("triggers")]
|
||||||
|
public int? Triggers { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
@using MongoDB.Bson;
|
||||||
|
@using Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
<MudDrawer @bind-Open="_visible" Anchor="Anchor.End" Elevation="0" Variant="@DrawerVariant.Temporary" ClipMode="DrawerClipMode.Always" Width="400px" Style="max-width:auto;">
|
||||||
|
<MudDrawerHeader>
|
||||||
|
<MudText Typo="Typo.h6">
|
||||||
|
Create Job
|
||||||
|
</MudText>
|
||||||
|
</MudDrawerHeader>
|
||||||
|
<MudStack Class="px-6">
|
||||||
|
@if (_model is not null)
|
||||||
|
{
|
||||||
|
<EditForm Model="@_model" OnValidSubmit="SubmitAsync">
|
||||||
|
<DataAnnotationsValidator />
|
||||||
|
<MudStack Spacing="5">
|
||||||
|
<MudTextField T="string" @bind-Value="_model.Name" For="()=>_model.Name" Label="Name" Variant="Variant.Text" Margin="Margin.Dense" AutoFocus Clearable />
|
||||||
|
<MudTextField T="string" @bind-Value="_model.Description" For="()=>_model.Description" Label="Description" Variant="Variant.Text" Margin="Margin.Dense" Clearable />
|
||||||
|
@* <MudSelect T="ScheduleMode" @bind-Value="_model.Mode">
|
||||||
|
@foreach (ScheduleMode state in Enum.GetValues(typeof(ScheduleMode)))
|
||||||
|
{
|
||||||
|
<MudSelectItem T="ScheduleMode" Value="@state">
|
||||||
|
@state
|
||||||
|
</MudSelectItem>
|
||||||
|
}
|
||||||
|
</MudSelect> *@
|
||||||
|
</MudStack>
|
||||||
|
<MudStack Justify="Justify.Center" Row Class="mt-7">
|
||||||
|
<MudButton OnClick="()=>_visible = false" Variant="Variant.Outlined" DisableElevation Size="Size.Large" Color="Color.Surface">
|
||||||
|
Cancel
|
||||||
|
</MudButton>
|
||||||
|
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" DisableElevation Size="Size.Large" Color="Color.Success" Style="width: 100%;">
|
||||||
|
Create
|
||||||
|
</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
</EditForm>
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
|
</MudDrawer>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private bool _visible;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Jobs;
|
||||||
|
|
||||||
|
public partial class JobCreateDialog
|
||||||
|
{
|
||||||
|
[Parameter] public EventCallback OnChanges { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private ILogger<JobCreateDialog> Logger { get; init; } = default!;
|
||||||
|
|
||||||
|
private JobEntity? _model;
|
||||||
|
|
||||||
|
public async void ToggleAsync()
|
||||||
|
{
|
||||||
|
_model = new();
|
||||||
|
_visible = !_visible;
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SubmitAsync()
|
||||||
|
{
|
||||||
|
if (_model is null) return;
|
||||||
|
|
||||||
|
_model.Insert = DateTime.Now;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Database.Job()
|
||||||
|
.InsertOneAsync(_model, cancellationToken: default)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
Notification.Success(Snackbar);
|
||||||
|
|
||||||
|
if (OnChanges.HasDelegate)
|
||||||
|
{
|
||||||
|
await InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
await OnChanges.InvokeAsync(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
Logger.LogError(ex.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
@using MongoDB.Bson;
|
||||||
|
|
||||||
|
<MudDrawer @bind-Open="_visible" Anchor="Anchor.End" Elevation="0" Variant="@DrawerVariant.Temporary" ClipMode="DrawerClipMode.Always" Width="400px" Style="max-width:auto;">
|
||||||
|
<MudDrawerHeader>
|
||||||
|
<MudText Typo="Typo.h6">
|
||||||
|
Delete Job
|
||||||
|
</MudText>
|
||||||
|
</MudDrawerHeader>
|
||||||
|
<MudStack Class="px-6">
|
||||||
|
@if (_model is not null)
|
||||||
|
{
|
||||||
|
<EditForm Model="@_model" OnValidSubmit="SubmitAsync">
|
||||||
|
<MudStack Spacing="5">
|
||||||
|
<MudTextField T="string" @bind-Value="_model.Name" For="()=>_model.Name" Label="Name" Variant="Variant.Text" Margin="Margin.Dense" ReadOnly />
|
||||||
|
</MudStack>
|
||||||
|
<MudStack Justify="Justify.Center" Row Class="mt-7">
|
||||||
|
<MudButton OnClick="()=>_visible = false" Variant="Variant.Outlined" DisableElevation Size="Size.Large" Color="Color.Surface">
|
||||||
|
Cancel
|
||||||
|
</MudButton>
|
||||||
|
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" DisableElevation Size="Size.Large" Color="Color.Error" Style="width: 100%;">
|
||||||
|
Delete
|
||||||
|
</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
</EditForm>
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
|
</MudDrawer>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private bool _visible;
|
||||||
|
public void Toggle()
|
||||||
|
{
|
||||||
|
_visible = !_visible;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Jobs;
|
||||||
|
|
||||||
|
public partial class JobDeleteDialog
|
||||||
|
{
|
||||||
|
[Parameter] public EventCallback OnChanges { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private ILogger<JobDeleteDialog> Logger { get; init; } = default!;
|
||||||
|
|
||||||
|
private JobEntity? _model;
|
||||||
|
|
||||||
|
public async void ToggleAsync(string? id)
|
||||||
|
{
|
||||||
|
if (id is null) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_model = await Database.Job().Find(p => p.Id == id).FirstAsync();
|
||||||
|
_visible = !_visible;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
}
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SubmitAsync()
|
||||||
|
{
|
||||||
|
if (_model is null) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Database.Job()
|
||||||
|
.DeleteOneAsync(Builders<JobEntity>
|
||||||
|
.Filter.Eq(p => p.Id, _model.Id),
|
||||||
|
cancellationToken: default).ConfigureAwait(false);
|
||||||
|
|
||||||
|
Notification.Success(Snackbar);
|
||||||
|
|
||||||
|
if (OnChanges.HasDelegate)
|
||||||
|
{
|
||||||
|
await InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
await OnChanges.InvokeAsync(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
Logger.LogError(ex.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
@using MongoDB.Bson;
|
||||||
|
|
||||||
|
<MudDrawer @bind-Open="_visible" Anchor="Anchor.End" Elevation="0" Variant="@DrawerVariant.Temporary" ClipMode="DrawerClipMode.Always" Width="400px" Style="max-width:auto;">
|
||||||
|
<MudDrawerHeader>
|
||||||
|
<MudText Typo="Typo.h6">
|
||||||
|
Edit Job
|
||||||
|
</MudText>
|
||||||
|
</MudDrawerHeader>
|
||||||
|
<MudStack Class="px-6">
|
||||||
|
@if (_model is not null)
|
||||||
|
{
|
||||||
|
<EditForm Model="@_model" OnValidSubmit="SubmitAsync">
|
||||||
|
<DataAnnotationsValidator />
|
||||||
|
<MudStack Spacing="5">
|
||||||
|
<MudTextField T="string" @bind-Value="_model.Name" For="()=>_model.Name" Label="Name" Variant="Variant.Text" Margin="Margin.Dense" AutoFocus Clearable />
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
<MudStack Justify="Justify.Center" Row Class="mt-7">
|
||||||
|
<MudButton OnClick="()=>_visible = false" Variant="Variant.Outlined" DisableElevation Size="Size.Large" Color="Color.Surface">
|
||||||
|
Cancel
|
||||||
|
</MudButton>
|
||||||
|
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" DisableElevation Size="Size.Large" Color="Color.Secondary" Style="width: 100%;">
|
||||||
|
Edit
|
||||||
|
</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
</EditForm>
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
|
</MudDrawer>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private bool _visible;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Jobs;
|
||||||
|
|
||||||
|
public partial class JobEditDialog
|
||||||
|
{
|
||||||
|
[Parameter] public EventCallback OnChanges { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private ILogger<JobEditDialog> Logger { get; init; } = default!;
|
||||||
|
|
||||||
|
private JobEntity? _model;
|
||||||
|
|
||||||
|
public async void ToggleAsync(string? id)
|
||||||
|
{
|
||||||
|
if (id is null) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_model = await Database.Job().Find(p => p.Id == id).FirstAsync();
|
||||||
|
_visible = !_visible;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
}
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SubmitAsync()
|
||||||
|
{
|
||||||
|
if (_model is null) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Database.Job()
|
||||||
|
.UpdateOneAsync(Builders<JobEntity>
|
||||||
|
.Filter
|
||||||
|
.Eq(p => p.Id, _model.Id), Builders<JobEntity>
|
||||||
|
.Update
|
||||||
|
.Set(p => p.Update, DateTime.Now)
|
||||||
|
.Set(p => p.Name, _model.Name), default).ConfigureAwait(false);
|
||||||
|
|
||||||
|
Notification.Success(Snackbar);
|
||||||
|
|
||||||
|
if (OnChanges.HasDelegate)
|
||||||
|
{
|
||||||
|
await InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
await OnChanges.InvokeAsync(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
Logger.LogError(ex.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
@inherits ComponentBase
|
||||||
|
|
||||||
|
<TableContainer T="TaskEntity"
|
||||||
|
@ref="Container"
|
||||||
|
@bind-Search="Search"
|
||||||
|
Title="@Title"
|
||||||
|
Breadcrumbs="@Breadcrumbs"
|
||||||
|
Data="LoadDataAsync"
|
||||||
|
OnAdd="OnAdd">
|
||||||
|
<Header>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Name" T="TaskEntity">
|
||||||
|
Name
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Description" T="TaskEntity">
|
||||||
|
Description
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
</Header>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd DataLabel="Name">
|
||||||
|
<MudLink Href="@Navigation.Management.Scheduler.Tasks.DetailsHref(context.Id)" Typo="Typo.inherit" Underline="Underline.None">
|
||||||
|
@context?.Name
|
||||||
|
</MudLink>
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Description">
|
||||||
|
@context?.Description
|
||||||
|
</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
<ActionTemplate>
|
||||||
|
<MudMenuItem OnClick="@(()=>OnUnassign(context))">
|
||||||
|
Unassign
|
||||||
|
</MudMenuItem>
|
||||||
|
</ActionTemplate>
|
||||||
|
</TableContainer>
|
||||||
|
|
||||||
|
<ActionDialog @bind-Visible="Unassign">
|
||||||
|
<Content>
|
||||||
|
<MudTextField T="string" @bind-Value="Model.Name" Label="Name" Variant="Variant.Text" Margin="Margin.Dense" ReadOnly />
|
||||||
|
<MudTextField T="string" @bind-Value="Model.Description" Label="Description" Variant="Variant.Text" Margin="Margin.Dense" ReadOnly />
|
||||||
|
</Content>
|
||||||
|
<Actions>
|
||||||
|
<MudButton OnClick="()=>Unassign = false">
|
||||||
|
Cancel
|
||||||
|
</MudButton>
|
||||||
|
<MudButton OnClick="OnUnassignSubmitAsync" Color="Color.Secondary">
|
||||||
|
Unassign
|
||||||
|
</MudButton>
|
||||||
|
</Actions>
|
||||||
|
</ActionDialog>
|
||||||
|
|
@ -0,0 +1,185 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Components.Containers;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using SortDirection = MudBlazor.SortDirection;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Jobs;
|
||||||
|
|
||||||
|
[Route(Navigation.Management.Scheduler.Jobs.Tasks)]
|
||||||
|
public partial class Tasks
|
||||||
|
{
|
||||||
|
[Parameter] public string? JobId { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private NavigationManager NavigationManager { get; init; } = default!;
|
||||||
|
|
||||||
|
private TableContainer<TaskEntity>? Container { get; set; }
|
||||||
|
private string Title { get; set; } = Global.Name;
|
||||||
|
private List<BreadcrumbItem> Breadcrumbs { get; } = new();
|
||||||
|
private string? Search { get; set; }
|
||||||
|
|
||||||
|
private TaskEntity? Model { get; set; }
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(JobId))
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Jobs.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Home", href: Navigation.Home));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Scheduler", href: Navigation.Management.Scheduler.Index));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Jobs", href: Navigation.Management.Scheduler.Jobs.Index));
|
||||||
|
|
||||||
|
var job = await Database.Job()
|
||||||
|
.Aggregate()
|
||||||
|
.Match(Builders<JobEntity>.Filter.Eq(p => p.Id, JobId))
|
||||||
|
.FirstOrDefaultAsync(default);
|
||||||
|
|
||||||
|
if (job is null)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Jobs.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Title = $"Scheduler » Jobs » {job.Name} » Tasks|Insight";
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem(job.Name, href: Navigation.Management.Scheduler.Jobs.DetailsHref(JobId)));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Tasks", href: "#", true));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<TableData<TaskEntity>> LoadDataAsync(TableState state)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var filter = Builders<BsonDocument>.Filter.Empty;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(Search) is false)
|
||||||
|
{
|
||||||
|
var regex = new BsonRegularExpression(new Regex(Search, RegexOptions.IgnoreCase));
|
||||||
|
|
||||||
|
filter &= Builders<BsonDocument>.Filter.Regex("name", regex) |
|
||||||
|
Builders<BsonDocument>.Filter.Regex("description", regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = Database.JobTask()
|
||||||
|
.Aggregate()
|
||||||
|
.Match(Builders<JobTaskEntity>.Filter.Eq(p => p.Job, JobId))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$lookup", new BsonDocument
|
||||||
|
{
|
||||||
|
{ "from", "task" },
|
||||||
|
{ "localField", "_task" },
|
||||||
|
{ "foreignField", "_id" },
|
||||||
|
{ "as", "tasks" }
|
||||||
|
}))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$addFields",
|
||||||
|
new BsonDocument("task", new BsonDocument("$first", "$tasks"))
|
||||||
|
))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$project", new BsonDocument
|
||||||
|
{
|
||||||
|
{ "_id", "$task._id" },
|
||||||
|
{ "name", "$task.name" },
|
||||||
|
{ "description", "$task.description" }
|
||||||
|
}))
|
||||||
|
.Match(filter)
|
||||||
|
.Sort(state.SortDirection switch
|
||||||
|
{
|
||||||
|
SortDirection.Ascending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Ascending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Ascending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
SortDirection.Descending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Descending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Descending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
_ => Builders<BsonDocument>.Sort.Ascending("name")
|
||||||
|
});
|
||||||
|
|
||||||
|
var countResult = await query.Count().FirstOrDefaultAsync(default);
|
||||||
|
var itemResult = await query.Skip(state.Page * state.PageSize).Limit(state.PageSize).ToListAsync(default);
|
||||||
|
|
||||||
|
return new TableData<TaskEntity>()
|
||||||
|
{
|
||||||
|
TotalItems = countResult is null ? 0 : (int)countResult.Count,
|
||||||
|
Items = itemResult.Select(x => BsonSerializer.Deserialize<TaskEntity>(x))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
return new TableData<TaskEntity>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAdd()
|
||||||
|
{
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Jobs.TasksAssignHref(JobId));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _unassign;
|
||||||
|
public bool Unassign
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _unassign;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _unassign)
|
||||||
|
{
|
||||||
|
_unassign = value;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUnassign(TaskEntity model)
|
||||||
|
{
|
||||||
|
Model = new TaskEntity
|
||||||
|
{
|
||||||
|
Id = model.Id,
|
||||||
|
Name = model?.Name,
|
||||||
|
Description = model?.Description
|
||||||
|
};
|
||||||
|
|
||||||
|
Unassign = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnUnassignSubmitAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Database.JobTask()
|
||||||
|
.DeleteOneAsync(Builders<JobTaskEntity>
|
||||||
|
.Filter.And(Builders<JobTaskEntity>.Filter
|
||||||
|
.Eq(p => p.Job, JobId), Builders<JobTaskEntity>.Filter
|
||||||
|
.Eq(p => p.Task, Model?.Id)),
|
||||||
|
cancellationToken: default);
|
||||||
|
|
||||||
|
if (Container is not null) await Container.RefreshAsync();
|
||||||
|
|
||||||
|
Notification.Success(Snackbar);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Unassign = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
@inherits ComponentBase
|
||||||
|
|
||||||
|
<TableContainer T="TaskEntity"
|
||||||
|
@ref="Container"
|
||||||
|
@bind-Search="Search"
|
||||||
|
Title="@Title"
|
||||||
|
Breadcrumbs="@Breadcrumbs"
|
||||||
|
Data="LoadDataAsync">
|
||||||
|
<Header>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Name" T="TaskEntity">
|
||||||
|
Name
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Description" T="TaskEntity">
|
||||||
|
Description
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
</Header>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd DataLabel="Name">
|
||||||
|
<MudLink Href="@Navigation.Management.Scheduler.Tasks.DetailsHref(context.Id)" Typo="Typo.inherit" Underline="Underline.None">
|
||||||
|
@context?.Name
|
||||||
|
</MudLink>
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Description">
|
||||||
|
@context?.Description
|
||||||
|
</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
<ActionTemplate>
|
||||||
|
<MudMenuItem OnClick="@(()=>OnAssign(context))">
|
||||||
|
Assign
|
||||||
|
</MudMenuItem>
|
||||||
|
</ActionTemplate>
|
||||||
|
</TableContainer>
|
||||||
|
|
||||||
|
<ActionDialog @bind-Visible="Assign">
|
||||||
|
<Content>
|
||||||
|
<MudTextField T="string" @bind-Value="Model.Name" Label="Name" Variant="Variant.Text" Margin="Margin.Dense" ReadOnly />
|
||||||
|
<MudTextField T="string" @bind-Value="Model.Description" Label="Description" Variant="Variant.Text" Margin="Margin.Dense" ReadOnly />
|
||||||
|
</Content>
|
||||||
|
<Actions>
|
||||||
|
<MudButton OnClick="()=>Assign = false">
|
||||||
|
Cancel
|
||||||
|
</MudButton>
|
||||||
|
<MudButton OnClick="OnAddSubmitAsync" Color="Color.Secondary">
|
||||||
|
Assign
|
||||||
|
</MudButton>
|
||||||
|
</Actions>
|
||||||
|
</ActionDialog>
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Components.Containers;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using SortDirection = MudBlazor.SortDirection;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Jobs;
|
||||||
|
|
||||||
|
[Route(Navigation.Management.Scheduler.Jobs.TasksAssign)]
|
||||||
|
public partial class TasksAssign
|
||||||
|
{
|
||||||
|
[Parameter] public string? JobId { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private NavigationManager NavigationManager { get; init; } = default!;
|
||||||
|
|
||||||
|
private TableContainer<TaskEntity>? Container { get; set; }
|
||||||
|
private string Title { get; set; } = Global.Name;
|
||||||
|
private List<BreadcrumbItem> Breadcrumbs { get; } = new();
|
||||||
|
private string? Search { get; set; }
|
||||||
|
|
||||||
|
private TaskEntity? Model { get; set; }
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(JobId))
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Jobs.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var job = await Database.Job()
|
||||||
|
.Aggregate()
|
||||||
|
.Match(Builders<JobEntity>.Filter.Eq(p => p.Id, JobId))
|
||||||
|
.FirstOrDefaultAsync(default);
|
||||||
|
|
||||||
|
if (job is null)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Jobs.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Home", href: Navigation.Home));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Scheduler", href: Navigation.Management.Scheduler.Index));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Jobs", href: Navigation.Management.Scheduler.Jobs.Index));
|
||||||
|
|
||||||
|
Title = $"Scheduler » Jobs » {job.Name} » Assign Tasks|Insight";
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem(job.Name, href: Navigation.Management.Scheduler.Jobs.DetailsHref(JobId)));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Tasks", href: Navigation.Management.Scheduler.Jobs.TasksHref(JobId)));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Assign", href: "#", true));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<TableData<TaskEntity>> LoadDataAsync(TableState state)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var filter = Builders<BsonDocument>.Filter.Empty;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(Search) is false)
|
||||||
|
{
|
||||||
|
var regex = new BsonRegularExpression(new Regex(Search, RegexOptions.IgnoreCase));
|
||||||
|
filter &= Builders<BsonDocument>.Filter.Regex("name", regex) |
|
||||||
|
Builders<BsonDocument>.Filter.Regex("description", regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = Database.Task()
|
||||||
|
.Aggregate()
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$lookup", new BsonDocument
|
||||||
|
{
|
||||||
|
{ "from", "job_task" },
|
||||||
|
{ "localField", "_id" },
|
||||||
|
{ "foreignField", "_task" },
|
||||||
|
{ "as", "map" }
|
||||||
|
}))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$unwind", new BsonDocument
|
||||||
|
{
|
||||||
|
{ "path", "$map" },
|
||||||
|
{ "preserveNullAndEmptyArrays", true }
|
||||||
|
}))
|
||||||
|
.AppendStage<BsonDocument>(
|
||||||
|
new BsonDocument("$match",
|
||||||
|
new BsonDocument("map._job", new BsonDocument("$ne", new ObjectId(JobId))))
|
||||||
|
)
|
||||||
|
.Sort(state.SortDirection switch
|
||||||
|
{
|
||||||
|
SortDirection.Ascending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Ascending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Ascending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
SortDirection.Descending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Descending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Descending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
_ => Builders<BsonDocument>.Sort.Ascending("name")
|
||||||
|
});
|
||||||
|
|
||||||
|
var countResult = await query.Count().FirstOrDefaultAsync(default);
|
||||||
|
var itemResult = await query.Skip(state.Page * state.PageSize).Limit(state.PageSize).ToListAsync(default);
|
||||||
|
|
||||||
|
return new TableData<TaskEntity>()
|
||||||
|
{
|
||||||
|
TotalItems = countResult is null ? 0 : (int)countResult.Count,
|
||||||
|
Items = itemResult.Select(x => BsonSerializer.Deserialize<TaskEntity>(x))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
return new TableData<TaskEntity>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool _assign;
|
||||||
|
public bool Assign
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _assign;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _assign)
|
||||||
|
{
|
||||||
|
_assign = value;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAssign(TaskEntity? model)
|
||||||
|
{
|
||||||
|
Model = model;
|
||||||
|
Assign = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnAddSubmitAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Database.JobTask()
|
||||||
|
.InsertOneAsync(new JobTaskEntity
|
||||||
|
{
|
||||||
|
Job = JobId,
|
||||||
|
Task = Model.Id
|
||||||
|
}, cancellationToken: default);
|
||||||
|
|
||||||
|
if (Container is not null)
|
||||||
|
{
|
||||||
|
await Container.RefreshAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
Notification.Success(Snackbar);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Assign = false;
|
||||||
|
NavigationManager?.NavigateTo(Navigation.Management.Scheduler.Jobs.TasksHref(JobId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
@inherits ComponentBase
|
||||||
|
|
||||||
|
<TableContainer T="TriggerEntity"
|
||||||
|
@ref="Container"
|
||||||
|
@bind-Search="Search"
|
||||||
|
Title="@Title"
|
||||||
|
Breadcrumbs="@Breadcrumbs"
|
||||||
|
Data="LoadDataAsync"
|
||||||
|
OnAdd="OnAdd">
|
||||||
|
<Header>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Name" T="TriggerEntity">
|
||||||
|
Name
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Description" T="TriggerEntity">
|
||||||
|
Description
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
</Header>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd DataLabel="Name">
|
||||||
|
<MudLink Href="@Navigation.Management.Scheduler.Triggers.DetailsHref(context.Id)" Typo="Typo.inherit" Underline="Underline.None">
|
||||||
|
@context?.Name
|
||||||
|
</MudLink>
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Description">
|
||||||
|
@context?.Description
|
||||||
|
</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
<ActionTemplate>
|
||||||
|
<MudMenuItem OnClick="@(()=>OnUnassign(context))">
|
||||||
|
Unassign
|
||||||
|
</MudMenuItem>
|
||||||
|
</ActionTemplate>
|
||||||
|
</TableContainer>
|
||||||
|
|
||||||
|
<ActionDialog @bind-Visible="Unassign">
|
||||||
|
<Content>
|
||||||
|
<MudTextField T="string" @bind-Value="Model.Name" Label="Name" Variant="Variant.Text" Margin="Margin.Dense" ReadOnly />
|
||||||
|
<MudTextField T="string" @bind-Value="Model.Description" Label="Description" Variant="Variant.Text" Margin="Margin.Dense" ReadOnly />
|
||||||
|
</Content>
|
||||||
|
<Actions>
|
||||||
|
<MudButton OnClick="()=>Unassign = false">
|
||||||
|
Cancel
|
||||||
|
</MudButton>
|
||||||
|
<MudButton OnClick="OnUnassignSubmitAsync" Color="Color.Secondary">
|
||||||
|
Unassign
|
||||||
|
</MudButton>
|
||||||
|
</Actions>
|
||||||
|
</ActionDialog>
|
||||||
|
|
@ -0,0 +1,185 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Components.Containers;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Bson.Serialization;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using SortDirection = MudBlazor.SortDirection;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Jobs;
|
||||||
|
|
||||||
|
[Route(Navigation.Management.Scheduler.Jobs.Triggers)]
|
||||||
|
public partial class Triggers
|
||||||
|
{
|
||||||
|
[Parameter] public string? JobId { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private NavigationManager NavigationManager { get; init; } = default!;
|
||||||
|
|
||||||
|
private TableContainer<TriggerEntity>? Container { get; set; }
|
||||||
|
private string Title { get; set; } = Global.Name;
|
||||||
|
private List<BreadcrumbItem> Breadcrumbs { get; } = new();
|
||||||
|
private string? Search { get; set; }
|
||||||
|
|
||||||
|
private TriggerEntity? Model { get; set; }
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(JobId))
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Jobs.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Home", href: Navigation.Home));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Scheduler", href: Navigation.Management.Scheduler.Index));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Jobs", href: Navigation.Management.Scheduler.Jobs.Index));
|
||||||
|
|
||||||
|
var job = await Database.Job()
|
||||||
|
.Aggregate()
|
||||||
|
.Match(Builders<JobEntity>.Filter.Eq(p => p.Id, JobId))
|
||||||
|
.FirstOrDefaultAsync(default);
|
||||||
|
|
||||||
|
if (job is null)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Jobs.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Title = $"Scheduler » Jobs » {job.Name} » Triggers|Insight";
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem(job.Name, href: Navigation.Management.Scheduler.Jobs.DetailsHref(JobId)));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Triggers", href: "#", true));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<TableData<TriggerEntity>> LoadDataAsync(TableState state)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var filter = Builders<BsonDocument>.Filter.Empty;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(Search) is false)
|
||||||
|
{
|
||||||
|
var regex = new BsonRegularExpression(new Regex(Search, RegexOptions.IgnoreCase));
|
||||||
|
|
||||||
|
filter &= Builders<BsonDocument>.Filter.Regex("name", regex) |
|
||||||
|
Builders<BsonDocument>.Filter.Regex("description", regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = Database.JobTrigger()
|
||||||
|
.Aggregate()
|
||||||
|
.Match(Builders<JobTriggerEntity>.Filter.Eq(p => p.Job, JobId))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$lookup", new BsonDocument
|
||||||
|
{
|
||||||
|
{ "from", "trigger" },
|
||||||
|
{ "localField", "_trigger" },
|
||||||
|
{ "foreignField", "_id" },
|
||||||
|
{ "as", "triggers" }
|
||||||
|
}))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$addFields",
|
||||||
|
new BsonDocument("trigger", new BsonDocument("$first", "$triggers"))
|
||||||
|
))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$project", new BsonDocument
|
||||||
|
{
|
||||||
|
{ "_id", "$trigger._id" },
|
||||||
|
{ "name", "$trigger.name" },
|
||||||
|
{ "description", "$trigger.description" }
|
||||||
|
}))
|
||||||
|
.Match(filter)
|
||||||
|
.Sort(state.SortDirection switch
|
||||||
|
{
|
||||||
|
SortDirection.Ascending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Ascending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Ascending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
SortDirection.Descending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Descending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Descending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
_ => Builders<BsonDocument>.Sort.Ascending("name")
|
||||||
|
});
|
||||||
|
|
||||||
|
var countResult = await query.Count().FirstOrDefaultAsync(default);
|
||||||
|
var itemResult = await query.Skip(state.Page * state.PageSize).Limit(state.PageSize).ToListAsync(default);
|
||||||
|
|
||||||
|
return new TableData<TriggerEntity>()
|
||||||
|
{
|
||||||
|
TotalItems = countResult is null ? 0 : (int)countResult.Count,
|
||||||
|
Items = itemResult.Select(x => BsonSerializer.Deserialize<TriggerEntity>(x))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
return new TableData<TriggerEntity>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAdd()
|
||||||
|
{
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Jobs.TriggersAssignHref(JobId));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _unassign;
|
||||||
|
public bool Unassign
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _unassign;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _unassign)
|
||||||
|
{
|
||||||
|
_unassign = value;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUnassign(TriggerEntity model)
|
||||||
|
{
|
||||||
|
Model = new TriggerEntity
|
||||||
|
{
|
||||||
|
Id = model.Id,
|
||||||
|
Name = model?.Name,
|
||||||
|
Description = model?.Description
|
||||||
|
};
|
||||||
|
|
||||||
|
Unassign = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnUnassignSubmitAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Database.JobTrigger()
|
||||||
|
.DeleteOneAsync(Builders<JobTriggerEntity>
|
||||||
|
.Filter.And(Builders<JobTriggerEntity>.Filter
|
||||||
|
.Eq(p => p.Job, JobId), Builders<JobTriggerEntity>.Filter
|
||||||
|
.Eq(p => p.Trigger, Model?.Id)),
|
||||||
|
cancellationToken: default);
|
||||||
|
|
||||||
|
if (Container is not null) await Container.RefreshAsync();
|
||||||
|
|
||||||
|
Notification.Success(Snackbar);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Unassign = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
@inherits ComponentBase
|
||||||
|
|
||||||
|
<TableContainer T="TriggerEntity"
|
||||||
|
@ref="Container"
|
||||||
|
@bind-Search="Search"
|
||||||
|
Title="@Title"
|
||||||
|
Breadcrumbs="@Breadcrumbs"
|
||||||
|
Data="LoadDataAsync">
|
||||||
|
<Header>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Name" T="TriggerEntity">
|
||||||
|
Name
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Description" T="TriggerEntity">
|
||||||
|
Description
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
</Header>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd DataLabel="Name">
|
||||||
|
<MudLink Href="@Navigation.Management.Scheduler.Triggers.DetailsHref(context.Id)" Typo="Typo.inherit" Underline="Underline.None">
|
||||||
|
@context?.Name
|
||||||
|
</MudLink>
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Description">
|
||||||
|
@context?.Description
|
||||||
|
</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
<ActionTemplate>
|
||||||
|
<MudMenuItem OnClick="@(()=>OnAssign(context))">
|
||||||
|
Assign
|
||||||
|
</MudMenuItem>
|
||||||
|
</ActionTemplate>
|
||||||
|
</TableContainer>
|
||||||
|
|
||||||
|
<ActionDialog @bind-Visible="Assign">
|
||||||
|
<Content>
|
||||||
|
<MudTextField T="string" @bind-Value="Model.Name" Label="Name" Variant="Variant.Text" Margin="Margin.Dense" ReadOnly />
|
||||||
|
<MudTextField T="string" @bind-Value="Model.Description" Label="Description" Variant="Variant.Text" Margin="Margin.Dense" ReadOnly />
|
||||||
|
</Content>
|
||||||
|
<Actions>
|
||||||
|
<MudButton OnClick="()=>Assign = false">
|
||||||
|
Cancel
|
||||||
|
</MudButton>
|
||||||
|
<MudButton OnClick="OnAddSubmitAsync" Color="Color.Secondary">
|
||||||
|
Assign
|
||||||
|
</MudButton>
|
||||||
|
</Actions>
|
||||||
|
</ActionDialog>
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Components.Containers;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using SortDirection = MudBlazor.SortDirection;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Jobs;
|
||||||
|
|
||||||
|
[Route(Navigation.Management.Scheduler.Jobs.TriggersAssign)]
|
||||||
|
public partial class TriggersAssign
|
||||||
|
{
|
||||||
|
[Parameter] public string? JobId { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private NavigationManager NavigationManager { get; init; } = default!;
|
||||||
|
|
||||||
|
private TableContainer<TriggerEntity>? Container { get; set; }
|
||||||
|
private string Title { get; set; } = Global.Name;
|
||||||
|
private List<BreadcrumbItem> Breadcrumbs { get; } = new();
|
||||||
|
private string? Search { get; set; }
|
||||||
|
|
||||||
|
private TriggerEntity? Model { get; set; }
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(JobId))
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Jobs.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var job = await Database.Job()
|
||||||
|
.Aggregate()
|
||||||
|
.Match(Builders<JobEntity>.Filter.Eq(p => p.Id, JobId))
|
||||||
|
.FirstOrDefaultAsync(default);
|
||||||
|
|
||||||
|
if (job is null)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Jobs.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Home", href: Navigation.Home));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Scheduler", href: Navigation.Management.Scheduler.Index));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Jobs", href: Navigation.Management.Scheduler.Jobs.Index));
|
||||||
|
|
||||||
|
Title = $"Scheduler » Jobs » {job.Name} » Assign Triggers|Insight";
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem(job.Name, href: Navigation.Management.Scheduler.Jobs.DetailsHref(JobId)));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Triggers", href: Navigation.Management.Scheduler.Jobs.TriggersHref(JobId)));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Assign", href: "#", true));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<TableData<TriggerEntity>> LoadDataAsync(TableState state)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var filter = Builders<BsonDocument>.Filter.Empty;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(Search) is false)
|
||||||
|
{
|
||||||
|
var regex = new BsonRegularExpression(new Regex(Search, RegexOptions.IgnoreCase));
|
||||||
|
filter &= Builders<BsonDocument>.Filter.Regex("name", regex) |
|
||||||
|
Builders<BsonDocument>.Filter.Regex("description", regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = Database.Trigger()
|
||||||
|
.Aggregate()
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$lookup", new BsonDocument
|
||||||
|
{
|
||||||
|
{ "from", "job_triggers" },
|
||||||
|
{ "localField", "_id" },
|
||||||
|
{ "foreignField", "_trigger" },
|
||||||
|
{ "as", "map" }
|
||||||
|
}))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$unwind", new BsonDocument
|
||||||
|
{
|
||||||
|
{ "path", "$map" },
|
||||||
|
{ "preserveNullAndEmptyArrays", true }
|
||||||
|
}))
|
||||||
|
.AppendStage<BsonDocument>(
|
||||||
|
new BsonDocument("$match",
|
||||||
|
new BsonDocument("map._job", new BsonDocument("$ne", new ObjectId(JobId))))
|
||||||
|
)
|
||||||
|
.Sort(state.SortDirection switch
|
||||||
|
{
|
||||||
|
SortDirection.Ascending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Ascending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Ascending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
SortDirection.Descending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Descending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Descending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
_ => Builders<BsonDocument>.Sort.Ascending("name")
|
||||||
|
});
|
||||||
|
|
||||||
|
var countResult = await query.Count().FirstOrDefaultAsync(default);
|
||||||
|
var itemResult = await query.Skip(state.Page * state.PageSize).Limit(state.PageSize).ToListAsync(default);
|
||||||
|
|
||||||
|
return new TableData<TriggerEntity>()
|
||||||
|
{
|
||||||
|
TotalItems = countResult is null ? 0 : (int)countResult.Count,
|
||||||
|
Items = itemResult.Select(x => BsonSerializer.Deserialize<TriggerEntity>(x))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
return new TableData<TriggerEntity>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool _assign;
|
||||||
|
public bool Assign
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _assign;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _assign)
|
||||||
|
{
|
||||||
|
_assign = value;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAssign(TriggerEntity? model)
|
||||||
|
{
|
||||||
|
Model = model;
|
||||||
|
Assign = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnAddSubmitAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Database.JobTrigger()
|
||||||
|
.InsertOneAsync(new JobTriggerEntity
|
||||||
|
{
|
||||||
|
Job = JobId,
|
||||||
|
Trigger = Model.Id
|
||||||
|
}, cancellationToken: default);
|
||||||
|
|
||||||
|
if (Container is not null)
|
||||||
|
{
|
||||||
|
await Container.RefreshAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
Notification.Success(Snackbar);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Assign = false;
|
||||||
|
NavigationManager?.NavigateTo(Navigation.Management.Scheduler.Jobs.TriggersHref(JobId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
@inherits ComponentBase
|
||||||
|
|
||||||
|
@using Vaitr.Scheduler;
|
||||||
|
|
||||||
|
<BaseContainer Title="@Title" Breadcrumbs="@Breadcrumbs" LoadData="LoadDataAsync">
|
||||||
|
<Content>
|
||||||
|
@if (Task is not null)
|
||||||
|
{
|
||||||
|
<MudGrid>
|
||||||
|
<MudItem xs="12" sm="6" md="6" lg="3">
|
||||||
|
<KeyValueCard T="string" Key="Name" Value="@Task.Name" />
|
||||||
|
</MudItem>
|
||||||
|
@* <MudItem xs="12" sm="6" md="6" lg="3">
|
||||||
|
<KeyValueCard T="int" Href="@Navigation.Management.Jobs.HostsHref(JobId)" Key="Hosts" Value="@(Job?.Hosts?.Count() ?? 0)" Icon="@Icons.Material.Outlined.Devices" IconColor="Color.Primary" />
|
||||||
|
</MudItem> *@
|
||||||
|
</MudGrid>
|
||||||
|
}
|
||||||
|
</Content>
|
||||||
|
</BaseContainer>
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Tasks;
|
||||||
|
|
||||||
|
[Route(Navigation.Management.Scheduler.Tasks.Details)]
|
||||||
|
public partial class Details
|
||||||
|
{
|
||||||
|
[Parameter] public string? TaskId { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private NavigationManager NavigationManager { get; init; } = default!;
|
||||||
|
|
||||||
|
private string Title { get; set; } = Global.Name;
|
||||||
|
private List<BreadcrumbItem> Breadcrumbs { get; } = new();
|
||||||
|
private TaskEntity? Task { get; set; }
|
||||||
|
|
||||||
|
private async Task LoadDataAsync()
|
||||||
|
{
|
||||||
|
Breadcrumbs.Clear();
|
||||||
|
Task = null;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(TaskId) || ObjectId.TryParse(TaskId, out var taskId) is false)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Tasks.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Task = await Database.Task()
|
||||||
|
.Aggregate()
|
||||||
|
.Match(Builders<TaskEntity>.Filter.Eq(p => p.Id, TaskId))
|
||||||
|
.FirstOrDefaultAsync(default);
|
||||||
|
|
||||||
|
if (Task is null)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Tasks.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Home", href: Navigation.Home));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Scheduler", href: Navigation.Management.Scheduler.Index));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Tasks", href: Navigation.Management.Scheduler.Tasks.Index));
|
||||||
|
|
||||||
|
Title = $"Task » {Task.Name ?? Task.Id}|Insight";
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem(Task.Name ?? Task.Id, href: "#", true));
|
||||||
|
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
@inherits ComponentBase
|
||||||
|
|
||||||
|
<TableContainer T="ViewModel"
|
||||||
|
@ref="_container"
|
||||||
|
@bind-Search="_search"
|
||||||
|
Title="@_title"
|
||||||
|
Breadcrumbs="@_breadcrumbs"
|
||||||
|
Data="LoadDataAsync"
|
||||||
|
OnAdd="()=>_createDialog?.ToggleAsync()">
|
||||||
|
<Header>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Name" T="ViewModel">
|
||||||
|
Name
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Description" T="ViewModel">
|
||||||
|
Description
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Jobs" T="ViewModel">
|
||||||
|
Jobs
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
</Header>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd DataLabel="Name">
|
||||||
|
<MudLink Href="@Navigation.Management.Scheduler.Tasks.DetailsHref(context?.Id)" Typo="Typo.inherit" Underline="Underline.None">
|
||||||
|
@context?.Name
|
||||||
|
</MudLink>
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Description">
|
||||||
|
@context?.Description
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Jobs">
|
||||||
|
<MudLink Href="@Navigation.Management.Scheduler.Tasks.JobsHref(context.Id)" Typo="Typo.inherit" Underline="Underline.None">
|
||||||
|
@(context.Jobs?.ToString() ?? "0")
|
||||||
|
</MudLink>
|
||||||
|
</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
<ActionTemplate>
|
||||||
|
<MudMenuItem OnClick="@(()=>_editDialog?.ToggleAsync(context.Id))">
|
||||||
|
Edit
|
||||||
|
</MudMenuItem>
|
||||||
|
<MudMenuItem OnClick="@(()=>_deleteDialog?.ToggleAsync(context.Id))">
|
||||||
|
Delete
|
||||||
|
</MudMenuItem>
|
||||||
|
</ActionTemplate>
|
||||||
|
</TableContainer>
|
||||||
|
|
||||||
|
<TaskCreateDialog @ref="_createDialog" OnChanges="OnRefreshAsync" />
|
||||||
|
<TaskEditDialog @ref="_editDialog" OnChanges="OnRefreshAsync" />
|
||||||
|
<TaskDeleteDialog @ref="_deleteDialog" OnChanges="OnRefreshAsync" />
|
||||||
|
|
||||||
|
@code{
|
||||||
|
private TaskCreateDialog? _createDialog;
|
||||||
|
private TaskEditDialog? _editDialog;
|
||||||
|
private TaskDeleteDialog? _deleteDialog;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Components.Containers;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using SortDirection = MudBlazor.SortDirection;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Tasks;
|
||||||
|
|
||||||
|
[Route(Navigation.Management.Scheduler.Tasks.Index)]
|
||||||
|
public partial class Index
|
||||||
|
{
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
|
||||||
|
private readonly List<BreadcrumbItem> _breadcrumbs = new();
|
||||||
|
|
||||||
|
private TableContainer<ViewModel>? _container;
|
||||||
|
private string _title = Global.Name;
|
||||||
|
private string? _search;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
_title = "Tasks|Insight";
|
||||||
|
_breadcrumbs.Add(new BreadcrumbItem("Home", href: Navigation.Home));
|
||||||
|
_breadcrumbs.Add(new BreadcrumbItem("Scheduler", href: Navigation.Management.Scheduler.Index));
|
||||||
|
_breadcrumbs.Add(new BreadcrumbItem("Tasks", href: Navigation.Management.Scheduler.Tasks.Index, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<TableData<ViewModel>> LoadDataAsync(TableState state)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var filter = Builders<TaskEntity>.Filter.Empty;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(_search) is false)
|
||||||
|
{
|
||||||
|
var regex = new BsonRegularExpression(new Regex(_search, RegexOptions.IgnoreCase));
|
||||||
|
filter &= Builders<TaskEntity>.Filter.Regex(x => x.Name, regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = Database.Task()
|
||||||
|
.Aggregate()
|
||||||
|
.Match(filter)
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$lookup", new BsonDocument
|
||||||
|
{
|
||||||
|
{ "from", "job_task" },
|
||||||
|
{ "localField", "_id" },
|
||||||
|
{ "foreignField", "_task" },
|
||||||
|
{ "as", "jobs" }
|
||||||
|
}))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$addFields",
|
||||||
|
new BsonDocument("jobs", new BsonDocument("$size", "$jobs"))
|
||||||
|
))
|
||||||
|
.Sort(state.SortDirection switch
|
||||||
|
{
|
||||||
|
SortDirection.Ascending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Ascending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Ascending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
SortDirection.Descending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Descending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Descending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
_ => Builders<BsonDocument>.Sort.Ascending("name")
|
||||||
|
});
|
||||||
|
|
||||||
|
var countResult = await query.Count().FirstOrDefaultAsync(default);
|
||||||
|
var itemResult = await query.Skip(state.Page * state.PageSize).Limit(state.PageSize).ToListAsync(default);
|
||||||
|
|
||||||
|
return new TableData<ViewModel>()
|
||||||
|
{
|
||||||
|
TotalItems = countResult is null ? 0 : (int)countResult.Count,
|
||||||
|
Items = itemResult.Select(x => BsonSerializer.Deserialize<ViewModel>(x))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
return new TableData<ViewModel>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnRefreshAsync()
|
||||||
|
{
|
||||||
|
if (_container is null) return;
|
||||||
|
await _container.RefreshAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
private class ViewModel : TaskEntity
|
||||||
|
{
|
||||||
|
[BsonElement("jobs")]
|
||||||
|
public int? Jobs { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
@inherits ComponentBase
|
||||||
|
|
||||||
|
<TableContainer T="JobEntity"
|
||||||
|
@ref="Container"
|
||||||
|
@bind-Search="Search"
|
||||||
|
Title="@Title"
|
||||||
|
Breadcrumbs="@Breadcrumbs"
|
||||||
|
Data="LoadDataAsync">
|
||||||
|
<Header>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Name" T="TaskEntity">
|
||||||
|
Name
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Description" T="TaskEntity">
|
||||||
|
Description
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
</Header>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd DataLabel="Name">
|
||||||
|
<MudLink Href="@Navigation.Management.Scheduler.Jobs.DetailsHref(context.Id)" Typo="Typo.inherit" Underline="Underline.None">
|
||||||
|
@context?.Name
|
||||||
|
</MudLink>
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Description">
|
||||||
|
@context?.Description
|
||||||
|
</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
<ActionTemplate>
|
||||||
|
<MudMenuItem OnClick="@(()=>OnUnassign(context))">
|
||||||
|
Unassign
|
||||||
|
</MudMenuItem>
|
||||||
|
</ActionTemplate>
|
||||||
|
</TableContainer>
|
||||||
|
|
||||||
|
<ActionDialog @bind-Visible="Unassign">
|
||||||
|
<Content>
|
||||||
|
<MudTextField T="string" @bind-Value="Model.Name" Label="Name" Variant="Variant.Text" Margin="Margin.Dense" ReadOnly />
|
||||||
|
<MudTextField T="string" @bind-Value="Model.Description" Label="Description" Variant="Variant.Text" Margin="Margin.Dense" ReadOnly />
|
||||||
|
</Content>
|
||||||
|
<Actions>
|
||||||
|
<MudButton OnClick="()=>Unassign = false">
|
||||||
|
Cancel
|
||||||
|
</MudButton>
|
||||||
|
<MudButton OnClick="OnUnassignSubmitAsync" Color="Color.Secondary">
|
||||||
|
Unassign
|
||||||
|
</MudButton>
|
||||||
|
</Actions>
|
||||||
|
</ActionDialog>
|
||||||
|
|
@ -0,0 +1,180 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Components.Containers;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Bson.Serialization;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using SortDirection = MudBlazor.SortDirection;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Tasks;
|
||||||
|
|
||||||
|
[Route(Navigation.Management.Scheduler.Tasks.Jobs)]
|
||||||
|
public partial class Jobs
|
||||||
|
{
|
||||||
|
[Parameter] public string? TaskId { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private NavigationManager NavigationManager { get; init; } = default!;
|
||||||
|
|
||||||
|
private TableContainer<JobEntity>? Container { get; set; }
|
||||||
|
private string Title { get; set; } = Global.Name;
|
||||||
|
private List<BreadcrumbItem> Breadcrumbs { get; } = new();
|
||||||
|
private string? Search { get; set; }
|
||||||
|
|
||||||
|
private JobEntity? Model { get; set; }
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(TaskId))
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Tasks.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Home", href: Navigation.Home));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Scheduler", href: Navigation.Management.Scheduler.Index));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Tasks", href: Navigation.Management.Scheduler.Tasks.Index));
|
||||||
|
|
||||||
|
var task = await Database.Task()
|
||||||
|
.Aggregate()
|
||||||
|
.Match(Builders<TaskEntity>.Filter.Eq(p => p.Id, TaskId))
|
||||||
|
.FirstOrDefaultAsync(default);
|
||||||
|
|
||||||
|
if (task is null)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Tasks.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Title = $"Scheduler » Tasks » {task.Name} » Jobs|Insight";
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem(task.Name, href: Navigation.Management.Scheduler.Tasks.DetailsHref(TaskId)));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Jobs", href: "#", true));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<TableData<JobEntity>> LoadDataAsync(TableState state)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var filter = Builders<BsonDocument>.Filter.Empty;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(Search) is false)
|
||||||
|
{
|
||||||
|
var regex = new BsonRegularExpression(new Regex(Search, RegexOptions.IgnoreCase));
|
||||||
|
|
||||||
|
filter &= Builders<BsonDocument>.Filter.Regex("name", regex) |
|
||||||
|
Builders<BsonDocument>.Filter.Regex("description", regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = Database.JobTask()
|
||||||
|
.Aggregate()
|
||||||
|
.Match(Builders<JobTaskEntity>.Filter.Eq(p => p.Task, TaskId))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$lookup", new BsonDocument
|
||||||
|
{
|
||||||
|
{ "from", "job" },
|
||||||
|
{ "localField", "_job" },
|
||||||
|
{ "foreignField", "_id" },
|
||||||
|
{ "as", "jobs" }
|
||||||
|
}))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$addFields",
|
||||||
|
new BsonDocument("job", new BsonDocument("$first", "$jobs"))
|
||||||
|
))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$project", new BsonDocument
|
||||||
|
{
|
||||||
|
{ "_id", "$job._id" },
|
||||||
|
{ "name", "$job.name" },
|
||||||
|
{ "description", "$job.description" }
|
||||||
|
}))
|
||||||
|
.Match(filter)
|
||||||
|
.Sort(state.SortDirection switch
|
||||||
|
{
|
||||||
|
SortDirection.Ascending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Ascending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Ascending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
SortDirection.Descending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Descending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Descending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
_ => Builders<BsonDocument>.Sort.Ascending("name")
|
||||||
|
});
|
||||||
|
|
||||||
|
var countResult = await query.Count().FirstOrDefaultAsync(default);
|
||||||
|
var itemResult = await query.Skip(state.Page * state.PageSize).Limit(state.PageSize).ToListAsync(default);
|
||||||
|
|
||||||
|
return new TableData<JobEntity>()
|
||||||
|
{
|
||||||
|
TotalItems = countResult is null ? 0 : (int)countResult.Count,
|
||||||
|
Items = itemResult.Select(x => BsonSerializer.Deserialize<JobEntity>(x))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
return new TableData<JobEntity>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _unassign;
|
||||||
|
public bool Unassign
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _unassign;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _unassign)
|
||||||
|
{
|
||||||
|
_unassign = value;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUnassign(JobEntity model)
|
||||||
|
{
|
||||||
|
Model = new JobEntity
|
||||||
|
{
|
||||||
|
Id = model.Id,
|
||||||
|
Name = model?.Name,
|
||||||
|
Description = model?.Description
|
||||||
|
};
|
||||||
|
|
||||||
|
Unassign = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnUnassignSubmitAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Database.JobTask()
|
||||||
|
.DeleteOneAsync(Builders<JobTaskEntity>
|
||||||
|
.Filter.And(Builders<JobTaskEntity>.Filter
|
||||||
|
.Eq(p => p.Task, TaskId), Builders<JobTaskEntity>.Filter
|
||||||
|
.Eq(p => p.Job, Model?.Id)),
|
||||||
|
cancellationToken: default);
|
||||||
|
|
||||||
|
if (Container is not null) await Container.RefreshAsync();
|
||||||
|
|
||||||
|
Notification.Success(Snackbar);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Unassign = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
@using MongoDB.Bson;
|
||||||
|
@using Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
<MudDrawer @bind-Open="_visible" Anchor="Anchor.End" Elevation="0" Variant="@DrawerVariant.Temporary" ClipMode="DrawerClipMode.Always" Width="400px" Style="max-width:auto;">
|
||||||
|
<MudDrawerHeader>
|
||||||
|
<MudText Typo="Typo.h6">
|
||||||
|
Create Task
|
||||||
|
</MudText>
|
||||||
|
</MudDrawerHeader>
|
||||||
|
<MudStack Class="px-6">
|
||||||
|
@if (_model is not null)
|
||||||
|
{
|
||||||
|
<EditForm Model="@_model" OnValidSubmit="SubmitAsync">
|
||||||
|
<DataAnnotationsValidator />
|
||||||
|
<MudStack Spacing="5">
|
||||||
|
<MudTextField T="string" @bind-Value="_model.Name" For="()=>_model.Name" Label="Name" Variant="Variant.Text" Margin="Margin.Dense" AutoFocus Clearable />
|
||||||
|
<MudTextField T="string" @bind-Value="_model.Description" For="()=>_model.Description" Label="Description" Variant="Variant.Text" Margin="Margin.Dense" Clearable />
|
||||||
|
</MudStack>
|
||||||
|
<MudStack Justify="Justify.Center" Row Class="mt-7">
|
||||||
|
<MudButton OnClick="()=>_visible = false" Variant="Variant.Outlined" DisableElevation Size="Size.Large" Color="Color.Surface">
|
||||||
|
Cancel
|
||||||
|
</MudButton>
|
||||||
|
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" DisableElevation Size="Size.Large" Color="Color.Success" Style="width: 100%;">
|
||||||
|
Create
|
||||||
|
</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
</EditForm>
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
|
</MudDrawer>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private bool _visible;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Tasks;
|
||||||
|
|
||||||
|
public partial class TaskCreateDialog
|
||||||
|
{
|
||||||
|
[Parameter] public EventCallback OnChanges { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private ILogger<TaskCreateDialog> Logger { get; init; } = default!;
|
||||||
|
|
||||||
|
private TaskEntity? _model;
|
||||||
|
|
||||||
|
public async void ToggleAsync()
|
||||||
|
{
|
||||||
|
_model = new();
|
||||||
|
_visible = !_visible;
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SubmitAsync()
|
||||||
|
{
|
||||||
|
if (_model is null) return;
|
||||||
|
|
||||||
|
_model.Insert = DateTime.Now;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Database.Task()
|
||||||
|
.InsertOneAsync(_model, cancellationToken: default)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
Notification.Success(Snackbar);
|
||||||
|
|
||||||
|
if (OnChanges.HasDelegate)
|
||||||
|
{
|
||||||
|
await InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
await OnChanges.InvokeAsync(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
Logger.LogError(ex.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
@using MongoDB.Bson;
|
||||||
|
|
||||||
|
<MudDrawer @bind-Open="_visible" Anchor="Anchor.End" Elevation="0" Variant="@DrawerVariant.Temporary" ClipMode="DrawerClipMode.Always" Width="400px" Style="max-width:auto;">
|
||||||
|
<MudDrawerHeader>
|
||||||
|
<MudText Typo="Typo.h6">
|
||||||
|
Delete Task
|
||||||
|
</MudText>
|
||||||
|
</MudDrawerHeader>
|
||||||
|
<MudStack Class="px-6">
|
||||||
|
@if (_model is not null)
|
||||||
|
{
|
||||||
|
<EditForm Model="@_model" OnValidSubmit="SubmitAsync">
|
||||||
|
<MudStack Spacing="5">
|
||||||
|
<MudTextField T="string" @bind-Value="_model.Name" For="()=>_model.Name" Label="Name" Variant="Variant.Text" Margin="Margin.Dense" ReadOnly />
|
||||||
|
</MudStack>
|
||||||
|
<MudStack Justify="Justify.Center" Row Class="mt-7">
|
||||||
|
<MudButton OnClick="()=>_visible = false" Variant="Variant.Outlined" DisableElevation Size="Size.Large" Color="Color.Surface">
|
||||||
|
Cancel
|
||||||
|
</MudButton>
|
||||||
|
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" DisableElevation Size="Size.Large" Color="Color.Error" Style="width: 100%;">
|
||||||
|
Delete
|
||||||
|
</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
</EditForm>
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
|
</MudDrawer>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private bool _visible;
|
||||||
|
public void Toggle()
|
||||||
|
{
|
||||||
|
_visible = !_visible;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Tasks;
|
||||||
|
|
||||||
|
public partial class TaskDeleteDialog
|
||||||
|
{
|
||||||
|
[Parameter] public EventCallback OnChanges { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private ILogger<TaskDeleteDialog> Logger { get; init; } = default!;
|
||||||
|
|
||||||
|
private TaskEntity? _model;
|
||||||
|
|
||||||
|
public async void ToggleAsync(string? id)
|
||||||
|
{
|
||||||
|
if (id is null) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_model = await Database.Task().Find(p => p.Id == id).FirstAsync();
|
||||||
|
_visible = !_visible;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
}
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SubmitAsync()
|
||||||
|
{
|
||||||
|
if (_model is null) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Database.Task()
|
||||||
|
.DeleteOneAsync(Builders<TaskEntity>
|
||||||
|
.Filter.Eq(p => p.Id, _model.Id),
|
||||||
|
cancellationToken: default);
|
||||||
|
|
||||||
|
Notification.Success(Snackbar);
|
||||||
|
|
||||||
|
if (OnChanges.HasDelegate)
|
||||||
|
{
|
||||||
|
await InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
await OnChanges.InvokeAsync(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
Logger.LogError(ex.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
@using MongoDB.Bson;
|
||||||
|
|
||||||
|
<MudDrawer @bind-Open="_visible" Anchor="Anchor.End" Elevation="0" Variant="@DrawerVariant.Temporary" ClipMode="DrawerClipMode.Always" Width="400px" Style="max-width:auto;">
|
||||||
|
<MudDrawerHeader>
|
||||||
|
<MudText Typo="Typo.h6">
|
||||||
|
Edit Task
|
||||||
|
</MudText>
|
||||||
|
</MudDrawerHeader>
|
||||||
|
<MudStack Class="px-6">
|
||||||
|
@if (_model is not null)
|
||||||
|
{
|
||||||
|
<EditForm Model="@_model" OnValidSubmit="SubmitAsync">
|
||||||
|
<DataAnnotationsValidator />
|
||||||
|
<MudStack Spacing="5">
|
||||||
|
<MudTextField T="string" @bind-Value="_model.Name" For="()=>_model.Name" Label="Name" Variant="Variant.Text" Margin="Margin.Dense" AutoFocus Clearable />
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
<MudStack Justify="Justify.Center" Row Class="mt-7">
|
||||||
|
<MudButton OnClick="()=>_visible = false" Variant="Variant.Outlined" DisableElevation Size="Size.Large" Color="Color.Surface">
|
||||||
|
Cancel
|
||||||
|
</MudButton>
|
||||||
|
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" DisableElevation Size="Size.Large" Color="Color.Secondary" Style="width: 100%;">
|
||||||
|
Edit
|
||||||
|
</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
</EditForm>
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
|
</MudDrawer>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private bool _visible;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Tasks;
|
||||||
|
|
||||||
|
public partial class TaskEditDialog
|
||||||
|
{
|
||||||
|
[Parameter] public EventCallback OnChanges { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private ILogger<TaskEditDialog> Logger { get; init; } = default!;
|
||||||
|
|
||||||
|
private TaskEntity? _model;
|
||||||
|
|
||||||
|
public async void ToggleAsync(string? id)
|
||||||
|
{
|
||||||
|
if (id is null) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_model = await Database.Task().Find(p => p.Id == id).FirstAsync();
|
||||||
|
_visible = !_visible;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
}
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SubmitAsync()
|
||||||
|
{
|
||||||
|
if (_model is null) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Database.Task()
|
||||||
|
.UpdateOneAsync(Builders<TaskEntity>
|
||||||
|
.Filter
|
||||||
|
.Eq(p => p.Id, _model.Id), Builders<TaskEntity>
|
||||||
|
.Update
|
||||||
|
.Set(p => p.Update, DateTime.Now)
|
||||||
|
.Set(p => p.Name, _model.Name), default);
|
||||||
|
|
||||||
|
Notification.Success(Snackbar);
|
||||||
|
|
||||||
|
if (OnChanges.HasDelegate)
|
||||||
|
{
|
||||||
|
await InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
await OnChanges.InvokeAsync(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
Logger.LogError(ex.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
@inherits ComponentBase
|
||||||
|
|
||||||
|
@using Vaitr.Scheduler;
|
||||||
|
|
||||||
|
<BaseContainer Title="@Title" Breadcrumbs="@Breadcrumbs" LoadData="LoadDataAsync">
|
||||||
|
<Content>
|
||||||
|
@if (Trigger is not null)
|
||||||
|
{
|
||||||
|
<MudGrid>
|
||||||
|
<MudItem xs="12" sm="6" md="6" lg="3">
|
||||||
|
<KeyValueCard T="string" Key="Name" Value="@Trigger.Name" />
|
||||||
|
</MudItem>
|
||||||
|
@* <MudItem xs="12" sm="6" md="6" lg="3">
|
||||||
|
<KeyValueCard T="int" Href="@Navigation.Management.Jobs.HostsHref(JobId)" Key="Hosts" Value="@(Job?.Hosts?.Count() ?? 0)" Icon="@Icons.Material.Outlined.Devices" IconColor="Color.Primary" />
|
||||||
|
</MudItem> *@
|
||||||
|
</MudGrid>
|
||||||
|
}
|
||||||
|
</Content>
|
||||||
|
</BaseContainer>
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Triggers;
|
||||||
|
|
||||||
|
[Route(Navigation.Management.Scheduler.Triggers.Details)]
|
||||||
|
public partial class Details
|
||||||
|
{
|
||||||
|
[Parameter] public string? TriggerId { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private NavigationManager NavigationManager { get; init; } = default!;
|
||||||
|
|
||||||
|
private string Title { get; set; } = Global.Name;
|
||||||
|
private List<BreadcrumbItem> Breadcrumbs { get; } = new();
|
||||||
|
private TriggerEntity? Trigger { get; set; }
|
||||||
|
|
||||||
|
private async Task LoadDataAsync()
|
||||||
|
{
|
||||||
|
Breadcrumbs.Clear();
|
||||||
|
Trigger = null;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(TriggerId) || ObjectId.TryParse(TriggerId, out var triggerId) is false)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Triggers.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Trigger = await Database.Trigger()
|
||||||
|
.Aggregate()
|
||||||
|
.Match(Builders<TriggerEntity>.Filter.Eq(p => p.Id, TriggerId))
|
||||||
|
.FirstOrDefaultAsync(default);
|
||||||
|
|
||||||
|
if (Trigger is null)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Triggers.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Home", href: Navigation.Home));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Scheduler", href: Navigation.Management.Scheduler.Index));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Triggers", href: Navigation.Management.Scheduler.Triggers.Index));
|
||||||
|
|
||||||
|
Title = $"Trigger » {Trigger.Name ?? Trigger.Id}|Insight";
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem(Trigger.Name ?? Trigger.Id, href: "#", true));
|
||||||
|
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
@inherits ComponentBase
|
||||||
|
|
||||||
|
<TableContainer T="ViewModel"
|
||||||
|
@ref="_container"
|
||||||
|
@bind-Search="_search"
|
||||||
|
Title="@_title"
|
||||||
|
Breadcrumbs="@_breadcrumbs"
|
||||||
|
Data="LoadDataAsync"
|
||||||
|
OnAdd="()=>_createDialog?.ToggleAsync()">
|
||||||
|
<Header>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Name" T="ViewModel">
|
||||||
|
Name
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Description" T="ViewModel">
|
||||||
|
Description
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Jobs" T="ViewModel">
|
||||||
|
Jobs
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
</Header>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd DataLabel="Name">
|
||||||
|
<MudLink Href="@Navigation.Management.Scheduler.Triggers.DetailsHref(context?.Id)" Typo="Typo.inherit" Underline="Underline.None">
|
||||||
|
@context?.Name
|
||||||
|
</MudLink>
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Description">
|
||||||
|
@context?.Description
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Jobs">
|
||||||
|
<MudLink Href="@Navigation.Management.Scheduler.Triggers.JobsHref(context.Id)" Typo="Typo.inherit" Underline="Underline.None">
|
||||||
|
@(context.Jobs?.ToString() ?? "0")
|
||||||
|
</MudLink>
|
||||||
|
</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
<ActionTemplate>
|
||||||
|
<MudMenuItem OnClick="@(()=>_editDialog?.ToggleAsync(context.Id))">
|
||||||
|
Edit
|
||||||
|
</MudMenuItem>
|
||||||
|
<MudMenuItem OnClick="@(()=>_deleteDialog?.ToggleAsync(context.Id))">
|
||||||
|
Delete
|
||||||
|
</MudMenuItem>
|
||||||
|
</ActionTemplate>
|
||||||
|
</TableContainer>
|
||||||
|
|
||||||
|
<TriggerCreateDialog @ref="_createDialog" OnChanges="OnRefreshAsync" />
|
||||||
|
<TriggerEditDialog @ref="_editDialog" OnChanges="OnRefreshAsync" />
|
||||||
|
<TriggerDeleteDialog @ref="_deleteDialog" OnChanges="OnRefreshAsync" />
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private TriggerCreateDialog? _createDialog;
|
||||||
|
private TriggerEditDialog? _editDialog;
|
||||||
|
private TriggerDeleteDialog? _deleteDialog;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Components.Containers;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using SortDirection = MudBlazor.SortDirection;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Triggers;
|
||||||
|
|
||||||
|
[Route(Navigation.Management.Scheduler.Triggers.Index)]
|
||||||
|
public partial class Index
|
||||||
|
{
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
|
||||||
|
private readonly List<BreadcrumbItem> _breadcrumbs = new();
|
||||||
|
|
||||||
|
private TableContainer<ViewModel>? _container;
|
||||||
|
private string _title = Global.Name;
|
||||||
|
private string? _search;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
_title = "Triggers|Insight";
|
||||||
|
_breadcrumbs.Add(new BreadcrumbItem("Home", href: Navigation.Home));
|
||||||
|
_breadcrumbs.Add(new BreadcrumbItem("Triggers", href: Navigation.Management.Scheduler.Triggers.Index, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<TableData<ViewModel>> LoadDataAsync(TableState state)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var filter = Builders<TriggerEntity>.Filter.Empty;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(_search) is false)
|
||||||
|
{
|
||||||
|
var regex = new BsonRegularExpression(new Regex(_search, RegexOptions.IgnoreCase));
|
||||||
|
filter &= Builders<TriggerEntity>.Filter.Regex(x => x.Name, regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = Database.Trigger()
|
||||||
|
.Aggregate()
|
||||||
|
.Match(filter)
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$lookup", new BsonDocument
|
||||||
|
{
|
||||||
|
{ "from", "job_trigger" },
|
||||||
|
{ "localField", "_id" },
|
||||||
|
{ "foreignField", "_trigger" },
|
||||||
|
{ "as", "jobs" }
|
||||||
|
}))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$addFields",
|
||||||
|
new BsonDocument("jobs", new BsonDocument("$size", "$jobs"))
|
||||||
|
))
|
||||||
|
.Sort(state.SortDirection switch
|
||||||
|
{
|
||||||
|
SortDirection.Ascending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Ascending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Ascending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
SortDirection.Descending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Descending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Descending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
_ => Builders<BsonDocument>.Sort.Ascending("name")
|
||||||
|
});
|
||||||
|
|
||||||
|
var countResult = await query.Count().FirstOrDefaultAsync(default);
|
||||||
|
var itemResult = await query.Skip(state.Page * state.PageSize).Limit(state.PageSize).ToListAsync(default);
|
||||||
|
|
||||||
|
return new TableData<ViewModel>()
|
||||||
|
{
|
||||||
|
TotalItems = countResult is null ? 0 : (int)countResult.Count,
|
||||||
|
Items = itemResult.Select(x => BsonSerializer.Deserialize<ViewModel>(x))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
return new TableData<ViewModel>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnRefreshAsync()
|
||||||
|
{
|
||||||
|
if (_container is null) return;
|
||||||
|
await _container.RefreshAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[BsonIgnoreExtraElements]
|
||||||
|
private class ViewModel : TriggerEntity
|
||||||
|
{
|
||||||
|
[BsonElement("jobs")]
|
||||||
|
public int? Jobs { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
@inherits ComponentBase
|
||||||
|
|
||||||
|
<TableContainer T="JobEntity"
|
||||||
|
@ref="Container"
|
||||||
|
@bind-Search="Search"
|
||||||
|
Title="@Title"
|
||||||
|
Breadcrumbs="@Breadcrumbs"
|
||||||
|
Data="LoadDataAsync">
|
||||||
|
<Header>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Name" T="TaskEntity">
|
||||||
|
Name
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortLabel="Description" T="TaskEntity">
|
||||||
|
Description
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
</Header>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd DataLabel="Name">
|
||||||
|
<MudLink Href="@Navigation.Management.Scheduler.Jobs.DetailsHref(context.Id)" Typo="Typo.inherit" Underline="Underline.None">
|
||||||
|
@context?.Name
|
||||||
|
</MudLink>
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Description">
|
||||||
|
@context?.Description
|
||||||
|
</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
<ActionTemplate>
|
||||||
|
<MudMenuItem OnClick="@(()=>OnUnassign(context))">
|
||||||
|
Unassign
|
||||||
|
</MudMenuItem>
|
||||||
|
</ActionTemplate>
|
||||||
|
</TableContainer>
|
||||||
|
|
||||||
|
<ActionDialog @bind-Visible="Unassign">
|
||||||
|
<Content>
|
||||||
|
<MudTextField T="string" @bind-Value="Model.Name" Label="Name" Variant="Variant.Text" Margin="Margin.Dense" ReadOnly />
|
||||||
|
<MudTextField T="string" @bind-Value="Model.Description" Label="Description" Variant="Variant.Text" Margin="Margin.Dense" ReadOnly />
|
||||||
|
</Content>
|
||||||
|
<Actions>
|
||||||
|
<MudButton OnClick="()=>Unassign = false">
|
||||||
|
Cancel
|
||||||
|
</MudButton>
|
||||||
|
<MudButton OnClick="OnUnassignSubmitAsync" Color="Color.Secondary">
|
||||||
|
Unassign
|
||||||
|
</MudButton>
|
||||||
|
</Actions>
|
||||||
|
</ActionDialog>
|
||||||
|
|
@ -0,0 +1,180 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Components.Containers;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Bson.Serialization;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using SortDirection = MudBlazor.SortDirection;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Triggers;
|
||||||
|
|
||||||
|
[Route(Navigation.Management.Scheduler.Triggers.Jobs)]
|
||||||
|
public partial class Jobs
|
||||||
|
{
|
||||||
|
[Parameter] public string? TriggerId { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private NavigationManager NavigationManager { get; init; } = default!;
|
||||||
|
|
||||||
|
private TableContainer<JobEntity>? Container { get; set; }
|
||||||
|
private string Title { get; set; } = Global.Name;
|
||||||
|
private List<BreadcrumbItem> Breadcrumbs { get; } = new();
|
||||||
|
private string? Search { get; set; }
|
||||||
|
|
||||||
|
private JobEntity? Model { get; set; }
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(TriggerId))
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Triggers.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Home", href: Navigation.Home));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Scheduler", href: Navigation.Management.Scheduler.Index));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Triggers", href: Navigation.Management.Scheduler.Triggers.Index));
|
||||||
|
|
||||||
|
var task = await Database.Trigger()
|
||||||
|
.Aggregate()
|
||||||
|
.Match(Builders<TriggerEntity>.Filter.Eq(p => p.Id, TriggerId))
|
||||||
|
.FirstOrDefaultAsync(default);
|
||||||
|
|
||||||
|
if (task is null)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar, "Not Found");
|
||||||
|
NavigationManager.NavigateTo(Navigation.Management.Scheduler.Triggers.Index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Title = $"Scheduler » Triggers » {task.Name} » Jobs|Insight";
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem(task.Name, href: Navigation.Management.Scheduler.Triggers.DetailsHref(TriggerId)));
|
||||||
|
Breadcrumbs.Add(new BreadcrumbItem("Jobs", href: "#", true));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<TableData<JobEntity>> LoadDataAsync(TableState state)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var filter = Builders<BsonDocument>.Filter.Empty;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(Search) is false)
|
||||||
|
{
|
||||||
|
var regex = new BsonRegularExpression(new Regex(Search, RegexOptions.IgnoreCase));
|
||||||
|
|
||||||
|
filter &= Builders<BsonDocument>.Filter.Regex("name", regex) |
|
||||||
|
Builders<BsonDocument>.Filter.Regex("description", regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = Database.JobTrigger()
|
||||||
|
.Aggregate()
|
||||||
|
.Match(Builders<JobTriggerEntity>.Filter.Eq(p => p.Trigger, TriggerId))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$lookup", new BsonDocument
|
||||||
|
{
|
||||||
|
{ "from", "job" },
|
||||||
|
{ "localField", "_job" },
|
||||||
|
{ "foreignField", "_id" },
|
||||||
|
{ "as", "jobs" }
|
||||||
|
}))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$addFields",
|
||||||
|
new BsonDocument("job", new BsonDocument("$first", "$jobs"))
|
||||||
|
))
|
||||||
|
.AppendStage<BsonDocument>(new BsonDocument("$project", new BsonDocument
|
||||||
|
{
|
||||||
|
{ "_id", "$job._id" },
|
||||||
|
{ "name", "$job.name" },
|
||||||
|
{ "description", "$job.description" }
|
||||||
|
}))
|
||||||
|
.Match(filter)
|
||||||
|
.Sort(state.SortDirection switch
|
||||||
|
{
|
||||||
|
SortDirection.Ascending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Ascending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Ascending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
SortDirection.Descending => state.SortLabel switch
|
||||||
|
{
|
||||||
|
"Name" => Builders<BsonDocument>.Sort.Descending("name"),
|
||||||
|
"Description" => Builders<BsonDocument>.Sort.Descending("description"),
|
||||||
|
_ => null
|
||||||
|
},
|
||||||
|
_ => Builders<BsonDocument>.Sort.Ascending("name")
|
||||||
|
});
|
||||||
|
|
||||||
|
var countResult = await query.Count().FirstOrDefaultAsync(default);
|
||||||
|
var itemResult = await query.Skip(state.Page * state.PageSize).Limit(state.PageSize).ToListAsync(default);
|
||||||
|
|
||||||
|
return new TableData<JobEntity>()
|
||||||
|
{
|
||||||
|
TotalItems = countResult is null ? 0 : (int)countResult.Count,
|
||||||
|
Items = itemResult.Select(x => BsonSerializer.Deserialize<JobEntity>(x))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
return new TableData<JobEntity>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _unassign;
|
||||||
|
public bool Unassign
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _unassign;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _unassign)
|
||||||
|
{
|
||||||
|
_unassign = value;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUnassign(JobEntity model)
|
||||||
|
{
|
||||||
|
Model = new JobEntity
|
||||||
|
{
|
||||||
|
Id = model.Id,
|
||||||
|
Name = model?.Name,
|
||||||
|
Description = model?.Description
|
||||||
|
};
|
||||||
|
|
||||||
|
Unassign = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnUnassignSubmitAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Database.JobTrigger()
|
||||||
|
.DeleteOneAsync(Builders<JobTriggerEntity>
|
||||||
|
.Filter.And(Builders<JobTriggerEntity>.Filter
|
||||||
|
.Eq(p => p.Trigger, TriggerId), Builders<JobTriggerEntity>.Filter
|
||||||
|
.Eq(p => p.Job, Model?.Id)),
|
||||||
|
cancellationToken: default);
|
||||||
|
|
||||||
|
if (Container is not null) await Container.RefreshAsync();
|
||||||
|
|
||||||
|
Notification.Success(Snackbar);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Unassign = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
@using MongoDB.Bson;
|
||||||
|
@using Insight.Infrastructure.Entities;
|
||||||
|
|
||||||
|
<MudDrawer @bind-Open="_visible" Anchor="Anchor.End" Elevation="0" Variant="@DrawerVariant.Temporary" ClipMode="DrawerClipMode.Always" Width="400px" Style="max-width:auto;">
|
||||||
|
<MudDrawerHeader>
|
||||||
|
<MudText Typo="Typo.h6">
|
||||||
|
Create Trigger
|
||||||
|
</MudText>
|
||||||
|
</MudDrawerHeader>
|
||||||
|
<MudStack Class="px-6">
|
||||||
|
@if (_model is not null)
|
||||||
|
{
|
||||||
|
<EditForm Model="@_model" OnValidSubmit="SubmitAsync">
|
||||||
|
<DataAnnotationsValidator />
|
||||||
|
<MudStack Spacing="5">
|
||||||
|
<MudTextField T="string" @bind-Value="_model.Name" For="()=>_model.Name" Label="Name" Variant="Variant.Text" Margin="Margin.Dense" AutoFocus Clearable />
|
||||||
|
<MudTextField T="string" @bind-Value="_model.Description" For="()=>_model.Description" Label="Description" Variant="Variant.Text" Margin="Margin.Dense" Clearable />
|
||||||
|
</MudStack>
|
||||||
|
<MudStack Justify="Justify.Center" Row Class="mt-7">
|
||||||
|
<MudButton OnClick="()=>_visible = false" Variant="Variant.Outlined" DisableElevation Size="Size.Large" Color="Color.Surface">
|
||||||
|
Cancel
|
||||||
|
</MudButton>
|
||||||
|
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" DisableElevation Size="Size.Large" Color="Color.Success" Style="width: 100%;">
|
||||||
|
Create
|
||||||
|
</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
</EditForm>
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
|
</MudDrawer>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private bool _visible;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Triggers;
|
||||||
|
|
||||||
|
public partial class TriggerCreateDialog
|
||||||
|
{
|
||||||
|
[Parameter] public EventCallback OnChanges { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private ILogger<TriggerCreateDialog> Logger { get; init; } = default!;
|
||||||
|
|
||||||
|
private TriggerEntity? _model;
|
||||||
|
|
||||||
|
public async void ToggleAsync()
|
||||||
|
{
|
||||||
|
_model = new();
|
||||||
|
_visible = !_visible;
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SubmitAsync()
|
||||||
|
{
|
||||||
|
if (_model is null) return;
|
||||||
|
|
||||||
|
_model.Insert = DateTime.Now;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Database.Trigger()
|
||||||
|
.InsertOneAsync(_model, cancellationToken: default)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
Notification.Success(Snackbar);
|
||||||
|
|
||||||
|
if (OnChanges.HasDelegate)
|
||||||
|
{
|
||||||
|
await InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
await OnChanges.InvokeAsync(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
Logger.LogError(ex.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
@using MongoDB.Bson;
|
||||||
|
|
||||||
|
<MudDrawer @bind-Open="_visible" Anchor="Anchor.End" Elevation="0" Variant="@DrawerVariant.Temporary" ClipMode="DrawerClipMode.Always" Width="400px" Style="max-width:auto;">
|
||||||
|
<MudDrawerHeader>
|
||||||
|
<MudText Typo="Typo.h6">
|
||||||
|
Delete Trigger
|
||||||
|
</MudText>
|
||||||
|
</MudDrawerHeader>
|
||||||
|
<MudStack Class="px-6">
|
||||||
|
@if (_model is not null)
|
||||||
|
{
|
||||||
|
<EditForm Model="@_model" OnValidSubmit="SubmitAsync">
|
||||||
|
<MudStack Spacing="5">
|
||||||
|
<MudTextField T="string" @bind-Value="_model.Name" For="()=>_model.Name" Label="Name" Variant="Variant.Text" Margin="Margin.Dense" ReadOnly />
|
||||||
|
</MudStack>
|
||||||
|
<MudStack Justify="Justify.Center" Row Class="mt-7">
|
||||||
|
<MudButton OnClick="()=>_visible = false" Variant="Variant.Outlined" DisableElevation Size="Size.Large" Color="Color.Surface">
|
||||||
|
Cancel
|
||||||
|
</MudButton>
|
||||||
|
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" DisableElevation Size="Size.Large" Color="Color.Error" Style="width: 100%;">
|
||||||
|
Delete
|
||||||
|
</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
</EditForm>
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
|
</MudDrawer>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private bool _visible;
|
||||||
|
public void Toggle()
|
||||||
|
{
|
||||||
|
_visible = !_visible;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Triggers;
|
||||||
|
|
||||||
|
public partial class TriggerDeleteDialog
|
||||||
|
{
|
||||||
|
[Parameter] public EventCallback OnChanges { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private ILogger<TriggerDeleteDialog> Logger { get; init; } = default!;
|
||||||
|
|
||||||
|
private TriggerEntity? _model;
|
||||||
|
|
||||||
|
public async void ToggleAsync(string? id)
|
||||||
|
{
|
||||||
|
if (id is null) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_model = await Database.Trigger().Find(p => p.Id == id).FirstAsync();
|
||||||
|
_visible = !_visible;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
}
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SubmitAsync()
|
||||||
|
{
|
||||||
|
if (_model is null) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Database.Trigger()
|
||||||
|
.DeleteOneAsync(Builders<TriggerEntity>
|
||||||
|
.Filter.Eq(p => p.Id, _model.Id),
|
||||||
|
cancellationToken: default);
|
||||||
|
|
||||||
|
Notification.Success(Snackbar);
|
||||||
|
|
||||||
|
if (OnChanges.HasDelegate)
|
||||||
|
{
|
||||||
|
await InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
await OnChanges.InvokeAsync(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
Logger.LogError(ex.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
@using MongoDB.Bson;
|
||||||
|
|
||||||
|
<MudDrawer @bind-Open="_visible" Anchor="Anchor.End" Elevation="0" Variant="@DrawerVariant.Temporary" ClipMode="DrawerClipMode.Always" Width="400px" Style="max-width:auto;">
|
||||||
|
<MudDrawerHeader>
|
||||||
|
<MudText Typo="Typo.h6">
|
||||||
|
Edit Trigger
|
||||||
|
</MudText>
|
||||||
|
</MudDrawerHeader>
|
||||||
|
<MudStack Class="px-6">
|
||||||
|
@if (_model is not null)
|
||||||
|
{
|
||||||
|
<EditForm Model="@_model" OnValidSubmit="SubmitAsync">
|
||||||
|
<DataAnnotationsValidator />
|
||||||
|
<MudStack Spacing="5">
|
||||||
|
<MudTextField T="string" @bind-Value="_model.Name" For="()=>_model.Name" Label="Name" Variant="Variant.Text" Margin="Margin.Dense" AutoFocus Clearable />
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
<MudStack Justify="Justify.Center" Row Class="mt-7">
|
||||||
|
<MudButton OnClick="()=>_visible = false" Variant="Variant.Outlined" DisableElevation Size="Size.Large" Color="Color.Surface">
|
||||||
|
Cancel
|
||||||
|
</MudButton>
|
||||||
|
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" DisableElevation Size="Size.Large" Color="Color.Secondary" Style="width: 100%;">
|
||||||
|
Edit
|
||||||
|
</MudButton>
|
||||||
|
</MudStack>
|
||||||
|
</EditForm>
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
|
</MudDrawer>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private bool _visible;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
using Insight.Infrastructure.Entities;
|
||||||
|
using Insight.Web.Constants;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace Insight.Web.Pages.Management.Scheduler.Triggers;
|
||||||
|
|
||||||
|
public partial class TriggerEditDialog
|
||||||
|
{
|
||||||
|
[Parameter] public EventCallback OnChanges { get; set; }
|
||||||
|
|
||||||
|
[Inject] private IMongoDatabase Database { get; init; } = default!;
|
||||||
|
[Inject] private ISnackbar Snackbar { get; init; } = default!;
|
||||||
|
[Inject] private ILogger<TriggerEditDialog> Logger { get; init; } = default!;
|
||||||
|
|
||||||
|
private TriggerEntity? _model;
|
||||||
|
|
||||||
|
public async void ToggleAsync(string? id)
|
||||||
|
{
|
||||||
|
if (id is null) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_model = await Database.Trigger().Find(p => p.Id == id).FirstAsync();
|
||||||
|
_visible = !_visible;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
}
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SubmitAsync()
|
||||||
|
{
|
||||||
|
if (_model is null) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Database.Trigger()
|
||||||
|
.UpdateOneAsync(Builders<TriggerEntity>
|
||||||
|
.Filter
|
||||||
|
.Eq(p => p.Id, _model.Id), Builders<TriggerEntity>
|
||||||
|
.Update
|
||||||
|
.Set(p => p.Update, DateTime.Now)
|
||||||
|
.Set(p => p.Name, _model.Name), default);
|
||||||
|
|
||||||
|
Notification.Success(Snackbar);
|
||||||
|
|
||||||
|
if (OnChanges.HasDelegate)
|
||||||
|
{
|
||||||
|
await InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
await OnChanges.InvokeAsync(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Notification.Error(Snackbar);
|
||||||
|
Logger.LogError(ex.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
<h3>Index</h3>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue