diff --git a/LANCommander/Pages/Dashboard/Charts/NetworkDownloadRate.razor b/LANCommander/Pages/Dashboard/Charts/NetworkDownloadRate.razor index 02f583f..cbc893d 100644 --- a/LANCommander/Pages/Dashboard/Charts/NetworkDownloadRate.razor +++ b/LANCommander/Pages/Dashboard/Charts/NetworkDownloadRate.razor @@ -1,45 +1,66 @@ @using System.Diagnostics; @using LANCommander.Extensions; @using AntDesign.Charts; - +@using System.Collections.Concurrent; + + @code { [Parameter] public int TimerHistory { get; set; } [Parameter] public int TimerInterval { get; set; } + IChartComponent? Chart; + System.Timers.Timer Timer; Dictionary Data = new Dictionary(); - Dictionary PerformanceCounters = new Dictionary(); + ConcurrentDictionary PerformanceCounters = new ConcurrentDictionary(); - LineConfig Config = new LineConfig + string JsConfig = @"{ + meta: { + value: { + alias: 'Speed', + formatter: (v) => humanFileSize(v, true) + '/s' + } + } + }"; + + AreaConfig Config = new AreaConfig { Name = "Network Download Rate", Padding = "auto", - SeriesField = "Series", - YField = "Value", - XField = "Index", + SeriesField = "series", + YField = "value", + XField = "index", + Animation = false, XAxis = new ValueCatTimeAxis { - Type = "dateTime", - TickCount = 1 + Visible = false } }; - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { - var timer = new System.Timers.Timer(); - - timer.Interval = TimerInterval; - - timer.Elapsed += async (s, e) => + if (Timer == null) { - await RefreshData(); + Timer = new System.Timers.Timer(); - await InvokeAsync(StateHasChanged); - }; + Timer.Interval = TimerInterval; - timer.Start(); + Timer.Elapsed += async (s, e) => + { + await RefreshData(); + }; + } + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + await Chart.UpdateChart(Config, null, null, JsConfig); + Timer.Start(); + } } private async Task RefreshData() @@ -57,6 +78,6 @@ Data[instance] = Data[instance].ShiftArrayAndInsert((double)PerformanceCounters[instance].NextValue(), TimerHistory); } - await Chart.ChangeData(Data.SelectMany(x => x.Value.Select((y, i) => new { Value = y, Index = i, Series = x.Key })), true); + await Chart.ChangeData(Data.SelectMany(x => x.Value.Select((y, i) => new { value = y, index = i, series = x.Key })), true); } } diff --git a/LANCommander/Pages/Dashboard/Charts/NetworkUploadRate.razor b/LANCommander/Pages/Dashboard/Charts/NetworkUploadRate.razor index aac2344..95f59ff 100644 --- a/LANCommander/Pages/Dashboard/Charts/NetworkUploadRate.razor +++ b/LANCommander/Pages/Dashboard/Charts/NetworkUploadRate.razor @@ -1,45 +1,66 @@ @using System.Diagnostics; @using LANCommander.Extensions; @using AntDesign.Charts; - +@using System.Collections.Concurrent; + + @code { [Parameter] public int TimerHistory { get; set; } [Parameter] public int TimerInterval { get; set; } + IChartComponent? Chart; + System.Timers.Timer Timer; Dictionary Data = new Dictionary(); - Dictionary PerformanceCounters = new Dictionary(); + ConcurrentDictionary PerformanceCounters = new ConcurrentDictionary(); - LineConfig Config = new LineConfig + string JsConfig = @"{ + meta: { + value: { + alias: 'Speed', + formatter: (v) => humanFileSize(v, true) + '/s' + } + } + }"; + + AreaConfig Config = new AreaConfig { Name = "Network Upload Rate", Padding = "auto", - SeriesField = "Series", - YField = "Value", - XField = "Index", + SeriesField = "series", + YField = "value", + XField = "index", + Animation = false, XAxis = new ValueCatTimeAxis { - Type = "dateTime", - TickCount = 1 + Visible = false } }; - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { - var timer = new System.Timers.Timer(); - - timer.Interval = TimerInterval; - - timer.Elapsed += async (s, e) => + if (Timer == null) { - await RefreshData(); + Timer = new System.Timers.Timer(); - await InvokeAsync(StateHasChanged); - }; + Timer.Interval = TimerInterval; - timer.Start(); + Timer.Elapsed += async (s, e) => + { + await RefreshData(); + }; + } + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + await Chart.UpdateChart(Config, null, null, JsConfig); + Timer.Start(); + } } private async Task RefreshData() @@ -57,6 +78,6 @@ Data[instance] = Data[instance].ShiftArrayAndInsert((double)PerformanceCounters[instance].NextValue(), TimerHistory); } - await Chart.ChangeData(Data.SelectMany(x => x.Value.Select((y, i) => new { Value = y, Index = i, Series = x.Key })), true); + await Chart.ChangeData(Data.SelectMany(x => x.Value.Select((y, i) => new { value = y, index = i, series = x.Key })), true); } } diff --git a/LANCommander/Pages/Dashboard/Charts/ProcessorUtilization.razor b/LANCommander/Pages/Dashboard/Charts/ProcessorUtilization.razor index 51f8043..9ba43ce 100644 --- a/LANCommander/Pages/Dashboard/Charts/ProcessorUtilization.razor +++ b/LANCommander/Pages/Dashboard/Charts/ProcessorUtilization.razor @@ -1,50 +1,75 @@ @using System.Diagnostics; @using LANCommander.Extensions; @using AntDesign.Charts; - + + @code { [Parameter] public int TimerHistory { get; set; } [Parameter] public int TimerInterval { get; set; } IChartComponent? Chart; + System.Timers.Timer Timer; double[] Data; PerformanceCounter PerformanceCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total"); - LineConfig Config = new LineConfig + string JsConfig = @"{ + meta: { + value: { + alias: '% Usage', + formatter: (v) => v + '%' + } + } + }"; + + AreaConfig Config = new AreaConfig { Name = "Processor Utilization", Padding = "auto", - YField = "Value", - XField = "Index", + YField = "value", + XField = "index", + Animation = false, + IsPercent = true, + YAxis = new ValueAxis + { + Min = 0, + Max = 100 + }, XAxis = new ValueCatTimeAxis { - Type = "dateTime", - TickCount = 1 + Visible = false } }; - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { - var timer = new System.Timers.Timer(); - - timer.Interval = TimerInterval; - - timer.Elapsed += async (s, e) => + if (Timer == null) { - await RefreshData(); + Timer = new System.Timers.Timer(); - await InvokeAsync(StateHasChanged); - }; + Timer.Interval = TimerInterval; - timer.Start(); + Timer.Elapsed += async (s, e) => + { + await RefreshData(); + }; + } + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + await Chart.UpdateChart(Config, null, null, JsConfig); + Timer.Start(); + } } private async Task RefreshData() { - Data = Data.ShiftArrayAndInsert((double)PerformanceCounter.NextValue(), TimerHistory); + Data = Data.ShiftArrayAndInsert((double)Math.Ceiling(PerformanceCounter.NextValue()), TimerHistory); - await Chart.ChangeData(Data.Select((x, i) => new { Value = x, Index = i }), true); + await Chart.ChangeData(Data.Select((x, i) => new { value = x, index = i }), true); } } diff --git a/LANCommander/Pages/Dashboard/Charts/StorageUsage.razor b/LANCommander/Pages/Dashboard/Charts/StorageUsage.razor new file mode 100644 index 0000000..a9a9615 --- /dev/null +++ b/LANCommander/Pages/Dashboard/Charts/StorageUsage.razor @@ -0,0 +1,63 @@ +@using AntDesign.Charts +@using ByteSizeLib + + + +@code { + object[] Data; + + string JsConfig = @"{ + meta: { + value: { + alias: 'Data Usage', + formatter: (v) => humanFileSize(v, true) + } + }, + label: { + visible: true, + type: 'outer-center' + } + }"; + + PieConfig Config = new PieConfig + { + Radius = 0.8, + AngleField = "value", + ColorField = "type", + }; + + protected override async Task OnInitializedAsync() + { + var drives = DriveInfo.GetDrives(); + var root = Path.GetPathRoot(System.Reflection.Assembly.GetExecutingAssembly().Location); + + var totalStorageSize = drives.Where(d => d.IsReady && d.Name == root).Sum(d => d.TotalSize); + var totalAvailableFreeSpace = drives.Where(d => d.IsReady && d.Name == root).Sum(d => d.AvailableFreeSpace); + var totalUploadDirectorySize = new DirectoryInfo("Upload").EnumerateFiles().Sum(f => f.Length); + var totalSaveDirectorySize = new DirectoryInfo("Save").EnumerateFiles().Sum(f => f.Length); + + Data = new object[] + { + new { + type = "Free", + value = totalAvailableFreeSpace + }, + new { + type = "Games", + value = totalUploadDirectorySize + }, + new + { + type = "Saves", + value = totalSaveDirectorySize + }, + new + { + type = "Other", + value = totalStorageSize - totalAvailableFreeSpace - totalUploadDirectorySize - totalSaveDirectorySize + } + }; + + StateHasChanged(); + } +} \ No newline at end of file diff --git a/LANCommander/Pages/Dashboard/Index.razor b/LANCommander/Pages/Dashboard/Index.razor index ce30bba..c0659da 100644 --- a/LANCommander/Pages/Dashboard/Index.razor +++ b/LANCommander/Pages/Dashboard/Index.razor @@ -1,10 +1,39 @@ -@page "/Dashboard" +@page "/" +@page "/Dashboard" @using LANCommander.Pages.Dashboard.Charts - - - + -@code { + + + + + + + + -} + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LANCommander/Pages/_Layout.cshtml b/LANCommander/Pages/_Layout.cshtml index 2a270a6..98f4aac 100644 --- a/LANCommander/Pages/_Layout.cshtml +++ b/LANCommander/Pages/_Layout.cshtml @@ -29,5 +29,6 @@ + diff --git a/LANCommander/wwwroot/js/site.js b/LANCommander/wwwroot/js/site.js index ac49c18..6c9a7e6 100644 --- a/LANCommander/wwwroot/js/site.js +++ b/LANCommander/wwwroot/js/site.js @@ -2,3 +2,24 @@ // for details on configuring this project to bundle and minify static web assets. // Write your JavaScript code. +function humanFileSize(bytes, si = false, dp = 1) { + const thresh = si ? 1000 : 1024; + + if (Math.abs(bytes) < thresh) { + return bytes + ' B'; + } + + const units = si + ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] + : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']; + let u = -1; + const r = 10 ** dp; + + do { + bytes /= thresh; + ++u; + } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1); + + + return bytes.toFixed(dp) + ' ' + units[u]; +} \ No newline at end of file