ca03154d3a0c45ce89a2968fc77ab577416f1631
[ccsdk/features.git] /
1 (function( $, app, i18n ) {
2
3         var ui = app.ns("ui");
4         var data = app.ns("data");
5         var ut = app.ns("ut");
6
7         ui.FilterBrowser = ui.AbstractWidget.extend({
8                 defaults: {
9                         cluster: null,  // (required) instanceof app.services.Cluster
10                         index: "" // (required) name of the index to query
11                 },
12
13                 init: function(parent) {
14                         this._super();
15                         this._cluster = this.config.cluster;
16                         this.el = $(this._main_template());
17                         this.filtersEl = this.el.find(".uiFilterBrowser-filters");
18                         this.attach( parent );
19                         new data.MetaDataFactory({ cluster: this._cluster, onReady: function(metadata, eventData) {
20                                 this.metadata = metadata;
21                                 this._createFilters_handler(eventData.originalData.metadata.indices);
22                         }.bind(this) });
23                 },
24
25                 _createFilters_handler: function(data) {
26                         var filters = [];
27                         function scan_properties(path, obj) {
28                                 if (obj.properties) {
29                                         for (var prop in obj.properties) {
30                                                 scan_properties(path.concat(prop), obj.properties[prop]);
31                                         }
32                                 } else {
33                                         // handle multi_field 
34                                         if (obj.fields) {
35                                                 for (var subField in obj.fields) {
36                                                         filters.push({ path: (path[path.length - 1] !== subField) ? path.concat(subField) : path, type: obj.fields[subField].type, meta: obj.fields[subField] });
37                                                 }
38                                         } else {
39                                                 filters.push({ path: path, type: obj.type, meta: obj });
40                                         }
41                                 }
42                         }
43                         for(var type in data[this.config.index].mappings) {
44                                 scan_properties([type], data[this.config.index].mappings[type]);
45                         }
46
47                         filters.sort( function(a, b) {
48                                 var x = a.path.join(".");
49                                 var y = b.path.join(".");
50                                 return (x < y) ? -1 : (x > y) ? 1 : 0;
51                         });
52
53                         this.filters = [
54                                 { path: ["match_all"], type: "match_all", meta: {} },
55                                 { path: ["_all"], type: "_all", meta: {}}
56                         ].concat(filters);
57
58                         this._addFilterRow_handler();
59                 },
60                 
61                 _addFilterRow_handler: function() {
62                         this.filtersEl.append(this._filter_template());
63                 },
64                 
65                 _removeFilterRow_handler: function(jEv) {
66                         $(jEv.target).closest("DIV.uiFilterBrowser-row").remove();
67                         if(this.filtersEl.children().length === 0) {
68                                 this._addFilterRow_handler();
69                         }
70                 },
71                 
72                 _search_handler: function() {
73                         var search = new data.BoolQuery();
74                         search.setSize( this.el.find(".uiFilterBrowser-outputSize").val() )
75                         this.fire("startingSearch");
76                         this.filtersEl.find(".uiFilterBrowser-row").each(function(i, row) {
77                                 row = $(row);
78                                 var bool = row.find(".bool").val();
79                                 var field = row.find(".field").val();
80                                 var op = row.find(".op").val();
81                                 var value = {};
82                                 if(field === "match_all") {
83                                         op = "match_all";
84                                 } else if(op === "range") {
85                                         var lowqual = row.find(".lowqual").val(),
86                                                 highqual = row.find(".highqual").val();
87                                         if(lowqual.length) {
88                                                 value[row.find(".lowop").val()] = lowqual;
89                                         }
90                                         if(highqual.length) {
91                                                 value[row.find(".highop").val()] = highqual;
92                                         }
93                                 } else if(op === "fuzzy") {
94                                         var qual = row.find(".qual").val(),
95                                                 fuzzyqual = row.find(".fuzzyqual").val();
96                                         if(qual.length) {
97                                                 value["value"] = qual;
98                                         }
99                                         if(fuzzyqual.length) {
100                                                 value[row.find(".fuzzyop").val()] = fuzzyqual;
101                                         }
102                                 } else {
103                                         value = row.find(".qual").val();
104                                 }
105                                 search.addClause(value, field, op, bool);
106                         });
107                         if(this.el.find(".uiFilterBrowser-showSrc").attr("checked")) {
108                                 this.fire("searchSource", search.search);
109                         }
110                         this._cluster.post( this.config.index + "/_search", search.getData(), this._results_handler );
111                 },
112                 
113                 _results_handler: function( data ) {
114                         var type = this.el.find(".uiFilterBrowser-outputFormat").val();
115                         this.fire("results", this, { type: type, data: data, metadata: this.metadata });
116                 },
117                 
118                 _changeQueryField_handler: function(jEv) {
119                         var select = $(jEv.target);
120                         var spec = select.children(":selected").data("spec");
121                         select.siblings().remove(".op,.qual,.range,.fuzzy");
122                         var ops = [];
123                         if(spec.type === 'match_all') {
124                         } else if(spec.type === '_all') {
125                                 ops = ["query_string"];
126                         } else if(spec.type === 'string' || spec.type === 'text' || spec.type === 'keyword') {
127                                 ops = ["term", "wildcard", "prefix", "fuzzy", "range", "query_string", "text", "missing"];
128                         } else if(spec.type === 'long' || spec.type === 'integer' || spec.type === 'float' ||
129                                         spec.type === 'byte' || spec.type === 'short' || spec.type === 'double') {
130                                 ops = ["term", "range", "fuzzy", "query_string", "missing"];
131                         } else if(spec.type === 'date') {
132                                 ops = ["term", "range", "fuzzy", "query_string", "missing"];
133                         } else if(spec.type === 'geo_point') {
134                                 ops = ["missing"];
135                         } else if(spec.type === 'ip') {
136                                 ops = ["term", "range", "fuzzy", "query_string", "missing"];
137                         } else if(spec.type === 'boolean') {
138                                 ops = ["term"]
139                         }
140                         select.after({ tag: "SELECT", cls: "op", onchange: this._changeQueryOp_handler, children: ops.map(ut.option_template) });
141                         select.next().change();
142                 },
143                 
144                 _changeQueryOp_handler: function(jEv) {
145                         var op = $(jEv.target), opv = op.val();
146                         op.siblings().remove(".qual,.range,.fuzzy");
147                         if(opv === 'term' || opv === 'wildcard' || opv === 'prefix' || opv === "query_string" || opv === 'text') {
148                                 op.after({ tag: "INPUT", cls: "qual", type: "text" });
149                         } else if(opv === 'range') {
150                                 op.after(this._range_template());
151                         } else if(opv === 'fuzzy') {
152                                 op.after(this._fuzzy_template());
153                         }
154                 },
155                 
156                 _main_template: function() {
157                         return { tag: "DIV", children: [
158                                 { tag: "DIV", cls: "uiFilterBrowser-filters" },
159                                 { tag: "BUTTON", type: "button", text: i18n.text("General.Search"), onclick: this._search_handler },
160                                 { tag: "LABEL", children:
161                                         i18n.complex("FilterBrowser.OutputType", { tag: "SELECT", cls: "uiFilterBrowser-outputFormat", children: [
162                                                 { text: i18n.text("Output.Table"), value: "table" },
163                                                 { text: i18n.text("Output.JSON"), value: "json" },
164                                                 { text: i18n.text("Output.CSV"), value: "csv" }
165                                         ].map(function( o ) { return $.extend({ tag: "OPTION" }, o ); } ) } )
166                                 },
167                                 { tag: "LABEL", children:
168                                         i18n.complex("FilterBrowser.OutputSize", { tag: "SELECT", cls: "uiFilterBrowser-outputSize",
169                                                 children: [ "10", "50", "250", "1000", "5000", "25000" ].map( ut.option_template )
170                                         } )
171                                 },
172                                 { tag: "LABEL", children: [ { tag: "INPUT", type: "checkbox", cls: "uiFilterBrowser-showSrc" }, i18n.text("Output.ShowSource") ] }
173                         ]};
174                 },
175                 
176                 _filter_template: function() {
177                         return { tag: "DIV", cls: "uiFilterBrowser-row", children: [
178                                 { tag: "SELECT", cls: "bool", children: ["must", "must_not", "should"].map(ut.option_template) },
179                                 { tag: "SELECT", cls: "field", onchange: this._changeQueryField_handler, children: this.filters.map(function(f) {
180                                         return { tag: "OPTION", data: { spec: f }, value: f.path.join("."), text: f.path.join(".") };
181                                 })},
182                                 { tag: "BUTTON", type: "button", text: "+", onclick: this._addFilterRow_handler },
183                                 { tag: "BUTTON", type: "button", text: "-", onclick: this._removeFilterRow_handler }
184                         ]};
185                 },
186                 
187                 _range_template: function() {
188                         return { tag: "SPAN", cls: "range", children: [
189                                 { tag: "SELECT", cls: "lowop", children: ["gt", "gte"].map(ut.option_template) },
190                                 { tag: "INPUT", type: "text", cls: "lowqual" },
191                                 { tag: "SELECT", cls: "highop", children: ["lt", "lte"].map(ut.option_template) },
192                                 { tag: "INPUT", type: "text", cls: "highqual" }
193                         ]};
194                 },
195
196                 _fuzzy_template: function() {
197                         return { tag: "SPAN", cls: "fuzzy", children: [
198                                 { tag: "INPUT", cls: "qual", type: "text" },
199                                 { tag: "SELECT", cls: "fuzzyop", children: ["max_expansions", "min_similarity"].map(ut.option_template) },
200                                 { tag: "INPUT", cls: "fuzzyqual", type: "text" }
201                         ]};
202                 }
203         });
204         
205 })( this.jQuery, this.app, this.i18n );