From 448a8b8d1c879988f8c250f8bffe84ec2ad199f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 13 May 2015 13:36:13 +0200 Subject: [PATCH] Major refactorings around searching, moved to seperate package, trying to move stuff out of models package, extend search support searching different types of entities and different types of dashboards, #960 --- conf/defaults.ini | 3 +- conf/sample.ini | 8 +++ main.go | 2 +- pkg/api/dashboard.go | 2 +- pkg/api/search.go | 2 +- pkg/models/dashboards.go | 10 ++++ pkg/models/search.go | 29 +---------- .../search/search.go => search/handlers.go} | 23 +++----- pkg/{services => }/search/json_index.go | 15 +++--- pkg/{services => }/search/json_index_test.go | 2 +- pkg/search/models.go | 47 +++++++++++++++++ pkg/services/sqlstore/dashboard.go | 11 ++-- pkg/services/sqlstore/dashboard_test.go | 9 ++-- public/app/controllers/search.js | 37 ++++--------- public/app/features/dashlinks/module.js | 4 +- public/app/panels/dashlist/module.html | 2 +- public/app/panels/dashlist/module.js | 2 +- public/app/partials/search.html | 52 +++++++++---------- public/css/less/search.less | 11 +++- 19 files changed, 143 insertions(+), 128 deletions(-) rename pkg/{services/search/search.go => search/handlers.go} (78%) rename pkg/{services => }/search/json_index.go (87%) rename pkg/{services => }/search/json_index_test.go (91%) create mode 100644 pkg/search/models.go diff --git a/conf/defaults.ini b/conf/defaults.ini index b4e5a1ddfae..628df5360e4 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -216,7 +216,6 @@ exchange = grafana_events #################################### Dashboard JSON files ########################## [dashboards.json] enabled = false -path = dashboards -orgs = * +path = /var/lib/grafana/dashboards diff --git a/conf/sample.ini b/conf/sample.ini index fc2d5a1c8f2..df204a7f45d 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -211,3 +211,11 @@ ;enabled = false ;rabbitmq_url = amqp://localhost/ ;exchange = grafana_events + +;#################################### Dashboard JSON files ########################## +[dashboards.json] +;enabled = false +;path = /var/lib/grafana/dashboards + + + diff --git a/main.go b/main.go index e794e4dfe4e..d31979b5ad2 100644 --- a/main.go +++ b/main.go @@ -14,8 +14,8 @@ import ( "github.com/grafana/grafana/pkg/log" "github.com/grafana/grafana/pkg/metrics" "github.com/grafana/grafana/pkg/plugins" + "github.com/grafana/grafana/pkg/search" "github.com/grafana/grafana/pkg/services/eventpublisher" - "github.com/grafana/grafana/pkg/services/search" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/social" diff --git a/pkg/api/dashboard.go b/pkg/api/dashboard.go index 3f05d53f3b5..b439bd67ac7 100644 --- a/pkg/api/dashboard.go +++ b/pkg/api/dashboard.go @@ -10,7 +10,7 @@ import ( "github.com/grafana/grafana/pkg/metrics" "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" - "github.com/grafana/grafana/pkg/services/search" + "github.com/grafana/grafana/pkg/search" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" ) diff --git a/pkg/api/search.go b/pkg/api/search.go index 68b24fca38e..10329f445bd 100644 --- a/pkg/api/search.go +++ b/pkg/api/search.go @@ -3,7 +3,7 @@ package api import ( "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/middleware" - "github.com/grafana/grafana/pkg/services/search" + "github.com/grafana/grafana/pkg/search" ) func Search(c *middleware.Context) { diff --git a/pkg/models/dashboards.go b/pkg/models/dashboards.go index 5d21533f960..b802eba7e1e 100644 --- a/pkg/models/dashboards.go +++ b/pkg/models/dashboards.go @@ -126,3 +126,13 @@ type GetDashboardQuery struct { Result *Dashboard } + +type DashboardTagCloudItem struct { + Term string `json:"term"` + Count int `json:"count"` +} + +type GetDashboardTagsQuery struct { + OrgId int64 + Result []*DashboardTagCloudItem +} diff --git a/pkg/models/search.go b/pkg/models/search.go index 6e6d88ed828..8bd4744f07b 100644 --- a/pkg/models/search.go +++ b/pkg/models/search.go @@ -1,12 +1,6 @@ package models -type SearchResult struct { - Dashboards []*DashboardSearchHit `json:"dashboards"` - Tags []*DashboardTagCloudItem `json:"tags"` - TagsOnly bool `json:"tagsOnly"` -} - -type DashboardSearchHit struct { +type SearchHit struct { Id int64 `json:"id"` Title string `json:"title"` Uri string `json:"uri"` @@ -14,24 +8,3 @@ type DashboardSearchHit struct { Tags []string `json:"tags"` IsStarred bool `json:"isStarred"` } - -type DashboardTagCloudItem struct { - Term string `json:"term"` - Count int `json:"count"` -} - -type SearchDashboardsQuery struct { - Title string - Tag string - OrgId int64 - UserId int64 - Limit int - IsStarred bool - - Result []*DashboardSearchHit -} - -type GetDashboardTagsQuery struct { - OrgId int64 - Result []*DashboardTagCloudItem -} diff --git a/pkg/services/search/search.go b/pkg/search/handlers.go similarity index 78% rename from pkg/services/search/search.go rename to pkg/search/handlers.go index 4ab7d7bd0ba..bbafffb8743 100644 --- a/pkg/services/search/search.go +++ b/pkg/search/handlers.go @@ -2,23 +2,13 @@ package search import ( "path/filepath" + "sort" "github.com/grafana/grafana/pkg/bus" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" ) -type Query struct { - Title string - Tag string - OrgId int64 - UserId int64 - Limit int - IsStarred bool - - Result []*m.DashboardSearchHit -} - var jsonDashIndex *JsonDashIndex func Init() { @@ -33,15 +23,14 @@ func Init() { jsonFilesPath = filepath.Join(setting.HomePath, jsonFilesPath) } - orgIds := jsonIndexCfg.Key("org_ids").String() - jsonDashIndex = NewJsonDashIndex(jsonFilesPath, orgIds) + jsonDashIndex = NewJsonDashIndex(jsonFilesPath) } } func searchHandler(query *Query) error { - hits := make([]*m.DashboardSearchHit, 0) + hits := make(HitList, 0) - dashQuery := m.SearchDashboardsQuery{ + dashQuery := FindPersistedDashboardsQuery{ Title: query.Title, Tag: query.Tag, UserId: query.UserId, @@ -65,6 +54,8 @@ func searchHandler(query *Query) error { hits = append(hits, jsonHits...) } + sort.Sort(hits) + if err := setIsStarredFlagOnSearchResults(query.UserId, hits); err != nil { return err } @@ -73,7 +64,7 @@ func searchHandler(query *Query) error { return nil } -func setIsStarredFlagOnSearchResults(userId int64, hits []*m.DashboardSearchHit) error { +func setIsStarredFlagOnSearchResults(userId int64, hits []*Hit) error { query := m.GetUserStarsQuery{UserId: userId} if err := bus.Dispatch(&query); err != nil { return err diff --git a/pkg/services/search/json_index.go b/pkg/search/json_index.go similarity index 87% rename from pkg/services/search/json_index.go rename to pkg/search/json_index.go index ac8482f77e1..5a500d2f688 100644 --- a/pkg/services/search/json_index.go +++ b/pkg/search/json_index.go @@ -11,9 +11,8 @@ import ( ) type JsonDashIndex struct { - path string - orgsIds []int64 - items []*JsonDashIndexItem + path string + items []*JsonDashIndexItem } type JsonDashIndexItem struct { @@ -23,7 +22,7 @@ type JsonDashIndexItem struct { Dashboard *m.Dashboard } -func NewJsonDashIndex(path string, orgIds string) *JsonDashIndex { +func NewJsonDashIndex(path string) *JsonDashIndex { log.Info("Creating json dashboard index for path: ", path) index := JsonDashIndex{} @@ -32,8 +31,8 @@ func NewJsonDashIndex(path string, orgIds string) *JsonDashIndex { return &index } -func (index *JsonDashIndex) Search(query *Query) ([]*m.DashboardSearchHit, error) { - results := make([]*m.DashboardSearchHit, 0) +func (index *JsonDashIndex) Search(query *Query) ([]*Hit, error) { + results := make([]*Hit, 0) for _, item := range index.items { if len(results) > query.Limit { @@ -49,8 +48,8 @@ func (index *JsonDashIndex) Search(query *Query) ([]*m.DashboardSearchHit, error // add results with matchig title filter if strings.Contains(item.TitleLower, query.Title) { - results = append(results, &m.DashboardSearchHit{ - Type: m.DashTypeJson, + results = append(results, &Hit{ + Type: DashHitJson, Title: item.Dashboard.Title, Tags: item.Dashboard.GetTags(), Uri: "file/" + item.Path, diff --git a/pkg/services/search/json_index_test.go b/pkg/search/json_index_test.go similarity index 91% rename from pkg/services/search/json_index_test.go rename to pkg/search/json_index_test.go index 13add2a667d..9c4d27e6233 100644 --- a/pkg/services/search/json_index_test.go +++ b/pkg/search/json_index_test.go @@ -9,7 +9,7 @@ import ( func TestJsonDashIndex(t *testing.T) { Convey("Given the json dash index", t, func() { - index := NewJsonDashIndex("../../../public/dashboards/", "*") + index := NewJsonDashIndex("../../public/dashboards/", "*") Convey("Should be able to update index", func() { err := index.updateIndex() diff --git a/pkg/search/models.go b/pkg/search/models.go new file mode 100644 index 00000000000..157d9a292e3 --- /dev/null +++ b/pkg/search/models.go @@ -0,0 +1,47 @@ +package search + +type HitType string + +const ( + DashHitDB HitType = "dash-db" + DashHitHome HitType = "dash-home" + DashHitJson HitType = "dash-json" + DashHitScripted HitType = "dash-scripted" +) + +type Hit struct { + Id int64 `json:"id"` + Title string `json:"title"` + Uri string `json:"uri"` + Type HitType `json:"type"` + Tags []string `json:"tags"` + IsStarred bool `json:"isStarred"` +} + +type HitList []*Hit + +func (s HitList) Len() int { return len(s) } +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 + Tag string + OrgId int64 + UserId int64 + Limit int + IsStarred bool + + Result HitList +} + +type FindPersistedDashboardsQuery struct { + Title string + Tag string + OrgId int64 + UserId int64 + Limit int + IsStarred bool + + Result HitList +} diff --git a/pkg/services/sqlstore/dashboard.go b/pkg/services/sqlstore/dashboard.go index 56e462fe2f6..027f2cd2fac 100644 --- a/pkg/services/sqlstore/dashboard.go +++ b/pkg/services/sqlstore/dashboard.go @@ -8,6 +8,7 @@ import ( "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/metrics" m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/search" ) func init() { @@ -119,7 +120,7 @@ type DashboardSearchProjection struct { Term string } -func SearchDashboards(query *m.SearchDashboardsQuery) error { +func SearchDashboards(query *search.FindPersistedDashboardsQuery) error { var sql bytes.Buffer params := make([]interface{}, 0) @@ -166,17 +167,17 @@ func SearchDashboards(query *m.SearchDashboardsQuery) error { return err } - query.Result = make([]*m.DashboardSearchHit, 0) - hits := make(map[int64]*m.DashboardSearchHit) + query.Result = make([]*search.Hit, 0) + hits := make(map[int64]*search.Hit) for _, item := range res { hit, exists := hits[item.Id] if !exists { - hit = &m.DashboardSearchHit{ + hit = &search.Hit{ Id: item.Id, Title: item.Title, Uri: "db/" + item.Slug, - Type: m.DashTypeDB, + Type: search.DashHitDB, Tags: []string{}, } query.Result = append(query.Result, hit) diff --git a/pkg/services/sqlstore/dashboard_test.go b/pkg/services/sqlstore/dashboard_test.go index ad4974af18b..70675f9c42b 100644 --- a/pkg/services/sqlstore/dashboard_test.go +++ b/pkg/services/sqlstore/dashboard_test.go @@ -6,6 +6,7 @@ import ( . "github.com/smartystreets/goconvey/convey" m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/search" ) func insertTestDashboard(title string, orgId int64, tags ...interface{}) *m.Dashboard { @@ -85,7 +86,7 @@ func TestDashboardDataAccess(t *testing.T) { }) Convey("Should be able to search for dashboard", func() { - query := m.SearchDashboardsQuery{ + query := search.FindPersistedDashboardsQuery{ Title: "test", OrgId: 1, } @@ -99,8 +100,8 @@ func TestDashboardDataAccess(t *testing.T) { }) Convey("Should be able to search for dashboards using tags", func() { - query1 := m.SearchDashboardsQuery{Tag: "webapp", OrgId: 1} - query2 := m.SearchDashboardsQuery{Tag: "tagdoesnotexist", OrgId: 1} + query1 := search.FindPersistedDashboardsQuery{Tag: "webapp", OrgId: 1} + query2 := search.FindPersistedDashboardsQuery{Tag: "tagdoesnotexist", OrgId: 1} err := SearchDashboards(&query1) err = SearchDashboards(&query2) @@ -146,7 +147,7 @@ func TestDashboardDataAccess(t *testing.T) { }) Convey("Should be able to search for starred dashboards", func() { - query := m.SearchDashboardsQuery{OrgId: 1, UserId: 10, IsStarred: true} + query := search.FindPersistedDashboardsQuery{OrgId: 1, UserId: 10, IsStarred: true} err := SearchDashboards(&query) So(err, ShouldBeNil) diff --git a/public/app/controllers/search.js b/public/app/controllers/search.js index c4785c6dd8f..9083ef74705 100644 --- a/public/app/controllers/search.js +++ b/public/app/controllers/search.js @@ -40,15 +40,15 @@ function (angular, _, config) { $scope.moveSelection(-1); } if (evt.keyCode === 13) { - if ($scope.query.tagcloud) { - var tag = $scope.results.tags[$scope.selectedIndex]; + if ($scope.tagMode) { + var tag = $scope.results[$scope.selectedIndex]; if (tag) { $scope.filterByTag(tag.term); } return; } - var selectedDash = $scope.results.dashboards[$scope.selectedIndex]; + var selectedDash = $scope.results[$scope.selectedIndex]; if (selectedDash) { $location.search({}); $location.path(selectedDash.url); @@ -57,7 +57,9 @@ function (angular, _, config) { }; $scope.moveSelection = function(direction) { - $scope.selectedIndex = Math.max(Math.min($scope.selectedIndex + direction, $scope.resultCount - 1), 0); + var max = ($scope.results || []).length; + var newIndex = $scope.selectedIndex + direction; + $scope.selectedIndex = ((newIndex %= max) < 0) ? newIndex + max : newIndex; }; $scope.searchDashboards = function() { @@ -68,14 +70,13 @@ function (angular, _, config) { return backendSrv.search($scope.query).then(function(results) { if (localSearchId < $scope.currentSearchId) { return; } - $scope.resultCount = results.length; $scope.results = _.map(results, function(dash) { dash.url = 'dashboard/' + dash.uri; return dash; }); if ($scope.queryHasNoFilters()) { - $scope.results.unshift({ title: 'Home', url: config.appSubUrl + '/', isHome: true }); + $scope.results.unshift({ title: 'Home', url: config.appSubUrl + '/', type: 'dash-home' }); } }); }; @@ -97,10 +98,10 @@ function (angular, _, config) { }; $scope.getTags = function() { - $scope.tagsMode = true; return backendSrv.get('/api/dashboards/tags').then(function(results) { - $scope.resultCount = results.length; + $scope.tagsMode = true; $scope.results = results; + $scope.giveSearchFocus = $scope.giveSearchFocus + 1; }); }; @@ -116,26 +117,6 @@ function (angular, _, config) { $scope.searchDashboards(); }; - $scope.addMetricToCurrentDashboard = function (metricId) { - $scope.dashboard.rows.push({ - title: '', - height: '250px', - editable: true, - panels: [ - { - type: 'graphite', - title: 'test', - span: 12, - targets: [{ target: metricId }] - } - ] - }); - }; - - $scope.toggleImport = function () { - $scope.showImport = !$scope.showImport; - }; - $scope.newDashboard = function() { $location.url('dashboard/new'); }; diff --git a/public/app/features/dashlinks/module.js b/public/app/features/dashlinks/module.js index fbf5104799c..e33d5406fc2 100644 --- a/public/app/features/dashlinks/module.js +++ b/public/app/features/dashlinks/module.js @@ -133,12 +133,12 @@ function (angular, _) { $scope.searchDashboards = function(link) { return backendSrv.search({tag: link.tag}).then(function(results) { - return _.reduce(results.dashboards, function(memo, dash) { + return _.reduce(results, function(memo, dash) { // do not add current dashboard if (dash.id !== currentDashId) { memo.push({ title: dash.title, - url: 'dashboard/db/'+ dash.slug, + url: 'dashboard/' + dash.uri, icon: 'fa fa-th-large', keepTime: link.keepTime, includeVars: link.includeVars diff --git a/public/app/panels/dashlist/module.html b/public/app/panels/dashlist/module.html index a7b114b31d2..de0e23a9ea5 100644 --- a/public/app/panels/dashlist/module.html +++ b/public/app/panels/dashlist/module.html @@ -1,7 +1,7 @@ -
-
-
-
- + -
-
No dashboards matching your query were found.
+
+
No dashboards matching your query were found.
- + - - - {{tag}} - - + + + {{tag}} + + - - - - - -
+ + + + +
diff --git a/public/css/less/search.less b/public/css/less/search.less index 7182333bd16..b72a7ca0e70 100644 --- a/public/css/less/search.less +++ b/public/css/less/search.less @@ -41,7 +41,7 @@ display: block; line-height: 28px; - .search-result-item:hover, .search-result-item.selected { + .search-item:hover, .search-item.selected { background-color: @grafanaListHighlight; } @@ -67,12 +67,19 @@ } } - .search-result-item { + .search-item { display: block; padding: 3px 10px; white-space: nowrap; background-color: @grafanaListBackground; margin-bottom: 4px; + .search-result-icon:before { + content: "\f009"; + } + + &.search-item-dash-home .search-result-icon:before { + content: "\f015"; + } } .search-result-tags {