• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eswdd / aardvark / 4031096410

pending completion
4031096410

push

github

GitHub
Add rel="noopener noreferrer" to external link (#247)

1622 of 2218 branches covered (73.13%)

3379 of 4186 relevant lines covered (80.72%)

83.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.42
/static-content/QueryControlCtrl.js
1
/*
2
 * Used to render the tag value rows in the queries control panel.
3
 */
4
//noinspection JSLint
5
aardvark.directive('tagFilterSelection', function() {
1✔
6
    return {
×
7
        template: '<div mass-autocomplete><input type="text" ng-model="tag.value" mass-autocomplete-item="tagOptions[tag.name]" size="15" ng-blur="saveQueryIfAutoUpdate()" aardvark-enter="addOrSaveQuery()" /> {{tagValuesMatchCountFiltering(tag)}}</div>'
8
    }
9
})
10
/*
11
 * Query management:
12
 * - adding/removing
13
 * - graph association
14
 * - per query graphing options (timeseries selection, aggregation)
15
 * - graph type specific graphing options
16
 */
17
.controller('QueryControlCtrl', [ '$scope', '$rootScope', '$sce', 'idGenerator', 'tsdbClient', 'tsdbUtils', '$uibModal', 'tsdbUtils', 'deepUtils', function QueryControlCtrl($scope, $rootScope, $sce, idGenerator, $tsdbClient, $tsdbUtils, $uibModal, tsdbUtils, deepUtils) {
18

19
    $scope.localModel = {};
26✔
20
    
21
    $scope.treeUpdateInProgress = false;
26✔
22
    $scope.allParentNodes = [];
26✔
23
    $scope.showFilterInput = false;
26✔
24
    $scope.selectedTreeNode = undefined;
26✔
25
    $scope.selectedMetric = "";
26✔
26
    $scope.filter = "";
26✔
27
    $scope.expandedNodes = [];
26✔
28
    $scope.tagOptions = {};
26✔
29
    $scope.tagValues = {};
26✔
30
    $scope.localModel.tagFilters = [];
26✔
31
        
32
    $scope.selectedQueryId = 0;
26✔
33
    $scope.selectedQueryType = null;
26✔
34
    $scope.nodeSelectionDisabled = false;
26✔
35

36
    // TODO load aggregators from /aggregators on tsdb..
37
    $scope.allAggregators = ["avg", "min", "max", "sum", "zimsum", "mimmax", "mimmin", "raw", "dev", "count", "p999", "p99", "p95", "p90", "p75", "p50", "ep999r7", "ep99r7", "ep95r7", "ep90r7", "ep75r7", "ep50r7", "ep999r3", "ep99r3", "ep95r3", "ep90r3", "ep75r3", "ep50r3"];
26✔
38

39
    $scope.localModel.graphId = "0";
26✔
40
    $scope.localModel.aggregator = "sum";
26✔
41
    $scope.localModel.rightAxis = false;
26✔
42
    $scope.localModel.rate = false;
26✔
43
    $scope.localModel.rateCounter = false;
26✔
44
    $scope.localModel.rateCounterMax = "";
26✔
45
    $scope.localModel.rateCounterReset = "";
26✔
46
    $scope.localModel.downsample = false;
26✔
47
    $scope.localModel.downsampleBy = "avg";
26✔
48
    $scope.localModel.downsampleTo = "";
26✔
49
        
50
    $scope.showingIgnoredPrefixes = false;
26✔
51

52
    $scope.globalDownsampling = false;
26✔
53

54
    $rootScope.$on('globalDownsamplingChanged', function (event, data) {
26✔
55
        $scope.globalDownsampling = data;
×
56
    });
57
        
58
    $scope.$watch('localModel.dygraph.drawLines', function(newVal, oldVal, scope) {
26✔
59
        // one of them must be true!
60
        if (newVal != oldVal && !newVal) {
×
61
            $scope.localModel.dygraph.drawPoints = true;
×
62
        }
63
    })
64
        
65
    $scope.$watch('localModel.dygraph.drawPoints', function(newVal, oldVal, scope) {
26✔
66
        // one of them must be true!
67
        if (newVal != oldVal && !newVal) {
×
68
            $scope.localModel.dygraph.drawLines = true;
×
69
        }
70
    })
71

72
    $scope.addButtonVisible = function() {
26✔
73
        var ret = $scope.selectedMetric != "";
18✔
74
        return ret;
18✔
75
    };
76
    $scope.deleteButtonVisible = function() {
26✔
77
        return $scope.selectedQueryId != "0";
4✔
78
    };
79
    $scope.saveButtonVisible = function() {
26✔
80
        return $scope.selectedQueryId != "0";
15✔
81
    };
82
    $scope.clearButtonEnabled = function() {
26✔
83
        return $scope.addButtonVisible() || $scope.saveButtonVisible();
9✔
84
    };
85
    $scope.expandAllVisible = function() {
26✔
86
        return $rootScope.config && $rootScope.config.ui.metrics.enableExpandAll;
2✔
87
    };
88
    $scope.tagFilteringSupported = function() {
26✔
89
        return $tsdbClient.versionNumber >= $tsdbClient.TSDB_2_2;
4✔
90
    };
91
    $scope.expressionQueriesSupported = function() {
26✔
92
        return $tsdbClient.versionNumber >= $tsdbClient.TSDB_2_3;
×
93
    }
94
    $scope.clearSelectedTreeNode = function() {
26✔
95
        $scope.selectedTreeNode = undefined;
4✔
96
    }
97
    $scope.graphType = function() {
26✔
98
        var graph = $scope.allocatedGraph();
×
99
        if (graph != null) {
×
100
            return graph.type;
×
101
        }
102
        return "";
×
103
    }
104
    $scope.metricString = function(metricQuery) {
26✔
105
        return tsdbUtils.metricQuery(metricQuery, false, null/*globalDownsampleTo*/, null/*downsampleOverrideFn*/, function(s){});
×
106
    }
107
    $scope.currentMetricName = function() {
26✔
108
        if ($scope.selectedMetric != null && $scope.selectedMetric != "") {
×
109
            return $scope.selectedMetric;
×
110
        }
111

112
        var queryId = $scope.selectedQueryId;
×
113
        if (queryId == "0") {
×
114
            return "";
×
115
        }
116
        for (var i=0; i<$rootScope.model.queries.length; i++) {
×
117
            var q = $rootScope.model.queries[i];
×
118
            if (q.id == queryId) {
×
119
                return q.name;
×
120
            }
121
        }
122
        return "";
×
123
    }
124
    $scope.addOrSaveQuery = function() {
26✔
125
        if ($scope.addButtonVisible()) {
×
126
            $scope.addQuery();
×
127
        }
128
        else {
129
            $scope.saveQuery();
×
130
        }
131
    }
132
    $scope.saveQueryIfAutoUpdate = function() {
26✔
133
        if (!$scope.addButtonVisible() && $rootScope.autoUpdateEnabled()) {
×
134
            $scope.saveQuery();
×
135
        }
136
    }
137
        
138
    $scope.allocatedGraph = function() {
26✔
139
        var graph = null;
×
140
        if ($rootScope.model.graphs != null) {
×
141
            for (var g=0; g<$rootScope.model.graphs.length; g++) {
×
142
                if ($rootScope.model.graphs[g].id == $scope.localModel.graphId) {
×
143
                    graph = $rootScope.model.graphs[g];
×
144
                }
145
            }
146
        }
147
        return graph;
×
148
    }
149

150
    $scope.downsampleByEnabled = function() {
26✔
151
        var graph = $scope.allocatedGraph();
×
152
        return $scope.localModel.downsample || $scope.globalDownsampling 
×
153
            || (graph != null && (graph.type == "horizon" || graph.type == "heatmap"));
154
    }
155

156
    $scope.treeOptions = {
26✔
157
        nodeChildren: "children",
158
        dirSelectable: true,
159
        injectClasses: {
160
            ul: "a1",
161
            li: "a2",
162
            liSelected: "a7",
163
            iExpanded: "a3",
164
            iCollapsed: "a4",
165
            iLeaf: "a5",
166
            label: "a6",
167
            labelSelected: "a8"
168
        }
169
    };
170

171
    $scope.nodeSelectedForAddition = function (node,selected) {
26✔
172
        var valid = selected && node.isMetric;
4✔
173
        $scope.selectedMetric = valid ? node.id : '';
4✔
174
        $scope.nodeSelectionDisabled = valid;
4✔
175
        if (valid) {
4✔
176
            $scope.selectedQueryId = "0";
3✔
177
            if ($rootScope.model.graphs.length == 1) {
3✔
178
                $scope.localModel.graphId = $rootScope.model.graphs[0].id;
2✔
179
            }
180
            else {
181
                $scope.localModel.graphId = "0";
1✔
182
            }
183
            $scope.metricSelected($scope.selectedMetric.trim(), true);
3✔
184
        }
185
        else {
186
            $scope.metricDeselected();
1✔
187
        }
188
    };
189

190
    $scope.nodeSelectedForEditing = function() {
26✔
191
        var queryId = $scope.selectedQueryId;
1✔
192
        if (queryId == "0") {
1!
193
            return;
×
194
        }
195
        var query = null;
1✔
196
        for (var i=0; i<$rootScope.model.queries.length; i++) {
1✔
197
            var q = $rootScope.model.queries[i];
1✔
198
            if (q.id == queryId) {
1!
199
                query = q;
1✔
200
                break;
1✔
201
            }
202
        }
203

204
        if (query == null) {
1!
205
            alert("couldn't find query "+queryId);
×
206
            return;
×
207
        }
208

209
        // load the tag names / possible values
210
        $scope.metricSelected(query.name, false);
1✔
211
        $scope.selectedQueryType = query.type;
1✔
212
        // populate tag chosen values / re flags
213
        $scope.localModel.tagFilters = query.tags;
1✔
214
        for (var t=0; t<$scope.localModel.tagFilters.length; t++) {
1✔
215
            var tag = $scope.localModel.tagFilters[t];
3✔
216
            $scope.tag[tag.name] = tag.value;
3✔
217
            if (tag.id == null) {
3!
218
                tag.id = idGenerator.nextId(); 
3✔
219
            }
220
        }
221
        // populate graph options
222
        if (query.graphOptions) {
1!
223
            $scope.localModel.graphId = query.graphOptions.graphId + "";
1✔
224
            $scope.localModel.rate = query.graphOptions.rate;
1✔
225
            $scope.localModel.rateCounter = query.graphOptions.rateCounter;
1✔
226
            $scope.localModel.rateCounterReset = query.graphOptions.rateCounterReset;
1✔
227
            $scope.localModel.rateCounterMax = query.graphOptions.rateCounterMax;
1✔
228
            $scope.localModel.aggregator = query.graphOptions.aggregator;
1✔
229
            $scope.localModel.rightAxis = query.graphOptions.axis == "x1y2";
1✔
230
            $scope.localModel.downsample = query.graphOptions.downsample;
1✔
231
            $scope.localModel.downsampleBy = query.graphOptions.downsampleBy;
1✔
232
            $scope.localModel.downsampleTo = query.graphOptions.downsampleTo;
1✔
233
            if (query.graphOptions.dygraph) {
1!
234
                $scope.localModel.dygraph.drawLines = query.graphOptions.dygraph.drawLines;
×
235
                $scope.localModel.dygraph.drawPoints = query.graphOptions.dygraph.drawPoints;
×
236
            }
237
        }
238
    }
239
        
240
    $scope._alwaysShowTreeFilterInput = function() {
26✔
241
        if ($rootScope.config && $rootScope.config.ui && $rootScope.config.ui.metrics && $rootScope.config.ui.metrics.alwaysShowMetricFilter != null) {
9✔
242
            return $rootScope.config.ui.metrics.alwaysShowMetricFilter;
4✔
243
        }
244
        return false;
5✔
245
    }
246

247
    $scope.treeFilterButtonVisible = function() {
26✔
248
        return !$scope._alwaysShowTreeFilterInput();
2✔
249
    }
250

251
    $scope.treeFilterVisible = function() {
26✔
252
        return $scope.showFilterInput || $scope._alwaysShowTreeFilterInput();
5✔
253
    }
254

255
    $scope.showHideFilterInput = function() {
26✔
256
        if (!$scope._alwaysShowTreeFilterInput()) {
3✔
257
            if ($scope.showFilterInput) {
2✔
258
                $scope.clearFilterInput();
1✔
259
            }
260
            $scope.showFilterInput = !$scope.showFilterInput;
2✔
261
        }
262
    }
263

264
    $scope.clearFilterInput = function() {
26✔
265
        $scope.filter = '';
1✔
266
    }
267

268

269
    $scope.collapseAll = function() {
26✔
270
        $scope.expandedNodes = [];
×
271
    };
272

273
    $scope.expandAll = function() {
26✔
274
        $scope.expandedNodes = $scope.allParentNodes;
×
275
    };
276

277
    $scope.showIgnoredPrefixes = function() {
26✔
278
        $scope.showingIgnoredPrefixes = true;
×
279
        $scope.updateTree();
×
280
    }
281

282
    $scope.hideIgnoredPrefixes = function() {
26✔
283
        $scope.showingIgnoredPrefixes = false;
×
284
        $scope.updateTree();
×
285
    }
286

287
    $scope.configContainsIgnoredPrefixes = function() {
26✔
288
        if ($rootScope.config == null) {
3!
289
            return false;
×
290
        }
291
        var ignorePrefixes = $rootScope.config.hidePrefixes;
3✔
292
        return ignorePrefixes != null && ignorePrefixes.length > 0;
3✔
293
    }
294

295
    $scope.showIgnoredPrefixesVisible = function() {
26✔
296
        return $scope.configContainsIgnoredPrefixes() && !$scope.showingIgnoredPrefixes;
×
297
    }
298

299
    $scope.hideIgnoredPrefixesVisible = function() {
26✔
300
        return $scope.configContainsIgnoredPrefixes() && $scope.showingIgnoredPrefixes;
×
301
    }
302

303
    $scope.nodeDecoration = function(node) {
26✔
304
        return node.isMetric ? "underline" : "none";
×
305
    };
306

307
    $scope.addQuery = function() {
26✔
308
        var query = {
1✔
309
            id: idGenerator.nextId(),
310
            name: $scope.selectedMetric
311
        };
312
        $rootScope.model.queries.push(query);
1✔
313
        $scope.persistViewToExistingQuery(query);
1✔
314
    }
315

316
    $scope.saveQuery = function() {
26✔
317
        // unlike the function above, this wants to save the state into the existing query
318
        for (var i=0; i<$rootScope.model.queries.length; i++) {
1✔
319
            if ($rootScope.model.queries[i].id == $scope.selectedQueryId) {
1!
320
                $scope.persistViewToExistingQuery($rootScope.model.queries[i]);
1✔
321
                return;
1✔
322
            }
323
        }
324
    }
325

326
    $scope.deleteQuery = function() {
26✔
327
        for (var i=0; i<$rootScope.model.queries.length; i++) {
2✔
328
            if ($rootScope.model.queries[i].id == $scope.selectedQueryId) {
2!
329
                $rootScope.model.queries.splice(i,1);
2✔
330
                $rootScope.saveModel(true);
2✔
331
                $scope.clearQuery();
2✔
332
                return;
2✔
333
            }
334
        }
335
    }
336

337
    $scope.clearQuery = function() {
26✔
338
        $scope.metricDeselected();
4✔
339
        $scope.clearSelectedTreeNode();
4✔
340
    }
341
        
342
    $scope.isMetricQuery = function() {
26✔
343
        return $scope.selectedQueryType == null || $scope.selectedQueryType == "metric";
×
344
    }
345
        
346
    $scope.isExpressionQuery = function() {
26✔
347
        return $scope.selectedQueryType == "gexp" || $scope.selectedQueryType == "exp";
×
348
    }
349
        
350
        
351

352
    $scope.persistViewToExistingQuery = function(query) {
26✔
353
        query.type = "metric"; // all we support right now
2✔
354
        query.tags = [];
2✔
355
        for (var t=0; t<$scope.localModel.tagFilters.length; t++) {
2✔
356
            var tag = {name:$scope.localModel.tagFilters[t].name,value:$scope.localModel.tagFilters[t].value};
6✔
357
            if ($scope.localModel.tagFilters[t].groupBy != null) {
6!
358
                tag.groupBy = $scope.localModel.tagFilters[t].groupBy;
×
359
            }
360
            else { // older versions
361
                tag.groupBy = true;
6✔
362
            }
363
            query.tags.push(tag);
6✔
364
        }
365
        query.graphOptions = {
2✔
366
            graphId: $scope.localModel.graphId,
367
            rate: $scope.localModel.rate,
368
            rateCounter: $scope.localModel.rateCounter,
369
            rateCounterMax: $scope.localModel.rateCounterMax,
370
            rateCounterReset: $scope.localModel.rateCounterReset,
371
            aggregator: $scope.localModel.aggregator,
372
            axis: $scope.localModel.rightAxis ? "x1y2" : "x1y1",
2✔
373
            downsample: $scope.localModel.downsample,
374
            downsampleBy: $scope.localModel.downsampleBy,
375
            downsampleTo: $scope.localModel.downsampleTo,
376
            dygraph: {
377
                drawLines: $scope.localModel.dygraph.drawLines,
378
                drawPoints: $scope.localModel.dygraph.drawPoints
379
            }
380
        };
381
        $rootScope.saveModel(true);
2✔
382
        $scope.selectedMetric = "";
2✔
383
        $scope.selectedQueryId = "" + query.id;
2✔
384
    }
385

386
    $scope.addTagRow = function(tagk) {
26✔
387
        if (!$scope.tagFilteringSupported()) {
4✔
388
            for (var t=0; t<$scope.localModel.tagFilters.length; t++) {
2✔
389
                if ($scope.localModel.tagFilters[t].name == tagk) {
1!
390
                    return;
1✔
391
                }
392
            }
393
        }
394
        $scope.localModel.tagFilters.push({id:idGenerator.nextId(),name:tagk,value:"",groupBy:true});
3✔
395
    }
396

397
    $scope.deleteTagRow = function(id) {
26✔
398
        var index = -1;
×
399
        for (var i=0; i<$scope.localModel.tagFilters.length; i++) {
×
400
            if ($scope.localModel.tagFilters[i].id == id) {
×
401
                index = i;
×
402
                break;
×
403
            }
404
        }
405
        if (index != -1) {
×
406
            $scope.localModel.tagFilters.splice(index, 1);
×
407
        }
408
    }
409

410
    // todo: this needs to have some failure handling
411
    $scope.updateTree = function() {
26✔
412
        if ($scope.treeUpdateInProgress) {
3!
413
            return;
×
414
        }
415
        $scope.treeUpdateInProgress = true;
3✔
416
        $tsdbClient.suggest("metrics", "", null, function(json) {
3✔
417
            $scope.treeUpdateInProgress = false;
3✔
418
            // right we need to build our tree, we have an array of name, we need to split by "."
419

420
            var roots = [];
3✔
421
            var nodes = {};
3✔
422
            var allNodes = [];
3✔
423
            var parentNodes = [];
3✔
424
            
425
            var prefixProcessing = $scope.configContainsIgnoredPrefixes() && !$scope.showingIgnoredPrefixes;
3✔
426
            
427
            var ignorePrefixes = $rootScope.config.hidePrefixes;
3✔
428
            if (prefixProcessing) {
3✔
429
                if (ignorePrefixes == null) {
1!
430
                    ignorePrefixes = [];
×
431
                }
432
                for (var p=0; p<ignorePrefixes.length; p++) {
1✔
433
                    if (ignorePrefixes[p].indexOf(".") != ignorePrefixes[p].length-1) {
2!
434
                        ignorePrefixes[p] += ".";
2✔
435
                    }
436
                }
437
            }
438

439
            for (var i = 0; i < json.length; i++) {
3✔
440
                if (prefixProcessing) {
19✔
441
                    var ignoreThis = false;
7✔
442
                    for (var p=0; p<ignorePrefixes.length; p++) {
7✔
443
                        if ((json[i]+".").indexOf(ignorePrefixes[p]) == 0) {
12✔
444
                            ignoreThis = true;
3✔
445
                            break;
3✔
446
                        }
447
                    }
448
                    if (ignoreThis) {
7✔
449
                        continue;
3✔
450
                    }
451
                }
452
                
453
                var path = json[i].split(".");
16✔
454
                var parent = roots;
16✔
455
                var id = "";
16✔
456
                for (var j = 0; j < path.length; j++) {
16✔
457
                    if (j > 0) {
30✔
458
                        id += ".";
14✔
459
                    }
460
                    id += path[j];
30✔
461
                    var node = nodes[id];
30✔
462
                    if (!node) {
30✔
463
                        node = {id: id, name:path[j], isMetric:false, children: []};
24✔
464
                        if (parent == roots) {
24✔
465
                            parent.push(node);
10✔
466
                        }
467
                        else {
468
                            parent.children.push(node);
14✔
469
                        }
470
                        nodes[id] = node;
24✔
471
                        allNodes.push(node);
24✔
472
                    }
473
                    parent = node;
30✔
474
                }
475
                parent.isMetric = true;
16✔
476
            }
477

478
            $scope.dataForTheTree = roots;
3✔
479
            for (var k=0; k<allNodes.length; k++) {
3✔
480
                if (allNodes[k].children.length > 0) {
24✔
481
                    parentNodes.push(allNodes[k]);
10✔
482
                }
483
            }
484
            $scope.allParentNodes = parentNodes;
3✔
485
        }, function() {
486
            $scope.treeUpdateInProgress = false;
×
487
        });
488
    };
489

490
    $scope.metricSelected = function(metricName, isNewMetric) {
26✔
491
        $scope.tagOptions = {};
4✔
492
        $scope.tag = {};
4✔
493
        $scope.resetUserQueryOptions();
4✔
494
        
495
        $tsdbUtils.getTags(metricName, function(tagValues) {
4✔
496
            var tagNames = [];
4✔
497

498
            for (var key in tagValues) {
4✔
499
                if (tagValues.hasOwnProperty(key)) {
9!
500
                    tagNames.push(key);
9✔
501
                }
502
            }
503

504
            // setup tagk options prior to making them available
505
            for (var i=0; i<tagNames.length; i++) {
4✔
506
                // nasty inner function to get around closure issues
507
                var fn = function(localKey) {
9✔
508
                    $scope.tagOptions[localKey] = {
9✔
509
                        suggest: function(term) {
510
                            return $scope.suggestTagValues(term, localKey);
2✔
511
                        }
512
                    };
513
                    if (isNewMetric) {
9✔
514
                        $scope.tag[localKey] = '';
6✔
515
                    }
516
                }
517
                fn(tagNames[i]);
9✔
518
            }
519
            $scope.tagNames = tagNames;
4✔
520
            $scope.tagValues = tagValues;
4✔
521
        }, function(results) {
522
            // todo: error handling
523
        });
524
    };
525
        
526
    // reset user entered query state, used when switching between queries
527
    $scope.resetUserQueryOptions = function() {
26✔
528
        $scope.localModel.tagFilters = [];
9✔
529
        $scope.localModel.rate = false;
9✔
530
        $scope.localModel.rateCounter = false;
9✔
531
        $scope.localModel.rateCounterMax = "";
9✔
532
        $scope.localModel.rateCounterReset = "";
9✔
533
        $scope.localModel.downsample = false;
9✔
534
        $scope.localModel.downsampleBy = "avg";
9✔
535
        $scope.localModel.downsampleTo = "";
9✔
536
        $scope.localModel.rightAxis = false;
9✔
537
        $scope.localModel.aggregator = "sum";
9✔
538
        if (!$scope.localModel.dygraph) {
9✔
539
            $scope.localModel.dygraph = {};
7✔
540
        }
541
        $scope.localModel.dygraph.drawLines = true;
9✔
542
        $scope.localModel.dygraph.drawPoints = false;
9✔
543
    }
544

545
    // todo: need better way of defining defaulting and copying between scope and model on per graph type basis
546
    //           perhaps using skeleton style approach
547
    $scope.metricDeselected = function() {
26✔
548
        $scope.tagOptions = {};
5✔
549
        $scope.tagValues = {};
5✔
550
        $scope.tagNames = [];
5✔
551
        $scope.tag = {};
5✔
552
        $scope.selectedMetric = "";
5✔
553
        $scope.selectedQueryId = "0";
5✔
554
        $scope.resetUserQueryOptions();
5✔
555
        $scope.nodeSelectionDisabled = false;
5✔
556
    };
557

558
    $scope.tagValuesMatchCount = function(tag) {
26✔
559
        var inputText = $scope.tag[tag];
7✔
560
        return $scope.tagValuesMatchCountInternal(tag, inputText, false);
7✔
561
    };
562

563
    $scope.tagValuesMatchCountFiltering = function(tagFilter) {
26✔
564
        var tag = tagFilter.name;
27✔
565
        
566
        var inputText = tagFilter.value;
27✔
567
        return $scope.tagValuesMatchCountInternal(tag, inputText, true);
27✔
568
    };
569
        
570
    $scope.tagValuesMatchCountInternal = function(tag, inputText, filtering) {
26✔
571
        if (inputText=="" || inputText==null){
34✔
572
            return "";
2✔
573
        }
574
        var allValues = $scope.tagValues[tag];
32✔
575
        if (allValues == null) {
32!
576
            return "";
×
577
        }
578
        var count = 0;
32✔
579
        if (inputText=="*") {
32✔
580
            return "("+allValues.length+")";
2✔
581
        }
582
        if (filtering && (inputText=="wildcard(*)" || inputText=="iwildcard(*)" || inputText=="regexp(.*)")) {
30✔
583
            return "("+allValues.length+")";
3✔
584
        }
585
        
586
        if (inputText.indexOf(")") == inputText.length - 1) {
27✔
587
            var fn = null;
17✔
588
            var ignoreCase = false;
17✔
589
            var negate = false;
17✔
590
            var openBraceIndex = inputText.indexOf("(");
17✔
591
            if (openBraceIndex > -1) {
17!
592
                var closeBraceIndex = inputText.indexOf(")");
17✔
593
                if (closeBraceIndex == inputText.length - 1) {
17!
594
                    var filterFn = inputText.substring(0, openBraceIndex);
17✔
595
                    negate = filterFn.indexOf("not_") == 0;
17✔
596
                    var filterValue = inputText.substring(openBraceIndex+1, closeBraceIndex);
17✔
597
                    fn = function(candidateValue) {
17✔
598
                        return $tsdbClient.tagFilterMatchesValue({fn:filterFn,value:filterValue}, candidateValue);
68✔
599
                    }
600
                }
601
                if (fn != null && allValues != null) {
17!
602
                    for (var j=0; j<allValues.length; j++) {
17✔
603
                        if (fn(allValues[j])) {
68✔
604
                            count++;
28✔
605
                        }
606
                    }
607
                    var result = negate ? allValues.length - count : count;
17✔
608
                    return "("+result+")";
17✔
609
                }
610
                
611
            }
612
        }
613
        // old school query
614
        if (allValues != null) {
10!
615
            var allTags = inputText.split("|");
10✔
616
            for (var j=0; j<allValues.length; j++) {
10✔
617
                var ind = allTags.indexOf(allValues[j]);
35✔
618
                if (ind >= 0) {
35✔
619
                    count++;
6✔
620
                }
621
            }
622
        }
623

624
        return "("+count+")";
10✔
625
    }
626
        
627

628
    $scope.suggestTagValues = function(term, tag) {
26✔
629
        var q = term.toLowerCase().trim();
11✔
630

631
        var lastPipe = q.lastIndexOf("|");
11✔
632
        var prefix = "";
11✔
633

634
        var haveValues = [];
11✔
635
        if (lastPipe >= 0) {
11✔
636
            prefix = q.substring(0,lastPipe+1);
4✔
637
            q = q.substring(lastPipe+1);
4✔
638

639
            var haveValuesString = prefix.substring(0, lastPipe);
4✔
640
            haveValues = haveValuesString.split("|");
4✔
641
        }
642

643
        var results = [];
11✔
644

645
        var allValues = $scope.tagValues[tag];
11✔
646
        for (var i=0; i<allValues.length; i++) {
11✔
647
            if (haveValues.indexOf(allValues[i])<0) {
30✔
648
                if (allValues[i].toLowerCase().startsWith(q)) {
23✔
649
                    results.push({label: allValues[i], value: prefix+allValues[i]});
13✔
650
                }
651
            }
652
        }
653
        return results;
11✔
654
    };
655
        
656
    $scope.expressionQueryCount = function(graph) {
26✔
657
        return 0; // todo
×
658
    }
659

660
    $scope.openQueryDialog = function() {
26✔
661
        var modalInstance = $uibModal.open({
×
662
            animation: false,
663
            ariaLabelledBy: 'query-editor-modal-title',
664
            ariaDescribedBy: 'query-editor-modal-body',
665
            templateUrl: 'queryEditorDialog.tmpl.html',
666
            controller: 'QueryEditorDialogCtrl',
667
            controllerAs: '$ctrl',
668
            size: 'lg',
669
            resolve: {
670
                queries: function() { return $rootScope.model.queries; },
×
671
                graphs: function() { return $rootScope.model.graphs; },
×
672
                idGenerator: function() { return idGenerator; },
×
673
                tsdbUtils: function() { return tsdbUtils; },
×
674
                deepUtils: function() { return deepUtils; }
×
675
            }
676
        });
677
        modalInstance.result.then(function (result) {
×
678
            var changed = result.changed;
×
679
//            var deleted = result.deleted;
680
//            var existingById = {};
681
//            for (var q=0; q<$rootScope.model.queries.length; q++) {
682
//                existingById[$rootScope.model.queries[q].id] = $rootScope.model.queries[q];
683
//            }
684
            $rootScope.model.queries = changed;
×
685
            $rootScope.saveModel(true);
×
686
        }, function () {
687
            // do nothing
688
        });
689
    }
690

691
    $scope.updateModel = function() {
26✔
692
        $scope.updateTree();
3✔
693
        // init internal copy
694
        $scope.globalDownsampling = $rootScope.model.global.globalDownsampling && true; // force to boolean
3!
695
    }
696
        
697
    $rootScope.$on("modelUpdated", function(event,data) {
26✔
698
        //console.log("rootScope.modelUpdated received, updating GraphControlCtrl model")
699
        $scope.updateModel();
×
700
    });
701

702
    // tell the main app controller to call us on any update of the config
703
    // it will call us if it's already loaded too
704
    $rootScope.onConfigUpdate($scope.updateModel);
26✔
705
}]);
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc