diff --git a/grafana b/grafana index c00384ad064..4b382e0faff 160000 --- a/grafana +++ b/grafana @@ -1 +1 @@ -Subproject commit c00384ad0644f9db7cdfa426c559d8fc3347a1d2 +Subproject commit 4b382e0faff3fa2e5c05ca3306d54d8e5f8ca89c diff --git a/grafana-pro b/grafana-pro index ffa72bf8aa0..0a717ff5f02 100755 Binary files a/grafana-pro and b/grafana-pro differ diff --git a/pkg/api/api_dashboard.go b/pkg/api/api_dashboard.go index bbcf64528f7..77b50bdf202 100644 --- a/pkg/api/api_dashboard.go +++ b/pkg/api/api_dashboard.go @@ -8,25 +8,49 @@ import ( func init() { addRoutes(func(self *HttpServer) { - self.router.GET("/api/dashboards/:id", self.auth(), self.getDashboard) + self.router.GET("/api/dashboards/:slug", self.auth(), self.getDashboard) self.router.GET("/api/search/", self.auth(), self.search) self.router.POST("/api/dashboard", self.auth(), self.postDashboard) + self.router.DELETE("/api/dashboard/:slug", self.auth(), self.deleteDashboard) }) } func (self *HttpServer) getDashboard(c *gin.Context) { - id := c.Params.ByName("id") + slug := c.Params.ByName("slug") accountId, err := c.Get("accountId") - dash, err := self.store.GetDashboard(id, accountId.(int)) + dash, err := self.store.GetDashboard(slug, accountId.(int)) if err != nil { c.JSON(404, newErrorResponse("Dashboard not found")) return } + dash.Data["id"] = dash.Id + c.JSON(200, dash.Data) } +func (self *HttpServer) deleteDashboard(c *gin.Context) { + slug := c.Params.ByName("slug") + accountId, err := c.Get("accountId") + + dash, err := self.store.GetDashboard(slug, accountId.(int)) + if err != nil { + c.JSON(404, newErrorResponse("Dashboard not found")) + return + } + + err = self.store.DeleteDashboard(slug, accountId.(int)) + if err != nil { + c.JSON(500, newErrorResponse("Failed to delete dashboard: "+err.Error())) + return + } + + var resp = map[string]interface{}{"title": dash.Title} + + c.JSON(200, resp) +} + func (self *HttpServer) search(c *gin.Context) { query := c.Params.ByName("q") accountId, err := c.Get("accountId") diff --git a/pkg/stores/rethinkdb.go b/pkg/stores/rethinkdb.go index e0e6679eb43..d4f5ee7aea5 100644 --- a/pkg/stores/rethinkdb.go +++ b/pkg/stores/rethinkdb.go @@ -1,6 +1,7 @@ package stores import ( + "errors" "time" log "github.com/alecthomas/log4go" @@ -63,7 +64,7 @@ func NewRethinkStore(config *RethinkCfg) *rethinkStore { } func (self *rethinkStore) SaveDashboard(dash *models.Dashboard) error { - resp, err := r.Table("dashboards").Insert(dash, r.InsertOpts{Upsert: true}).RunWrite(self.session) + resp, err := r.Table("dashboards").Insert(dash, r.InsertOpts{Conflict: "update"}).RunWrite(self.session) if err != nil { return err } @@ -92,6 +93,22 @@ func (self *rethinkStore) GetDashboard(slug string, accountId int) (*models.Dash return &dashboard, nil } +func (self *rethinkStore) DeleteDashboard(slug string, accountId int) error { + resp, err := r.Table("dashboards"). + GetAllByIndex("AccountIdSlug", []interface{}{accountId, slug}). + Delete().RunWrite(self.session) + + if err != nil { + return err + } + + if resp.Deleted != 1 { + return errors.New("Did not find dashboard to delete") + } + + return nil +} + func (self *rethinkStore) Query(query string, accountId int) ([]*models.SearchResult, error) { docs, err := r.Table("dashboards").GetAllByIndex("AccountId", []interface{}{accountId}).Filter(r.Row.Field("Title").Match(".*")).Run(self.session) diff --git a/pkg/stores/rethinkdb_accounts.go b/pkg/stores/rethinkdb_accounts.go index e2a337146ae..9d574fc3bda 100644 --- a/pkg/stores/rethinkdb_accounts.go +++ b/pkg/stores/rethinkdb_accounts.go @@ -10,17 +10,19 @@ import ( func (self *rethinkStore) getNextAccountId() (int, error) { resp, err := r.Table("master").Get("ids").Update(map[string]interface{}{ "NextAccountId": r.Row.Field("NextAccountId").Add(1), - }, r.UpdateOpts{ReturnVals: true}).RunWrite(self.session) + }, r.UpdateOpts{ReturnChanges: true}).RunWrite(self.session) if err != nil { return 0, err } - if resp.NewValue == nil { + change := resp.Changes[0] + + if change.NewValue == nil { return 0, errors.New("Failed to get new value after incrementing account id") } - return int(resp.NewValue.(map[string]interface{})["NextAccountId"].(float64)), nil + return int(change.NewValue.(map[string]interface{})["NextAccountId"].(float64)), nil } func (self *rethinkStore) SaveUserAccount(account *models.UserAccount) error { @@ -62,15 +64,17 @@ func (self *rethinkStore) GetUserAccountLogin(emailOrName string) (*models.UserA func (self *rethinkStore) getNextDashboardNumber(accountId int) (int, error) { resp, err := r.Table("accounts").Get(accountId).Update(map[string]interface{}{ "NextDashboardId": r.Row.Field("NextDashboardId").Add(1), - }, r.UpdateOpts{ReturnVals: true}).RunWrite(self.session) + }, r.UpdateOpts{ReturnChanges: true}).RunWrite(self.session) if err != nil { return 0, err } - if resp.NewValue == nil { + change := resp.Changes[0] + + if change.NewValue == nil { return 0, errors.New("Failed to get next dashboard id, no new value after update") } - return int(resp.NewValue.(map[string]interface{})["NextDashboardId"].(float64)), nil + return int(change.NewValue.(map[string]interface{})["NextDashboardId"].(float64)), nil } diff --git a/pkg/stores/store.go b/pkg/stores/store.go index 4669b344bcc..8b7fec3eb5b 100644 --- a/pkg/stores/store.go +++ b/pkg/stores/store.go @@ -7,6 +7,7 @@ import ( type Store interface { GetDashboard(slug string, accountId int) (*models.Dashboard, error) SaveDashboard(dash *models.Dashboard) error + DeleteDashboard(slug string, accountId int) error Query(query string, acccountId int) ([]*models.SearchResult, error) SaveUserAccount(acccount *models.UserAccount) error GetUserAccountLogin(emailOrName string) (*models.UserAccount, error)