Merge pull request #1169 from influxdata/feature/dashboard-description

feat(dashboard): add description fields to dashboard
pull/10616/head
Chris Goller 2018-10-22 20:56:36 -05:00 committed by GitHub
commit 287082129f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 119 additions and 33 deletions

View File

@ -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.
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
err := c.db.Update(func(tx *bolt.Tx) error {
dash, err := c.updateDashboard(ctx, tx, id, upd)

View File

@ -45,9 +45,10 @@ type DashboardService interface {
// Dashboard represents all visual and query data for a dashboard
type Dashboard struct {
ID ID `json:"id,omitempty"`
Name string `json:"name"`
Cells []*Cell `json:"cells"`
ID ID `json:"id,omitempty"`
Name string `json:"name"`
Description string `json:"description"`
Cells []*Cell `json:"cells"`
}
// 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.
type DashboardUpdate struct {
Name *string `json:"name"`
}
// 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
Name *string `json:"name"`
Description *string `json:"description"`
}
// Apply applies an update to a dashboard.
@ -83,9 +78,29 @@ func (u DashboardUpdate) Apply(d *Dashboard) error {
d.Name = *u.Name
}
if u.Description != nil {
d.Description = *u.Description
}
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.
type CellUpdate struct {
X *int32 `json:"x"`
@ -119,12 +134,3 @@ func (u CellUpdate) Apply(c *Cell) error {
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
}

View File

@ -43,8 +43,9 @@ func TestService_handleGetDashboards(t *testing.T) {
FindDashboardsF: func(ctx context.Context, filter platform.DashboardFilter) ([]*platform.Dashboard, int, error) {
return []*platform.Dashboard{
{
ID: platformtesting.MustIDBase16("da7aba5e5d81e550"),
Name: "hello",
ID: platformtesting.MustIDBase16("da7aba5e5d81e550"),
Name: "hello",
Description: "oh hello there!",
Cells: []*platform.Cell{
{
ID: platformtesting.MustIDBase16("da7aba5e5d81e550"),
@ -77,6 +78,7 @@ func TestService_handleGetDashboards(t *testing.T) {
{
"id": "da7aba5e5d81e550",
"name": "hello",
"description": "oh hello there!",
"cells": [
{
"id": "da7aba5e5d81e550",
@ -99,6 +101,7 @@ func TestService_handleGetDashboards(t *testing.T) {
{
"id": "0ca2204eca2204e0",
"name": "example",
"description": "",
"cells": [],
"links": {
"self": "/api/v2/dashboards/0ca2204eca2204e0",
@ -227,6 +230,7 @@ func TestService_handleGetDashboard(t *testing.T) {
{
"id": "020f755c3c082000",
"name": "hello",
"description": "",
"cells": [
{
"id": "da7aba5e5d81e550",
@ -337,8 +341,9 @@ func TestService_handlePostDashboard(t *testing.T) {
},
args: args{
dashboard: &platform.Dashboard{
ID: platformtesting.MustIDBase16("020f755c3c082000"),
Name: "hello",
ID: platformtesting.MustIDBase16("020f755c3c082000"),
Name: "hello",
Description: "howdy there",
Cells: []*platform.Cell{
{
ID: platformtesting.MustIDBase16("da7aba5e5d81e550"),
@ -358,6 +363,7 @@ func TestService_handlePostDashboard(t *testing.T) {
{
"id": "020f755c3c082000",
"name": "hello",
"description": "howdy there",
"cells": [
{
"id": "da7aba5e5d81e550",
@ -575,6 +581,7 @@ func TestService_handlePatchDashboard(t *testing.T) {
{
"id": "020f755c3c082000",
"name": "example",
"description": "",
"cells": [
{
"id": "da7aba5e5d81e550",

View File

@ -4394,6 +4394,10 @@ components:
type: string
name:
type: string
description: user-facing name of the dashboard
description:
type: string
description: user-facing description of the dashboard
cells:
$ref: "#/components/schemas/Cells"
Dashboards:

View File

@ -83,17 +83,21 @@ func (s *Service) PutDashboard(ctx context.Context, o *platform.Dashboard) error
// UpdateDashboard implements platform.DashboardService interface.
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 {
return nil, err
}
if upd.Name != nil {
o.Name = *upd.Name
if err := upd.Apply(d); err != nil {
return nil, err
}
s.dashboardKV.Store(o.ID.String(), o)
return o, nil
s.dashboardKV.Store(d.ID.String(), d)
return d, nil
}
// DeleteDashboard implements platform.DashboardService interface.
@ -105,6 +109,7 @@ func (s *Service) DeleteDashboard(ctx context.Context, id platform.ID) error {
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 {
d, err := s.FindDashboardByID(ctx, id)
if err != nil {
@ -119,6 +124,7 @@ func (s *Service) AddDashboardCell(ctx context.Context, id platform.ID, cell *pl
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 {
d, err := s.FindDashboardByID(ctx, id)
if err != nil {
@ -134,6 +140,7 @@ func (s *Service) PutDashboardCell(ctx context.Context, id platform.ID, cell *pl
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 {
d, err := s.FindDashboardByID(ctx, dashboardID)
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) {
d, err := s.FindDashboardByID(ctx, dashboardID)
if err != nil {
@ -190,6 +198,7 @@ func (s *Service) UpdateDashboardCell(ctx context.Context, dashboardID platform.
return cell, nil
}
// ReplaceDashboardCells replaces many dashboard cells.
func (s *Service) ReplaceDashboardCells(ctx context.Context, id platform.ID, cs []*platform.Cell) error {
d, err := s.FindDashboardByID(ctx, id)
if err != nil {

View File

@ -11,7 +11,7 @@ import (
func initDashboardService(f platformtesting.DashboardFields, t *testing.T) (platform.DashboardService, func()) {
s := NewService()
s.IDGenerator = f.IDGenerator
ctx := context.TODO()
ctx := context.Background()
for _, b := range f.Dashboards {
if err := s.PutDashboard(ctx, b); err != nil {
t.Fatalf("failed to populate Dashboards")

View File

@ -665,9 +665,9 @@ func UpdateDashboard(
t *testing.T,
) {
type args struct {
name string
id platform.ID
retention int
name string
description string
id platform.ID
}
type wants struct {
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 {
@ -717,6 +770,9 @@ func UpdateDashboard(
if 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)
if (err != nil) != (tt.wants.err != nil) {