ソースを参照

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
bergquist 10 年 前
コミット
8a38991270

+ 1 - 1
pkg/api/api.go

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

+ 115 - 8
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)
 }

+ 40 - 10
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 {

+ 0 - 20
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
 	})
 }

+ 14 - 2
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))
 }

+ 74 - 21
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,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,27 +148,28 @@ func SearchPlaylists(query *m.PlaylistQuery) error {
 	return err
 }
 
-func GetPlaylistDashboards(query *m.GetPlaylistDashboardsQuery) error {
-	if query.Id == 0 {
+func GetPlaylistItem(query *m.GetPlaylistItemsByIdQuery) error {
+	if query.PlaylistId == 0 {
 		return m.ErrCommandValidationFailed
 	}
 
-	var dashboards = make(m.PlaylistDashboards, 0)
-	var playlist = m.Playlist{}
+	var playlistItems = make([]m.PlaylistItem, 0)
+	err := x.Where("playlist_id=?", query.PlaylistId).Find(&playlistItems)
 
-	hasPlaylist, err := x.Id(query.Id).Get(&playlist)
+	query.Result = &playlistItems
 
-	query.Result = &dashboards
+	return err
+}
 
-	if err != nil {
-		return err
+func GetPlaylistDashboards(query *m.GetPlaylistDashboardsQuery) error {
+	if len(query.DashboardIds) == 0 {
+		return m.ErrCommandValidationFailed
 	}
 
-	if !hasPlaylist || len(playlist.Data) == 0 {
-		return nil
-	}
+	var dashboards = make(m.PlaylistDashboards, 0)
 
-	err = x.In("id", playlist.Data).Find(&dashboards)
+	err := x.In("id", query.DashboardIds).Find(&dashboards)
+	query.Result = &dashboards
 
 	if err != nil {
 		return err