diff --git a/pkg/api/api.go b/pkg/api/api.go index d184a03f58e..9c06512c6d3 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -176,7 +176,8 @@ func Register(r *macaron.Macaron) { r.Group("/playlists", func() { r.Get("/", wrap(SearchPlaylists)) r.Get("/:id", ValidateOrgPlaylist, wrap(GetPlaylist)) - r.Get("/:id/dashboards", ValidateOrgPlaylist, wrap(GetPlaylistDashboards)) + r.Get("/:id/playlistitems", ValidateOrgPlaylist, wrap(GetPlaylistItems)) + r.Get("/:id/playlistdashboards", ValidateOrgPlaylist, wrap(GetPlaylistDashboards)) r.Delete("/:id", reqEditorRole, ValidateOrgPlaylist, wrap(DeletePlaylist)) r.Put("/:id", reqEditorRole, bind(m.UpdatePlaylistQuery{}), ValidateOrgPlaylist, wrap(UpdatePlaylist)) r.Post("/", reqEditorRole, bind(m.CreatePlaylistQuery{}), wrap(CreatePlaylist)) diff --git a/pkg/api/playlist.go b/pkg/api/playlist.go index 44745f91143..b2d048efcc2 100644 --- a/pkg/api/playlist.go +++ b/pkg/api/playlist.go @@ -1,9 +1,12 @@ package api import ( + "errors" "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/log" "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" + "strconv" ) func ValidateOrgPlaylist(c *middleware.Context) { @@ -52,19 +55,67 @@ func GetPlaylist(c *middleware.Context) Response { return ApiError(500, "Playlist not found", err) } - return Json(200, cmd.Result) + itemQuery := m.GetPlaylistItemsByIdQuery{PlaylistId: id} + if err := bus.Dispatch(&itemQuery); err != nil { + log.Warn("itemQuery failed: %v", err) + return ApiError(500, "Playlist items not found", err) + } + + playlistDTOs := make([]m.PlaylistItemDTO, 0) + + for _, item := range *itemQuery.Result { + playlistDTOs = append(playlistDTOs, m.PlaylistItemDTO{ + Id: item.Id, + PlaylistId: item.PlaylistId, + Type: item.Type, + Value: item.Value, + Order: item.Order, + }) + } + + dto := &m.PlaylistDTO{ + Id: cmd.Result.Id, + Title: cmd.Result.Title, + Timespan: cmd.Result.Timespan, + OrgId: cmd.Result.OrgId, + Items: playlistDTOs, + } + + return Json(200, dto) } -func GetPlaylistDashboards(c *middleware.Context) Response { - id := c.ParamsInt64(":id") +func LoadPlaylistItems(id int64) ([]m.PlaylistItem, error) { + itemQuery := m.GetPlaylistItemsByIdQuery{PlaylistId: id} + if err := bus.Dispatch(&itemQuery); err != nil { + log.Warn("itemQuery failed: %v", err) + return nil, errors.New("Playlist not found") + } - query := m.GetPlaylistDashboardsQuery{Id: id} - if err := bus.Dispatch(&query); err != nil { - return ApiError(500, "Playlist not found", err) + return *itemQuery.Result, nil +} + +func LoadPlaylistDashboards(id int64) ([]m.PlaylistDashboardDto, error) { + playlistItems, _ := LoadPlaylistItems(id) + + dashboardIds := make([]int64, 0) + + for _, i := range playlistItems { + dashboardId, _ := strconv.ParseInt(i.Value, 10, 64) + dashboardIds = append(dashboardIds, dashboardId) + } + + if len(dashboardIds) == 0 { + return make([]m.PlaylistDashboardDto, 0), nil + } + + dashboardQuery := m.GetPlaylistDashboardsQuery{DashboardIds: dashboardIds} + if err := bus.Dispatch(&dashboardQuery); err != nil { + log.Warn("dashboardquery failed: %v", err) + return nil, errors.New("Playlist not found") } dtos := make([]m.PlaylistDashboardDto, 0) - for _, item := range *query.Result { + for _, item := range *dashboardQuery.Result { dtos = append(dtos, m.PlaylistDashboardDto{ Id: item.Id, Slug: item.Slug, @@ -73,7 +124,43 @@ func GetPlaylistDashboards(c *middleware.Context) Response { }) } - return Json(200, dtos) + return dtos, nil +} + +func GetPlaylistItems(c *middleware.Context) Response { + id := c.ParamsInt64(":id") + + items, err := LoadPlaylistItems(id) + + if err != nil { + return ApiError(500, "Could not load playlist items", err) + } + + playlistDTOs := make([]m.PlaylistItemDTO, 0) + + for _, item := range items { + playlistDTOs = append(playlistDTOs, m.PlaylistItemDTO{ + Id: item.Id, + PlaylistId: item.PlaylistId, + Type: item.Type, + Value: item.Value, + Order: item.Order, + Title: item.Title, + }) + } + + return Json(200, playlistDTOs) +} + +func GetPlaylistDashboards(c *middleware.Context) Response { + id := c.ParamsInt64(":id") + + playlists, err := LoadPlaylistDashboards(id) + if err != nil { + return ApiError(500, "Could not load dashboards", err) + } + + return Json(200, playlists) } func DeletePlaylist(c *middleware.Context) Response { @@ -103,5 +190,25 @@ func UpdatePlaylist(c *middleware.Context, query m.UpdatePlaylistQuery) Response return ApiError(500, "Failed to save playlist", err) } + items, err := LoadPlaylistItems(query.Id) + + playlistDTOs := make([]m.PlaylistItemDTO, 0) + + for _, item := range items { + playlistDTOs = append(playlistDTOs, m.PlaylistItemDTO{ + Id: item.Id, + PlaylistId: item.PlaylistId, + Type: item.Type, + Value: item.Value, + Order: item.Order, + }) + } + + if err != nil { + return ApiError(500, "Failed to save playlist", err) + } + + query.Result.Items = playlistDTOs + return Json(200, query.Result) } diff --git a/pkg/models/playlist.go b/pkg/models/playlist.go index 84478459922..802a9262c9f 100644 --- a/pkg/models/playlist.go +++ b/pkg/models/playlist.go @@ -12,12 +12,27 @@ var ( // Playlist model type Playlist struct { - Id int64 `json:"id"` - Title string `json:"title"` - Type string `json:"type"` - Timespan string `json:"timespan"` - Data []int64 `json:"data"` - OrgId int64 `json:"-"` + Id int64 `json:"id"` + Title string `json:"title"` + Timespan string `json:"timespan"` + OrgId int64 `json:"-"` +} + +type PlaylistDTO struct { + Id int64 `json:"id"` + Title string `json:"title"` + Timespan string `json:"timespan"` + OrgId int64 `json:"-"` + Items []PlaylistItemDTO `json:"items"` +} + +type PlaylistItemDTO struct { + Id int64 `json:"id"` + PlaylistId int64 `json:"playlistid"` + Type string `json:"type"` + Title string `json:"title"` + Value string `json:"value"` + Order int `json:"order"` } type PlaylistDashboard struct { @@ -26,6 +41,15 @@ type PlaylistDashboard struct { Title string `json:"title"` } +type PlaylistItem struct { + Id int64 + PlaylistId int64 + Type string + Value string + Order int + Title string +} + func (this PlaylistDashboard) TableName() string { return "dashboard" } @@ -60,9 +84,9 @@ type UpdatePlaylistQuery struct { Title string Type string Timespan string - Data []int64 + Items []PlaylistItemDTO - Result *Playlist + Result *PlaylistDTO } type CreatePlaylistQuery struct { @@ -71,6 +95,7 @@ type CreatePlaylistQuery struct { Timespan string Data []int64 OrgId int64 + Items []PlaylistItemDTO Result *Playlist } @@ -80,9 +105,14 @@ type GetPlaylistByIdQuery struct { Result *Playlist } +type GetPlaylistItemsByIdQuery struct { + PlaylistId int64 + Result *[]PlaylistItem +} + type GetPlaylistDashboardsQuery struct { - Id int64 - Result *PlaylistDashboards + DashboardIds []int64 + Result *PlaylistDashboards } type DeletePlaylistQuery struct { diff --git a/pkg/services/sqlstore/dashboard.go b/pkg/services/sqlstore/dashboard.go index 547c24fc7df..bbec541589c 100644 --- a/pkg/services/sqlstore/dashboard.go +++ b/pkg/services/sqlstore/dashboard.go @@ -220,26 +220,6 @@ func DeleteDashboard(cmd *m.DeleteDashboardCommand) error { } } - var playlists = make(m.Playlists, 0) - err = sess.Where("data LIKE ?", fmt.Sprintf("%%%v%%", dashboard.Id)).Find(&playlists) - if err != nil { - return err - } - - for _, playlist := range playlists { - filteredData := make([]int64, 0) - for _, plDashboardId := range playlist.Data { - if plDashboardId != dashboard.Id { - filteredData = append(filteredData, plDashboardId) - } - } - playlist.Data = filteredData - _, err = sess.Id(playlist.Id).Cols("data").Update(playlist) - if err != nil { - return err - } - } - return nil }) } diff --git a/pkg/services/sqlstore/migrations/playlist_mig.go b/pkg/services/sqlstore/migrations/playlist_mig.go index d8625f301ae..c97fc1adb3d 100644 --- a/pkg/services/sqlstore/migrations/playlist_mig.go +++ b/pkg/services/sqlstore/migrations/playlist_mig.go @@ -8,8 +8,6 @@ func addPlaylistMigrations(mg *Migrator) { Columns: []*Column{ {Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true}, {Name: "title", Type: DB_NVarchar, Length: 255, Nullable: false}, - {Name: "type", Type: DB_NVarchar, Length: 255, Nullable: false}, - {Name: "data", Type: DB_Text, Nullable: false}, {Name: "timespan", Type: DB_NVarchar, Length: 255, Nullable: false}, {Name: "org_id", Type: DB_BigInt, Nullable: false}, }, @@ -17,4 +15,18 @@ func addPlaylistMigrations(mg *Migrator) { // create table mg.AddMigration("create playlist table v1", NewAddTableMigration(playlistV1)) + + playlistItemV1 := Table{ + Name: "playlist_item", + Columns: []*Column{ + {Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true}, + {Name: "playlist_id", Type: DB_BigInt, Nullable: false}, + {Name: "type", Type: DB_NVarchar, Length: 255, Nullable: false}, + {Name: "value", Type: DB_Text, Nullable: false}, + {Name: "title", Type: DB_Text, Nullable: false}, + {Name: "order", Type: DB_Int, Nullable: false}, + }, + } + + mg.AddMigration("create playlist item table v1", NewAddTableMigration(playlistItemV1)) } diff --git a/pkg/services/sqlstore/playlist.go b/pkg/services/sqlstore/playlist.go index 56f6ca23fcb..ff3f1753a3c 100644 --- a/pkg/services/sqlstore/playlist.go +++ b/pkg/services/sqlstore/playlist.go @@ -1,6 +1,7 @@ package sqlstore import ( + "fmt" "github.com/go-xorm/xorm" "github.com/grafana/grafana/pkg/bus" @@ -14,6 +15,7 @@ func init() { bus.AddHandler("sql", SearchPlaylists) bus.AddHandler("sql", GetPlaylist) bus.AddHandler("sql", GetPlaylistDashboards) + bus.AddHandler("sql", GetPlaylistItem) } func CreatePlaylist(query *m.CreatePlaylistQuery) error { @@ -21,14 +23,27 @@ func CreatePlaylist(query *m.CreatePlaylistQuery) error { playlist := m.Playlist{ Title: query.Title, - Type: query.Type, - Data: query.Data, Timespan: query.Timespan, OrgId: query.OrgId, } _, err = x.Insert(&playlist) + fmt.Printf("%v", playlist.Id) + + playlistItems := make([]m.PlaylistItem, 0) + for _, item := range query.Items { + playlistItems = append(playlistItems, m.PlaylistItem{ + PlaylistId: playlist.Id, + Type: item.Type, + Value: item.Value, + Order: item.Order, + Title: item.Title, + }) + } + + _, err = x.Insert(&playlistItems) + query.Result = &playlist return err } @@ -39,8 +54,6 @@ func UpdatePlaylist(query *m.UpdatePlaylistQuery) error { playlist := m.Playlist{ Id: query.Id, Title: query.Title, - Type: query.Type, - Data: query.Data, Timespan: query.Timespan, } @@ -50,9 +63,40 @@ func UpdatePlaylist(query *m.UpdatePlaylistQuery) error { return m.ErrPlaylistNotFound } - _, err = x.Id(query.Id).Cols("id", "title", "data", "timespan").Update(&playlist) + query.Result = &m.PlaylistDTO{ + Id: playlist.Id, + OrgId: playlist.OrgId, + Title: playlist.Title, + Timespan: playlist.Timespan, + } + + _, err = x.Id(query.Id).Cols("id", "title", "timespan").Update(&playlist) + + if err != nil { + return err + } + + rawSql := "DELETE FROM playlist_item WHERE playlist_id = ?" + _, err = x.Exec(rawSql, query.Id) + + if err != nil { + return err + } + + playlistItems := make([]m.PlaylistItem, 0) + + for _, item := range query.Items { + playlistItems = append(playlistItems, m.PlaylistItem{ + PlaylistId: playlist.Id, + Type: item.Type, + Value: item.Value, + Order: item.Order, + Title: item.Title, + }) + } + + _, err = x.Insert(&playlistItems) - query.Result = &playlist return err } @@ -63,6 +107,7 @@ func GetPlaylist(query *m.GetPlaylistByIdQuery) error { playlist := m.Playlist{} _, err := x.Id(query.Id).Get(&playlist) + query.Result = &playlist return err @@ -74,9 +119,17 @@ func DeletePlaylist(query *m.DeletePlaylistQuery) error { } return inTransaction(func(sess *xorm.Session) error { - var rawSql = "DELETE FROM playlist WHERE id = ?" - _, err := sess.Exec(rawSql, query.Id) - return err + var rawPlaylistSql = "DELETE FROM playlist WHERE id = ?" + _, err := sess.Exec(rawPlaylistSql, query.Id) + + if err != nil { + return err + } + + var rawItemSql = "DELETE FROM playlist_item WHERE playlist_id = ?" + _, err2 := sess.Exec(rawItemSql, query.Id) + + return err2 }) } @@ -96,31 +149,32 @@ func SearchPlaylists(query *m.PlaylistQuery) error { return err } +func GetPlaylistItem(query *m.GetPlaylistItemsByIdQuery) error { + if query.PlaylistId == 0 { + return m.ErrCommandValidationFailed + } + + var playlistItems = make([]m.PlaylistItem, 0) + err := x.Where("playlist_id=?", query.PlaylistId).Find(&playlistItems) + + query.Result = &playlistItems + + return err +} + func GetPlaylistDashboards(query *m.GetPlaylistDashboardsQuery) error { - if query.Id == 0 { + if len(query.DashboardIds) == 0 { return m.ErrCommandValidationFailed } var dashboards = make(m.PlaylistDashboards, 0) - var playlist = m.Playlist{} - - hasPlaylist, err := x.Id(query.Id).Get(&playlist) + err := x.In("id", query.DashboardIds).Find(&dashboards) query.Result = &dashboards if err != nil { return err } - if !hasPlaylist || len(playlist.Data) == 0 { - return nil - } - - err = x.In("id", playlist.Data).Find(&dashboards) - - if err != nil { - return err - } - return nil } diff --git a/public/app/features/playlist/partials/playlist.html b/public/app/features/playlist/partials/playlist.html index 71fec4abb9b..925b3699505 100644 --- a/public/app/features/playlist/partials/playlist.html +++ b/public/app/features/playlist/partials/playlist.html @@ -59,14 +59,14 @@
- {{dashboard.title}} + {{playlistItem.title}} | - |