Merge pull request #1169 from influxdata/feature/dashboard-description
feat(dashboard): add description fields to dashboardpull/10616/head
commit
287082129f
|
@ -356,6 +356,10 @@ func (c *Client) forEachDashboard(ctx context.Context, tx *bolt.Tx, fn func(*pla
|
||||||
|
|
||||||
// UpdateDashboard updates a dashboard according the parameters set on upd.
|
// UpdateDashboard updates a dashboard according the parameters set on upd.
|
||||||
func (c *Client) UpdateDashboard(ctx context.Context, id platform.ID, upd platform.DashboardUpdate) (*platform.Dashboard, error) {
|
func (c *Client) UpdateDashboard(ctx context.Context, id platform.ID, upd platform.DashboardUpdate) (*platform.Dashboard, error) {
|
||||||
|
if err := upd.Valid(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
var d *platform.Dashboard
|
var d *platform.Dashboard
|
||||||
err := c.db.Update(func(tx *bolt.Tx) error {
|
err := c.db.Update(func(tx *bolt.Tx) error {
|
||||||
dash, err := c.updateDashboard(ctx, tx, id, upd)
|
dash, err := c.updateDashboard(ctx, tx, id, upd)
|
||||||
|
|
46
dashboard.go
46
dashboard.go
|
@ -45,9 +45,10 @@ type DashboardService interface {
|
||||||
|
|
||||||
// Dashboard represents all visual and query data for a dashboard
|
// Dashboard represents all visual and query data for a dashboard
|
||||||
type Dashboard struct {
|
type Dashboard struct {
|
||||||
ID ID `json:"id,omitempty"`
|
ID ID `json:"id,omitempty"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Cells []*Cell `json:"cells"`
|
Description string `json:"description"`
|
||||||
|
Cells []*Cell `json:"cells"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cell holds positional information about a cell on dashboard and a reference to a cell.
|
// Cell holds positional information about a cell on dashboard and a reference to a cell.
|
||||||
|
@ -67,14 +68,8 @@ type DashboardFilter struct {
|
||||||
|
|
||||||
// DashboardUpdate is the patch structure for a dashboard.
|
// DashboardUpdate is the patch structure for a dashboard.
|
||||||
type DashboardUpdate struct {
|
type DashboardUpdate struct {
|
||||||
Name *string `json:"name"`
|
Name *string `json:"name"`
|
||||||
}
|
Description *string `json:"description"`
|
||||||
|
|
||||||
// AddDashboardCellOptions are options for adding a dashboard.
|
|
||||||
type AddDashboardCellOptions struct {
|
|
||||||
// UsingView specifies the view that should be used as a template
|
|
||||||
// for the new cells view.
|
|
||||||
UsingView ID
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply applies an update to a dashboard.
|
// Apply applies an update to a dashboard.
|
||||||
|
@ -83,9 +78,29 @@ func (u DashboardUpdate) Apply(d *Dashboard) error {
|
||||||
d.Name = *u.Name
|
d.Name = *u.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if u.Description != nil {
|
||||||
|
d.Description = *u.Description
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Valid returns an error if the dashboard update is invalid.
|
||||||
|
func (u DashboardUpdate) Valid() error {
|
||||||
|
if u.Name == nil && u.Description == nil {
|
||||||
|
return fmt.Errorf("must update at least one attribute")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddDashboardCellOptions are options for adding a dashboard.
|
||||||
|
type AddDashboardCellOptions struct {
|
||||||
|
// UsingView specifies the view that should be used as a template
|
||||||
|
// for the new cells view.
|
||||||
|
UsingView ID
|
||||||
|
}
|
||||||
|
|
||||||
// CellUpdate is the patch structure for a cell.
|
// CellUpdate is the patch structure for a cell.
|
||||||
type CellUpdate struct {
|
type CellUpdate struct {
|
||||||
X *int32 `json:"x"`
|
X *int32 `json:"x"`
|
||||||
|
@ -119,12 +134,3 @@ func (u CellUpdate) Apply(c *Cell) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid returns an error if the dashboard update is invalid.
|
|
||||||
func (u DashboardUpdate) Valid() error {
|
|
||||||
if u.Name == nil {
|
|
||||||
return fmt.Errorf("must update at least one attribute")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -43,8 +43,9 @@ func TestService_handleGetDashboards(t *testing.T) {
|
||||||
FindDashboardsF: func(ctx context.Context, filter platform.DashboardFilter) ([]*platform.Dashboard, int, error) {
|
FindDashboardsF: func(ctx context.Context, filter platform.DashboardFilter) ([]*platform.Dashboard, int, error) {
|
||||||
return []*platform.Dashboard{
|
return []*platform.Dashboard{
|
||||||
{
|
{
|
||||||
ID: platformtesting.MustIDBase16("da7aba5e5d81e550"),
|
ID: platformtesting.MustIDBase16("da7aba5e5d81e550"),
|
||||||
Name: "hello",
|
Name: "hello",
|
||||||
|
Description: "oh hello there!",
|
||||||
Cells: []*platform.Cell{
|
Cells: []*platform.Cell{
|
||||||
{
|
{
|
||||||
ID: platformtesting.MustIDBase16("da7aba5e5d81e550"),
|
ID: platformtesting.MustIDBase16("da7aba5e5d81e550"),
|
||||||
|
@ -77,6 +78,7 @@ func TestService_handleGetDashboards(t *testing.T) {
|
||||||
{
|
{
|
||||||
"id": "da7aba5e5d81e550",
|
"id": "da7aba5e5d81e550",
|
||||||
"name": "hello",
|
"name": "hello",
|
||||||
|
"description": "oh hello there!",
|
||||||
"cells": [
|
"cells": [
|
||||||
{
|
{
|
||||||
"id": "da7aba5e5d81e550",
|
"id": "da7aba5e5d81e550",
|
||||||
|
@ -99,6 +101,7 @@ func TestService_handleGetDashboards(t *testing.T) {
|
||||||
{
|
{
|
||||||
"id": "0ca2204eca2204e0",
|
"id": "0ca2204eca2204e0",
|
||||||
"name": "example",
|
"name": "example",
|
||||||
|
"description": "",
|
||||||
"cells": [],
|
"cells": [],
|
||||||
"links": {
|
"links": {
|
||||||
"self": "/api/v2/dashboards/0ca2204eca2204e0",
|
"self": "/api/v2/dashboards/0ca2204eca2204e0",
|
||||||
|
@ -227,6 +230,7 @@ func TestService_handleGetDashboard(t *testing.T) {
|
||||||
{
|
{
|
||||||
"id": "020f755c3c082000",
|
"id": "020f755c3c082000",
|
||||||
"name": "hello",
|
"name": "hello",
|
||||||
|
"description": "",
|
||||||
"cells": [
|
"cells": [
|
||||||
{
|
{
|
||||||
"id": "da7aba5e5d81e550",
|
"id": "da7aba5e5d81e550",
|
||||||
|
@ -337,8 +341,9 @@ func TestService_handlePostDashboard(t *testing.T) {
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
dashboard: &platform.Dashboard{
|
dashboard: &platform.Dashboard{
|
||||||
ID: platformtesting.MustIDBase16("020f755c3c082000"),
|
ID: platformtesting.MustIDBase16("020f755c3c082000"),
|
||||||
Name: "hello",
|
Name: "hello",
|
||||||
|
Description: "howdy there",
|
||||||
Cells: []*platform.Cell{
|
Cells: []*platform.Cell{
|
||||||
{
|
{
|
||||||
ID: platformtesting.MustIDBase16("da7aba5e5d81e550"),
|
ID: platformtesting.MustIDBase16("da7aba5e5d81e550"),
|
||||||
|
@ -358,6 +363,7 @@ func TestService_handlePostDashboard(t *testing.T) {
|
||||||
{
|
{
|
||||||
"id": "020f755c3c082000",
|
"id": "020f755c3c082000",
|
||||||
"name": "hello",
|
"name": "hello",
|
||||||
|
"description": "howdy there",
|
||||||
"cells": [
|
"cells": [
|
||||||
{
|
{
|
||||||
"id": "da7aba5e5d81e550",
|
"id": "da7aba5e5d81e550",
|
||||||
|
@ -575,6 +581,7 @@ func TestService_handlePatchDashboard(t *testing.T) {
|
||||||
{
|
{
|
||||||
"id": "020f755c3c082000",
|
"id": "020f755c3c082000",
|
||||||
"name": "example",
|
"name": "example",
|
||||||
|
"description": "",
|
||||||
"cells": [
|
"cells": [
|
||||||
{
|
{
|
||||||
"id": "da7aba5e5d81e550",
|
"id": "da7aba5e5d81e550",
|
||||||
|
|
|
@ -4394,6 +4394,10 @@ components:
|
||||||
type: string
|
type: string
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
|
description: user-facing name of the dashboard
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
description: user-facing description of the dashboard
|
||||||
cells:
|
cells:
|
||||||
$ref: "#/components/schemas/Cells"
|
$ref: "#/components/schemas/Cells"
|
||||||
Dashboards:
|
Dashboards:
|
||||||
|
|
|
@ -83,17 +83,21 @@ func (s *Service) PutDashboard(ctx context.Context, o *platform.Dashboard) error
|
||||||
|
|
||||||
// UpdateDashboard implements platform.DashboardService interface.
|
// UpdateDashboard implements platform.DashboardService interface.
|
||||||
func (s *Service) UpdateDashboard(ctx context.Context, id platform.ID, upd platform.DashboardUpdate) (*platform.Dashboard, error) {
|
func (s *Service) UpdateDashboard(ctx context.Context, id platform.ID, upd platform.DashboardUpdate) (*platform.Dashboard, error) {
|
||||||
o, err := s.FindDashboardByID(ctx, id)
|
if err := upd.Valid(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
d, err := s.FindDashboardByID(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if upd.Name != nil {
|
if err := upd.Apply(d); err != nil {
|
||||||
o.Name = *upd.Name
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.dashboardKV.Store(o.ID.String(), o)
|
s.dashboardKV.Store(d.ID.String(), d)
|
||||||
return o, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteDashboard implements platform.DashboardService interface.
|
// DeleteDashboard implements platform.DashboardService interface.
|
||||||
|
@ -105,6 +109,7 @@ func (s *Service) DeleteDashboard(ctx context.Context, id platform.ID) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddDashboardCell adds a new cell to the dashboard.
|
||||||
func (s *Service) AddDashboardCell(ctx context.Context, id platform.ID, cell *platform.Cell, opts platform.AddDashboardCellOptions) error {
|
func (s *Service) AddDashboardCell(ctx context.Context, id platform.ID, cell *platform.Cell, opts platform.AddDashboardCellOptions) error {
|
||||||
d, err := s.FindDashboardByID(ctx, id)
|
d, err := s.FindDashboardByID(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -119,6 +124,7 @@ func (s *Service) AddDashboardCell(ctx context.Context, id platform.ID, cell *pl
|
||||||
return s.PutDashboard(ctx, d)
|
return s.PutDashboard(ctx, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PutDashboardCell replaces a dashboad cell with the cell contents.
|
||||||
func (s *Service) PutDashboardCell(ctx context.Context, id platform.ID, cell *platform.Cell) error {
|
func (s *Service) PutDashboardCell(ctx context.Context, id platform.ID, cell *platform.Cell) error {
|
||||||
d, err := s.FindDashboardByID(ctx, id)
|
d, err := s.FindDashboardByID(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -134,6 +140,7 @@ func (s *Service) PutDashboardCell(ctx context.Context, id platform.ID, cell *pl
|
||||||
return s.PutDashboard(ctx, d)
|
return s.PutDashboard(ctx, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveDashboardCell removes a dashboard cell from the dashboard.
|
||||||
func (s *Service) RemoveDashboardCell(ctx context.Context, dashboardID platform.ID, cellID platform.ID) error {
|
func (s *Service) RemoveDashboardCell(ctx context.Context, dashboardID platform.ID, cellID platform.ID) error {
|
||||||
d, err := s.FindDashboardByID(ctx, dashboardID)
|
d, err := s.FindDashboardByID(ctx, dashboardID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -160,6 +167,7 @@ func (s *Service) RemoveDashboardCell(ctx context.Context, dashboardID platform.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateDashboardCell will remove a cell from a dashboard.
|
||||||
func (s *Service) UpdateDashboardCell(ctx context.Context, dashboardID platform.ID, cellID platform.ID, upd platform.CellUpdate) (*platform.Cell, error) {
|
func (s *Service) UpdateDashboardCell(ctx context.Context, dashboardID platform.ID, cellID platform.ID, upd platform.CellUpdate) (*platform.Cell, error) {
|
||||||
d, err := s.FindDashboardByID(ctx, dashboardID)
|
d, err := s.FindDashboardByID(ctx, dashboardID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -190,6 +198,7 @@ func (s *Service) UpdateDashboardCell(ctx context.Context, dashboardID platform.
|
||||||
return cell, nil
|
return cell, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReplaceDashboardCells replaces many dashboard cells.
|
||||||
func (s *Service) ReplaceDashboardCells(ctx context.Context, id platform.ID, cs []*platform.Cell) error {
|
func (s *Service) ReplaceDashboardCells(ctx context.Context, id platform.ID, cs []*platform.Cell) error {
|
||||||
d, err := s.FindDashboardByID(ctx, id)
|
d, err := s.FindDashboardByID(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
func initDashboardService(f platformtesting.DashboardFields, t *testing.T) (platform.DashboardService, func()) {
|
func initDashboardService(f platformtesting.DashboardFields, t *testing.T) (platform.DashboardService, func()) {
|
||||||
s := NewService()
|
s := NewService()
|
||||||
s.IDGenerator = f.IDGenerator
|
s.IDGenerator = f.IDGenerator
|
||||||
ctx := context.TODO()
|
ctx := context.Background()
|
||||||
for _, b := range f.Dashboards {
|
for _, b := range f.Dashboards {
|
||||||
if err := s.PutDashboard(ctx, b); err != nil {
|
if err := s.PutDashboard(ctx, b); err != nil {
|
||||||
t.Fatalf("failed to populate Dashboards")
|
t.Fatalf("failed to populate Dashboards")
|
||||||
|
|
|
@ -665,9 +665,9 @@ func UpdateDashboard(
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
) {
|
) {
|
||||||
type args struct {
|
type args struct {
|
||||||
name string
|
name string
|
||||||
id platform.ID
|
description string
|
||||||
retention int
|
id platform.ID
|
||||||
}
|
}
|
||||||
type wants struct {
|
type wants struct {
|
||||||
err error
|
err error
|
||||||
|
@ -705,6 +705,59 @@ func UpdateDashboard(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "update description",
|
||||||
|
fields: DashboardFields{
|
||||||
|
Dashboards: []*platform.Dashboard{
|
||||||
|
{
|
||||||
|
ID: MustIDBase16(dashOneID),
|
||||||
|
Name: "dashboard1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: MustIDBase16(dashTwoID),
|
||||||
|
Name: "dashboard2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
id: MustIDBase16(dashOneID),
|
||||||
|
description: "changed",
|
||||||
|
},
|
||||||
|
wants: wants{
|
||||||
|
dashboard: &platform.Dashboard{
|
||||||
|
ID: MustIDBase16(dashOneID),
|
||||||
|
Name: "dashboard1",
|
||||||
|
Description: "changed",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "update description and name",
|
||||||
|
fields: DashboardFields{
|
||||||
|
Dashboards: []*platform.Dashboard{
|
||||||
|
{
|
||||||
|
ID: MustIDBase16(dashOneID),
|
||||||
|
Name: "dashboard1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: MustIDBase16(dashTwoID),
|
||||||
|
Name: "dashboard2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
id: MustIDBase16(dashOneID),
|
||||||
|
description: "changed",
|
||||||
|
name: "changed",
|
||||||
|
},
|
||||||
|
wants: wants{
|
||||||
|
dashboard: &platform.Dashboard{
|
||||||
|
ID: MustIDBase16(dashOneID),
|
||||||
|
Name: "changed",
|
||||||
|
Description: "changed",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -717,6 +770,9 @@ func UpdateDashboard(
|
||||||
if tt.args.name != "" {
|
if tt.args.name != "" {
|
||||||
upd.Name = &tt.args.name
|
upd.Name = &tt.args.name
|
||||||
}
|
}
|
||||||
|
if tt.args.description != "" {
|
||||||
|
upd.Description = &tt.args.description
|
||||||
|
}
|
||||||
|
|
||||||
dashboard, err := s.UpdateDashboard(ctx, tt.args.id, upd)
|
dashboard, err := s.UpdateDashboard(ctx, tt.args.id, upd)
|
||||||
if (err != nil) != (tt.wants.err != nil) {
|
if (err != nil) != (tt.wants.err != nil) {
|
||||||
|
|
Loading…
Reference in New Issue