diff --git a/pkg/api/dashboard.go b/pkg/api/dashboard.go index 3e7ad57f368..7c8e1cdc9bb 100644 --- a/pkg/api/dashboard.go +++ b/pkg/api/dashboard.go @@ -88,13 +88,13 @@ func GetDashboard(c *middleware.Context) Response { Version: dash.Version, HasAcl: dash.HasAcl, IsFolder: dash.IsFolder, - FolderId: dash.ParentId, + FolderId: dash.FolderId, FolderTitle: "Root", } // lookup folder title - if dash.ParentId > 0 { - query := m.GetDashboardQuery{Id: dash.ParentId, OrgId: c.OrgId} + if dash.FolderId > 0 { + query := m.GetDashboardQuery{Id: dash.FolderId, OrgId: c.OrgId} if err := bus.Dispatch(&query); err != nil { return ApiError(500, "Dashboard folder could not be read", err) } @@ -170,7 +170,7 @@ func PostDashboard(c *middleware.Context, cmd m.SaveDashboardCommand) Response { return dashboardGuardianResponse(err) } - if dash.IsFolder && dash.ParentId > 0 { + if dash.IsFolder && dash.FolderId > 0 { return ApiError(400, m.ErrDashboardFolderCannotHaveParent.Error(), nil) } diff --git a/pkg/api/dashboard_test.go b/pkg/api/dashboard_test.go index 446bffcad98..cd27639c4e4 100644 --- a/pkg/api/dashboard_test.go +++ b/pkg/api/dashboard_test.go @@ -22,7 +22,7 @@ func TestDashboardApiEndpoint(t *testing.T) { Convey("Given a dashboard with a parent folder which does not have an acl", t, func() { fakeDash := m.NewDashboard("Child dash") fakeDash.Id = 1 - fakeDash.ParentId = 1 + fakeDash.FolderId = 1 fakeDash.HasAcl = false bus.AddHandler("test", func(query *m.GetDashboardQuery) error { @@ -50,7 +50,7 @@ func TestDashboardApiEndpoint(t *testing.T) { cmd := m.SaveDashboardCommand{ Dashboard: simplejson.NewFromAny(map[string]interface{}{ - "parentId": fakeDash.ParentId, + "folderId": fakeDash.FolderId, "title": fakeDash.Title, "id": fakeDash.Id, }), @@ -163,10 +163,10 @@ func TestDashboardApiEndpoint(t *testing.T) { return nil }) invalidCmd := m.SaveDashboardCommand{ - ParentId: fakeDash.ParentId, + FolderId: fakeDash.FolderId, IsFolder: true, Dashboard: simplejson.NewFromAny(map[string]interface{}{ - "parentId": fakeDash.ParentId, + "folderId": fakeDash.FolderId, "title": fakeDash.Title, }), } @@ -183,7 +183,7 @@ func TestDashboardApiEndpoint(t *testing.T) { Convey("Given a dashboard with a parent folder which has an acl", t, func() { fakeDash := m.NewDashboard("Child dash") fakeDash.Id = 1 - fakeDash.ParentId = 1 + fakeDash.FolderId = 1 fakeDash.HasAcl = true aclMockResp := []*m.DashboardAclInfoDTO{ @@ -210,10 +210,10 @@ func TestDashboardApiEndpoint(t *testing.T) { }) cmd := m.SaveDashboardCommand{ - ParentId: fakeDash.ParentId, + FolderId: fakeDash.FolderId, Dashboard: simplejson.NewFromAny(map[string]interface{}{ "id": fakeDash.Id, - "parentId": fakeDash.ParentId, + "folderId": fakeDash.FolderId, "title": fakeDash.Title, }), } diff --git a/pkg/models/dashboards.go b/pkg/models/dashboards.go index 35f761d9936..eadf4cd15e5 100644 --- a/pkg/models/dashboards.go +++ b/pkg/models/dashboards.go @@ -48,7 +48,7 @@ type Dashboard struct { UpdatedBy int64 CreatedBy int64 - ParentId int64 + FolderId int64 IsFolder bool HasAcl bool @@ -116,7 +116,7 @@ func (cmd *SaveDashboardCommand) GetDashboardModel() *Dashboard { dash.OrgId = cmd.OrgId dash.PluginId = cmd.PluginId dash.IsFolder = cmd.IsFolder - dash.ParentId = cmd.ParentId + dash.FolderId = cmd.FolderId dash.UpdateSlug() return dash } @@ -144,7 +144,7 @@ type SaveDashboardCommand struct { OrgId int64 `json:"-"` RestoredFrom int `json:"-"` PluginId string `json:"-"` - ParentId int64 `json:"parentId"` + FolderId int64 `json:"folderId"` IsFolder bool `json:"isFolder"` Result *Dashboard diff --git a/pkg/models/dashboards_test.go b/pkg/models/dashboards_test.go index a527e5b3891..0ec773dfb97 100644 --- a/pkg/models/dashboards_test.go +++ b/pkg/models/dashboards_test.go @@ -44,11 +44,11 @@ func TestDashboardModel(t *testing.T) { json := simplejson.New() json.Set("title", "test dash") - cmd := &SaveDashboardCommand{Dashboard: json, ParentId: 1} + cmd := &SaveDashboardCommand{Dashboard: json, FolderId: 1} dash := cmd.GetDashboardModel() - Convey("Should set ParentId", func() { - So(dash.ParentId, ShouldEqual, 1) + Convey("Should set FolderId", func() { + So(dash.FolderId, ShouldEqual, 1) }) }) } diff --git a/pkg/services/search/handlers.go b/pkg/services/search/handlers.go index 1b7eab79720..44fd4d9da45 100644 --- a/pkg/services/search/handlers.go +++ b/pkg/services/search/handlers.go @@ -44,7 +44,7 @@ func searchHandler(query *Query) error { IsStarred: query.IsStarred, DashboardIds: query.DashboardIds, Type: query.Type, - ParentId: query.FolderId, + FolderId: query.FolderId, Mode: query.Mode, } diff --git a/pkg/services/search/handlers_test.go b/pkg/services/search/handlers_test.go index 18b7453271e..3f6ede3e572 100644 --- a/pkg/services/search/handlers_test.go +++ b/pkg/services/search/handlers_test.go @@ -20,9 +20,7 @@ func TestSearch(t *testing.T) { &Hit{Id: 10, Title: "AABB", Type: "dash-db", Tags: []string{"CC", "AA"}}, &Hit{Id: 15, Title: "BBAA", Type: "dash-db", Tags: []string{"EE", "AA", "BB"}}, &Hit{Id: 25, Title: "bbAAa", Type: "dash-db", Tags: []string{"EE", "AA", "BB"}}, - &Hit{Id: 17, Title: "FOLDER", Type: "dash-folder", Dashboards: []Hit{ - {Id: 18, Title: "ZZAA", Tags: []string{"ZZ"}}, - }}, + &Hit{Id: 17, Title: "FOLDER", Type: "dash-folder"}, } return nil }) diff --git a/pkg/services/search/models.go b/pkg/services/search/models.go index 8f6a42ac40a..5940a824b6a 100644 --- a/pkg/services/search/models.go +++ b/pkg/services/search/models.go @@ -14,14 +14,15 @@ const ( ) type Hit struct { - Id int64 `json:"id"` - Title string `json:"title"` - Uri string `json:"uri"` - Type HitType `json:"type"` - Tags []string `json:"tags"` - IsStarred bool `json:"isStarred"` - ParentId int64 `json:"parentId"` - Dashboards []Hit `json:"dashboards"` + Id int64 `json:"id"` + Title string `json:"title"` + Uri string `json:"uri"` + Type HitType `json:"type"` + Tags []string `json:"tags"` + IsStarred bool `json:"isStarred"` + FolderId int64 `json:"folderId,omitempty"` + FolderTitle string `json:"folderTitle,omitempty"` + FolderSlug string `json:"folderSlug,omitempty"` } type HitList []*Hit @@ -62,7 +63,7 @@ type FindPersistedDashboardsQuery struct { IsStarred bool DashboardIds []int64 Type string - ParentId int64 + FolderId int64 Mode string Result HitList diff --git a/pkg/services/sqlstore/dashboard.go b/pkg/services/sqlstore/dashboard.go index 447b8a74a48..4e93325efc0 100644 --- a/pkg/services/sqlstore/dashboard.go +++ b/pkg/services/sqlstore/dashboard.go @@ -81,7 +81,7 @@ func SaveDashboard(cmd *m.SaveDashboardCommand) error { } else { dash.Version += 1 dash.Data.Set("version", dash.Version) - affectedRows, err = sess.MustCols("parent_id").Id(dash.Id).Update(dash) + affectedRows, err = sess.MustCols("folder_id").Id(dash.Id).Update(dash) } if err != nil { @@ -153,7 +153,7 @@ type DashboardSearchProjection struct { Slug string Term string IsFolder bool - ParentId int64 + FolderId int64 FolderSlug string FolderTitle string } @@ -168,11 +168,11 @@ func findDashboards(query *search.FindPersistedDashboardsQuery) ([]DashboardSear dashboard.slug, dashboard_tag.term, dashboard.is_folder, - dashboard.parent_id, + dashboard.folder_id, f.slug as folder_slug, f.title as folder_title FROM dashboard - LEFT OUTER JOIN dashboard f on f.id = dashboard.parent_id + LEFT OUTER JOIN dashboard f on f.id = dashboard.folder_id LEFT OUTER JOIN dashboard_tag on dashboard_tag.dashboard_id = dashboard.id`) if query.IsStarred { @@ -204,7 +204,7 @@ func findDashboards(query *search.FindPersistedDashboardsQuery) ([]DashboardSear allowedDashboardsSubQuery := ` AND (dashboard.has_acl = 0 OR dashboard.id in ( SELECT distinct d.id AS DashboardId FROM dashboard AS d - LEFT JOIN dashboard_acl as da on d.parent_id = da.dashboard_id or d.id = da.dashboard_id + LEFT JOIN dashboard_acl as da on d.folder_id = da.dashboard_id or d.id = da.dashboard_id LEFT JOIN user_group_member as ugm on ugm.user_group_id = da.user_group_id LEFT JOIN org_user ou on ou.role = da.role WHERE @@ -230,9 +230,9 @@ func findDashboards(query *search.FindPersistedDashboardsQuery) ([]DashboardSear sql.WriteString(" AND dashboard.is_folder = 0") } - if query.ParentId > 0 { - sql.WriteString(" AND dashboard.parent_id = ?") - params = append(params, query.ParentId) + if query.FolderId > 0 { + sql.WriteString(" AND dashboard.folder_id = ?") + params = append(params, query.FolderId) } sql.WriteString(fmt.Sprintf(" ORDER BY dashboard.title ASC LIMIT 1000")) @@ -253,38 +253,11 @@ func SearchDashboards(query *search.FindPersistedDashboardsQuery) error { return err } - if query.Mode == "tree" { - res, err = appendDashboardFolders(res) - if err != nil { - return err - } - } - makeQueryResult(query, res) - if query.Mode == "tree" { - convertToDashboardFolders(query) - } - return nil } -// appends parent folders for any hits to the search result -func appendDashboardFolders(res []DashboardSearchProjection) ([]DashboardSearchProjection, error) { - for _, item := range res { - if item.ParentId > 0 { - res = append(res, DashboardSearchProjection{ - Id: item.ParentId, - IsFolder: true, - Slug: item.FolderSlug, - Title: item.FolderTitle, - }) - } - } - - return res, nil -} - func getHitType(item DashboardSearchProjection) search.HitType { var hitType search.HitType if item.IsFolder { @@ -304,12 +277,14 @@ func makeQueryResult(query *search.FindPersistedDashboardsQuery, res []Dashboard hit, exists := hits[item.Id] if !exists { hit = &search.Hit{ - Id: item.Id, - Title: item.Title, - Uri: "db/" + item.Slug, - Type: getHitType(item), - ParentId: item.ParentId, - Tags: []string{}, + Id: item.Id, + Title: item.Title, + Uri: "db/" + item.Slug, + Type: getHitType(item), + FolderId: item.FolderId, + FolderTitle: item.FolderTitle, + FolderSlug: item.FolderSlug, + Tags: []string{}, } query.Result = append(query.Result, hit) hits[item.Id] = hit @@ -320,34 +295,6 @@ func makeQueryResult(query *search.FindPersistedDashboardsQuery, res []Dashboard } } -func convertToDashboardFolders(query *search.FindPersistedDashboardsQuery) error { - root := make(map[int64]*search.Hit) - var keys []int64 - - // Add dashboards and folders that should be at the root level - for _, item := range query.Result { - if item.Type == search.DashHitFolder || item.ParentId == 0 { - root[item.Id] = item - keys = append(keys, item.Id) - } - } - - // Populate folders with their child dashboards - for _, item := range query.Result { - if item.Type == search.DashHitDB && item.ParentId > 0 { - root[item.ParentId].Dashboards = append(root[item.ParentId].Dashboards, *item) - } - } - - query.Result = make([]*search.Hit, 0) - - for _, key := range keys { - query.Result = append(query.Result, root[key]) - } - - return nil -} - func GetDashboardTags(query *m.GetDashboardTagsQuery) error { sql := `SELECT COUNT(*) as count, @@ -379,7 +326,7 @@ func DeleteDashboard(cmd *m.DeleteDashboardCommand) error { "DELETE FROM dashboard WHERE id = ?", "DELETE FROM playlist_item WHERE type = 'dashboard_by_id' AND value = ?", "DELETE FROM dashboard_version WHERE dashboard_id = ?", - "DELETE FROM dashboard WHERE parent_id = ?", + "DELETE FROM dashboard WHERE folder_id = ?", } for _, sql := range deletes { diff --git a/pkg/services/sqlstore/dashboard_acl.go b/pkg/services/sqlstore/dashboard_acl.go index dbe6ac9f23a..43c582f6c73 100644 --- a/pkg/services/sqlstore/dashboard_acl.go +++ b/pkg/services/sqlstore/dashboard_acl.go @@ -40,7 +40,7 @@ func UpdateDashboardAcl(cmd *m.UpdateDashboardAclCommand) error { // Update dashboard HasAcl flag dashboard := m.Dashboard{HasAcl: true} - if _, err := sess.Cols("has_acl").Where("id=? OR parent_id=?", cmd.DashboardId, cmd.DashboardId).Update(&dashboard); err != nil { + if _, err := sess.Cols("has_acl").Where("id=? OR folder_id=?", cmd.DashboardId, cmd.DashboardId).Update(&dashboard); err != nil { return err } return nil @@ -105,7 +105,7 @@ func SetDashboardAcl(cmd *m.SetDashboardAclCommand) error { HasAcl: true, } - if _, err := sess.Cols("has_acl").Where("id=? OR parent_id=?", cmd.DashboardId, cmd.DashboardId).Update(&dashboard); err != nil { + if _, err := sess.Cols("has_acl").Where("id=? OR folder_id=?", cmd.DashboardId, cmd.DashboardId).Update(&dashboard); err != nil { return err } @@ -129,7 +129,7 @@ func GetDashboardAclInfoList(query *m.GetDashboardAclInfoListQuery) error { dashboardFilter := fmt.Sprintf(`IN ( SELECT %d UNION - SELECT parent_id from dashboard where id = %d + SELECT folder_id from dashboard where id = %d )`, query.DashboardId, query.DashboardId) rawSQL := ` diff --git a/pkg/services/sqlstore/dashboard_test.go b/pkg/services/sqlstore/dashboard_test.go index 7e5301c061e..541f71271cd 100644 --- a/pkg/services/sqlstore/dashboard_test.go +++ b/pkg/services/sqlstore/dashboard_test.go @@ -11,10 +11,10 @@ import ( "github.com/grafana/grafana/pkg/setting" ) -func insertTestDashboard(title string, orgId int64, parentId int64, isFolder bool, tags ...interface{}) *m.Dashboard { +func insertTestDashboard(title string, orgId int64, folderId int64, isFolder bool, tags ...interface{}) *m.Dashboard { cmd := m.SaveDashboardCommand{ OrgId: orgId, - ParentId: parentId, + FolderId: folderId, IsFolder: isFolder, Dashboard: simplejson.NewFromAny(map[string]interface{}{ "id": nil, @@ -45,13 +45,13 @@ func TestDashboardDataAccess(t *testing.T) { So(savedDash.Slug, ShouldEqual, "test-dash-23") So(savedDash.Id, ShouldNotEqual, 0) So(savedDash.IsFolder, ShouldBeFalse) - So(savedDash.ParentId, ShouldBeGreaterThan, 0) + So(savedDash.FolderId, ShouldBeGreaterThan, 0) So(savedFolder.Title, ShouldEqual, "1 test dash folder") So(savedFolder.Slug, ShouldEqual, "1-test-dash-folder") So(savedFolder.Id, ShouldNotEqual, 0) So(savedFolder.IsFolder, ShouldBeTrue) - So(savedFolder.ParentId, ShouldEqual, 0) + So(savedFolder.FolderId, ShouldEqual, 0) }) Convey("Should be able to get dashboard", func() { @@ -112,26 +112,6 @@ func TestDashboardDataAccess(t *testing.T) { So(err, ShouldNotBeNil) }) - Convey("Should be able to search for dashboard and return in folder hierarchy", func() { - query := search.FindPersistedDashboardsQuery{ - Title: "test dash 23", - OrgId: 1, - Mode: "tree", - SignedInUser: &m.SignedInUser{OrgId: 1}, - } - - err := SearchDashboards(&query) - So(err, ShouldBeNil) - - So(len(query.Result), ShouldEqual, 1) - hit := query.Result[0].Dashboards[0] - - So(len(hit.Tags), ShouldEqual, 2) - So(hit.Type, ShouldEqual, search.DashHitDB) - So(hit.ParentId, ShouldBeGreaterThan, 0) - - }) - Convey("Should be able to search for dashboard folder", func() { query := search.FindPersistedDashboardsQuery{ Title: "1 test dash folder", @@ -150,7 +130,7 @@ func TestDashboardDataAccess(t *testing.T) { Convey("Should be able to search for a dashboard folder's children", func() { query := search.FindPersistedDashboardsQuery{ OrgId: 1, - ParentId: savedFolder.Id, + FolderId: savedFolder.Id, SignedInUser: &m.SignedInUser{OrgId: 1}, } @@ -166,19 +146,18 @@ func TestDashboardDataAccess(t *testing.T) { Convey("should be able to find two dashboards by id", func() { query := search.FindPersistedDashboardsQuery{ DashboardIds: []int64{2, 3}, - Mode: "tree", SignedInUser: &m.SignedInUser{OrgId: 1}, } err := SearchDashboards(&query) So(err, ShouldBeNil) - So(len(query.Result[0].Dashboards), ShouldEqual, 2) + So(len(query.Result), ShouldEqual, 2) - hit := query.Result[0].Dashboards[0] + hit := query.Result[0] So(len(hit.Tags), ShouldEqual, 2) - hit2 := query.Result[0].Dashboards[1] + hit2 := query.Result[1] So(len(hit2.Tags), ShouldEqual, 1) }) @@ -208,30 +187,30 @@ func TestDashboardDataAccess(t *testing.T) { So(err, ShouldNotBeNil) }) - Convey("Should be able to update dashboard and remove parentId", func() { + Convey("Should be able to update dashboard and remove folderId", func() { cmd := m.SaveDashboardCommand{ OrgId: 1, Dashboard: simplejson.NewFromAny(map[string]interface{}{ "id": 1, - "title": "parentId", + "title": "folderId", "tags": []interface{}{}, }), Overwrite: true, - ParentId: 2, + FolderId: 2, } err := SaveDashboard(&cmd) So(err, ShouldBeNil) - So(cmd.Result.ParentId, ShouldEqual, 2) + So(cmd.Result.FolderId, ShouldEqual, 2) cmd = m.SaveDashboardCommand{ OrgId: 1, Dashboard: simplejson.NewFromAny(map[string]interface{}{ "id": 1, - "title": "parentId", + "title": "folderId", "tags": []interface{}{}, }), - ParentId: 0, + FolderId: 0, Overwrite: true, } @@ -245,7 +224,7 @@ func TestDashboardDataAccess(t *testing.T) { err = GetDashboard(&query) So(err, ShouldBeNil) - So(query.Result.ParentId, ShouldEqual, 0) + So(query.Result.FolderId, ShouldEqual, 0) }) Convey("Should be able to delete a dashboard folder and its children", func() { @@ -255,7 +234,7 @@ func TestDashboardDataAccess(t *testing.T) { query := search.FindPersistedDashboardsQuery{ OrgId: 1, - ParentId: savedFolder.Id, + FolderId: savedFolder.Id, SignedInUser: &m.SignedInUser{}, } diff --git a/pkg/services/sqlstore/migrations/dashboard_mig.go b/pkg/services/sqlstore/migrations/dashboard_mig.go index 869196c04d5..ed8d2c73a5d 100644 --- a/pkg/services/sqlstore/migrations/dashboard_mig.go +++ b/pkg/services/sqlstore/migrations/dashboard_mig.go @@ -137,9 +137,9 @@ func addDashboardMigration(mg *Migrator) { {Name: "term", Type: DB_NVarchar, Length: 50, Nullable: false}, })) - // add column to store parent_id for dashboard folder structure - mg.AddMigration("Add column parent_id in dashboard", NewAddColumnMigration(dashboardV2, &Column{ - Name: "parent_id", Type: DB_BigInt, Nullable: true, + // add column to store folder_id for dashboard folder structure + mg.AddMigration("Add column folder_id in dashboard", NewAddColumnMigration(dashboardV2, &Column{ + Name: "folder_id", Type: DB_BigInt, Nullable: true, })) mg.AddMigration("Add column isFolder in dashboard", NewAddColumnMigration(dashboardV2, &Column{ diff --git a/public/app/core/components/search/search.html b/public/app/core/components/search/search.html index 103e526e2a7..a1816ede44e 100644 --- a/public/app/core/components/search/search.html +++ b/public/app/core/components/search/search.html @@ -53,8 +53,8 @@