Skip to content

Commit c958f12

Browse files
Merge pull request umbraco#413 from rustyswayne/7.1.5-templatequery
Template Query Editor Prototype
2 parents 9a973d0 + b170053 commit c958f12

File tree

18 files changed

+848
-1
lines changed

18 files changed

+848
-1
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
angular.module("umbraco").controller('Umbraco.Dialogs.Template.QueryBuilderController',
2+
function($scope, $http, dialogService){
3+
4+
5+
$http.get("backoffice/UmbracoApi/TemplateQuery/GetAllowedProperties").then(function(response) {
6+
$scope.properties = response.data;
7+
});
8+
9+
$http.get("backoffice/UmbracoApi/TemplateQuery/GetContentTypes").then(function (response) {
10+
$scope.contentTypes = response.data;
11+
});
12+
13+
$http.get("backoffice/UmbracoApi/TemplateQuery/GetFilterConditions").then(function (response) {
14+
$scope.conditions = response.data;
15+
});
16+
17+
18+
$scope.query = {
19+
contentType: {
20+
name: "Everything"
21+
},
22+
source:{
23+
name: "My website"
24+
},
25+
filters:[
26+
{
27+
property:undefined,
28+
operator: undefined
29+
}
30+
],
31+
sort:{
32+
property:{
33+
alias: "",
34+
name: "",
35+
},
36+
direction: "Ascending"
37+
}
38+
};
39+
40+
41+
42+
$scope.chooseSource = function(query){
43+
dialogService.contentPicker({
44+
callback: function (data) {
45+
46+
if (data.id > 0) {
47+
query.source = { id: data.id, name: data.name };
48+
} else {
49+
query.source.name = "My website";
50+
delete query.source.id;
51+
}
52+
}
53+
});
54+
};
55+
56+
var throttledFunc = _.throttle(function() {
57+
58+
$http.post("backoffice/UmbracoApi/TemplateQuery/PostTemplateQuery", $scope.query).then(function (response) {
59+
$scope.result = response.data;
60+
});
61+
62+
}, 200);
63+
64+
$scope.$watch("query", function(value) {
65+
throttledFunc();
66+
}, true);
67+
68+
$scope.getPropertyOperators = function (property) {
69+
70+
var conditions = _.filter($scope.conditions, function(condition) {
71+
var index = condition.appliesTo.indexOf(property.type);
72+
return index >= 0;
73+
});
74+
return conditions;
75+
};
76+
77+
78+
$scope.addFilter = function(query){
79+
query.filters.push({});
80+
};
81+
82+
$scope.trashFilter = function (query) {
83+
query.filters.splice(query,1);
84+
};
85+
86+
$scope.changeSortOrder = function(query){
87+
if(query.sort.direction === "ascending"){
88+
query.sort.direction = "descending";
89+
}else{
90+
query.sort.direction = "ascending";
91+
}
92+
};
93+
94+
$scope.setSortProperty = function(query, property){
95+
query.sort.property = property;
96+
if(property.type === "datetime"){
97+
query.sort.direction = "descending";
98+
}else{
99+
query.sort.direction = "ascending";
100+
}
101+
};
102+
});
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<form novalidate name="contentForm"
2+
ng-controller="Umbraco.Dialogs.Template.QueryBuilderController"
3+
ng-submit="close()"
4+
val-form-manager>
5+
6+
<style>
7+
.umb-querybuilder .row {font-size: 12px; line-height: 12px}
8+
9+
.umb-querybuilder .row a.btn{font-size: 12px; background: lightyellow}
10+
11+
.umb-querybuilder .row > div{
12+
padding: 20px;
13+
border-bottom: 1px solid #efefef;
14+
}
15+
</style>
16+
17+
<div class="umb-panel">
18+
19+
<div class="umb-panel-header">
20+
<h1 class="headline" style="margin: 10px 0 0 0">Build a query</h1>
21+
</div>
22+
23+
<div class="umb-panel-body with-footer umb-querybuilder">
24+
25+
<div class="row">
26+
<div>
27+
I want
28+
29+
<div class="btn-group">
30+
<a class="btn btn-link dropdown-toggle"
31+
data-toggle="dropdown" href="#">
32+
{{query.contentType.name}}
33+
<span class="caret"></span>
34+
</a>
35+
<ul class="dropdown-menu">
36+
<li ng-repeat="contentType in contentTypes">
37+
<a href ng-click="query.contentType = contentType">
38+
{{contentType.name}}
39+
</a>
40+
</li>
41+
42+
</ul>
43+
</div>
44+
45+
<span>from</span>
46+
47+
<a href class="btn btn-link" ng-click="chooseSource(query)">
48+
{{query.source.name}}
49+
<span class="caret"></span>
50+
</a>
51+
</div>
52+
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>
75+
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>
102+
103+
104+
105+
<div>
106+
107+
Order by
108+
109+
<div class="btn-group">
110+
<a class="btn btn-link dropdown-toggle"
111+
data-toggle="dropdown" href="#">
112+
{{query.sort.property.name}}
113+
<span class="caret"></span>
114+
</a>
115+
116+
<ul class="dropdown-menu">
117+
<li ng-repeat="property in properties">
118+
<a href ng-click="setSortProperty(query, property)">
119+
{{property.name}}
120+
</a>
121+
</li>
122+
</ul>
123+
124+
</div>
125+
126+
127+
<a href class="btn" ng-click="changeSortOrder(query)">
128+
{{query.sort.direction}}
129+
</a>
130+
</div>
131+
</div>
132+
133+
134+
<h4>Returns {{result.resultCount}} items in {{result.executionTime}} miliseconds</h4>
135+
136+
<ul class="nav unstyled">
137+
<li ng-repeat="item in result.sampleResults">
138+
<i class="icon icon-document blue"></i> {{item.name}}
139+
</li>
140+
</ul>
141+
142+
<pre>{{result.queryExpression}}</pre>
143+
</div>
144+
145+
<div class="umb-panel-footer" >
146+
<div class="umb-el-wrap umb-panel-buttons">
147+
<div class="btn-toolbar umb-btn-toolbar pull-right">
148+
<a href ng-click="close()" class="btn btn-link">
149+
<localize key="general_close">Close</localize>
150+
</a>
151+
152+
<a href ng-click="submit(result.queryExpression)" class="btn btn-primary">Insert</a>
153+
</div>
154+
</div>
155+
</div>
156+
</div>
157+
</div>
158+
</form>

