diff --git a/Core/Utility/TimeInProgressEstimater.cs b/Core/Utility/TimeInProgressEstimater.cs index ace8845..6b5ce01 100644 --- a/Core/Utility/TimeInProgressEstimater.cs +++ b/Core/Utility/TimeInProgressEstimater.cs @@ -23,12 +23,16 @@ namespace LeafWeb.Core.Utility _yData = yData.ToArray(); } + private Func FitFunc => Fit.PolynomialFunc(_xData, _yData, 3); + public TimeSpan EstimateTimeInProgress(ILeafInput leafInput) { - //var lineFunc = Fit.LineFunc(_xData, _yData); - var lineFunc = Fit.PolynomialFunc(_xData, _yData, 3); - var estimate = lineFunc(leafInput.InputFiles.Count); - return ConvertToTimeSpan(estimate); + return EstimateTimeInProgress(leafInput.InputFiles.Count); + } + + public TimeSpan EstimateTimeInProgress(int inputFileCount) + { + return ConvertToTimeSpan(FitFunc(inputFileCount)); } private static double ConvertFromTimeSpan(TimeSpan timeSpan) diff --git a/WebCms/App_Data/Models/all.dll.path b/WebCms/App_Data/Models/all.dll.path index 393d9a7..bc81773 100644 --- a/WebCms/App_Data/Models/all.dll.path +++ b/WebCms/App_Data/Models/all.dll.path @@ -1 +1 @@ -C:\Users\poprhythm\AppData\Local\Temp\Temporary ASP.NET Files\vs\f80e29bb\faae20bf\App_Web_all.generated.cs.8f9494c4.idigbf5n.dll \ No newline at end of file +C:\Users\poprhythm\AppData\Local\Temp\Temporary ASP.NET Files\vs\f80e29bb\faae20bf\App_Web_all.generated.cs.8f9494c4.g_xi0dfe.dll \ No newline at end of file diff --git a/WebCms/Content/style.css b/WebCms/Content/style.css index 697b0d7..0354c10 100644 --- a/WebCms/Content/style.css +++ b/WebCms/Content/style.css @@ -188,3 +188,15 @@ form .validation-summary-errors ul { .divider-right { border-right: 1px dashed #333; } +.read { + overflow: hidden; + font-size: 16px !important; + transition: all 0.3s; + margin-bottom: 10px; } + +.read-less { + height: 90px !important; } + +code, pre { + line-height: 1; } + diff --git a/WebCms/Content/style.min.css b/WebCms/Content/style.min.css index 77b6f42..7681efb 100644 --- a/WebCms/Content/style.min.css +++ b/WebCms/Content/style.min.css @@ -1 +1 @@ -body.debug header .brand{position:relative;}body.debug header .brand:before{content:"";font-family:FontAwesome;font-style:normal;font-weight:normal;text-decoration:inherit;color:#f00;font-size:60px;padding-right:.5em;position:absolute;top:10px;left:0;}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;}.top-buffer{margin-top:20px;}.detail-actions>a,.detail-actions>form>button{margin-top:20px;float:left;clear:left;}.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:#a8ed4f;}.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{white-space:nowrap;}.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:"";}.status.status-cancelpending,.status.status-cancelling{color:#f0ad4e;}.status.status-cancelled{color:#ec971f;}.status.status-cancelpending:after{content:"";}.status.status-cancelling:after{content:"";}.status.status-cancelled: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;}.dropdown-menu li form .btn-link{display:block;color:#333;clear:both;float:left;font-size:1rem;font-weight:normal;line-height:1.42857;min-width:160px;padding:3px 20px;text-align:left;white-space:nowrap;}.dropdown-menu li form .btn-link:focus,.dropdown-menu li form .btn-link:hover{text-decoration:none;color:#262626;background-color:#f5f5f5;}.divider-right{border-right:1px dashed #333;} \ No newline at end of file +body.debug header .brand{position:relative;}body.debug header .brand:before{content:"";font-family:FontAwesome;font-style:normal;font-weight:normal;text-decoration:inherit;color:#f00;font-size:60px;padding-right:.5em;position:absolute;top:10px;left:0;}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;}.top-buffer{margin-top:20px;}.detail-actions>a,.detail-actions>form>button{margin-top:20px;float:left;clear:left;}.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:#a8ed4f;}.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{white-space:nowrap;}.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:"";}.status.status-cancelpending,.status.status-cancelling{color:#f0ad4e;}.status.status-cancelled{color:#ec971f;}.status.status-cancelpending:after{content:"";}.status.status-cancelling:after{content:"";}.status.status-cancelled: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;}.dropdown-menu li form .btn-link{display:block;color:#333;clear:both;float:left;font-size:1rem;font-weight:normal;line-height:1.42857;min-width:160px;padding:3px 20px;text-align:left;white-space:nowrap;}.dropdown-menu li form .btn-link:focus,.dropdown-menu li form .btn-link:hover{text-decoration:none;color:#262626;background-color:#f5f5f5;}.divider-right{border-right:1px dashed #333;}.read{overflow:hidden;font-size:16px !important;transition:all .3s;margin-bottom:10px;}.read-less{height:90px !important;}code,pre{line-height:1;} \ No newline at end of file diff --git a/WebCms/Content/style.scss b/WebCms/Content/style.scss index cf29030..1cbffa8 100644 --- a/WebCms/Content/style.scss +++ b/WebCms/Content/style.scss @@ -238,4 +238,18 @@ form .validation-summary-errors ul { .divider-right { border-right: 1px dashed #333; +} + +.read{ + overflow: hidden; + font-size: 16px !important; + transition: all 0.3s; + margin-bottom: 10px; +} +.read-less{ + height: 90px!important; +} + +code,pre { + line-height: 1; } \ No newline at end of file diff --git a/WebCms/Controllers/QueueController.cs b/WebCms/Controllers/QueueController.cs index c171424..9de1bc1 100644 --- a/WebCms/Controllers/QueueController.cs +++ b/WebCms/Controllers/QueueController.cs @@ -20,6 +20,7 @@ namespace LeafWeb.WebCms.Controllers var resultItems = DataService.GetLeafInputsOrdered() ; + // search functionality if (!string.IsNullOrEmpty(query)) { foreach (var piece in query.Split(' ').Select(p => p.Trim())) @@ -33,13 +34,16 @@ namespace LeafWeb.WebCms.Controllers } } + // completed leaf input for computing runtime statistics var completedLeafInput = DataService.GetLeafInputsOrdered().Where(li => li.CurrentStatus == LeafInputStatusType.Complete); + var timeInProgressEstimater = new TimeInProgressEstimater(completedLeafInput.Take(20)); var serviceDescription = ServiceDescription(); var queueViewModel = new QueueViewModel { - Items = resultItems, ServerDescription = serviceDescription, Query = query, CompletedLeafInput = completedLeafInput + Items = resultItems, ServerDescription = serviceDescription, Query = query, + TimeInProgressEstimater = timeInProgressEstimater }; return View(queueViewModel); diff --git a/WebCms/Models/LeafInputDetails.cs b/WebCms/Models/LeafInputDetails.cs index 6876201..600d6c1 100644 --- a/WebCms/Models/LeafInputDetails.cs +++ b/WebCms/Models/LeafInputDetails.cs @@ -42,9 +42,11 @@ namespace LeafWeb.WebCms.Models public DateTime Added { get; set; } [Display(Name = "Piscal Error")] + [UIHint("PreReadMore")] public string OutputErrorMessage { get; set; } [Display(Name = "Piscal Warning")] + [UIHint("PreReadMore")] public string OutputWarningMessage { get; set; } [Display(Name = "Time In Progress")] diff --git a/WebCms/Models/QueueViewModel.cs b/WebCms/Models/QueueViewModel.cs index fdf246a..d4ce771 100644 --- a/WebCms/Models/QueueViewModel.cs +++ b/WebCms/Models/QueueViewModel.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using LeafWeb.Core.Entities; +using LeafWeb.Core.Utility; namespace LeafWeb.WebCms.Models { @@ -10,6 +11,6 @@ namespace LeafWeb.WebCms.Models public string ServerStatus { get; set; } public IEnumerable Items { get; set; } public string Query { get; set; } - public IQueryable CompletedLeafInput { get; set; } + public TimeInProgressEstimater TimeInProgressEstimater { get; set; } } } \ No newline at end of file diff --git a/WebCms/Views/Queue/Index.cshtml b/WebCms/Views/Queue/Index.cshtml index f697d4d..0c63898 100644 --- a/WebCms/Views/Queue/Index.cshtml +++ b/WebCms/Views/Queue/Index.cshtml @@ -8,7 +8,11 @@
- Service description: @Model.ServerDescription + Service description: @Model.ServerDescription
+ Est. processing time by LeafInput size - + < 1: @Model.TimeInProgressEstimater.EstimateTimeInProgress(1).ToRoundedReadableString() + 10: @Model.TimeInProgressEstimater.EstimateTimeInProgress(10).ToRoundedReadableString() + 100: @Model.TimeInProgressEstimater.EstimateTimeInProgress(100).ToRoundedReadableString()
@using (Html.BeginUmbracoForm("Search", FormMethod.Post)) @@ -129,7 +133,7 @@ if (leafInput.EndTime.HasValue) } var summaryText = string.Join(Environment.NewLine, summary); - @leafInput.InputFiles.Count input @if(leafInput.InputFiles.Count > 1) {files} else { file} + @leafInput.InputFiles.Count @if(leafInput.InputFiles.Count > 1) {LeafInputs} else { LeafInput}
@if (leafInput.TimeInProgress > TimeSpan.Zero) { @@ -140,14 +144,14 @@ var summaryText = string.Join(Environment.NewLine, summary); else if (leafInput.IsPending) { - @Html.Partial("DisplayTemplates/_TimeRemaining", Tuple.Create(leafInput, Model.CompletedLeafInput)) est. + @Html.Partial("DisplayTemplates/_TimeRemaining", Tuple.Create(leafInput, Model.TimeInProgressEstimater)) est. } @if (leafInput.IsRunning) {
- @Html.Partial("DisplayTemplates/_TimeRemaining", Tuple.Create(leafInput, Model.CompletedLeafInput)) left + @Html.Partial("DisplayTemplates/_TimeRemaining", Tuple.Create(leafInput, Model.TimeInProgressEstimater)) left
}
diff --git a/WebCms/Views/Shared/DisplayTemplates/PreReadMore.cshtml b/WebCms/Views/Shared/DisplayTemplates/PreReadMore.cshtml new file mode 100644 index 0000000..c56ea08 --- /dev/null +++ b/WebCms/Views/Shared/DisplayTemplates/PreReadMore.cshtml @@ -0,0 +1,13 @@ +@{ + Layout = "~/Views/Shared/DisplayTemplates/_FieldLayout.cshtml"; + var lowerPropertyName = ViewData.ModelMetadata.PropertyName.ToFirstLower(); +} +@if (Model == null) +{ + @Html.Encode(ViewData.ModelMetadata.NullDisplayText) +} +else +{ +
@Html.Raw(Model)
+ Show More +} diff --git a/WebCms/Views/Shared/DisplayTemplates/_TimeRemaining.cshtml b/WebCms/Views/Shared/DisplayTemplates/_TimeRemaining.cshtml index 97814de..32a1861 100644 --- a/WebCms/Views/Shared/DisplayTemplates/_TimeRemaining.cshtml +++ b/WebCms/Views/Shared/DisplayTemplates/_TimeRemaining.cshtml @@ -1,10 +1,9 @@ @using LeafWeb.Core.Entities -@model Tuple> +@model Tuple @{ var leafInput = Model.Item1; - var observations = Model.Item2.Take(20); + var estimater = Model.Item2; - var estimater = new TimeInProgressEstimater(observations); var totalTimeEstimate = estimater.EstimateTimeInProgress(leafInput); var remaining = totalTimeEstimate - leafInput.TimeInProgress; if (remaining > TimeSpan.Zero) diff --git a/WebCms/WebCms.csproj b/WebCms/WebCms.csproj index a3a4546..057aec6 100644 --- a/WebCms/WebCms.csproj +++ b/WebCms/WebCms.csproj @@ -893,6 +893,7 @@ + Web.config diff --git a/WebCms/scripts/site.js b/WebCms/scripts/site.js index 231f265..13970b9 100644 --- a/WebCms/scripts/site.js +++ b/WebCms/scripts/site.js @@ -38,8 +38,8 @@ $(container).find('.equal').each(function() { $el = $(this); - $($el).height('auto') - topPostion = $el.position().top; + $($el).height('auto'); + topPostion = $el.position().top; if (currentRowStart != topPostion) { for (currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) { @@ -110,4 +110,15 @@ } }); + $(".read-more") + .click(function () { + var control = $(this).attr('readcontrol'); + $("#" + control).toggleClass("read-less"); + if ($(this).text() === "Show Less") + $(this).text("Show More"); + else + $(this).text("Show Less"); + return false; + }); + })(jQuery); \ No newline at end of file