From 1d8e217c6f63b5101cbe56e63ed2983e36f74ffb Mon Sep 17 00:00:00 2001 From: Jeavon Leopold Date: Mon, 9 Jun 2014 23:23:31 +0100 Subject: [PATCH] Template Query builder prototype working! --- .../common/dialogs/template/querybuilder.html | 10 +- .../umbraco_client/Editors/EditView.js | 25 +++ .../Editors/TemplateQuery/QueryCondition.cs | 44 +++++- .../Editors/TemplateQuery/QueryModel.cs | 2 +- .../Editors/TemplateQuery/QueryResultModel.cs | 9 -- .../Editors/TemplateQuery/SortExpression.cs | 2 +- .../TemplateQuery/TemplateQueryController.cs | 149 +++++++++--------- 7 files changed, 153 insertions(+), 88 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/template/querybuilder.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/template/querybuilder.html index 6c91c9e45e..7e279eaeca 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/template/querybuilder.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/template/querybuilder.html @@ -126,15 +126,17 @@ -
{{result.queryExpression | json}}
+
{{result.queryExpression}}
diff --git a/src/Umbraco.Web.UI/umbraco_client/Editors/EditView.js b/src/Umbraco.Web.UI/umbraco_client/Editors/EditView.js index e32c43941d..557413bef1 100644 --- a/src/Umbraco.Web.UI/umbraco_client/Editors/EditView.js +++ b/src/Umbraco.Web.UI/umbraco_client/Editors/EditView.js @@ -69,6 +69,31 @@ }); }, + + openQueryModal: function () { + /// callback used to display the modal dialog to insert a macro with parameters + + var self = this; + + UmbClientMgr.openAngularModalWindow({ + template: "views/common/dialogs/template/queryBuilder.html", + callback: function (data) { + + var code = "\n@{\n" + "\tvar selection = " + data + ";\n}\n"; + code += "\n\n"; + + UmbEditor.Insert(code, '', self._opts.codeEditorElementId); + } + }); + }, + + doSubmit: function () { /// Submits the data to the server for saving var codeVal = UmbClientMgr.contentFrame().UmbEditor.GetCode(); diff --git a/src/Umbraco.Web/Editors/TemplateQuery/QueryCondition.cs b/src/Umbraco.Web/Editors/TemplateQuery/QueryCondition.cs index 9afd2d8ae8..8fe8c7e83e 100644 --- a/src/Umbraco.Web/Editors/TemplateQuery/QueryCondition.cs +++ b/src/Umbraco.Web/Editors/TemplateQuery/QueryCondition.cs @@ -13,9 +13,49 @@ internal static class QueryConditionExtensions { - public static string MakeBinaryOperation(this QueryCondition condition, string operation) + private static string MakeBinaryOperation(this QueryCondition condition, string operand, int token) { - return string.Format("{0}{1}{2}", condition.Property.Name, operation, condition.ConstraintValue); + return string.Format("{0}{1}@{2}", condition.Property.Name, operand, token); + } + + + public static string BuildCondition(this QueryCondition condition, int token) + { + var operand = string.Empty; + var value = string.Empty; + + switch (condition.Term.Operathor) + { + case Operathor.Equals: + operand = " == "; + break; + case Operathor.NotEquals: + operand = " != "; + break; + case Operathor.GreaterThan: + operand = " > "; + break; + case Operathor.GreaterThanEqualTo: + operand = " >= "; + break; + case Operathor.LessThan: + operand = " < "; + break; + case Operathor.LessThanEqualTo: + operand = " <= "; + break; + case Operathor.Contains: + value = string.Format("{0}.Contains(@{1})", condition.Property.Name, token); + break; + case Operathor.NotContains: + value = string.Format("!{0}.Contains(@{1})", condition.Property.Name, token); + break; + default : + operand = " == "; + break; + } + + return string.IsNullOrEmpty(value) ? condition.MakeBinaryOperation(operand, token) : value; } } diff --git a/src/Umbraco.Web/Editors/TemplateQuery/QueryModel.cs b/src/Umbraco.Web/Editors/TemplateQuery/QueryModel.cs index 0f6bb4df13..999406f1a3 100644 --- a/src/Umbraco.Web/Editors/TemplateQuery/QueryModel.cs +++ b/src/Umbraco.Web/Editors/TemplateQuery/QueryModel.cs @@ -9,7 +9,7 @@ namespace Umbraco.Web.Editors public ContentTypeModel ContentType { get; set; } public SourceModel Source { get; set; } public IEnumerable Filters { get; set; } - public SortExpression SortExpression { get; set; } + public SortExpression Sort { get; set; } public int Take { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Editors/TemplateQuery/QueryResultModel.cs b/src/Umbraco.Web/Editors/TemplateQuery/QueryResultModel.cs index 50ae2e920a..d4922f6f62 100644 --- a/src/Umbraco.Web/Editors/TemplateQuery/QueryResultModel.cs +++ b/src/Umbraco.Web/Editors/TemplateQuery/QueryResultModel.cs @@ -5,16 +5,7 @@ namespace Umbraco.Web.Editors public class QueryResultModel { - public QueryResultModel() - { - Initialize(); - } - private void Initialize() - { - QueryExpression = "CurrentPage.Site()"; - } - public string QueryExpression { get; set; } public IEnumerable SampleResults { get; set; } public int ResultCount { get; set; } diff --git a/src/Umbraco.Web/Editors/TemplateQuery/SortExpression.cs b/src/Umbraco.Web/Editors/TemplateQuery/SortExpression.cs index 88d95c1299..d891ece0d8 100644 --- a/src/Umbraco.Web/Editors/TemplateQuery/SortExpression.cs +++ b/src/Umbraco.Web/Editors/TemplateQuery/SortExpression.cs @@ -6,6 +6,6 @@ { public PropertyModel Property { get; set; } - public string SortDirection { get; set; } + public string Direction { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Editors/TemplateQuery/TemplateQueryController.cs b/src/Umbraco.Web/Editors/TemplateQuery/TemplateQueryController.cs index 9107f06f46..9e48770993 100644 --- a/src/Umbraco.Web/Editors/TemplateQuery/TemplateQueryController.cs +++ b/src/Umbraco.Web/Editors/TemplateQuery/TemplateQueryController.cs @@ -10,10 +10,16 @@ namespace Umbraco.Web.Editors { using System; using System.Diagnostics; + using System.Diagnostics.Eventing.Reader; + using System.Drawing; using global::umbraco; + using global::umbraco.cms.presentation; + using Umbraco.Core.Persistence.DatabaseModelDefinitions; + using Umbraco.Web.Dynamics; using Umbraco.Web.Editors.TemplateQuery; + using System.Linq.Expressions; /// /// The API controller used for building content queries within the template @@ -57,10 +63,8 @@ namespace Umbraco.Web.Editors new PropertyModel() { Name = "Creation Date", Alias = "createDate", Type = "datetime" }, new PropertyModel() { Name = "Publishing Date", Alias = "publishDate", Type = "datetime" } - }; + }; - - public QueryResultModel PostTemplateQuery(QueryModel model) { var umbraco = new UmbracoHelper(UmbracoContext); @@ -68,8 +72,9 @@ namespace Umbraco.Web.Editors var queryResult = new QueryResultModel(); var sb = new StringBuilder(); - sb.Append(queryResult.QueryExpression); - + + sb.Append("CurrentPage.Site()"); + var timer = new Stopwatch(); timer.Start(); @@ -92,13 +97,23 @@ namespace Umbraco.Web.Editors { timer.Start(); - pointerNode = pointerNode.Children.OfTypes(contentTypeAlias).First(); + pointerNode = pointerNode.FirstChild(x => x.DocumentTypeAlias == contentTypeAlias); + + if (pointerNode == null) break; timer.Stop(); - + sb.AppendFormat(".FirstChild(\"{0}\")", contentTypeAlias); } + if (pointerNode == null || pointerNode.Id != model.Source.Id) + { + // we did not find the path + sb.Clear(); + sb.AppendFormat("Umbraco.Content({0})", model.Source.Id); + pointerNode = targetNode; + } + } // TYPE to return if filtered by type @@ -124,79 +139,46 @@ namespace Umbraco.Web.Editors var clause = string.Empty; // WHERE + var token = 0; foreach (var condition in model.Filters) { if(string.IsNullOrEmpty( condition.ConstraintValue)) continue; - var operation = string.Empty; - switch (condition.Term.Operathor) - { - case Operathor.Equals: - operation = condition.MakeBinaryOperation(" == "); - break; + var operation = condition.BuildCondition(token); - case Operathor.NotEquals: - operation = condition.MakeBinaryOperation(" != "); - break; - - case Operathor.GreaterThan: - operation = condition.MakeBinaryOperation(" > "); - break; - - case Operathor.GreaterThanEqualTo: - operation = condition.MakeBinaryOperation(" >= "); - break; - - case Operathor.LessThan: - operation = condition.MakeBinaryOperation(" < "); - break; - - case Operathor.LessThanEqualTo: - operation = condition.MakeBinaryOperation(" <= "); - break; - - case Operathor.Contains: - - operation = string.Format("{0}.ToLowerInvariant().Contains(\"{1}\")", condition.Property.Name, condition.ConstraintValue.ToLowerInvariant()); - - break; - - case Operathor.NotContains: - operation = string.Format("!{0}.ToLowerInvariant().Contains(\"{1}\")", condition.Property.Name, condition.ConstraintValue.ToLowerInvariant()); - break; - } - - clause = string.IsNullOrEmpty(clause) ? operation : string.Concat(new[] { clause, " && ", operation }); + clause = string.IsNullOrEmpty(clause) ? operation : string.Concat(new[] { clause, " && ", operation }); + token++; } if(string.IsNullOrEmpty(clause) == false) - { + { + timer.Start(); - - contents = contents.Where(clause); + + contents = contents.AsQueryable().Where(clause, model.Filters.Select(GetConstraintValue).ToArray()); + // contents = contents.Where(clause, values.ToArray()); timer.Stop(); + + clause = string.Format("\"{0}\",{1}", clause, string.Join(",", model.Filters.Select(x => x.Property.Type == "string" ? string.Format("\"{0}\"", x.ConstraintValue) : x.ConstraintValue).ToArray())); - sb.AppendFormat(".Where(\"{0}\")", clause); + sb.AppendFormat(".Where({0})", clause); } - if (model.SortExpression != null && string.IsNullOrEmpty(model.SortExpression.Property.Alias) == false) + if (model.Sort != null && string.IsNullOrEmpty(model.Sort.Property.Alias) == false) { timer.Start(); - // TODO write extension to determine if built in property or not - contents = model.SortExpression.SortDirection == "ascending" - ? contents.OrderBy(x => GetDefaultPropertyValue(x, model.SortExpression.Property)).ToList() - : contents.OrderByDescending(x => GetDefaultPropertyValue(x, model.SortExpression.Property)).ToList(); + contents = SortByDefaultPropertyValue(contents, model.Sort); timer.Stop(); - var direction = model.SortExpression.SortDirection == "ascending" ? string.Empty : " desc"; + var direction = model.Sort.Direction == "ascending" ? string.Empty : " desc"; - sb.AppendFormat(".OrderBy(\"{0}{1}\")", model.SortExpression.Property.Alias, direction); + sb.AppendFormat(".OrderBy(\"{0}{1}\")", model.Sort.Property.Name, direction); } if (model.Take > 0) @@ -223,20 +205,47 @@ namespace Umbraco.Web.Editors return queryResult; } - private object GetDefaultPropertyValue(IPublishedContent content, PropertyModel prop) + private object GetConstraintValue(QueryCondition condition) { - switch (prop.Alias) + switch (condition.Property.Type) + { + case "int" : + return int.Parse(condition.ConstraintValue); + case "datetime": + DateTime dt; + return DateTime.TryParse(condition.ConstraintValue, out dt) ? dt : DateTime.Today; + default: + return condition.ConstraintValue; + } + } + + private IEnumerable SortByDefaultPropertyValue(IEnumerable contents, SortExpression sortExpression) + { + switch (sortExpression.Property.Alias) { case "id" : - return content.Id; + return sortExpression.Direction == "ascending" + ? contents.OrderBy(x => x.Id) + : contents.OrderByDescending(x => x.Id); case "createDate" : - return content.CreateDate; + + return sortExpression.Direction == "ascending" + ? contents.OrderBy(x => x.CreateDate) + : contents.OrderByDescending(x => x.CreateDate); case "publishDate": - return content.UpdateDate; + + return sortExpression.Direction == "ascending" + ? contents.OrderBy(x => x.UpdateDate) + : contents.OrderByDescending(x => x.UpdateDate); case "name": - return content.Name; + return sortExpression.Direction == "ascending" + ? contents.OrderBy(x => x.Name) + : contents.OrderByDescending(x => x.Name); default : - return content.Name; + + return sortExpression.Direction == "ascending" + ? contents.OrderBy(x => x.Name) + : contents.OrderByDescending(x => x.Name); } } @@ -263,9 +272,13 @@ namespace Umbraco.Web.Editors /// public IEnumerable GetContentTypes() { - return + var contentTypes = ApplicationContext.Services.ContentTypeService.GetAllContentTypes() - .Select(x => new ContentTypeModel() { Alias = x.Alias, Name = x.Name }).OrderBy(x => x.Name); + .Select(x => new ContentTypeModel() { Alias = x.Alias, Name = x.Name }) + .OrderBy(x => x.Name).ToList(); + contentTypes.Insert(0, new ContentTypeModel() { Alias = string.Empty, Name = "Everything" }); + + return contentTypes; } /// @@ -281,12 +294,6 @@ namespace Umbraco.Web.Editors /// public IEnumerable GetFilterConditions() { - //return _terms.Select(x => new - // { - // x.Name, - // Operathor = x.Operathor.ToString(), - // x.AppliesTo - // }); return _terms; }