feat(playlist): changes to relation table

Also introduces an abstraction between playlist and dashboard.
This will make it possible to att search, and tag filtering to
playlists without any major refactoring
This commit is contained in:
bergquist 2016-01-08 17:32:55 +01:00
parent 0ea01f24a8
commit 8a38991270
6 changed files with 246 additions and 64 deletions

View File

@ -176,7 +176,7 @@ 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.Delete("/:id", reqEditorRole, ValidateOrgPlaylist, wrap(DeletePlaylist))
r.Put("/:id", reqEditorRole, bind(m.UpdatePlaylistQuery{}), ValidateOrgPlaylist, wrap(UpdatePlaylist))
r.Post("/", reqEditorRole, bind(m.CreatePlaylistQuery{}), wrap(CreatePlaylist))

View File

@ -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)
}

View File

@ -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 {

View File

@ -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
})
}

View File

@ -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))
}

View File

@ -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,39 @@ 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 +106,7 @@ func GetPlaylist(query *m.GetPlaylistByIdQuery) error {
playlist := m.Playlist{}
_, err := x.Id(query.Id).Get(&playlist)
query.Result = &playlist
return err
@ -74,9 +118,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 +148,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
}