Skip to content

Commit 532a0bd

Browse files
committed
FF-1633: Started adding reporting
1 parent 7fc302c commit 532a0bd

File tree

11 files changed

+245
-14
lines changed

11 files changed

+245
-14
lines changed

Client/Client.csproj

0 Bytes
Binary file not shown.

Client/Pages/Reporting/Reporting.Editor.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using FileFlows.Client.Components.Inputs;
44
using FileFlows.Plugin;
55
using FileFlows.Shared.Validators;
6+
using Microsoft.JSInterop;
67

78
namespace FileFlows.Client.Pages;
89

@@ -155,7 +156,7 @@ private async Task ShowReport(string name, string html)
155156
Toast.ShowWarning("No matching data found.");
156157
return;
157158
}
158-
await Editor.Open(new()
159+
var task = Editor.Open(new()
159160
{
160161
TypeName = "ReportRender", Title = name, Model = new { Html = $"<div class=\"report-output\">{html}</div>" },
161162
Large = true, ReadOnly = true,
@@ -168,6 +169,11 @@ await Editor.Open(new()
168169
}
169170
]
170171
});
172+
173+
await Task.Delay(50);
174+
await jsReports.InvokeVoidAsync("initCharts");
175+
176+
await task;
171177
}
172178

173179
private void AddLibrarySelectField(string title, Dictionary<Guid, string> list, ReportSelection selection,

Client/Pages/Reporting/Reporting.razor.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using FileFlows.Client.Components;
2+
using Microsoft.AspNetCore.Components;
3+
using Microsoft.JSInterop;
24

35
namespace FileFlows.Client.Pages;
46

@@ -7,6 +9,11 @@ namespace FileFlows.Client.Pages;
79
/// </summary>
810
public partial class Reporting : ListPage<Guid, ReportDefinition>
911
{
12+
/// <summary>
13+
/// Gets or sets the JS Runtime
14+
/// </summary>
15+
[Inject] public IJSRuntime jsRuntime { get; set; }
16+
1017
/// <summary>
1118
/// Gets or sets the report form editor component
1219
/// </summary>
@@ -21,4 +28,18 @@ public partial class Reporting : ListPage<Guid, ReportDefinition>
2128
/// <inheritdoc />
2229
protected override bool Licensed()
2330
=> Profile.LicensedFor(LicenseFlags.Reporting);
31+
32+
/// <summary>
33+
/// Reference to JS Report class
34+
/// </summary>
35+
private IJSObjectReference jsReports;
36+
37+
38+
/// <inheritdoc />
39+
protected override async Task OnInitializedAsync()
40+
{
41+
await base.OnInitializedAsync();
42+
var jsObjectReference = await jsRuntime.InvokeAsync<IJSObjectReference>("import", $"./Pages/Reporting/Reporting.razor.js?v={Globals.Version}");
43+
jsReports = await jsObjectReference.InvokeAsync<IJSObjectReference>("createReporting", [DotNetObjectReference.Create(this)]);
44+
}
2445
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Creates the Reporting instance and returns it
3+
* @param dotNetObject The calling dotnet object
4+
* @returns {InputCode} the Reporting instance
5+
*/
6+
export function createReporting(dotNetObject)
7+
{
8+
return new Reporting(dotNetObject);
9+
}
10+
11+
export class Reporting {
12+
13+
initCharts() {
14+
console.log('init charts!');
15+
let pieCharts = document.querySelectorAll('.report-output svg.pie-chart');
16+
17+
for (let pie of pieCharts) {
18+
console.log('pie', pie);
19+
let slices = pie.querySelectorAll('.slice');
20+
21+
for (let slice of slices) {
22+
slice.addEventListener('mouseover', () => {
23+
// Get tooltip content from data-tooltip attribute
24+
let tooltipText = slice.getAttribute('data-title');
25+
26+
// Create a tooltip element
27+
let tooltip = document.createElement('div');
28+
tooltip.classList.add('svg-tooltip');
29+
tooltip.textContent = tooltipText;
30+
31+
// Position the tooltip relative to the slice
32+
let rect = slice.getBoundingClientRect();
33+
tooltip.style.left = rect.left + rect.width / 2 + 'px';
34+
tooltip.style.top = rect.top + rect.height / 2 + 'px';
35+
36+
// Append tooltip to the body or another container
37+
document.body.appendChild(tooltip);
38+
});
39+
40+
slice.addEventListener('mouseout', () => {
41+
// Remove tooltip on mouse out
42+
let tooltip = document.querySelector('.svg-tooltip');
43+
if (tooltip) {
44+
tooltip.parentNode.removeChild(tooltip);
45+
}
46+
});
47+
}
48+
}
49+
}
50+
}

Client/wwwroot/css/app.css

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3786,6 +3786,12 @@ hr {
37863786
background: var(--danger);
37873787
}
37883788

3789+
.report-output {
3790+
text-align: center;
3791+
}
3792+
.report-output table {
3793+
text-align: left;
3794+
}
37893795
.report-output .percentage {
37903796
display: flex;
37913797
flex-direction: row;
@@ -3827,6 +3833,9 @@ hr {
38273833
background: rgba(77, 77, 77, 0.38);
38283834
background: linear-gradient(to right, rgba(94, 94, 94, 0.25), rgba(255, 255, 255, 0.5));
38293835
}
3836+
.report-output svg text {
3837+
fill: var(--color);
3838+
}
38303839

38313840
.Report.editor.large {
38323841
width: 65rem !important;
@@ -3837,3 +3846,13 @@ hr {
38373846
.daterangeinput {
38383847
max-width: 40rem;
38393848
}
3849+
3850+
.svg-tooltip {
3851+
position: absolute;
3852+
z-index: 6;
3853+
background: var(--base-lighter);
3854+
padding: 0.5rem;
3855+
border-radius: 0.5rem;
3856+
font-weight: var(--bold, 600);
3857+
font-size: 0.9rem;
3858+
}

Client/wwwroot/css/app.scss

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,10 @@ input[type=file]{
13121312

13131313
.report-output
13141314
{
1315+
text-align: center;
1316+
table {
1317+
text-align: left;
1318+
}
13151319
.percentage {
13161320
display: flex;
13171321
flex-direction: row;
@@ -1356,6 +1360,10 @@ input[type=file]{
13561360
}
13571361
}
13581362
}
1363+
1364+
svg text {
1365+
fill: var(--color);
1366+
}
13591367
}
13601368

13611369
.Report.editor.large {
@@ -1365,4 +1373,14 @@ input[type=file]{
13651373
}
13661374
.daterangeinput {
13671375
max-width: 40rem;
1376+
}
1377+
1378+
.svg-tooltip {
1379+
position:absolute;
1380+
z-index:6;
1381+
background: var(--base-lighter);
1382+
padding: 0.5rem;
1383+
border-radius: 0.5rem;
1384+
font-weight: var(--bold, 600);
1385+
font-size: 0.9rem;
13681386
}

DataLayer/Reports/Codec.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,15 @@ public override async Task<Result<string>> Generate(Dictionary<string, object> m
7777
}
7878
}
7979

80-
return GenerateHtmlTable(codecs.OrderByDescending(x => x.Value)
81-
.Select(x => new { Codec = x.Key, Count = x.Value }));
80+
var data = codecs.OrderByDescending(x => x.Value)
81+
.Select(x => new { Codec = x.Key, Count = x.Value })
82+
.ToList();
83+
84+
var table = GenerateHtmlTable(data) ?? string.Empty;
85+
86+
var chart = GenerateSvgPieChart(data.ToDictionary(x => x.Codec, x=> x.Count)) ?? string.Empty;
87+
88+
return table + chart;
8289

8390
}
8491
}

DataLayer/Reports/Language.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,17 @@ public override async Task<Result<string>> Generate(Dictionary<string, object> m
7777
}
7878
}
7979

80-
return GenerateHtmlTable(languages.OrderByDescending(x => x.Value)
81-
.Select(x => new { Language = LanguageHelper.GetEnglishFor(x.Key), Count = x.Value }));
80+
if (languages.Count == 0)
81+
return string.Empty;
82+
83+
var data = languages.OrderByDescending(x => x.Value)
84+
.Select(x => new { Language = LanguageHelper.GetEnglishFor(x.Key), Count = x.Value })
85+
.ToList();
86+
87+
var table = GenerateHtmlTable(data) ?? string.Empty;
88+
89+
var chart = GenerateSvgPieChart(data.ToDictionary(x => x.Language, x=> x.Count)) ?? string.Empty;
8290

91+
return table + chart;
8392
}
8493
}

0 commit comments

Comments
 (0)