Browse Source

Lots of work on search and dashboard loading, trying to generalize concepts and code, #960

Torkel Ödegaard 10 years ago
parent
commit
b3be51f17f

+ 1 - 0
pkg/api/api.go

@@ -100,6 +100,7 @@ func Register(r *macaron.Macaron) {
 		r.Group("/dashboards", func() {
 			r.Combo("/db/:slug").Get(GetDashboard).Delete(DeleteDashboard)
 			r.Post("/db", reqEditorRole, bind(m.SaveDashboardCommand{}), PostDashboard)
+			r.Get("/file/:file", GetDashboardFromJsonFile)
 			r.Get("/home", GetHomeDashboard)
 		})
 

+ 18 - 1
pkg/api/dashboard.go

@@ -10,6 +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/setting"
 	"github.com/grafana/grafana/pkg/util"
 )
@@ -48,7 +49,7 @@ func GetDashboard(c *middleware.Context) {
 	dash := query.Result
 	dto := dtos.DashboardFullWithMeta{
 		Dashboard: dash.Data,
-		Meta:      dtos.DashboardMeta{IsStarred: isStarred, Slug: slug},
+		Meta:      dtos.DashboardMeta{IsStarred: isStarred, Slug: slug, Type: m.DashTypeDB},
 	}
 
 	c.JSON(200, dto)
@@ -118,3 +119,19 @@ func GetHomeDashboard(c *middleware.Context) {
 
 	c.JSON(200, &dash)
 }
+
+func GetDashboardFromJsonFile(c *middleware.Context) {
+	file := c.Params(":file")
+
+	dashboard := search.GetDashboardFromJsonIndex(file)
+	if dashboard == nil {
+		c.JsonApiErr(404, "Dashboard not found", nil)
+		return
+	}
+
+	dash := dtos.DashboardFullWithMeta{Dashboard: dashboard.Data}
+	dash.Meta.Type = m.DashTypeJson
+	dash.Meta.CanSave = false
+
+	c.JSON(200, &dash)
+}

+ 2 - 0
pkg/api/dtos/models.go

@@ -32,6 +32,8 @@ type DashboardMeta struct {
 	IsStarred  bool      `json:"isStarred,omitempty"`
 	IsHome     bool      `json:"isHome,omitempty"`
 	IsSnapshot bool      `json:"isSnapshot,omitempty"`
+	Type       string    `json:"type,omitempty"`
+	CanSave    bool      `json:"canSave"`
 	Slug       string    `json:"slug"`
 	Expires    time.Time `json:"expires"`
 	Created    time.Time `json:"created"`

+ 6 - 0
pkg/models/dashboards.go

@@ -15,6 +15,12 @@ var (
 	ErrDashboardVersionMismatch    = errors.New("The dashboard has been changed by someone else")
 )
 
+var (
+	DashTypeJson   = "file"
+	DashTypeDB     = "db"
+	DashTypeScript = "script"
+)
+
 // Dashboard model
 type Dashboard struct {
 	Id      int64

+ 2 - 1
pkg/models/search.go

@@ -9,7 +9,8 @@ type SearchResult struct {
 type DashboardSearchHit struct {
 	Id        int64    `json:"id"`
 	Title     string   `json:"title"`
-	Slug      string   `json:"slug"`
+	Uri       string   `json:"uri"`
+	Type      string   `json:"type"`
 	Tags      []string `json:"tags"`
 	IsStarred bool     `json:"isStarred"`
 }

+ 20 - 11
pkg/services/search/json_index.go

@@ -17,11 +17,10 @@ type JsonDashIndex struct {
 }
 
 type JsonDashIndexItem struct {
-	Title      string
 	TitleLower string
-	Tags       []string
 	TagsCsv    string
-	FilePath   string
+	Path       string
+	Dashboard  *m.Dashboard
 }
 
 func NewJsonDashIndex(path string, orgIds string) *JsonDashIndex {
@@ -40,9 +39,9 @@ func (index *JsonDashIndex) Search(query *Query) ([]*m.DashboardSearchHit, error
 	for _, item := range index.items {
 		if strings.Contains(item.TitleLower, query.Title) {
 			results = append(results, &m.DashboardSearchHit{
-				Title: item.Title,
-				Tags:  item.Tags,
-				Slug:  item.FilePath,
+				Title: item.Dashboard.Title,
+				Tags:  item.Dashboard.GetTags(),
+				Uri:   "file/" + item.Path,
 			})
 		}
 	}
@@ -50,6 +49,16 @@ func (index *JsonDashIndex) Search(query *Query) ([]*m.DashboardSearchHit, error
 	return results, nil
 }
 
+func (index *JsonDashIndex) GetDashboard(path string) *m.Dashboard {
+	for _, item := range index.items {
+		if item.Path == path {
+			return item.Dashboard
+		}
+	}
+
+	return nil
+}
+
 func (index *JsonDashIndex) updateIndex() error {
 	log.Info("Updating JSON dashboard index, path: %v", index.path)
 
@@ -102,13 +111,13 @@ func loadDashboardFromFile(filename string) (*JsonDashIndexItem, error) {
 		return nil, err
 	}
 
-	dash := m.NewDashboardFromJson(data)
+	stat, _ := os.Stat(filename)
 
 	item := &JsonDashIndexItem{}
-	item.Title = dash.Title
-	item.TitleLower = strings.ToLower(item.Title)
-	item.Tags = dash.GetTags()
-	item.TagsCsv = strings.Join(item.Tags, ",")
+	item.Dashboard = m.NewDashboardFromJson(data)
+	item.TitleLower = strings.ToLower(item.Dashboard.Title)
+	item.TagsCsv = strings.Join(item.Dashboard.GetTags(), ",")
+	item.Path = stat.Name()
 
 	return item, nil
 }

+ 7 - 0
pkg/services/search/search.go

@@ -87,3 +87,10 @@ func setIsStarredFlagOnSearchResults(userId int64, hits []*m.DashboardSearchHit)
 
 	return nil
 }
+
+func GetDashboardFromJsonIndex(filename string) *m.Dashboard {
+	if jsonDashIndex == nil {
+		return nil
+	}
+	return jsonDashIndex.GetDashboard(filename)
+}

+ 1 - 1
pkg/services/sqlstore/dashboard.go

@@ -175,7 +175,7 @@ func SearchDashboards(query *m.SearchDashboardsQuery) error {
 			hit = &m.DashboardSearchHit{
 				Id:    item.Id,
 				Title: item.Title,
-				Slug:  item.Slug,
+				Uri:   "db/" + item.Slug,
 				Tags:  []string{},
 			}
 			query.Result = append(query.Result, hit)

+ 1 - 1
public/app/controllers/search.js

@@ -70,7 +70,7 @@ function (angular, _, config) {
         $scope.resultCount = results.tagsOnly ? results.tags.length : results.dashboards.length;
         $scope.results.tags = results.tags;
         $scope.results.dashboards = _.map(results.dashboards, function(dash) {
-          dash.url = 'dashboard/db/' + dash.slug;
+          dash.url = 'dashboard/' + dash.uri;
           return dash;
         });
 

+ 1 - 0
public/app/features/panel/panelHelper.js

@@ -22,6 +22,7 @@ function (angular, _, kbn, $) {
     };
 
     this.setTimeRenderStart = function(scope) {
+      scope.timing = scope.timing || {};
       scope.timing.renderStart = new Date().getTime();
     };
 

+ 1 - 1
public/app/panels/dashlist/module.html

@@ -1,7 +1,7 @@
 <grafana-panel>
 	<div class="dashlist">
 	<div class="dashlist-item" ng-repeat="dash in dashList">
-		<a class="dashlist-link" href="dashboard/db/{{dash.slug}}">
+		<a class="dashlist-link" href="dashboard/{{dash.uri}}">
 			<span class="dashlist-title">
 				{{dash.title}}
 			</span>

+ 4 - 18
public/app/routes/all.js

@@ -12,22 +12,7 @@ define([
     $routeProvider
       .when('/', {
         templateUrl: 'app/partials/dashboard.html',
-        controller : 'DashFromDBCtrl',
-        reloadOnSearch: false,
-      })
-      .when('/dashboard/db/:slug', {
-        templateUrl: 'app/partials/dashboard.html',
-        controller : 'DashFromDBCtrl',
-        reloadOnSearch: false,
-      })
-      .when('/dashboard/file/:jsonFile', {
-        templateUrl: 'app/partials/dashboard.html',
-        controller : 'DashFromFileCtrl',
-        reloadOnSearch: false,
-      })
-      .when('/dashboard/script/:jsFile', {
-        templateUrl: 'app/partials/dashboard.html',
-        controller : 'DashFromScriptCtrl',
+        controller : 'LoadDashboardCtrl',
         reloadOnSearch: false,
       })
       .when('/dashboard/import/:file', {
@@ -35,9 +20,10 @@ define([
         controller : 'DashFromImportCtrl',
         reloadOnSearch: false,
       })
-      .when('/dashboard/snapshot/:key', {
+      .when('/dashboard/:type/:slug', {
         templateUrl: 'app/partials/dashboard.html',
-        controller : 'DashFromSnapshotCtrl',
+        controller : 'LoadDashboardCtrl',
+        reloadOnSearch: false,
       })
       .when('/dashboard/solo/db/:slug', {
         templateUrl: 'app/features/panel/partials/soloPanel.html',

+ 54 - 87
public/app/routes/dashLoadControllers.js

@@ -10,12 +10,14 @@ function (angular, _, kbn, moment, $) {
 
   var module = angular.module('grafana.routes');
 
-  module.controller('DashFromDBCtrl', function($scope, $routeParams, backendSrv) {
+  module.controller('LoadDashboardCtrl', function(
+    $scope, $routeParams, backendSrv, dashboardSrv, datasourceSrv, $http, $q, $timeout, contextSrv) {
 
     function dashboardLoadFailed(title) {
       $scope.initDashboard({meta: {}, dashboard: {title: title}}, $scope);
     }
 
+    // Home dashboard
     if (!$routeParams.slug) {
       backendSrv.get('/api/dashboards/home').then(function(result) {
         var meta = result.meta;
@@ -24,90 +26,10 @@ function (angular, _, kbn, moment, $) {
       },function() {
         dashboardLoadFailed('Not found');
       });
-
       return;
     }
 
-    return backendSrv.getDashboard($routeParams.slug).then(function(result) {
-      $scope.initDashboard(result, $scope);
-    }, function() {
-      dashboardLoadFailed('Not found');
-    });
-
-  });
-
-  module.controller('DashFromSnapshotCtrl', function($scope, $routeParams, backendSrv, contextSrv) {
-    //don't show the sidemenu in snapshots.
-    contextSrv.sidemenu = false;
-    backendSrv.get('/api/snapshots/' + $routeParams.key).then(function(result) {
-      $scope.initDashboard(result, $scope);
-    }, function() {
-      $scope.initDashboard({
-        meta: {
-          isSnapshot: true,
-          canSave: false,
-          canEdit: false,
-        },
-        dashboard: {
-          title: 'Snapshot not found'
-        }
-      }, $scope);
-    });
-  });
-
-  module.controller('DashFromImportCtrl', function($scope, $location, alertSrv) {
-    if (!window.grafanaImportDashboard) {
-      alertSrv.set('Not found', 'Cannot reload page with unsaved imported dashboard', 'warning', 7000);
-      $location.path('');
-      return;
-    }
-    $scope.initDashboard({
-      meta: { canShare: false, canStar: false },
-      dashboard: window.grafanaImportDashboard
-    }, $scope);
-  });
-
-  module.controller('NewDashboardCtrl', function($scope) {
-    $scope.initDashboard({
-      meta: { canStar: false, canShare: false },
-      dashboard: {
-        title: "New dashboard",
-        rows: [{ height: '250px', panels:[] }]
-      },
-    }, $scope);
-  });
-
-  module.controller('DashFromFileCtrl', function($scope, $rootScope, $http, $routeParams) {
-
-    var file_load = function(file) {
-      return $http({
-        url: "public/dashboards/"+file.replace(/\.(?!json)/,"/")+'?' + new Date().getTime(),
-        method: "GET",
-        transformResponse: function(response) {
-          return angular.fromJson(response);
-        }
-      }).then(function(result) {
-        if(!result) {
-          return false;
-        }
-        return result.data;
-      },function() {
-        $scope.appEvent('alert-error', ["Dashboard load failed", "Could not load "+file+". Please make sure it exists"]);
-        return false;
-      });
-    };
-
-    file_load($routeParams.jsonFile).then(function(result) {
-      $scope.initDashboard({
-        meta: { canSave: false, canDelete: false },
-        dashboard: result
-      }, $scope);
-    });
-
-  });
-
-  module.controller('DashFromScriptCtrl', function($scope, $rootScope, $http, $routeParams, $q, dashboardSrv, datasourceSrv, $timeout) {
-
+    // Scripted dashboards
     var execute_script = function(result) {
       var services = {
         dashboardSrv: dashboardSrv,
@@ -145,13 +67,58 @@ function (angular, _, kbn, moment, $) {
       });
     };
 
-    script_load($routeParams.jsFile).then(function(result) {
-      $scope.initDashboard({
-        meta: {fromScript: true, canDelete: false, canSave: false},
-        dashboard: result.data
-      }, $scope);
+    function loadScriptedDashboard() {
+      script_load($routeParams.slug).then(function(result) {
+        $scope.initDashboard({
+          meta: {fromScript: true, canDelete: false, canSave: false},
+          dashboard: result.data
+        }, $scope);
+      });
+    }
+
+    if ($routeParams.type === 'script') {
+      loadScriptedDashboard();
+      return;
+    }
+
+    if ($routeParams.type === 'snapshot') {
+      contextSrv.sidemenu = false;
+      backendSrv.get('/api/snapshots/' + $routeParams.slug).then(function(result) {
+        $scope.initDashboard(result, $scope);
+      }, function() {
+        $scope.initDashboard({meta:{isSnapshot: true, canSave: false, canEdit: false}, dashboard: {title: 'Snapshot not found'}}, $scope);
+      });
+      return;
+    }
+
+    return backendSrv.getDashboard($routeParams.type, $routeParams.slug).then(function(result) {
+      $scope.initDashboard(result, $scope);
+    }, function() {
+      dashboardLoadFailed('Not found');
     });
 
   });
 
+  module.controller('DashFromImportCtrl', function($scope, $location, alertSrv) {
+    if (!window.grafanaImportDashboard) {
+      alertSrv.set('Not found', 'Cannot reload page with unsaved imported dashboard', 'warning', 7000);
+      $location.path('');
+      return;
+    }
+    $scope.initDashboard({
+      meta: { canShare: false, canStar: false },
+      dashboard: window.grafanaImportDashboard
+    }, $scope);
+  });
+
+  module.controller('NewDashboardCtrl', function($scope) {
+    $scope.initDashboard({
+      meta: { canStar: false, canShare: false },
+      dashboard: {
+        title: "New dashboard",
+        rows: [{ height: '250px', panels:[] }]
+      },
+    }, $scope);
+  });
+
 });

+ 2 - 2
public/app/services/backendSrv.js

@@ -119,8 +119,8 @@ function (angular, _, config) {
       return this.get('/api/search', query);
     };
 
-    this.getDashboard = function(slug) {
-      return this.get('/api/dashboards/db/' + slug);
+    this.getDashboard = function(type, slug) {
+      return this.get('/api/dashboards/' + type + '/' + slug);
     };
 
     this.saveDashboard = function(dash, options) {

+ 0 - 53
public/dashboards/empty.json

@@ -1,53 +0,0 @@
-{
-  "title": "New Dashboard",
-  "time": {
-    "from": "now-6h",
-    "to": "now"
-  },
-  "templating": {
-    "list": []
-  },
-  "rows": [
-    {
-      "title": "Row1",
-      "height": "250px",
-      "editable": true,
-      "collapse": false,
-      "panels": []
-    }
-  ],
-  "editable": true,
-  "style": "dark",
-  "nav": [
-    {
-      "type": "timepicker",
-      "enable": true,
-      "status": "Stable",
-      "time_options": [
-        "5m",
-        "15m",
-        "1h",
-        "6h",
-        "12h",
-        "24h",
-        "2d",
-        "7d",
-        "30d"
-      ],
-      "refresh_intervals": [
-        "5s",
-        "10s",
-        "30s",
-        "1m",
-        "5m",
-        "15m",
-        "30m",
-        "1h",
-        "2h",
-        "1d"
-      ],
-      "now": true
-    }
-  ],
-  "refresh": false
-}