From 046cda40b4e543660323f0e0b8a692410a43df31 Mon Sep 17 00:00:00 2001 From: James Kolpack Date: Tue, 14 Jan 2020 14:10:11 -0500 Subject: [PATCH] More improvements to registration, leaf input create, and charting --- Core.Tests/Parsers/LeafInputData/b2.csv | 32 ++++++++++++++ WebCms/App_Start/RegisterServices.cs | 6 ++- WebCms/Controllers/ChartController.cs | 39 +++++++++++------ WebCms/Controllers/LeafInputController.cs | 21 +++++++++- WebCms/Controllers/MembershipController.cs | 10 ++--- WebCms/Controllers/QueueController.cs | 2 +- WebCms/Services/EmailNotificationService.cs | 27 ++++++++---- WebCms/Services/UrlService.cs | 10 +++++ .../Utility/RequireRequestValueAttribute.cs | 19 +++++++++ WebCms/Views/LeafInput/Create.cshtml | 15 +++---- WebCms/Views/Master.cshtml | 2 +- WebCms/Views/Partials/MainNavigation.cshtml | 3 +- .../Shared/EditorTemplates/Password.cshtml | 20 ++++++++- .../SelectListViewModel.cshtml | 6 +-- .../EditorTemplates/TermsOfService.cshtml | 1 - WebCms/Web.config | 1 + WebCms/WebCms.csproj | 1 + .../jquery.validate.unobtrusive.bootstrap.js | 42 ++++++------------- 18 files changed, 180 insertions(+), 77 deletions(-) create mode 100644 Core.Tests/Parsers/LeafInputData/b2.csv create mode 100644 WebCms/Utility/RequireRequestValueAttribute.cs diff --git a/Core.Tests/Parsers/LeafInputData/b2.csv b/Core.Tests/Parsers/LeafInputData/b2.csv new file mode 100644 index 0000000..cfbf7ea --- /dev/null +++ b/Core.Tests/Parsers/LeafInputData/b2.csv @@ -0,0 +1,32 @@ +Investigator name: -9999,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Contact information: -9999,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Site name in full: -9999,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Vegetation type: -9999,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Soil type: -9999,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Major species: -9999,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Sample leaf light environment:-9999,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Water stress assessment: -9999,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Instrument used: Licor-6400,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Extra info: -9999,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +SiteID,Latitude(Degrees),Longitude(Degrees),Elevation,SampleYear,SampleDayOfYear,GrowSeasonStart,GrowSeasonEnd,StandAge,CanopyHeight,LeafAreaIndex,SpeciesSampled,AveTimeResolution,SampleHeight,LeafAge,SpecificLeafArea,LfNitrogenContent,LfCarbonContent,LfPhosphContent,,,,,,,,,,,, +NoUnit,NorthPositive,EastPositive,m,NoUnit,DayOfYear,DayOfYear,DayOfYear,Year,m,m2/m2,NoBlankSpace,Minutes,m,days,cm2/g,%,%,%,,,,,,,,,,,, +MOFLUX,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,P.glauca-2,-9999,-9999,-9999,-9999,-9999,-9999,-9999,,,,,,,,,,,, +Gamma*,Kc,Ko,Alpha,Rd,gi,,,,,,,,,,,,,,,,,,,,,,,,, +Pa,Pa,Pa,NoUnit,umol/m2/s,umol/m2/s/Pa,,,,,,,,,,,,,,,,,,,,,,,,, +-9999,-9999,-9999,-9999,-9999,-9999,,,,,,,,,,,,,,,,,,,,,,,,, +Obs,HHMMSS,FTime,Photo,!AdjPhoto,!StomCond,!Ci,!Trmmol,!VpdL,Area,StmRat,BLCond,Tair,!Tleaf,TBlk,CO2R,CO2S,H2OR,H2OS,RH_R,RH_S,Flow,!PARi,PARo,Press,CsMch,HsMch,StableF,Status,PhiPS2,OxygenPress +NoUnit,HHMMSS,Second,umol/m2/s,umol/m2/s,mol/m2/s,umol/mol,mmol/m2/s,kPa,cm2,NA,mol/m2/s,oC,oC,oC,umol/mol,umol/mol,mmol/mol,mmol/mol,%,%,umol/s,umol/m2/s,umol/m2/s,Kpa,umol/mol,mmol/mol,NA,NA,NA,KPA +1,14:04:01,216.9999995,17.66091043,4.492612863,0.098849451,280.3709372,1.338910842,1.139404191,39.311,1,8,32.96362305,31.3519249,32.06974411,399.9895935,360.8808594,32.6089325,42.68330765,56.52416992,73.98905945,500.1534424,1599.706421,1804.285645,87.39344788,8.136817932,0.023298264,0.666666687,111115,-9999,-9999 +2,14:06:29,364.9999998,11.42024488,2.905101595,0.068416192,198.4392999,1.330580521,1.62531275,39.311,1,8,32.97150803,33.09469604,32.0753479,299.9839478,274.2851257,32.50420761,42.51641846,56.31570816,73.66376495,500.2148743,1599.678955,1799.178467,87.3903656,8.136817932,0.023298264,1,111115,-9999,-9999 +3,14:09:14,529.9999995,4.434742866,1.128117541,0.071337939,158.6916287,1.307510509,1.533645385,39.311,1,8,32.97004318,32.658741,32.07339859,200.1413116,189.3286438,32.34984589,42.19319153,56.05310059,73.1060257,500.1433105,1599.645996,1799.468262,87.39042664,8.136817932,0.023298264,0.666666687,111115,-9999,-9999 +4,14:12:22,717.9999999,0.483357938,0.122957426,0.094024954,94.0967433,1.353692054,1.210345081,39.311,1,8,32.94629669,31.44996452,32.06907272,100.4642715,98.45015717,31.96475983,42.15702438,55.45473099,73.1427002,500.1008606,1599.779297,1795.099731,87.38063049,6.053817749,0.123514175,1,111115,-9999,-9999 +5,14:15:12,887.9999999,-1.857541948,-0.472524725,0.082404107,70.17079835,1.329135733,1.352970625,39.311,1,8,32.98172379,31.94628525,32.07586288,59.58465195,62.64400101,32.03879166,42.04571915,55.69216919,72.7999115,500.1813049,1599.699463,1760.709595,87.37692261,5.704711914,0.062330246,1,111115,-9999,-9999 +6,14:19:34,1150,16.30916547,4.14875365,0.079962358,271.383255,1.338371639,1.403340902,39.311,1,8,33.02922058,32.06547928,32.07368469,400.1173706,363.6842041,31.76015663,41.83911514,54.8360939,72.24120331,500.1653442,1599.657104,1755.306274,87.37147522,8.517822266,0.066820145,1,111115,-9999,-9999 +7,14:22:50,1345.499999,16.06966804,4.08782988,0.08531807,278.9191735,1.306694333,1.286360373,39.311,1,8,32.99898911,31.48867989,32.07667542,400.1026001,364.2318726,31.60316467,41.44794846,54.65733719,71.68660736,500.1469421,1599.771118,1741.524658,87.36854553,8.694000244,0.037614822,0.666666687,111115,-9999,-9999 +8,14:26:41,1576.999999,24.90194221,6.334599019,0.072383026,391.2392941,1.27531951,1.476526969,39.311,1,8,33.01140594,32.02433777,32.06568146,600.9141846,545.6561279,31.30322266,40.9168129,54.09747696,70.71539307,500.1540222,1599.645874,1693.521729,87.3644104,9.683013916,0.058748245,0.333333343,111115,-9999,-9999 +9,14:30:55,1830.999999,31.45972651,8.002779504,0.067210056,520.0650538,1.234006387,1.538109638,39.311,1,8,33.00231934,32.02142334,32.07824326,800.427002,730.4495239,30.92346191,40.2313118,53.46592331,69.56246185,500.20578,1599.726563,1707.336426,87.35868835,11.23129272,-0.098421097,0.666666687,111115,-9999,-9999 +10,14:34:26,2039.499999,36.75349062,9.349416351,0.064911969,662.3618311,1.195136545,1.542834603,39.311,1,8,32.99179459,31.8321476,32.07229233,999.9680786,917.8516846,30.60204124,39.62445831,52.94240189,68.55239105,500.0918884,1599.651855,985.2610474,87.35500336,11.23129272,-0.098421097,1,111115,-9999,-9999 +11,14:38:03,2258.999999,41.55310038,10.57034936,0.058111493,783.109101,1.186337212,1.708234786,39.311,1,8,32.98957062,32.30555344,32.07281494,1200.413086,1107.016968,30.23540306,39.19365311,52.30853271,67.81102753,500.1899109,1599.74231,1676.356567,87.35036469,12.14645386,0.012842178,0.333333343,111115,-9999,-9999 +12,14:42:21,2516.999999,44.97176888,11.43999615,0.059221762,952.2061451,1.160387436,1.64134362,39.311,1,8,33.0266304,31.86928368,32.0715065,1400.504028,1298.748413,29.87436676,38.64186859,51.57442474,66.71395111,500.1801453,1599.677002,1667.658203,87.34835815,13.11935425,0.060182571,0.666666687,111115,-9999,-9999 +13,14:46:53,2788.499999,49.88318877,12.68937162,0.055250937,1268.009959,1.13122438,1.714106087,39.311,1,8,33.04856491,31.98287392,32.07389069,1801.062866,1686.328369,29.63163757,38.18371582,51.08673859,65.8352356,500.1304626,1599.650146,1641.924194,87.33757019,14.18380737,0.081045151,0.666666687,111115,-9999,-9999 +14,14:50:47,3022.999999,54.15459401,13.77593905,0.049960229,1374.984929,1.103395472,1.847114612,39.311,1,8,33.05990219,32.31631851,32.07295609,2000.835083,1876.276733,29.3665905,37.71268463,50.59538269,64.97751617,500.1114197,1599.500244,1635.361938,87.33286285,20.7996521,0.11482811,0.666666687,111115,-9999,-9999 diff --git a/WebCms/App_Start/RegisterServices.cs b/WebCms/App_Start/RegisterServices.cs index 452fc92..b213ac9 100644 --- a/WebCms/App_Start/RegisterServices.cs +++ b/WebCms/App_Start/RegisterServices.cs @@ -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); } } } \ No newline at end of file diff --git a/WebCms/Controllers/ChartController.cs b/WebCms/Controllers/ChartController.cs index d25308d..e96df8d 100644 --- a/WebCms/Controllers/ChartController.cs +++ b/WebCms/Controllers/ChartController.cs @@ -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); diff --git a/WebCms/Controllers/LeafInputController.cs b/WebCms/Controllers/LeafInputController.cs index 37c0f30..4c2e2c4 100644 --- a/WebCms/Controllers/LeafInputController.cs +++ b/WebCms/Controllers/LeafInputController.cs @@ -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", "
"), + StatusType.Success); var logger = LogManager.GetLogger(GetType()); logger.Info($"LeafInput: {leafInput.Id} Added, {leafInput.Identifier}, {leafInput.SiteId}, {leafInput.Email}"); diff --git a/WebCms/Controllers/MembershipController.cs b/WebCms/Controllers/MembershipController.cs index 1d820c8..db42263 100644 --- a/WebCms/Controllers/MembershipController.cs +++ b/WebCms/Controllers/MembershipController.cs @@ -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 } } diff --git a/WebCms/Controllers/QueueController.cs b/WebCms/Controllers/QueueController.cs index 1ac5cdc..a56169a 100644 --- a/WebCms/Controllers/QueueController.cs +++ b/WebCms/Controllers/QueueController.cs @@ -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; diff --git a/WebCms/Services/EmailNotificationService.cs b/WebCms/Services/EmailNotificationService.cs index b036702..fef4fa2 100644 --- a/WebCms/Services/EmailNotificationService.cs +++ b/WebCms/Services/EmailNotificationService.cs @@ -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); } diff --git a/WebCms/Services/UrlService.cs b/WebCms/Services/UrlService.cs index 13340b1..2bdf267 100644 --- a/WebCms/Services/UrlService.cs +++ b/WebCms/Services/UrlService.cs @@ -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; diff --git a/WebCms/Utility/RequireRequestValueAttribute.cs b/WebCms/Utility/RequireRequestValueAttribute.cs new file mode 100644 index 0000000..1f883b3 --- /dev/null +++ b/WebCms/Utility/RequireRequestValueAttribute.cs @@ -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; } + } +} \ No newline at end of file diff --git a/WebCms/Views/LeafInput/Create.cshtml b/WebCms/Views/LeafInput/Create.cshtml index 21b6383..59ba415 100644 --- a/WebCms/Views/LeafInput/Create.cshtml +++ b/WebCms/Views/LeafInput/Create.cshtml @@ -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(); }
-
+
@Html.Partial("_ValidationSummary") @@ -58,8 +58,8 @@
@Html.Partial("_ValidationField", "Files") -
- +
+
@@ -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) } diff --git a/WebCms/Views/Master.cshtml b/WebCms/Views/Master.cshtml index 1535641..6f5128d 100644 --- a/WebCms/Views/Master.cshtml +++ b/WebCms/Views/Master.cshtml @@ -88,7 +88,7 @@ @RenderBody() -