Display results from Piscal processing
Error handling for Piscal processing
This commit is contained in:
@@ -8,5 +8,6 @@ namespace LeafWeb.Core.Remote
|
|||||||
PiscalStatus GetLeafInputFileStatus(PiscalLeafInputFile file);
|
PiscalStatus GetLeafInputFileStatus(PiscalLeafInputFile file);
|
||||||
IEnumerable<PiscalLeafOutputFile> RetrieveLeafOutput(PiscalLeafInputFile file);
|
IEnumerable<PiscalLeafOutputFile> RetrieveLeafOutput(PiscalLeafInputFile file);
|
||||||
void CleanupLeafProcess(PiscalLeafInputFile file);
|
void CleanupLeafProcess(PiscalLeafInputFile file);
|
||||||
|
string GetErrorMessage(PiscalLeafInputFile file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ namespace LeafWeb.Core.Remote
|
|||||||
|
|
||||||
private const string StatusSuccess = "success";
|
private const string StatusSuccess = "success";
|
||||||
private const string StatusRunning = "running";
|
private const string StatusRunning = "running";
|
||||||
|
private const string StatusNotStarted = "not started";
|
||||||
private const string StatusError = "error";
|
private const string StatusError = "error";
|
||||||
|
|
||||||
public PiscalSshClient(string connectionString)
|
public PiscalSshClient(string connectionString)
|
||||||
@@ -62,7 +63,7 @@ namespace LeafWeb.Core.Remote
|
|||||||
ssh.Disconnect();
|
ssh.Disconnect();
|
||||||
|
|
||||||
if (command.ExitStatus != 0)
|
if (command.ExitStatus != 0)
|
||||||
throw new PiscalClientException(command.Error);
|
throw new PiscalClientException(command.Result);
|
||||||
|
|
||||||
Console.Write(command.Result);
|
Console.Write(command.Result);
|
||||||
}
|
}
|
||||||
@@ -78,6 +79,8 @@ namespace LeafWeb.Core.Remote
|
|||||||
return PiscalStatus.Running;
|
return PiscalStatus.Running;
|
||||||
case StatusSuccess:
|
case StatusSuccess:
|
||||||
return PiscalStatus.Success;
|
return PiscalStatus.Success;
|
||||||
|
case StatusNotStarted:
|
||||||
|
return PiscalStatus.NotStarted;
|
||||||
default:
|
default:
|
||||||
return PiscalStatus.Error;
|
return PiscalStatus.Error;
|
||||||
}
|
}
|
||||||
@@ -94,7 +97,7 @@ namespace LeafWeb.Core.Remote
|
|||||||
ssh.Disconnect();
|
ssh.Disconnect();
|
||||||
|
|
||||||
if (command.ExitStatus != 0)
|
if (command.ExitStatus != 0)
|
||||||
throw new PiscalClientException(command.Error);
|
throw new PiscalClientException(command.Result);
|
||||||
|
|
||||||
return command.Result
|
return command.Result
|
||||||
.SplitNewLine()
|
.SplitNewLine()
|
||||||
@@ -137,6 +140,16 @@ namespace LeafWeb.Core.Remote
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetErrorMessage(PiscalLeafInputFile file)
|
||||||
|
{
|
||||||
|
var status = GetLeafInputStatusRaw(file);
|
||||||
|
if (status[0] != StatusError)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
var errorLines = status.Skip(1).ToArray();
|
||||||
|
return errorLines.Join(Environment.NewLine);
|
||||||
|
}
|
||||||
|
|
||||||
public void CleanupLeafProcess(PiscalLeafInputFile file)
|
public void CleanupLeafProcess(PiscalLeafInputFile file)
|
||||||
{
|
{
|
||||||
var status = GetLeafInputStatusRaw(file);
|
var status = GetLeafInputStatusRaw(file);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace LeafWeb.Core.Remote
|
|||||||
{
|
{
|
||||||
Running,
|
Running,
|
||||||
Success,
|
Success,
|
||||||
|
NotStarted,
|
||||||
Error
|
Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
@@ -50,5 +51,10 @@ namespace LeafWeb.Core.Utility
|
|||||||
{
|
{
|
||||||
return Regex.Replace(path, @".*/([^/]*$)", "$1");
|
return Regex.Replace(path, @".*/([^/]*$)", "$1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string Join<T>(this IEnumerable<T> enumerable, string separator)
|
||||||
|
{
|
||||||
|
return string.Join(separator, enumerable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using LeafWeb.Core.Entities;
|
using LeafWeb.Core.Entities;
|
||||||
using LeafWeb.Web.ViewModels.LeafOutput;
|
using LeafWeb.Web.ViewModels.LeafOutput;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
@@ -8,34 +9,71 @@ namespace LeafWeb.Web.Tests.ViewModels.LeafOutput
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class LeafOutputViewModelTests
|
public class LeafOutputViewModelTests
|
||||||
{
|
{
|
||||||
private LeafInputFile file = new LeafInputFile
|
private LeafInputFile GetLeafInputFile()
|
||||||
{
|
{
|
||||||
Filename = "MyFilename.ext",
|
return new LeafInputFile
|
||||||
Id = 3,
|
|
||||||
CurrentStatus = LeafInputStatusType.Running,
|
|
||||||
LeafInput = new LeafInput
|
|
||||||
{
|
{
|
||||||
Added = DateTime.Today,
|
Filename = "MyFilename.ext",
|
||||||
Email = "test@email.com",
|
Id = 3,
|
||||||
Identifier = "Ident I Fier",
|
CurrentStatus = LeafInputStatusType.Complete,
|
||||||
Name = "My Name",
|
LeafInput = new LeafInput
|
||||||
PhotosynthesisType = new PhotosynthesisType { Id = "1", Name = "1", SortOrder = 1}
|
{
|
||||||
},
|
Added = DateTime.Today,
|
||||||
LeafOutputFiles = new[] { new LeafOutputFile { Filename = "OutputFilename.txt" } }
|
Email = "test@email.com",
|
||||||
};
|
Identifier = "Ident I Fier",
|
||||||
|
Name = "My Name",
|
||||||
|
PhotosynthesisType = new PhotosynthesisType {Id = "1", Name = "1", SortOrder = 1}
|
||||||
|
},
|
||||||
|
LeafOutputFiles = new[] {new LeafOutputFile {Filename = "OutputFilename.txt"}}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void CanConstructFromLeafInputFile()
|
public void CanConstructFromLeafInputFile()
|
||||||
{
|
{
|
||||||
|
var file = GetLeafInputFile();
|
||||||
var viewModel = new LeafOutputViewModel(file);
|
var viewModel = new LeafOutputViewModel(file);
|
||||||
|
|
||||||
Assert.That(viewModel.CurrentStatus, Is.EqualTo(file.CurrentStatus.ToString()));
|
Assert.That(viewModel.CurrentStatus, Is.EqualTo(file.CurrentStatus.ToString()));
|
||||||
Assert.That(viewModel.LeafInputFileId, Is.EqualTo(file.Id));
|
Assert.That(viewModel.LeafInputFileId, Is.EqualTo(file.Id));
|
||||||
Assert.That(viewModel.LeafInputFilename, Is.EqualTo(file.Filename));
|
Assert.That(viewModel.LeafInputFilename, Is.EqualTo(file.Filename));
|
||||||
Assert.That(viewModel.LeafOutputFilenames, Is.Empty);
|
Assert.That(viewModel.LeafOutputFilenames, Has.Length.EqualTo(1));
|
||||||
Assert.That(viewModel.LeafInputIdentifier, Is.EqualTo(file.LeafInput.Identifier));
|
Assert.That(viewModel.LeafInputIdentifier, Is.EqualTo(file.LeafInput.Identifier));
|
||||||
Assert.That(viewModel.LeafInputSiteId, Is.EqualTo(file.LeafInput.SiteId));
|
Assert.That(viewModel.LeafInputSiteId, Is.EqualTo(file.LeafInput.SiteId));
|
||||||
Assert.That(viewModel.LeafInputPhotosynthesisType, Is.EqualTo(file.LeafInput.PhotosynthesisType.Name));
|
Assert.That(viewModel.LeafInputPhotosynthesisType, Is.EqualTo(file.LeafInput.PhotosynthesisType.Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CanConstructFromLeafInputFile_Running()
|
||||||
|
{
|
||||||
|
var file = GetLeafInputFile();
|
||||||
|
file.CurrentStatus = LeafInputStatusType.Running;
|
||||||
|
file.LeafOutputFiles = new LeafOutputFile[0];
|
||||||
|
var viewModel = new LeafOutputViewModel(file);
|
||||||
|
|
||||||
|
Assert.That(viewModel.CurrentStatus, Is.EqualTo(LeafInputStatusType.Running.ToString()));
|
||||||
|
Assert.That(viewModel.LeafOutputFilenames, Has.Length.EqualTo(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CanConstructFromLeafInputFile_Error()
|
||||||
|
{
|
||||||
|
var file = GetLeafInputFile();
|
||||||
|
file.CurrentStatus = LeafInputStatusType.Error;
|
||||||
|
file.StatusHistory = new []
|
||||||
|
{
|
||||||
|
new LeafInputFileStatus
|
||||||
|
{
|
||||||
|
DateTime = DateTime.Today,
|
||||||
|
LeafInputFile = file,
|
||||||
|
Description = "My Error",
|
||||||
|
Status = LeafInputStatusType.Error
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var viewModel = new LeafOutputViewModel(file);
|
||||||
|
|
||||||
|
Assert.That(viewModel.CurrentStatus, Is.EqualTo(LeafInputStatusType.Error.ToString()));
|
||||||
|
Assert.That(viewModel.ErrorMessages[0], Is.EqualTo(file.StatusHistory.First().Description));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
using System.Linq;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
|
using LeafWeb.Web.ViewModels.LeafOutput;
|
||||||
|
|
||||||
namespace LeafWeb.Web.Controllers
|
namespace LeafWeb.Web.Controllers
|
||||||
{
|
{
|
||||||
@@ -6,7 +8,11 @@ namespace LeafWeb.Web.Controllers
|
|||||||
{
|
{
|
||||||
public ActionResult Index()
|
public ActionResult Index()
|
||||||
{
|
{
|
||||||
var viewModel = DataService.GetLeafOutputFiles();
|
var viewModel =
|
||||||
|
DataService.GetLeafInputFiles()
|
||||||
|
.OrderByDescending(f => f.Id)
|
||||||
|
.ToList()
|
||||||
|
.Select(f => new LeafOutputViewModel(f));
|
||||||
return View(viewModel);
|
return View(viewModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
<rules>
|
<rules>
|
||||||
<logger name="Hangfire.*" minlevel="Debug" maxlevel="Info" final="true"/>
|
<logger name="Hangfire.*" minlevel="Debug" maxlevel="Info" final="true"/>
|
||||||
<logger name="*" minlevel="Debug" writeTo="debugLogger"/>
|
<logger name="*" minlevel="Trace" writeTo="debugLogger"/>
|
||||||
<logger name="*" minlevel="Error" writeTo="exceptionLogger" />
|
<logger name="*" minlevel="Error" writeTo="exceptionLogger" />
|
||||||
</rules>
|
</rules>
|
||||||
</nlog>
|
</nlog>
|
||||||
@@ -31,13 +31,18 @@ namespace LeafWeb.Web.Services
|
|||||||
{
|
{
|
||||||
logger.Trace("ProcessQueue entered");
|
logger.Trace("ProcessQueue entered");
|
||||||
|
|
||||||
ProcessRunning(logger);
|
try
|
||||||
|
{
|
||||||
|
ProcessRunning(logger);
|
||||||
|
|
||||||
ProcessQueue(logger);
|
ProcessQueue(logger);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
logger.Trace("ProcessQueue exit");
|
||||||
|
|
||||||
logger.Trace("ProcessQueue completed");
|
Monitor.Exit(ProcessQueueLock);
|
||||||
|
}
|
||||||
Monitor.Exit(ProcessQueueLock);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -54,14 +59,25 @@ namespace LeafWeb.Web.Services
|
|||||||
var queuedFile =
|
var queuedFile =
|
||||||
_dataService
|
_dataService
|
||||||
.GetLeafInputFiles(LeafInputStatusType.Queued)
|
.GetLeafInputFiles(LeafInputStatusType.Queued)
|
||||||
.OrderBy(l => l.Id)
|
.OrderBy(l => l.StatusHistory.Min(sh => sh.DateTime))
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
|
||||||
if (queuedFile == null)
|
if (queuedFile == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
logger.Info("LeafInputFile: {0}, Start", queuedFile.Id);
|
logger.Info("LeafInputFile: {0}, Start", queuedFile.Id);
|
||||||
_piscalService.Run(queuedFile);
|
try
|
||||||
|
{
|
||||||
|
_piscalService.Run(queuedFile);
|
||||||
|
}
|
||||||
|
catch (PiscalClientException ex)
|
||||||
|
{
|
||||||
|
logger.Error("LeafInputFile: {0}, ProcessQueue Exception: {1}", queuedFile.Id, ex.Message);
|
||||||
|
_dataService.SetLeafInputFileStatus(queuedFile, LeafInputStatusType.Error, "Error occurred submitting LeafInput");
|
||||||
|
|
||||||
|
// TODO: re-queue
|
||||||
|
//_dataService.SetLeafInputFileStatus(queuedFile, LeafInputStatusType.Queued, "Re-queuing LeafInput");
|
||||||
|
}
|
||||||
_dataService.SetLeafInputFileStatus(queuedFile, LeafInputStatusType.Running);
|
_dataService.SetLeafInputFileStatus(queuedFile, LeafInputStatusType.Running);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,33 +87,55 @@ namespace LeafWeb.Web.Services
|
|||||||
foreach (var file in runningLeafInputFiles)
|
foreach (var file in runningLeafInputFiles)
|
||||||
{
|
{
|
||||||
var status = _piscalService.GetStatus(file);
|
var status = _piscalService.GetStatus(file);
|
||||||
switch (status)
|
try
|
||||||
{
|
{
|
||||||
case PiscalStatus.Running:
|
switch (status)
|
||||||
logger.Trace("LeafInputFile: {0}, {1}", file.Id, status);
|
{
|
||||||
// continue running
|
case PiscalStatus.Running:
|
||||||
break;
|
logger.Trace("LeafInputFile: {0}, Running", file.Id);
|
||||||
case PiscalStatus.Success:
|
// continue running
|
||||||
logger.Info("LeafInputFile: {0}, {1}", file.Id, status);
|
break;
|
||||||
// collect the leaf output
|
|
||||||
var leafOutputFiles = _piscalService.RetrieveOutputFiles(file).ToList();
|
|
||||||
foreach (var outputFile in leafOutputFiles)
|
|
||||||
_dataService.AddLeafOutputFile(outputFile);
|
|
||||||
|
|
||||||
logger.Info("LeafInputFile: {0}, output files: {1}", file.Id,
|
case PiscalStatus.Success:
|
||||||
string.Join(", ", leafOutputFiles.Select(o => o.Filename)));
|
logger.Info("LeafInputFile: {0}, Success", file.Id);
|
||||||
|
// collect the leaf output
|
||||||
|
var leafOutputFiles = _piscalService.RetrieveOutputFiles(file).ToList();
|
||||||
|
foreach (var outputFile in leafOutputFiles)
|
||||||
|
_dataService.AddLeafOutputFile(outputFile);
|
||||||
|
|
||||||
// update db
|
logger.Info("LeafInputFile: {0}, output files: {1}", file.Id,
|
||||||
_dataService.SetLeafInputFileStatus(file, LeafInputStatusType.Complete);
|
string.Join(", ", leafOutputFiles.Select(o => o.Filename)));
|
||||||
|
|
||||||
// remove working data from the server
|
// update db
|
||||||
logger.Info("LeafInputFile: {0}, cleanup", file.Id);
|
_dataService.SetLeafInputFileStatus(file, LeafInputStatusType.Complete);
|
||||||
_piscalService.Cleanup(file);
|
|
||||||
break;
|
// remove working data from the server
|
||||||
case PiscalStatus.Error:
|
logger.Info("LeafInputFile: {0}, Cleanup", file.Id);
|
||||||
logger.Info("LeafInputFile: {0}, error", file.Id);
|
_piscalService.Cleanup(file);
|
||||||
_dataService.SetLeafInputFileStatus(file, LeafInputStatusType.Error);
|
break;
|
||||||
break;
|
|
||||||
|
case PiscalStatus.NotStarted:
|
||||||
|
logger.Warn("LeafInputFile: {0}, Not Started, re-queueing", file.Id);
|
||||||
|
// if it's not started, try to requeue the process - unusual state
|
||||||
|
_dataService.SetLeafInputFileStatus(file, LeafInputStatusType.Queued);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PiscalStatus.Error:
|
||||||
|
logger.Info("LeafInputFile: {0}, Error", file.Id);
|
||||||
|
|
||||||
|
var errorMessage = _piscalService.GetErrorMessage(file);
|
||||||
|
logger.Info("LeafInputFile: {0}, Error Message: {1}", file.Id, errorMessage);
|
||||||
|
|
||||||
|
_dataService.SetLeafInputFileStatus(file, LeafInputStatusType.Error, errorMessage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (PiscalClientException ex)
|
||||||
|
{
|
||||||
|
logger.Error("LeafInputFile: {0}, ProcessRunning Exception: {1}", file.Id, ex.Message);
|
||||||
|
_dataService.SetLeafInputFileStatus(file, LeafInputStatusType.Error, "Error occurred processing LeafInput");
|
||||||
|
|
||||||
|
// TODO: re-queue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,12 @@ namespace LeafWeb.Web.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetErrorMessage(LeafInputFile leafInputFile)
|
||||||
|
{
|
||||||
|
var inputFile = new PiscalLeafInputFile(leafInputFile);
|
||||||
|
return _piscalClient.GetErrorMessage(inputFile);
|
||||||
|
}
|
||||||
|
|
||||||
public void Cleanup(LeafInputFile leafInputFile)
|
public void Cleanup(LeafInputFile leafInputFile)
|
||||||
{
|
{
|
||||||
var inputFile = new PiscalLeafInputFile(leafInputFile);
|
var inputFile = new PiscalLeafInputFile(leafInputFile);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
|
using LeafWeb.Core.Entities;
|
||||||
|
|
||||||
namespace LeafWeb.Web.ViewModels.LeafOutput
|
namespace LeafWeb.Web.ViewModels.LeafOutput
|
||||||
{
|
{
|
||||||
@@ -10,7 +11,9 @@ namespace LeafWeb.Web.ViewModels.LeafOutput
|
|||||||
public int LeafInputFileId { get; set; }
|
public int LeafInputFileId { get; set; }
|
||||||
public string LeafInputFilename { get; set; }
|
public string LeafInputFilename { get; set; }
|
||||||
public string CurrentStatus { get; set; }
|
public string CurrentStatus { get; set; }
|
||||||
|
public string[] ErrorMessages { get; set; }
|
||||||
public string[] LeafOutputFilenames { get; set; }
|
public string[] LeafOutputFilenames { get; set; }
|
||||||
|
public string LeafInputName { get; set; }
|
||||||
public string LeafInputIdentifier { get; set; }
|
public string LeafInputIdentifier { get; set; }
|
||||||
public string LeafInputSiteId { get; set; }
|
public string LeafInputSiteId { get; set; }
|
||||||
public string LeafInputPhotosynthesisType { get; set; }
|
public string LeafInputPhotosynthesisType { get; set; }
|
||||||
@@ -20,19 +23,33 @@ namespace LeafWeb.Web.ViewModels.LeafOutput
|
|||||||
var config =
|
var config =
|
||||||
new MapperConfiguration(cfg =>
|
new MapperConfiguration(cfg =>
|
||||||
{
|
{
|
||||||
cfg.CreateMap<Core.Entities.LeafInputFile, LeafOutputViewModel>()
|
cfg.CreateMap<LeafInputFile, LeafOutputViewModel>()
|
||||||
.ForMember(dest => dest.LeafInputFileId, opt => opt.MapFrom(src => src.Id))
|
.ForMember(dest => dest.LeafInputFileId, opt => opt.MapFrom(src => src.Id))
|
||||||
.ForMember(dest => dest.LeafInputFilename, opt => opt.MapFrom(src => src.Filename))
|
.ForMember(dest => dest.LeafInputFilename, opt => opt.MapFrom(src => src.Filename))
|
||||||
.ForMember(dest => dest.LeafOutputFilenames,
|
.ForMember(dest => dest.LeafOutputFilenames,
|
||||||
opt => opt.ResolveUsing(file => file.LeafOutputFiles?.Select(o => o.Filename).ToArray() ?? new string[] {}))
|
opt => opt.ResolveUsing(
|
||||||
|
file =>
|
||||||
|
file.LeafOutputFiles?
|
||||||
|
.Select(o => o.Filename)
|
||||||
|
.ToArray()
|
||||||
|
?? new string[] {}))
|
||||||
|
.ForMember(dest => dest.LeafInputName, opt => opt.MapFrom(src => src.LeafInput.Name))
|
||||||
.ForMember(dest => dest.LeafInputIdentifier, opt => opt.MapFrom(src => src.LeafInput.Identifier))
|
.ForMember(dest => dest.LeafInputIdentifier, opt => opt.MapFrom(src => src.LeafInput.Identifier))
|
||||||
.ForMember(dest => dest.LeafInputSiteId, opt => opt.MapFrom(src => src.LeafInput.SiteId))
|
.ForMember(dest => dest.LeafInputSiteId, opt => opt.MapFrom(src => src.LeafInput.SiteId))
|
||||||
.ForMember(dest => dest.LeafInputPhotosynthesisType, opt => opt.MapFrom(src => src.LeafInput.PhotosynthesisType.Name));
|
.ForMember(dest => dest.LeafInputPhotosynthesisType, opt => opt.MapFrom(src => src.LeafInput.PhotosynthesisType.Name))
|
||||||
|
.ForMember(dest => dest.ErrorMessages,
|
||||||
|
opt => opt.ResolveUsing(
|
||||||
|
src =>
|
||||||
|
src.StatusHistory?
|
||||||
|
.Where(sh => sh.Status == LeafInputStatusType.Error)
|
||||||
|
.Select(sh => sh.Description)
|
||||||
|
.ToArray()
|
||||||
|
?? new string[] {}));
|
||||||
});
|
});
|
||||||
Mapper = config.CreateMapper();
|
Mapper = config.CreateMapper();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LeafOutputViewModel(Core.Entities.LeafInputFile leafInput)
|
public LeafOutputViewModel(LeafInputFile leafInput)
|
||||||
{
|
{
|
||||||
Mapper.Map(leafInput, this);
|
Mapper.Map(leafInput, this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
@model LeafWeb.Web.ViewModels.LeafOutput.LeafOutputViewModel
|
@model IEnumerable<LeafWeb.Web.ViewModels.LeafOutput.LeafOutputViewModel>
|
||||||
|
|
||||||
@{
|
@{
|
||||||
ViewBag.Title = "Users";
|
ViewBag.Title = "Results";
|
||||||
var grid = new WebGrid(Model, rowsPerPage: 45);
|
var grid = new WebGrid(Model, rowsPerPage: 45);
|
||||||
}
|
}
|
||||||
|
|
||||||
<h1>EDO Results</h1>
|
<h1>Results</h1>
|
||||||
|
|
||||||
<div class="row">
|
@grid.GetHtml(columns:
|
||||||
|
grid.Columns(
|
||||||
</div>
|
grid.Column("LeafInputIdentifier", "Identifier"),
|
||||||
|
grid.Column("LeafInputSiteId", "Site Id"),
|
||||||
|
grid.Column("LeafInputFilename", "Filename"),
|
||||||
|
grid.Column("LeafInputName", "Submitted By"),
|
||||||
|
grid.Column("CurrentStatus", "Status")
|
||||||
|
),
|
||||||
|
htmlAttributes: new { @class = "table table-striped table-bordered table-hover table-condensed" }
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user