diff --git a/pkg/api/search.go b/pkg/api/search.go index 035e59fa3f4..4b253e32cb0 100644 --- a/pkg/api/search.go +++ b/pkg/api/search.go @@ -4,6 +4,7 @@ import ( "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/middleware" "github.com/grafana/grafana/pkg/services/search" + "strconv" ) func Search(c *middleware.Context) { @@ -16,13 +17,22 @@ func Search(c *middleware.Context) { limit = 1000 } + dbids := make([]int, 0) + for _, id := range c.QueryStrings("dashboardIds") { + dashboardId, err := strconv.Atoi(id) + if err == nil { + dbids = append(dbids, dashboardId) + } + } + searchQuery := search.Query{ - Title: query, - Tags: tags, - UserId: c.UserId, - Limit: limit, - IsStarred: starred == "true", - OrgId: c.OrgId, + Title: query, + Tags: tags, + UserId: c.UserId, + Limit: limit, + IsStarred: starred == "true", + OrgId: c.OrgId, + DashboardIds: dbids, } err := bus.Dispatch(&searchQuery) diff --git a/pkg/services/search/handlers.go b/pkg/services/search/handlers.go index 1c480992cbc..a4905d6fa58 100644 --- a/pkg/services/search/handlers.go +++ b/pkg/services/search/handlers.go @@ -39,10 +39,11 @@ func searchHandler(query *Query) error { hits := make(HitList, 0) dashQuery := FindPersistedDashboardsQuery{ - Title: query.Title, - UserId: query.UserId, - IsStarred: query.IsStarred, - OrgId: query.OrgId, + Title: query.Title, + UserId: query.UserId, + IsStarred: query.IsStarred, + OrgId: query.OrgId, + DashboardIds: query.DashboardIds, } if err := bus.Dispatch(&dashQuery); err != nil { diff --git a/pkg/services/search/models.go b/pkg/services/search/models.go index 9b8c7627f89..159637013f5 100644 --- a/pkg/services/search/models.go +++ b/pkg/services/search/models.go @@ -25,21 +25,23 @@ func (s HitList) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s HitList) Less(i, j int) bool { return s[i].Title < s[j].Title } type Query struct { - Title string - Tags []string - OrgId int64 - UserId int64 - Limit int - IsStarred bool + Title string + Tags []string + OrgId int64 + UserId int64 + Limit int + IsStarred bool + DashboardIds []int Result HitList } type FindPersistedDashboardsQuery struct { - Title string - OrgId int64 - UserId int64 - IsStarred bool + Title string + OrgId int64 + UserId int64 + IsStarred bool + DashboardIds []int Result HitList } diff --git a/pkg/services/sqlstore/dashboard.go b/pkg/services/sqlstore/dashboard.go index 2a8ff2dc941..f99265754d5 100644 --- a/pkg/services/sqlstore/dashboard.go +++ b/pkg/services/sqlstore/dashboard.go @@ -146,6 +146,19 @@ func SearchDashboards(query *search.FindPersistedDashboardsQuery) error { params = append(params, query.UserId) } + if len(query.DashboardIds) > 0 { + sql.WriteString(" AND (") + for i, dashboardId := range query.DashboardIds { + if i != 0 { + sql.WriteString("OR") + } + + sql.WriteString(" dashboard.id = ?") + params = append(params, dashboardId) + } + sql.WriteString(")") + } + if len(query.Title) > 0 { sql.WriteString(" AND dashboard.title " + dialect.LikeStr() + " ?") params = append(params, "%"+query.Title+"%") diff --git a/pkg/services/sqlstore/dashboard_test.go b/pkg/services/sqlstore/dashboard_test.go index 0d4eb111868..2d35a0742de 100644 --- a/pkg/services/sqlstore/dashboard_test.go +++ b/pkg/services/sqlstore/dashboard_test.go @@ -32,6 +32,8 @@ func TestDashboardDataAccess(t *testing.T) { Convey("Given saved dashboard", func() { savedDash := insertTestDashboard("test dash 23", 1, "prod", "webapp") + insertTestDashboard("test dash 45", 1, "prod") + insertTestDashboard("test dash 67", 1, "prod", "webapp") Convey("Should return dashboard model", func() { So(savedDash.Title, ShouldEqual, "test dash 23") @@ -87,7 +89,7 @@ func TestDashboardDataAccess(t *testing.T) { Convey("Should be able to search for dashboard", func() { query := search.FindPersistedDashboardsQuery{ - Title: "test", + Title: "test dash 23", OrgId: 1, } @@ -99,6 +101,37 @@ func TestDashboardDataAccess(t *testing.T) { So(len(hit.Tags), ShouldEqual, 2) }) + Convey("Should be able to search for dashboard by dashboard ids", func() { + Convey("should be able to find two dashboards by id", func() { + query := search.FindPersistedDashboardsQuery{ + DashboardIds: []int{1, 2}, + OrgId: 1, + } + + err := SearchDashboards(&query) + So(err, ShouldBeNil) + + So(len(query.Result), ShouldEqual, 2) + + hit := query.Result[0] + So(len(hit.Tags), ShouldEqual, 2) + + hit2 := query.Result[1] + So(len(hit2.Tags), ShouldEqual, 1) + }) + + Convey("DashboardIds that does not exists should not cause errors", func() { + query := search.FindPersistedDashboardsQuery{ + DashboardIds: []int{1000}, + OrgId: 1, + } + + err := SearchDashboards(&query) + So(err, ShouldBeNil) + So(len(query.Result), ShouldEqual, 0) + }) + }) + Convey("Should not be able to save dashboard with same name", func() { cmd := m.SaveDashboardCommand{ OrgId: 1, diff --git a/public/app/features/dashboard/dashboardLoaderSrv.js b/public/app/features/dashboard/dashboardLoaderSrv.js index eba0a962629..1af0894b462 100644 --- a/public/app/features/dashboard/dashboardLoaderSrv.js +++ b/public/app/features/dashboard/dashboardLoaderSrv.js @@ -8,7 +8,7 @@ define([ './impression_store', 'app/core/config', ], -function (angular, moment, _, $, kbn, dateMath, impressionStore, config) { +function (angular, moment, _, $, kbn, dateMath, impressionStore) { 'use strict'; var module = angular.module('grafana.services'); @@ -48,12 +48,7 @@ function (angular, moment, _, $, kbn, dateMath, impressionStore, config) { promise.then(function(result) { if (result.meta.dashboardNotFound !== true) { - impressionStore.impressions.addDashboardImpression({ - type: type, - slug: slug, - title: result.dashboard.title, - orgId: config.bootData.user.orgId - }); + impressionStore.impressions.addDashboardImpression(result.dashboard.id); } return result; diff --git a/public/app/features/dashboard/impression_store.ts b/public/app/features/dashboard/impression_store.ts index 7f7ecb9a9ba..6afe763ceac 100644 --- a/public/app/features/dashboard/impression_store.ts +++ b/public/app/features/dashboard/impression_store.ts @@ -6,7 +6,7 @@ import _ from 'lodash'; export class ImpressionsStore { constructor() {} - addDashboardImpression(impression) { + addDashboardImpression(dashboardId) { var impressions = []; if (store.exists("dashboard_impressions")) { impressions = JSON.parse(store.get("dashboard_impressions")); @@ -16,18 +16,13 @@ export class ImpressionsStore { } impressions = impressions.filter((imp) => { - return impression.slug !== imp.slug; + return dashboardId !== imp; }); - impressions.unshift({ - title: impression.title, - slug: impression.slug, - orgId: impression.orgId, - type: impression.type - }); + impressions.unshift(dashboardId); - if (impressions.length > 20) { - impressions.shift(); + if (impressions.length > 50) { + impressions.pop(); } store.set("dashboard_impressions", JSON.stringify(impressions)); } diff --git a/public/app/plugins/panel/dashlist/module.ts b/public/app/plugins/panel/dashlist/module.ts index 0ad573d6330..e899439093c 100644 --- a/public/app/plugins/panel/dashlist/module.ts +++ b/public/app/plugins/panel/dashlist/module.ts @@ -43,22 +43,21 @@ class DashListCtrl extends PanelCtrl { var params: any = {limit: this.panel.limit}; if (this.panel.mode === 'recently viewed') { + var dashboardIds = impressions.getDashboardOpened(); - var dashListNames = impressions.getDashboardOpened().filter((imp) => { - return imp.orgId === config.bootData.user.orgId; + return this.backendSrv.search({ + dashboardIds: impressions.getDashboardOpened(), + limit: this.panel.limit + }).then(result => { + + this.dashList = dashboardIds.map(e => { + return _.find(result, r => { + return r.id === e; + }); + }); + + this.renderingCompleted(); }); - - dashListNames = _.first(dashListNames, params.limit).map((dashboard) => { - return { - title: dashboard.title, - uri: dashboard.type + '/' + dashboard.slug - }; - }); - - - this.dashList = dashListNames; - this.renderingCompleted(); - return; } if (this.panel.mode === 'starred') {