More improvements to registration, leaf input create, and charting

This commit is contained in:
2020-01-14 14:10:11 -05:00
parent 8452a9cce0
commit 046cda40b4
18 changed files with 180 additions and 77 deletions
+4 -2
View File
@@ -3,7 +3,9 @@ using System.Web.Optimization;
using System.Web.Routing;
using Backload.Bundles;
using LeafWeb.Core.DAL;
using LeafWeb.WebCms.Controllers;
using Umbraco.Core;
using Umbraco.Web;
namespace LeafWeb.WebCms.App_Start
{
@@ -24,8 +26,8 @@ namespace LeafWeb.WebCms.App_Start
"Results/Download", // URL with parameters
new { controller = "Results", action = "Download" } // Parameter defaults
);
base.ApplicationStarted(umbracoApplication, applicationContext);
base.ApplicationStarted(umbracoApplication, applicationContext);
}
}
}
+26 -13
View File
@@ -15,12 +15,14 @@ using LeafWeb.Core.Parsers;
using LeafWeb.Core.Utility;
using LeafWeb.WebCms.Models;
using LeafWeb.WebCms.Services;
using LeafWeb.WebCms.Utility;
namespace LeafWeb.WebCms.Controllers
{
public class ChartController : BaseController
{
public ActionResult Index(int? leafInputId)
public class ChartController : BaseController
{
[RequireRequestValue("leafInputId")]
public ActionResult Index(int? leafInputId)
{
if (!leafInputId.HasValue)
return View("DataError", model: "Must specify LeafInputId");
@@ -60,17 +62,28 @@ namespace LeafWeb.WebCms.Controllers
}
}
//private ChartViewModel GetTestChartViewModel()
//{
// return new ChartViewModel
// {
// AvailableCurveId = new []{"Valid", "Test"},
// LeafInputId = 2147483647,
// LeafInputIdentifier = "Chart Tests"
// };
//}
[RequireRequestValue("token")]
public ActionResult Index(string token)
{
var leafInput = DataService.GetLeafInput(token);
public ActionResult ChartCurve(int leafInputId, string curveId, bool base64 = false)
if (leafInput == null)
return View("DataError", model: "Leaf Input Token not found");
return Index(leafInput.Id);
}
//private ChartViewModel GetTestChartViewModel()
//{
// return new ChartViewModel
// {
// AvailableCurveId = new []{"Valid", "Test"},
// LeafInputId = 2147483647,
// LeafInputIdentifier = "Chart Tests"
// };
//}
public ActionResult ChartCurve(int leafInputId, string curveId, bool base64 = false)
{
var leafOutputFile = DataService.GetLeafOutput_ChartFile(leafInputId);
+20 -1
View File
@@ -8,6 +8,7 @@ using LeafWeb.Core.Entities;
using LeafWeb.Core.Utility;
using LeafWeb.WebCms.App_Start;
using LeafWeb.WebCms.Models;
using Umbraco.Web;
namespace LeafWeb.WebCms.Controllers
{
@@ -37,6 +38,20 @@ namespace LeafWeb.WebCms.Controllers
if (ModelState.ContainsKey("TermsOfService"))
ModelState["TermsOfService"].Errors.Clear();
var membershipHelper = new Umbraco.Web.Security.MembershipHelper(UmbracoContext.Current);
var member = membershipHelper.GetCurrentMember();
if (member != null)
{
ModelState["Name"].Errors.Clear();
viewModel.Name = member.Name;
ModelState["Email"].Errors.Clear();
viewModel.Email = member.GetProperty("Email").Value as string;
ModelState["EmailConfirm"].Errors.Clear();
viewModel.EmailConfirm = viewModel.Email;
}
if (ModelState.IsValid) // HttpParamMatch indicates it's backing out from Confirm
{
// convert viewModel into Model
@@ -56,7 +71,11 @@ namespace LeafWeb.WebCms.Controllers
var msg = $"A data set has submitted for '{viewModel.Identifier}' from '{viewModel.SiteId}'. " + Environment.NewLine
+ $"When complete, an email will be delivered to {viewModel.Name} <{viewModel.Email}> with results.";
SetStatusMessage(HttpUtility.HtmlEncode(msg), StatusType.Success);
SetStatusMessage(
HttpUtility
.HtmlEncode(msg)
.Replace("\n", "<br/>"),
StatusType.Success);
var logger = LogManager.GetLogger(GetType());
logger.Info($"LeafInput: {leafInput.Id} Added, {leafInput.Identifier}, {leafInput.SiteId}, {leafInput.Email}");
+5 -5
View File
@@ -13,13 +13,13 @@ namespace LeafWeb.WebCms.Controllers
var member = memberService.GetByEmail(email);
if (member == null)
{
TempData["StatusMessage"] = $"User with email {email} not found.";
TempData["StatusMessage"] = $"Sorry, user with email {email} not found. Please try to register again, or use Contact Us to resolve the issue.";
TempData["StatusMessage-Type"] = "alert-danger";
}
else if (member.IsApproved)
{
TempData["StatusMessage"] = "You've already been verified, " + member.Name;
TempData["StatusMessage-Type"] = "alert-info";
TempData["StatusMessage-Type"] = "alert-info";
}
else
{
@@ -32,7 +32,7 @@ namespace LeafWeb.WebCms.Controllers
}
else if (storedToken != token)
{
TempData["StatusMessage"] = $"Bad token.";
TempData["StatusMessage"] = $"Sorry, your token cannot be found. Please try to register again, or use Contact Us to resolve the issue.";
TempData["StatusMessage-Type"] = "alert-danger";
}
else
@@ -44,10 +44,10 @@ namespace LeafWeb.WebCms.Controllers
member.SetValue("VerificationToken", string.Empty);
memberService.Save(member);
TempData["StatusMessage"] = "You have been verified, " + member.Name;
TempData["StatusMessage"] = "Thank you! Your email is now verified at " + member.Email;
TempData["StatusMessage-Type"] = "alert-success";
// TODO: rewrite url to their own page
// TODO: change redirectUrl to their own page
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ using Umbraco.Web.Mvc;
namespace LeafWeb.WebCms.Controllers
{
[MemberAuthorize]
[MemberAuthorize(AllowGroup = "Administrator")]
public class QueueController : BaseController
{
private const int TimeSamples = 40;
+19 -8
View File
@@ -110,7 +110,7 @@ namespace LeafWeb.WebCms.Services
private void SendLeafWebSuccess(LeafInput leafInput)
{
var body = $"Your leaf analysis job, {leafInput.Identifier}, has completed. ";
var body = $"Your leaf analysis job '{leafInput.Identifier}' has completed. ";
body += FormatWarningMessage(leafInput);
@@ -119,13 +119,21 @@ namespace LeafWeb.WebCms.Services
if (downloadLink)
{
var downloadUrl = _urlService.GetDownloadUrl(leafInput);
var chartUrl = _urlService.GetChartUrl(leafInput);
body +=
"Download results with the following link:"
body +=
Environment.NewLine + Environment.NewLine
+ "Download results with the following link:"
+ Environment.NewLine + Environment.NewLine
+ downloadUrl;
var message = new MailMessage(_emailFromAddress, leafInput.Email, FormatSubject(SuccessSubject, leafInput), body);
body +=
Environment.NewLine + Environment.NewLine
+ "Chart results with the following link:"
+ Environment.NewLine + Environment.NewLine
+ chartUrl;
var message = new MailMessage(_emailFromAddress, leafInput.Email, FormatSubject(SuccessSubject, leafInput), body);
SendMessage(message);
}
//else
@@ -161,7 +169,7 @@ namespace LeafWeb.WebCms.Services
private void SendLeafWebError(LeafInput leafInput, string errorMessage)
{
var body = $"Your leaf analysis job, {leafInput.Identifier}, encountered the following errors." + Environment.NewLine
var body = $"Your leaf analysis job '{leafInput.Identifier}' encountered the following errors." + Environment.NewLine
+ Environment.NewLine + Environment.NewLine
+ errorMessage
+ Environment.NewLine + Environment.NewLine
@@ -175,7 +183,7 @@ namespace LeafWeb.WebCms.Services
public void SendLeafWebSystemException(string leafInputIdentifier, string leafInputEmail)
{
var body = $"A system error occured while processing your leaf analysis job, {leafInputIdentifier}." + Environment.NewLine
var body = $"A system error occured while processing your leaf analysis job '{leafInputIdentifier}'." + Environment.NewLine
+ "System administrators have been notified. You will be notified again when the system error "
+ "has been resolved and your data has been processed.";
@@ -205,9 +213,12 @@ namespace LeafWeb.WebCms.Services
{
var member = ApplicationContext.Current.Services.MemberService.GetByEmail(memberEmail);
var verifyEmailURl = _urlService.GetVerifyEmailURl(member);
var body = "Please verify your email address with this link " + verifyEmailURl;
var body =
"Welcome to LeafWeb!" + Environment.NewLine + Environment.NewLine +
"Please verify your email address with this link " + verifyEmailURl + Environment.NewLine +
"Read more information about LeafWeb on the site here: https://leafweb.org/information/about/";
var message = new MailMessage(_emailFromAddress, member.Email, "Verify your email for LeafWeb", body);
var message = new MailMessage(_emailFromAddress, member.Email, "Welcome to LeafWeb, please verify your email address", body);
SendMessage(message);
}
+10
View File
@@ -8,6 +8,7 @@ namespace LeafWeb.WebCms.Services
public class UrlService
{
private readonly string _downloadUrl;
private readonly string _chartUrl;
private readonly string _verifyEmailUrl;
public UrlService()
@@ -16,6 +17,10 @@ namespace LeafWeb.WebCms.Services
ConfigurationManager.AppSettings["LeafWebUrl"]
+ ConfigurationManager.AppSettings["ResultsDownloadPath"];
_chartUrl =
ConfigurationManager.AppSettings["LeafWebUrl"]
+ ConfigurationManager.AppSettings["ChartPath"];
_verifyEmailUrl =
ConfigurationManager.AppSettings["LeafWebUrl"]
+ ConfigurationManager.AppSettings["MemberVerifyPath"];
@@ -26,6 +31,11 @@ namespace LeafWeb.WebCms.Services
return string.Format(_downloadUrl, leafInput.UniqueToken);
}
public string GetChartUrl(LeafInput leafInput)
{
return string.Format(_chartUrl, leafInput.UniqueToken);
}
public string GetVerifyEmailURl(IMember member)
{
var memberEmail = member.Email;
@@ -0,0 +1,19 @@
using System.Reflection;
using System.Web.Mvc;
namespace LeafWeb.WebCms.Utility
{
// stack overflow
public class RequireRequestValueAttribute : ActionMethodSelectorAttribute
{
public RequireRequestValueAttribute(string valueName)
{
ValueName = valueName;
}
public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
{
return (controllerContext.HttpContext.Request[ValueName] != null);
}
public string ValueName { get; private set; }
}
}
+5 -10
View File
@@ -7,15 +7,15 @@
Html.RequiresJs("~/scripts/jquery.autocomplete.min.js", 2);
Html.RequiresJs("~/scripts/jquery.validate.min.js", 2);
Html.RequiresJs("~/scripts/jquery.validate.unobtrusive.min.js", 2);
Html.RequiresJs("~/scripts/jquery.validate.unobtrusive.bootstrap.js", 2);
Html.RequiresJs("~/scripts/jquery.validate.custom.js", 2);
Html.RequiresJs("~/scripts/jquery.validate.unobtrusive.bootstrap.js", 2);
Html.RequiresJs("~/scripts/LeafInputCreate.js", 3);
var user = Membership.GetUser();
}
<div class="container-lg">
<div class="row">
<div class="row justify-content-center">
<div class="col-md-8 card card-body bg-light">
@Html.Partial("_ValidationSummary")
@@ -58,8 +58,8 @@
</div>
@Html.Partial("_ValidationField", "Files")
<!-- The table listing the files available for upload/download -->
<div class="table-responsive">
<table role="presentation" class="table table-sm table-striped"><tbody class="files"></tbody></table>
<div class="table-responsive card mb-4">
<table role="presentation" class="table table-sm table-striped mb-0"><tbody class="files"></tbody></table>
</div>
</form>
@@ -74,12 +74,7 @@
@Html.EditorFor(m => m.Email)
@Html.EditorFor(m => m.EmailConfirm)
}
else
{
@Html.HiddenFor(m => m.Name)
@Html.HiddenFor(m => m.Email)
@Html.HiddenFor(m => m.EmailConfirm)
}
@Html.EditorFor(m => m.TermsOfService)
<input type="submit" id="submit-form" class="d-none" />
}
+1 -1
View File
@@ -88,7 +88,7 @@
@RenderBody()
</main>
<footer class="mt-auto py-3 dark">
<footer class="mt-5 py-3 dark">
<div class="container">
<div class="row">
+2 -1
View File
@@ -2,6 +2,7 @@
@{
var home = CurrentPage.Site();
var loginStatus = Members.GetCurrentLoginStatus();
var admin = Members.IsMemberAuthorized(allowGroups: new List<string>{"Administrator"});
}
@if (home.Children.Any())
@@ -40,7 +41,7 @@
</ul>
<div class="navbar-text text-light text-left">
@Html.Partial("LoginStatus")
@if (loginStatus.IsLoggedIn)
@if (loginStatus.IsLoggedIn && admin)
{
<div class="align-items-center">
<a href="~/umbraco#"><span class="fa fa-cog"></span> Site Editor</a>
@@ -2,4 +2,22 @@
@{
Layout = "_FieldLayout.cshtml";
}
@Html.Password("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "form-control" })
@{
var htmlAttributes = new RouteValueDictionary();
var controlClass = "form-control";
if (ViewBag.@class != null)
{
controlClass = string.Concat(controlClass, " ", ViewBag.@class);
}
if (ViewData.ModelState.ContainsKey(ViewData.TemplateInfo.HtmlFieldPrefix) &&
ViewData.ModelState[ViewData.TemplateInfo.HtmlFieldPrefix].Errors.Any())
{
controlClass = string.Concat(controlClass, " ", "is-invalid");
}
htmlAttributes.Add("class", controlClass);
}
@Html.Password("", ViewData.TemplateInfo.FormattedModelValue, htmlAttributes)
@@ -6,18 +6,18 @@
var prefix = ViewData.TemplateInfo.HtmlFieldPrefix;
ViewData.TemplateInfo.HtmlFieldPrefix = string.Empty;
var required = new { required = "true" };
var required = " required";
foreach (var li in Model.ListItems)
{
var name = prefix + ".Selected";
<div class="form-check">
<input class="form-check-input" type="radio" name="@name" id="@li.Value" value="@li.Value" @(li.Selected ? " checked" : "")>
<input class="form-check-input" type="radio" name="@name" id="@li.Value" value="@li.Value" @(li.Selected ? " checked" : "")@required>
<label class="form-check-label" for="@li.Value">
@li.Text
</label>
</div>
required = null;
//required = string.Empty;
}
ViewData.TemplateInfo.HtmlFieldPrefix = prefix;
}
@@ -3,7 +3,6 @@
@{
var propertyName = ViewData.ModelMetadata.PropertyName;
//var isChecked = Model.HasValue && Model.Value;
}
<div class="@(Html.ValidationErrorFor(m => m, " is-invalid"))">
+1
View File
@@ -76,6 +76,7 @@
<add key="LeafWebUrl" value="http://localhost:61755/" />
<add key="PiscalNotifyCompleteUrlPath" value="notifycomplete" />
<add key="ResultsDownloadPath" value="Results/Download?token={0}" />
<add key="ChartPath" value="leaf-data/chart?token={0}" />
<add key="MemberVerifyPath" value="verify?email={0}&amp;token={1}" />
<add key="PiscalUnresponsiveHourCount" value="24" />
</appSettings>
+1
View File
@@ -1117,6 +1117,7 @@
<Compile Include="Services\PiscalQueue\PiscalQueueWorker.cs" />
<Compile Include="Services\PiscalQueue\PiscalService.cs" />
<Compile Include="Services\PiscalQueue\StartPending.cs" />
<Compile Include="Utility\RequireRequestValueAttribute.cs" />
<Compile Include="Utility\Validation.cs" />
</ItemGroup>
<ItemGroup>
@@ -1,40 +1,22 @@
(function ($) {
if($.validator && $.validator.unobtrusive){
var defaultOptions = {
validClass: 'is-valid',
errorClass: 'is-invalid',
highlight: function (element, errorClass, validClass) {
$(element)
.removeClass(validClass)
.addClass(errorClass);
},
unhighlight: function (element, errorClass, validClass) {
$(element)
.removeClass(errorClass)
.addClass(validClass);
}
//,
//errorElement: 'span',
//errorPlacement: function(error, element) {
// error.addClass('invalid-feedback');
// var errElement =
// $('field-validation-error[data-validation-for="' + element.id + '"]');
// errElement.append(error);
//}
};
$.validator.setDefaults(defaultOptions);
$.validator.unobtrusive.options = {
errorClass: defaultOptions.errorClass,
validClass: defaultOptions.validClass,
errorClass: 'is-invalid',
validClass: 'is-valid',
errorElement: 'span',
errorPlacement: function (error, element) {
error.addClass('invalid-feedback');
var valmsgFor = element[0].id;
if (element[0].type === 'radio') {
valmsgFor = element[0].name.replace(/\..*/g, "");
}
var errElement =
$('field-validation-error[data-validation-for="' + element.id + '"]');
errElement.append(error);
}
$('[data-valmsg-for="' + valmsgFor + '"]');
errElement.after(error);
}
};
}
else {