src/Umbraco.Web.UI/umbraco/settings/views/EditView.aspx.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,12 @@ protected override void OnInit(EventArgs e)
202202
ClientCallbackOpenMacroModel = "function(alias) {editViewEditor.openMacroModal(alias);}"
203203
};
204204
editorSource.Menu.InsertNewControl(macroSplitButton, 40);
205-
205+
206+
MenuIconI umbTemplateQueryBuilder = editorSource.Menu.NewIcon();
207+
umbTemplateQueryBuilder.ImageURL = UmbracoPath + "/images/editor/inshtml.gif";
208+
umbTemplateQueryBuilder.OnClickCommand = "editViewEditor.openQueryModal()";
209+
umbTemplateQueryBuilder.AltText = "Open query builder";
210+
206211
if (_template == null)
207212
{
208213
InitializeEditorForPartialView();

src/Umbraco.Web.UI/umbraco_client/Editors/EditView.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,31 @@
6969
});
7070
},
7171

72+
73+
openQueryModal: function () {
74+
/// <summary>callback used to display the modal dialog to insert a macro with parameters</summary>
75+
76+
var self = this;
77+
78+
UmbClientMgr.openAngularModalWindow({
79+
template: "views/common/dialogs/template/queryBuilder.html",
80+
callback: function (data) {
81+
82+
var code = "\n@{\n" + "\tvar selection = " + data + ";\n}\n";
83+
code += "<ul>\n" +
84+
"\t@foreach(var item in selection){\n" +
85+
"\t\t<li>\n" +
86+
"\t\t\t<a href=\"@item.Url\">@item.Name</a>\n" +
87+
"\t\t</li>\n" +
88+
"\t}\n" +
89+
"</ul>\n\n";
90+
91+
UmbEditor.Insert(code, '', self._opts.codeEditorElementId);
92+
}
93+
});
94+
},
95+
96+
7297
doSubmit: function () {
7398
/// <summary>Submits the data to the server for saving</summary>
7499
var codeVal = UmbClientMgr.contentFrame().UmbEditor.GetCode();
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Umbraco.Web.Editors.TemplateQuery
8+
{
9+
public class ContentTypeModel
10+
{
11+
public string Alias { get; set; }
12+
13+
public string Name { get; set; }
14+
}
15+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace Umbraco.Web.Editors
2+
{
3+
public enum Operathor
4+
{
5+
Equals = 1,
6+
NotEquals = 2,
7+
Contains = 3,
8+
NotContains = 4,
9+
LessThan = 5,
10+
LessThanEqualTo = 6,
11+
GreaterThan = 7,
12+
GreaterThanEqualTo = 8
13+
}
14+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System.Collections.Generic;
2+
3+
namespace Umbraco.Web.Editors
4+
{
5+
public class OperathorTerm
6+
{
7+
public OperathorTerm()
8+
{
9+
Name = "is";
10+
Operathor = Operathor.Equals;
11+
AppliesTo = new [] { "string" };
12+
}
13+
14+
public OperathorTerm(string name, Operathor operathor, IEnumerable<string> appliesTo)
15+
{
16+
Name = name;
17+
Operathor = operathor;
18+
AppliesTo = appliesTo;
19+
}
20+
21+
public string Name { get; set; }
22+
public Operathor Operathor { get; set; }
23+
public IEnumerable<string> AppliesTo { get; set; }
24+
}
25+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Umbraco.Web.Editors.TemplateQuery
8+
{
9+
public class PropertyModel
10+
{
11+
public string Name { get; set; }
12+
13+
public string Alias { get; set; }
14+
15+
public string Type { get; set; }
16+
}
17+
}

0 commit comments

Comments
 (0)