Kaynağa Gözat

Worked on search filter flag IsStarred, and updated frontend with new dashboard list panel

Torkel Ödegaard 11 yıl önce
ebeveyn
işleme
60541a455f

+ 1 - 1
grafana

@@ -1 +1 @@
-Subproject commit df51be02bf4fa72ac4f1bcb15006f08f8b93ce8d
+Subproject commit 882ee4d49f1df4550e898a914b4d17d40add4ddf

+ 9 - 0
pkg/api/search.go

@@ -7,10 +7,13 @@ import (
 	"github.com/torkelo/grafana-pro/pkg/bus"
 	"github.com/torkelo/grafana-pro/pkg/middleware"
 	m "github.com/torkelo/grafana-pro/pkg/models"
+	"github.com/torkelo/grafana-pro/pkg/setting"
 )
 
 func Search(c *middleware.Context) {
 	queryText := c.Query("q")
+	starred := c.Query("starred")
+
 	result := m.SearchResult{
 		Dashboards: []*m.DashboardSearchHit{},
 		Tags:       []*m.DashboardTagCloudItem{},
@@ -31,6 +34,8 @@ func Search(c *middleware.Context) {
 		query := m.SearchDashboardsQuery{
 			Title:     matches[3],
 			Tag:       matches[2],
+			UserId:    c.UserId,
+			IsStarred: starred == "1",
 			AccountId: c.AccountId,
 		}
 		err := bus.Dispatch(&query)
@@ -38,7 +43,11 @@ func Search(c *middleware.Context) {
 			c.JsonApiErr(500, "Search failed", err)
 			return
 		}
+
 		result.Dashboards = query.Result
+		for _, dash := range result.Dashboards {
+			dash.Url = setting.AbsUrlTo("dashboard/db/" + dash.Slug)
+		}
 	}
 
 	c.JSON(200, result)

+ 3 - 0
pkg/models/search.go

@@ -11,6 +11,7 @@ type DashboardSearchHit struct {
 	Title string   `json:"title"`
 	Slug  string   `json:"slug"`
 	Tags  []string `json:"tags"`
+	Url   string   `json:"url"`
 }
 
 type DashboardTagCloudItem struct {
@@ -22,6 +23,8 @@ type SearchDashboardsQuery struct {
 	Title     string
 	Tag       string
 	AccountId int64
+	UserId    int64
+	IsStarred bool
 
 	Result []*DashboardSearchHit
 }

+ 2 - 1
pkg/services/sqlstore/account_users.go

@@ -1,6 +1,7 @@
 package sqlstore
 
 import (
+	"fmt"
 	"time"
 
 	"github.com/go-xorm/xorm"
@@ -34,7 +35,7 @@ func AddAccountUser(cmd *m.AddAccountUserCommand) error {
 func GetAccountUsers(query *m.GetAccountUsersQuery) error {
 	query.Result = make([]*m.AccountUserDTO, 0)
 	sess := x.Table("account_user")
-	sess.Join("INNER", "user", "account_user.user_id=user.id")
+	sess.Join("INNER", "user", fmt.Sprintf("account_user.user_id=%s.id", x.Dialect().Quote("user")))
 	sess.Where("account_user.account_id=?", query.AccountId)
 	sess.Cols("account_user.account_id", "account_user.user_id", "user.email", "user.login", "account_user.role")
 	sess.Asc("user.email", "user.login")

+ 32 - 8
pkg/services/sqlstore/dashboard.go

@@ -1,6 +1,8 @@
 package sqlstore
 
 import (
+	"bytes"
+
 	"github.com/go-xorm/xorm"
 	"github.com/torkelo/grafana-pro/pkg/bus"
 	m "github.com/torkelo/grafana-pro/pkg/models"
@@ -80,20 +82,42 @@ type DashboardSearchProjection struct {
 }
 
 func SearchDashboards(query *m.SearchDashboardsQuery) error {
-	titleQuery := "%" + query.Title + "%"
+	var sql bytes.Buffer
+	params := make([]interface{}, 0)
+
+	sql.WriteString(`SELECT
+					  dashboard.id,
+					  dashboard.title,
+					  dashboard.slug,
+					  dashboard_tag.term
+					FROM dashboard
+					LEFT OUTER JOIN dashboard_tag on dashboard_tag.dashboard_id = dashboard.id`)
+
+	if query.IsStarred {
+		sql.WriteString(" INNER JOIN star on star.dashboard_id = dashboard.id")
+	}
+
+	sql.WriteString(` WHERE dashboard.account_id=?`)
 
-	sess := x.Table("dashboard")
-	sess.Join("LEFT OUTER", "dashboard_tag", "dashboard.id=dashboard_tag.dashboard_id")
-	sess.Where("account_id=? AND title LIKE ?", query.AccountId, titleQuery)
-	sess.Cols("dashboard.id", "dashboard.title", "dashboard.slug", "dashboard_tag.term")
-	sess.Limit(100, 0)
+	params = append(params, query.AccountId)
+
+	if query.IsStarred {
+		sql.WriteString(` AND star.user_id=?`)
+		params = append(params, query.UserId)
+	}
+
+	if len(query.Title) > 0 {
+		sql.WriteString(" AND dashboard.title LIKE ?")
+		params = append(params, "%"+query.Title+"%")
+	}
 
 	if len(query.Tag) > 0 {
-		sess.And("dashboard_tag.term=?", query.Tag)
+		sql.WriteString(" AND dashboard_tag.term=?")
+		params = append(params, query.Tag)
 	}
 
 	var res []DashboardSearchProjection
-	err := sess.Find(&res)
+	err := x.Sql(sql.String(), params...).Find(&res)
 	if err != nil {
 		return err
 	}

+ 39 - 15
pkg/services/sqlstore/dashboard_test.go

@@ -8,27 +8,29 @@ import (
 	m "github.com/torkelo/grafana-pro/pkg/models"
 )
 
+func insertTestDashboard(title string, accountId int64, tags ...interface{}) *m.Dashboard {
+	cmd := m.SaveDashboardCommand{
+		AccountId: accountId,
+		Dashboard: map[string]interface{}{
+			"id":    nil,
+			"title": title,
+			"tags":  tags,
+		},
+	}
+
+	err := SaveDashboard(&cmd)
+	So(err, ShouldBeNil)
+
+	return cmd.Result
+}
+
 func TestDashboardDataAccess(t *testing.T) {
 
 	Convey("Testing DB", t, func() {
 		InitTestDB(t)
 
 		Convey("Given saved dashboard", func() {
-			var savedDash *m.Dashboard
-
-			cmd := m.SaveDashboardCommand{
-				AccountId: 1,
-				Dashboard: map[string]interface{}{
-					"id":    nil,
-					"title": "test dash 23",
-					"tags":  []interface{}{"prod", "webapp"},
-				},
-			}
-
-			err := SaveDashboard(&cmd)
-			So(err, ShouldBeNil)
-
-			savedDash = cmd.Result
+			savedDash := insertTestDashboard("test dash 23", 1, "prod", "webapp")
 
 			Convey("Should return dashboard model", func() {
 				So(savedDash.Title, ShouldEqual, "test dash 23")
@@ -97,6 +99,28 @@ func TestDashboardDataAccess(t *testing.T) {
 
 				So(len(query.Result), ShouldEqual, 2)
 			})
+
+			Convey("Given two dashboards, one is starred dashboard by user 10, other starred by user 1", func() {
+				starredDash := insertTestDashboard("starred dash", 1)
+				StarDashboard(&m.StarDashboardCommand{
+					DashboardId: starredDash.Id,
+					UserId:      10,
+				})
+
+				StarDashboard(&m.StarDashboardCommand{
+					DashboardId: savedDash.Id,
+					UserId:      1,
+				})
+
+				Convey("Should be able to search for starred dashboards", func() {
+					query := m.SearchDashboardsQuery{AccountId: 1, UserId: 10, IsStarred: true}
+					err := SearchDashboards(&query)
+
+					So(err, ShouldBeNil)
+					So(len(query.Result), ShouldEqual, 1)
+					So(query.Result[0].Title, ShouldEqual, "starred dash")
+				})
+			})
 		})
 	})
 }

+ 1 - 1
pkg/services/sqlstore/migrations.go

@@ -36,7 +36,7 @@ func addUserMigrations(mg *Migrator) {
 		&Column{Name: "login", Type: DB_NVarchar, Length: 255, Nullable: false},
 		&Column{Name: "email", Type: DB_NVarchar, Length: 255, Nullable: false},
 		&Column{Name: "name", Type: DB_NVarchar, Length: 255, Nullable: true},
-		&Column{Name: "password", Type: DB_NVarchar, Length: 50, Nullable: true},
+		&Column{Name: "password", Type: DB_NVarchar, Length: 255, Nullable: true},
 		&Column{Name: "salt", Type: DB_NVarchar, Length: 50, Nullable: true},
 		&Column{Name: "company", Type: DB_NVarchar, Length: 255, Nullable: true},
 		&Column{Name: "account_id", Type: DB_BigInt, Nullable: false},

+ 1 - 1
pkg/services/sqlstore/migrator/dialect.go

@@ -95,7 +95,7 @@ func (b *BaseDialect) CreateTableSql(table *Table) string {
 }
 
 func (db *BaseDialect) AddColumnSql(tableName string, col *Column) string {
-	return fmt.Sprintf("alter table %s ADD COLUMN %s", tableName, col.StringNoPk(db.dialect))
+	return fmt.Sprintf("alter table %s ADD COLUMN %s", db.dialect.Quote(tableName), col.StringNoPk(db.dialect))
 }
 
 func (db *BaseDialect) CreateIndexSql(tableName string, index *Index) string {

+ 2 - 3
pkg/services/sqlstore/star.go

@@ -1,8 +1,6 @@
 package sqlstore
 
 import (
-	"strconv"
-
 	"github.com/go-xorm/xorm"
 
 	"github.com/torkelo/grafana-pro/pkg/bus"
@@ -23,11 +21,12 @@ func IsStarredByUser(query *m.IsStarredByUserQuery) error {
 	if err != nil {
 		return err
 	}
+
 	if len(results) == 0 {
 		return nil
 	}
 
-	query.Result, _ = strconv.ParseBool(string(results[0]["1"]))
+	query.Result = true
 
 	return nil
 }

+ 5 - 3
pkg/services/sqlstore/user.go

@@ -69,9 +69,11 @@ func CreateUser(cmd *m.CreateUserCommand) error {
 			Updated:   time.Now(),
 		}
 
-		user.Salt = util.GetRandomString(10)
-		user.Rands = util.GetRandomString(10)
-		user.Password = util.EncodePassword(cmd.Password, user.Salt)
+		if len(cmd.Password) > 0 {
+			user.Salt = util.GetRandomString(10)
+			user.Rands = util.GetRandomString(10)
+			user.Password = util.EncodePassword(cmd.Password, user.Salt)
+		}
 
 		sess.UseBool("is_admin")
 

+ 4 - 0
pkg/setting/setting.go

@@ -148,6 +148,10 @@ func parseAppUrlAndSubUrl(section *ini.Section) (string, string) {
 	return appUrl, appSubUrl
 }
 
+func AbsUrlTo(relativeUrl string) string {
+	return AppUrl + relativeUrl
+}
+
 func NewConfigContext() {
 	configFiles := findConfigFiles()