diff --git a/pkg/api/dashboard.go b/pkg/api/dashboard.go
index 11a028cdd29..c2ab6dd9a1a 100644
--- a/pkg/api/dashboard.go
+++ b/pkg/api/dashboard.go
@@ -102,6 +102,16 @@ func GetDashboard(c *m.ReqContext) Response {
meta.FolderUrl = query.Result.GetUrl()
}
+ isDashboardProvisioned := &m.IsDashboardProvisionedQuery{DashboardId: dash.Id}
+ err = bus.Dispatch(isDashboardProvisioned)
+ if err != nil {
+ return Error(500, "Error while checking if dashboard is provisioned", err)
+ }
+
+ if isDashboardProvisioned.Result {
+ meta.Provisioned = true
+ }
+
// make sure db version is in sync with json model version
dash.Data.Set("version", dash.Version)
@@ -228,7 +238,8 @@ func PostDashboard(c *m.ReqContext, cmd m.SaveDashboardCommand) Response {
err == m.ErrDashboardWithSameUIDExists ||
err == m.ErrFolderNotFound ||
err == m.ErrDashboardFolderCannotHaveParent ||
- err == m.ErrDashboardFolderNameExists {
+ err == m.ErrDashboardFolderNameExists ||
+ err == m.ErrDashboardCannotSaveProvisionedDashboard {
return Error(400, err.Error(), nil)
}
diff --git a/pkg/api/dashboard_test.go b/pkg/api/dashboard_test.go
index 0d87023ce40..ccde2382787 100644
--- a/pkg/api/dashboard_test.go
+++ b/pkg/api/dashboard_test.go
@@ -42,6 +42,11 @@ func TestDashboardApiEndpoint(t *testing.T) {
return nil
})
+ bus.AddHandler("test", func(query *m.IsDashboardProvisionedQuery) error {
+ query.Result = false
+ return nil
+ })
+
viewerRole := m.ROLE_VIEWER
editorRole := m.ROLE_EDITOR
@@ -192,6 +197,11 @@ func TestDashboardApiEndpoint(t *testing.T) {
fakeDash.HasAcl = true
setting.ViewersCanEdit = false
+ bus.AddHandler("test", func(query *m.IsDashboardProvisionedQuery) error {
+ query.Result = false
+ return nil
+ })
+
bus.AddHandler("test", func(query *m.GetDashboardsBySlugQuery) error {
dashboards := []*m.Dashboard{fakeDash}
query.Result = dashboards
@@ -625,6 +635,11 @@ func TestDashboardApiEndpoint(t *testing.T) {
dashTwo.FolderId = 3
dashTwo.HasAcl = false
+ bus.AddHandler("test", func(query *m.IsDashboardProvisionedQuery) error {
+ query.Result = false
+ return nil
+ })
+
bus.AddHandler("test", func(query *m.GetDashboardsBySlugQuery) error {
dashboards := []*m.Dashboard{dashOne, dashTwo}
query.Result = dashboards
@@ -720,6 +735,7 @@ func TestDashboardApiEndpoint(t *testing.T) {
{SaveError: m.ErrDashboardUpdateAccessDenied, ExpectedStatusCode: 403},
{SaveError: m.ErrDashboardInvalidUid, ExpectedStatusCode: 400},
{SaveError: m.ErrDashboardUidToLong, ExpectedStatusCode: 400},
+ {SaveError: m.ErrDashboardCannotSaveProvisionedDashboard, ExpectedStatusCode: 400},
{SaveError: m.UpdatePluginDashboardError{PluginId: "plug"}, ExpectedStatusCode: 412},
}
@@ -750,6 +766,11 @@ func TestDashboardApiEndpoint(t *testing.T) {
return nil
})
+ bus.AddHandler("test", func(query *m.IsDashboardProvisionedQuery) error {
+ query.Result = false
+ return nil
+ })
+
bus.AddHandler("test", func(query *m.GetDashboardVersionQuery) error {
query.Result = &m.DashboardVersion{
Data: simplejson.NewFromAny(map[string]interface{}{
diff --git a/pkg/api/dtos/dashboard.go b/pkg/api/dtos/dashboard.go
index e4c66aebbda..39a6dca580d 100644
--- a/pkg/api/dtos/dashboard.go
+++ b/pkg/api/dtos/dashboard.go
@@ -28,6 +28,7 @@ type DashboardMeta struct {
FolderId int64 `json:"folderId"`
FolderTitle string `json:"folderTitle"`
FolderUrl string `json:"folderUrl"`
+ Provisioned bool `json:"provisioned"`
}
type DashboardFullWithMeta struct {
diff --git a/pkg/models/dashboards.go b/pkg/models/dashboards.go
index ece0ba06e62..eb44c1bc582 100644
--- a/pkg/models/dashboards.go
+++ b/pkg/models/dashboards.go
@@ -13,26 +13,27 @@ import (
// Typed errors
var (
- ErrDashboardNotFound = errors.New("Dashboard not found")
- ErrDashboardFolderNotFound = errors.New("Folder not found")
- ErrDashboardSnapshotNotFound = errors.New("Dashboard snapshot not found")
- ErrDashboardWithSameUIDExists = errors.New("A dashboard with the same uid already exists")
- ErrDashboardWithSameNameInFolderExists = errors.New("A dashboard with the same name in the folder already exists")
- ErrDashboardVersionMismatch = errors.New("The dashboard has been changed by someone else")
- ErrDashboardTitleEmpty = errors.New("Dashboard title cannot be empty")
- ErrDashboardFolderCannotHaveParent = errors.New("A Dashboard Folder cannot be added to another folder")
- ErrDashboardContainsInvalidAlertData = errors.New("Invalid alert data. Cannot save dashboard")
- ErrDashboardFailedToUpdateAlertData = errors.New("Failed to save alert data")
- ErrDashboardsWithSameSlugExists = errors.New("Multiple dashboards with the same slug exists")
- ErrDashboardFailedGenerateUniqueUid = errors.New("Failed to generate unique dashboard id")
- ErrDashboardTypeMismatch = errors.New("Dashboard cannot be changed to a folder")
- ErrDashboardFolderWithSameNameAsDashboard = errors.New("Folder name cannot be the same as one of its dashboards")
- ErrDashboardWithSameNameAsFolder = errors.New("Dashboard name cannot be the same as folder")
- ErrDashboardFolderNameExists = errors.New("A folder with that name already exists")
- ErrDashboardUpdateAccessDenied = errors.New("Access denied to save dashboard")
- ErrDashboardInvalidUid = errors.New("uid contains illegal characters")
- ErrDashboardUidToLong = errors.New("uid to long. max 40 characters")
- RootFolderName = "General"
+ ErrDashboardNotFound = errors.New("Dashboard not found")
+ ErrDashboardFolderNotFound = errors.New("Folder not found")
+ ErrDashboardSnapshotNotFound = errors.New("Dashboard snapshot not found")
+ ErrDashboardWithSameUIDExists = errors.New("A dashboard with the same uid already exists")
+ ErrDashboardWithSameNameInFolderExists = errors.New("A dashboard with the same name in the folder already exists")
+ ErrDashboardVersionMismatch = errors.New("The dashboard has been changed by someone else")
+ ErrDashboardTitleEmpty = errors.New("Dashboard title cannot be empty")
+ ErrDashboardFolderCannotHaveParent = errors.New("A Dashboard Folder cannot be added to another folder")
+ ErrDashboardContainsInvalidAlertData = errors.New("Invalid alert data. Cannot save dashboard")
+ ErrDashboardFailedToUpdateAlertData = errors.New("Failed to save alert data")
+ ErrDashboardsWithSameSlugExists = errors.New("Multiple dashboards with the same slug exists")
+ ErrDashboardFailedGenerateUniqueUid = errors.New("Failed to generate unique dashboard id")
+ ErrDashboardTypeMismatch = errors.New("Dashboard cannot be changed to a folder")
+ ErrDashboardFolderWithSameNameAsDashboard = errors.New("Folder name cannot be the same as one of its dashboards")
+ ErrDashboardWithSameNameAsFolder = errors.New("Dashboard name cannot be the same as folder")
+ ErrDashboardFolderNameExists = errors.New("A folder with that name already exists")
+ ErrDashboardUpdateAccessDenied = errors.New("Access denied to save dashboard")
+ ErrDashboardInvalidUid = errors.New("uid contains illegal characters")
+ ErrDashboardUidToLong = errors.New("uid to long. max 40 characters")
+ ErrDashboardCannotSaveProvisionedDashboard = errors.New("Cannot save provisioned dashboard")
+ RootFolderName = "General"
)
type UpdatePluginDashboardError struct {
@@ -322,6 +323,12 @@ type GetDashboardSlugByIdQuery struct {
Result string
}
+type IsDashboardProvisionedQuery struct {
+ DashboardId int64
+
+ Result bool
+}
+
type GetProvisionedDashboardDataQuery struct {
Name string
diff --git a/pkg/services/dashboards/dashboard_service.go b/pkg/services/dashboards/dashboard_service.go
index 1656bb74c9c..278421e6be7 100644
--- a/pkg/services/dashboards/dashboard_service.go
+++ b/pkg/services/dashboards/dashboard_service.go
@@ -57,7 +57,7 @@ func (dr *dashboardServiceImpl) GetProvisionedDashboardData(name string) ([]*mod
return cmd.Result, nil
}
-func (dr *dashboardServiceImpl) buildSaveDashboardCommand(dto *SaveDashboardDTO, validateAlerts bool) (*models.SaveDashboardCommand, error) {
+func (dr *dashboardServiceImpl) buildSaveDashboardCommand(dto *SaveDashboardDTO, validateAlerts bool, validateProvisionedDashboard bool) (*models.SaveDashboardCommand, error) {
dash := dto.Dashboard
dash.Title = strings.TrimSpace(dash.Title)
@@ -113,6 +113,19 @@ func (dr *dashboardServiceImpl) buildSaveDashboardCommand(dto *SaveDashboardDTO,
}
}
+ if validateProvisionedDashboard {
+ isDashboardProvisioned := &models.IsDashboardProvisionedQuery{DashboardId: dash.Id}
+ err := bus.Dispatch(isDashboardProvisioned)
+
+ if err != nil {
+ return nil, err
+ }
+
+ if isDashboardProvisioned.Result {
+ return nil, models.ErrDashboardCannotSaveProvisionedDashboard
+ }
+ }
+
guard := guardian.New(dash.GetDashboardIdForSavePermissionCheck(), dto.OrgId, dto.User)
if canSave, err := guard.CanSave(); err != nil || !canSave {
if err != nil {
@@ -158,7 +171,7 @@ func (dr *dashboardServiceImpl) SaveProvisionedDashboard(dto *SaveDashboardDTO,
UserId: 0,
OrgRole: models.ROLE_ADMIN,
}
- cmd, err := dr.buildSaveDashboardCommand(dto, true)
+ cmd, err := dr.buildSaveDashboardCommand(dto, true, false)
if err != nil {
return nil, err
}
@@ -188,7 +201,7 @@ func (dr *dashboardServiceImpl) SaveFolderForProvisionedDashboards(dto *SaveDash
UserId: 0,
OrgRole: models.ROLE_ADMIN,
}
- cmd, err := dr.buildSaveDashboardCommand(dto, false)
+ cmd, err := dr.buildSaveDashboardCommand(dto, false, false)
if err != nil {
return nil, err
}
@@ -207,7 +220,7 @@ func (dr *dashboardServiceImpl) SaveFolderForProvisionedDashboards(dto *SaveDash
}
func (dr *dashboardServiceImpl) SaveDashboard(dto *SaveDashboardDTO) (*models.Dashboard, error) {
- cmd, err := dr.buildSaveDashboardCommand(dto, true)
+ cmd, err := dr.buildSaveDashboardCommand(dto, true, true)
if err != nil {
return nil, err
}
@@ -226,7 +239,7 @@ func (dr *dashboardServiceImpl) SaveDashboard(dto *SaveDashboardDTO) (*models.Da
}
func (dr *dashboardServiceImpl) ImportDashboard(dto *SaveDashboardDTO) (*models.Dashboard, error) {
- cmd, err := dr.buildSaveDashboardCommand(dto, false)
+ cmd, err := dr.buildSaveDashboardCommand(dto, false, true)
if err != nil {
return nil, err
}
diff --git a/pkg/services/dashboards/dashboard_service_test.go b/pkg/services/dashboards/dashboard_service_test.go
index d2c5863d994..f9d487f625c 100644
--- a/pkg/services/dashboards/dashboard_service_test.go
+++ b/pkg/services/dashboards/dashboard_service_test.go
@@ -14,7 +14,9 @@ import (
func TestDashboardService(t *testing.T) {
Convey("Dashboard service tests", t, func() {
- service := dashboardServiceImpl{}
+ bus.ClearBusHandlers()
+
+ service := &dashboardServiceImpl{}
origNewDashboardGuardian := guardian.New
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
@@ -55,6 +57,11 @@ func TestDashboardService(t *testing.T) {
return nil
})
+ bus.AddHandler("test", func(cmd *models.IsDashboardProvisionedQuery) error {
+ cmd.Result = false
+ return nil
+ })
+
testCases := []struct {
Uid string
Error error
@@ -73,12 +80,42 @@ func TestDashboardService(t *testing.T) {
dto.Dashboard.SetUid(tc.Uid)
dto.User = &models.SignedInUser{}
- _, err := service.buildSaveDashboardCommand(dto, true)
+ _, err := service.buildSaveDashboardCommand(dto, true, false)
So(err, ShouldEqual, tc.Error)
}
})
+ Convey("Should return validation error if dashboard is provisioned", func() {
+ provisioningValidated := false
+ bus.AddHandler("test", func(cmd *models.IsDashboardProvisionedQuery) error {
+ provisioningValidated = true
+ cmd.Result = true
+ return nil
+ })
+
+ bus.AddHandler("test", func(cmd *models.ValidateDashboardAlertsCommand) error {
+ return nil
+ })
+
+ bus.AddHandler("test", func(cmd *models.ValidateDashboardBeforeSaveCommand) error {
+ cmd.Result = &models.ValidateDashboardBeforeSaveResult{}
+ return nil
+ })
+
+ dto.Dashboard = models.NewDashboard("Dash")
+ dto.Dashboard.SetId(3)
+ dto.User = &models.SignedInUser{UserId: 1}
+ _, err := service.SaveDashboard(dto)
+ So(provisioningValidated, ShouldBeTrue)
+ So(err, ShouldEqual, models.ErrDashboardCannotSaveProvisionedDashboard)
+ })
+
Convey("Should return validation error if alert data is invalid", func() {
+ bus.AddHandler("test", func(cmd *models.IsDashboardProvisionedQuery) error {
+ cmd.Result = false
+ return nil
+ })
+
bus.AddHandler("test", func(cmd *models.ValidateDashboardAlertsCommand) error {
return errors.New("error")
})
@@ -89,6 +126,80 @@ func TestDashboardService(t *testing.T) {
})
})
+ Convey("Save provisioned dashboard validation", func() {
+ dto := &SaveDashboardDTO{}
+
+ Convey("Should not return validation error if dashboard is provisioned", func() {
+ provisioningValidated := false
+ bus.AddHandler("test", func(cmd *models.IsDashboardProvisionedQuery) error {
+ provisioningValidated = true
+ cmd.Result = true
+ return nil
+ })
+
+ bus.AddHandler("test", func(cmd *models.ValidateDashboardAlertsCommand) error {
+ return nil
+ })
+
+ bus.AddHandler("test", func(cmd *models.ValidateDashboardBeforeSaveCommand) error {
+ cmd.Result = &models.ValidateDashboardBeforeSaveResult{}
+ return nil
+ })
+
+ bus.AddHandler("test", func(cmd *models.SaveProvisionedDashboardCommand) error {
+ return nil
+ })
+
+ bus.AddHandler("test", func(cmd *models.UpdateDashboardAlertsCommand) error {
+ return nil
+ })
+
+ dto.Dashboard = models.NewDashboard("Dash")
+ dto.Dashboard.SetId(3)
+ dto.User = &models.SignedInUser{UserId: 1}
+ _, err := service.SaveProvisionedDashboard(dto, nil)
+ So(err, ShouldBeNil)
+ So(provisioningValidated, ShouldBeFalse)
+ })
+ })
+
+ Convey("Import dashboard validation", func() {
+ dto := &SaveDashboardDTO{}
+
+ Convey("Should return validation error if dashboard is provisioned", func() {
+ provisioningValidated := false
+ bus.AddHandler("test", func(cmd *models.IsDashboardProvisionedQuery) error {
+ provisioningValidated = true
+ cmd.Result = true
+ return nil
+ })
+
+ bus.AddHandler("test", func(cmd *models.ValidateDashboardAlertsCommand) error {
+ return nil
+ })
+
+ bus.AddHandler("test", func(cmd *models.ValidateDashboardBeforeSaveCommand) error {
+ cmd.Result = &models.ValidateDashboardBeforeSaveResult{}
+ return nil
+ })
+
+ bus.AddHandler("test", func(cmd *models.SaveProvisionedDashboardCommand) error {
+ return nil
+ })
+
+ bus.AddHandler("test", func(cmd *models.UpdateDashboardAlertsCommand) error {
+ return nil
+ })
+
+ dto.Dashboard = models.NewDashboard("Dash")
+ dto.Dashboard.SetId(3)
+ dto.User = &models.SignedInUser{UserId: 1}
+ _, err := service.ImportDashboard(dto)
+ So(provisioningValidated, ShouldBeTrue)
+ So(err, ShouldEqual, models.ErrDashboardCannotSaveProvisionedDashboard)
+ })
+ })
+
Reset(func() {
guardian.New = origNewDashboardGuardian
})
diff --git a/pkg/services/dashboards/folder_service.go b/pkg/services/dashboards/folder_service.go
index ae92952056e..b521b0e5213 100644
--- a/pkg/services/dashboards/folder_service.go
+++ b/pkg/services/dashboards/folder_service.go
@@ -104,7 +104,7 @@ func (dr *dashboardServiceImpl) CreateFolder(cmd *models.CreateFolderCommand) er
User: dr.user,
}
- saveDashboardCmd, err := dr.buildSaveDashboardCommand(dto, false)
+ saveDashboardCmd, err := dr.buildSaveDashboardCommand(dto, false, false)
if err != nil {
return toFolderError(err)
}
@@ -141,7 +141,7 @@ func (dr *dashboardServiceImpl) UpdateFolder(existingUid string, cmd *models.Upd
Overwrite: cmd.Overwrite,
}
- saveDashboardCmd, err := dr.buildSaveDashboardCommand(dto, false)
+ saveDashboardCmd, err := dr.buildSaveDashboardCommand(dto, false, false)
if err != nil {
return toFolderError(err)
}
diff --git a/pkg/services/dashboards/folder_service_test.go b/pkg/services/dashboards/folder_service_test.go
index 1e678e3b1a1..4c9cecd3352 100644
--- a/pkg/services/dashboards/folder_service_test.go
+++ b/pkg/services/dashboards/folder_service_test.go
@@ -110,11 +110,19 @@ func TestFolderService(t *testing.T) {
return nil
})
+ provisioningValidated := false
+
+ bus.AddHandler("test", func(query *models.IsDashboardProvisionedQuery) error {
+ provisioningValidated = true
+ return nil
+ })
+
Convey("When creating folder should not return access denied error", func() {
err := service.CreateFolder(&models.CreateFolderCommand{
Title: "Folder",
})
So(err, ShouldBeNil)
+ So(provisioningValidated, ShouldBeFalse)
})
Convey("When updating folder should not return access denied error", func() {
@@ -123,6 +131,7 @@ func TestFolderService(t *testing.T) {
Title: "Folder",
})
So(err, ShouldBeNil)
+ So(provisioningValidated, ShouldBeFalse)
})
Convey("When deleting folder by uid should not return access denied error", func() {
diff --git a/pkg/services/provisioning/dashboards/types.go b/pkg/services/provisioning/dashboards/types.go
index f742b321552..4a55351d3e4 100644
--- a/pkg/services/provisioning/dashboards/types.go
+++ b/pkg/services/provisioning/dashboards/types.go
@@ -55,9 +55,6 @@ func createDashboardJson(data *simplejson.Json, lastModified time.Time, cfg *Das
dash.OrgId = cfg.OrgId
dash.Dashboard.OrgId = cfg.OrgId
dash.Dashboard.FolderId = folderId
- if !cfg.Editable {
- dash.Dashboard.Data.Set("editable", cfg.Editable)
- }
if dash.Dashboard.Title == "" {
return nil, models.ErrDashboardTitleEmpty
diff --git a/pkg/services/sqlstore/dashboard_provisioning.go b/pkg/services/sqlstore/dashboard_provisioning.go
index 69409c3b873..33fbb01c5b7 100644
--- a/pkg/services/sqlstore/dashboard_provisioning.go
+++ b/pkg/services/sqlstore/dashboard_provisioning.go
@@ -8,6 +8,7 @@ import (
func init() {
bus.AddHandler("sql", GetProvisionedDashboardDataQuery)
bus.AddHandler("sql", SaveProvisionedDashboard)
+ bus.AddHandler("sql", GetProvisionedDataByDashboardId)
}
type DashboardExtras struct {
@@ -17,6 +18,19 @@ type DashboardExtras struct {
Value string
}
+func GetProvisionedDataByDashboardId(cmd *models.IsDashboardProvisionedQuery) error {
+ result := &models.DashboardProvisioning{}
+
+ exist, err := x.Where("dashboard_id = ?", cmd.DashboardId).Get(result)
+ if err != nil {
+ return err
+ }
+
+ cmd.Result = exist
+
+ return nil
+}
+
func SaveProvisionedDashboard(cmd *models.SaveProvisionedDashboardCommand) error {
return inTransaction(func(sess *DBSession) error {
err := saveDashboard(sess, cmd.DashboardCmd)
diff --git a/pkg/services/sqlstore/dashboard_provisioning_test.go b/pkg/services/sqlstore/dashboard_provisioning_test.go
index b752173b67d..7ef45df3152 100644
--- a/pkg/services/sqlstore/dashboard_provisioning_test.go
+++ b/pkg/services/sqlstore/dashboard_provisioning_test.go
@@ -50,6 +50,23 @@ func TestDashboardProvisioningTest(t *testing.T) {
So(query.Result[0].DashboardId, ShouldEqual, dashId)
So(query.Result[0].Updated, ShouldEqual, now.Unix())
})
+
+ Convey("Can query for one provisioned dashboard", func() {
+ query := &models.IsDashboardProvisionedQuery{DashboardId: cmd.Result.Id}
+
+ err := GetProvisionedDataByDashboardId(query)
+ So(err, ShouldBeNil)
+
+ So(query.Result, ShouldBeTrue)
+ })
+
+ Convey("Can query for none provisioned dashboard", func() {
+ query := &models.IsDashboardProvisionedQuery{DashboardId: 3000}
+
+ err := GetProvisionedDataByDashboardId(query)
+ So(err, ShouldBeNil)
+ So(query.Result, ShouldBeFalse)
+ })
})
})
}
diff --git a/pkg/services/sqlstore/dashboard_service_integration_test.go b/pkg/services/sqlstore/dashboard_service_integration_test.go
index 21ebc6505bb..a9658f7ab76 100644
--- a/pkg/services/sqlstore/dashboard_service_integration_test.go
+++ b/pkg/services/sqlstore/dashboard_service_integration_test.go
@@ -19,7 +19,6 @@ func TestIntegratedDashboardService(t *testing.T) {
var testOrgId int64 = 1
Convey("Given saved folders and dashboards in organization A", func() {
-
bus.AddHandler("test", func(cmd *models.ValidateDashboardAlertsCommand) error {
return nil
})
@@ -28,6 +27,11 @@ func TestIntegratedDashboardService(t *testing.T) {
return nil
})
+ bus.AddHandler("test", func(cmd *models.IsDashboardProvisionedQuery) error {
+ cmd.Result = false
+ return nil
+ })
+
savedFolder := saveTestFolder("Saved folder", testOrgId)
savedDashInFolder := saveTestDashboard("Saved dash in folder", testOrgId, savedFolder.Id)
saveTestDashboard("Other saved dash in folder", testOrgId, savedFolder.Id)
diff --git a/public/app/features/dashboard/all.ts b/public/app/features/dashboard/all.ts
index f2e2e3dcdc0..a8f491f3ddd 100644
--- a/public/app/features/dashboard/all.ts
+++ b/public/app/features/dashboard/all.ts
@@ -6,6 +6,7 @@ import './dashnav/dashnav';
import './submenu/submenu';
import './save_as_modal';
import './save_modal';
+import './save_provisioned_modal';
import './shareModalCtrl';
import './share_snapshot_ctrl';
import './dashboard_srv';
diff --git a/public/app/features/dashboard/dashboard_srv.ts b/public/app/features/dashboard/dashboard_srv.ts
index 9d766fdfc3f..1890323da29 100644
--- a/public/app/features/dashboard/dashboard_srv.ts
+++ b/public/app/features/dashboard/dashboard_srv.ts
@@ -105,6 +105,10 @@ export class DashboardSrv {
this.setCurrent(this.create(clone, this.dash.meta));
}
+ if (this.dash.meta.provisioned) {
+ return this.showDashboardProvisionedModal();
+ }
+
if (!this.dash.meta.canSave && options.makeEditable !== true) {
return Promise.resolve();
}
@@ -120,6 +124,12 @@ export class DashboardSrv {
return this.save(this.dash.getSaveModelClone(), options);
}
+ showDashboardProvisionedModal() {
+ this.$rootScope.appEvent('show-modal', {
+ templateHtml: '