From e7eaf6959f5e4d9f9cd5e6e176e66bf6493b3d5f Mon Sep 17 00:00:00 2001 From: Claus Date: Thu, 4 May 2017 15:08:37 +0200 Subject: [PATCH] U4-9849 Query Builder not working in template editor. Always returns Model.Content.Site().Children() adding missing nullchecks in the endpoint action. ensuring promise returns before setting init data - the unresolved promise was being used on the query model instead of the actual text string the promise returns - causing the endpoint to fail to bind the model. --- .../querybuilder/querybuilder.controller.js | 119 +++++++++--------- .../Editors/TemplateQueryController.cs | 86 ++++++------- 2 files changed, 100 insertions(+), 105 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/querybuilder/querybuilder.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/querybuilder/querybuilder.controller.js index 979428de0c..ea9ad6ca97 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/querybuilder/querybuilder.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/querybuilder/querybuilder.controller.js @@ -1,14 +1,13 @@ -(function () { +(function() { "use strict"; function QueryBuilderOverlayController($scope, templateQueryResource, localizationService) { - var everything = localizationService.localize("template_allContent"); - var myWebsite = localizationService.localize("template_websiteRoot"); + var everything = ""; + var myWebsite = ""; + var ascendingTranslation = ""; + var descendingTranslation = ""; - var ascendingTranslation = localizationService.localize("template_ascending"); - var descendingTranslation = localizationService.localize("template_descending"); - var vm = this; vm.properties = []; @@ -21,34 +20,6 @@ format: "YYYY-MM-DD" }; - vm.query = { - contentType: { - name: everything - }, - source: { - name: myWebsite - }, - filters: [ - { - property: undefined, - operator: undefined - } - ], - sort: { - property: { - alias: "", - name: "", - }, - direction: "ascending", //This is the value for sorting sent to server - translation: { - currentLabel: ascendingTranslation, //This is the localized UI value in the the dialog - ascending: ascendingTranslation, - descending: descendingTranslation - } - - } - }; - vm.chooseSource = chooseSource; vm.getPropertyOperators = getPropertyOperators; vm.addFilter = addFilter; @@ -63,21 +34,48 @@ function onInit() { + vm.query = { + contentType: { + name: everything + }, + source: { + name: myWebsite + }, + filters: [ + { + property: undefined, + operator: undefined + } + ], + sort: { + property: { + alias: "", + name: "", + }, + direction: "ascending", //This is the value for sorting sent to server + translation: { + currentLabel: ascendingTranslation, //This is the localized UI value in the the dialog + ascending: ascendingTranslation, + descending: descendingTranslation + } + } + }; + templateQueryResource.getAllowedProperties() - .then(function (properties) { + .then(function(properties) { vm.properties = properties; }); templateQueryResource.getContentTypes() - .then(function (contentTypes) { + .then(function(contentTypes) { vm.contentTypes = contentTypes; }); templateQueryResource.getFilterConditions() - .then(function (conditions) { + .then(function(conditions) { vm.conditions = conditions; }); - + throttledFunc(); } @@ -111,10 +109,11 @@ } function getPropertyOperators(property) { - var conditions = _.filter(vm.conditions, function (condition) { - var index = condition.appliesTo.indexOf(property.type); - return index >= 0; - }); + var conditions = _.filter(vm.conditions, + function(condition) { + var index = condition.appliesTo.indexOf(property.type); + return index >= 0; + }); return conditions; } @@ -123,10 +122,8 @@ } function trashFilter(query, filter) { - for (var i = 0; i < query.filters.length; i++) - { - if (query.filters[i] == filter) - { + for (var i = 0; i < query.filters.length; i++) { + if (query.filters[i] == filter) { query.filters.splice(i, 1); } } @@ -173,7 +170,7 @@ function setFilterTerm(filter, term) { filter.term = term; - if(filter.constraintValue) { + if (filter.constraintValue) { throttledFunc(); } } @@ -183,22 +180,32 @@ } function datePickerChange(event, filter) { - if(event.date && event.date.isValid()) { + if (event.date && event.date.isValid()) { filter.constraintValue = event.date.format(vm.datePickerConfig.format); throttledFunc(); } } - var throttledFunc = _.throttle(function () { - - templateQueryResource.postTemplateQuery(vm.query) - .then(function (response) { - $scope.model.result = response; - }); + var throttledFunc = _.throttle(function() { - }, 200); + templateQueryResource.postTemplateQuery(vm.query) + .then(function(response) { + $scope.model.result = response; + }); - onInit(); + }, + 200); + + localizationService.localizeMany([ + "template_allContent", "template_websiteRoot", "template_ascending", "template_descending" + ]) + .then(function(res) { + everything = res[0]; + myWebsite = res[1]; + ascendingTranslation = res[2]; + descendingTranslation = res[3]; + onInit(); + }); } angular.module("umbraco").controller("Umbraco.Overlays.QueryBuilderController", QueryBuilderOverlayController); diff --git a/src/Umbraco.Web/Editors/TemplateQueryController.cs b/src/Umbraco.Web/Editors/TemplateQueryController.cs index cd004fe926..d7351b0e97 100644 --- a/src/Umbraco.Web/Editors/TemplateQueryController.cs +++ b/src/Umbraco.Web/Editors/TemplateQueryController.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Text; using Umbraco.Core.Models; using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi.Filters; using Umbraco.Web.WebApi; using System; using System.Diagnostics; @@ -13,8 +12,6 @@ using Umbraco.Core.Services; namespace Umbraco.Web.Editors { - - /// /// The API controller used for building content queries within the template /// @@ -26,10 +23,9 @@ namespace Umbraco.Web.Editors { } public TemplateQueryController(UmbracoContext umbracoContext) - :base(umbracoContext) + : base(umbracoContext) { } - private IEnumerable Terms { get @@ -77,20 +73,19 @@ namespace Umbraco.Web.Editors var sb = new StringBuilder(); var indention = Environment.NewLine + "\t\t\t\t\t\t"; - + sb.Append("Model.Content.Site()"); var timer = new Stopwatch(); - + timer.Start(); var currentPage = umbraco.TypedContentAtRoot().FirstOrDefault(); timer.Stop(); - var pointerNode = currentPage; // adjust the "FROM" - if (model != null && model.Source.Id > 0) + if (model != null && model.Source != null && model.Source.Id > 0) { var targetNode = umbraco.TypedContent(model.Source.Id); @@ -120,10 +115,10 @@ namespace Umbraco.Web.Editors } } } - - // TYPE to return if filtered by type + + // TYPE to return if filtered by type IEnumerable contents; - if (model != null && string.IsNullOrEmpty(model.ContentType.Alias) == false) + if (model != null && model.ContentType != null && string.IsNullOrEmpty(model.ContentType.Alias) == false) { timer.Start(); @@ -154,13 +149,13 @@ namespace Umbraco.Web.Editors foreach (var condition in model.Filters) { - if(string.IsNullOrEmpty( condition.ConstraintValue)) continue; - + if (string.IsNullOrEmpty(condition.ConstraintValue)) continue; + //x is passed in as the parameter alias for the linq where statement clause var operation = condition.BuildCondition("x"); var tokenizedOperation = condition.BuildTokenizedCondition(token); - clause = string.IsNullOrEmpty(clause) ? operation : string.Concat(new[] { clause, " && ", operation }); + clause = string.IsNullOrEmpty(clause) ? operation : string.Concat(new[] { clause, " && ", operation }); tokenizedClause = string.IsNullOrEmpty(tokenizedClause) ? tokenizedOperation : string.Concat(new[] { tokenizedClause, " && ", tokenizedOperation }); token++; @@ -168,7 +163,6 @@ namespace Umbraco.Web.Editors if (string.IsNullOrEmpty(clause) == false) { - timer.Start(); //trial-run the tokenized clause to time the execution @@ -178,14 +172,13 @@ namespace Umbraco.Web.Editors timer.Stop(); - + //the query to output to the editor sb.Append(indention); sb.Append(".Where(x => x.IsVisible())"); sb.Append(indention); sb.AppendFormat(".Where(x => {0})", clause); - } else { @@ -197,7 +190,6 @@ namespace Umbraco.Web.Editors sb.Append(indention); sb.Append(".Where(x => x.IsVisible())"); - } if (model.Sort != null && string.IsNullOrEmpty(model.Sort.Property.Alias) == false) @@ -231,20 +223,19 @@ namespace Umbraco.Web.Editors queryResult.ExecutionTime = timer.ElapsedMilliseconds; queryResult.ResultCount = contents.Count(); queryResult.SampleResults = contents.Take(20).Select(x => new TemplateQueryResult() - { - Icon = "icon-file", - Name = x.Name - }); + { + Icon = "icon-file", + Name = x.Name + }); - - return queryResult; + return queryResult; } private object GetConstraintValue(QueryCondition condition) { switch (condition.Property.Type) { - case "int" : + case "int": return int.Parse(condition.ConstraintValue); case "datetime": DateTime dt; @@ -254,42 +245,41 @@ namespace Umbraco.Web.Editors } } - private IEnumerable SortByDefaultPropertyValue(IEnumerable contents, SortExpression sortExpression) + private IEnumerable SortByDefaultPropertyValue(IEnumerable contents, SortExpression sortExpression) { switch (sortExpression.Property.Alias) { - case "id" : + case "id": return sortExpression.Direction == "ascending" - ? contents.OrderBy(x => x.Id) - : contents.OrderByDescending(x => x.Id); - case "createDate" : - + ? contents.OrderBy(x => x.Id) + : contents.OrderByDescending(x => x.Id); + case "createDate": + return sortExpression.Direction == "ascending" - ? contents.OrderBy(x => x.CreateDate) - : contents.OrderByDescending(x => x.CreateDate); + ? contents.OrderBy(x => x.CreateDate) + : contents.OrderByDescending(x => x.CreateDate); case "publishDate": - + return sortExpression.Direction == "ascending" - ? contents.OrderBy(x => x.UpdateDate) - : contents.OrderByDescending(x => x.UpdateDate); + ? contents.OrderBy(x => x.UpdateDate) + : contents.OrderByDescending(x => x.UpdateDate); case "name": return sortExpression.Direction == "ascending" - ? contents.OrderBy(x => x.Name) - : contents.OrderByDescending(x => x.Name); - default : + ? contents.OrderBy(x => x.Name) + : contents.OrderByDescending(x => x.Name); + default: return sortExpression.Direction == "ascending" - ? contents.OrderBy(x => x.Name) - : contents.OrderByDescending(x => x.Name); - + ? contents.OrderBy(x => x.Name) + : contents.OrderByDescending(x => x.Name); } } - + private IEnumerable GetChildContentTypeAliases(IPublishedContent targetNode, IPublishedContent current) { var aliases = new List(); - - if (targetNode.Id == current.Id) return aliases; + + if (targetNode == null || targetNode.Id == current.Id) return aliases; if (targetNode.Id != current.Id) { aliases.Add(targetNode.DocumentTypeAlias); @@ -309,7 +299,7 @@ namespace Umbraco.Web.Editors { var contentTypes = ApplicationContext.Services.ContentTypeService.GetAllContentTypes() - .Select(x => new ContentTypeModel() { Alias = x.Alias, Name = Services.TextService.Localize("template/contentOfType", tokens: new string[] { x.Name } ) }) + .Select(x => new ContentTypeModel() { Alias = x.Alias, Name = Services.TextService.Localize("template/contentOfType", tokens: new string[] { x.Name }) }) .OrderBy(x => x.Name).ToList(); contentTypes.Insert(0, new ContentTypeModel() { Alias = string.Empty, Name = Services.TextService.Localize("template/allContent") }); @@ -332,7 +322,5 @@ namespace Umbraco.Web.Editors { return Terms; } - - } } \ No newline at end of file