mirror of
https://github.com/grafana/grafana.git
synced 2025-08-01 18:26:52 +08:00
Worked on dashboard starring and unstarring, renamed favorite model to star
This commit is contained in:
2
grafana
2
grafana
Submodule grafana updated: 66d9c4f1af...1e3970c6e5
@ -45,8 +45,8 @@ func Register(r *macaron.Macaron) {
|
|||||||
r.Put("/", bind(m.UpdateUserCommand{}), UpdateUser)
|
r.Put("/", bind(m.UpdateUserCommand{}), UpdateUser)
|
||||||
r.Post("/using/:id", SetUsingAccount)
|
r.Post("/using/:id", SetUsingAccount)
|
||||||
r.Get("/accounts", GetUserAccounts)
|
r.Get("/accounts", GetUserAccounts)
|
||||||
r.Post("/favorites/dashboard/:id", AddAsFavorite)
|
r.Post("/stars/dashboard/:id", StarDashboard)
|
||||||
r.Delete("/favorites/dashboard/:id", RemoveAsFavorite)
|
r.Delete("/stars/dashboard/:id", UnstarDashboard)
|
||||||
})
|
})
|
||||||
|
|
||||||
// account
|
// account
|
||||||
|
@ -8,6 +8,19 @@ import (
|
|||||||
"github.com/torkelo/grafana-pro/pkg/util"
|
"github.com/torkelo/grafana-pro/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func isDasboardStarredByUser(c *middleware.Context, dashId int64) (bool, error) {
|
||||||
|
if !c.IsSignedIn {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
query := m.IsStarredByUserQuery{UserId: c.UserId, DashboardId: dashId}
|
||||||
|
if err := bus.Dispatch(&query); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.Result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func GetDashboard(c *middleware.Context) {
|
func GetDashboard(c *middleware.Context) {
|
||||||
slug := c.Params(":slug")
|
slug := c.Params(":slug")
|
||||||
|
|
||||||
@ -18,10 +31,16 @@ func GetDashboard(c *middleware.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isStarred, err := isDasboardStarredByUser(c, query.Result.Id)
|
||||||
|
if err != nil {
|
||||||
|
c.JsonApiErr(500, "Error while checking if dashboard was starred by user", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
dash := query.Result
|
dash := query.Result
|
||||||
dto := dtos.Dashboard{
|
dto := dtos.Dashboard{
|
||||||
IsFavorite: false,
|
Model: dash.Data,
|
||||||
Dashboard: dash.Data,
|
Meta: dtos.DashboardMeta{IsStarred: isStarred},
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(200, dto)
|
c.JSON(200, dto)
|
||||||
|
@ -25,9 +25,13 @@ type CurrentUser struct {
|
|||||||
GravatarUrl string `json:"gravatarUrl"`
|
GravatarUrl string `json:"gravatarUrl"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DashboardMeta struct {
|
||||||
|
IsStarred bool `json:"isStarred"`
|
||||||
|
}
|
||||||
|
|
||||||
type Dashboard struct {
|
type Dashboard struct {
|
||||||
IsFavorite bool `json:"isFavorite"`
|
Meta DashboardMeta `json:"meta"`
|
||||||
Dashboard map[string]interface{} `json:"dashboard"`
|
Model map[string]interface{} `json:"model"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DataSource struct {
|
type DataSource struct {
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/torkelo/grafana-pro/pkg/bus"
|
|
||||||
"github.com/torkelo/grafana-pro/pkg/middleware"
|
|
||||||
m "github.com/torkelo/grafana-pro/pkg/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
func AddAsFavorite(c *middleware.Context) {
|
|
||||||
var cmd = m.AddAsFavoriteCommand{
|
|
||||||
UserId: c.UserId,
|
|
||||||
DashboardId: c.ParamsInt64(":id"),
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := bus.Dispatch(&cmd); err != nil {
|
|
||||||
c.JsonApiErr(500, "Failed to add favorite", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JsonOK("Dashboard marked as favorite")
|
|
||||||
}
|
|
||||||
|
|
||||||
func RemoveAsFavorite(c *middleware.Context) {
|
|
||||||
var cmd = m.RemoveAsFavoriteCommand{
|
|
||||||
UserId: c.UserId,
|
|
||||||
DashboardId: c.ParamsInt64(":id"),
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := bus.Dispatch(&cmd); err != nil {
|
|
||||||
c.JsonApiErr(500, "Failed to remove favorite", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JsonOK("Favorite removed")
|
|
||||||
}
|
|
45
pkg/api/stars.go
Normal file
45
pkg/api/stars.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/torkelo/grafana-pro/pkg/bus"
|
||||||
|
"github.com/torkelo/grafana-pro/pkg/middleware"
|
||||||
|
m "github.com/torkelo/grafana-pro/pkg/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StarDashboard(c *middleware.Context) {
|
||||||
|
var cmd = m.StarDashboardCommand{
|
||||||
|
UserId: c.UserId,
|
||||||
|
DashboardId: c.ParamsInt64(":id"),
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.DashboardId <= 0 {
|
||||||
|
c.JsonApiErr(400, "Missing dashboard id", nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := bus.Dispatch(&cmd); err != nil {
|
||||||
|
c.JsonApiErr(500, "Failed to star dashboard", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JsonOK("Dashboard starred!")
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnstarDashboard(c *middleware.Context) {
|
||||||
|
var cmd = m.UnstarDashboardCommand{
|
||||||
|
UserId: c.UserId,
|
||||||
|
DashboardId: c.ParamsInt64(":id"),
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.DashboardId <= 0 {
|
||||||
|
c.JsonApiErr(400, "Missing dashboard id", nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := bus.Dispatch(&cmd); err != nil {
|
||||||
|
c.JsonApiErr(500, "Failed to unstar dashboard", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JsonOK("Dashboard unstarred")
|
||||||
|
}
|
@ -1,29 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
type Favorite struct {
|
|
||||||
Id int64
|
|
||||||
UserId int64
|
|
||||||
DashboardId int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------
|
|
||||||
// COMMANDS
|
|
||||||
|
|
||||||
type AddAsFavoriteCommand struct {
|
|
||||||
UserId int64
|
|
||||||
DashboardId int64
|
|
||||||
}
|
|
||||||
|
|
||||||
type RemoveAsFavoriteCommand struct {
|
|
||||||
UserId int64
|
|
||||||
DashboardId int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------
|
|
||||||
// QUERIES
|
|
||||||
|
|
||||||
type GetUserFavoritesQuery struct {
|
|
||||||
UserId int64
|
|
||||||
|
|
||||||
Result []Favorite
|
|
||||||
}
|
|
40
pkg/models/star.go
Normal file
40
pkg/models/star.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var ErrCommandValidationFailed = errors.New("Command missing required fields")
|
||||||
|
|
||||||
|
type Star struct {
|
||||||
|
Id int64
|
||||||
|
UserId int64
|
||||||
|
DashboardId int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
// COMMANDS
|
||||||
|
|
||||||
|
type StarDashboardCommand struct {
|
||||||
|
UserId int64
|
||||||
|
DashboardId int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type UnstarDashboardCommand struct {
|
||||||
|
UserId int64
|
||||||
|
DashboardId int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------
|
||||||
|
// QUERIES
|
||||||
|
|
||||||
|
type GetUserStarsQuery struct {
|
||||||
|
UserId int64
|
||||||
|
|
||||||
|
Result []Star
|
||||||
|
}
|
||||||
|
|
||||||
|
type IsStarredByUserQuery struct {
|
||||||
|
UserId int64
|
||||||
|
DashboardId int64
|
||||||
|
|
||||||
|
Result bool
|
||||||
|
}
|
@ -1,41 +0,0 @@
|
|||||||
package sqlstore
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/go-xorm/xorm"
|
|
||||||
|
|
||||||
"github.com/torkelo/grafana-pro/pkg/bus"
|
|
||||||
m "github.com/torkelo/grafana-pro/pkg/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
bus.AddHandler("sql", AddAsFavorite)
|
|
||||||
bus.AddHandler("sql", RemoveAsFavorite)
|
|
||||||
bus.AddHandler("sql", GetUserFavorites)
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddAsFavorite(cmd *m.AddAsFavoriteCommand) error {
|
|
||||||
return inTransaction(func(sess *xorm.Session) error {
|
|
||||||
|
|
||||||
entity := m.Favorite{
|
|
||||||
UserId: cmd.UserId,
|
|
||||||
DashboardId: cmd.DashboardId,
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := sess.Insert(&entity)
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func RemoveAsFavorite(cmd *m.RemoveAsFavoriteCommand) error {
|
|
||||||
return inTransaction(func(sess *xorm.Session) error {
|
|
||||||
var rawSql = "DELETE FROM favorite WHERE user_id=? and dashboard_id=?"
|
|
||||||
_, err := sess.Exec(rawSql, cmd.UserId, cmd.DashboardId)
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUserFavorites(query *m.GetUserFavoritesQuery) error {
|
|
||||||
query.Result = make([]m.Favorite, 0)
|
|
||||||
err := x.Where("user_id=?", query.UserId).Find(&query.Result)
|
|
||||||
return err
|
|
||||||
}
|
|
@ -10,7 +10,7 @@ import . "github.com/torkelo/grafana-pro/pkg/services/sqlstore/migrator"
|
|||||||
func addMigrations(mg *Migrator) {
|
func addMigrations(mg *Migrator) {
|
||||||
addMigrationLogMigrations(mg)
|
addMigrationLogMigrations(mg)
|
||||||
addUserMigrations(mg)
|
addUserMigrations(mg)
|
||||||
addFavoritesMigrations(mg)
|
addStarMigrations(mg)
|
||||||
addAccountMigrations(mg)
|
addAccountMigrations(mg)
|
||||||
addDashboardMigration(mg)
|
addDashboardMigration(mg)
|
||||||
addDataSourceMigration(mg)
|
addDataSourceMigration(mg)
|
||||||
@ -55,16 +55,16 @@ func addUserMigrations(mg *Migrator) {
|
|||||||
Table("user").Column(&Column{Name: "rands", Type: DB_NVarchar, Length: 255, Nullable: true}))
|
Table("user").Column(&Column{Name: "rands", Type: DB_NVarchar, Length: 255, Nullable: true}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func addFavoritesMigrations(mg *Migrator) {
|
func addStarMigrations(mg *Migrator) {
|
||||||
mg.AddMigration("create favorite table", new(AddTableMigration).
|
mg.AddMigration("create star table", new(AddTableMigration).
|
||||||
Name("favorite").WithColumns(
|
Name("star").WithColumns(
|
||||||
&Column{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
|
&Column{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
|
||||||
&Column{Name: "user_id", Type: DB_BigInt, Nullable: false},
|
&Column{Name: "user_id", Type: DB_BigInt, Nullable: false},
|
||||||
&Column{Name: "dashboard_id", Type: DB_BigInt, Nullable: false},
|
&Column{Name: "dashboard_id", Type: DB_BigInt, Nullable: false},
|
||||||
))
|
))
|
||||||
|
|
||||||
mg.AddMigration("add unique index favorite.user_id_dashboard_id", new(AddIndexMigration).
|
mg.AddMigration("add unique index star.user_id_dashboard_id", new(AddIndexMigration).
|
||||||
Table("favorite").Columns("user_id", "dashboard_id").Unique())
|
Table("star").Columns("user_id", "dashboard_id").Unique())
|
||||||
}
|
}
|
||||||
|
|
||||||
func addAccountMigrations(mg *Migrator) {
|
func addAccountMigrations(mg *Migrator) {
|
||||||
|
68
pkg/services/sqlstore/star.go
Normal file
68
pkg/services/sqlstore/star.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package sqlstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/go-xorm/xorm"
|
||||||
|
|
||||||
|
"github.com/torkelo/grafana-pro/pkg/bus"
|
||||||
|
m "github.com/torkelo/grafana-pro/pkg/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
bus.AddHandler("sql", StarDashboard)
|
||||||
|
bus.AddHandler("sql", UnstarDashboard)
|
||||||
|
bus.AddHandler("sql", GetUserStars)
|
||||||
|
bus.AddHandler("sql", IsStarredByUser)
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsStarredByUser(query *m.IsStarredByUserQuery) error {
|
||||||
|
rawSql := "SELECT 1 from star where user_id=? and dashboard_id=?"
|
||||||
|
results, err := x.Query(rawSql, query.UserId, query.DashboardId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(results) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
query.Result, _ = strconv.ParseBool(string(results[0]["1"]))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func StarDashboard(cmd *m.StarDashboardCommand) error {
|
||||||
|
if cmd.DashboardId == 0 || cmd.UserId == 0 {
|
||||||
|
return m.ErrCommandValidationFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
return inTransaction(func(sess *xorm.Session) error {
|
||||||
|
|
||||||
|
entity := m.Star{
|
||||||
|
UserId: cmd.UserId,
|
||||||
|
DashboardId: cmd.DashboardId,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := sess.Insert(&entity)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnstarDashboard(cmd *m.UnstarDashboardCommand) error {
|
||||||
|
if cmd.DashboardId == 0 || cmd.UserId == 0 {
|
||||||
|
return m.ErrCommandValidationFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
return inTransaction(func(sess *xorm.Session) error {
|
||||||
|
var rawSql = "DELETE FROM star WHERE user_id=? and dashboard_id=?"
|
||||||
|
_, err := sess.Exec(rawSql, cmd.UserId, cmd.DashboardId)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUserStars(query *m.GetUserStarsQuery) error {
|
||||||
|
query.Result = make([]m.Star, 0)
|
||||||
|
err := x.Where("user_id=?", query.UserId).Find(&query.Result)
|
||||||
|
return err
|
||||||
|
}
|
42
pkg/services/sqlstore/stars_test.go
Normal file
42
pkg/services/sqlstore/stars_test.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package sqlstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
m "github.com/torkelo/grafana-pro/pkg/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUserStarsDataAccess(t *testing.T) {
|
||||||
|
|
||||||
|
Convey("Testing User Stars Data Access", t, func() {
|
||||||
|
InitTestDB(t)
|
||||||
|
|
||||||
|
Convey("Given saved star", func() {
|
||||||
|
cmd := m.StarDashboardCommand{
|
||||||
|
DashboardId: 10,
|
||||||
|
UserId: 12,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := StarDashboard(&cmd)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
Convey("IsStarredByUser should return true when starred", func() {
|
||||||
|
query := m.IsStarredByUserQuery{UserId: 12, DashboardId: 10}
|
||||||
|
err := IsStarredByUser(&query)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
So(query.Result, ShouldBeTrue)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("IsStarredByUser should return false when not starred", func() {
|
||||||
|
query := m.IsStarredByUserQuery{UserId: 12, DashboardId: 12}
|
||||||
|
err := IsStarredByUser(&query)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
So(query.Result, ShouldBeFalse)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
Reference in New Issue
Block a user