mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge remote-tracking branch 'origin/7883_frontend_step' into 7883_backend
* origin/7883_frontend_step: dashboards: make scripted dashboards work using the old legacy urls dashboards: redirect from old url used to load dashboard to new url dashboards: add new default frontend route for rendering a dashboard panel dashboards: fix links to recently viewed and starred dashboards dashboards: use new *url* prop from dashboard search for linking to dashboards dashboards: when saving dashboard redirect if url changes dashboards: add new default frontend route for loading a dashboard dashboards: return url in response to save dashboard. #7883
This commit is contained in:
commit
9aa488c084
@ -15,6 +15,8 @@ func (hs *HttpServer) registerRoutes() {
|
|||||||
reqGrafanaAdmin := middleware.Auth(&middleware.AuthOptions{ReqSignedIn: true, ReqGrafanaAdmin: true})
|
reqGrafanaAdmin := middleware.Auth(&middleware.AuthOptions{ReqSignedIn: true, ReqGrafanaAdmin: true})
|
||||||
reqEditorRole := middleware.RoleAuth(m.ROLE_EDITOR, m.ROLE_ADMIN)
|
reqEditorRole := middleware.RoleAuth(m.ROLE_EDITOR, m.ROLE_ADMIN)
|
||||||
reqOrgAdmin := middleware.RoleAuth(m.ROLE_ADMIN)
|
reqOrgAdmin := middleware.RoleAuth(m.ROLE_ADMIN)
|
||||||
|
redirectFromLegacyDashboardUrl := middleware.RedirectFromLegacyDashboardUrl()
|
||||||
|
redirectFromLegacyDashboardSoloUrl := middleware.RedirectFromLegacyDashboardSoloUrl()
|
||||||
quota := middleware.Quota
|
quota := middleware.Quota
|
||||||
bind := binding.Bind
|
bind := binding.Bind
|
||||||
|
|
||||||
@ -63,9 +65,13 @@ func (hs *HttpServer) registerRoutes() {
|
|||||||
r.Get("/plugins/:id/edit", reqSignedIn, Index)
|
r.Get("/plugins/:id/edit", reqSignedIn, Index)
|
||||||
r.Get("/plugins/:id/page/:page", reqSignedIn, Index)
|
r.Get("/plugins/:id/page/:page", reqSignedIn, Index)
|
||||||
|
|
||||||
r.Get("/dashboard/*", reqSignedIn, Index)
|
r.Get("/d/:uid/:slug", reqSignedIn, Index)
|
||||||
|
r.Get("/dashboard/db/:slug", reqSignedIn, redirectFromLegacyDashboardUrl, Index)
|
||||||
|
r.Get("/dashboard/script/*", reqSignedIn, Index)
|
||||||
r.Get("/dashboard-solo/snapshot/*", Index)
|
r.Get("/dashboard-solo/snapshot/*", Index)
|
||||||
r.Get("/dashboard-solo/*", reqSignedIn, Index)
|
r.Get("/d-solo/:uid/:slug", reqSignedIn, Index)
|
||||||
|
r.Get("/dashboard-solo/db/:slug", reqSignedIn, redirectFromLegacyDashboardSoloUrl, Index)
|
||||||
|
r.Get("/dashboard-solo/script/*", reqSignedIn, Index)
|
||||||
r.Get("/import/dashboard", reqSignedIn, Index)
|
r.Get("/import/dashboard", reqSignedIn, Index)
|
||||||
r.Get("/dashboards/", reqSignedIn, Index)
|
r.Get("/dashboards/", reqSignedIn, Index)
|
||||||
r.Get("/dashboards/*", reqSignedIn, Index)
|
r.Get("/dashboards/*", reqSignedIn, Index)
|
||||||
|
@ -238,8 +238,22 @@ func PostDashboard(c *middleware.Context, cmd m.SaveDashboardCommand) Response {
|
|||||||
return ApiError(500, "Invalid alert data. Cannot save dashboard", err)
|
return ApiError(500, "Invalid alert data. Cannot save dashboard", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var url string
|
||||||
|
if dash.IsFolder {
|
||||||
|
url = m.GetFolderUrl(dashboard.Uid, dashboard.Slug)
|
||||||
|
} else {
|
||||||
|
url = m.GetDashboardUrl(dashboard.Uid, dashboard.Slug)
|
||||||
|
}
|
||||||
|
|
||||||
c.TimeRequest(metrics.M_Api_Dashboard_Save)
|
c.TimeRequest(metrics.M_Api_Dashboard_Save)
|
||||||
return Json(200, util.DynMap{"status": "success", "slug": dashboard.Slug, "version": dashboard.Version, "id": dashboard.Id, "uid": dashboard.Uid})
|
return Json(200, util.DynMap{
|
||||||
|
"status": "success",
|
||||||
|
"slug": dashboard.Slug,
|
||||||
|
"version": dashboard.Version,
|
||||||
|
"id": dashboard.Id,
|
||||||
|
"uid": dashboard.Uid,
|
||||||
|
"url": url,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetHomeDashboard(c *middleware.Context) Response {
|
func GetHomeDashboard(c *middleware.Context) Response {
|
||||||
|
@ -180,13 +180,7 @@ func TestDashboardApiEndpoint(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
postDashboardScenario("When calling POST on", "/api/dashboards", "/api/dashboards", role, cmd, func(sc *scenarioContext) {
|
postDashboardScenario("When calling POST on", "/api/dashboards", "/api/dashboards", role, cmd, func(sc *scenarioContext) {
|
||||||
CallPostDashboard(sc)
|
CallPostDashboardShouldReturnSuccess(sc)
|
||||||
So(sc.resp.Code, ShouldEqual, 200)
|
|
||||||
result := sc.ToJson()
|
|
||||||
So(result.Get("status").MustString(), ShouldEqual, "success")
|
|
||||||
So(result.Get("id").MustInt64(), ShouldBeGreaterThan, 0)
|
|
||||||
So(result.Get("uid").MustString(), ShouldNotBeNil)
|
|
||||||
So(result.Get("slug").MustString(), ShouldNotBeNil)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("When saving a dashboard folder in another folder", func() {
|
Convey("When saving a dashboard folder in another folder", func() {
|
||||||
@ -423,13 +417,7 @@ func TestDashboardApiEndpoint(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
postDashboardScenario("When calling POST on", "/api/dashboards", "/api/dashboards", role, cmd, func(sc *scenarioContext) {
|
postDashboardScenario("When calling POST on", "/api/dashboards", "/api/dashboards", role, cmd, func(sc *scenarioContext) {
|
||||||
CallPostDashboard(sc)
|
CallPostDashboardShouldReturnSuccess(sc)
|
||||||
So(sc.resp.Code, ShouldEqual, 200)
|
|
||||||
result := sc.ToJson()
|
|
||||||
So(result.Get("status").MustString(), ShouldEqual, "success")
|
|
||||||
So(result.Get("id").MustInt64(), ShouldBeGreaterThan, 0)
|
|
||||||
So(result.Get("uid").MustString(), ShouldNotBeNil)
|
|
||||||
So(result.Get("slug").MustString(), ShouldNotBeNil)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -544,13 +532,7 @@ func TestDashboardApiEndpoint(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
postDashboardScenario("When calling POST on", "/api/dashboards", "/api/dashboards", role, cmd, func(sc *scenarioContext) {
|
postDashboardScenario("When calling POST on", "/api/dashboards", "/api/dashboards", role, cmd, func(sc *scenarioContext) {
|
||||||
CallPostDashboard(sc)
|
CallPostDashboardShouldReturnSuccess(sc)
|
||||||
So(sc.resp.Code, ShouldEqual, 200)
|
|
||||||
result := sc.ToJson()
|
|
||||||
So(result.Get("status").MustString(), ShouldEqual, "success")
|
|
||||||
So(result.Get("id").MustInt64(), ShouldBeGreaterThan, 0)
|
|
||||||
So(result.Get("uid").MustString(), ShouldNotBeNil)
|
|
||||||
So(result.Get("slug").MustString(), ShouldNotBeNil)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -678,6 +660,18 @@ func CallPostDashboard(sc *scenarioContext) {
|
|||||||
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
|
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CallPostDashboardShouldReturnSuccess(sc *scenarioContext) {
|
||||||
|
CallPostDashboard(sc)
|
||||||
|
|
||||||
|
So(sc.resp.Code, ShouldEqual, 200)
|
||||||
|
result := sc.ToJson()
|
||||||
|
So(result.Get("status").MustString(), ShouldEqual, "success")
|
||||||
|
So(result.Get("id").MustInt64(), ShouldBeGreaterThan, 0)
|
||||||
|
So(result.Get("uid").MustString(), ShouldNotBeNil)
|
||||||
|
So(result.Get("slug").MustString(), ShouldNotBeNil)
|
||||||
|
So(result.Get("url").MustString(), ShouldNotBeNil)
|
||||||
|
}
|
||||||
|
|
||||||
func postDashboardScenario(desc string, url string, routePattern string, role m.RoleType, cmd m.SaveDashboardCommand, fn scenarioFunc) {
|
func postDashboardScenario(desc string, url string, routePattern string, role m.RoleType, cmd m.SaveDashboardCommand, fn scenarioFunc) {
|
||||||
Convey(desc+" "+url, func() {
|
Convey(desc+" "+url, func() {
|
||||||
defer bus.ClearBusHandlers()
|
defer bus.ClearBusHandlers()
|
||||||
|
46
pkg/middleware/dashboard_redirect.go
Normal file
46
pkg/middleware/dashboard_redirect.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
|
"gopkg.in/macaron.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getDashboardUrlBySlug(orgId int64, slug string) (string, error) {
|
||||||
|
query := m.GetDashboardQuery{Slug: slug, OrgId: orgId}
|
||||||
|
|
||||||
|
if err := bus.Dispatch(&query); err != nil {
|
||||||
|
return "", m.ErrDashboardNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.GetDashboardUrl(query.Result.Uid, query.Result.Slug), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RedirectFromLegacyDashboardUrl() macaron.Handler {
|
||||||
|
return func(c *Context) {
|
||||||
|
slug := c.Params("slug")
|
||||||
|
|
||||||
|
if slug != "" {
|
||||||
|
if url, err := getDashboardUrlBySlug(c.OrgId, slug); err == nil {
|
||||||
|
c.Redirect(url, 301)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RedirectFromLegacyDashboardSoloUrl() macaron.Handler {
|
||||||
|
return func(c *Context) {
|
||||||
|
slug := c.Params("slug")
|
||||||
|
|
||||||
|
if slug != "" {
|
||||||
|
if url, err := getDashboardUrlBySlug(c.OrgId, slug); err == nil {
|
||||||
|
url = strings.Replace(url, "/d/", "/d-solo/", 1)
|
||||||
|
c.Redirect(url, 301)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
pkg/middleware/dashboard_redirect_test.go
Normal file
54
pkg/middleware/dashboard_redirect_test.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMiddlewareDashboardRedirect(t *testing.T) {
|
||||||
|
Convey("Given the dashboard redirect middleware", t, func() {
|
||||||
|
bus.ClearBusHandlers()
|
||||||
|
redirectFromLegacyDashboardUrl := RedirectFromLegacyDashboardUrl()
|
||||||
|
redirectFromLegacyDashboardSoloUrl := RedirectFromLegacyDashboardSoloUrl()
|
||||||
|
|
||||||
|
fakeDash := m.NewDashboard("Child dash")
|
||||||
|
fakeDash.Id = 1
|
||||||
|
fakeDash.FolderId = 1
|
||||||
|
fakeDash.HasAcl = false
|
||||||
|
|
||||||
|
bus.AddHandler("test", func(query *m.GetDashboardQuery) error {
|
||||||
|
query.Result = fakeDash
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
middlewareScenario("GET dashboard by legacy url", func(sc *scenarioContext) {
|
||||||
|
sc.m.Get("/dashboard/db/:slug", redirectFromLegacyDashboardUrl, sc.defaultHandler)
|
||||||
|
|
||||||
|
sc.fakeReqWithParams("GET", "/dashboard/db/dash", map[string]string{}).exec()
|
||||||
|
|
||||||
|
Convey("Should redirect to new dashboard url with a 301 Moved Permanently", func() {
|
||||||
|
So(sc.resp.Code, ShouldEqual, 301)
|
||||||
|
redirectUrl, _ := sc.resp.Result().Location()
|
||||||
|
So(redirectUrl.Path, ShouldEqual, m.GetDashboardUrl(fakeDash.Uid, fakeDash.Slug))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
middlewareScenario("GET dashboard solo by legacy url", func(sc *scenarioContext) {
|
||||||
|
sc.m.Get("/dashboard-solo/db/:slug", redirectFromLegacyDashboardSoloUrl, sc.defaultHandler)
|
||||||
|
|
||||||
|
sc.fakeReqWithParams("GET", "/dashboard-solo/db/dash", map[string]string{}).exec()
|
||||||
|
|
||||||
|
Convey("Should redirect to new dashboard url with a 301 Moved Permanently", func() {
|
||||||
|
So(sc.resp.Code, ShouldEqual, 301)
|
||||||
|
redirectUrl, _ := sc.resp.Result().Location()
|
||||||
|
expectedUrl := m.GetDashboardUrl(fakeDash.Uid, fakeDash.Slug)
|
||||||
|
expectedUrl = strings.Replace(expectedUrl, "/d/", "/d-solo/", 1)
|
||||||
|
So(redirectUrl.Path, ShouldEqual, expectedUrl)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
@ -399,6 +399,20 @@ func (sc *scenarioContext) fakeReq(method, url string) *scenarioContext {
|
|||||||
return sc
|
return sc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sc *scenarioContext) fakeReqWithParams(method, url string, queryParams map[string]string) *scenarioContext {
|
||||||
|
sc.resp = httptest.NewRecorder()
|
||||||
|
req, err := http.NewRequest(method, url, nil)
|
||||||
|
q := req.URL.Query()
|
||||||
|
for k, v := range queryParams {
|
||||||
|
q.Add(k, v)
|
||||||
|
}
|
||||||
|
req.URL.RawQuery = q.Encode()
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
sc.req = req
|
||||||
|
|
||||||
|
return sc
|
||||||
|
}
|
||||||
|
|
||||||
func (sc *scenarioContext) handler(fn handlerFunc) *scenarioContext {
|
func (sc *scenarioContext) handler(fn handlerFunc) *scenarioContext {
|
||||||
sc.handlerFunc = fn
|
sc.handlerFunc = fn
|
||||||
return sc
|
return sc
|
||||||
|
@ -225,6 +225,10 @@ export class BackendSrv {
|
|||||||
return this.get('/api/dashboards/' + type + '/' + slug);
|
return this.get('/api/dashboards/' + type + '/' + slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDashboardByUid(uid: string) {
|
||||||
|
return this.get(`/api/dashboards/uid/${uid}`);
|
||||||
|
}
|
||||||
|
|
||||||
saveDashboard(dash, options) {
|
saveDashboard(dash, options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
|
@ -41,10 +41,7 @@ export class SearchSrv {
|
|||||||
.map(orderId => {
|
.map(orderId => {
|
||||||
return _.find(result, { id: orderId });
|
return _.find(result, { id: orderId });
|
||||||
})
|
})
|
||||||
.filter(hit => hit && !hit.isStarred)
|
.filter(hit => hit && !hit.isStarred);
|
||||||
.map(hit => {
|
|
||||||
return this.transformToViewModel(hit);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,17 +78,12 @@ export class SearchSrv {
|
|||||||
score: -2,
|
score: -2,
|
||||||
expanded: this.starredIsOpen,
|
expanded: this.starredIsOpen,
|
||||||
toggle: this.toggleStarred.bind(this),
|
toggle: this.toggleStarred.bind(this),
|
||||||
items: result.map(this.transformToViewModel),
|
items: result,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private transformToViewModel(hit) {
|
|
||||||
hit.url = 'dashboard/db/' + hit.slug;
|
|
||||||
return hit;
|
|
||||||
}
|
|
||||||
|
|
||||||
search(options) {
|
search(options) {
|
||||||
let sections: any = {};
|
let sections: any = {};
|
||||||
let promises = [];
|
let promises = [];
|
||||||
@ -181,7 +173,7 @@ export class SearchSrv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
section.expanded = true;
|
section.expanded = true;
|
||||||
section.items.push(this.transformToViewModel(hit));
|
section.items.push(hit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +190,7 @@ export class SearchSrv {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return this.backendSrv.search(query).then(results => {
|
return this.backendSrv.search(query).then(results => {
|
||||||
section.items = _.map(results, this.transformToViewModel);
|
section.items = results;
|
||||||
return Promise.resolve(section);
|
return Promise.resolve(section);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -35,18 +35,18 @@ export class DashboardLoaderSrv {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
loadDashboard(type, slug) {
|
loadDashboard(type, slug, uid) {
|
||||||
var promise;
|
var promise;
|
||||||
|
|
||||||
if (type === 'script') {
|
if (type === 'script') {
|
||||||
promise = this._loadScriptedDashboard(slug);
|
promise = this._loadScriptedDashboard(slug);
|
||||||
} else if (type === 'snapshot') {
|
} else if (type === 'snapshot') {
|
||||||
promise = this.backendSrv.get('/api/snapshots/' + this.$routeParams.slug).catch(() => {
|
promise = this.backendSrv.get('/api/snapshots/' + slug).catch(() => {
|
||||||
return this._dashboardLoadFailed('Snapshot not found', true);
|
return this._dashboardLoadFailed('Snapshot not found', true);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
promise = this.backendSrv
|
promise = this.backendSrv
|
||||||
.getDashboard(this.$routeParams.type, this.$routeParams.slug)
|
.getDashboardByUid(uid)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
if (result.meta.isFolder) {
|
if (result.meta.isFolder) {
|
||||||
this.$rootScope.appEvent('alert-error', ['Dashboard not found']);
|
this.$rootScope.appEvent('alert-error', ['Dashboard not found']);
|
||||||
|
@ -73,9 +73,8 @@ export class DashboardSrv {
|
|||||||
postSave(clone, data) {
|
postSave(clone, data) {
|
||||||
this.dash.version = data.version;
|
this.dash.version = data.version;
|
||||||
|
|
||||||
var dashboardUrl = '/dashboard/db/' + data.slug;
|
if (data.url !== this.$location.path()) {
|
||||||
if (dashboardUrl !== this.$location.path()) {
|
this.$location.url(data.url);
|
||||||
this.$location.url(dashboardUrl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$rootScope.appEvent('dashboard-saved', this.dash);
|
this.$rootScope.appEvent('dashboard-saved', this.dash);
|
||||||
|
@ -74,6 +74,7 @@ export class ShareModalCtrl {
|
|||||||
$scope.shareUrl = linkSrv.addParamsToUrl(baseUrl, params);
|
$scope.shareUrl = linkSrv.addParamsToUrl(baseUrl, params);
|
||||||
|
|
||||||
var soloUrl = baseUrl.replace(config.appSubUrl + '/dashboard/', config.appSubUrl + '/dashboard-solo/');
|
var soloUrl = baseUrl.replace(config.appSubUrl + '/dashboard/', config.appSubUrl + '/dashboard-solo/');
|
||||||
|
soloUrl = soloUrl.replace(config.appSubUrl + '/d/', config.appSubUrl + '/d-solo/');
|
||||||
delete params.fullscreen;
|
delete params.fullscreen;
|
||||||
delete params.edit;
|
delete params.edit;
|
||||||
soloUrl = linkSrv.addParamsToUrl(soloUrl, params);
|
soloUrl = linkSrv.addParamsToUrl(soloUrl, params);
|
||||||
@ -84,6 +85,7 @@ export class ShareModalCtrl {
|
|||||||
config.appSubUrl + '/dashboard-solo/',
|
config.appSubUrl + '/dashboard-solo/',
|
||||||
config.appSubUrl + '/render/dashboard-solo/'
|
config.appSubUrl + '/render/dashboard-solo/'
|
||||||
);
|
);
|
||||||
|
$scope.imageUrl = $scope.imageUrl.replace(config.appSubUrl + '/d-solo/', config.appSubUrl + '/render/d-solo/');
|
||||||
$scope.imageUrl += '&width=1000';
|
$scope.imageUrl += '&width=1000';
|
||||||
$scope.imageUrl += '&height=500';
|
$scope.imageUrl += '&height=500';
|
||||||
$scope.imageUrl += '&tz=UTC' + encodeURIComponent(moment().format('Z'));
|
$scope.imageUrl += '&tz=UTC' + encodeURIComponent(moment().format('Z'));
|
||||||
|
@ -43,12 +43,23 @@ describe('ShareModalCtrl', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should generate render url', function() {
|
it('should generate render url', function() {
|
||||||
ctx.$location.$$absUrl = 'http://dashboards.grafana.com/dashboard/db/my-dash';
|
ctx.$location.$$absUrl = 'http://dashboards.grafana.com/d/abcdefghi/my-dash';
|
||||||
|
|
||||||
ctx.scope.panel = { id: 22 };
|
ctx.scope.panel = { id: 22 };
|
||||||
|
|
||||||
ctx.scope.init();
|
ctx.scope.init();
|
||||||
var base = 'http://dashboards.grafana.com/render/dashboard-solo/db/my-dash';
|
var base = 'http://dashboards.grafana.com/render/d-solo/abcdefghi/my-dash';
|
||||||
|
var params = '?from=1000&to=2000&orgId=1&panelId=22&width=1000&height=500&tz=UTC';
|
||||||
|
expect(ctx.scope.imageUrl).to.contain(base + params);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate render url for scripted dashboard', function() {
|
||||||
|
ctx.$location.$$absUrl = 'http://dashboards.grafana.com/dashboard/script/my-dash.js';
|
||||||
|
|
||||||
|
ctx.scope.panel = { id: 22 };
|
||||||
|
|
||||||
|
ctx.scope.init();
|
||||||
|
var base = 'http://dashboards.grafana.com/render/dashboard-solo/script/my-dash.js';
|
||||||
var params = '?from=1000&to=2000&orgId=1&panelId=22&width=1000&height=500&tz=UTC';
|
var params = '?from=1000&to=2000&orgId=1&panelId=22&width=1000&height=500&tz=UTC';
|
||||||
expect(ctx.scope.imageUrl).to.contain(base + params);
|
expect(ctx.scope.imageUrl).to.contain(base + params);
|
||||||
});
|
});
|
||||||
|
@ -2,7 +2,7 @@ import angular from 'angular';
|
|||||||
|
|
||||||
export class SoloPanelCtrl {
|
export class SoloPanelCtrl {
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
constructor($scope, $routeParams, $location, dashboardLoaderSrv, contextSrv) {
|
constructor($scope, $routeParams, $location, dashboardLoaderSrv, contextSrv, backendSrv) {
|
||||||
var panelId;
|
var panelId;
|
||||||
|
|
||||||
$scope.init = function() {
|
$scope.init = function() {
|
||||||
@ -13,7 +13,17 @@ export class SoloPanelCtrl {
|
|||||||
|
|
||||||
$scope.onAppEvent('dashboard-initialized', $scope.initPanelScope);
|
$scope.onAppEvent('dashboard-initialized', $scope.initPanelScope);
|
||||||
|
|
||||||
dashboardLoaderSrv.loadDashboard($routeParams.type, $routeParams.slug).then(function(result) {
|
// if no uid, redirect to new route based on slug
|
||||||
|
if (!($routeParams.type === 'script' || $routeParams.type === 'snapshot') && !$routeParams.uid) {
|
||||||
|
backendSrv.get(`/api/dashboards/db/${$routeParams.slug}`).then(res => {
|
||||||
|
if (res) {
|
||||||
|
$location.path(res.meta.url.replace('/d/', '/d-solo/'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dashboardLoaderSrv.loadDashboard($routeParams.type, $routeParams.slug, $routeParams.uid).then(function(result) {
|
||||||
result.meta.soloMode = true;
|
result.meta.soloMode = true;
|
||||||
$scope.initDashboard(result, $scope);
|
$scope.initDashboard(result, $scope);
|
||||||
});
|
});
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
{{group.header}}
|
{{group.header}}
|
||||||
</h6>
|
</h6>
|
||||||
<div class="dashlist-item" ng-repeat="dash in group.list">
|
<div class="dashlist-item" ng-repeat="dash in group.list">
|
||||||
<a class="dashlist-link dashlist-link-{{dash.type}}" href="dashboard/{{dash.uri}}">
|
<a class="dashlist-link dashlist-link-{{dash.type}}" href="{{dash.url}}">
|
||||||
<span class="dashlist-title">
|
<span class="dashlist-title">
|
||||||
{{dash.title}}
|
{{dash.title}}
|
||||||
</span>
|
</span>
|
||||||
|
@ -5,7 +5,7 @@ export class LoadDashboardCtrl {
|
|||||||
constructor($scope, $routeParams, dashboardLoaderSrv, backendSrv, $location) {
|
constructor($scope, $routeParams, dashboardLoaderSrv, backendSrv, $location) {
|
||||||
$scope.appEvent('dashboard-fetch-start');
|
$scope.appEvent('dashboard-fetch-start');
|
||||||
|
|
||||||
if (!$routeParams.slug) {
|
if (!$routeParams.uid && !$routeParams.slug) {
|
||||||
backendSrv.get('/api/dashboards/home').then(function(homeDash) {
|
backendSrv.get('/api/dashboards/home').then(function(homeDash) {
|
||||||
if (homeDash.redirectUri) {
|
if (homeDash.redirectUri) {
|
||||||
$location.path('dashboard/' + homeDash.redirectUri);
|
$location.path('dashboard/' + homeDash.redirectUri);
|
||||||
@ -18,7 +18,17 @@ export class LoadDashboardCtrl {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dashboardLoaderSrv.loadDashboard($routeParams.type, $routeParams.slug).then(function(result) {
|
// if no uid, redirect to new route based on slug
|
||||||
|
if (!($routeParams.type === 'script' || $routeParams.type === 'snapshot') && !$routeParams.uid) {
|
||||||
|
backendSrv.get(`/api/dashboards/db/${$routeParams.slug}`).then(res => {
|
||||||
|
if (res) {
|
||||||
|
$location.path(res.meta.url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dashboardLoaderSrv.loadDashboard($routeParams.type, $routeParams.slug, $routeParams.uid).then(function(result) {
|
||||||
if ($routeParams.keepRows) {
|
if ($routeParams.keepRows) {
|
||||||
result.meta.keepRows = true;
|
result.meta.keepRows = true;
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,24 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
|
|||||||
reloadOnSearch: false,
|
reloadOnSearch: false,
|
||||||
pageClass: 'page-dashboard',
|
pageClass: 'page-dashboard',
|
||||||
})
|
})
|
||||||
|
.when('/d/:uid/:slug', {
|
||||||
|
templateUrl: 'public/app/partials/dashboard.html',
|
||||||
|
controller: 'LoadDashboardCtrl',
|
||||||
|
reloadOnSearch: false,
|
||||||
|
pageClass: 'page-dashboard',
|
||||||
|
})
|
||||||
.when('/dashboard/:type/:slug', {
|
.when('/dashboard/:type/:slug', {
|
||||||
templateUrl: 'public/app/partials/dashboard.html',
|
templateUrl: 'public/app/partials/dashboard.html',
|
||||||
controller: 'LoadDashboardCtrl',
|
controller: 'LoadDashboardCtrl',
|
||||||
reloadOnSearch: false,
|
reloadOnSearch: false,
|
||||||
pageClass: 'page-dashboard',
|
pageClass: 'page-dashboard',
|
||||||
})
|
})
|
||||||
|
.when('/d-solo/:uid/:slug', {
|
||||||
|
templateUrl: 'public/app/features/panel/partials/soloPanel.html',
|
||||||
|
controller: 'SoloPanelCtrl',
|
||||||
|
reloadOnSearch: false,
|
||||||
|
pageClass: 'page-dashboard',
|
||||||
|
})
|
||||||
.when('/dashboard-solo/:type/:slug', {
|
.when('/dashboard-solo/:type/:slug', {
|
||||||
templateUrl: 'public/app/features/panel/partials/soloPanel.html',
|
templateUrl: 'public/app/features/panel/partials/soloPanel.html',
|
||||||
controller: 'SoloPanelCtrl',
|
controller: 'SoloPanelCtrl',
|
||||||
|
Loading…
Reference in New Issue
Block a user