mirror of
https://github.com/grafana/grafana.git
synced 2025-02-16 18:34:52 -06:00
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
This commit is contained in:
parent
c8146e759f
commit
448a8b8d1c
@ -216,7 +216,6 @@ exchange = grafana_events
|
|||||||
#################################### Dashboard JSON files ##########################
|
#################################### Dashboard JSON files ##########################
|
||||||
[dashboards.json]
|
[dashboards.json]
|
||||||
enabled = false
|
enabled = false
|
||||||
path = dashboards
|
path = /var/lib/grafana/dashboards
|
||||||
orgs = *
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -211,3 +211,11 @@
|
|||||||
;enabled = false
|
;enabled = false
|
||||||
;rabbitmq_url = amqp://localhost/
|
;rabbitmq_url = amqp://localhost/
|
||||||
;exchange = grafana_events
|
;exchange = grafana_events
|
||||||
|
|
||||||
|
;#################################### Dashboard JSON files ##########################
|
||||||
|
[dashboards.json]
|
||||||
|
;enabled = false
|
||||||
|
;path = /var/lib/grafana/dashboards
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
2
main.go
2
main.go
@ -14,8 +14,8 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/log"
|
"github.com/grafana/grafana/pkg/log"
|
||||||
"github.com/grafana/grafana/pkg/metrics"
|
"github.com/grafana/grafana/pkg/metrics"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
"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/eventpublisher"
|
||||||
"github.com/grafana/grafana/pkg/services/search"
|
|
||||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
"github.com/grafana/grafana/pkg/social"
|
"github.com/grafana/grafana/pkg/social"
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/metrics"
|
"github.com/grafana/grafana/pkg/metrics"
|
||||||
"github.com/grafana/grafana/pkg/middleware"
|
"github.com/grafana/grafana/pkg/middleware"
|
||||||
m "github.com/grafana/grafana/pkg/models"
|
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/setting"
|
||||||
"github.com/grafana/grafana/pkg/util"
|
"github.com/grafana/grafana/pkg/util"
|
||||||
)
|
)
|
||||||
|
@ -3,7 +3,7 @@ package api
|
|||||||
import (
|
import (
|
||||||
"github.com/grafana/grafana/pkg/bus"
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
"github.com/grafana/grafana/pkg/middleware"
|
"github.com/grafana/grafana/pkg/middleware"
|
||||||
"github.com/grafana/grafana/pkg/services/search"
|
"github.com/grafana/grafana/pkg/search"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Search(c *middleware.Context) {
|
func Search(c *middleware.Context) {
|
||||||
|
@ -126,3 +126,13 @@ type GetDashboardQuery struct {
|
|||||||
|
|
||||||
Result *Dashboard
|
Result *Dashboard
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DashboardTagCloudItem struct {
|
||||||
|
Term string `json:"term"`
|
||||||
|
Count int `json:"count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetDashboardTagsQuery struct {
|
||||||
|
OrgId int64
|
||||||
|
Result []*DashboardTagCloudItem
|
||||||
|
}
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
type SearchResult struct {
|
type SearchHit struct {
|
||||||
Dashboards []*DashboardSearchHit `json:"dashboards"`
|
|
||||||
Tags []*DashboardTagCloudItem `json:"tags"`
|
|
||||||
TagsOnly bool `json:"tagsOnly"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DashboardSearchHit struct {
|
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Uri string `json:"uri"`
|
Uri string `json:"uri"`
|
||||||
@ -14,24 +8,3 @@ type DashboardSearchHit struct {
|
|||||||
Tags []string `json:"tags"`
|
Tags []string `json:"tags"`
|
||||||
IsStarred bool `json:"isStarred"`
|
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
|
|
||||||
}
|
|
||||||
|
@ -2,23 +2,13 @@ package search
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/bus"
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
m "github.com/grafana/grafana/pkg/models"
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"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
|
var jsonDashIndex *JsonDashIndex
|
||||||
|
|
||||||
func Init() {
|
func Init() {
|
||||||
@ -33,15 +23,14 @@ func Init() {
|
|||||||
jsonFilesPath = filepath.Join(setting.HomePath, jsonFilesPath)
|
jsonFilesPath = filepath.Join(setting.HomePath, jsonFilesPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
orgIds := jsonIndexCfg.Key("org_ids").String()
|
jsonDashIndex = NewJsonDashIndex(jsonFilesPath)
|
||||||
jsonDashIndex = NewJsonDashIndex(jsonFilesPath, orgIds)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func searchHandler(query *Query) error {
|
func searchHandler(query *Query) error {
|
||||||
hits := make([]*m.DashboardSearchHit, 0)
|
hits := make(HitList, 0)
|
||||||
|
|
||||||
dashQuery := m.SearchDashboardsQuery{
|
dashQuery := FindPersistedDashboardsQuery{
|
||||||
Title: query.Title,
|
Title: query.Title,
|
||||||
Tag: query.Tag,
|
Tag: query.Tag,
|
||||||
UserId: query.UserId,
|
UserId: query.UserId,
|
||||||
@ -65,6 +54,8 @@ func searchHandler(query *Query) error {
|
|||||||
hits = append(hits, jsonHits...)
|
hits = append(hits, jsonHits...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sort.Sort(hits)
|
||||||
|
|
||||||
if err := setIsStarredFlagOnSearchResults(query.UserId, hits); err != nil {
|
if err := setIsStarredFlagOnSearchResults(query.UserId, hits); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -73,7 +64,7 @@ func searchHandler(query *Query) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setIsStarredFlagOnSearchResults(userId int64, hits []*m.DashboardSearchHit) error {
|
func setIsStarredFlagOnSearchResults(userId int64, hits []*Hit) error {
|
||||||
query := m.GetUserStarsQuery{UserId: userId}
|
query := m.GetUserStarsQuery{UserId: userId}
|
||||||
if err := bus.Dispatch(&query); err != nil {
|
if err := bus.Dispatch(&query); err != nil {
|
||||||
return err
|
return err
|
@ -11,9 +11,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type JsonDashIndex struct {
|
type JsonDashIndex struct {
|
||||||
path string
|
path string
|
||||||
orgsIds []int64
|
items []*JsonDashIndexItem
|
||||||
items []*JsonDashIndexItem
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type JsonDashIndexItem struct {
|
type JsonDashIndexItem struct {
|
||||||
@ -23,7 +22,7 @@ type JsonDashIndexItem struct {
|
|||||||
Dashboard *m.Dashboard
|
Dashboard *m.Dashboard
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewJsonDashIndex(path string, orgIds string) *JsonDashIndex {
|
func NewJsonDashIndex(path string) *JsonDashIndex {
|
||||||
log.Info("Creating json dashboard index for path: ", path)
|
log.Info("Creating json dashboard index for path: ", path)
|
||||||
|
|
||||||
index := JsonDashIndex{}
|
index := JsonDashIndex{}
|
||||||
@ -32,8 +31,8 @@ func NewJsonDashIndex(path string, orgIds string) *JsonDashIndex {
|
|||||||
return &index
|
return &index
|
||||||
}
|
}
|
||||||
|
|
||||||
func (index *JsonDashIndex) Search(query *Query) ([]*m.DashboardSearchHit, error) {
|
func (index *JsonDashIndex) Search(query *Query) ([]*Hit, error) {
|
||||||
results := make([]*m.DashboardSearchHit, 0)
|
results := make([]*Hit, 0)
|
||||||
|
|
||||||
for _, item := range index.items {
|
for _, item := range index.items {
|
||||||
if len(results) > query.Limit {
|
if len(results) > query.Limit {
|
||||||
@ -49,8 +48,8 @@ func (index *JsonDashIndex) Search(query *Query) ([]*m.DashboardSearchHit, error
|
|||||||
|
|
||||||
// add results with matchig title filter
|
// add results with matchig title filter
|
||||||
if strings.Contains(item.TitleLower, query.Title) {
|
if strings.Contains(item.TitleLower, query.Title) {
|
||||||
results = append(results, &m.DashboardSearchHit{
|
results = append(results, &Hit{
|
||||||
Type: m.DashTypeJson,
|
Type: DashHitJson,
|
||||||
Title: item.Dashboard.Title,
|
Title: item.Dashboard.Title,
|
||||||
Tags: item.Dashboard.GetTags(),
|
Tags: item.Dashboard.GetTags(),
|
||||||
Uri: "file/" + item.Path,
|
Uri: "file/" + item.Path,
|
@ -9,7 +9,7 @@ import (
|
|||||||
func TestJsonDashIndex(t *testing.T) {
|
func TestJsonDashIndex(t *testing.T) {
|
||||||
|
|
||||||
Convey("Given the json dash index", t, func() {
|
Convey("Given the json dash index", t, func() {
|
||||||
index := NewJsonDashIndex("../../../public/dashboards/", "*")
|
index := NewJsonDashIndex("../../public/dashboards/", "*")
|
||||||
|
|
||||||
Convey("Should be able to update index", func() {
|
Convey("Should be able to update index", func() {
|
||||||
err := index.updateIndex()
|
err := index.updateIndex()
|
47
pkg/search/models.go
Normal file
47
pkg/search/models.go
Normal file
@ -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
|
||||||
|
}
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/bus"
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
"github.com/grafana/grafana/pkg/metrics"
|
"github.com/grafana/grafana/pkg/metrics"
|
||||||
m "github.com/grafana/grafana/pkg/models"
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
|
"github.com/grafana/grafana/pkg/search"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -119,7 +120,7 @@ type DashboardSearchProjection struct {
|
|||||||
Term string
|
Term string
|
||||||
}
|
}
|
||||||
|
|
||||||
func SearchDashboards(query *m.SearchDashboardsQuery) error {
|
func SearchDashboards(query *search.FindPersistedDashboardsQuery) error {
|
||||||
var sql bytes.Buffer
|
var sql bytes.Buffer
|
||||||
params := make([]interface{}, 0)
|
params := make([]interface{}, 0)
|
||||||
|
|
||||||
@ -166,17 +167,17 @@ func SearchDashboards(query *m.SearchDashboardsQuery) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
query.Result = make([]*m.DashboardSearchHit, 0)
|
query.Result = make([]*search.Hit, 0)
|
||||||
hits := make(map[int64]*m.DashboardSearchHit)
|
hits := make(map[int64]*search.Hit)
|
||||||
|
|
||||||
for _, item := range res {
|
for _, item := range res {
|
||||||
hit, exists := hits[item.Id]
|
hit, exists := hits[item.Id]
|
||||||
if !exists {
|
if !exists {
|
||||||
hit = &m.DashboardSearchHit{
|
hit = &search.Hit{
|
||||||
Id: item.Id,
|
Id: item.Id,
|
||||||
Title: item.Title,
|
Title: item.Title,
|
||||||
Uri: "db/" + item.Slug,
|
Uri: "db/" + item.Slug,
|
||||||
Type: m.DashTypeDB,
|
Type: search.DashHitDB,
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
}
|
}
|
||||||
query.Result = append(query.Result, hit)
|
query.Result = append(query.Result, hit)
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
m "github.com/grafana/grafana/pkg/models"
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
|
"github.com/grafana/grafana/pkg/search"
|
||||||
)
|
)
|
||||||
|
|
||||||
func insertTestDashboard(title string, orgId int64, tags ...interface{}) *m.Dashboard {
|
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() {
|
Convey("Should be able to search for dashboard", func() {
|
||||||
query := m.SearchDashboardsQuery{
|
query := search.FindPersistedDashboardsQuery{
|
||||||
Title: "test",
|
Title: "test",
|
||||||
OrgId: 1,
|
OrgId: 1,
|
||||||
}
|
}
|
||||||
@ -99,8 +100,8 @@ func TestDashboardDataAccess(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
Convey("Should be able to search for dashboards using tags", func() {
|
Convey("Should be able to search for dashboards using tags", func() {
|
||||||
query1 := m.SearchDashboardsQuery{Tag: "webapp", OrgId: 1}
|
query1 := search.FindPersistedDashboardsQuery{Tag: "webapp", OrgId: 1}
|
||||||
query2 := m.SearchDashboardsQuery{Tag: "tagdoesnotexist", OrgId: 1}
|
query2 := search.FindPersistedDashboardsQuery{Tag: "tagdoesnotexist", OrgId: 1}
|
||||||
|
|
||||||
err := SearchDashboards(&query1)
|
err := SearchDashboards(&query1)
|
||||||
err = SearchDashboards(&query2)
|
err = SearchDashboards(&query2)
|
||||||
@ -146,7 +147,7 @@ func TestDashboardDataAccess(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
Convey("Should be able to search for starred dashboards", func() {
|
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)
|
err := SearchDashboards(&query)
|
||||||
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
@ -40,15 +40,15 @@ function (angular, _, config) {
|
|||||||
$scope.moveSelection(-1);
|
$scope.moveSelection(-1);
|
||||||
}
|
}
|
||||||
if (evt.keyCode === 13) {
|
if (evt.keyCode === 13) {
|
||||||
if ($scope.query.tagcloud) {
|
if ($scope.tagMode) {
|
||||||
var tag = $scope.results.tags[$scope.selectedIndex];
|
var tag = $scope.results[$scope.selectedIndex];
|
||||||
if (tag) {
|
if (tag) {
|
||||||
$scope.filterByTag(tag.term);
|
$scope.filterByTag(tag.term);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var selectedDash = $scope.results.dashboards[$scope.selectedIndex];
|
var selectedDash = $scope.results[$scope.selectedIndex];
|
||||||
if (selectedDash) {
|
if (selectedDash) {
|
||||||
$location.search({});
|
$location.search({});
|
||||||
$location.path(selectedDash.url);
|
$location.path(selectedDash.url);
|
||||||
@ -57,7 +57,9 @@ function (angular, _, config) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.moveSelection = function(direction) {
|
$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() {
|
$scope.searchDashboards = function() {
|
||||||
@ -68,14 +70,13 @@ function (angular, _, config) {
|
|||||||
return backendSrv.search($scope.query).then(function(results) {
|
return backendSrv.search($scope.query).then(function(results) {
|
||||||
if (localSearchId < $scope.currentSearchId) { return; }
|
if (localSearchId < $scope.currentSearchId) { return; }
|
||||||
|
|
||||||
$scope.resultCount = results.length;
|
|
||||||
$scope.results = _.map(results, function(dash) {
|
$scope.results = _.map(results, function(dash) {
|
||||||
dash.url = 'dashboard/' + dash.uri;
|
dash.url = 'dashboard/' + dash.uri;
|
||||||
return dash;
|
return dash;
|
||||||
});
|
});
|
||||||
|
|
||||||
if ($scope.queryHasNoFilters()) {
|
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.getTags = function() {
|
||||||
$scope.tagsMode = true;
|
|
||||||
return backendSrv.get('/api/dashboards/tags').then(function(results) {
|
return backendSrv.get('/api/dashboards/tags').then(function(results) {
|
||||||
$scope.resultCount = results.length;
|
$scope.tagsMode = true;
|
||||||
$scope.results = results;
|
$scope.results = results;
|
||||||
|
$scope.giveSearchFocus = $scope.giveSearchFocus + 1;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -116,26 +117,6 @@ function (angular, _, config) {
|
|||||||
$scope.searchDashboards();
|
$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() {
|
$scope.newDashboard = function() {
|
||||||
$location.url('dashboard/new');
|
$location.url('dashboard/new');
|
||||||
};
|
};
|
||||||
|
@ -133,12 +133,12 @@ function (angular, _) {
|
|||||||
|
|
||||||
$scope.searchDashboards = function(link) {
|
$scope.searchDashboards = function(link) {
|
||||||
return backendSrv.search({tag: link.tag}).then(function(results) {
|
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
|
// do not add current dashboard
|
||||||
if (dash.id !== currentDashId) {
|
if (dash.id !== currentDashId) {
|
||||||
memo.push({
|
memo.push({
|
||||||
title: dash.title,
|
title: dash.title,
|
||||||
url: 'dashboard/db/'+ dash.slug,
|
url: 'dashboard/' + dash.uri,
|
||||||
icon: 'fa fa-th-large',
|
icon: 'fa fa-th-large',
|
||||||
keepTime: link.keepTime,
|
keepTime: link.keepTime,
|
||||||
includeVars: link.includeVars
|
includeVars: link.includeVars
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<grafana-panel>
|
<grafana-panel>
|
||||||
<div class="dashlist">
|
<div class="dashlist">
|
||||||
<div class="dashlist-item" ng-repeat="dash in dashList">
|
<div class="dashlist-item" ng-repeat="dash in dashList">
|
||||||
<a class="dashlist-link" href="dashboard/{{dash.uri}}">
|
<a class="dashlist-link dashlist-link-{{dash.type}}" href="dashboard/{{dash.uri}}">
|
||||||
<span class="dashlist-title">
|
<span class="dashlist-title">
|
||||||
{{dash.title}}
|
{{dash.title}}
|
||||||
</span>
|
</span>
|
||||||
|
@ -62,7 +62,7 @@ function (angular, app, _, config, PanelMeta) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return backendSrv.search(params).then(function(result) {
|
return backendSrv.search(params).then(function(result) {
|
||||||
$scope.dashList = result.dashboards;
|
$scope.dashList = result;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,41 +24,39 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-if="!showImport">
|
<div class="search-results-container" ng-if="tagsMode">
|
||||||
<div class="search-results-container" ng-if="tagsMode">
|
<div class="row">
|
||||||
<div class="row">
|
<div class="span6 offset1">
|
||||||
<div class="span6 offset1">
|
<div ng-repeat="tag in results" class="pointer" style="width: 180px; float: left;"
|
||||||
<div ng-repeat="tag in results" class="pointer" style="width: 180px; float: left;"
|
ng-class="{'selected': $index === selectedIndex }"
|
||||||
ng-class="{'selected': $index === selectedIndex }"
|
ng-click="filterByTag(tag.term, $event)">
|
||||||
ng-click="filterByTag(tag.term, $event)">
|
<a class="search-result-tag label label-tag" tag-color-from-name tag="tag.term">
|
||||||
<a class="search-result-tag label label-tag" tag-color-from-name tag="tag.term">
|
<i class="fa fa-tag"></i>
|
||||||
<i class="fa fa-tag"></i>
|
<span>{{tag.term}} ({{tag.count}})</span>
|
||||||
<span>{{tag.term}} ({{tag.count}})</span>
|
</a>
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="search-results-container" ng-if="!tagsMode">
|
<div class="search-results-container" ng-if="!tagsMode">
|
||||||
<h6 ng-hide="results.length">No dashboards matching your query were found.</h6>
|
<h6 ng-hide="results.length">No dashboards matching your query were found.</h6>
|
||||||
|
|
||||||
<a class="search-result-item pointer search-result-item-{{row.type}}" bindonce ng-repeat="row in results"
|
<a class="search-item pointer search-item-{{row.type}}" bindonce ng-repeat="row in results"
|
||||||
ng-class="{'selected': $index == selectedIndex}" ng-href="{{row.url}}">
|
ng-class="{'selected': $index == selectedIndex}" ng-href="{{row.url}}">
|
||||||
|
|
||||||
<span class="search-result-tags">
|
<span class="search-result-tags">
|
||||||
<span ng-click="filterByTag(tag, $event)" ng-repeat="tag in row.tags" tag-color-from-name tag="tag" class="label label-tag">
|
<span ng-click="filterByTag(tag, $event)" ng-repeat="tag in row.tags" tag-color-from-name tag="tag" class="label label-tag">
|
||||||
{{tag}}
|
{{tag}}
|
||||||
</span>
|
|
||||||
<i class="fa" ng-class="{'fa-star': row.isStarred, 'fa-star-o': !row.isStarred}"></i>
|
|
||||||
</span>
|
</span>
|
||||||
|
<i class="fa" ng-class="{'fa-star': row.isStarred, 'fa-star-o': !row.isStarred}"></i>
|
||||||
|
</span>
|
||||||
|
|
||||||
<span class="search-result-link">
|
<span class="search-result-link">
|
||||||
<i class="search-result-icon"></i>
|
<i class="fa search-result-icon"></i>
|
||||||
<span bo-text="row.title"></span>
|
<span bo-text="row.title"></span>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="search-button-row">
|
<div class="search-button-row">
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
display: block;
|
display: block;
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
|
|
||||||
.search-result-item:hover, .search-result-item.selected {
|
.search-item:hover, .search-item.selected {
|
||||||
background-color: @grafanaListHighlight;
|
background-color: @grafanaListHighlight;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,12 +67,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-result-item {
|
.search-item {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 3px 10px;
|
padding: 3px 10px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
background-color: @grafanaListBackground;
|
background-color: @grafanaListBackground;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
|
.search-result-icon:before {
|
||||||
|
content: "\f009";
|
||||||
|
}
|
||||||
|
|
||||||
|
&.search-item-dash-home .search-result-icon:before {
|
||||||
|
content: "\f015";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-result-tags {
|
.search-result-tags {
|
||||||
|
Loading…
Reference in New Issue
Block a user