Details and queue management
This commit is contained in:
@@ -21,6 +21,15 @@ namespace LeafWeb.Core.Entities
|
|||||||
public LeafInputStatusType CurrentStatus { get; set; }
|
public LeafInputStatusType CurrentStatus { get; set; }
|
||||||
public virtual ICollection<LeafInputStatus> StatusHistory { get; set; }
|
public virtual ICollection<LeafInputStatus> StatusHistory { get; set; }
|
||||||
|
|
||||||
|
public bool IsInProgress => CurrentStatus == LeafInputStatusType.Starting
|
||||||
|
|| CurrentStatus == LeafInputStatusType.Running
|
||||||
|
|| CurrentStatus == LeafInputStatusType.Finishing;
|
||||||
|
|
||||||
|
public bool IsComplete => CurrentStatus == LeafInputStatusType.Complete;
|
||||||
|
public bool IsDeletable => !IsInProgress;
|
||||||
|
public bool IsPending => CurrentStatus == LeafInputStatusType.Pending;
|
||||||
|
public bool IsRunning => CurrentStatus == LeafInputStatusType.Running;
|
||||||
|
|
||||||
[Required(ErrorMessage = "Name required")]
|
[Required(ErrorMessage = "Name required")]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
C:\Users\poprhythm\AppData\Local\Temp\Temporary ASP.NET Files\vs\f80e29bb\faae20bf\App_Web_all.generated.cs.8f9494c4.vnu9hbgh.dll
|
C:\Users\poprhythm\AppData\Local\Temp\Temporary ASP.NET Files\vs\f80e29bb\faae20bf\App_Web_all.generated.cs.8f9494c4.xctgaqtc.dll
|
||||||
@@ -39,7 +39,7 @@ a.banner-link:hover {
|
|||||||
.headline-icon {
|
.headline-icon {
|
||||||
/* http://glyphicons.bootstrapcheatsheets.com/ */ }
|
/* http://glyphicons.bootstrapcheatsheets.com/ */ }
|
||||||
.headline-icon h1:after {
|
.headline-icon h1:after {
|
||||||
color: #c4e29d;
|
color: rgba(172, 214, 118, 0.8);
|
||||||
font-family: "Glyphicons Halflings";
|
font-family: "Glyphicons Halflings";
|
||||||
font-size: .8em;
|
font-size: .8em;
|
||||||
padding-left: 10px; }
|
padding-left: 10px; }
|
||||||
@@ -61,6 +61,11 @@ a.banner-link:hover {
|
|||||||
font-size: .8em;
|
font-size: .8em;
|
||||||
padding-left: 5px; }
|
padding-left: 5px; }
|
||||||
|
|
||||||
|
.status.status-pending {
|
||||||
|
color: #f0ad4e; }
|
||||||
|
.status.status-pending:after {
|
||||||
|
content: "\e023"; }
|
||||||
|
|
||||||
.status.status-complete {
|
.status.status-complete {
|
||||||
color: #337ab7; }
|
color: #337ab7; }
|
||||||
.status.status-complete:after {
|
.status.status-complete:after {
|
||||||
@@ -71,15 +76,12 @@ a.banner-link:hover {
|
|||||||
.status.status-exception:after {
|
.status.status-exception:after {
|
||||||
content: "\e101"; }
|
content: "\e101"; }
|
||||||
|
|
||||||
.status.status-running, .status.status-pending, .status.status-starting, .status.status-finishing {
|
.status.status-running, .status.status-starting, .status.status-finishing {
|
||||||
color: #3c763d; }
|
color: #3c763d; }
|
||||||
|
|
||||||
.status.status-running:after {
|
.status.status-running:after {
|
||||||
content: "\e089"; }
|
content: "\e089"; }
|
||||||
|
|
||||||
.status.status-pending:after {
|
|
||||||
content: "\e023"; }
|
|
||||||
|
|
||||||
.status.status-starting:after {
|
.status.status-starting:after {
|
||||||
content: "\e026"; }
|
content: "\e026"; }
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
h1{padding:24px 0 12px 0;}p{padding:12px 0;}footer{margin-top:24px !important;}.row-no-padding [class*="col-"]{padding-left:0 !important;padding-right:0 !important;}.home .dark .row:first-child .column:first-child h1{padding-top:0;}.home .blogarchive{padding-top:20px;}.banner-link{white-space:normal;padding:20px;background:#000;background:rgba(0,0,0,.5);-moz-border-radius:10px;border-radius:10px;}.banner-link .glyphicon{color:#8cc641;}a.banner-link:hover{text-decoration:none;background:rgba(0,0,0,.6);}a.banner-link:hover .glyphicon{color:#a8ed4e;}.headline-icon h1:after{color:#c4e29d;font-family:"Glyphicons Halflings";font-size:.8em;padding-left:10px;}.headline-icon.headline-icon-file h1:after{content:"";}.headline-icon.headline-icon-leaf h1:after{content:"";}.headline-icon.headline-icon-question h1:after{content:"";}.headline-icon.headline-icon-stats h1:after{content:"";}.headline-icon.headline-icon-user h1:after{content:"";}.headline-icon.headline-icon-list h1:after{content:"";}.status:after{font-family:"Glyphicons Halflings";font-size:.8em;padding-left:5px;}.status.status-complete{color:#337ab7;}.status.status-complete:after{content:"";}.status.status-exception{color:#a94442;}.status.status-exception:after{content:"";}.status.status-running,.status.status-pending,.status.status-starting,.status.status-finishing{color:#3c763d;}.status.status-running:after{content:"";}.status.status-pending:after{content:"";}.status.status-starting:after{content:"";}.status.status-finishing:after{content:"";}#chart{padding-top:20px;}.btn-file{position:relative;overflow:hidden;}.btn-file input[type=file]{position:absolute;top:0;right:0;min-width:100%;min-height:100%;font-size:100px;text-align:right;filter:alpha(opacity=0);opacity:0;outline:none;background:#fff;cursor:inherit;display:block;}form .validation-summary-errors ul{list-style-type:none;}.autocomplete-suggestions{border:1px solid #999;background:#fff;overflow:auto;}.autocomplete-suggestion{padding:2px 5px;white-space:nowrap;overflow:hidden;}.autocomplete-selected{background:#f0f0f0;}.autocomplete-suggestions strong{font-weight:normal;color:#39f;}.autocomplete-group{padding:2px 5px;}.autocomplete-group strong{display:block;border-bottom:1px solid #000;}.toggle{width:15px;}
|
h1{padding:24px 0 12px 0;}p{padding:12px 0;}footer{margin-top:24px !important;}.row-no-padding [class*="col-"]{padding-left:0 !important;padding-right:0 !important;}.home .dark .row:first-child .column:first-child h1{padding-top:0;}.home .blogarchive{padding-top:20px;}.banner-link{white-space:normal;padding:20px;background:#000;background:rgba(0,0,0,.5);-moz-border-radius:10px;border-radius:10px;}.banner-link .glyphicon{color:#8cc641;}a.banner-link:hover{text-decoration:none;background:rgba(0,0,0,.6);}a.banner-link:hover .glyphicon{color:#a8ed4e;}.headline-icon h1:after{color:rgba(172,214,118,.8);font-family:"Glyphicons Halflings";font-size:.8em;padding-left:10px;}.headline-icon.headline-icon-file h1:after{content:"";}.headline-icon.headline-icon-leaf h1:after{content:"";}.headline-icon.headline-icon-question h1:after{content:"";}.headline-icon.headline-icon-stats h1:after{content:"";}.headline-icon.headline-icon-user h1:after{content:"";}.headline-icon.headline-icon-list h1:after{content:"";}.status:after{font-family:"Glyphicons Halflings";font-size:.8em;padding-left:5px;}.status.status-pending{color:#f0ad4e;}.status.status-pending:after{content:"";}.status.status-complete{color:#337ab7;}.status.status-complete:after{content:"";}.status.status-exception{color:#a94442;}.status.status-exception:after{content:"";}.status.status-running,.status.status-starting,.status.status-finishing{color:#3c763d;}.status.status-running:after{content:"";}.status.status-starting:after{content:"";}.status.status-finishing:after{content:"";}#chart{padding-top:20px;}.btn-file{position:relative;overflow:hidden;}.btn-file input[type=file]{position:absolute;top:0;right:0;min-width:100%;min-height:100%;font-size:100px;text-align:right;filter:alpha(opacity=0);opacity:0;outline:none;background:#fff;cursor:inherit;display:block;}form .validation-summary-errors ul{list-style-type:none;}.autocomplete-suggestions{border:1px solid #999;background:#fff;overflow:auto;}.autocomplete-suggestion{padding:2px 5px;white-space:nowrap;overflow:hidden;}.autocomplete-selected{background:#f0f0f0;}.autocomplete-suggestions strong{font-weight:normal;color:#39f;}.autocomplete-group{padding:2px 5px;}.autocomplete-group strong{display:block;border-bottom:1px solid #000;}.toggle{width:15px;}
|
||||||
@@ -59,7 +59,7 @@ a.banner-link:hover {
|
|||||||
.headline-icon {
|
.headline-icon {
|
||||||
|
|
||||||
h1:after {
|
h1:after {
|
||||||
color: #c4e29d;
|
color: rgba(172, 214, 118, 0.8);
|
||||||
font-family: "Glyphicons Halflings";
|
font-family: "Glyphicons Halflings";
|
||||||
font-size: .8em;
|
font-size: .8em;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
@@ -95,7 +95,13 @@ a.banner-link:hover {
|
|||||||
font-size: .8em;
|
font-size: .8em;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.status-pending {
|
||||||
|
color: #f0ad4e;
|
||||||
|
&:after {
|
||||||
|
content:"\e023";
|
||||||
|
}
|
||||||
|
}
|
||||||
&.status-complete {
|
&.status-complete {
|
||||||
color: #337ab7;
|
color: #337ab7;
|
||||||
&:after {
|
&:after {
|
||||||
@@ -109,15 +115,12 @@ a.banner-link:hover {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.status-running,&.status-pending,&.status-starting,&.status-finishing {
|
&.status-running,&.status-starting,&.status-finishing {
|
||||||
color: #3c763d;
|
color: #3c763d;
|
||||||
}
|
}
|
||||||
&.status-running:after {
|
&.status-running:after {
|
||||||
content:"\e089";
|
content:"\e089";
|
||||||
}
|
}
|
||||||
&.status-pending:after {
|
|
||||||
content:"\e023";
|
|
||||||
}
|
|
||||||
&.status-starting:after {
|
&.status-starting:after {
|
||||||
content:"\e026";
|
content:"\e026";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Web.Mvc;
|
||||||
|
|
||||||
|
namespace LeafWeb.WebCms.Controllers
|
||||||
|
{
|
||||||
|
// http://stackoverflow.com/a/9036075/99492
|
||||||
|
public class EnforceTrueAttribute : ValidationAttribute, IClientValidatable
|
||||||
|
{
|
||||||
|
public override bool IsValid(object value)
|
||||||
|
{
|
||||||
|
if (value == null) return false;
|
||||||
|
if (value.GetType() != typeof(bool)) throw new InvalidOperationException("can only be used on boolean properties.");
|
||||||
|
return (bool)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string FormatErrorMessage(string name)
|
||||||
|
{
|
||||||
|
return "The " + name + " field must be checked in order to continue.";
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
|
||||||
|
{
|
||||||
|
yield return new ModelClientValidationRule
|
||||||
|
{
|
||||||
|
ErrorMessage =
|
||||||
|
string.IsNullOrEmpty(ErrorMessage)
|
||||||
|
? FormatErrorMessage(metadata.DisplayName)
|
||||||
|
: ErrorMessage,
|
||||||
|
ValidationType = "enforcetrue"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
|
using Hangfire;
|
||||||
using LeafWeb.Core.Entities;
|
using LeafWeb.Core.Entities;
|
||||||
using LeafWeb.Core.Utility;
|
using LeafWeb.Core.Utility;
|
||||||
using LeafWeb.WebCms.Models;
|
using LeafWeb.WebCms.Models;
|
||||||
|
using LeafWeb.WebCms.Services;
|
||||||
|
|
||||||
namespace LeafWeb.WebCms.Controllers
|
namespace LeafWeb.WebCms.Controllers
|
||||||
{
|
{
|
||||||
@@ -73,23 +75,45 @@ namespace LeafWeb.WebCms.Controllers
|
|||||||
return new FileContentResult(zip, "application/zip") { FileDownloadName = filename };
|
return new FileContentResult(zip, "application/zip") { FileDownloadName = filename };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[ActionLog]
|
||||||
public ActionResult Delete(int id)
|
public ActionResult Delete(int id)
|
||||||
{
|
{
|
||||||
var leafInput = DataService.GetLeafInput(id);
|
var leafInput = DataService.GetLeafInput(id);
|
||||||
var viewModel = new LeafInputCreate();
|
|
||||||
return View(viewModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost, ActionName("Delete")]
|
// don't allow currently running LeafInput to be deleted
|
||||||
[ActionLog]
|
if (leafInput.IsRunning)
|
||||||
public ActionResult DeleteConfirmed(int id)
|
{
|
||||||
{
|
SetStatusMessage($"LeafInput '{leafInput.Identifier}' is currently running!", StatusType.Error);
|
||||||
// TODO: don't allow currently running LeafInput to be deleted
|
return View(Request.UrlReferrer.ToString());
|
||||||
var leafInput = DataService.GetLeafInput(id);
|
}
|
||||||
|
|
||||||
DataService.DeleteLeafInput(leafInput);
|
DataService.DeleteLeafInput(leafInput);
|
||||||
|
|
||||||
SetStatusMessage($"LeafInput '{leafInput.Identifier}' deleted");
|
SetStatusMessage($"LeafInput '{leafInput.Identifier}' deleted");
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[ActionLog]
|
||||||
|
public ActionResult SendUserDownloadLink(int id)
|
||||||
|
{
|
||||||
|
var leafInput = DataService.GetLeafInput(id);
|
||||||
|
if (!leafInput.IsComplete)
|
||||||
|
{
|
||||||
|
SetStatusMessage($"LeafInput '{leafInput.Identifier}' is not complete!", StatusType.Error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var leafInputId = leafInput.Id;
|
||||||
|
BackgroundJob.Enqueue<EmailNotificationService>(e => e.SendLeafWebComplete(leafInputId));
|
||||||
|
SetStatusMessage($"LeafInput '{leafInput.Identifier}' download link sent", StatusType.Success);
|
||||||
|
}
|
||||||
|
return View(Request.UrlReferrer.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[ActionLog]
|
||||||
|
public ActionResult SendUserChartLink(int id)
|
||||||
|
{
|
||||||
|
throw new System.NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using LeafWeb.Core.DAL;
|
using LeafWeb.Core.DAL;
|
||||||
using LeafWeb.Core.Entities;
|
using LeafWeb.Core.Entities;
|
||||||
|
using LeafWeb.WebCms.Controllers;
|
||||||
|
|
||||||
namespace LeafWeb.WebCms.Models
|
namespace LeafWeb.WebCms.Models
|
||||||
{
|
{
|
||||||
@@ -20,7 +21,7 @@ namespace LeafWeb.WebCms.Models
|
|||||||
|
|
||||||
[Display(Name = "Confirm email address")]
|
[Display(Name = "Confirm email address")]
|
||||||
[Required(ErrorMessage = "Enter email exactly as above")]
|
[Required(ErrorMessage = "Enter email exactly as above")]
|
||||||
[Compare("Email")]
|
[System.ComponentModel.DataAnnotations.Compare("Email")]
|
||||||
public string EmailConfirm { get; set; }
|
public string EmailConfirm { get; set; }
|
||||||
|
|
||||||
[Display(Name = "A unique identifier for this data")]
|
[Display(Name = "A unique identifier for this data")]
|
||||||
@@ -35,6 +36,10 @@ namespace LeafWeb.WebCms.Models
|
|||||||
[Required(ErrorMessage = "A Photosynthetic pathway must be chosen")]
|
[Required(ErrorMessage = "A Photosynthetic pathway must be chosen")]
|
||||||
public SelectListViewModel PhotosynthesisType { get; set; }
|
public SelectListViewModel PhotosynthesisType { get; set; }
|
||||||
|
|
||||||
|
[UIHint("TermsOfService")]
|
||||||
|
[EnforceTrue(ErrorMessage = "Terms of Service must be accepted to continue")]
|
||||||
|
public bool? TermsOfService { get; set; }
|
||||||
|
|
||||||
static LeafInputCreate()
|
static LeafInputCreate()
|
||||||
{
|
{
|
||||||
Mapper.CreateMap<LeafInputCreate, LeafInput>()
|
Mapper.CreateMap<LeafInputCreate, LeafInput>()
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Web.Mvc;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using LeafWeb.Core.Entities;
|
using LeafWeb.Core.Entities;
|
||||||
using LeafWeb.Core.Utility;
|
using LeafWeb.Core.Utility;
|
||||||
@@ -9,6 +11,9 @@ namespace LeafWeb.WebCms.Models
|
|||||||
{
|
{
|
||||||
public class LeafInputDetails
|
public class LeafInputDetails
|
||||||
{
|
{
|
||||||
|
[HiddenInput(DisplayValue = false)]
|
||||||
|
public int LeafInputId { get; set; }
|
||||||
|
|
||||||
[Display(Name = "Name")]
|
[Display(Name = "Name")]
|
||||||
[Required(ErrorMessage = "Name required")]
|
[Required(ErrorMessage = "Name required")]
|
||||||
[RegularExpression(@"[A-Za-z().]+(\s+[A-Za-z().]+)+", ErrorMessage = "Please provide full name")]
|
[RegularExpression(@"[A-Za-z().]+(\s+[A-Za-z().]+)+", ErrorMessage = "Please provide full name")]
|
||||||
@@ -48,6 +53,18 @@ namespace LeafWeb.WebCms.Models
|
|||||||
[UIHint("LeafInputStatusViewModels")]
|
[UIHint("LeafInputStatusViewModels")]
|
||||||
public List<LeafInputStatusViewModel> StatusHistory { get; set; }
|
public List<LeafInputStatusViewModel> StatusHistory { get; set; }
|
||||||
|
|
||||||
|
[HiddenInput(DisplayValue = false)]
|
||||||
|
public bool HasLeafChart { get; set; }
|
||||||
|
|
||||||
|
[HiddenInput(DisplayValue = false)]
|
||||||
|
public bool IsRunning { get; set; }
|
||||||
|
|
||||||
|
[HiddenInput(DisplayValue = false)]
|
||||||
|
public bool IsComplete { get; set; }
|
||||||
|
|
||||||
|
[HiddenInput(DisplayValue = false)]
|
||||||
|
public bool IsDeletable { get; set; }
|
||||||
|
|
||||||
static LeafInputDetails()
|
static LeafInputDetails()
|
||||||
{
|
{
|
||||||
Mapper.CreateMap<LeafInputFile, string>().ConvertUsing(file => file?.Contents.GetString());
|
Mapper.CreateMap<LeafInputFile, string>().ConvertUsing(file => file?.Contents.GetString());
|
||||||
@@ -55,7 +72,9 @@ namespace LeafWeb.WebCms.Models
|
|||||||
Mapper.CreateMap<LeafInputStatusType, string>().ConvertUsing(st => st.ToString());
|
Mapper.CreateMap<LeafInputStatusType, string>().ConvertUsing(st => st.ToString());
|
||||||
Mapper.CreateMap<LeafInputStatusType, LeafInputStatus>().ConvertUsing(st => new LeafInputStatus());
|
Mapper.CreateMap<LeafInputStatusType, LeafInputStatus>().ConvertUsing(st => new LeafInputStatus());
|
||||||
Mapper.CreateMap<LeafInputStatus, LeafInputStatusViewModel>();
|
Mapper.CreateMap<LeafInputStatus, LeafInputStatusViewModel>();
|
||||||
Mapper.CreateMap<LeafInput, LeafInputDetails>();
|
Mapper.CreateMap<LeafInput, LeafInputDetails>()
|
||||||
|
.ForMember(dest => dest.LeafInputId, opt => opt.MapFrom(src => src.Id))
|
||||||
|
.ForMember(dest => dest.HasLeafChart, opt => opt.ResolveUsing(src => src.OutputFiles.Any(o => o.IsLeafChartFile)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public LeafInputDetails(LeafInput leafInput)
|
public LeafInputDetails(LeafInput leafInput)
|
||||||
|
|||||||
@@ -12,7 +12,12 @@ namespace LeafWeb.WebCms.Models
|
|||||||
public string LeafInputSiteId { get; set; }
|
public string LeafInputSiteId { get; set; }
|
||||||
public string LeafInputPhotosynthesisType { get; set; }
|
public string LeafInputPhotosynthesisType { get; set; }
|
||||||
public bool HasLeafChart { get; set; }
|
public bool HasLeafChart { get; set; }
|
||||||
|
public bool IsRunning { get; set; }
|
||||||
|
public bool IsComplete { get; set; }
|
||||||
|
public bool IsDeletable { get; set; }
|
||||||
|
public bool IsPending { get; set; }
|
||||||
public string CurrentStatus { get; set; }
|
public string CurrentStatus { get; set; }
|
||||||
|
|
||||||
//public string[] ErrorMessages { get; set; }
|
//public string[] ErrorMessages { get; set; }
|
||||||
//public string[] LeafOutputFilenames { get; set; }
|
//public string[] LeafOutputFilenames { get; set; }
|
||||||
//public bool HasLeafChartOutputFile { get; set; }
|
//public bool HasLeafChartOutputFile { get; set; }
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace LeafWeb.WebCms.Services
|
|||||||
|
|
||||||
private readonly string _emailFromAddress;
|
private readonly string _emailFromAddress;
|
||||||
|
|
||||||
private const string EmailSuccessSubject = "LeafWeb Results";
|
private const string EmailSuccessSubject = "LeafWeb results";
|
||||||
private const string EmailErrorSubject = "LeafWeb processing error";
|
private const string EmailErrorSubject = "LeafWeb processing error";
|
||||||
private const string EmailSystemErrorSubject = "LeafWeb system error";
|
private const string EmailSystemErrorSubject = "LeafWeb system error";
|
||||||
|
|
||||||
@@ -58,6 +58,11 @@ namespace LeafWeb.WebCms.Services
|
|||||||
public void SendLeafWebComplete(int leafInputId)
|
public void SendLeafWebComplete(int leafInputId)
|
||||||
{
|
{
|
||||||
var leafInput = _dataService.GetLeafInput(leafInputId);
|
var leafInput = _dataService.GetLeafInput(leafInputId);
|
||||||
|
if (leafInput.CurrentStatus != LeafInputStatusType.Complete)
|
||||||
|
{
|
||||||
|
Logger.Error($"Attempting to SendLeafWebComplete when status is not complete for leafInput: {leafInput}, current status: {leafInput.CurrentStatus}");
|
||||||
|
throw new ArgumentException($"Attempting to SendLeafWebComplete when status is not complete for leafInput: {leafInput}, current status: {leafInput.CurrentStatus}");
|
||||||
|
}
|
||||||
|
|
||||||
var outputErrorMessage = leafInput.OutputErrorMessage;
|
var outputErrorMessage = leafInput.OutputErrorMessage;
|
||||||
if (outputErrorMessage != null)
|
if (outputErrorMessage != null)
|
||||||
|
|||||||
@@ -83,15 +83,15 @@ namespace LeafWeb.WebCms.Services.PiscalQueue
|
|||||||
Logger.InfoFormat("LeafInput: {0}, Starting", pendingInputId);
|
Logger.InfoFormat("LeafInput: {0}, Starting", pendingInputId);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
DataService.SetLeafInputStatus(pendingInput, LeafInputStatusType.Starting,
|
DataService.SetLeafInputStatus(pendingInput, LeafInputStatusType.Starting, "Copying input to Piscal",
|
||||||
details: $"File count: {pendingInput.InputFiles.Count}");
|
$"File count: {pendingInput.InputFiles.Count}");
|
||||||
BackgroundJobEnqueueRetry<StartPending>(c => c.DoWork(pendingInputId));
|
BackgroundJobEnqueueRetry<StartPending>(c => c.DoWork(pendingInputId));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
var errorMessage = FormatException(ex);
|
var errorMessage = FormatException(ex);
|
||||||
Logger.Error(errorMessage);
|
Logger.Error(errorMessage);
|
||||||
DataService.SetLeafInputStatus(pendingInput, LeafInputStatusType.Exception, ex.Message, errorMessage);
|
DataService.SetLeafInputStatus(pendingInput, LeafInputStatusType.Exception, "Exception while StartPending", errorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,8 +108,9 @@ namespace LeafWeb.WebCms.Services.PiscalQueue
|
|||||||
{
|
{
|
||||||
case PiscalStatus.NotStarted:
|
case PiscalStatus.NotStarted:
|
||||||
// if it's not started - this is unusual state
|
// if it's not started - this is unusual state
|
||||||
PiscalWarningHandler($"LeafInput: {leafInput.Id}, Piscal reporting Not Started, setting to pending to retry", leafInput);
|
var pendingToRetry = "Piscal reporting Not Started, setting to Pending to retry";
|
||||||
DataService.SetLeafInputStatus(leafInput, LeafInputStatusType.Pending);
|
PiscalWarningHandler($"LeafInput: {leafInput.Id}, {pendingToRetry}", leafInput);
|
||||||
|
DataService.SetLeafInputStatus(leafInput, LeafInputStatusType.Pending, details: pendingToRetry);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PiscalStatus.Running:
|
case PiscalStatus.Running:
|
||||||
@@ -118,7 +119,7 @@ namespace LeafWeb.WebCms.Services.PiscalQueue
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PiscalStatus.Complete:
|
case PiscalStatus.Complete:
|
||||||
DataService.SetLeafInputStatus(leafInput, LeafInputStatusType.Finishing);
|
DataService.SetLeafInputStatus(leafInput, LeafInputStatusType.Finishing, "Copying output from Piscal");
|
||||||
BackgroundJobEnqueueRetry<FinishComplete>(s => s.DoWork(leafInputId));
|
BackgroundJobEnqueueRetry<FinishComplete>(s => s.DoWork(leafInputId));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace LeafWeb.WebCms.Services.PiscalQueue
|
|||||||
|
|
||||||
PiscalService.Run(leafInput);
|
PiscalService.Run(leafInput);
|
||||||
|
|
||||||
DataService.SetLeafInputStatus(leafInput, LeafInputStatusType.Running, details: $"ServiceInfo: {PiscalService.ServiceDescription}");
|
DataService.SetLeafInputStatus(leafInput, LeafInputStatusType.Running, "Starting Piscal", $"{PiscalService.ServiceDescription}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
@Html.EditorFor(m => m.Name)
|
@Html.EditorFor(m => m.Name)
|
||||||
@Html.EditorFor(m => m.Email)
|
@Html.EditorFor(m => m.Email)
|
||||||
@Html.EditorFor(m => m.EmailConfirm)
|
@Html.EditorFor(m => m.EmailConfirm)
|
||||||
<a href="@UmbracoContext.Current.UrlProvider.GetUrl(1115)" target="_blank">Terms of Service</a>
|
@Html.EditorFor(m => m.TermsOfService)
|
||||||
<input type="submit" id="submit-form" class="hidden"/>
|
<input type="submit" id="submit-form" class="hidden"/>
|
||||||
}
|
}
|
||||||
<label for="submit-form" class="btn btn-primary pull-right">Submit...</label>
|
<label for="submit-form" class="btn btn-primary pull-right">Submit...</label>
|
||||||
|
|||||||
@@ -1,3 +1,35 @@
|
|||||||
@model LeafWeb.WebCms.Models.LeafInputDetails
|
@model LeafWeb.WebCms.Models.LeafInputDetails
|
||||||
|
|
||||||
|
<div class="btn-group" role="group">
|
||||||
|
@Html.Partial("DisplayTemplates/_ChartButton", Model.LeafInputId, new ViewDataDictionary { { "Disabled", !Model.HasLeafChart } })
|
||||||
|
</div>
|
||||||
|
<div class="btn-group" role="group">
|
||||||
|
<a href="@Url.Action("DownloadInput", "Queue", new {id = Model.LeafInputId})"
|
||||||
|
class="btn btn-default" role="button">
|
||||||
|
<span class="glyphicon glyphicon-download"></span> Download Input
|
||||||
|
</a>
|
||||||
|
<a href="@Url.Action("DownloadOutputToUser", "Queue", new {id = Model.LeafInputId})"
|
||||||
|
class="btn btn-default@{if (!Model.IsComplete){<text> disabled</text>}}" role="button">
|
||||||
|
<span class="glyphicon glyphicon-download"></span> Download ToUser
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group" role="group">
|
||||||
|
<a href="@Url.Action("SendUserDownloadLink", "Queue", new {id = Model.LeafInputId})"
|
||||||
|
class="btn btn-default@{if (!Model.IsComplete){<text> disabled</text>}}" role="button">
|
||||||
|
<span class="glyphicon glyphicon-send"></span> Send download link to User
|
||||||
|
</a>
|
||||||
|
<a href="@Url.Action("SendUserChartLink", "Queue", new {id = Model.LeafInputId})"
|
||||||
|
class="btn btn-default@{if (!Model.HasLeafChart){<text> disabled</text>}}" role="button">
|
||||||
|
<span class="glyphicon glyphicon-send"></span> Send chart link to User
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group" role="group">
|
||||||
|
<a href="@Url.Action("Delete", "Queue", new {id = Model.LeafInputId})"
|
||||||
|
class="btn btn-default@{if (!Model.IsDeletable){<text> disabled</text>}}" role="button">
|
||||||
|
<span class="glyphicon glyphicon-remove"></span> Delete
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
@Html.DisplayForModel()
|
@Html.DisplayForModel()
|
||||||
|
|||||||
@@ -24,17 +24,17 @@
|
|||||||
<span class="caret"></span>
|
<span class="caret"></span>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
|
<li class="dropdown-header">Priority</li>
|
||||||
|
<li>Set High</li>
|
||||||
|
<li>Set Low</li>
|
||||||
<li>@DetailsLink(item)</li>
|
<li>@DetailsLink(item)</li>
|
||||||
<li @if (!item.HasLeafChart)
|
<li @DisableItem(!item.HasLeafChart)>@ChartLink(item)</li>
|
||||||
{
|
|
||||||
<text>class="disabled"</text>
|
|
||||||
}>@ChartLink(item)</li>
|
|
||||||
<li role="separator" class="divider"></li>
|
<li role="separator" class="divider"></li>
|
||||||
<li class="dropdown-header">Download</li>
|
<li class="dropdown-header">Download</li>
|
||||||
<li><a href="@Url.Action("DownloadOutputToUser", "Queue", new {id = item.LeafInputId})"><span class="glyphicon glyphicon-download"></span> ToUser</a></li>
|
<li>@DownloadInput(item)</li>
|
||||||
<li><a href="@Url.Action("DownloadInput", "Queue", new {id = item.LeafInputId})"><span class="glyphicon glyphicon-download"></span> Input</a></li>
|
<li @DisableItem(!item.IsComplete)>@DownloadOutputToUser(item)</li>
|
||||||
<li role="separator" class="divider"></li>
|
<li role="separator" class="divider"></li>
|
||||||
<li><a href="@Url.Action("Delete", "Queue", new {id = item.LeafInputId})"><span class="glyphicon glyphicon-remove"></span> Delete</a></li>
|
<li @DisableItem(!item.IsDeletable)>@DeleteLink(item)</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -48,4 +48,27 @@
|
|||||||
@helper ChartLink(dynamic item)
|
@helper ChartLink(dynamic item)
|
||||||
{
|
{
|
||||||
@Html.Partial("DisplayTemplates/_ChartLink", (int)item.LeafInputId)
|
@Html.Partial("DisplayTemplates/_ChartLink", (int)item.LeafInputId)
|
||||||
|
}
|
||||||
|
|
||||||
|
@helper DownloadInput(dynamic item)
|
||||||
|
{
|
||||||
|
<a href="@Url.Action("DownloadInput", "Queue", new {id = item.LeafInputId})">
|
||||||
|
<span class="glyphicon glyphicon-download"></span> Input
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
@helper DownloadOutputToUser(dynamic item)
|
||||||
|
{
|
||||||
|
<a href="@Url.Action("DownloadOutputToUser", "Queue", new {id = item.LeafInputId})">
|
||||||
|
<span class="glyphicon glyphicon-download"></span> ToUser
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
@helper DeleteLink(dynamic item)
|
||||||
|
{
|
||||||
|
<a href="@Url.Action("Delete", "Queue", new {id = item.LeafInputId})">
|
||||||
|
<span class="glyphicon glyphicon-remove"></span> Delete
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
@helper DisableItem(bool disabled)
|
||||||
|
{
|
||||||
|
if (disabled) {<text>class="disabled"</text>}
|
||||||
}
|
}
|
||||||
@@ -18,8 +18,5 @@
|
|||||||
|
|
||||||
@helper ChartLink(dynamic item)
|
@helper ChartLink(dynamic item)
|
||||||
{
|
{
|
||||||
if (item.HasLeafChart)
|
@Html.Partial("DisplayTemplates/_ChartButton", (int)item.LeafInputId, new ViewDataDictionary { { "Disabled", !item.HasLeafChart }, {"xs", true} })
|
||||||
{
|
|
||||||
@Html.Partial("DisplayTemplates/_ChartButton", (int)item.LeafInputId)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,13 @@
|
|||||||
@model int
|
@model int
|
||||||
<a href="@UmbracoContext.Current.UrlProvider.GetUrl(1100)?leafInputId=@Model" class="btn btn-default btn-xs" role="button">
|
@{
|
||||||
|
var url = UmbracoContext.Current.UrlProvider.GetUrl(1100);
|
||||||
|
var disabled = ViewData.ContainsKey("Disabled") && (bool) ViewData["Disabled"];
|
||||||
|
var xs = ViewData.ContainsKey("xs") && (bool) ViewData["xs"];
|
||||||
|
}
|
||||||
|
<a href="@url?leafInputId=@Model"
|
||||||
|
class="btn btn-default @{if (xs) {<text>btn-xs</text>}} @{if (disabled) {<text>disabled</text>}}"
|
||||||
|
role="button"
|
||||||
|
@{if (disabled) {<text>title="No chart has been generated"</text>}} />
|
||||||
<span class="glyphicon glyphicon-stats"></span>
|
<span class="glyphicon glyphicon-stats"></span>
|
||||||
Chart
|
Chart
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
@model int
|
@model int
|
||||||
<a href="@UmbracoContext.Current.UrlProvider.GetUrl(1100)?leafInputId=@Model">
|
@{
|
||||||
|
var url = UmbracoContext.Current.UrlProvider.GetUrl(1100);
|
||||||
|
}
|
||||||
|
<a href="@url?leafInputId=@Model">
|
||||||
<span class="glyphicon glyphicon-stats"></span>
|
<span class="glyphicon glyphicon-stats"></span>
|
||||||
Chart
|
Chart
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
@model int
|
@model int
|
||||||
<a href="@UmbracoContext.Current.UrlProvider.GetUrl(1111)?id=@Model">
|
@{
|
||||||
|
var url = UmbracoContext.Current.UrlProvider.GetUrl(1111);
|
||||||
|
}
|
||||||
|
<a href="@url?id=@Model">
|
||||||
<span class="glyphicon glyphicon-edit"></span> Details
|
<span class="glyphicon glyphicon-edit"></span> Details
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
@using LeafWeb.WebCms.Utility
|
||||||
|
@model bool?
|
||||||
|
|
||||||
|
@{
|
||||||
|
var propertyName = ViewData.ModelMetadata.PropertyName;
|
||||||
|
var isChecked = Model.HasValue && Model.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
<div class="@(Html.ValidationErrorFor(m => m, " has-error"))">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
@Html.CheckBox(
|
||||||
|
name: "",
|
||||||
|
isChecked: isChecked)
|
||||||
|
I agree to the
|
||||||
|
<a href="@UmbracoContext.Current.UrlProvider.GetUrl(1115)" target="_blank">
|
||||||
|
Terms of Service
|
||||||
|
<span class="glyphicon glyphicon-new-window" aria-hidden="true"></span>
|
||||||
|
</a>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
@Html.ValidationMessageFor(m => m, null, new { @class = "help-block" })
|
||||||
|
</div>
|
||||||
@@ -803,6 +803,8 @@
|
|||||||
<Content Include="Views\Shared\DisplayTemplates\_DetailsLink.cshtml" />
|
<Content Include="Views\Shared\DisplayTemplates\_DetailsLink.cshtml" />
|
||||||
<Content Include="Views\Shared\DisplayTemplates\_ChartButton.cshtml" />
|
<Content Include="Views\Shared\DisplayTemplates\_ChartButton.cshtml" />
|
||||||
<Content Include="Views\EmptyPage.cshtml" />
|
<Content Include="Views\EmptyPage.cshtml" />
|
||||||
|
<Content Include="Views\Shared\DisplayTemplates\TermsOfService.cshtml" />
|
||||||
|
<Content Include="Views\Shared\EditorTemplates\TermsOfService.cshtml" />
|
||||||
<None Include="Web.Debug.config">
|
<None Include="Web.Debug.config">
|
||||||
<DependentUpon>Web.config</DependentUpon>
|
<DependentUpon>Web.config</DependentUpon>
|
||||||
</None>
|
</None>
|
||||||
@@ -825,6 +827,7 @@
|
|||||||
<Compile Include="Backload\Controller\BackloadController.obsolete.cs" />
|
<Compile Include="Backload\Controller\BackloadController.obsolete.cs" />
|
||||||
<Compile Include="Backload\Helper\ResultCreator.Classic.cs" />
|
<Compile Include="Backload\Helper\ResultCreator.Classic.cs" />
|
||||||
<Compile Include="Backload\Helper\ResultCreator.cs" />
|
<Compile Include="Backload\Helper\ResultCreator.cs" />
|
||||||
|
<Compile Include="Controllers\EnforceTrueAttribute.cs" />
|
||||||
<Compile Include="Controllers\ActionLogAttribute.cs" />
|
<Compile Include="Controllers\ActionLogAttribute.cs" />
|
||||||
<Compile Include="Controllers\BackloadController.cs" />
|
<Compile Include="Controllers\BackloadController.cs" />
|
||||||
<Compile Include="Controllers\BaseController.cs" />
|
<Compile Include="Controllers\BaseController.cs" />
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
function initFileUpload(objectContext) {
|
function initFileUpload(objectContext) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
// enforce true attribute client support
|
||||||
|
jQuery.validator.addMethod("enforcetrue", function (value, element, param) {
|
||||||
|
return element.checked;
|
||||||
|
});
|
||||||
|
jQuery.validator.unobtrusive.adapters.addBool("enforcetrue");
|
||||||
|
|
||||||
// We use the upload handler integrated into Backload:
|
// We use the upload handler integrated into Backload:
|
||||||
// In this example we set an objectContect (id) in the url query (or as form parameter).
|
// In this example we set an objectContect (id) in the url query (or as form parameter).
|
||||||
// You can use a user id as objectContext give users only access to their own uploads.
|
// You can use a user id as objectContext give users only access to their own uploads.
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
(function($) {
|
(function($) {
|
||||||
|
|
||||||
|
// disable anchors in menu links which are disabled
|
||||||
|
$("li.disabled a").click(function () {
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
// Making elements equal height
|
// Making elements equal height
|
||||||
var equalheight = function(container){
|
var equalheight = function(container){
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user