Dashboard list panel: Now supports search by multiple tags, Closes #2096

This commit is contained in:
Torkel Ödegaard 2015-06-02 11:04:06 +02:00
parent 6df9012141
commit 50a1feb90a
9 changed files with 29 additions and 18 deletions

View File

@ -6,6 +6,7 @@
- [Issue #1888](https://github.com/grafana/grafana/issues/1144). Templating: Repeat panel or row for each selected template variable value - [Issue #1888](https://github.com/grafana/grafana/issues/1144). Templating: Repeat panel or row for each selected template variable value
- [Issue #1888](https://github.com/grafana/grafana/issues/1944). Dashboard: Custom Navigation links & dynamic links to related dashboards - [Issue #1888](https://github.com/grafana/grafana/issues/1944). Dashboard: Custom Navigation links & dynamic links to related dashboards
- [Issue #590](https://github.com/grafana/grafana/issues/590). Graph: Define series color using regex rule - [Issue #590](https://github.com/grafana/grafana/issues/590). Graph: Define series color using regex rule
- [Issue #2096](https://github.com/grafana/grafana/issues/2096). Dashboard list panel: Now supports search by multiple tags
**User or Organization admin** **User or Organization admin**
- [Issue #1899](https://github.com/grafana/grafana/issues/1899). Organization: You can now update the organization user role directly (without removing and readding the organization user). - [Issue #1899](https://github.com/grafana/grafana/issues/1899). Organization: You can now update the organization user role directly (without removing and readding the organization user).

View File

@ -13,7 +13,7 @@ func Search(c *middleware.Context) {
limit := c.QueryInt("limit") limit := c.QueryInt("limit")
if limit == 0 { if limit == 0 {
limit = 200 limit = 1000
} }
searchQuery := search.Query{ searchQuery := search.Query{

View File

@ -1,6 +1,7 @@
package search package search
import ( import (
"fmt"
"path/filepath" "path/filepath"
"sort" "sort"
@ -34,7 +35,6 @@ func searchHandler(query *Query) error {
dashQuery := FindPersistedDashboardsQuery{ dashQuery := FindPersistedDashboardsQuery{
Title: query.Title, Title: query.Title,
UserId: query.UserId, UserId: query.UserId,
Limit: query.Limit,
IsStarred: query.IsStarred, IsStarred: query.IsStarred,
OrgId: query.OrgId, OrgId: query.OrgId,
} }
@ -65,6 +65,14 @@ func searchHandler(query *Query) error {
hits = filtered hits = filtered
} }
// sort main result array
sort.Sort(hits)
fmt.Printf("Length: %d", len(hits))
if len(hits) > query.Limit {
hits = hits[0 : query.Limit-1]
}
// sort tags // sort tags
for _, hit := range hits { for _, hit := range hits {
sort.Strings(hit.Tags) sort.Strings(hit.Tags)
@ -75,9 +83,6 @@ func searchHandler(query *Query) error {
return err return err
} }
// sort main result array
sort.Sort(hits)
query.Result = hits query.Result = hits
return nil return nil
} }

View File

@ -12,7 +12,7 @@ func TestSearch(t *testing.T) {
Convey("Given search query", t, func() { Convey("Given search query", t, func() {
jsonDashIndex = NewJsonDashIndex("../../public/dashboards/") jsonDashIndex = NewJsonDashIndex("../../public/dashboards/")
query := Query{} query := Query{Limit: 2000}
bus.AddHandler("test", func(query *FindPersistedDashboardsQuery) error { bus.AddHandler("test", func(query *FindPersistedDashboardsQuery) error {
query.Result = HitList{ query.Result = HitList{

View File

@ -39,7 +39,6 @@ type FindPersistedDashboardsQuery struct {
Title string Title string
OrgId int64 OrgId int64
UserId int64 UserId int64
Limit int
IsStarred bool IsStarred bool
Result HitList Result HitList

View File

@ -150,11 +150,7 @@ func SearchDashboards(query *search.FindPersistedDashboardsQuery) error {
params = append(params, "%"+query.Title+"%") params = append(params, "%"+query.Title+"%")
} }
if query.Limit == 0 || query.Limit > 10000 { sql.WriteString(fmt.Sprintf(" ORDER BY dashboard.title ASC LIMIT 1000"))
query.Limit = 1000
}
sql.WriteString(fmt.Sprintf(" ORDER BY dashboard.title ASC LIMIT %d", query.Limit))
var res []DashboardSearchProjection var res []DashboardSearchProjection
err := x.Sql(sql.String(), params...).Find(&res) err := x.Sql(sql.String(), params...).Find(&res)

View File

@ -70,7 +70,8 @@ function (angular, $) {
return { return {
restrict: 'EA', restrict: 'EA',
scope: { scope: {
model: '=ngModel' model: '=ngModel',
onTagsUpdated: "&",
}, },
template: '<select multiple></select>', template: '<select multiple></select>',
replace: false, replace: false,
@ -99,6 +100,9 @@ function (angular, $) {
select.on('itemAdded', function(event) { select.on('itemAdded', function(event) {
if (scope.model.indexOf(event.item) === -1) { if (scope.model.indexOf(event.item) === -1) {
scope.model.push(event.item); scope.model.push(event.item);
if (scope.onTagsUpdated) {
scope.onTagsUpdated();
}
} }
var tagElement = select.next().children("span").filter(function() { return $(this).text() === event.item; }); var tagElement = select.next().children("span").filter(function() { return $(this).text() === event.item; });
setColor(event.item, tagElement); setColor(event.item, tagElement);
@ -108,6 +112,9 @@ function (angular, $) {
var idx = scope.model.indexOf(event.item); var idx = scope.model.indexOf(event.item);
if (idx !== -1) { if (idx !== -1) {
scope.model.splice(idx, 1); scope.model.splice(idx, 1);
if (scope.onTagsUpdated) {
scope.onTagsUpdated();
}
} }
}); });

View File

@ -27,11 +27,11 @@
ng-model="panel.query" ng-change="get_data()" ng-model-onblur> ng-model="panel.query" ng-change="get_data()" ng-model-onblur>
</li> </li>
<li class="tight-form-item"> <li class="tight-form-item">
Tag Tags
</li> </li>
<li> <li>
<input type="text" class="input-small tight-form-input" placeholder="full tag name" <bootstrap-tagsinput ng-model="panel.tags" tagclass="label label-tag" placeholder="add tags" on-tags-updated="get_data()">
ng-model="panel.tag" ng-change="get_data()" ng-model-onblur> </bootstrap-tagsinput>
</li> </li>
</ul> </ul>
<div class="clearfix"></div> <div class="clearfix"></div>

View File

@ -32,7 +32,7 @@ function (angular, app, _, config, PanelMeta) {
mode: 'starred', mode: 'starred',
query: '', query: '',
limit: 10, limit: 10,
tag: '', tags: []
}; };
$scope.modes = ['starred', 'search']; $scope.modes = ['starred', 'search'];
@ -43,6 +43,9 @@ function (angular, app, _, config, PanelMeta) {
$scope.init = function() { $scope.init = function() {
panelSrv.init($scope); panelSrv.init($scope);
if ($scope.panel.tag) {
$scope.panel.tags = [$scope.panel.tag];
}
if ($scope.isNewPanel()) { if ($scope.isNewPanel()) {
$scope.panel.title = "Starred Dashboards"; $scope.panel.title = "Starred Dashboards";
@ -58,7 +61,7 @@ function (angular, app, _, config, PanelMeta) {
params.starred = "true"; params.starred = "true";
} else { } else {
params.query = $scope.panel.query; params.query = $scope.panel.query;
params.tag = $scope.panel.tag; params.tag = $scope.panel.tags;
} }
return backendSrv.search(params).then(function(result) { return backendSrv.search(params).then(function(result) {