-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #19 from davewalker5/FR-67-Job-Status-Report
Added Job Status report and export
- Loading branch information
Showing
12 changed files
with
332 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
FROM mcr.microsoft.com/dotnet/aspnet:latest AS runtime | ||
COPY flightrecorder.mvc-1.5.0.0 /opt/flightrecorder.mvc-1.5.0.0 | ||
WORKDIR /opt/flightrecorder.mvc-1.5.0.0/bin | ||
COPY flightrecorder.mvc-1.6.0.0 /opt/flightrecorder.mvc-1.6.0.0 | ||
WORKDIR /opt/flightrecorder.mvc-1.6.0.0/bin | ||
ENTRYPOINT [ "./FlightRecorder.Mvc" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
src/FlightRecorder.Mvc/Controllers/JobStatusController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
using FlightRecorder.Mvc.Api; | ||
using FlightRecorder.Mvc.Configuration; | ||
using FlightRecorder.Mvc.Entities; | ||
using FlightRecorder.Mvc.Models; | ||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.Extensions.Options; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Threading.Tasks; | ||
|
||
namespace FlightRecorder.Mvc.Controllers | ||
{ | ||
[Authorize] | ||
public class JobStatusController : Controller | ||
{ | ||
private readonly ReportsClient _reportsClient; | ||
private readonly ExportClient _exportClient; | ||
private readonly IOptions<AppSettings> _settings; | ||
|
||
public JobStatusController( | ||
ReportsClient reportsClient, | ||
ExportClient exportsClient, | ||
IOptions<AppSettings> settings) | ||
{ | ||
_reportsClient = reportsClient; | ||
_exportClient = exportsClient; | ||
_settings = settings; | ||
} | ||
|
||
/// <summary> | ||
/// Serve the empty report page | ||
/// </summary> | ||
/// <returns></returns> | ||
[HttpGet] | ||
public IActionResult Index() | ||
{ | ||
JobStatusViewModel model = new JobStatusViewModel | ||
{ | ||
PageNumber = 1 | ||
}; | ||
return View(model); | ||
} | ||
|
||
/// <summary> | ||
/// Respond to a POST event triggering the report generation | ||
/// </summary> | ||
/// <param name="model"></param> | ||
/// <returns></returns> | ||
[HttpPost] | ||
[ValidateAntiForgeryToken] | ||
public async Task<IActionResult> Index(JobStatusViewModel model) | ||
{ | ||
if (ModelState.IsValid) | ||
{ | ||
int page = model.PageNumber; | ||
switch (model.Action) | ||
{ | ||
case ControllerActions.ActionPreviousPage: | ||
page -= 1; | ||
break; | ||
case ControllerActions.ActionNextPage: | ||
page += 1; | ||
break; | ||
case ControllerActions.ActionSearch: | ||
page = 1; | ||
break; | ||
default: | ||
break; | ||
} | ||
|
||
// Need to clear model state here or the page number that was posted | ||
// is returned and page navigation doesn't work correctly. So, capture | ||
// and amend the page number, above, then apply it, below | ||
ModelState.Clear(); | ||
|
||
// Get the date and time | ||
DateTime start = !string.IsNullOrEmpty(model.From) ? DateTime.Parse(model.From) : DateTime.MinValue; | ||
DateTime end = !string.IsNullOrEmpty(model.To) ? DateTime.Parse(model.To) : DateTime.MaxValue; | ||
|
||
// Retrieve the matching report records | ||
List<JobStatus> records = await _reportsClient.JobStatusAsync(start, end, page, _settings.Value.SearchPageSize); | ||
model.SetRecords(records, page, _settings.Value.SearchPageSize); | ||
} | ||
|
||
return View(model); | ||
} | ||
|
||
/// <summary> | ||
/// Request export of the report | ||
/// </summary> | ||
/// <param name="model"></param> | ||
/// <returns></returns> | ||
[HttpPost] | ||
public async Task<IActionResult> Export([FromBody] JobStatusViewModel model) | ||
{ | ||
await _exportClient.ExportReport<JobStatus>(model); | ||
return Ok(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using System.ComponentModel.DataAnnotations; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System; | ||
|
||
namespace FlightRecorder.Mvc.Entities | ||
{ | ||
[ExcludeFromCodeCoverage] | ||
public class JobStatus | ||
{ | ||
[Key] | ||
public long Id { get; set; } | ||
public string Name { get; set; } | ||
public string Parameters { get; set; } | ||
public DateTime Start { get; set; } | ||
public DateTime? End { get; set; } | ||
public string Error { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
using FlightRecorder.Mvc.Entities; | ||
|
||
namespace FlightRecorder.Mvc.Models | ||
{ | ||
public class JobStatusViewModel : DateBasedReportViewModelBase<JobStatus> | ||
{ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
@using FlightRecorder.Mvc.Entities | ||
@model FlightRecorder.Mvc.Models.JobStatusViewModel | ||
|
||
@{ | ||
ViewData["Title"] = "Job Status Report"; | ||
string previousDisabled = (Model.PreviousEnabled) ? "" : "disabled"; | ||
string nextDisabled = (Model.NextEnabled) ? "" : "disabled"; | ||
} | ||
|
||
<p class="text-center font-weight-bold"> | ||
<span style="font-size: 1.2rem"> | ||
Job Status | ||
</span> | ||
<br /> | ||
<small class="text-muted"> | ||
<em> | ||
Report the status of background jobs | ||
</em> | ||
</small> | ||
</p> | ||
|
||
<div id="MessageContainer" style="display:none"> | ||
<div class="row"> | ||
<div class="col-md-12 message"> | ||
<span id="MessageText"></span> | ||
</div> | ||
</div> | ||
<hr /> | ||
</div> | ||
|
||
<div id="ErrorContainer" style="display:none"> | ||
<div class="row"> | ||
<div class="col-md-12 error"> | ||
<span id="ErrorText"></span> | ||
</div> | ||
</div> | ||
<hr /> | ||
</div> | ||
|
||
<div class="container-fluid"> | ||
@using (Html.BeginForm()) | ||
{ | ||
@Html.AntiForgeryToken() | ||
|
||
<div class="row"> | ||
<div class="col"> | ||
<strong>@Html.LabelFor(m => m.From)</strong> | ||
<div class="input-group"> | ||
@Html.EditorFor(m => m.From, new { @class = "form-control" }) | ||
<script type="text/javascript"> | ||
new GijgoDatePicker(document.getElementById("From"), { calendarWeeks: false, uiLibrary: "bootstrap4" }); | ||
</script> | ||
</div> | ||
<span>@Html.ValidationMessageFor(m => m.From, "", new { @class = "text-danger" })</span> | ||
</div> | ||
<div class="col"> | ||
<strong>@Html.LabelFor(m => m.To)</strong> | ||
<div class="input-group"> | ||
@Html.EditorFor(m => m.To, new { @class = "form-control" }) | ||
<script type="text/javascript"> | ||
new GijgoDatePicker(document.getElementById("To"), { calendarWeeks: false, uiLibrary: "bootstrap4" }); | ||
</script> | ||
</div> | ||
<span>@Html.ValidationMessageFor(m => m.To, "", new { @class = "text-danger" })</span> | ||
</div> | ||
<div class="col"> | ||
<strong><label> </label></strong> | ||
<div class="input-group"> | ||
@if (Model.Records != null) | ||
{ | ||
<button id="Export" class="btn btn-secondary">Export</button> | ||
<strong><label> </label></strong> | ||
} | ||
<button type="submit" name="Action" value="@ControllerActions.ActionSearch" class="btn btn-primary">Search</button> | ||
</div> | ||
</div> | ||
</div> | ||
<br /> | ||
|
||
@Html.HiddenFor(m => m.PageNumber) | ||
|
||
@if (Model.Records != null) | ||
{ | ||
<table class="table"> | ||
<tr> | ||
<th>Job Name</th> | ||
<th>Parameters</th> | ||
<th>Started</th> | ||
<th>Completed</th> | ||
<th>Errors</th> | ||
</tr> | ||
@foreach (var record in Model.Records) | ||
{ | ||
<tr> | ||
<td valign="center">@record.Name</td> | ||
<td valign="center">@record.Parameters</td> | ||
<td valign="center">@record.Start</td> | ||
<td valign="center">@record.End</td> | ||
<td valign="center">@record.Error</td> | ||
</tr> | ||
} | ||
</table> | ||
<hr /> | ||
<p class="text-right"> | ||
<button type="submit" name="Action" value="@ControllerActions.ActionPreviousPage" class="btn btn-secondary" @previousDisabled>Previous</button> | ||
<button type="submit" name="Action" value="@ControllerActions.ActionNextPage" class="btn btn-primary" @nextDisabled>Next</button> | ||
</p> | ||
} | ||
else if (Model.HasNoMatchingResults) | ||
{ | ||
<hr /> | ||
@Html.Raw("Airline statistics are not available") | ||
} | ||
} | ||
</div> | ||
|
||
<script type="text/javascript"> | ||
function ExportReport(url) { | ||
// Hide the error and message elements | ||
$("#MessageContainer").hide(); | ||
$("#WarningContainer").hide(); | ||
$("#ErrorContainer").hide(); | ||
|
||
// Construct the model holding the export parameters to POST to the controller | ||
const model = { | ||
"From": $("#From").val(), | ||
"To": $("#To").val() | ||
}; | ||
|
||
// Set a busy cursor | ||
$('html, body').css("cursor", "wait"); | ||
|
||
// POST the data to the controller | ||
$.ajax({ | ||
url: url, | ||
method: "POST", | ||
data: JSON.stringify(model), | ||
contentType: "application/json", | ||
cache: false, | ||
success: function (result) { | ||
// Worked, so show an "OK" message | ||
$("#MessageText").text("The report export has been queued in the background"); | ||
$("#MessageContainer").show(); | ||
$('html, body').css("cursor", "auto"); | ||
}, | ||
error: function (xhr, status, error) { | ||
// Failed, so show an error message | ||
var errorMessage = xhr.status + ': ' + xhr.statusText | ||
$("#ErrorText").text(errorMessage); | ||
$("#ErrorContainer").show(); | ||
$('html, body').css("cursor", "auto"); | ||
} | ||
}); | ||
} | ||
|
||
$(document).ready(function () { | ||
// Respond to a click on the "Export" button by POSTing an export request back | ||
$("#Export").click(function (e) { | ||
e.preventDefault(); | ||
ExportReport("/JobStatus/Export"); | ||
}); | ||
}); | ||
</script> |
Oops, something went wrong.