فهرست منبع

dashboard load/save work and began work on register

Torkel Ödegaard 11 سال پیش
والد
کامیت
c684b1ddab

+ 1 - 1
grafana

@@ -1 +1 @@
-Subproject commit 06de80f2a764b76df6047fc4700c74aaf5734521
+Subproject commit 477f66f56bdd7f310d439ac428cb646fbb9b1949

+ 4 - 2
pkg/api/api_dashboard.go

@@ -17,7 +17,7 @@ func init() {
 func (self *HttpServer) getDashboard(c *gin.Context) {
 	id := c.Params.ByName("id")
 
-	dash, err := self.store.GetDashboardByTitle(id, "test")
+	dash, err := self.store.GetDashboard(id, 1)
 	if err != nil {
 		c.JSON(404, newErrorResponse("Dashboard not found"))
 		return
@@ -46,6 +46,8 @@ func (self *HttpServer) postDashboard(c *gin.Context) {
 		dashboard := models.NewDashboard("test")
 		dashboard.Data = command.Dashboard
 		dashboard.Title = dashboard.Data["title"].(string)
+		dashboard.AccountId = 1
+		dashboard.UpdateSlug()
 
 		if dashboard.Data["id"] != nil {
 			dashboard.Id = dashboard.Data["id"].(string)
@@ -53,7 +55,7 @@ func (self *HttpServer) postDashboard(c *gin.Context) {
 
 		err := self.store.SaveDashboard(dashboard)
 		if err == nil {
-			c.JSON(200, gin.H{"status": "success", "id": dashboard.Id})
+			c.JSON(200, gin.H{"status": "success", "slug": dashboard.Slug})
 			return
 		}
 	}

+ 1 - 0
pkg/api/api_login.go

@@ -5,6 +5,7 @@ import "github.com/gin-gonic/gin"
 func init() {
 	addRoutes(func(self *HttpServer) {
 		self.router.GET("/login/*_", self.index)
+		self.router.GET("/register/*_", self.index)
 		self.router.POST("/login", self.loginPost)
 		self.router.POST("/logout", self.logoutPost)
 	})

+ 18 - 0
pkg/models/dashboard_test.go

@@ -0,0 +1,18 @@
+package models
+
+import (
+	"testing"
+
+	. "github.com/smartystreets/goconvey/convey"
+)
+
+func TestDashboardModel(t *testing.T) {
+
+	Convey("When generating slug", t, func() {
+		dashboard := NewDashboard("Grafana Play Home")
+		dashboard.UpdateSlug()
+
+		So(dashboard.Slug, ShouldEqual, "grafana-play-home")
+	})
+
+}

+ 14 - 5
pkg/models/dashboards.go

@@ -3,12 +3,15 @@ package models
 import (
 	"encoding/json"
 	"io"
+	"regexp"
+	"strings"
 	"time"
 )
 
 type Dashboard struct {
 	Id                   string `gorethink:"id,omitempty"`
-	AccountId            string
+	Slug                 string
+	AccountId            int
 	LastModifiedByUserId string
 	LastModifiedByDate   time.Time
 	CreatedDate          time.Time
@@ -26,18 +29,19 @@ type UserContext struct {
 type SearchResult struct {
 	Id    string `json:"id"`
 	Title string `json:"title"`
+	Slug  string `json:"slug"`
 }
 
 func NewDashboard(title string) *Dashboard {
 	dash := &Dashboard{}
 	dash.Id = ""
-	dash.AccountId = "test"
 	dash.LastModifiedByDate = time.Now()
 	dash.CreatedDate = time.Now()
 	dash.LastModifiedByUserId = "123"
-	dash.Title = title
 	dash.Data = make(map[string]interface{})
 	dash.Data["title"] = title
+	dash.Title = title
+	dash.UpdateSlug()
 
 	return dash
 }
@@ -50,11 +54,16 @@ func NewFromJson(reader io.Reader) (*Dashboard, error) {
 		return nil, err
 	}
 
-	dash.Title = dash.Data["title"].(string)
-
 	return dash, nil
 }
 
 func (dash *Dashboard) GetString(prop string) string {
 	return dash.Data[prop].(string)
 }
+
+func (dash *Dashboard) UpdateSlug() {
+	title := strings.ToLower(dash.Data["title"].(string))
+	re := regexp.MustCompile("[^\\w ]+")
+	re2 := regexp.MustCompile("\\s")
+	dash.Slug = re2.ReplaceAllString(re.ReplaceAllString(title, ""), "-")
+}

+ 18 - 7
pkg/stores/rethinkdb.go

@@ -16,6 +16,11 @@ type RethinkCfg struct {
 	DatabaseName string
 }
 
+type Account struct {
+	Id              int `gorethink:"id"`
+	NextDashboardId int
+}
+
 func NewRethinkStore(config *RethinkCfg) *rethinkStore {
 	log.Info("Initializing rethink storage")
 
@@ -32,17 +37,24 @@ func NewRethinkStore(config *RethinkCfg) *rethinkStore {
 
 	r.DbCreate(config.DatabaseName).Exec(session)
 	r.Db(config.DatabaseName).TableCreate("dashboards").Exec(session)
-	r.Db(config.DatabaseName).Table("dashboards").IndexCreateFunc("AccountIdTitle", func(row r.Term) interface{} {
-		return []interface{}{row.Field("AccountId"), row.Field("Title")}
+	r.Db(config.DatabaseName).TableCreate("accounts").Exec(session)
+	r.Db(config.DatabaseName).TableCreate("master").Exec(session)
+	r.Db(config.DatabaseName).Table("dashboards").IndexCreateFunc("AccountIdSlug", func(row r.Term) interface{} {
+		return []interface{}{row.Field("AccountId"), row.Field("Slug")}
 	}).Exec(session)
 
+	_, err = r.Table("master").Insert(map[string]interface{}{"id": "ids", "NextAccountId": 0}).RunWrite(session)
+	if err != nil {
+		log.Error("Failed to insert master ids row", err)
+	}
+
 	return &rethinkStore{
 		session: session,
 	}
 }
 
 func (self *rethinkStore) SaveDashboard(dash *models.Dashboard) error {
-	resp, err := r.Table("dashboards").Insert(dash).RunWrite(self.session)
+	resp, err := r.Table("dashboards").Insert(dash, r.InsertOpts{Upsert: true}).RunWrite(self.session)
 	if err != nil {
 		return err
 	}
@@ -56,8 +68,8 @@ func (self *rethinkStore) SaveDashboard(dash *models.Dashboard) error {
 	return nil
 }
 
-func (self *rethinkStore) GetDashboardByTitle(title string, accountId string) (*models.Dashboard, error) {
-	resp, err := r.Table("dashboards").GetAllByIndex("AccountIdTitle", []interface{}{accountId, title}).Run(self.session)
+func (self *rethinkStore) GetDashboard(slug string, accountId int) (*models.Dashboard, error) {
+	resp, err := r.Table("dashboards").GetAllByIndex("AccountIdSlug", []interface{}{accountId, slug}).Run(self.session)
 	if err != nil {
 		return nil, err
 	}
@@ -81,10 +93,9 @@ func (self *rethinkStore) Query(query string) ([]*models.SearchResult, error) {
 	results := make([]*models.SearchResult, 0, 50)
 	var dashboard models.Dashboard
 	for docs.Next(&dashboard) {
-		log.Info("title: ", dashboard.Title)
 		results = append(results, &models.SearchResult{
 			Title: dashboard.Title,
-			Id:    dashboard.Id,
+			Id:    dashboard.Slug,
 		})
 	}
 

+ 59 - 0
pkg/stores/rethinkdb_accounts.go

@@ -0,0 +1,59 @@
+package stores
+
+import (
+	"errors"
+
+	r "github.com/dancannon/gorethink"
+)
+
+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)
+
+	if err != nil {
+		return 0, err
+	}
+
+	if resp.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
+}
+
+func (self *rethinkStore) createAccount() (*Account, error) {
+	accountId, err := self.getNextAccountId()
+	if err != nil {
+		return nil, err
+	}
+
+	account := &Account{Id: accountId, NextDashboardId: 0}
+
+	resp, err := r.Table("accounts").Insert(account).RunWrite(self.session)
+	if err != nil {
+		return nil, err
+	}
+
+	if resp.Inserted == 0 {
+		return nil, errors.New("Failed to insert acccount")
+	}
+
+	return account, nil
+}
+
+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)
+
+	if err != nil {
+		return 0, err
+	}
+
+	if resp.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
+}

+ 27 - 5
pkg/stores/rethinkdb_test.go

@@ -3,27 +3,49 @@ package stores
 import (
 	"testing"
 
+	"github.com/dancannon/gorethink"
 	. "github.com/smartystreets/goconvey/convey"
 	"github.com/torkelo/grafana-pro/pkg/models"
 )
 
 func TestRethinkStore(t *testing.T) {
+	store := NewRethinkStore(&RethinkCfg{DatabaseName: "tests"})
+	defer gorethink.DbDrop("tests").Exec(store.session)
 
 	Convey("Insert dashboard", t, func() {
-		store := NewRethinkStore(&RethinkCfg{DatabaseName: "tests"})
-		//defer r.DbDrop("tests").Exec(store.session)
-
 		dashboard := models.NewDashboard("test")
-		dashboard.AccountId = "123"
+		dashboard.AccountId = 1
 
 		err := store.SaveDashboard(dashboard)
 		So(err, ShouldBeNil)
 		So(dashboard.Id, ShouldNotBeEmpty)
 
-		read, err := store.GetDashboardByTitle("test", "123")
+		read, err := store.GetDashboard("test", 1)
 		So(err, ShouldBeNil)
 		So(read, ShouldNotBeNil)
+	})
+
+	Convey("can get next account id", t, func() {
+		id, err := store.getNextAccountId()
+		So(err, ShouldBeNil)
+		So(id, ShouldNotEqual, 0)
+
+		id2, err := store.getNextAccountId()
+		So(id2, ShouldEqual, id+1)
+	})
 
+	Convey("can create account", t, func() {
+		account, err := store.createAccount()
+		So(err, ShouldBeNil)
+		So(account, ShouldNotBeNil)
+		So(account.Id, ShouldNotEqual, 0)
+	})
+
+	Convey("can get next dashboard id", t, func() {
+		account, err := store.createAccount()
+		dashId, err := store.getNextDashboardNumber(account.Id)
+		So(err, ShouldBeNil)
+		So(dashId, ShouldEqual, 1)
 	})
 
 }

+ 1 - 1
pkg/stores/store.go

@@ -5,7 +5,7 @@ import (
 )
 
 type Store interface {
-	GetDashboardByTitle(id string, accountId string) (*models.Dashboard, error)
+	GetDashboard(title string, accountId int) (*models.Dashboard, error)
 	SaveDashboard(dash *models.Dashboard) error
 	Query(query string) ([]*models.SearchResult, error)
 	Close()