Skip to content

Commit b170053

Browse files
committed
Support for multiple "and" conditions in the query builder
1 parent 2ffd041 commit b170053

File tree

3 files changed

+107
-90
lines changed

3 files changed

+107
-90
lines changed

src/Umbraco.Web.UI.Client/src/views/common/dialogs/template/querybuilder.controller.js

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,16 @@ angular.module("umbraco").controller('Umbraco.Dialogs.Template.QueryBuilderContr
5353
});
5454
};
5555

56-
$scope.$watch("query", function(value) {
57-
56+
var throttledFunc = _.throttle(function() {
57+
5858
$http.post("backoffice/UmbracoApi/TemplateQuery/PostTemplateQuery", $scope.query).then(function (response) {
5959
$scope.result = response.data;
6060
});
6161

62+
}, 200);
63+
64+
$scope.$watch("query", function(value) {
65+
throttledFunc();
6266
}, true);
6367

6468
$scope.getPropertyOperators = function (property) {
@@ -71,18 +75,12 @@ angular.module("umbraco").controller('Umbraco.Dialogs.Template.QueryBuilderContr
7175
};
7276

7377

74-
$scope.addFilter = function(query){
75-
76-
var f = {
77-
property:{
78-
alias: "meh",
79-
name: "Meh"
80-
},
81-
operator: "IS",
82-
value: "nothing"
83-
};
84-
85-
query.filters.push(f);
78+
$scope.addFilter = function(query){
79+
query.filters.push({});
80+
};
81+
82+
$scope.trashFilter = function (query) {
83+
query.filters.splice(query,1);
8684
};
8785

8886
$scope.changeSortOrder = function(query){

src/Umbraco.Web.UI.Client/src/views/common/dialogs/template/querybuilder.html

Lines changed: 49 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -50,46 +50,59 @@ <h1 class="headline" style="margin: 10px 0 0 0">Build a query</h1>
5050
</a>
5151
</div>
5252

53-
<div ng-repeat="filter in query.filters">
54-
<span>Where</span>
53+
<div ng-repeat="filter in query.filters">
54+
55+
<span ng-if="$first">Where</span>
56+
<span ng-if="!$first">And</span>
57+
58+
<div class="btn-group">
59+
60+
<a class="btn btn-link dropdown-toggle"
61+
data-toggle="dropdown" href="#">
62+
{{filter.property.name}}
63+
<span class="caret"></span>
64+
</a>
65+
66+
<ul class="dropdown-menu">
67+
<li ng-repeat="property in properties">
68+
<a href ng-click="filter.property = property">
69+
{{property.name}}
70+
</a>
71+
</li>
72+
</ul>
73+
74+
</div>
5575

56-
<div class="btn-group">
57-
58-
<a class="btn btn-link dropdown-toggle"
59-
data-toggle="dropdown" href="#">
60-
{{filter.property.name}}
61-
<span class="caret"></span>
62-
</a>
76+
<div class="btn-group" ng-if="filter.property">
77+
<a class="btn btn-link dropdown-toggle"
78+
data-toggle="dropdown" href="#">
79+
{{filter.term.name}}
80+
<span class="caret"></span>
81+
</a>
82+
<ul class="dropdown-menu">
83+
<li ng-repeat="term in getPropertyOperators(filter.property)">
84+
<a href ng-click="filter.term = term">
85+
{{term.name}}
86+
</a>
87+
</li>
88+
</ul>
89+
</div>
90+
91+
<input type="text" ng-if="filter.term" style="width:90px;" ng-model="filter.constraintValue" />
92+
93+
<a href ng-click="addFilter(query)">
94+
<i class="icon-add"></i>
95+
</a>
96+
97+
<a href ng-if="query.filters.length > 1" ng-click="trashFilter(query)">
98+
<i class="icon-trash"></i>
99+
</a>
100+
101+
</div>
63102

64-
<ul class="dropdown-menu">
65-
<li ng-repeat="property in properties">
66-
<a href ng-click="filter.property = property">
67-
{{property.name}}
68-
</a>
69-
</li>
70-
</ul>
71103

72-
</div>
73-
74-
<div class="btn-group" ng-if="filter.property">
75-
<a class="btn btn-link dropdown-toggle"
76-
data-toggle="dropdown" href="#">
77-
{{filter.term.name}}
78-
<span class="caret"></span>
79-
</a>
80-
<ul class="dropdown-menu">
81-
<li ng-repeat="term in getPropertyOperators(filter.property)">
82-
<a href ng-click="filter.term = term">
83-
{{term.name}}
84-
</a>
85-
</li>
86-
</ul>
87-
</div>
88-
89-
<input type="text" ng-if="filter.term" style="width:100px;" ng-model="filter.constraintValue" />
90-
</div>
91104

92-
<div>
105+
<div>
93106

94107
Order by
95108

src/Umbraco.Web/Editors/TemplateQuery/TemplateQueryController.cs

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -142,72 +142,78 @@ public QueryResultModel PostTemplateQuery(QueryModel model)
142142

143143
// WHERE
144144
var token = 0;
145-
foreach (var condition in model.Filters)
145+
146+
if (model != null)
146147
{
147-
if(string.IsNullOrEmpty( condition.ConstraintValue)) continue;
148+
model.Filters = model.Filters.Where(x => x.ConstraintValue != null);
149+
150+
foreach (var condition in model.Filters)
151+
{
152+
if(string.IsNullOrEmpty( condition.ConstraintValue)) continue;
148153

149154

150155

151-
var operation = condition.BuildCondition(token);
156+
var operation = condition.BuildCondition(token);
152157

153-
clause = string.IsNullOrEmpty(clause) ? operation : string.Concat(new[] { clause, " && ", operation });
158+
clause = string.IsNullOrEmpty(clause) ? operation : string.Concat(new[] { clause, " && ", operation });
154159

155-
token++;
156-
}
160+
token++;
161+
}
157162

158-
if (string.IsNullOrEmpty(clause) == false)
159-
{
163+
if (string.IsNullOrEmpty(clause) == false)
164+
{
160165

161-
timer.Start();
166+
timer.Start();
162167

163-
//clause = "Visible && " + clause;
168+
//clause = "Visible && " + clause;
164169

165-
contents = contents.AsQueryable().Where(clause, model.Filters.Select(GetConstraintValue).ToArray());
166-
// contents = contents.Where(clause, values.ToArray());
167-
contents = contents.Where(x => x.IsVisible());
170+
contents = contents.AsQueryable().Where(clause, model.Filters.Select(this.GetConstraintValue).ToArray());
171+
// contents = contents.Where(clause, values.ToArray());
172+
contents = contents.Where(x => x.IsVisible());
168173

169-
timer.Stop();
174+
timer.Stop();
170175

171-
clause = string.Format("\"Visible && {0}\",{1}", clause,
172-
string.Join(",", model.Filters.Select(x => x.Property.Type == "string" ?
173-
string.Format("\"{0}\"", x.ConstraintValue) : x.ConstraintValue).ToArray()));
176+
clause = string.Format("\"Visible && {0}\",{1}", clause,
177+
string.Join(",", model.Filters.Select(x => x.Property.Type == "string" ?
178+
string.Format("\"{0}\"", x.ConstraintValue) : x.ConstraintValue).ToArray()));
174179

175-
sb.AppendFormat(".Where({0})", clause);
176-
}
177-
else
178-
{
179-
timer.Start();
180+
sb.AppendFormat(".Where({0})", clause);
181+
}
182+
else
183+
{
184+
timer.Start();
180185

181-
contents = contents.Where(x => x.IsVisible());
186+
contents = contents.Where(x => x.IsVisible());
182187

183-
timer.Stop();
188+
timer.Stop();
184189

185-
sb.Append(".Where(\"Visible\")");
190+
sb.Append(".Where(\"Visible\")");
186191

187-
}
192+
}
188193

189-
if (model.Sort != null && string.IsNullOrEmpty(model.Sort.Property.Alias) == false)
190-
{
191-
timer.Start();
194+
if (model.Sort != null && string.IsNullOrEmpty(model.Sort.Property.Alias) == false)
195+
{
196+
timer.Start();
192197

193-
contents = SortByDefaultPropertyValue(contents, model.Sort);
198+
contents = this.SortByDefaultPropertyValue(contents, model.Sort);
194199

195-
timer.Stop();
200+
timer.Stop();
196201

197-
var direction = model.Sort.Direction == "ascending" ? string.Empty : " desc";
202+
var direction = model.Sort.Direction == "ascending" ? string.Empty : " desc";
198203

199-
sb.AppendFormat(".OrderBy(\"{0}{1}\")", model.Sort.Property.Name, direction);
200-
}
204+
sb.AppendFormat(".OrderBy(\"{0}{1}\")", model.Sort.Property.Name, direction);
205+
}
201206

202-
if (model.Take > 0)
203-
{
204-
timer.Start();
207+
if (model.Take > 0)
208+
{
209+
timer.Start();
205210

206-
contents = contents.Take(model.Take);
211+
contents = contents.Take(model.Take);
207212

208-
timer.Stop();
213+
timer.Stop();
209214

210-
sb.AppendFormat(".Take({0})", model.Take);
215+
sb.AppendFormat(".Take({0})", model.Take);
216+
}
211217
}
212218

213219
queryResult.QueryExpression = sb.ToString();

0 commit comments

Comments
 (0)