From 680f139aa5e90e964071790ea812d2ec007443ab Mon Sep 17 00:00:00 2001 From: James Kolpack Date: Thu, 2 Feb 2023 09:35:22 -0500 Subject: [PATCH] Search for both LeafInput and LeafInputData --- Core/DAL/DataService.cs | 5 + Core/Entities/LeafInputData.cs | 21 +- .../Models/LeafDataResultViewModelTests.cs | 30 +++ WebCms.Tests/Models/LeafInputDetailsTests.cs | 115 +-------- WebCms.Tests/Models/LeafInputTestData.cs | 120 +++++++++ WebCms.Tests/WebCms.Tests.csproj | 2 + WebCms/App_Start/AutoMapperConfig.cs | 12 + WebCms/Controllers/ResultsController.cs | 59 +++-- WebCms/Models/ChartViewModel.cs | 7 - WebCms/Models/LeafDataQuery.cs | 23 +- WebCms/Models/LeafDataResultViewModel.cs | 44 ++++ WebCms/Models/LeafInputDataCurveViewModel.cs | 31 +++ ...del.cs => SearchLeafInputDataViewModel.cs} | 5 +- WebCms/Models/SearchLeafInputViewModel.cs | 11 + WebCms/Utility/QueryFilter.cs | 235 +++++++++++++++--- WebCms/Views/Chart/Index.cshtml | 20 +- WebCms/Views/Results/Index.cshtml | 69 +---- WebCms/Views/Results/LeafInput.cshtml | 69 +++++ WebCms/Views/Results/LeafInputData.cshtml | 84 +++++++ WebCms/Views/Results/NoResults.cshtml | 9 + WebCms/Views/Results/Recent.cshtml | 34 ++- WebCms/Views/Shared/_LeafDataQuery.cshtml | 67 +++-- WebCms/Views/Shared/_LeafInputActions.cshtml | 10 +- WebCms/WebCms.csproj | 7 +- 24 files changed, 808 insertions(+), 281 deletions(-) create mode 100644 WebCms.Tests/Models/LeafDataResultViewModelTests.cs create mode 100644 WebCms.Tests/Models/LeafInputTestData.cs create mode 100644 WebCms/Models/LeafDataResultViewModel.cs rename WebCms/Models/{SearchViewModel.cs => SearchLeafInputDataViewModel.cs} (54%) create mode 100644 WebCms/Models/SearchLeafInputViewModel.cs create mode 100644 WebCms/Views/Results/LeafInput.cshtml create mode 100644 WebCms/Views/Results/LeafInputData.cshtml create mode 100644 WebCms/Views/Results/NoResults.cshtml diff --git a/Core/DAL/DataService.cs b/Core/DAL/DataService.cs index d3c3cd8..7bd23e0 100644 --- a/Core/DAL/DataService.cs +++ b/Core/DAL/DataService.cs @@ -80,6 +80,11 @@ namespace LeafWeb.Core.DAL select s).Max(s => s.DateTime)); } + public IQueryable GetLeafInputData() + { + return _db.LeafInputData; + } + public IEnumerable GetLeafInputRecentlyCompleted(int count) { return diff --git a/Core/Entities/LeafInputData.cs b/Core/Entities/LeafInputData.cs index 96d25a4..cc025af 100644 --- a/Core/Entities/LeafInputData.cs +++ b/Core/Entities/LeafInputData.cs @@ -1,5 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; using LeafWeb.Core.Utility; namespace LeafWeb.Core.Entities @@ -23,7 +25,7 @@ namespace LeafWeb.Core.Entities public virtual LeafInput LeafInput { get; set; } /// - /// Output file this data was parsed from + /// Output file this data was parsed from - the cleaned input from Piscal /// public virtual LeafOutputFile LeafOutputFile { get; set; } @@ -58,5 +60,18 @@ namespace LeafWeb.Core.Entities [ParseInfo(10, exampleValue: "Any extra information you feel would be helpful to put the sampled leaf in context")] public string ExtraInfo { get; set; } - } + + /// + /// Utility method for calculating the range of values in the curves + /// + public static double? Range( + ICollection curves, + Func param) + => curves.Max(param) - curves.Min(param); + + public double? CO2S_Range => Range(Data, curve => curve.CO2S); + public double? PARi_Range => Range(Data, curve => curve.PARi); + public double? Tleaf_Range => Range(Data, curve => curve.Tleaf); + public double? PhiPS2_Range => Range(Data, curve => curve.PhiPS2); + } } \ No newline at end of file diff --git a/WebCms.Tests/Models/LeafDataResultViewModelTests.cs b/WebCms.Tests/Models/LeafDataResultViewModelTests.cs new file mode 100644 index 0000000..0ea7e3e --- /dev/null +++ b/WebCms.Tests/Models/LeafDataResultViewModelTests.cs @@ -0,0 +1,30 @@ +using System.Linq; +using LeafWeb.WebCms.App_Start; +using LeafWeb.WebCms.Models; +using NUnit.Framework; + +namespace LeafWeb.WebCms.Tests.Models +{ + [TestFixture] + public class LeafDataResultViewModelTests + { + [SetUp] + public void SetUp() + { + AutoMapperConfig.RegisterMappings(); + } + + [Test] + public void CanConstruct_LeafDataResultViewModel() + { + var leafInputData = LeafInputTestData.GetLeafInputData; + var viewModel = new LeafDataResultViewModel(leafInputData); + + Assert.That(viewModel.SiteId, Is.EqualTo(leafInputData.Site.SiteId)); + Assert.That(viewModel.SpeciesSampled, Is.EqualTo(leafInputData.Site.SpeciesSampled)); + Assert.That(viewModel.Latitude, Is.EqualTo(10)); + Assert.That(viewModel.Longitude, Is.EqualTo(20)); + //Assert.That(viewModel.CO2S, Is.EqualTo(leafInputData.Data.First().CO2S)); + } + } +} \ No newline at end of file diff --git a/WebCms.Tests/Models/LeafInputDetailsTests.cs b/WebCms.Tests/Models/LeafInputDetailsTests.cs index d726ff7..5081a12 100644 --- a/WebCms.Tests/Models/LeafInputDetailsTests.cs +++ b/WebCms.Tests/Models/LeafInputDetailsTests.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using LeafWeb.Core.Entities; -using LeafWeb.WebCms.App_Start; +using LeafWeb.WebCms.App_Start; using LeafWeb.WebCms.Models; using NUnit.Framework; @@ -16,106 +13,10 @@ namespace LeafWeb.WebCms.Tests.Models AutoMapperConfig.RegisterMappings(); } - private LeafInput GetLeafInput => - new LeafInput - { - CurrentStatus = LeafInputStatusType.Complete, - OutputFiles = new[] {new LeafOutputFile {Filename = "OutputFilename.txt"}}, - Added = DateTime.Today, - Email = "test@email.com", - Identifier = "Ident I Fier", - Name = "My Name", - PhotosynthesisType = new PhotosynthesisType {Id = "1", Name = "1", SortOrder = 1}, - InputFiles = new[] - { - new LeafInputFile - { - Filename = "MyFilename.ext", - Id = 3 - } - }, - StatusHistory = new List - { - new LeafInputStatus - { - DateTime = DateTime.Today.Subtract(new TimeSpan(4, 0, 0)), - Description = "Added", - Details = "Uploaded from Web", - Id = 1, - Status = LeafInputStatusType.Pending - }, - new LeafInputStatus - { - DateTime = DateTime.Today.Subtract(new TimeSpan(3, 0, 0)), - Description = "Uploading input data", - Id = 2, - Status = LeafInputStatusType.Starting - }, - new LeafInputStatus - { - DateTime = DateTime.Today.Subtract(new TimeSpan(2, 12, 0)), - Description = "Running on server", - Id = 3, - Status = LeafInputStatusType.Running - }, - new LeafInputStatus - { - DateTime = DateTime.Today.Subtract(new TimeSpan(1, 0, 0)), - Description = "Downloading results", - Id = 4, - Status = LeafInputStatusType.Finishing - }, - new LeafInputStatus - { - DateTime = DateTime.Today.Subtract(new TimeSpan(0, 12, 0)), - Description = "All done", - Id = 5, - Status = LeafInputStatusType.Complete - } - }, - LeafInputData = new List - { - new LeafInputData - { - Site = new LeafInputDataSite {Latitude = 10, Longitude = 20, SiteId = "MySiteId"}, - SiteName = "MySite", - Id = 123, - Data = new List - { - new LeafInputDataCurve - { - CO2S = 3.1 - } - } - } - } - }; - - private LeafInputData GetLeafInputData => - new LeafInputData - { - Site = new LeafInputDataSite {Latitude = 10, Longitude = 20, SiteId = "MySiteId"}, - SiteName = "MySite", - Id = 123, - Data = new List - { - new LeafInputDataCurve - { - CO2S = 3.1 - } - } - }; - - private LeafInputDataCurve GetLeafInputDataCurve => - new LeafInputDataCurve - { - CO2S = 3.1 - }; - [Test] public void CanConstructLeafInputDataCurve() { - var leafInputDataCurve = GetLeafInputDataCurve; + var leafInputDataCurve = LeafInputTestData.GetLeafInputDataCurve; var viewModel = new LeafInputDataCurveViewModel(leafInputDataCurve); Assert.That(viewModel.CO2S, Is.EqualTo(3.1)); @@ -124,19 +25,19 @@ namespace LeafWeb.WebCms.Tests.Models [Test] public void CanConstructLeafInputData() { - var leafInputData = GetLeafInputData; + var leafInputData = LeafInputTestData.GetLeafInputData; var viewModel = new LeafInputDataViewModel(leafInputData); Assert.That(viewModel.SiteName, Is.EqualTo("MySite")); Assert.That(viewModel.Data, Is.Not.Null); Assert.That(viewModel.Data, Has.Count.GreaterThan(0)); - Assert.That(viewModel.Data[0].CO2S, Is.EqualTo(3.1)); + Assert.That(viewModel.Data[0].CO2S, Is.EqualTo(292.5618317)); } [Test] public void CanConstructAdminFromLeafInputFile() { - var leafInput = GetLeafInput; + var leafInput = LeafInputTestData.GetLeafInput; var viewModel = new LeafInputDetails_Admin(leafInput); //Assert.That(viewModel.CurrentStatus, Is.EqualTo(leafInput.CurrentStatus.ToString())); @@ -162,7 +63,7 @@ namespace LeafWeb.WebCms.Tests.Models Assert.That(viewModel.LeafInputData[0].Data, Is.Not.Null); Assert.That(viewModel.LeafInputData[0].Data, Has.Count.GreaterThan(0)); - Assert.That(viewModel.LeafInputData[0].Data[0].CO2S, Is.EqualTo(3.1)); + Assert.That(viewModel.LeafInputData[0].Data[1].CO2S, Is.EqualTo(195.4142136)); //Assert.That(viewModel.LeafInputData[0].Id, Is.EqualTo(123)); } @@ -170,7 +71,7 @@ namespace LeafWeb.WebCms.Tests.Models [Test] public void CanConstructFromLeafInputFile() { - var leafInput = GetLeafInput; + var leafInput = LeafInputTestData.GetLeafInput; var viewModel = new LeafInputDetails(leafInput); //Assert.That(viewModel.CurrentStatus, Is.EqualTo(leafInput.CurrentStatus.ToString())); @@ -192,7 +93,7 @@ namespace LeafWeb.WebCms.Tests.Models Assert.That(viewModel.LeafInputData[0].Data, Is.Not.Null); Assert.That(viewModel.LeafInputData[0].Data, Has.Count.GreaterThan(0)); - Assert.That(viewModel.LeafInputData[0].Data[0].CO2S, Is.EqualTo(3.1)); + Assert.That(viewModel.LeafInputData[0].Data[0].CO2S, Is.EqualTo(292.5618317)); //Assert.That(viewModel.LeafInputData[0].Id, Is.EqualTo(123)); } diff --git a/WebCms.Tests/Models/LeafInputTestData.cs b/WebCms.Tests/Models/LeafInputTestData.cs new file mode 100644 index 0000000..290ed92 --- /dev/null +++ b/WebCms.Tests/Models/LeafInputTestData.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using LeafWeb.Core.Entities; + +namespace LeafWeb.WebCms.Tests.Models +{ + public static class LeafInputTestData + { + public static LeafInput GetLeafInput => + new LeafInput + { + CurrentStatus = LeafInputStatusType.Complete, + OutputFiles = new[] {new LeafOutputFile {Filename = "OutputFilename.txt"}}, + Added = DateTime.Today, + Email = "test@email.com", + Identifier = "Ident I Fier", + Name = "My Name", + PhotosynthesisType = new PhotosynthesisType {Id = "1", Name = "1", SortOrder = 1}, + InputFiles = new[] + { + new LeafInputFile + { + Filename = "MyFilename.ext", + Id = 3 + } + }, + StatusHistory = new List + { + new LeafInputStatus + { + DateTime = DateTime.Today.Subtract(new TimeSpan(4, 0, 0)), + Description = "Added", + Details = "Uploaded from Web", + Id = 1, + Status = LeafInputStatusType.Pending + }, + new LeafInputStatus + { + DateTime = DateTime.Today.Subtract(new TimeSpan(3, 0, 0)), + Description = "Uploading input data", + Id = 2, + Status = LeafInputStatusType.Starting + }, + new LeafInputStatus + { + DateTime = DateTime.Today.Subtract(new TimeSpan(2, 12, 0)), + Description = "Running on server", + Id = 3, + Status = LeafInputStatusType.Running + }, + new LeafInputStatus + { + DateTime = DateTime.Today.Subtract(new TimeSpan(1, 0, 0)), + Description = "Downloading results", + Id = 4, + Status = LeafInputStatusType.Finishing + }, + new LeafInputStatus + { + DateTime = DateTime.Today.Subtract(new TimeSpan(0, 12, 0)), + Description = "All done", + Id = 5, + Status = LeafInputStatusType.Complete + } + }, + LeafInputData = new List + { + new LeafInputData + { + Site = SampleLeafInputDataSite, + SiteName = "MySite", + Id = 123, + Data = GetLeafInputDataCurves + } + } + }; + + public static LeafInputData GetLeafInputData => + new LeafInputData + { + Site = SampleLeafInputDataSite, + SiteName = "MySite", + Id = 123, + Data = GetLeafInputDataCurves + }; + + public static List GetLeafInputDataCurves => + new List { + new LeafInputDataCurve{ CO2S=292.5618317, PARi=993.0888855, Tleaf=23.53769627, PhiPS2=0.180769687 }, + new LeafInputDataCurve{ CO2S=195.4142136, PARi=992.5410278, Tleaf=23.68962097, PhiPS2=0.163288942 }, + new LeafInputDataCurve{ CO2S=146.4719864, PARi=992.1625671, Tleaf=23.90329285, PhiPS2=0.147352806 }, + new LeafInputDataCurve{ CO2S=98.51480789, PARi=991.761908, Tleaf=24.21637478, PhiPS2=0.130597749 }, + new LeafInputDataCurve{ CO2S=73.31520309, PARi=991.5204651, Tleaf=24.19524651, PhiPS2=0.122154858 }, + new LeafInputDataCurve{ CO2S=49.07753906, PARi=991.50896, Tleaf=24.11649742, PhiPS2=0.11011836 }, + new LeafInputDataCurve{ CO2S=389.8589264, PARi=991.5494934, Tleaf=23.77918701, PhiPS2=0.183856114 }, + new LeafInputDataCurve{ CO2S=587.4440186, PARi=990.6557251, Tleaf=23.97962074, PhiPS2=0.224674063 }, + new LeafInputDataCurve{ CO2S=783.7866455, PARi=990.5349609, Tleaf=24.24497566, PhiPS2=0.241833394 }, + new LeafInputDataCurve{ CO2S=981.9117737, PARi=990.3832764, Tleaf=24.27973061, PhiPS2=0.250284039 }, + new LeafInputDataCurve{ CO2S=1181.568982, PARi=990.2308533, Tleaf=24.49090347, PhiPS2=0.252074273 }, + new LeafInputDataCurve{ CO2S=1379.865356, PARi=990.0950989, Tleaf=24.66598072, PhiPS2=0.25113703 }, + new LeafInputDataCurve{ CO2S=1579.277905, PARi=989.9327454, Tleaf=24.77762184, PhiPS2=0.252735204 }, + new LeafInputDataCurve{ CO2S=1977.797449, PARi=989.8097778, Tleaf=24.84818077, PhiPS2=0.248197252 }, + }; + + public static LeafInputDataCurve GetLeafInputDataCurve => + new LeafInputDataCurve + { + CO2S = 3.1, + PARi = 1.1, + }; + + public static LeafInputDataSite SampleLeafInputDataSite => new LeafInputDataSite + { + Latitude = 10, + Longitude = 20, + SiteId = "MySiteId", + SpeciesSampled = "Maple" + }; + } +} \ No newline at end of file diff --git a/WebCms.Tests/WebCms.Tests.csproj b/WebCms.Tests/WebCms.Tests.csproj index f73a284..c502ce6 100644 --- a/WebCms.Tests/WebCms.Tests.csproj +++ b/WebCms.Tests/WebCms.Tests.csproj @@ -55,7 +55,9 @@ + + diff --git a/WebCms/App_Start/AutoMapperConfig.cs b/WebCms/App_Start/AutoMapperConfig.cs index ea4b254..c07c88d 100644 --- a/WebCms/App_Start/AutoMapperConfig.cs +++ b/WebCms/App_Start/AutoMapperConfig.cs @@ -59,6 +59,18 @@ namespace LeafWeb.WebCms.App_Start //System.Collections.Generic.HashSet`1[LeafWeb.Core.Entities.LeafInputDataCurve]"} Mapper.CreateMap, LeafInputData>() .ForAllMembers(opt => opt.Ignore()); + + Mapper.CreateMap() + .ForMember(dest => dest.SiteId, opt => opt.MapFrom(lid => lid.Site.SiteId)) + .ForMember(dest => dest.SpeciesSampled, opt => opt.MapFrom(lid => lid.Site.SpeciesSampled)) + .ForMember(dest => dest.Latitude, opt => opt.MapFrom(lid => lid.Site.Latitude)) + .ForMember(dest => dest.Longitude, opt => opt.MapFrom(lid => lid.Site.Longitude)) + // TODO: Change to range? + .ForMember(dest => dest.CO2S, opt => opt.MapFrom(lid => lid.Data.Max(d => d.CO2S) - lid.Data.Min(d => d.CO2S))) + .ForMember(dest => dest.PARi, opt => opt.MapFrom(lid => lid.Data.Max(d => d.PARi) - lid.Data.Min(d => d.PARi))) + .ForMember(dest => dest.Tleaf, opt => opt.MapFrom(lid => lid.Data.Max(d => d.Tleaf) - lid.Data.Min(d => d.Tleaf))) + .ForMember(dest => dest.PhiPS2, opt => opt.MapFrom(lid => lid.Data.Max(d => d.PhiPS2) - lid.Data.Min(d => d.PhiPS2))) + ; } } } \ No newline at end of file diff --git a/WebCms/Controllers/ResultsController.cs b/WebCms/Controllers/ResultsController.cs index a5a2316..335a093 100644 --- a/WebCms/Controllers/ResultsController.cs +++ b/WebCms/Controllers/ResultsController.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Web.Mvc; using LeafWeb.WebCms.Models; using LeafWeb.WebCms.Utility; +using Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix; using Umbraco.Web.Mvc; namespace LeafWeb.WebCms.Controllers @@ -12,22 +13,52 @@ namespace LeafWeb.WebCms.Controllers [MemberAuthorize(AllowGroup = "Authenticated")] public ActionResult Index(LeafDataQuery model) { - if (!model.HasParameters && !TempData.ContainsKey("Posted")) - model.usr = "on"; - - var resultItems = - DataService.GetLeafInputsOrdered(); - - resultItems = - QueryFilter.Search(resultItems, model, Members.GetCurrentLoginStatus()?.Email); - - var searchViewModel = new SearchViewModel + // if there are no search parameters, show an empty search page + if (!model.HasParameters) { - Items = resultItems, - Q = model - }; + // Default to "only my data" + if (!TempData.ContainsKey("Posted")) + model.usr = "on"; - return View(searchViewModel); + model.dsp = LeafDataQuery.LeafInputDataSearchParam; + model.compl = "1"; + + return View("Index", new SearchLeafInputViewModel + { + Q = model + }); + } + + var currentUserEmail = Members.GetCurrentLoginStatus()?.Email; + + if (model.ShowLeafInputData) + { + var resultItems = + DataService.GetLeafInputData(); + + resultItems = + QueryFilter.Search(resultItems, model, currentUserEmail); + + return View("LeafInputData", new SearchLeafInputDataViewModel + { + Results = resultItems, + Q = model + }); + } + else + { + var resultItems = + DataService.GetLeafInputsOrdered(); + + resultItems = + QueryFilter.Search(resultItems, model, currentUserEmail); + + return View("LeafInput", new SearchLeafInputViewModel + { + Results = resultItems, + Q = model + }); + } } [MemberAuthorize(AllowGroup = "Authenticated")] diff --git a/WebCms/Models/ChartViewModel.cs b/WebCms/Models/ChartViewModel.cs index 218219d..9fbbed9 100644 --- a/WebCms/Models/ChartViewModel.cs +++ b/WebCms/Models/ChartViewModel.cs @@ -5,14 +5,7 @@ namespace LeafWeb.WebCms.Models public class ChartViewModel { public int LeafInputId { get; set; } - public string CurveId { get; set; } public IEnumerable AvailableCurveId { get; set; } public string LeafInputIdentifier { get; set; } } - - public class ChartQueryViewModel - { - public int LeafInputId { get; set; } - public string CurveId { get; set; } - } } \ No newline at end of file diff --git a/WebCms/Models/LeafDataQuery.cs b/WebCms/Models/LeafDataQuery.cs index 73020e7..832a1d6 100644 --- a/WebCms/Models/LeafDataQuery.cs +++ b/WebCms/Models/LeafDataQuery.cs @@ -5,7 +5,11 @@ namespace LeafWeb.WebCms.Models { public class LeafDataQuery { - private const string FloatingPointRegex = @"^([-+]?[0-9]*\.[0-9]+|[0-9]+)$"; + // https://3widgets.com/ + private const string NumberRange_0_to_2000_Regex = @"^(\d|[1-9]\d{1,2}|1\d{3}|2000)(\.[0-9]+)?$"; + private const string NumberRange_0_to_3000_Regex = @"^(\d|[1-9]\d{1,2}|[12]\d{3}|3000)(\.[0-9]+)?$"; + private const string NumberRange_Neg20_to_50_Regex = @"^(-[1-9]|-1\d|-20|\d|[1-4]\d|50)(\.[0-9]+)?$"; + private const string NumberRange_0_to_1_Regex = @"^(0?\.[0-9]+)|(0|1)?$"; /// Query [Display(Name = "Search", Description = "General query")] @@ -39,22 +43,22 @@ namespace LeafWeb.WebCms.Models /// Sample CO2 concentration [Display(Name = "CO2 response curves (CO2S)")] - [RegularExpression(FloatingPointRegex, ErrorMessage = "Must be numeric")] + [RegularExpression(NumberRange_0_to_2000_Regex, ErrorMessage = "Must be numeric, 0 to 2000")] public string co2s { get; set; } /// PAR measured by the in-chamber quantum sensor [Display(Name = "Light response curves (PARi)")] - [RegularExpression(FloatingPointRegex, ErrorMessage = "Must be numeric")] + [RegularExpression(NumberRange_0_to_3000_Regex, ErrorMessage = "Must be numeric, 0 to 3000")] public string pari { get; set; } /// temperature of leaf thermocouple [Display(Name = "Temperature response curves (Tleaf)")] - [RegularExpression(FloatingPointRegex, ErrorMessage = "Must be numeric")] + [RegularExpression(NumberRange_Neg20_to_50_Regex, ErrorMessage = "Must be numeric, -20 to 50")] public string tleaf { get; set; } /// DeltaF/Fm, the fraction of absorbed PSII photons that are used in photochemistry [Display(Name = "Fluorometry measurements (PhiPS2)")] - [RegularExpression(FloatingPointRegex, ErrorMessage = "Must be numeric")] + [RegularExpression(NumberRange_0_to_1_Regex, ErrorMessage = "Must be numeric, 0 to 1")] public string phips2 { get; set; } [Display(Name = "Show Only Successfully Completed")] @@ -75,6 +79,15 @@ namespace LeafWeb.WebCms.Models public bool OnlyUserData => !string.IsNullOrEmpty(usr); + [Display(Name = "Result Type")] + //[UIHint("Radio")] + public string dsp { get; set; } + + public const string LeafInputDataSearchParam = "data"; + public bool ShowLeafInputData => dsp == LeafInputDataSearchParam; + + public const string LeafInputSearchParam = "set"; + public bool ShowLeafInput => dsp == LeafInputSearchParam; public bool HasExtendedParameters => !( diff --git a/WebCms/Models/LeafDataResultViewModel.cs b/WebCms/Models/LeafDataResultViewModel.cs new file mode 100644 index 0000000..c0158e0 --- /dev/null +++ b/WebCms/Models/LeafDataResultViewModel.cs @@ -0,0 +1,44 @@ +using System.ComponentModel.DataAnnotations; +using AutoMapper; +using LeafWeb.Core.Entities; + +namespace LeafWeb.WebCms.Models +{ + public class LeafDataResultViewModel + { + [Display(Name = "Site ID", Description = "The site's name/Fluxnet ID, if known")] + public string SiteId { get; set; } + + [Display(Name = "Species Name")] + public string SpeciesSampled { get; set; } + + /// Site latitude, northern hemisphere positive + [Display(Name = "Latitude")] + public double? Latitude { get; set; } + + /// Site longitude, east positive + [Display(Name = "Longitude")] + public double? Longitude { get; set; } + + /// Sample CO2 concentration + [Display(Name = "CO2 response curves (CO2S)")] + public double? CO2S { get; set; } + + /// PAR measured by the in-chamber quantum sensor + [Display(Name = "Light response curves (PARi)")] + public double? PARi { get; set; } + + /// temperature of leaf thermocouple + [Display(Name = "Temperature response curves (Tleaf)")] + public double? Tleaf { get; set; } + + /// DeltaF/Fm, the fraction of absorbed PSII photons that are used in photochemistry + [Display(Name = "Fluorometry measurements (PhiPS2)")] + public double? PhiPS2 { get; set; } + + public LeafDataResultViewModel(LeafInputData inputData) + { + Mapper.Map(inputData, this); + } + } +} \ No newline at end of file diff --git a/WebCms/Models/LeafInputDataCurveViewModel.cs b/WebCms/Models/LeafInputDataCurveViewModel.cs index 9a35428..27b1c85 100644 --- a/WebCms/Models/LeafInputDataCurveViewModel.cs +++ b/WebCms/Models/LeafInputDataCurveViewModel.cs @@ -18,9 +18,40 @@ namespace LeafWeb.WebCms.Models public double? PhiPS2 { get; set; } public LeafInputDataCurveViewModel() {} + static LeafInputDataCurveViewModel() + { + Mapper.CreateMap() + .ForMember(m => m.CO2S, + conf => + conf.MapFrom(d => + LeafInputData.Range(d.Data, c => c.CO2S))) + .ForMember(m => m.PARi, + conf => + conf.MapFrom(d => + LeafInputData.Range(d.Data, c => c.PARi))) + .ForMember(m => m.Tleaf, + conf => + conf.MapFrom(d => + LeafInputData.Range(d.Data, c => c.Tleaf))) + .ForMember(m => m.PhiPS2, + conf => + conf.MapFrom(d => + LeafInputData.Range(d.Data, c => c.PhiPS2))) + ; + } + public LeafInputDataCurveViewModel(LeafInputDataCurve leafInputDataCurve) { Mapper.Map(leafInputDataCurve, this); } + + public LeafInputDataCurveViewModel(LeafInputData leafInputData) + { + Mapper.Map(leafInputData, this); + //CO2S = LeafInputData.Range(dataCurves, c => c.CO2S); + //PARi = LeafInputData.Range(dataCurves, c => c.PARi); + //Tleaf = LeafInputData.Range(dataCurves, c => c.Tleaf); + //PhiPS2 = LeafInputData.Range(dataCurves, c => c.PhiPS2); + } } } \ No newline at end of file diff --git a/WebCms/Models/SearchViewModel.cs b/WebCms/Models/SearchLeafInputDataViewModel.cs similarity index 54% rename from WebCms/Models/SearchViewModel.cs rename to WebCms/Models/SearchLeafInputDataViewModel.cs index 62ec9bb..844e3a9 100644 --- a/WebCms/Models/SearchViewModel.cs +++ b/WebCms/Models/SearchLeafInputDataViewModel.cs @@ -1,11 +1,12 @@ using System.Collections.Generic; +using System.Linq; using LeafWeb.Core.Entities; namespace LeafWeb.WebCms.Models { - public class SearchViewModel + public class SearchLeafInputDataViewModel { - public IEnumerable Items { get; set; } + public IQueryable Results { get; set; } public LeafDataQuery Q { get; set; } } } \ No newline at end of file diff --git a/WebCms/Models/SearchLeafInputViewModel.cs b/WebCms/Models/SearchLeafInputViewModel.cs new file mode 100644 index 0000000..348569b --- /dev/null +++ b/WebCms/Models/SearchLeafInputViewModel.cs @@ -0,0 +1,11 @@ +using System.Linq; +using LeafWeb.Core.Entities; + +namespace LeafWeb.WebCms.Models +{ + public class SearchLeafInputViewModel + { + public IQueryable Results { get; set; } + public LeafDataQuery Q { get; set; } + } +} \ No newline at end of file diff --git a/WebCms/Utility/QueryFilter.cs b/WebCms/Utility/QueryFilter.cs index 377a1c6..f0a3265 100644 --- a/WebCms/Utility/QueryFilter.cs +++ b/WebCms/Utility/QueryFilter.cs @@ -5,36 +5,40 @@ using LeafWeb.WebCms.Models; namespace LeafWeb.WebCms.Utility { + // NOTE: Make sure to update both Search functions with any changes. internal static class QueryFilter { - public static IQueryable Search(IQueryable resultItems, LeafDataQuery query, string currentUserEmail) + + public static IQueryable Search(IQueryable leafInput, LeafDataQuery query, string currentUserEmail) { // search functionality if (!string.IsNullOrEmpty(query.q)) { - foreach (var piece in query.q.Split(' ').Select(p => p.Trim())) - { - resultItems = - from li in resultItems - where li.Name.Contains(piece) - || li.Identifier.Contains(piece) - || li.SiteId.Contains(piece) - select li; - } + leafInput = + query.q.Split(' ') + .Select(p => p.Trim()) + .Aggregate( + leafInput, + (current, piece) => + from li in current + where li.Name.Contains(piece) + || li.Identifier.Contains(piece) + || li.SiteId.Contains(piece) + select li); } if (!string.IsNullOrEmpty(query.species)) { - resultItems = - from li in resultItems + leafInput = + from li in leafInput where li.LeafInputData.Any(lid => lid.MajorSpecies.Contains(query.species)) select li; } if (!string.IsNullOrEmpty(query.siteid)) { - resultItems = - from li in resultItems + leafInput = + from li in leafInput where li.SiteId.Contains(query.siteid) select li; } @@ -48,8 +52,8 @@ namespace LeafWeb.WebCms.Utility range = int.Parse(query.latr); } - resultItems = - from li in resultItems + leafInput = + from li in leafInput where li.LeafInputData.Any(lid => lid.Site.Latitude >= latitude - range && lid.Site.Latitude <= latitude + range) @@ -65,22 +69,21 @@ namespace LeafWeb.WebCms.Utility range = int.Parse(query.lonr); } - resultItems = - from li in resultItems + leafInput = + from li in leafInput where li.LeafInputData.Any(lid => lid.Site.Longitude >= longitude - range && lid.Site.Longitude <= longitude + range) select li; } - // co2s if (!string.IsNullOrEmpty(query.co2s)) { var p = double.Parse(query.co2s); - resultItems = - from li in resultItems + leafInput = + from li in leafInput where // maximum range inside LeafInputFiles li.LeafInputData.Max(lid => @@ -91,14 +94,13 @@ namespace LeafWeb.WebCms.Utility select li; } - // pari if (!string.IsNullOrEmpty(query.pari)) { var p = double.Parse(query.pari); - resultItems = - from li in resultItems + leafInput = + from li in leafInput where // maximum range inside LeafInputFiles li.LeafInputData.Max(lid => @@ -114,8 +116,8 @@ namespace LeafWeb.WebCms.Utility { var p = double.Parse(query.tleaf); - resultItems = - from li in resultItems + leafInput = + from li in leafInput where // maximum range inside LeafInputFiles li.LeafInputData.Max(lid => @@ -131,8 +133,8 @@ namespace LeafWeb.WebCms.Utility { var p = double.Parse(query.phips2); - resultItems = - from li in resultItems + leafInput = + from li in leafInput where // maximum range inside LeafInputFiles li.LeafInputData.Max(lid => @@ -145,8 +147,8 @@ namespace LeafWeb.WebCms.Utility if (query.ShowOnlySuccessfullyCompleted) { - resultItems = - from li in resultItems + leafInput = + from li in leafInput where li.CurrentStatus == LeafInputStatusType.Complete // didn't have an error message @@ -156,8 +158,8 @@ namespace LeafWeb.WebCms.Utility if (query.ShowOnlyErred) { - resultItems = - from li in resultItems + leafInput = + from li in leafInput where // has an error message li.OutputFiles.Any(f => f.Filename.Contains(LeafOutputFile.Filename_ErrorMessage)) @@ -166,14 +168,177 @@ namespace LeafWeb.WebCms.Utility if (query.OnlyUserData && !string.IsNullOrEmpty(currentUserEmail)) { - resultItems = - from li in resultItems + leafInput = + from li in leafInput where li.Email.Equals(currentUserEmail, StringComparison.OrdinalIgnoreCase) select li; } - return resultItems; + return leafInput; + } + + + public static IQueryable Search(IQueryable leafInputData, LeafDataQuery query, string currentUserEmail) + { + // search functionality + if (!string.IsNullOrEmpty(query.q)) + { + leafInputData = + query.q.Split(' ') + .Select(p => p.Trim()) + .Aggregate( + leafInputData, + (current, piece) => + from lid in current + where lid.LeafInput.Name.Contains(piece) + || lid.LeafInput.Identifier.Contains(piece) + || lid.LeafInput.SiteId.Contains(piece) + select lid); + } + + if (!string.IsNullOrEmpty(query.species)) + { + leafInputData = + from lid in leafInputData + where lid.MajorSpecies.Contains(query.species) + select lid; + } + + if (!string.IsNullOrEmpty(query.siteid)) + { + leafInputData = + from lid in leafInputData + where lid.LeafInput.SiteId.Contains(query.siteid) + select lid; + } + + if (!string.IsNullOrEmpty(query.lat)) + { + var latitude = int.Parse(query.lat); + var range = 0; + if (!string.IsNullOrEmpty(query.latr)) + { + range = int.Parse(query.latr); + } + + leafInputData = + from lid in leafInputData + where + lid.Site.Latitude >= latitude - range && + lid.Site.Latitude <= latitude + range + select lid; + } + + if (!string.IsNullOrEmpty(query.lon)) + { + var longitude = int.Parse(query.lon); + var range = 0; + if (!string.IsNullOrEmpty(query.lonr)) + { + range = int.Parse(query.lonr); + } + + leafInputData = + from lid in leafInputData + where + lid.Site.Longitude >= longitude - range && + lid.Site.Longitude <= longitude + range + select lid; + } + + + // co2s + if (!string.IsNullOrEmpty(query.co2s)) + { + var p = double.Parse(query.co2s); + + leafInputData = + from lid in leafInputData + where + // range of LeafInputData + (lid.Data.Max(d => d.CO2S) + - lid.Data.Min(d => d.CO2S)) + >= p + select lid; + } + + // pari + if (!string.IsNullOrEmpty(query.pari)) + { + var p = double.Parse(query.pari); + + leafInputData = + from lid in leafInputData + where + // range of LeafInputData + (lid.Data.Max(d => d.PARi) + - lid.Data.Min(d => d.PARi)) + >= p + select lid; + } + + // tleaf + if (!string.IsNullOrEmpty(query.tleaf)) + { + var p = double.Parse(query.tleaf); + + leafInputData = + from lid in leafInputData + where + // range of LeafInputData + (lid.Data.Max(d => d.Tleaf) + - lid.Data.Min(d => d.Tleaf)) + >= p + select lid; + } + + // phips2 + if (!string.IsNullOrEmpty(query.phips2)) + { + var p = double.Parse(query.phips2); + + leafInputData = + from lid in leafInputData + where + // range of LeafInputData + (lid.Data.Max(d => d.PhiPS2) + - lid.Data.Min(d => d.PhiPS2)) + >= p + select lid; + } + + if (query.ShowOnlySuccessfullyCompleted) + { + leafInputData = + from lid in leafInputData + where + lid.LeafInput.CurrentStatus == LeafInputStatusType.Complete + // didn't have an error message + && !lid.LeafInput.OutputFiles.Any(f => f.Filename.Contains(LeafOutputFile.Filename_ErrorMessage)) + select lid; + } + + if (query.ShowOnlyErred) + { + leafInputData = + from lid in leafInputData + where + // has an error message + lid.LeafInput.OutputFiles.Any(f => f.Filename.Contains(LeafOutputFile.Filename_ErrorMessage)) + select lid; + } + + if (query.OnlyUserData && !string.IsNullOrEmpty(currentUserEmail)) + { + leafInputData = + from lid in leafInputData + where + lid.LeafInput.Email.Equals(currentUserEmail, StringComparison.OrdinalIgnoreCase) + select lid; + } + + return leafInputData; } } } \ No newline at end of file diff --git a/WebCms/Views/Chart/Index.cshtml b/WebCms/Views/Chart/Index.cshtml index eed5cd1..2b8992a 100644 --- a/WebCms/Views/Chart/Index.cshtml +++ b/WebCms/Views/Chart/Index.cshtml @@ -2,7 +2,6 @@ @model LeafWeb.WebCms.Models.ChartViewModel @{ Html.RequiresJs("~/scripts/Chart.js"); - Html.RequiresCss("~/Content/jquery.fancybox.min.css"); Html.RequiresJs("~/scripts/jquery.fancybox.min.js"); } @@ -16,16 +15,21 @@ @foreach (var cId in Model.AvailableCurveId) {

- - - @cId Chart - + @ChartLink(Model.LeafInputId, cId)

} + +@helper ChartLink(int leafInputId, string curveId) +{ + + + @curveId Chart + +} \ No newline at end of file diff --git a/WebCms/Views/Results/Index.cshtml b/WebCms/Views/Results/Index.cshtml index 9a56aab..efa3214 100644 --- a/WebCms/Views/Results/Index.cshtml +++ b/WebCms/Views/Results/Index.cshtml @@ -1,70 +1,15 @@ @using LeafWeb.Core.Entities @using LeafWeb.WebCms.Controllers @using LeafWeb.WebCms.Utility -@model SearchViewModel -@{ - var grid = new WebGrid(Model.Items, rowsPerPage: 45); -} +@model SearchLeafInputViewModel -
-
- @Model.Items.Count() results -
-
+
+
@Html.Partial("_LeafDataQuery", Model.Q, new ViewDataDictionary{ - {"actionName", "Search"}, - {"controllerName", "Results"}, - {"htmlFormAction", "/services/search/"}}) + {"actionName", "Search"}, + {"controllerName", "Results"}, + {"htmlFormAction", "/services/search/"}, + {"expand", true}})
- -@if (Model.Items.Any()) -{ -
- @grid.Table(columns: - grid.Columns( - grid.Column("Identifier", "Identifier"), - grid.Column("SiteId", "Site Id"), - //grid.Column("Name", "Submitted By"), - grid.Column("CurrentStatus", "Status", item => Status(item.Value)), - grid.Column("", format: item => Actions(item.Value), canSort: false) - ), - htmlAttributes: new { @class = "table table-sm table-striped table-bordered table-hover" } - ) -
-
-
@grid.PagerList()
- @*
- Download Results - @DownloadResults() -
*@ -
-} -else -{ -

No results. Click here to submit Leaf Data.

-} - - -@helper Actions(LeafInput leafInput) -{ - @Html.Partial("_LeafInputActions", leafInput) -} - -@helper Status(LeafInput leafInput) -{ - @Html.Partial("DisplayTemplates/_LeafInputStatus", leafInput) -} - -@helper DownloadResults() -{ - -} \ No newline at end of file diff --git a/WebCms/Views/Results/LeafInput.cshtml b/WebCms/Views/Results/LeafInput.cshtml new file mode 100644 index 0000000..cbcd71f --- /dev/null +++ b/WebCms/Views/Results/LeafInput.cshtml @@ -0,0 +1,69 @@ +@using LeafWeb.Core.Entities +@using LeafWeb.WebCms.Utility +@model SearchLeafInputViewModel +@{ + var grid = new WebGrid(Model.Results, rowsPerPage: 45); +} + +
+
+ @Model.Results.Count() results +
+
+ @Html.Partial("_LeafDataQuery", Model.Q, + new ViewDataDictionary{ + {"actionName", "Search"}, + {"controllerName", "Results"}, + {"htmlFormAction", "/services/search/"}}) +
+
+ +@if (Model.Results.Any()) +{ +
+ @grid.Table(columns: + grid.Columns( + grid.Column("Identifier", "Identifier"), + grid.Column("SiteId", "Site Id"), + //grid.Column("Name", "Submitted By"), + grid.Column("CurrentStatus", "Status", item => Status(item.Value)), + grid.Column("", format: item => Actions(item.Value), canSort: false) + ), + htmlAttributes: new { @class = "table table-sm table-striped table-bordered table-hover" } + ) +
+
+
@grid.PagerList()
+ @*
+ Download Results + @DownloadResults() +
*@ +
+} +else +{ + @Html.Partial("NoResults") +} + + +@helper Actions(LeafInput leafInput) +{ + @Html.Partial("_LeafInputActions", leafInput) +} + +@helper Status(LeafInput leafInput) +{ + @Html.Partial("DisplayTemplates/_LeafInputStatus", leafInput) +} + +@helper DownloadResults() +{ + +} \ No newline at end of file diff --git a/WebCms/Views/Results/LeafInputData.cshtml b/WebCms/Views/Results/LeafInputData.cshtml new file mode 100644 index 0000000..03e656c --- /dev/null +++ b/WebCms/Views/Results/LeafInputData.cshtml @@ -0,0 +1,84 @@ +@using LeafWeb.Core.Entities +@using LeafWeb.WebCms.Controllers +@using LeafWeb.WebCms.Utility +@model SearchLeafInputDataViewModel +@{ + var grid = new WebGrid(Model.Results, rowsPerPage: 45); +} + +
+
+ @Model.Results.Count() results +
+
+ @Html.Partial("_LeafDataQuery", Model.Q, + new ViewDataDictionary{ + {"actionName", "Search"}, + {"controllerName", "Results"}, + {"htmlFormAction", "/services/search/"}}) +
+
+ +@if (Model.Results.Any()) +{ +
+ @grid.Table(columns: + grid.Columns( + grid.Column("Identifier", "Identifier", data => data.LeafInput.Identifier), // TODO: link to LeafInput details + grid.Column("SiteId", "Site Id", data => data.LeafInput.SiteId), + grid.Column("", "Location: Lat., Long., Elev.", data => FormatLatLongEl(data.Site)), + grid.Column("CO2S", "CO2S [umol/mol]", data => data.CO2S_Range?.ToString("#.##")), + grid.Column("PARi", "PARi [umol/m2/s]", data => data.PARi_Range?.ToString("#.##")), + grid.Column("Tleaf", "Tleaf [oC]", data => data.Tleaf_Range?.ToString("#.##")), + grid.Column("PhiPS2", "PhiPS2", data => data.PhiPS2_Range?.ToString("#.##")), + grid.Column("", "", data => ChartLink(data.LeafInput)) + ), + htmlAttributes: new { @class = "table table-sm table-striped table-bordered table-hover" } + ) +
+
+
@grid.PagerList()
+ @*
+ Download Results + @DownloadResults() +
*@ +
+} +else +{ +

No results. Click here to submit Leaf Data.

+} + +@helper FormatLatLongEl(LeafInputDataSite site) +{ + @(site.Latitude?.ToString("#.00"))if (site.Latitude != null){°if (site.Longitude != null){, } } + @(site.Longitude?.ToString("#.00"))if (site.Longitude != null){°if (site.Elevation != null){, }} + @(site.Elevation?.ToString("#.#m")) +} + +@helper ChartLink(LeafInput item) +{ + @Html.Partial("DisplayTemplates/_ChartLink", item.Id) +} + +@helper Actions(LeafInput leafInput) +{ + @Html.Partial("_LeafInputActions", leafInput) +} + +@helper Status(LeafInput leafInput) +{ + @Html.Partial("DisplayTemplates/_LeafInputStatus", leafInput) +} + +@helper DownloadResults() +{ + +} \ No newline at end of file diff --git a/WebCms/Views/Results/NoResults.cshtml b/WebCms/Views/Results/NoResults.cshtml new file mode 100644 index 0000000..63bd953 --- /dev/null +++ b/WebCms/Views/Results/NoResults.cshtml @@ -0,0 +1,9 @@ +@using LeafWeb.WebCms.Controllers +
+ +
\ No newline at end of file diff --git a/WebCms/Views/Results/Recent.cshtml b/WebCms/Views/Results/Recent.cshtml index 2d86737..a85494d 100644 --- a/WebCms/Views/Results/Recent.cshtml +++ b/WebCms/Views/Results/Recent.cshtml @@ -1,23 +1,31 @@ @using LeafWeb.Core.Entities +@using LeafWeb.WebCms.Controllers @using LeafWeb.WebCms.Utility @model IQueryable @{ var grid = new WebGrid(Model, rowsPerPage: 45); } -
- @grid.Table(columns: - grid.Columns( - grid.Column("Identifier", "Identifier"), - grid.Column("SiteId", "Site Id"), - //grid.Column("Name", "Submitted By"), - grid.Column("CurrentStatus", "Status", item => Status(item.Value)), - grid.Column("", "", item => ChartLink(item.Value)) - ), - htmlAttributes: new { @class = "table table-sm table-striped table-bordered table-hover" } - ) - @grid.PagerList() -
+@if (Model.Any()) +{ +
+ @grid.Table(columns: + grid.Columns( + grid.Column("Identifier", "Identifier"), + grid.Column("SiteId", "Site Id"), + //grid.Column("Name", "Submitted By"), + grid.Column("CurrentStatus", "Status", item => Status(item.Value)), + grid.Column("", "", item => ChartLink(item.Value)) + ), + htmlAttributes: new { @class = "table table-sm table-striped table-bordered table-hover" } + ) + @grid.PagerList() +
+} +else +{ + @Html.Partial("NoResults") +} @helper ChartLink(LeafInput leafInput) { diff --git a/WebCms/Views/Shared/_LeafDataQuery.cshtml b/WebCms/Views/Shared/_LeafDataQuery.cshtml index 9026c34..47d4a33 100644 --- a/WebCms/Views/Shared/_LeafDataQuery.cshtml +++ b/WebCms/Views/Shared/_LeafDataQuery.cshtml @@ -12,6 +12,7 @@ var controllerName = string.Empty; var htmlFormAction = string.Empty; var admin = false; + var expand = false; if (ViewData.ContainsKey("actionName")) { @@ -29,6 +30,10 @@ { admin = true; } + if (ViewData.ContainsKey("expand") || Model.HasExtendedParameters) + { + expand = true; + } } @using (Html.BeginUmbracoForm(actionName, controllerName, null, new { action = htmlFormAction, id = "leafdataquery" })) { @@ -38,21 +43,45 @@
- + - - +
-
+ +
+
+
Result Type:
+
+
+ checked} > + +
+
+ checked} > + +
+
+
+
@Html.EditorFor(m => m.siteid) @@ -63,23 +92,23 @@

-
+
- @Html.EditorFor(m => m.lat, new {size = "small", append = "°"}) + @Html.EditorFor(m => m.lat, new { size = "small", append = "°" })
- @Html.EditorFor(m => m.latr, new {size = "small", prepend = "±", append = "°"}) + @Html.EditorFor(m => m.latr, new { size = "small", prepend = "±", append = "°" })
-
+
- @Html.EditorFor(m => m.lon, new {size = "small", append = "°"}) + @Html.EditorFor(m => m.lon, new { size = "small", append = "°" })
- @Html.EditorFor(m => m.lonr, new {size = "small", prepend = "±", append = "°"}) + @Html.EditorFor(m => m.lonr, new { size = "small", prepend = "±", append = "°" })
@@ -88,32 +117,32 @@
Curve Variation range minimum
- @Html.EditorFor(m => m.co2s, new {size = "small", prepend = ">", append = "umol/m"}) + @Html.EditorFor(m => m.co2s, new { size = "small", prepend = ">", append = "umol/m" })
- @Html.EditorFor(m => m.pari, new {size = "small", prepend = ">", append = "umol/m2/s"}) + @Html.EditorFor(m => m.pari, new { size = "small", prepend = ">", append = "umol/m2/s" })
- @Html.EditorFor(m => m.tleaf, new {size = "small", prepend = ">", append = "oC"}) + @Html.EditorFor(m => m.tleaf, new { size = "small", prepend = ">", append = "oC" })
- @Html.EditorFor(m => m.phips2, new {size = "small", prepend = ">"}) + @Html.EditorFor(m => m.phips2, new { size = "small", prepend = ">" })

-
+
@Html.EditorFor(m => m.compl)
@if (admin) {
-
+
@Html.EditorFor(m => m.erred)
- } + }
diff --git a/WebCms/Views/Shared/_LeafInputActions.cshtml b/WebCms/Views/Shared/_LeafInputActions.cshtml index e301599..85e8fee 100644 --- a/WebCms/Views/Shared/_LeafInputActions.cshtml +++ b/WebCms/Views/Shared/_LeafInputActions.cshtml @@ -54,21 +54,21 @@
-@helper Details_AdminLink(dynamic item) +@helper Details_AdminLink(LeafInput item) { var cssClass = CssClassUtil.CreateCssClassDataDictionary("dropdown-item"); @Html.Partial("DisplayTemplates/_Details_AdminLink", (int)item.Id, cssClass) } -@helper Details_ResultsLink(dynamic item) +@helper Details_ResultsLink(LeafInput item) { var cssClass = CssClassUtil.CreateCssClassDataDictionary("dropdown-item"); @Html.Partial("DisplayTemplates/_Details_ResultsLink", (int)item.Id, cssClass) } -@helper ChartLink(dynamic item) +@helper ChartLink(LeafInput item) { var cssClass = CssClassUtil.CreateCssClassDataDictionary("dropdown-item"); @@ -79,13 +79,13 @@ @Html.Partial("DisplayTemplates/_ChartLink", (int)item.Id, cssClass) } -@helper DownloadInput(dynamic item) +@helper DownloadInput(LeafInput item) { Input } -@helper DownloadOutputToUser(dynamic item) +@helper DownloadOutputToUser(LeafInput item) { Output diff --git a/WebCms/WebCms.csproj b/WebCms/WebCms.csproj index 402b8bc..f1a9f3c 100644 --- a/WebCms/WebCms.csproj +++ b/WebCms/WebCms.csproj @@ -1084,6 +1084,9 @@ + + + Web.config @@ -1127,6 +1130,7 @@ + @@ -1137,7 +1141,8 @@ - + +