From 7266cd75e6026d7f9529ac4907dd7821af2a6296 Mon Sep 17 00:00:00 2001 From: Tim Raymond Date: Wed, 9 Aug 2017 13:06:34 -0700 Subject: [PATCH 01/47] Add Prefix, Suffix, and Base to Axes We would like to add additional user-configurable options to the display of axes on Dashboards. This adds three fields to expand settings that the frontend can persist through the API. One field of interest here is the "Base" field which controls when and how axes transition the display of values such as bytes, kilobytes, megabytes, etc. By default, it's returned from the API as "10" to indicate decimal, but can be set to anything the frontend wishes--the immediate differing value will be "2" for the aforementioned use case. --- bolt/internal/internal.go | 13 ++++ bolt/internal/internal.pb.go | 130 +++++++++++++++++---------------- bolt/internal/internal.proto | 3 + bolt/internal/internal_test.go | 7 +- chronograf.go | 3 + 5 files changed, 92 insertions(+), 64 deletions(-) diff --git a/bolt/internal/internal.go b/bolt/internal/internal.go index fefa93e78..4ff5e3d62 100644 --- a/bolt/internal/internal.go +++ b/bolt/internal/internal.go @@ -203,6 +203,9 @@ func MarshalDashboard(d chronograf.Dashboard) ([]byte, error) { axes[a] = &Axis{ Bounds: r.Bounds, Label: r.Label, + Prefix: r.Prefix, + Suffix: r.Suffix, + Base: r.Base, } } @@ -281,14 +284,24 @@ func UnmarshalDashboard(data []byte, d *chronograf.Dashboard) error { axes := make(map[string]chronograf.Axis, len(c.Axes)) for a, r := range c.Axes { + // axis base defaults to 10 + if r.Base == "" { + r.Base = "10" + } + if r.Bounds != nil { axes[a] = chronograf.Axis{ Bounds: r.Bounds, Label: r.Label, + Prefix: r.Prefix, + Suffix: r.Suffix, + Base: r.Base, } + } else { axes[a] = chronograf.Axis{ Bounds: []string{}, + Base: r.Base, } } } diff --git a/bolt/internal/internal.pb.go b/bolt/internal/internal.pb.go index 19a6c8d44..8c9b099fc 100644 --- a/bolt/internal/internal.pb.go +++ b/bolt/internal/internal.pb.go @@ -121,6 +121,9 @@ type Axis struct { LegacyBounds []int64 `protobuf:"varint,1,rep,name=legacyBounds" json:"legacyBounds,omitempty"` Bounds []string `protobuf:"bytes,2,rep,name=bounds" json:"bounds,omitempty"` Label string `protobuf:"bytes,3,opt,name=label,proto3" json:"label,omitempty"` + Prefix string `protobuf:"bytes,4,opt,name=prefix,proto3" json:"prefix,omitempty"` + Suffix string `protobuf:"bytes,5,opt,name=suffix,proto3" json:"suffix,omitempty"` + Base string `protobuf:"bytes,6,opt,name=base,proto3" json:"base,omitempty"` } func (m *Axis) Reset() { *m = Axis{} } @@ -323,67 +326,68 @@ func init() { func init() { proto.RegisterFile("internal.proto", fileDescriptorInternal) } var fileDescriptorInternal = []byte{ - // 985 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x56, 0xcd, 0x6e, 0x23, 0x45, - 0x10, 0x56, 0xcf, 0x8f, 0xed, 0x29, 0x67, 0x03, 0x6a, 0xad, 0xd8, 0x61, 0xb9, 0x98, 0x11, 0x48, - 0x06, 0x41, 0x40, 0xbb, 0x42, 0x42, 0xdc, 0x9c, 0x18, 0xad, 0x42, 0xb2, 0x4b, 0x68, 0x27, 0x81, - 0x0b, 0x5a, 0xb5, 0xc7, 0x95, 0x64, 0xb4, 0x63, 0xcf, 0xd0, 0x33, 0x13, 0x7b, 0xde, 0x82, 0x27, - 0x40, 0x42, 0xe2, 0xc4, 0x81, 0x03, 0x2f, 0xc0, 0x9d, 0xa7, 0x42, 0xd5, 0xdd, 0x33, 0x1e, 0xb3, - 0x59, 0xb4, 0x17, 0xf6, 0xd6, 0x5f, 0x55, 0xbb, 0xba, 0xe6, 0xab, 0xfa, 0x3e, 0x19, 0xf6, 0x93, - 0x55, 0x89, 0x6a, 0x25, 0xd3, 0x83, 0x5c, 0x65, 0x65, 0xc6, 0x07, 0x0d, 0x8e, 0xfe, 0x70, 0xa0, - 0x37, 0xcb, 0x2a, 0x15, 0x23, 0xdf, 0x07, 0xe7, 0x78, 0x1a, 0xb2, 0x11, 0x1b, 0xbb, 0xc2, 0x39, - 0x9e, 0x72, 0x0e, 0xde, 0x33, 0xb9, 0xc4, 0xd0, 0x19, 0xb1, 0x71, 0x20, 0xf4, 0x99, 0x62, 0xe7, - 0x75, 0x8e, 0xa1, 0x6b, 0x62, 0x74, 0xe6, 0x0f, 0x61, 0x70, 0x51, 0x50, 0xb5, 0x25, 0x86, 0x9e, - 0x8e, 0xb7, 0x98, 0x72, 0x67, 0xb2, 0x28, 0xd6, 0x99, 0x5a, 0x84, 0xbe, 0xc9, 0x35, 0x98, 0xbf, - 0x0d, 0xee, 0x85, 0x38, 0x0d, 0x7b, 0x3a, 0x4c, 0x47, 0x1e, 0x42, 0x7f, 0x8a, 0x57, 0xb2, 0x4a, - 0xcb, 0xb0, 0x3f, 0x62, 0xe3, 0x81, 0x68, 0x20, 0xd5, 0x39, 0xc7, 0x14, 0xaf, 0x95, 0xbc, 0x0a, - 0x07, 0xa6, 0x4e, 0x83, 0xf9, 0x01, 0xf0, 0xe3, 0x55, 0x81, 0x71, 0xa5, 0x70, 0xf6, 0x22, 0xc9, - 0x2f, 0x51, 0x25, 0x57, 0x75, 0x18, 0xe8, 0x02, 0x77, 0x64, 0xe8, 0x95, 0xa7, 0x58, 0x4a, 0x7a, - 0x1b, 0x74, 0xa9, 0x06, 0xf2, 0x08, 0xf6, 0x66, 0x37, 0x52, 0xe1, 0x62, 0x86, 0xb1, 0xc2, 0x32, - 0x1c, 0xea, 0xf4, 0x4e, 0x2c, 0xfa, 0x99, 0x41, 0x30, 0x95, 0xc5, 0xcd, 0x3c, 0x93, 0x6a, 0xf1, - 0x5a, 0x9c, 0x7d, 0x0a, 0x7e, 0x8c, 0x69, 0x5a, 0x84, 0xee, 0xc8, 0x1d, 0x0f, 0x1f, 0x3d, 0x38, - 0x68, 0x87, 0xd1, 0xd6, 0x39, 0xc2, 0x34, 0x15, 0xe6, 0x16, 0xff, 0x1c, 0x82, 0x12, 0x97, 0x79, - 0x2a, 0x4b, 0x2c, 0x42, 0x4f, 0xff, 0x84, 0x6f, 0x7f, 0x72, 0x6e, 0x53, 0x62, 0x7b, 0x29, 0xfa, - 0xdd, 0x81, 0x7b, 0x3b, 0xa5, 0xf8, 0x1e, 0xb0, 0x8d, 0xee, 0xca, 0x17, 0x6c, 0x43, 0xa8, 0xd6, - 0x1d, 0xf9, 0x82, 0xd5, 0x84, 0xd6, 0x7a, 0x7e, 0xbe, 0x60, 0x6b, 0x42, 0x37, 0x7a, 0x6a, 0xbe, - 0x60, 0x37, 0xfc, 0x23, 0xe8, 0xff, 0x54, 0xa1, 0x4a, 0xb0, 0x08, 0x7d, 0xfd, 0xf2, 0x5b, 0xdb, - 0x97, 0xbf, 0xab, 0x50, 0xd5, 0xa2, 0xc9, 0xd3, 0x97, 0xea, 0x89, 0x9b, 0xf1, 0xe9, 0x33, 0xc5, - 0x4a, 0xda, 0x8e, 0xbe, 0x89, 0xd1, 0xd9, 0x32, 0x64, 0x66, 0x46, 0x0c, 0x7d, 0x01, 0x9e, 0xdc, - 0x60, 0x11, 0x06, 0xba, 0xfe, 0xfb, 0xaf, 0x20, 0xe3, 0x60, 0xb2, 0xc1, 0xe2, 0xeb, 0x55, 0xa9, - 0x6a, 0xa1, 0xaf, 0x3f, 0x7c, 0x02, 0x41, 0x1b, 0xa2, 0xcd, 0x79, 0x81, 0xb5, 0xfe, 0xc0, 0x40, - 0xd0, 0x91, 0x7f, 0x00, 0xfe, 0xad, 0x4c, 0x2b, 0x43, 0xfc, 0xf0, 0xd1, 0xfe, 0xb6, 0xec, 0x64, - 0x93, 0x14, 0xc2, 0x24, 0xbf, 0x72, 0xbe, 0x64, 0xd1, 0x0f, 0xe0, 0x51, 0x88, 0x66, 0x9d, 0xe2, - 0xb5, 0x8c, 0xeb, 0xc3, 0xac, 0x5a, 0x2d, 0x8a, 0x90, 0x8d, 0xdc, 0xb1, 0x2b, 0x76, 0x62, 0xfc, - 0x1d, 0xe8, 0xcd, 0x4d, 0xd6, 0x19, 0xb9, 0xe3, 0x40, 0x58, 0xc4, 0xef, 0x83, 0x9f, 0xca, 0x39, - 0xa6, 0x56, 0x06, 0x06, 0x44, 0x7f, 0x31, 0x5a, 0x52, 0x33, 0x94, 0xce, 0x62, 0x98, 0xcf, 0x7e, - 0x17, 0x06, 0x34, 0xb0, 0xe7, 0xb7, 0x52, 0xd9, 0xe5, 0xe8, 0x13, 0xbe, 0x94, 0x8a, 0x7f, 0x06, - 0x3d, 0xdd, 0xde, 0x1d, 0x0b, 0xd2, 0x94, 0xbb, 0xa4, 0xbc, 0xb0, 0xd7, 0x5a, 0x9a, 0xbd, 0x0e, - 0xcd, 0x6d, 0x4b, 0x7e, 0xa7, 0x25, 0x5a, 0x3d, 0x9a, 0x57, 0xad, 0xa7, 0x74, 0x67, 0x65, 0x33, - 0x55, 0x73, 0x2b, 0xba, 0x80, 0x7b, 0x3b, 0x2f, 0xb6, 0x2f, 0xb1, 0xdd, 0x97, 0xb6, 0x54, 0x07, - 0x96, 0x5a, 0x12, 0x68, 0x81, 0x29, 0xc6, 0x25, 0x2e, 0x34, 0x2b, 0x03, 0xd1, 0xe2, 0xe8, 0x57, - 0xb6, 0xad, 0xab, 0xdf, 0x23, 0x09, 0xc6, 0xd9, 0x72, 0x29, 0x57, 0x0b, 0x5b, 0xba, 0x81, 0xc4, - 0xdb, 0x62, 0x6e, 0x4b, 0x3b, 0x8b, 0x39, 0x61, 0x95, 0x5b, 0x9e, 0x1d, 0x95, 0xf3, 0x11, 0x0c, - 0x97, 0x28, 0x8b, 0x4a, 0xe1, 0x12, 0x57, 0xa5, 0xa5, 0xa0, 0x1b, 0xe2, 0x0f, 0xa0, 0x5f, 0xca, - 0xeb, 0xe7, 0xb4, 0x20, 0x86, 0x8b, 0x5e, 0x29, 0xaf, 0x4f, 0xb0, 0xe6, 0xef, 0x41, 0x70, 0x95, - 0x60, 0xba, 0xd0, 0x29, 0xb3, 0xb6, 0x03, 0x1d, 0x38, 0xc1, 0x3a, 0xfa, 0x8d, 0x41, 0x6f, 0x86, - 0xea, 0x16, 0xd5, 0x6b, 0x69, 0xba, 0xeb, 0x79, 0xee, 0x7f, 0x78, 0x9e, 0x77, 0xb7, 0xe7, 0xf9, - 0x5b, 0xcf, 0xbb, 0x0f, 0xfe, 0x4c, 0xc5, 0xc7, 0x53, 0xdd, 0x91, 0x2b, 0x0c, 0xa0, 0xcd, 0x9b, - 0xc4, 0x65, 0x72, 0x8b, 0xd6, 0x08, 0x2d, 0x8a, 0x7e, 0x61, 0xd0, 0x3b, 0x95, 0x75, 0x56, 0x95, - 0x2f, 0x6d, 0xd8, 0x08, 0x86, 0x93, 0x3c, 0x4f, 0x93, 0x58, 0x96, 0x49, 0xb6, 0xb2, 0xdd, 0x76, - 0x43, 0x74, 0xe3, 0x69, 0x87, 0x3b, 0xd3, 0x77, 0x37, 0x44, 0x32, 0x3a, 0xd2, 0x56, 0x65, 0x7c, - 0xa7, 0x23, 0x23, 0xe3, 0x50, 0x3a, 0x49, 0x1f, 0x38, 0xa9, 0xca, 0xec, 0x2a, 0xcd, 0xd6, 0xfa, - 0x4b, 0x06, 0xa2, 0xc5, 0xd1, 0xdf, 0x0e, 0x78, 0x6f, 0xca, 0x82, 0xf6, 0x80, 0x25, 0x76, 0x90, - 0x2c, 0x69, 0x0d, 0xa9, 0xdf, 0x31, 0xa4, 0x10, 0xfa, 0xb5, 0x92, 0xab, 0x6b, 0x2c, 0xc2, 0x81, - 0xd6, 0x77, 0x03, 0x75, 0x46, 0x6b, 0xc4, 0x38, 0x51, 0x20, 0x1a, 0xd8, 0xee, 0x3c, 0x74, 0x76, - 0xfe, 0x13, 0x6b, 0x5a, 0x43, 0xdd, 0x51, 0xb8, 0x4b, 0xcb, 0xff, 0xe7, 0x55, 0x7f, 0x32, 0xf0, - 0x5b, 0xc1, 0x1c, 0xed, 0x0a, 0xe6, 0x68, 0x2b, 0x98, 0xe9, 0x61, 0x23, 0x98, 0xe9, 0x21, 0x61, - 0x71, 0xd6, 0x08, 0x46, 0x9c, 0xd1, 0xb0, 0x9e, 0xa8, 0xac, 0xca, 0x0f, 0x6b, 0x33, 0xd5, 0x40, - 0xb4, 0x98, 0xb6, 0xec, 0xfb, 0x1b, 0x54, 0x96, 0xea, 0x40, 0x58, 0x44, 0x3b, 0x79, 0xaa, 0xcd, - 0xc4, 0x90, 0x6b, 0x00, 0xff, 0x10, 0x7c, 0x41, 0xe4, 0x69, 0x86, 0x77, 0xe6, 0xa2, 0xc3, 0xc2, - 0x64, 0xa3, 0xc7, 0xf6, 0x1a, 0x55, 0xb9, 0xc8, 0x73, 0x54, 0x56, 0x4a, 0x06, 0xe8, 0xda, 0xd9, - 0x1a, 0x8d, 0x0b, 0xba, 0xc2, 0x80, 0xe8, 0x47, 0x08, 0x26, 0x29, 0xaa, 0x52, 0x54, 0xe9, 0xcb, - 0xde, 0xc9, 0xc1, 0xfb, 0x66, 0xf6, 0xed, 0xb3, 0x46, 0x80, 0x74, 0xde, 0xca, 0xc6, 0xfd, 0x97, - 0x6c, 0x4e, 0x64, 0x2e, 0x8f, 0xa7, 0x7a, 0x9f, 0x5c, 0x61, 0x51, 0xf4, 0x31, 0x78, 0x24, 0xcf, - 0x4e, 0x65, 0xef, 0x55, 0xd2, 0x9e, 0xf7, 0xf4, 0x5f, 0xa4, 0xc7, 0xff, 0x04, 0x00, 0x00, 0xff, - 0xff, 0x5a, 0xf0, 0x92, 0xd4, 0x34, 0x09, 0x00, 0x00, + // 998 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x56, 0xcd, 0x8e, 0xe3, 0x44, + 0x10, 0x56, 0xc7, 0x76, 0x12, 0xd7, 0xec, 0x0e, 0xa8, 0xb5, 0x62, 0xcd, 0x72, 0x09, 0x16, 0x48, + 0x01, 0x69, 0x07, 0xb4, 0x2b, 0x24, 0xc4, 0x2d, 0x33, 0x41, 0xab, 0x61, 0x66, 0x97, 0xa1, 0x33, + 0x33, 0x9c, 0xd0, 0xaa, 0xe3, 0x54, 0x26, 0xd6, 0x3a, 0xb1, 0x69, 0xdb, 0x93, 0xf8, 0x2d, 0x78, + 0x00, 0x84, 0x84, 0xc4, 0x89, 0x03, 0x07, 0x5e, 0x80, 0x87, 0xe0, 0x85, 0x50, 0x75, 0xb7, 0x7f, + 0xc2, 0xce, 0xa2, 0x3d, 0x71, 0xeb, 0xaf, 0xaa, 0xf3, 0xb5, 0xab, 0xbe, 0xaf, 0x4a, 0x81, 0xc3, + 0x78, 0x53, 0xa0, 0xda, 0xc8, 0xe4, 0x28, 0x53, 0x69, 0x91, 0xf2, 0x61, 0x8d, 0xc3, 0x3f, 0x7a, + 0xd0, 0x9f, 0xa5, 0xa5, 0x8a, 0x90, 0x1f, 0x42, 0xef, 0x74, 0x1a, 0xb0, 0x11, 0x1b, 0x3b, 0xa2, + 0x77, 0x3a, 0xe5, 0x1c, 0xdc, 0x17, 0x72, 0x8d, 0x41, 0x6f, 0xc4, 0xc6, 0xbe, 0xd0, 0x67, 0x8a, + 0x5d, 0x56, 0x19, 0x06, 0x8e, 0x89, 0xd1, 0x99, 0x3f, 0x82, 0xe1, 0x55, 0x4e, 0x6c, 0x6b, 0x0c, + 0x5c, 0x1d, 0x6f, 0x30, 0xe5, 0x2e, 0x64, 0x9e, 0x6f, 0x53, 0xb5, 0x08, 0x3c, 0x93, 0xab, 0x31, + 0x7f, 0x17, 0x9c, 0x2b, 0x71, 0x1e, 0xf4, 0x75, 0x98, 0x8e, 0x3c, 0x80, 0xc1, 0x14, 0x97, 0xb2, + 0x4c, 0x8a, 0x60, 0x30, 0x62, 0xe3, 0xa1, 0xa8, 0x21, 0xf1, 0x5c, 0x62, 0x82, 0x37, 0x4a, 0x2e, + 0x83, 0xa1, 0xe1, 0xa9, 0x31, 0x3f, 0x02, 0x7e, 0xba, 0xc9, 0x31, 0x2a, 0x15, 0xce, 0x5e, 0xc5, + 0xd9, 0x35, 0xaa, 0x78, 0x59, 0x05, 0xbe, 0x26, 0xb8, 0x23, 0x43, 0xaf, 0x3c, 0xc7, 0x42, 0xd2, + 0xdb, 0xa0, 0xa9, 0x6a, 0xc8, 0x43, 0xb8, 0x37, 0x5b, 0x49, 0x85, 0x8b, 0x19, 0x46, 0x0a, 0x8b, + 0xe0, 0x40, 0xa7, 0xf7, 0x62, 0xe1, 0x4f, 0x0c, 0xfc, 0xa9, 0xcc, 0x57, 0xf3, 0x54, 0xaa, 0xc5, + 0x5b, 0xf5, 0xec, 0x31, 0x78, 0x11, 0x26, 0x49, 0x1e, 0x38, 0x23, 0x67, 0x7c, 0xf0, 0xe4, 0xe1, + 0x51, 0x23, 0x46, 0xc3, 0x73, 0x82, 0x49, 0x22, 0xcc, 0x2d, 0xfe, 0x39, 0xf8, 0x05, 0xae, 0xb3, + 0x44, 0x16, 0x98, 0x07, 0xae, 0xfe, 0x09, 0x6f, 0x7f, 0x72, 0x69, 0x53, 0xa2, 0xbd, 0x14, 0xfe, + 0xde, 0x83, 0xfb, 0x7b, 0x54, 0xfc, 0x1e, 0xb0, 0x9d, 0xfe, 0x2a, 0x4f, 0xb0, 0x1d, 0xa1, 0x4a, + 0x7f, 0x91, 0x27, 0x58, 0x45, 0x68, 0xab, 0xf5, 0xf3, 0x04, 0xdb, 0x12, 0x5a, 0x69, 0xd5, 0x3c, + 0xc1, 0x56, 0xfc, 0x13, 0x18, 0xfc, 0x58, 0xa2, 0x8a, 0x31, 0x0f, 0x3c, 0xfd, 0xf2, 0x3b, 0xed, + 0xcb, 0xdf, 0x95, 0xa8, 0x2a, 0x51, 0xe7, 0xa9, 0x52, 0xad, 0xb8, 0x91, 0x4f, 0x9f, 0x29, 0x56, + 0x90, 0x3b, 0x06, 0x26, 0x46, 0x67, 0xdb, 0x21, 0xa3, 0x19, 0x75, 0xe8, 0x0b, 0x70, 0xe5, 0x0e, + 0xf3, 0xc0, 0xd7, 0xfc, 0x1f, 0xbe, 0xa1, 0x19, 0x47, 0x93, 0x1d, 0xe6, 0x5f, 0x6f, 0x0a, 0x55, + 0x09, 0x7d, 0xfd, 0xd1, 0x33, 0xf0, 0x9b, 0x10, 0x39, 0xe7, 0x15, 0x56, 0xba, 0x40, 0x5f, 0xd0, + 0x91, 0x7f, 0x04, 0xde, 0xad, 0x4c, 0x4a, 0xd3, 0xf8, 0x83, 0x27, 0x87, 0x2d, 0xed, 0x64, 0x17, + 0xe7, 0xc2, 0x24, 0xbf, 0xea, 0x7d, 0xc9, 0xc2, 0x9f, 0x19, 0xb8, 0x14, 0x23, 0xb1, 0x13, 0xbc, + 0x91, 0x51, 0x75, 0x9c, 0x96, 0x9b, 0x45, 0x1e, 0xb0, 0x91, 0x33, 0x76, 0xc4, 0x5e, 0x8c, 0xbf, + 0x07, 0xfd, 0xb9, 0xc9, 0xf6, 0x46, 0xce, 0xd8, 0x17, 0x16, 0xf1, 0x07, 0xe0, 0x25, 0x72, 0x8e, + 0x89, 0x9d, 0x03, 0x03, 0xe8, 0x76, 0xa6, 0x70, 0x19, 0xef, 0xec, 0x18, 0x58, 0x44, 0xf1, 0xbc, + 0x5c, 0x52, 0xdc, 0x8c, 0x80, 0x45, 0xd4, 0xae, 0xb9, 0xcc, 0x9b, 0x16, 0xd2, 0x39, 0xfc, 0x8b, + 0x91, 0xd3, 0x8d, 0xb2, 0x1d, 0x77, 0x99, 0xde, 0xbd, 0x0f, 0x43, 0x52, 0xfd, 0xe5, 0xad, 0x54, + 0xd6, 0x61, 0x03, 0xc2, 0xd7, 0x52, 0xf1, 0xcf, 0xa0, 0xaf, 0x6b, 0xbc, 0xc3, 0x65, 0x35, 0xdd, + 0x35, 0xe5, 0x85, 0xbd, 0xd6, 0x68, 0xe5, 0x76, 0xb4, 0x6a, 0xca, 0xf2, 0xba, 0x65, 0x3d, 0x06, + 0x8f, 0x44, 0xaf, 0xf4, 0x77, 0xde, 0xc9, 0x6c, 0xac, 0x61, 0x6e, 0x85, 0x57, 0x70, 0x7f, 0xef, + 0xc5, 0xe6, 0x25, 0xb6, 0xff, 0x52, 0xab, 0x97, 0x6f, 0xf5, 0xa1, 0x29, 0xcf, 0x31, 0xc1, 0xa8, + 0xc0, 0x85, 0xee, 0xec, 0x50, 0x34, 0x38, 0xfc, 0x95, 0xb5, 0xbc, 0xfa, 0x3d, 0x9a, 0xe3, 0x28, + 0x5d, 0xaf, 0xe5, 0x66, 0x61, 0xa9, 0x6b, 0x48, 0x7d, 0x5b, 0xcc, 0x2d, 0x75, 0x6f, 0x31, 0x27, + 0xac, 0x32, 0xab, 0x55, 0x4f, 0x65, 0x7c, 0x04, 0x07, 0x6b, 0x94, 0x79, 0xa9, 0x70, 0x8d, 0x9b, + 0xc2, 0xb6, 0xa0, 0x1b, 0xe2, 0x0f, 0x61, 0x50, 0xc8, 0x9b, 0x97, 0xe4, 0x32, 0xab, 0x59, 0x21, + 0x6f, 0xce, 0xb0, 0xe2, 0x1f, 0x80, 0xbf, 0x8c, 0x31, 0x59, 0xe8, 0x94, 0x11, 0x6e, 0xa8, 0x03, + 0x67, 0x58, 0x85, 0xbf, 0x31, 0xe8, 0xcf, 0x50, 0xdd, 0xa2, 0x7a, 0xab, 0xc5, 0xd0, 0x5d, 0x9c, + 0xce, 0x7f, 0x2c, 0x4e, 0xf7, 0xee, 0xc5, 0xe9, 0xb5, 0x8b, 0xf3, 0x01, 0x78, 0x33, 0x15, 0x9d, + 0x4e, 0xf5, 0x17, 0x39, 0xc2, 0x00, 0xf2, 0xdd, 0x24, 0x2a, 0xe2, 0x5b, 0xb4, 0xdb, 0xd4, 0xa2, + 0xf0, 0x17, 0x06, 0xfd, 0x73, 0x59, 0xa5, 0x65, 0xf1, 0x9a, 0xc3, 0x46, 0x70, 0x30, 0xc9, 0xb2, + 0x24, 0x8e, 0x64, 0x11, 0xa7, 0x1b, 0xfb, 0xb5, 0xdd, 0x10, 0xdd, 0x78, 0xde, 0xe9, 0x9d, 0xf9, + 0xee, 0x6e, 0x88, 0x66, 0xf1, 0x44, 0xef, 0x3b, 0xb3, 0xbc, 0x3a, 0xb3, 0x68, 0xd6, 0x9c, 0x4e, + 0x52, 0x81, 0x93, 0xb2, 0x48, 0x97, 0x49, 0xba, 0xd5, 0x95, 0x0c, 0x45, 0x83, 0xc3, 0xbf, 0x19, + 0xb8, 0xff, 0xd7, 0x1e, 0xbb, 0x07, 0x2c, 0xb6, 0x42, 0xb2, 0xb8, 0xd9, 0x6a, 0x83, 0xce, 0x56, + 0x0b, 0x60, 0x50, 0x29, 0xb9, 0xb9, 0xc1, 0x3c, 0x18, 0xea, 0x1d, 0x51, 0x43, 0x9d, 0xd1, 0x33, + 0x62, 0xd6, 0x99, 0x2f, 0x6a, 0xd8, 0x78, 0x1e, 0x5a, 0xcf, 0x87, 0x7f, 0x32, 0xf0, 0x1a, 0xe7, + 0x9e, 0xec, 0x3b, 0xf7, 0xa4, 0x75, 0xee, 0xf4, 0xb8, 0x76, 0xee, 0xf4, 0x98, 0xb0, 0xb8, 0xa8, + 0x9d, 0x2b, 0x2e, 0xa8, 0x6b, 0xcf, 0x54, 0x5a, 0x66, 0xc7, 0x95, 0x69, 0xaf, 0x2f, 0x1a, 0x4c, + 0x72, 0x7f, 0xbf, 0x42, 0x65, 0x6b, 0xf6, 0x85, 0x45, 0x64, 0x8e, 0x73, 0x3d, 0xd5, 0xa6, 0x4a, + 0x03, 0xf8, 0xc7, 0xe0, 0x09, 0xaa, 0x42, 0x97, 0xba, 0xd7, 0x20, 0x1d, 0x16, 0x26, 0x1b, 0x3e, + 0xb5, 0xd7, 0x88, 0xe5, 0x2a, 0xcb, 0x50, 0x59, 0x4f, 0x1b, 0xa0, 0xb9, 0xd3, 0x2d, 0x9a, 0x75, + 0xe4, 0x08, 0x03, 0xc2, 0x1f, 0xc0, 0x9f, 0x24, 0xa8, 0x0a, 0x51, 0x26, 0xaf, 0x2f, 0x31, 0x0e, + 0xee, 0x37, 0xb3, 0x6f, 0x5f, 0xd4, 0x93, 0x40, 0xe7, 0xd6, 0xbf, 0xce, 0xbf, 0xfc, 0x7b, 0x26, + 0x33, 0x79, 0x3a, 0xd5, 0xc2, 0x3a, 0xc2, 0xa2, 0xf0, 0x53, 0x70, 0x69, 0x4e, 0x3a, 0xcc, 0xee, + 0x9b, 0x66, 0x6c, 0xde, 0xd7, 0x7f, 0x78, 0x9e, 0xfe, 0x13, 0x00, 0x00, 0xff, 0xff, 0x35, 0xc8, + 0x8f, 0x51, 0x02, 0x09, 0x00, 0x00, } diff --git a/bolt/internal/internal.proto b/bolt/internal/internal.proto index b146cfd0a..cb41ec895 100644 --- a/bolt/internal/internal.proto +++ b/bolt/internal/internal.proto @@ -38,6 +38,9 @@ message Axis { repeated int64 legacyBounds = 1; // legacyBounds are an ordered 2-tuple consisting of lower and upper axis extents, respectively repeated string bounds = 2; // bounds are an arbitrary list of client-defined bounds. string label = 3; // label is a description of this axis + string prefix = 4; // specifies the prefix for axis values + string suffix = 5; // specifies the suffix for axis values + string base = 6; // defines the base for axis values } message Template { diff --git a/bolt/internal/internal_test.go b/bolt/internal/internal_test.go index 7a53243d2..2759b7f0f 100644 --- a/bolt/internal/internal_test.go +++ b/bolt/internal/internal_test.go @@ -168,6 +168,9 @@ func Test_MarshalDashboard(t *testing.T) { "y": chronograf.Axis{ Bounds: []string{"0", "3", "1-7", "foo"}, Label: "foo", + Prefix: "M", + Suffix: "m", + Base: "2", }, }, Type: "line", @@ -241,6 +244,7 @@ func Test_MarshalDashboard_WithLegacyBounds(t *testing.T) { Axes: map[string]chronograf.Axis{ "y": chronograf.Axis{ Bounds: []string{}, + Base: "10", }, }, Type: "line", @@ -260,7 +264,7 @@ func Test_MarshalDashboard_WithLegacyBounds(t *testing.T) { } } -func Test_MarshalDashboard_WithNoLegacyBounds(t *testing.T) { +func Test_MarshalDashboard_WithEmptyLegacyBounds(t *testing.T) { dashboard := chronograf.Dashboard{ ID: 1, Cells: []chronograf.DashboardCell{ @@ -314,6 +318,7 @@ func Test_MarshalDashboard_WithNoLegacyBounds(t *testing.T) { Axes: map[string]chronograf.Axis{ "y": chronograf.Axis{ Bounds: []string{}, + Base: "10", }, }, Type: "line", diff --git a/chronograf.go b/chronograf.go index 535adfe1e..3affae80a 100644 --- a/chronograf.go +++ b/chronograf.go @@ -644,6 +644,9 @@ type Axis struct { Bounds []string `json:"bounds"` // bounds are an arbitrary list of client-defined strings that specify the viewport for a cell LegacyBounds [2]int64 `json:"-"` // legacy bounds are for testing a migration from an earlier version of axis Label string `json:"label"` // label is a description of this Axis + Prefix string `json:"prefix"` // specifies a prefix for axis values + Suffix string `json:"suffix"` // specifies a suffix for axis values + Base string `json:"base"` // defines the base for axis values } // DashboardCell holds visual and query information for a cell From 5eeb52017575ab1e29916cc8653dbe1cc222784f Mon Sep 17 00:00:00 2001 From: Tim Raymond Date: Fri, 18 Aug 2017 13:48:41 -0400 Subject: [PATCH 02/47] Add Scale attribute to Cell Axis This allows clients to specify the magnitude of numbers found on a particular axis. --- bolt/internal/internal.go | 2 + bolt/internal/internal.pb.go | 129 +++++++++++++++++---------------- bolt/internal/internal.proto | 1 + bolt/internal/internal_test.go | 1 + chronograf.go | 1 + 5 files changed, 70 insertions(+), 64 deletions(-) diff --git a/bolt/internal/internal.go b/bolt/internal/internal.go index 4ff5e3d62..c844665ec 100644 --- a/bolt/internal/internal.go +++ b/bolt/internal/internal.go @@ -206,6 +206,7 @@ func MarshalDashboard(d chronograf.Dashboard) ([]byte, error) { Prefix: r.Prefix, Suffix: r.Suffix, Base: r.Base, + Scale: r.Scale, } } @@ -296,6 +297,7 @@ func UnmarshalDashboard(data []byte, d *chronograf.Dashboard) error { Prefix: r.Prefix, Suffix: r.Suffix, Base: r.Base, + Scale: r.Scale, } } else { diff --git a/bolt/internal/internal.pb.go b/bolt/internal/internal.pb.go index 8c9b099fc..317db658a 100644 --- a/bolt/internal/internal.pb.go +++ b/bolt/internal/internal.pb.go @@ -124,6 +124,7 @@ type Axis struct { Prefix string `protobuf:"bytes,4,opt,name=prefix,proto3" json:"prefix,omitempty"` Suffix string `protobuf:"bytes,5,opt,name=suffix,proto3" json:"suffix,omitempty"` Base string `protobuf:"bytes,6,opt,name=base,proto3" json:"base,omitempty"` + Scale string `protobuf:"bytes,7,opt,name=scale,proto3" json:"scale,omitempty"` } func (m *Axis) Reset() { *m = Axis{} } @@ -326,68 +327,68 @@ func init() { func init() { proto.RegisterFile("internal.proto", fileDescriptorInternal) } var fileDescriptorInternal = []byte{ - // 998 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x56, 0xcd, 0x8e, 0xe3, 0x44, - 0x10, 0x56, 0xc7, 0x76, 0x12, 0xd7, 0xec, 0x0e, 0xa8, 0xb5, 0x62, 0xcd, 0x72, 0x09, 0x16, 0x48, - 0x01, 0x69, 0x07, 0xb4, 0x2b, 0x24, 0xc4, 0x2d, 0x33, 0x41, 0xab, 0x61, 0x66, 0x97, 0xa1, 0x33, - 0x33, 0x9c, 0xd0, 0xaa, 0xe3, 0x54, 0x26, 0xd6, 0x3a, 0xb1, 0x69, 0xdb, 0x93, 0xf8, 0x2d, 0x78, - 0x00, 0x84, 0x84, 0xc4, 0x89, 0x03, 0x07, 0x5e, 0x80, 0x87, 0xe0, 0x85, 0x50, 0x75, 0xb7, 0x7f, - 0xc2, 0xce, 0xa2, 0x3d, 0x71, 0xeb, 0xaf, 0xaa, 0xf3, 0xb5, 0xab, 0xbe, 0xaf, 0x4a, 0x81, 0xc3, - 0x78, 0x53, 0xa0, 0xda, 0xc8, 0xe4, 0x28, 0x53, 0x69, 0x91, 0xf2, 0x61, 0x8d, 0xc3, 0x3f, 0x7a, - 0xd0, 0x9f, 0xa5, 0xa5, 0x8a, 0x90, 0x1f, 0x42, 0xef, 0x74, 0x1a, 0xb0, 0x11, 0x1b, 0x3b, 0xa2, - 0x77, 0x3a, 0xe5, 0x1c, 0xdc, 0x17, 0x72, 0x8d, 0x41, 0x6f, 0xc4, 0xc6, 0xbe, 0xd0, 0x67, 0x8a, - 0x5d, 0x56, 0x19, 0x06, 0x8e, 0x89, 0xd1, 0x99, 0x3f, 0x82, 0xe1, 0x55, 0x4e, 0x6c, 0x6b, 0x0c, - 0x5c, 0x1d, 0x6f, 0x30, 0xe5, 0x2e, 0x64, 0x9e, 0x6f, 0x53, 0xb5, 0x08, 0x3c, 0x93, 0xab, 0x31, - 0x7f, 0x17, 0x9c, 0x2b, 0x71, 0x1e, 0xf4, 0x75, 0x98, 0x8e, 0x3c, 0x80, 0xc1, 0x14, 0x97, 0xb2, - 0x4c, 0x8a, 0x60, 0x30, 0x62, 0xe3, 0xa1, 0xa8, 0x21, 0xf1, 0x5c, 0x62, 0x82, 0x37, 0x4a, 0x2e, - 0x83, 0xa1, 0xe1, 0xa9, 0x31, 0x3f, 0x02, 0x7e, 0xba, 0xc9, 0x31, 0x2a, 0x15, 0xce, 0x5e, 0xc5, - 0xd9, 0x35, 0xaa, 0x78, 0x59, 0x05, 0xbe, 0x26, 0xb8, 0x23, 0x43, 0xaf, 0x3c, 0xc7, 0x42, 0xd2, - 0xdb, 0xa0, 0xa9, 0x6a, 0xc8, 0x43, 0xb8, 0x37, 0x5b, 0x49, 0x85, 0x8b, 0x19, 0x46, 0x0a, 0x8b, - 0xe0, 0x40, 0xa7, 0xf7, 0x62, 0xe1, 0x4f, 0x0c, 0xfc, 0xa9, 0xcc, 0x57, 0xf3, 0x54, 0xaa, 0xc5, - 0x5b, 0xf5, 0xec, 0x31, 0x78, 0x11, 0x26, 0x49, 0x1e, 0x38, 0x23, 0x67, 0x7c, 0xf0, 0xe4, 0xe1, - 0x51, 0x23, 0x46, 0xc3, 0x73, 0x82, 0x49, 0x22, 0xcc, 0x2d, 0xfe, 0x39, 0xf8, 0x05, 0xae, 0xb3, - 0x44, 0x16, 0x98, 0x07, 0xae, 0xfe, 0x09, 0x6f, 0x7f, 0x72, 0x69, 0x53, 0xa2, 0xbd, 0x14, 0xfe, - 0xde, 0x83, 0xfb, 0x7b, 0x54, 0xfc, 0x1e, 0xb0, 0x9d, 0xfe, 0x2a, 0x4f, 0xb0, 0x1d, 0xa1, 0x4a, - 0x7f, 0x91, 0x27, 0x58, 0x45, 0x68, 0xab, 0xf5, 0xf3, 0x04, 0xdb, 0x12, 0x5a, 0x69, 0xd5, 0x3c, - 0xc1, 0x56, 0xfc, 0x13, 0x18, 0xfc, 0x58, 0xa2, 0x8a, 0x31, 0x0f, 0x3c, 0xfd, 0xf2, 0x3b, 0xed, - 0xcb, 0xdf, 0x95, 0xa8, 0x2a, 0x51, 0xe7, 0xa9, 0x52, 0xad, 0xb8, 0x91, 0x4f, 0x9f, 0x29, 0x56, - 0x90, 0x3b, 0x06, 0x26, 0x46, 0x67, 0xdb, 0x21, 0xa3, 0x19, 0x75, 0xe8, 0x0b, 0x70, 0xe5, 0x0e, - 0xf3, 0xc0, 0xd7, 0xfc, 0x1f, 0xbe, 0xa1, 0x19, 0x47, 0x93, 0x1d, 0xe6, 0x5f, 0x6f, 0x0a, 0x55, - 0x09, 0x7d, 0xfd, 0xd1, 0x33, 0xf0, 0x9b, 0x10, 0x39, 0xe7, 0x15, 0x56, 0xba, 0x40, 0x5f, 0xd0, - 0x91, 0x7f, 0x04, 0xde, 0xad, 0x4c, 0x4a, 0xd3, 0xf8, 0x83, 0x27, 0x87, 0x2d, 0xed, 0x64, 0x17, - 0xe7, 0xc2, 0x24, 0xbf, 0xea, 0x7d, 0xc9, 0xc2, 0x9f, 0x19, 0xb8, 0x14, 0x23, 0xb1, 0x13, 0xbc, - 0x91, 0x51, 0x75, 0x9c, 0x96, 0x9b, 0x45, 0x1e, 0xb0, 0x91, 0x33, 0x76, 0xc4, 0x5e, 0x8c, 0xbf, - 0x07, 0xfd, 0xb9, 0xc9, 0xf6, 0x46, 0xce, 0xd8, 0x17, 0x16, 0xf1, 0x07, 0xe0, 0x25, 0x72, 0x8e, - 0x89, 0x9d, 0x03, 0x03, 0xe8, 0x76, 0xa6, 0x70, 0x19, 0xef, 0xec, 0x18, 0x58, 0x44, 0xf1, 0xbc, - 0x5c, 0x52, 0xdc, 0x8c, 0x80, 0x45, 0xd4, 0xae, 0xb9, 0xcc, 0x9b, 0x16, 0xd2, 0x39, 0xfc, 0x8b, - 0x91, 0xd3, 0x8d, 0xb2, 0x1d, 0x77, 0x99, 0xde, 0xbd, 0x0f, 0x43, 0x52, 0xfd, 0xe5, 0xad, 0x54, - 0xd6, 0x61, 0x03, 0xc2, 0xd7, 0x52, 0xf1, 0xcf, 0xa0, 0xaf, 0x6b, 0xbc, 0xc3, 0x65, 0x35, 0xdd, - 0x35, 0xe5, 0x85, 0xbd, 0xd6, 0x68, 0xe5, 0x76, 0xb4, 0x6a, 0xca, 0xf2, 0xba, 0x65, 0x3d, 0x06, - 0x8f, 0x44, 0xaf, 0xf4, 0x77, 0xde, 0xc9, 0x6c, 0xac, 0x61, 0x6e, 0x85, 0x57, 0x70, 0x7f, 0xef, - 0xc5, 0xe6, 0x25, 0xb6, 0xff, 0x52, 0xab, 0x97, 0x6f, 0xf5, 0xa1, 0x29, 0xcf, 0x31, 0xc1, 0xa8, - 0xc0, 0x85, 0xee, 0xec, 0x50, 0x34, 0x38, 0xfc, 0x95, 0xb5, 0xbc, 0xfa, 0x3d, 0x9a, 0xe3, 0x28, - 0x5d, 0xaf, 0xe5, 0x66, 0x61, 0xa9, 0x6b, 0x48, 0x7d, 0x5b, 0xcc, 0x2d, 0x75, 0x6f, 0x31, 0x27, - 0xac, 0x32, 0xab, 0x55, 0x4f, 0x65, 0x7c, 0x04, 0x07, 0x6b, 0x94, 0x79, 0xa9, 0x70, 0x8d, 0x9b, - 0xc2, 0xb6, 0xa0, 0x1b, 0xe2, 0x0f, 0x61, 0x50, 0xc8, 0x9b, 0x97, 0xe4, 0x32, 0xab, 0x59, 0x21, - 0x6f, 0xce, 0xb0, 0xe2, 0x1f, 0x80, 0xbf, 0x8c, 0x31, 0x59, 0xe8, 0x94, 0x11, 0x6e, 0xa8, 0x03, - 0x67, 0x58, 0x85, 0xbf, 0x31, 0xe8, 0xcf, 0x50, 0xdd, 0xa2, 0x7a, 0xab, 0xc5, 0xd0, 0x5d, 0x9c, - 0xce, 0x7f, 0x2c, 0x4e, 0xf7, 0xee, 0xc5, 0xe9, 0xb5, 0x8b, 0xf3, 0x01, 0x78, 0x33, 0x15, 0x9d, - 0x4e, 0xf5, 0x17, 0x39, 0xc2, 0x00, 0xf2, 0xdd, 0x24, 0x2a, 0xe2, 0x5b, 0xb4, 0xdb, 0xd4, 0xa2, - 0xf0, 0x17, 0x06, 0xfd, 0x73, 0x59, 0xa5, 0x65, 0xf1, 0x9a, 0xc3, 0x46, 0x70, 0x30, 0xc9, 0xb2, - 0x24, 0x8e, 0x64, 0x11, 0xa7, 0x1b, 0xfb, 0xb5, 0xdd, 0x10, 0xdd, 0x78, 0xde, 0xe9, 0x9d, 0xf9, - 0xee, 0x6e, 0x88, 0x66, 0xf1, 0x44, 0xef, 0x3b, 0xb3, 0xbc, 0x3a, 0xb3, 0x68, 0xd6, 0x9c, 0x4e, - 0x52, 0x81, 0x93, 0xb2, 0x48, 0x97, 0x49, 0xba, 0xd5, 0x95, 0x0c, 0x45, 0x83, 0xc3, 0xbf, 0x19, - 0xb8, 0xff, 0xd7, 0x1e, 0xbb, 0x07, 0x2c, 0xb6, 0x42, 0xb2, 0xb8, 0xd9, 0x6a, 0x83, 0xce, 0x56, - 0x0b, 0x60, 0x50, 0x29, 0xb9, 0xb9, 0xc1, 0x3c, 0x18, 0xea, 0x1d, 0x51, 0x43, 0x9d, 0xd1, 0x33, - 0x62, 0xd6, 0x99, 0x2f, 0x6a, 0xd8, 0x78, 0x1e, 0x5a, 0xcf, 0x87, 0x7f, 0x32, 0xf0, 0x1a, 0xe7, - 0x9e, 0xec, 0x3b, 0xf7, 0xa4, 0x75, 0xee, 0xf4, 0xb8, 0x76, 0xee, 0xf4, 0x98, 0xb0, 0xb8, 0xa8, - 0x9d, 0x2b, 0x2e, 0xa8, 0x6b, 0xcf, 0x54, 0x5a, 0x66, 0xc7, 0x95, 0x69, 0xaf, 0x2f, 0x1a, 0x4c, - 0x72, 0x7f, 0xbf, 0x42, 0x65, 0x6b, 0xf6, 0x85, 0x45, 0x64, 0x8e, 0x73, 0x3d, 0xd5, 0xa6, 0x4a, - 0x03, 0xf8, 0xc7, 0xe0, 0x09, 0xaa, 0x42, 0x97, 0xba, 0xd7, 0x20, 0x1d, 0x16, 0x26, 0x1b, 0x3e, - 0xb5, 0xd7, 0x88, 0xe5, 0x2a, 0xcb, 0x50, 0x59, 0x4f, 0x1b, 0xa0, 0xb9, 0xd3, 0x2d, 0x9a, 0x75, - 0xe4, 0x08, 0x03, 0xc2, 0x1f, 0xc0, 0x9f, 0x24, 0xa8, 0x0a, 0x51, 0x26, 0xaf, 0x2f, 0x31, 0x0e, - 0xee, 0x37, 0xb3, 0x6f, 0x5f, 0xd4, 0x93, 0x40, 0xe7, 0xd6, 0xbf, 0xce, 0xbf, 0xfc, 0x7b, 0x26, - 0x33, 0x79, 0x3a, 0xd5, 0xc2, 0x3a, 0xc2, 0xa2, 0xf0, 0x53, 0x70, 0x69, 0x4e, 0x3a, 0xcc, 0xee, - 0x9b, 0x66, 0x6c, 0xde, 0xd7, 0x7f, 0x78, 0x9e, 0xfe, 0x13, 0x00, 0x00, 0xff, 0xff, 0x35, 0xc8, - 0x8f, 0x51, 0x02, 0x09, 0x00, 0x00, + // 1006 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x56, 0xcf, 0x8e, 0xe3, 0xc4, + 0x13, 0x56, 0xc7, 0x76, 0x12, 0xd7, 0xcc, 0xce, 0xef, 0xa7, 0xd6, 0x8a, 0x35, 0xcb, 0x25, 0x58, + 0x20, 0x05, 0xa4, 0x1d, 0xd0, 0xae, 0x90, 0x10, 0xb7, 0xcc, 0x04, 0xad, 0x86, 0x99, 0x5d, 0x86, + 0xce, 0xcc, 0x70, 0x42, 0xab, 0x8e, 0x53, 0x99, 0x58, 0xeb, 0xc4, 0xa6, 0x6d, 0x4f, 0xe2, 0xb7, + 0xe0, 0x09, 0x90, 0x90, 0x38, 0x71, 0xe0, 0xc0, 0x0b, 0xf0, 0x10, 0xbc, 0x10, 0xaa, 0xee, 0xf6, + 0x9f, 0xb0, 0xb3, 0x68, 0x4f, 0xdc, 0xfa, 0xab, 0xea, 0x7c, 0xed, 0xaa, 0xef, 0xab, 0x52, 0xe0, + 0x28, 0xde, 0x14, 0xa8, 0x36, 0x32, 0x39, 0xce, 0x54, 0x5a, 0xa4, 0x7c, 0x58, 0xe3, 0xf0, 0xf7, + 0x1e, 0xf4, 0x67, 0x69, 0xa9, 0x22, 0xe4, 0x47, 0xd0, 0x3b, 0x9b, 0x06, 0x6c, 0xc4, 0xc6, 0x8e, + 0xe8, 0x9d, 0x4d, 0x39, 0x07, 0xf7, 0xa5, 0x5c, 0x63, 0xd0, 0x1b, 0xb1, 0xb1, 0x2f, 0xf4, 0x99, + 0x62, 0x57, 0x55, 0x86, 0x81, 0x63, 0x62, 0x74, 0xe6, 0x8f, 0x61, 0x78, 0x9d, 0x13, 0xdb, 0x1a, + 0x03, 0x57, 0xc7, 0x1b, 0x4c, 0xb9, 0x4b, 0x99, 0xe7, 0xdb, 0x54, 0x2d, 0x02, 0xcf, 0xe4, 0x6a, + 0xcc, 0xff, 0x0f, 0xce, 0xb5, 0xb8, 0x08, 0xfa, 0x3a, 0x4c, 0x47, 0x1e, 0xc0, 0x60, 0x8a, 0x4b, + 0x59, 0x26, 0x45, 0x30, 0x18, 0xb1, 0xf1, 0x50, 0xd4, 0x90, 0x78, 0xae, 0x30, 0xc1, 0x5b, 0x25, + 0x97, 0xc1, 0xd0, 0xf0, 0xd4, 0x98, 0x1f, 0x03, 0x3f, 0xdb, 0xe4, 0x18, 0x95, 0x0a, 0x67, 0xaf, + 0xe3, 0xec, 0x06, 0x55, 0xbc, 0xac, 0x02, 0x5f, 0x13, 0xdc, 0x93, 0xa1, 0x57, 0x5e, 0x60, 0x21, + 0xe9, 0x6d, 0xd0, 0x54, 0x35, 0xe4, 0x21, 0x1c, 0xce, 0x56, 0x52, 0xe1, 0x62, 0x86, 0x91, 0xc2, + 0x22, 0x38, 0xd0, 0xe9, 0xbd, 0x58, 0xf8, 0x13, 0x03, 0x7f, 0x2a, 0xf3, 0xd5, 0x3c, 0x95, 0x6a, + 0xf1, 0x4e, 0x3d, 0x7b, 0x02, 0x5e, 0x84, 0x49, 0x92, 0x07, 0xce, 0xc8, 0x19, 0x1f, 0x3c, 0x7d, + 0x74, 0xdc, 0x88, 0xd1, 0xf0, 0x9c, 0x62, 0x92, 0x08, 0x73, 0x8b, 0x7f, 0x0e, 0x7e, 0x81, 0xeb, + 0x2c, 0x91, 0x05, 0xe6, 0x81, 0xab, 0x7f, 0xc2, 0xdb, 0x9f, 0x5c, 0xd9, 0x94, 0x68, 0x2f, 0x85, + 0xbf, 0xf5, 0xe0, 0xc1, 0x1e, 0x15, 0x3f, 0x04, 0xb6, 0xd3, 0x5f, 0xe5, 0x09, 0xb6, 0x23, 0x54, + 0xe9, 0x2f, 0xf2, 0x04, 0xab, 0x08, 0x6d, 0xb5, 0x7e, 0x9e, 0x60, 0x5b, 0x42, 0x2b, 0xad, 0x9a, + 0x27, 0xd8, 0x8a, 0x7f, 0x02, 0x83, 0x1f, 0x4b, 0x54, 0x31, 0xe6, 0x81, 0xa7, 0x5f, 0xfe, 0x5f, + 0xfb, 0xf2, 0x77, 0x25, 0xaa, 0x4a, 0xd4, 0x79, 0xaa, 0x54, 0x2b, 0x6e, 0xe4, 0xd3, 0x67, 0x8a, + 0x15, 0xe4, 0x8e, 0x81, 0x89, 0xd1, 0xd9, 0x76, 0xc8, 0x68, 0x46, 0x1d, 0xfa, 0x02, 0x5c, 0xb9, + 0xc3, 0x3c, 0xf0, 0x35, 0xff, 0x87, 0x6f, 0x69, 0xc6, 0xf1, 0x64, 0x87, 0xf9, 0xd7, 0x9b, 0x42, + 0x55, 0x42, 0x5f, 0x7f, 0xfc, 0x1c, 0xfc, 0x26, 0x44, 0xce, 0x79, 0x8d, 0x95, 0x2e, 0xd0, 0x17, + 0x74, 0xe4, 0x1f, 0x81, 0x77, 0x27, 0x93, 0xd2, 0x34, 0xfe, 0xe0, 0xe9, 0x51, 0x4b, 0x3b, 0xd9, + 0xc5, 0xb9, 0x30, 0xc9, 0xaf, 0x7a, 0x5f, 0xb2, 0xf0, 0x0f, 0x06, 0x2e, 0xc5, 0x48, 0xec, 0x04, + 0x6f, 0x65, 0x54, 0x9d, 0xa4, 0xe5, 0x66, 0x91, 0x07, 0x6c, 0xe4, 0x8c, 0x1d, 0xb1, 0x17, 0xe3, + 0xef, 0x41, 0x7f, 0x6e, 0xb2, 0xbd, 0x91, 0x33, 0xf6, 0x85, 0x45, 0xfc, 0x21, 0x78, 0x89, 0x9c, + 0x63, 0x62, 0xe7, 0xc0, 0x00, 0xba, 0x9d, 0x29, 0x5c, 0xc6, 0x3b, 0x3b, 0x06, 0x16, 0x51, 0x3c, + 0x2f, 0x97, 0x14, 0x37, 0x23, 0x60, 0x11, 0xb5, 0x6b, 0x2e, 0xf3, 0xa6, 0x85, 0x74, 0x26, 0xe6, + 0x3c, 0x92, 0x49, 0xdd, 0x43, 0x03, 0xc2, 0x3f, 0x19, 0xf9, 0xdf, 0xe8, 0xdd, 0xf1, 0x9c, 0xe9, + 0xe8, 0xfb, 0x30, 0x24, 0x2f, 0xbc, 0xba, 0x93, 0xca, 0xfa, 0x6e, 0x40, 0xf8, 0x46, 0x2a, 0xfe, + 0x19, 0xf4, 0x75, 0xe5, 0xf7, 0x78, 0xaf, 0xa6, 0xbb, 0xa1, 0xbc, 0xb0, 0xd7, 0x1a, 0x05, 0xdd, + 0x8e, 0x82, 0x4d, 0xb1, 0x5e, 0xb7, 0xd8, 0x27, 0xe0, 0x91, 0x15, 0x2a, 0xfd, 0xf5, 0xf7, 0x32, + 0x1b, 0xc3, 0x98, 0x5b, 0xe1, 0x35, 0x3c, 0xd8, 0x7b, 0xb1, 0x79, 0x89, 0xed, 0xbf, 0xd4, 0xaa, + 0xe8, 0x5b, 0xd5, 0x68, 0xf6, 0x73, 0x4c, 0x30, 0x2a, 0x70, 0xa1, 0xfb, 0x3d, 0x14, 0x0d, 0x0e, + 0x7f, 0x61, 0x2d, 0xaf, 0x7e, 0x8f, 0xa6, 0x3b, 0x4a, 0xd7, 0x6b, 0xb9, 0x59, 0x58, 0xea, 0x1a, + 0x52, 0xdf, 0x16, 0x73, 0x4b, 0xdd, 0x5b, 0xcc, 0x09, 0xab, 0xcc, 0x2a, 0xd8, 0x53, 0x19, 0x1f, + 0xc1, 0xc1, 0x1a, 0x65, 0x5e, 0x2a, 0x5c, 0xe3, 0xa6, 0xb0, 0x2d, 0xe8, 0x86, 0xf8, 0x23, 0x18, + 0x14, 0xf2, 0xf6, 0x15, 0x79, 0xcf, 0x2a, 0x59, 0xc8, 0xdb, 0x73, 0xac, 0xf8, 0x07, 0xe0, 0x2f, + 0x63, 0x4c, 0x16, 0x3a, 0x65, 0xe4, 0x1c, 0xea, 0xc0, 0x39, 0x56, 0xe1, 0xaf, 0x0c, 0xfa, 0x33, + 0x54, 0x77, 0xa8, 0xde, 0x69, 0x5d, 0x74, 0xd7, 0xa9, 0xf3, 0x2f, 0xeb, 0xd4, 0xbd, 0x7f, 0x9d, + 0x7a, 0xed, 0x3a, 0x7d, 0x08, 0xde, 0x4c, 0x45, 0x67, 0x53, 0xfd, 0x45, 0x8e, 0x30, 0x80, 0xdc, + 0x38, 0x89, 0x8a, 0xf8, 0x0e, 0xed, 0x8e, 0xb5, 0x28, 0xfc, 0x99, 0x41, 0xff, 0x42, 0x56, 0x69, + 0x59, 0xbc, 0xe1, 0xb0, 0x11, 0x1c, 0x4c, 0xb2, 0x2c, 0x89, 0x23, 0x59, 0xc4, 0xe9, 0xc6, 0x7e, + 0x6d, 0x37, 0x44, 0x37, 0x5e, 0x74, 0x7a, 0x67, 0xbe, 0xbb, 0x1b, 0xa2, 0x09, 0x3d, 0xd5, 0x5b, + 0xd0, 0xac, 0xb4, 0xce, 0x84, 0x9a, 0xe5, 0xa7, 0x93, 0x54, 0xe0, 0xa4, 0x2c, 0xd2, 0x65, 0x92, + 0x6e, 0x75, 0x25, 0x43, 0xd1, 0xe0, 0xf0, 0x2f, 0x06, 0xee, 0x7f, 0xb5, 0xdd, 0x0e, 0x81, 0xc5, + 0x56, 0x48, 0x16, 0x37, 0xbb, 0x6e, 0xd0, 0xd9, 0x75, 0x01, 0x0c, 0x2a, 0x25, 0x37, 0xb7, 0x98, + 0x07, 0x43, 0xbd, 0x39, 0x6a, 0xa8, 0x33, 0x7a, 0x46, 0xcc, 0x92, 0xf3, 0x45, 0x0d, 0x1b, 0xcf, + 0x43, 0xeb, 0x79, 0xda, 0x47, 0x5e, 0xe3, 0xdc, 0xd3, 0x7d, 0xe7, 0x9e, 0xb6, 0xce, 0x9d, 0x9e, + 0xd4, 0xce, 0x9d, 0x9e, 0x10, 0x16, 0x97, 0xb5, 0x73, 0xc5, 0x25, 0x75, 0xed, 0xb9, 0x4a, 0xcb, + 0xec, 0xa4, 0x32, 0xed, 0xf5, 0x45, 0x83, 0x49, 0xee, 0xef, 0x57, 0xa8, 0x6c, 0xcd, 0xbe, 0xb0, + 0x88, 0xcc, 0x71, 0xa1, 0xa7, 0xda, 0x54, 0x69, 0x00, 0xff, 0x18, 0x3c, 0x41, 0x55, 0xe8, 0x52, + 0xf7, 0x1a, 0xa4, 0xc3, 0xc2, 0x64, 0xc3, 0x67, 0xf6, 0x1a, 0xb1, 0x5c, 0x67, 0x19, 0x2a, 0xeb, + 0x69, 0x03, 0x34, 0x77, 0xba, 0x45, 0xb3, 0x8e, 0x1c, 0x61, 0x40, 0xf8, 0x03, 0xf8, 0x93, 0x04, + 0x55, 0x21, 0xca, 0xe4, 0xcd, 0x25, 0xc6, 0xc1, 0xfd, 0x66, 0xf6, 0xed, 0xcb, 0x7a, 0x12, 0xe8, + 0xdc, 0xfa, 0xd7, 0xf9, 0x87, 0x7f, 0xcf, 0x65, 0x26, 0xcf, 0xa6, 0x5a, 0x58, 0x47, 0x58, 0x14, + 0x7e, 0x0a, 0x2e, 0xcd, 0x49, 0x87, 0xd9, 0x7d, 0xdb, 0x8c, 0xcd, 0xfb, 0xfa, 0x6f, 0xd0, 0xb3, + 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xa9, 0x7c, 0x6a, 0x48, 0x18, 0x09, 0x00, 0x00, } diff --git a/bolt/internal/internal.proto b/bolt/internal/internal.proto index cb41ec895..aa4fe470b 100644 --- a/bolt/internal/internal.proto +++ b/bolt/internal/internal.proto @@ -41,6 +41,7 @@ message Axis { string prefix = 4; // specifies the prefix for axis values string suffix = 5; // specifies the suffix for axis values string base = 6; // defines the base for axis values + string scale = 7; // represents the magnitude of the numbers on this axis } message Template { diff --git a/bolt/internal/internal_test.go b/bolt/internal/internal_test.go index 2759b7f0f..c57bccd88 100644 --- a/bolt/internal/internal_test.go +++ b/bolt/internal/internal_test.go @@ -171,6 +171,7 @@ func Test_MarshalDashboard(t *testing.T) { Prefix: "M", Suffix: "m", Base: "2", + Scale: "roflscale", }, }, Type: "line", diff --git a/chronograf.go b/chronograf.go index 3affae80a..5b77438de 100644 --- a/chronograf.go +++ b/chronograf.go @@ -647,6 +647,7 @@ type Axis struct { Prefix string `json:"prefix"` // specifies a prefix for axis values Suffix string `json:"suffix"` // specifies a suffix for axis values Base string `json:"base"` // defines the base for axis values + Scale string `json:"scale"` // the magnitude of the numbers for this axis } // DashboardCell holds visual and query information for a cell From 55d07398dd6f9e9bb34147ff3fa94c2bb2415df8 Mon Sep 17 00:00:00 2001 From: Hunter Trujillo Date: Thu, 27 Jul 2017 13:39:51 -0600 Subject: [PATCH 03/47] CHANGELOG. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62a8da107..93ef2cc93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ 1. [#1798](https://github.com/influxdata/chronograf/pull/1798): Fix domain not updating in visualizations when changing time range manually 1. [#1799](https://github.com/influxdata/chronograf/pull/1799): Prevent console error spam from Dygraph's synchronize method when a dashboard has only one graph 1. [#1813](https://github.com/influxdata/chronograf/pull/1813): Guarantee UUID for each Alert Table key to prevent dropping items when keys overlap +1. [#1795](https://github.com/influxdata/chronograf/pull/1795): Fix uptime status on Windows hosts running Telegraf ### Features 1. [#1744](https://github.com/influxdata/chronograf/pull/1744): Add a few time range shortcuts to the custom time range menu From b12e5ef6fcd40d589a35b1e2950dacca0a59d857 Mon Sep 17 00:00:00 2001 From: Hunter Trujillo Date: Thu, 27 Jul 2017 17:08:07 -0600 Subject: [PATCH 04/47] CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93ef2cc93..923841e9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ 1. [#1744](https://github.com/influxdata/chronograf/pull/1744): Add a few time range shortcuts to the custom time range menu 1. [#1714](https://github.com/influxdata/chronograf/pull/1714): Add ability to edit a dashboard graph's y-axis bounds 1. [#1714](https://github.com/influxdata/chronograf/pull/1714): Add ability to edit a dashboard graph's y-axis label +1. [#1744](https://github.com/influxdata/chronograf/pull/1744): Add a few pre-set time range selections to the custom time range menu-- be sure to add a sensible GROUP BY ### UI Improvements 1. [#1796](https://github.com/influxdata/chronograf/pull/1796): Add spinner write data modal to indicate data is being written From 866f1ecf7e5e374fd8112ba138f74c1806f1995c Mon Sep 17 00:00:00 2001 From: Hunter Trujillo Date: Thu, 27 Jul 2017 17:31:24 -0600 Subject: [PATCH 05/47] CHAMGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 923841e9f..caa338fa8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ 1. [#1799](https://github.com/influxdata/chronograf/pull/1799): Prevent console error spam from Dygraph's synchronize method when a dashboard has only one graph 1. [#1813](https://github.com/influxdata/chronograf/pull/1813): Guarantee UUID for each Alert Table key to prevent dropping items when keys overlap 1. [#1795](https://github.com/influxdata/chronograf/pull/1795): Fix uptime status on Windows hosts running Telegraf +1. [#1715](https://github.com/influxdata/chronograf/pull/1715): Chronograf now renders properly on IE11. ### Features 1. [#1744](https://github.com/influxdata/chronograf/pull/1744): Add a few time range shortcuts to the custom time range menu From abf3da2a787fd4199fff1357bde2302aed56ae76 Mon Sep 17 00:00:00 2001 From: Hunter Trujillo Date: Mon, 7 Aug 2017 16:47:02 -0700 Subject: [PATCH 06/47] Update changelog in response to comments. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index caa338fa8..f86faf09f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ 1. [#1714](https://github.com/influxdata/chronograf/pull/1714): Add ability to edit a dashboard graph's y-axis bounds 1. [#1714](https://github.com/influxdata/chronograf/pull/1714): Add ability to edit a dashboard graph's y-axis label 1. [#1744](https://github.com/influxdata/chronograf/pull/1744): Add a few pre-set time range selections to the custom time range menu-- be sure to add a sensible GROUP BY +1. [#1744](https://github.com/influxdata/chronograf/pull/1744): Add a few time range shortcuts to the custom time range menu ### UI Improvements 1. [#1796](https://github.com/influxdata/chronograf/pull/1796): Add spinner write data modal to indicate data is being written From 0cb5523f5b4fef24576147f4ce07c7e9ee74fa0c Mon Sep 17 00:00:00 2001 From: Jared Scheib Date: Tue, 8 Aug 2017 17:38:19 -0700 Subject: [PATCH 07/47] Pass default Y label into DisplayOptions Refactor DisplayOptions into ES6 component Rename buildYLabel to buildDefaultYLabel --- .../dashboards/components/DisplayOptions.js | 8 ++++---- ui/src/shared/components/Dygraph.js | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/ui/src/dashboards/components/DisplayOptions.js b/ui/src/dashboards/components/DisplayOptions.js index edbd71d1f..de67cb3b5 100644 --- a/ui/src/dashboards/components/DisplayOptions.js +++ b/ui/src/dashboards/components/DisplayOptions.js @@ -43,16 +43,16 @@ class DisplayOptions extends Component { return (
- +
) } diff --git a/ui/src/shared/components/Dygraph.js b/ui/src/shared/components/Dygraph.js index ea0f7b925..32cf286c4 100644 --- a/ui/src/shared/components/Dygraph.js +++ b/ui/src/shared/components/Dygraph.js @@ -42,6 +42,25 @@ export default class Dygraph extends Component { dygraphRef: () => {}, } + getTimeSeries() { + const {timeSeries} = this.props + // Avoid 'Can't plot empty data set' errors by falling back to a + // default dataset that's valid for Dygraph. + return timeSeries.length ? timeSeries : [[0]] + } + + getLabel(axis) { + const {axes, queries} = this.props + const label = _.get(axes, [axis, 'label'], '') + const queryConfig = _.get(queries, ['0', 'queryConfig'], false) + + if (label || !queryConfig) { + return label + } + + return buildDefaultYLabel(queryConfig) + } + componentDidMount() { const timeSeries = this.getTimeSeries() // dygraphSeries is a legend label and its corresponding y-axis e.g. {legendLabel1: 'y', legendLabel2: 'y2'}; From a25d19c85063acf104929deb9da60f29383154bb Mon Sep 17 00:00:00 2001 From: Hunter Trujillo Date: Tue, 8 Aug 2017 22:43:16 -0700 Subject: [PATCH 08/47] Add SHOW DATABASES integration test with Nightwatch.js. --- ui/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/package.json b/ui/package.json index b60aa4946..ec0e28389 100644 --- a/ui/package.json +++ b/ui/package.json @@ -17,6 +17,7 @@ "test:integration": "nightwatch tests --skip", "test:lint": "yarn run lint; yarn run test", "test:dev": "concurrently \"yarn run lint -- --watch\" \"yarn run test -- --no-single-run --reporters=verbose\"", + "test:integration": "nightwatch tests --skip", "clean": "rm -rf build", "storybook": "node ./storybook.js", "prettier": "prettier --single-quote --trailing-comma es5 --bracket-spacing false --semi false --write \"{src,spec}/**/*.js\"; eslint src --fix" From e3d8aeead56f9945d84407595750155f075add60 Mon Sep 17 00:00:00 2001 From: Tim Raymond Date: Mon, 24 Jul 2017 18:30:53 -0400 Subject: [PATCH 09/47] Add Axes to Cells on Layouts This allows a creator of a layout to specify the visible extents of graphs for individual cells. For example, a cell displaying a percentage could be limited to values between 0 and 100. Existing canned layouts need to updated as a separate step. However, this adds support for Axes to appear in them as well. --- bolt/internal/internal.pb.go | 127 +++++++++++++++++------------------ 1 file changed, 63 insertions(+), 64 deletions(-) diff --git a/bolt/internal/internal.pb.go b/bolt/internal/internal.pb.go index 317db658a..4af4f8fd0 100644 --- a/bolt/internal/internal.pb.go +++ b/bolt/internal/internal.pb.go @@ -327,68 +327,67 @@ func init() { func init() { proto.RegisterFile("internal.proto", fileDescriptorInternal) } var fileDescriptorInternal = []byte{ - // 1006 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x56, 0xcf, 0x8e, 0xe3, 0xc4, - 0x13, 0x56, 0xc7, 0x76, 0x12, 0xd7, 0xcc, 0xce, 0xef, 0xa7, 0xd6, 0x8a, 0x35, 0xcb, 0x25, 0x58, - 0x20, 0x05, 0xa4, 0x1d, 0xd0, 0xae, 0x90, 0x10, 0xb7, 0xcc, 0x04, 0xad, 0x86, 0x99, 0x5d, 0x86, - 0xce, 0xcc, 0x70, 0x42, 0xab, 0x8e, 0x53, 0x99, 0x58, 0xeb, 0xc4, 0xa6, 0x6d, 0x4f, 0xe2, 0xb7, - 0xe0, 0x09, 0x90, 0x90, 0x38, 0x71, 0xe0, 0xc0, 0x0b, 0xf0, 0x10, 0xbc, 0x10, 0xaa, 0xee, 0xf6, - 0x9f, 0xb0, 0xb3, 0x68, 0x4f, 0xdc, 0xfa, 0xab, 0xea, 0x7c, 0xed, 0xaa, 0xef, 0xab, 0x52, 0xe0, - 0x28, 0xde, 0x14, 0xa8, 0x36, 0x32, 0x39, 0xce, 0x54, 0x5a, 0xa4, 0x7c, 0x58, 0xe3, 0xf0, 0xf7, - 0x1e, 0xf4, 0x67, 0x69, 0xa9, 0x22, 0xe4, 0x47, 0xd0, 0x3b, 0x9b, 0x06, 0x6c, 0xc4, 0xc6, 0x8e, - 0xe8, 0x9d, 0x4d, 0x39, 0x07, 0xf7, 0xa5, 0x5c, 0x63, 0xd0, 0x1b, 0xb1, 0xb1, 0x2f, 0xf4, 0x99, - 0x62, 0x57, 0x55, 0x86, 0x81, 0x63, 0x62, 0x74, 0xe6, 0x8f, 0x61, 0x78, 0x9d, 0x13, 0xdb, 0x1a, - 0x03, 0x57, 0xc7, 0x1b, 0x4c, 0xb9, 0x4b, 0x99, 0xe7, 0xdb, 0x54, 0x2d, 0x02, 0xcf, 0xe4, 0x6a, - 0xcc, 0xff, 0x0f, 0xce, 0xb5, 0xb8, 0x08, 0xfa, 0x3a, 0x4c, 0x47, 0x1e, 0xc0, 0x60, 0x8a, 0x4b, - 0x59, 0x26, 0x45, 0x30, 0x18, 0xb1, 0xf1, 0x50, 0xd4, 0x90, 0x78, 0xae, 0x30, 0xc1, 0x5b, 0x25, - 0x97, 0xc1, 0xd0, 0xf0, 0xd4, 0x98, 0x1f, 0x03, 0x3f, 0xdb, 0xe4, 0x18, 0x95, 0x0a, 0x67, 0xaf, - 0xe3, 0xec, 0x06, 0x55, 0xbc, 0xac, 0x02, 0x5f, 0x13, 0xdc, 0x93, 0xa1, 0x57, 0x5e, 0x60, 0x21, - 0xe9, 0x6d, 0xd0, 0x54, 0x35, 0xe4, 0x21, 0x1c, 0xce, 0x56, 0x52, 0xe1, 0x62, 0x86, 0x91, 0xc2, - 0x22, 0x38, 0xd0, 0xe9, 0xbd, 0x58, 0xf8, 0x13, 0x03, 0x7f, 0x2a, 0xf3, 0xd5, 0x3c, 0x95, 0x6a, - 0xf1, 0x4e, 0x3d, 0x7b, 0x02, 0x5e, 0x84, 0x49, 0x92, 0x07, 0xce, 0xc8, 0x19, 0x1f, 0x3c, 0x7d, - 0x74, 0xdc, 0x88, 0xd1, 0xf0, 0x9c, 0x62, 0x92, 0x08, 0x73, 0x8b, 0x7f, 0x0e, 0x7e, 0x81, 0xeb, - 0x2c, 0x91, 0x05, 0xe6, 0x81, 0xab, 0x7f, 0xc2, 0xdb, 0x9f, 0x5c, 0xd9, 0x94, 0x68, 0x2f, 0x85, - 0xbf, 0xf5, 0xe0, 0xc1, 0x1e, 0x15, 0x3f, 0x04, 0xb6, 0xd3, 0x5f, 0xe5, 0x09, 0xb6, 0x23, 0x54, - 0xe9, 0x2f, 0xf2, 0x04, 0xab, 0x08, 0x6d, 0xb5, 0x7e, 0x9e, 0x60, 0x5b, 0x42, 0x2b, 0xad, 0x9a, - 0x27, 0xd8, 0x8a, 0x7f, 0x02, 0x83, 0x1f, 0x4b, 0x54, 0x31, 0xe6, 0x81, 0xa7, 0x5f, 0xfe, 0x5f, - 0xfb, 0xf2, 0x77, 0x25, 0xaa, 0x4a, 0xd4, 0x79, 0xaa, 0x54, 0x2b, 0x6e, 0xe4, 0xd3, 0x67, 0x8a, - 0x15, 0xe4, 0x8e, 0x81, 0x89, 0xd1, 0xd9, 0x76, 0xc8, 0x68, 0x46, 0x1d, 0xfa, 0x02, 0x5c, 0xb9, - 0xc3, 0x3c, 0xf0, 0x35, 0xff, 0x87, 0x6f, 0x69, 0xc6, 0xf1, 0x64, 0x87, 0xf9, 0xd7, 0x9b, 0x42, - 0x55, 0x42, 0x5f, 0x7f, 0xfc, 0x1c, 0xfc, 0x26, 0x44, 0xce, 0x79, 0x8d, 0x95, 0x2e, 0xd0, 0x17, - 0x74, 0xe4, 0x1f, 0x81, 0x77, 0x27, 0x93, 0xd2, 0x34, 0xfe, 0xe0, 0xe9, 0x51, 0x4b, 0x3b, 0xd9, - 0xc5, 0xb9, 0x30, 0xc9, 0xaf, 0x7a, 0x5f, 0xb2, 0xf0, 0x0f, 0x06, 0x2e, 0xc5, 0x48, 0xec, 0x04, - 0x6f, 0x65, 0x54, 0x9d, 0xa4, 0xe5, 0x66, 0x91, 0x07, 0x6c, 0xe4, 0x8c, 0x1d, 0xb1, 0x17, 0xe3, - 0xef, 0x41, 0x7f, 0x6e, 0xb2, 0xbd, 0x91, 0x33, 0xf6, 0x85, 0x45, 0xfc, 0x21, 0x78, 0x89, 0x9c, - 0x63, 0x62, 0xe7, 0xc0, 0x00, 0xba, 0x9d, 0x29, 0x5c, 0xc6, 0x3b, 0x3b, 0x06, 0x16, 0x51, 0x3c, - 0x2f, 0x97, 0x14, 0x37, 0x23, 0x60, 0x11, 0xb5, 0x6b, 0x2e, 0xf3, 0xa6, 0x85, 0x74, 0x26, 0xe6, - 0x3c, 0x92, 0x49, 0xdd, 0x43, 0x03, 0xc2, 0x3f, 0x19, 0xf9, 0xdf, 0xe8, 0xdd, 0xf1, 0x9c, 0xe9, - 0xe8, 0xfb, 0x30, 0x24, 0x2f, 0xbc, 0xba, 0x93, 0xca, 0xfa, 0x6e, 0x40, 0xf8, 0x46, 0x2a, 0xfe, - 0x19, 0xf4, 0x75, 0xe5, 0xf7, 0x78, 0xaf, 0xa6, 0xbb, 0xa1, 0xbc, 0xb0, 0xd7, 0x1a, 0x05, 0xdd, - 0x8e, 0x82, 0x4d, 0xb1, 0x5e, 0xb7, 0xd8, 0x27, 0xe0, 0x91, 0x15, 0x2a, 0xfd, 0xf5, 0xf7, 0x32, - 0x1b, 0xc3, 0x98, 0x5b, 0xe1, 0x35, 0x3c, 0xd8, 0x7b, 0xb1, 0x79, 0x89, 0xed, 0xbf, 0xd4, 0xaa, - 0xe8, 0x5b, 0xd5, 0x68, 0xf6, 0x73, 0x4c, 0x30, 0x2a, 0x70, 0xa1, 0xfb, 0x3d, 0x14, 0x0d, 0x0e, - 0x7f, 0x61, 0x2d, 0xaf, 0x7e, 0x8f, 0xa6, 0x3b, 0x4a, 0xd7, 0x6b, 0xb9, 0x59, 0x58, 0xea, 0x1a, - 0x52, 0xdf, 0x16, 0x73, 0x4b, 0xdd, 0x5b, 0xcc, 0x09, 0xab, 0xcc, 0x2a, 0xd8, 0x53, 0x19, 0x1f, - 0xc1, 0xc1, 0x1a, 0x65, 0x5e, 0x2a, 0x5c, 0xe3, 0xa6, 0xb0, 0x2d, 0xe8, 0x86, 0xf8, 0x23, 0x18, - 0x14, 0xf2, 0xf6, 0x15, 0x79, 0xcf, 0x2a, 0x59, 0xc8, 0xdb, 0x73, 0xac, 0xf8, 0x07, 0xe0, 0x2f, - 0x63, 0x4c, 0x16, 0x3a, 0x65, 0xe4, 0x1c, 0xea, 0xc0, 0x39, 0x56, 0xe1, 0xaf, 0x0c, 0xfa, 0x33, - 0x54, 0x77, 0xa8, 0xde, 0x69, 0x5d, 0x74, 0xd7, 0xa9, 0xf3, 0x2f, 0xeb, 0xd4, 0xbd, 0x7f, 0x9d, - 0x7a, 0xed, 0x3a, 0x7d, 0x08, 0xde, 0x4c, 0x45, 0x67, 0x53, 0xfd, 0x45, 0x8e, 0x30, 0x80, 0xdc, - 0x38, 0x89, 0x8a, 0xf8, 0x0e, 0xed, 0x8e, 0xb5, 0x28, 0xfc, 0x99, 0x41, 0xff, 0x42, 0x56, 0x69, - 0x59, 0xbc, 0xe1, 0xb0, 0x11, 0x1c, 0x4c, 0xb2, 0x2c, 0x89, 0x23, 0x59, 0xc4, 0xe9, 0xc6, 0x7e, - 0x6d, 0x37, 0x44, 0x37, 0x5e, 0x74, 0x7a, 0x67, 0xbe, 0xbb, 0x1b, 0xa2, 0x09, 0x3d, 0xd5, 0x5b, - 0xd0, 0xac, 0xb4, 0xce, 0x84, 0x9a, 0xe5, 0xa7, 0x93, 0x54, 0xe0, 0xa4, 0x2c, 0xd2, 0x65, 0x92, - 0x6e, 0x75, 0x25, 0x43, 0xd1, 0xe0, 0xf0, 0x2f, 0x06, 0xee, 0x7f, 0xb5, 0xdd, 0x0e, 0x81, 0xc5, - 0x56, 0x48, 0x16, 0x37, 0xbb, 0x6e, 0xd0, 0xd9, 0x75, 0x01, 0x0c, 0x2a, 0x25, 0x37, 0xb7, 0x98, - 0x07, 0x43, 0xbd, 0x39, 0x6a, 0xa8, 0x33, 0x7a, 0x46, 0xcc, 0x92, 0xf3, 0x45, 0x0d, 0x1b, 0xcf, - 0x43, 0xeb, 0x79, 0xda, 0x47, 0x5e, 0xe3, 0xdc, 0xd3, 0x7d, 0xe7, 0x9e, 0xb6, 0xce, 0x9d, 0x9e, - 0xd4, 0xce, 0x9d, 0x9e, 0x10, 0x16, 0x97, 0xb5, 0x73, 0xc5, 0x25, 0x75, 0xed, 0xb9, 0x4a, 0xcb, - 0xec, 0xa4, 0x32, 0xed, 0xf5, 0x45, 0x83, 0x49, 0xee, 0xef, 0x57, 0xa8, 0x6c, 0xcd, 0xbe, 0xb0, - 0x88, 0xcc, 0x71, 0xa1, 0xa7, 0xda, 0x54, 0x69, 0x00, 0xff, 0x18, 0x3c, 0x41, 0x55, 0xe8, 0x52, - 0xf7, 0x1a, 0xa4, 0xc3, 0xc2, 0x64, 0xc3, 0x67, 0xf6, 0x1a, 0xb1, 0x5c, 0x67, 0x19, 0x2a, 0xeb, - 0x69, 0x03, 0x34, 0x77, 0xba, 0x45, 0xb3, 0x8e, 0x1c, 0x61, 0x40, 0xf8, 0x03, 0xf8, 0x93, 0x04, - 0x55, 0x21, 0xca, 0xe4, 0xcd, 0x25, 0xc6, 0xc1, 0xfd, 0x66, 0xf6, 0xed, 0xcb, 0x7a, 0x12, 0xe8, - 0xdc, 0xfa, 0xd7, 0xf9, 0x87, 0x7f, 0xcf, 0x65, 0x26, 0xcf, 0xa6, 0x5a, 0x58, 0x47, 0x58, 0x14, - 0x7e, 0x0a, 0x2e, 0xcd, 0x49, 0x87, 0xd9, 0x7d, 0xdb, 0x8c, 0xcd, 0xfb, 0xfa, 0x6f, 0xd0, 0xb3, - 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xa9, 0x7c, 0x6a, 0x48, 0x18, 0x09, 0x00, 0x00, + // 985 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x56, 0xcd, 0x6e, 0x23, 0x45, + 0x10, 0x56, 0xcf, 0x8f, 0xed, 0x29, 0x67, 0x03, 0x6a, 0xad, 0xd8, 0x61, 0xb9, 0x98, 0x11, 0x48, + 0x06, 0x41, 0x40, 0xbb, 0x42, 0x42, 0xdc, 0x9c, 0x18, 0xad, 0x42, 0xb2, 0x4b, 0x68, 0x27, 0x81, + 0x0b, 0x5a, 0xb5, 0xc7, 0x95, 0x64, 0xb4, 0x63, 0xcf, 0xd0, 0x33, 0x13, 0x7b, 0xde, 0x82, 0x27, + 0x40, 0x42, 0xe2, 0xc4, 0x81, 0x03, 0x2f, 0xc0, 0x9d, 0xa7, 0x42, 0xd5, 0xdd, 0x33, 0x1e, 0xb3, + 0x59, 0xb4, 0x17, 0xf6, 0xd6, 0x5f, 0x55, 0xbb, 0xba, 0xe6, 0xab, 0xfa, 0x3e, 0x19, 0xf6, 0x93, + 0x55, 0x89, 0x6a, 0x25, 0xd3, 0x83, 0x5c, 0x65, 0x65, 0xc6, 0x07, 0x0d, 0x8e, 0xfe, 0x70, 0xa0, + 0x37, 0xcb, 0x2a, 0x15, 0x23, 0xdf, 0x07, 0xe7, 0x78, 0x1a, 0xb2, 0x11, 0x1b, 0xbb, 0xc2, 0x39, + 0x9e, 0x72, 0x0e, 0xde, 0x33, 0xb9, 0xc4, 0xd0, 0x19, 0xb1, 0x71, 0x20, 0xf4, 0x99, 0x62, 0xe7, + 0x75, 0x8e, 0xa1, 0x6b, 0x62, 0x74, 0xe6, 0x0f, 0x61, 0x70, 0x51, 0x50, 0xb5, 0x25, 0x86, 0x9e, + 0x8e, 0xb7, 0x98, 0x72, 0x67, 0xb2, 0x28, 0xd6, 0x99, 0x5a, 0x84, 0xbe, 0xc9, 0x35, 0x98, 0xbf, + 0x0d, 0xee, 0x85, 0x38, 0x0d, 0x7b, 0x3a, 0x4c, 0x47, 0x1e, 0x42, 0x7f, 0x8a, 0x57, 0xb2, 0x4a, + 0xcb, 0xb0, 0x3f, 0x62, 0xe3, 0x81, 0x68, 0x20, 0xd5, 0x39, 0xc7, 0x14, 0xaf, 0x95, 0xbc, 0x0a, + 0x07, 0xa6, 0x4e, 0x83, 0xf9, 0x01, 0xf0, 0xe3, 0x55, 0x81, 0x71, 0xa5, 0x70, 0xf6, 0x22, 0xc9, + 0x2f, 0x51, 0x25, 0x57, 0x75, 0x18, 0xe8, 0x02, 0x77, 0x64, 0xe8, 0x95, 0xa7, 0x58, 0x4a, 0x7a, + 0x1b, 0x74, 0xa9, 0x06, 0xf2, 0x08, 0xf6, 0x66, 0x37, 0x52, 0xe1, 0x62, 0x86, 0xb1, 0xc2, 0x32, + 0x1c, 0xea, 0xf4, 0x4e, 0x2c, 0xfa, 0x99, 0x41, 0x30, 0x95, 0xc5, 0xcd, 0x3c, 0x93, 0x6a, 0xf1, + 0x5a, 0x9c, 0x7d, 0x0a, 0x7e, 0x8c, 0x69, 0x5a, 0x84, 0xee, 0xc8, 0x1d, 0x0f, 0x1f, 0x3d, 0x38, + 0x68, 0x87, 0xd1, 0xd6, 0x39, 0xc2, 0x34, 0x15, 0xe6, 0x16, 0xff, 0x1c, 0x82, 0x12, 0x97, 0x79, + 0x2a, 0x4b, 0x2c, 0x42, 0x4f, 0xff, 0x84, 0x6f, 0x7f, 0x72, 0x6e, 0x53, 0x62, 0x7b, 0x29, 0xfa, + 0xdd, 0x81, 0x7b, 0x3b, 0xa5, 0xf8, 0x1e, 0xb0, 0x8d, 0xee, 0xca, 0x17, 0x6c, 0x43, 0xa8, 0xd6, + 0x1d, 0xf9, 0x82, 0xd5, 0x84, 0xd6, 0x7a, 0x7e, 0xbe, 0x60, 0x6b, 0x42, 0x37, 0x7a, 0x6a, 0xbe, + 0x60, 0x37, 0xfc, 0x23, 0xe8, 0xff, 0x54, 0xa1, 0x4a, 0xb0, 0x08, 0x7d, 0xfd, 0xf2, 0x5b, 0xdb, + 0x97, 0xbf, 0xab, 0x50, 0xd5, 0xa2, 0xc9, 0xd3, 0x97, 0xea, 0x89, 0x9b, 0xf1, 0xe9, 0x33, 0xc5, + 0x4a, 0xda, 0x8e, 0xbe, 0x89, 0xd1, 0xd9, 0x32, 0x64, 0x66, 0x46, 0x0c, 0x7d, 0x01, 0x9e, 0xdc, + 0x60, 0x11, 0x06, 0xba, 0xfe, 0xfb, 0xaf, 0x20, 0xe3, 0x60, 0xb2, 0xc1, 0xe2, 0xeb, 0x55, 0xa9, + 0x6a, 0xa1, 0xaf, 0x3f, 0x7c, 0x02, 0x41, 0x1b, 0xa2, 0xcd, 0x79, 0x81, 0xb5, 0xfe, 0xc0, 0x40, + 0xd0, 0x91, 0x7f, 0x00, 0xfe, 0xad, 0x4c, 0x2b, 0x43, 0xfc, 0xf0, 0xd1, 0xfe, 0xb6, 0xec, 0x64, + 0x93, 0x14, 0xc2, 0x24, 0xbf, 0x72, 0xbe, 0x64, 0xd1, 0x0f, 0xe0, 0x51, 0x88, 0x66, 0x9d, 0xe2, + 0xb5, 0x8c, 0xeb, 0xc3, 0xac, 0x5a, 0x2d, 0x8a, 0x90, 0x8d, 0xdc, 0xb1, 0x2b, 0x76, 0x62, 0xfc, + 0x1d, 0xe8, 0xcd, 0x4d, 0xd6, 0x19, 0xb9, 0xe3, 0x40, 0x58, 0xc4, 0xef, 0x83, 0x9f, 0xca, 0x39, + 0xa6, 0x56, 0x06, 0x06, 0x44, 0x7f, 0x31, 0x5a, 0x52, 0x33, 0x94, 0xce, 0x62, 0x98, 0xcf, 0x7e, + 0x17, 0x06, 0x34, 0xb0, 0xe7, 0xb7, 0x52, 0xd9, 0xe5, 0xe8, 0x13, 0xbe, 0x94, 0x8a, 0x7f, 0x06, + 0x3d, 0xdd, 0xde, 0x1d, 0x0b, 0xd2, 0x94, 0xbb, 0xa4, 0xbc, 0xb0, 0xd7, 0x5a, 0x9a, 0xbd, 0x0e, + 0xcd, 0x6d, 0x4b, 0x7e, 0xa7, 0x25, 0x5a, 0x3d, 0x9a, 0x57, 0xad, 0xa7, 0x74, 0x67, 0x65, 0x33, + 0x55, 0x73, 0x2b, 0xba, 0x80, 0x7b, 0x3b, 0x2f, 0xb6, 0x2f, 0xb1, 0xdd, 0x97, 0xb6, 0x54, 0x07, + 0x96, 0x5a, 0x12, 0x68, 0x81, 0x29, 0xc6, 0x25, 0x2e, 0x34, 0x2b, 0x03, 0xd1, 0xe2, 0xe8, 0x57, + 0xb6, 0xad, 0xab, 0xdf, 0x23, 0x09, 0xc6, 0xd9, 0x72, 0x29, 0x57, 0x0b, 0x5b, 0xba, 0x81, 0xc4, + 0xdb, 0x62, 0x6e, 0x4b, 0x3b, 0x8b, 0x39, 0x61, 0x95, 0x5b, 0x9e, 0x1d, 0x95, 0xf3, 0x11, 0x0c, + 0x97, 0x28, 0x8b, 0x4a, 0xe1, 0x12, 0x57, 0xa5, 0xa5, 0xa0, 0x1b, 0xe2, 0x0f, 0xa0, 0x5f, 0xca, + 0xeb, 0xe7, 0xb4, 0x20, 0x86, 0x8b, 0x5e, 0x29, 0xaf, 0x4f, 0xb0, 0xe6, 0xef, 0x41, 0x70, 0x95, + 0x60, 0xba, 0xd0, 0x29, 0xb3, 0xb6, 0x03, 0x1d, 0x38, 0xc1, 0x3a, 0xfa, 0x8d, 0x41, 0x6f, 0x86, + 0xea, 0x16, 0xd5, 0x6b, 0x69, 0xba, 0xeb, 0x79, 0xee, 0x7f, 0x78, 0x9e, 0x77, 0xb7, 0xe7, 0xf9, + 0x5b, 0xcf, 0xbb, 0x0f, 0xfe, 0x4c, 0xc5, 0xc7, 0x53, 0xdd, 0x91, 0x2b, 0x0c, 0xa0, 0xcd, 0x9b, + 0xc4, 0x65, 0x72, 0x8b, 0xd6, 0x08, 0x2d, 0x8a, 0x7e, 0x61, 0xd0, 0x3b, 0x95, 0x75, 0x56, 0x95, + 0x2f, 0x6d, 0xd8, 0x08, 0x86, 0x93, 0x3c, 0x4f, 0x93, 0x58, 0x96, 0x49, 0xb6, 0xb2, 0xdd, 0x76, + 0x43, 0x74, 0xe3, 0x69, 0x87, 0x3b, 0xd3, 0x77, 0x37, 0x44, 0x32, 0x3a, 0xd2, 0x56, 0x65, 0x7c, + 0xa7, 0x23, 0x23, 0xe3, 0x50, 0x3a, 0x49, 0x1f, 0x38, 0xa9, 0xca, 0xec, 0x2a, 0xcd, 0xd6, 0xfa, + 0x4b, 0x06, 0xa2, 0xc5, 0xd1, 0xdf, 0x0e, 0x78, 0x6f, 0xca, 0x82, 0xf6, 0x80, 0x25, 0x76, 0x90, + 0x2c, 0x69, 0x0d, 0xa9, 0xdf, 0x31, 0xa4, 0x10, 0xfa, 0xb5, 0x92, 0xab, 0x6b, 0x2c, 0xc2, 0x81, + 0xd6, 0x77, 0x03, 0x75, 0x46, 0x6b, 0xc4, 0x38, 0x51, 0x20, 0x1a, 0xd8, 0xee, 0x3c, 0x74, 0x76, + 0xfe, 0x13, 0x6b, 0x5a, 0x43, 0xdd, 0x51, 0xb8, 0x4b, 0xcb, 0xff, 0xe7, 0x55, 0x7f, 0x32, 0xf0, + 0x5b, 0xc1, 0x1c, 0xed, 0x0a, 0xe6, 0x68, 0x2b, 0x98, 0xe9, 0x61, 0x23, 0x98, 0xe9, 0x21, 0x61, + 0x71, 0xd6, 0x08, 0x46, 0x9c, 0xd1, 0xb0, 0x9e, 0xa8, 0xac, 0xca, 0x0f, 0x6b, 0x33, 0xd5, 0x40, + 0xb4, 0x98, 0xb6, 0xec, 0xfb, 0x1b, 0x54, 0x96, 0xea, 0x40, 0x58, 0x44, 0x3b, 0x79, 0xaa, 0xcd, + 0xc4, 0x90, 0x6b, 0x00, 0xff, 0x10, 0x7c, 0x41, 0xe4, 0x69, 0x86, 0x77, 0xe6, 0xa2, 0xc3, 0xc2, + 0x64, 0xa3, 0xc7, 0xf6, 0x1a, 0x55, 0xb9, 0xc8, 0x73, 0x54, 0x56, 0x4a, 0x06, 0xe8, 0xda, 0xd9, + 0x1a, 0x8d, 0x0b, 0xba, 0xc2, 0x80, 0xe8, 0x47, 0x08, 0x26, 0x29, 0xaa, 0x52, 0x54, 0xe9, 0xcb, + 0xde, 0xc9, 0xc1, 0xfb, 0x66, 0xf6, 0xed, 0xb3, 0x46, 0x80, 0x74, 0xde, 0xca, 0xc6, 0xfd, 0x97, + 0x6c, 0x4e, 0x64, 0x2e, 0x8f, 0xa7, 0x7a, 0x9f, 0x5c, 0x61, 0x51, 0xf4, 0x31, 0x78, 0x24, 0xcf, + 0x4e, 0x65, 0xef, 0x55, 0xd2, 0x9e, 0xf7, 0xf4, 0x5f, 0xa4, 0xc7, 0xff, 0x04, 0x00, 0x00, 0xff, + 0xff, 0x5a, 0xf0, 0x92, 0xd4, 0x34, 0x09, 0x00, 0x00, } From fb52d7982182d49b5c619945c7310c40580fef2c Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Tue, 8 Aug 2017 16:33:08 -0700 Subject: [PATCH 10/47] Change height of table dynamically according to resizer --- ui/src/data_explorer/components/Table.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/data_explorer/components/Table.js b/ui/src/data_explorer/components/Table.js index 978c99d74..88c1ca555 100644 --- a/ui/src/data_explorer/components/Table.js +++ b/ui/src/data_explorer/components/Table.js @@ -103,7 +103,7 @@ class ChronoTable extends Component { const minWidth = 70 const rowHeight = 34 const headerHeight = 30 - const stylePixelOffset = 125 + const stylePixelOffset = 130 const defaultColumnWidth = 200 const styleAdjustedHeight = height - stylePixelOffset const width = From 32c3874a947e07087ffd8f8fcb0124a9d8d86c41 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Thu, 10 Aug 2017 15:48:07 -0700 Subject: [PATCH 11/47] Move active query logic to container --- .../components/CellEditorOverlay.js | 53 +++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/ui/src/dashboards/components/CellEditorOverlay.js b/ui/src/dashboards/components/CellEditorOverlay.js index 3ee8d0d4d..026d0bda6 100644 --- a/ui/src/dashboards/components/CellEditorOverlay.js +++ b/ui/src/dashboards/components/CellEditorOverlay.js @@ -88,6 +88,22 @@ class CellEditorOverlay extends Component { this.setState({axes: {...axes, y: {...axes.y, label}}}) } + handleSetPrefixSuffix = e => { + const {axes} = this.state + const {prefix, suffix} = e.target.form + + this.setState({ + axes: { + ...axes, + y: { + ...axes.y, + prefix: prefix.value, + suffix: suffix.value, + }, + }, + }) + } + handleAddQuery = () => { const {queriesWorkingDraft} = this.state const newIndex = queriesWorkingDraft.length @@ -149,6 +165,34 @@ class CellEditorOverlay extends Component { this.setState({activeQueryIndex}) } + handleSetBase = base => () => { + const {axes} = this.state + + this.setState({ + axes: { + ...axes, + y: { + ...axes.y, + base, + }, + }, + }) + } + + handleSetScale = scale => () => { + const {axes} = this.state + + this.setState({ + axes: { + ...axes, + y: { + ...axes.y, + scale, + }, + }, + }) + } + getActiveQuery = () => { const {queriesWorkingDraft, activeQueryIndex} = this.state const activeQuery = queriesWorkingDraft[activeQueryIndex] @@ -230,13 +274,16 @@ class CellEditorOverlay extends Component { /> {isDisplayOptionsTabActive ? : Date: Mon, 14 Aug 2017 10:43:24 -0700 Subject: [PATCH 12/47] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f86faf09f..8508f78d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ 1. [#1872](https://github.com/influxdata/chronograf/pull/1872): Prevent stats in the legend from wrapping line 1. [#1899](https://github.com/influxdata/chronograf/pull/1899): Fix raw query editor in Data Explorer not using selected time 1. [#1922](https://github.com/influxdata/chronograf/pull/1922): Fix Safari display issues in the Cell Editor display options +1. [#1715](https://github.com/influxdata/chronograf/pull/1715): Chronograf now renders on IE11. ### Features 1. [#1863](https://github.com/influxdata/chronograf/pull/1863): Improve 'new-sources' server flag example by adding 'type' key From fea0c91e8f97bbb13043334e32d3897672e4c2e0 Mon Sep 17 00:00:00 2001 From: Tim Raymond Date: Mon, 14 Aug 2017 14:03:40 -0400 Subject: [PATCH 13/47] Update CHANGELOG w/ fix for single stat --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8508f78d0..2b1adc4c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ 1. [#1899](https://github.com/influxdata/chronograf/pull/1899): Fix raw query editor in Data Explorer not using selected time 1. [#1922](https://github.com/influxdata/chronograf/pull/1922): Fix Safari display issues in the Cell Editor display options 1. [#1715](https://github.com/influxdata/chronograf/pull/1715): Chronograf now renders on IE11. +1. [#1866](https://github.com/influxdata/chronograf/pull/1866): Fix missing cell type (and consequently single-stat) ### Features 1. [#1863](https://github.com/influxdata/chronograf/pull/1863): Improve 'new-sources' server flag example by adding 'type' key From 155b41da8020be997c9455149d569a292394ab27 Mon Sep 17 00:00:00 2001 From: Tim Raymond Date: Mon, 14 Aug 2017 14:26:47 -0400 Subject: [PATCH 14/47] Update CHANGELOG and version for v1.3.6.1 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b1adc4c0..48a5e7602 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## v1.3.7.0 [unreleased] +## v1.3.6.1 [2017-08-14] ### Bug Fixes 1. [#1795](https://github.com/influxdata/chronograf/pull/1795): Fix uptime status on Windows hosts running Telegraf 1. [#1715](https://github.com/influxdata/chronograf/pull/1715): Chronograf now renders on IE11. From ca9b01594e144a96f1cd7a0bc019b10f2509c6af Mon Sep 17 00:00:00 2001 From: Tim Raymond Date: Mon, 14 Aug 2017 15:26:09 -0400 Subject: [PATCH 15/47] Update CHANGELOG with data corruption notes --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48a5e7602..b5ed22d19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ 1. [#1922](https://github.com/influxdata/chronograf/pull/1922): Fix Safari display issues in the Cell Editor display options 1. [#1715](https://github.com/influxdata/chronograf/pull/1715): Chronograf now renders on IE11. 1. [#1866](https://github.com/influxdata/chronograf/pull/1866): Fix missing cell type (and consequently single-stat) +1. [#1866](https://github.com/influxdata/chronograf/pull/1866): Fix data corruption issue with dashboard graph types + **Note**: If you upgraded to 1.3.6.0 and visited any dashboard, you will need to manually reset the graph type for every cell via the cell's caret -> Edit -> Display Options. ### Features 1. [#1863](https://github.com/influxdata/chronograf/pull/1863): Improve 'new-sources' server flag example by adding 'type' key From d9b736d1474cd1730662021c72905dd56166b4e6 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Mon, 14 Aug 2017 15:26:22 -0700 Subject: [PATCH 16/47] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5ed22d19..ccc7ffa5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ 1. [#1866](https://github.com/influxdata/chronograf/pull/1866): Fix missing cell type (and consequently single-stat) 1. [#1866](https://github.com/influxdata/chronograf/pull/1866): Fix data corruption issue with dashboard graph types **Note**: If you upgraded to 1.3.6.0 and visited any dashboard, you will need to manually reset the graph type for every cell via the cell's caret -> Edit -> Display Options. +1. [#1870](https://github.com/influxdata/chronograf/pull/1870): Fix console error for placing prop on div ### Features 1. [#1863](https://github.com/influxdata/chronograf/pull/1863): Improve 'new-sources' server flag example by adding 'type' key From ab275e121005e64a6773f236d491df52d0f9fc88 Mon Sep 17 00:00:00 2001 From: Jared Scheib Date: Mon, 14 Aug 2017 16:40:02 -0700 Subject: [PATCH 17/47] Clarify data corruption release note, clean up changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccc7ffa5a..8f327ad5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ ## v1.3.6.1 [2017-08-14] +**Upgrade Note** This release (1.3.6.1) fixes a possibly data corruption issue with dashboard cells' graph types. If you upgraded to 1.3.6.0 and visited any dashboard, once you have then upgraded to this release (1.3.6.1) you will need to manually reset the graph type for every cell via the cell's caret --> Edit --> Display Options. If you upgraded directly to 1.3.6.1, you should not experience this issue. + ### Bug Fixes 1. [#1795](https://github.com/influxdata/chronograf/pull/1795): Fix uptime status on Windows hosts running Telegraf 1. [#1715](https://github.com/influxdata/chronograf/pull/1715): Chronograf now renders on IE11. @@ -17,6 +19,8 @@ 1. [#1866](https://github.com/influxdata/chronograf/pull/1866): Fix data corruption issue with dashboard graph types **Note**: If you upgraded to 1.3.6.0 and visited any dashboard, you will need to manually reset the graph type for every cell via the cell's caret -> Edit -> Display Options. 1. [#1870](https://github.com/influxdata/chronograf/pull/1870): Fix console error for placing prop on div +1. [#1845](https://github.com/influxdata/chronograf/pull/1845): Fix inaccessible scroll bar in Data Explorer table +1. [#1866](https://github.com/influxdata/chronograf/pull/1866): Fix non-persistence of dashboard graph types ### Features 1. [#1863](https://github.com/influxdata/chronograf/pull/1863): Improve 'new-sources' server flag example by adding 'type' key From 2f509f21c8eae187edabe66df13992074cb11bef Mon Sep 17 00:00:00 2001 From: Alex P Date: Tue, 15 Aug 2017 09:58:24 -0700 Subject: [PATCH 18/47] Updoot changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f327ad5b..778452f4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ 1. [#1870](https://github.com/influxdata/chronograf/pull/1870): Fix console error for placing prop on div 1. [#1845](https://github.com/influxdata/chronograf/pull/1845): Fix inaccessible scroll bar in Data Explorer table 1. [#1866](https://github.com/influxdata/chronograf/pull/1866): Fix non-persistence of dashboard graph types +1. [#1872](https://github.com/influxdata/chronograf/pull/1872): Prevent stats in the legend from wrapping line + ### Features 1. [#1863](https://github.com/influxdata/chronograf/pull/1863): Improve 'new-sources' server flag example by adding 'type' key From 8cae0863aec7a7a74341885e22d2fbf84c9f738a Mon Sep 17 00:00:00 2001 From: Tim Raymond Date: Wed, 16 Aug 2017 16:44:43 -0400 Subject: [PATCH 19/47] Update CHANGELOG for layout cell axes --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 778452f4e..b6e2f48ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ 1. [#1863](https://github.com/influxdata/chronograf/pull/1863): Improve 'new-sources' server flag example by adding 'type' key 1. [#1898](https://github.com/influxdata/chronograf/pull/1898): Add an input and validation to custom time range calendar dropdowns 1. [#1904](https://github.com/influxdata/chronograf/pull/1904): Add support for selecting template variables with URL params +1. [#1859](https://github.com/influxdata/chronograf/pull/1859): Add y-axis controls to the API for layouts ### UI Improvements 1. [#1862](https://github.com/influxdata/chronograf/pull/1862): Show "Add Graph" button on cells with no queries From e0f397f8dd510a5bc172e65d9ad1573ee1e4e14e Mon Sep 17 00:00:00 2001 From: Jared Scheib Date: Wed, 16 Aug 2017 13:58:46 -0700 Subject: [PATCH 20/47] Update changelog --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6e2f48ee..8835a7867 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## v1.3.7.0 [unreleased] +### Bug Fixes +1. [#1795](https://github.com/influxdata/chronograf/pull/1795): Fix uptime status on Windows hosts running Telegraf +1. [#1715](https://github.com/influxdata/chronograf/pull/1715): Chronograf now renders on IE11. +1. [#1870](https://github.com/influxdata/chronograf/pull/1870): Fix console error for placing prop on div +1. [#1864](https://github.com/influxdata/chronograf/pull/1864): Fix Write Data form upload button and add `onDragExit` handler +1. [#1891](https://github.com/influxdata/chronograf/pull/1891): Fix Kapacitor config for PagerDuty via the UI + +### Features +1. [#1863](https://github.com/influxdata/chronograf/pull/1863): Improve 'new-sources' server flag example by adding 'type' key + +### UI Improvements +1. [#1862](https://github.com/influxdata/chronograf/pull/1862): Show "Add Graph" button on cells with no queries + ## v1.3.6.1 [2017-08-14] **Upgrade Note** This release (1.3.6.1) fixes a possibly data corruption issue with dashboard cells' graph types. If you upgraded to 1.3.6.0 and visited any dashboard, once you have then upgraded to this release (1.3.6.1) you will need to manually reset the graph type for every cell via the cell's caret --> Edit --> Display Options. If you upgraded directly to 1.3.6.1, you should not experience this issue. From 4188bc96767ddbbd08fb8211b30c3ffbeee1be7b Mon Sep 17 00:00:00 2001 From: Alex P Date: Thu, 17 Aug 2017 13:59:43 -0700 Subject: [PATCH 21/47] Remove obsolete changelog entry introduced in merge --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8835a7867..28b6cf787 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ 1. [#1870](https://github.com/influxdata/chronograf/pull/1870): Fix console error for placing prop on div 1. [#1864](https://github.com/influxdata/chronograf/pull/1864): Fix Write Data form upload button and add `onDragExit` handler 1. [#1891](https://github.com/influxdata/chronograf/pull/1891): Fix Kapacitor config for PagerDuty via the UI +1. [#1872](https://github.com/influxdata/chronograf/pull/1872): Prevent stats in the legend from wrapping line ### Features 1. [#1863](https://github.com/influxdata/chronograf/pull/1863): Improve 'new-sources' server flag example by adding 'type' key From b6b2fb0655d9bd5863a31bf003931ffd5c0ab203 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Sat, 19 Aug 2017 10:21:17 -0700 Subject: [PATCH 22/47] WIP Import dygraphs number axis formatter --- ui/src/dashboards/components/AxesOptions.js | 21 +++-- .../dashboards/components/DisplayOptions.js | 7 +- ui/src/shared/components/Dygraph.js | 3 + ui/src/utils/formatting.js | 83 +++++++++++++++++++ 4 files changed, 105 insertions(+), 9 deletions(-) diff --git a/ui/src/dashboards/components/AxesOptions.js b/ui/src/dashboards/components/AxesOptions.js index aea060b67..6cfc1cbed 100644 --- a/ui/src/dashboards/components/AxesOptions.js +++ b/ui/src/dashboards/components/AxesOptions.js @@ -3,17 +3,19 @@ import _ from 'lodash' import OptIn from 'shared/components/OptIn' -// TODO: add logic for for Prefix, Suffix, Scale, and Multiplier const AxesOptions = ({ + axes, + onSetLabel, + onSetPrefixSuffix, onSetYAxisBoundMin, onSetYAxisBoundMax, - onSetLabel, - axes, }) => { const min = _.get(axes, ['y', 'bounds', '0'], '') const max = _.get(axes, ['y', 'bounds', '1'], '') const label = _.get(axes, ['y', 'label'], '') const defaultYLabel = _.get(axes, ['y', 'defaultYLabel'], '') + const prefix = _.get(axes, ['y', 'prefix'], '') + const suffix = _.get(axes, ['y', 'suffix'], '') return (
@@ -46,22 +48,26 @@ const AxesOptions = ({ type="number" />
- {/*
- +
+
- +
@@ -77,7 +83,7 @@ const AxesOptions = ({
  • Linear
  • Logarithmic
  • -
    */} +
    ) @@ -86,6 +92,7 @@ const AxesOptions = ({ const {arrayOf, func, shape, string} = PropTypes AxesOptions.propTypes = { + onSetPrefixSuffix: func.isRequired, onSetYAxisBoundMin: func.isRequired, onSetYAxisBoundMax: func.isRequired, onSetLabel: func.isRequired, diff --git a/ui/src/dashboards/components/DisplayOptions.js b/ui/src/dashboards/components/DisplayOptions.js index de67cb3b5..6be6dca76 100644 --- a/ui/src/dashboards/components/DisplayOptions.js +++ b/ui/src/dashboards/components/DisplayOptions.js @@ -33,9 +33,10 @@ class DisplayOptions extends Component { render() { const { + onSetLabel, selectedGraphType, onSelectGraphType, - onSetLabel, + onSetPrefixSuffix, onSetYAxisBoundMin, onSetYAxisBoundMax, } = this.props @@ -44,10 +45,11 @@ class DisplayOptions extends Component { return (
    str @@ -115,6 +116,8 @@ export default class Dygraph extends Component { axes: { y: { valueRange: getRange(timeSeries, yAxis, ruleValues), + axisLabelFormatter: (yval, _, opts) => + numberValueFormatter(yval, opts), }, y2: { valueRange: getRange(timeSeries, y2Axis), diff --git a/ui/src/utils/formatting.js b/ui/src/utils/formatting.js index 652d90c95..23c632146 100644 --- a/ui/src/utils/formatting.js +++ b/ui/src/utils/formatting.js @@ -1,3 +1,86 @@ +var KMB_LABELS = ['K', 'M', 'B', 'T', 'Q'] +var KMG2_BIG_LABELS = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'] +var KMG2_SMALL_LABELS = ['m', 'u', 'n', 'p', 'f', 'a', 'z', 'y'] + +const pow = (base, exp) => { + if (exp < 0) { + return 1.0 / Math.pow(base, -exp) + } + + return Math.pow(base, exp) +} + +const round_ = (num, places) => { + var shift = Math.pow(10, places) + return Math.round(num * shift) / shift +} + +export const numberValueFormatter = (x, opts) => { + const sigFigs = opts('sigFigs') + + if (sigFigs !== null) { + // User has opted for a fixed number of significant figures. + return floatFormat(x, sigFigs) + } + + const digits = opts('digitsAfterDecimal') + const maxNumberWidth = opts('maxNumberWidth') + + const kmb = opts('labelsKMB') + const kmg2 = opts('labelsKMG2') + + let label + + // switch to scientific notation if we underflow or overflow fixed display. + if ( + x !== 0.0 && + (Math.abs(x) >= Math.pow(10, maxNumberWidth) || + Math.abs(x) < Math.pow(10, -digits)) + ) { + label = x.toExponential(digits) + } else { + label = '' + round_(x, digits) + } + + if (kmb || kmg2) { + let k + let k_labels = [] + let m_labels = [] + if (kmb) { + k = 1000 + k_labels = KMB_LABELS + } + if (kmg2) { + if (kmb) console.warn('Setting both labelsKMB and labelsKMG2. Pick one!') + k = 1024 + k_labels = KMG2_BIG_LABELS + m_labels = KMG2_SMALL_LABELS + } + + let absx = Math.abs(x) + let n = pow(k, k_labels.length) + for (var j = k_labels.length - 1; j >= 0; j--, n /= k) { + if (absx >= n) { + label = round_(x / n, digits) + k_labels[j] + break + } + } + if (kmg2) { + const x_parts = String(x.toExponential()).split('e-') + if (x_parts.length === 2 && x_parts[1] >= 3 && x_parts[1] <= 24) { + if (x_parts[1] % 3 > 0) { + label = round_(x_parts[0] / pow(10, x_parts[1] % 3), digits) + } else { + label = Number(x_parts[0]).toFixed(2) + } + label += m_labels[Math.floor(x_parts[1] / 3) - 1] + } + } + } + + return label +} + export const formatBytes = bytes => { if (bytes === 0) { return '0 Bytes' From edd9fa41df99a7d3798a57735f0ba8b0180311a5 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Mon, 21 Aug 2017 12:36:39 -0700 Subject: [PATCH 23/47] Fix linter errors --- ui/src/shared/components/Dygraph.js | 2 +- ui/src/utils/formatting.js | 70 ++++++++++++++++++++--------- 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/ui/src/shared/components/Dygraph.js b/ui/src/shared/components/Dygraph.js index ab030fc5c..78f0695e9 100644 --- a/ui/src/shared/components/Dygraph.js +++ b/ui/src/shared/components/Dygraph.js @@ -116,7 +116,7 @@ export default class Dygraph extends Component { axes: { y: { valueRange: getRange(timeSeries, yAxis, ruleValues), - axisLabelFormatter: (yval, _, opts) => + axisLabelFormatter: (yval, __, opts) => numberValueFormatter(yval, opts), }, y2: { diff --git a/ui/src/utils/formatting.js b/ui/src/utils/formatting.js index 23c632146..db1937941 100644 --- a/ui/src/utils/formatting.js +++ b/ui/src/utils/formatting.js @@ -1,6 +1,6 @@ -var KMB_LABELS = ['K', 'M', 'B', 'T', 'Q'] -var KMG2_BIG_LABELS = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'] -var KMG2_SMALL_LABELS = ['m', 'u', 'n', 'p', 'f', 'a', 'z', 'y'] +const KMB_LABELS = ['K', 'M', 'B', 'T', 'Q'] +const KMG2_BIG_LABELS = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'] +const KMG2_SMALL_LABELS = ['m', 'u', 'n', 'p', 'f', 'a', 'z', 'y'] const pow = (base, exp) => { if (exp < 0) { @@ -11,10 +11,36 @@ const pow = (base, exp) => { } const round_ = (num, places) => { - var shift = Math.pow(10, places) + const shift = Math.pow(10, places) return Math.round(num * shift) / shift } +const floatFormat = (x, optPrecision) => { + // Avoid invalid precision values; [1, 21] is the valid range. + const p = Math.min(Math.max(1, optPrecision || 2), 21) + + // This is deceptively simple. The actual algorithm comes from: + // + // Max allowed length = p + 4 + // where 4 comes from 'e+n' and '.'. + // + // Length of fixed format = 2 + y + p + // where 2 comes from '0.' and y = # of leading zeroes. + // + // Equating the two and solving for y yields y = 2, or 0.00xxxx which is + // 1.0e-3. + // + // Since the behavior of toPrecision() is identical for larger numbers, we + // don't have to worry about the other bound. + // + // Finally, the argument for toExponential() is the number of trailing digits, + // so we take off 1 for the value before the '.'. + return Math.abs(x) < 1.0e-3 && x !== 0.0 + ? x.toExponential(p - 1) + : x.toPrecision(p) +} + +// taken from https://github.com/danvk/dygraphs/blob/aaec6de56dba8ed712fd7b9d949de47b46a76ccd/src/dygraph-utils.js#L1103 export const numberValueFormatter = (x, opts) => { const sigFigs = opts('sigFigs') @@ -39,41 +65,43 @@ export const numberValueFormatter = (x, opts) => { ) { label = x.toExponential(digits) } else { - label = '' + round_(x, digits) + label = `${round_(x, digits)}` } if (kmb || kmg2) { let k - let k_labels = [] - let m_labels = [] + let kLabels = [] + let mLabels = [] if (kmb) { k = 1000 - k_labels = KMB_LABELS + kLabels = KMB_LABELS } if (kmg2) { - if (kmb) console.warn('Setting both labelsKMB and labelsKMG2. Pick one!') + if (kmb) { + console.error('Setting both labelsKMB and labelsKMG2. Pick one!') + } k = 1024 - k_labels = KMG2_BIG_LABELS - m_labels = KMG2_SMALL_LABELS + kLabels = KMG2_BIG_LABELS + mLabels = KMG2_SMALL_LABELS } - let absx = Math.abs(x) - let n = pow(k, k_labels.length) - for (var j = k_labels.length - 1; j >= 0; j--, n /= k) { + const absx = Math.abs(x) + let n = pow(k, kLabels.length) + for (let j = kLabels.length - 1; j >= 0; j -= 1, n /= k) { if (absx >= n) { - label = round_(x / n, digits) + k_labels[j] + label = round_(x / n, digits) + kLabels[j] break } } if (kmg2) { - const x_parts = String(x.toExponential()).split('e-') - if (x_parts.length === 2 && x_parts[1] >= 3 && x_parts[1] <= 24) { - if (x_parts[1] % 3 > 0) { - label = round_(x_parts[0] / pow(10, x_parts[1] % 3), digits) + const xParts = String(x.toExponential()).split('e-') + if (xParts.length === 2 && xParts[1] >= 3 && xParts[1] <= 24) { + if (xParts[1] % 3 > 0) { + label = round_(xParts[0] / pow(10, xParts[1] % 3), digits) } else { - label = Number(x_parts[0]).toFixed(2) + label = Number(xParts[0]).toFixed(2) } - label += m_labels[Math.floor(x_parts[1] / 3) - 1] + label += mLabels[Math.floor(xParts[1] / 3) - 1] } } } From 25bcb1c37240cd83be2459c2313451cdc7ceb000 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Mon, 21 Aug 2017 22:13:49 -0700 Subject: [PATCH 24/47] WIP Allow user to set prefix and suffix in y-axis --- ui/src/shared/components/Dygraph.js | 95 ++++++++++++++++------------- ui/src/utils/formatting.js | 4 +- 2 files changed, 53 insertions(+), 46 deletions(-) diff --git a/ui/src/shared/components/Dygraph.js b/ui/src/shared/components/Dygraph.js index 78f0695e9..4a8270134 100644 --- a/ui/src/shared/components/Dygraph.js +++ b/ui/src/shared/components/Dygraph.js @@ -36,37 +36,11 @@ export default class Dygraph extends Component { } } - static defaultProps = { - containerStyle: {}, - isGraphFilled: true, - overrideLineColors: null, - dygraphRef: () => {}, - } - - getTimeSeries() { - const {timeSeries} = this.props - // Avoid 'Can't plot empty data set' errors by falling back to a - // default dataset that's valid for Dygraph. - return timeSeries.length ? timeSeries : [[0]] - } - - getLabel(axis) { - const {axes, queries} = this.props - const label = _.get(axes, [axis, 'label'], '') - const queryConfig = _.get(queries, ['0', 'queryConfig'], false) - - if (label || !queryConfig) { - return label - } - - return buildDefaultYLabel(queryConfig) - } - componentDidMount() { const timeSeries = this.getTimeSeries() // dygraphSeries is a legend label and its corresponding y-axis e.g. {legendLabel1: 'y', legendLabel2: 'y2'}; const { - axes, + axes: {y, y2}, dygraphSeries, ruleValues, overrideLineColors, @@ -89,9 +63,6 @@ export default class Dygraph extends Component { hashColorDygraphSeries[seriesName] = {...series, color} } - const yAxis = _.get(axes, ['y', 'bounds'], [null, null]) - const y2Axis = _.get(axes, ['y2', 'bounds'], undefined) - const defaultOptions = { plugins: isBarGraph ? [] @@ -115,12 +86,14 @@ export default class Dygraph extends Component { series: hashColorDygraphSeries, axes: { y: { - valueRange: getRange(timeSeries, yAxis, ruleValues), - axisLabelFormatter: (yval, __, opts) => - numberValueFormatter(yval, opts), + valueRange: getRange(timeSeries, y.bounds, ruleValues), + axisLabelFormatter: (yval, __, opts, d) => { + return numberValueFormatter(yval, opts, y.prefix, y.suffix) + }, + axisLabelWidth: 60 + y.prefix.length * 7 + y.suffix.length * 7, }, y2: { - valueRange: getRange(timeSeries, y2Axis), + valueRange: getRange(timeSeries, y2.bounds), }, }, highlightSeriesOpts: { @@ -136,10 +109,10 @@ export default class Dygraph extends Component { const highlighted = legend.series.find(s => s.isHighlighted) const prevHighlighted = prevLegend.series.find(s => s.isHighlighted) - const y = highlighted && highlighted.y + const yVal = highlighted && highlighted.y const prevY = prevHighlighted && prevHighlighted.y - if (legend.x === prevLegend.x && y === prevY) { + if (legend.x === prevLegend.x && yVal === prevY) { return '' } @@ -234,6 +207,13 @@ export default class Dygraph extends Component { this.dygraph.resetZoom() } + if ( + this.props.axes.y.prefix !== nextProps.axes.y.prefix || + this.props.axes.y.suffix !== nextProps.axes.y.suffix + ) { + this.resize() + } + // Will cause componentDidUpdate to fire twice, currently. This could // be reduced by returning false from within the reset conditional above, // though that would be based on the assumption that props for timeRange @@ -241,10 +221,15 @@ export default class Dygraph extends Component { return shallowCompare(this, nextProps, nextState) } + resize() { + this.dygraph.resizeElements_() + this.dygraph.predraw_() + } + componentDidUpdate() { const { labels, - axes, + axes: {y, y2}, options, dygraphSeries, ruleValues, @@ -259,8 +244,6 @@ export default class Dygraph extends Component { ) } - const y = _.get(axes, ['y', 'bounds'], [null, null]) - const y2 = _.get(axes, ['y2', 'bounds'], undefined) const timeSeries = this.getTimeSeries() const ylabel = this.getLabel('y') const finalLineColors = [...(overrideLineColors || LINE_COLORS)] @@ -275,16 +258,21 @@ export default class Dygraph extends Component { hashColorDygraphSeries[seriesName] = {...series, color} } + const axisLabelWidth = 60 + y.prefix.length * 7 + y.suffix.length * 7 + const updateOptions = { labels, file: timeSeries, ylabel, axes: { y: { - valueRange: getRange(timeSeries, y, ruleValues), + valueRange: getRange(timeSeries, y.bounds, ruleValues), + axisLabelFormatter: (yval, __, opts) => + numberValueFormatter(yval, opts, y.prefix, y.suffix), + axisLabelWidth, }, y2: { - valueRange: getRange(timeSeries, y2), + valueRange: getRange(timeSeries, y2.bounds), }, }, stepPlot: options.stepPlot, @@ -297,7 +285,7 @@ export default class Dygraph extends Component { } dygraph.updateOptions(updateOptions) - dygraph.resize() + const {w} = this.dygraph.getArea() this.props.setResolution(w) } @@ -408,16 +396,16 @@ export default class Dygraph extends Component { onSnip={this.handleSnipLabel} onSort={this.handleSortLegend} legendRef={this.handleLegendRef} - onInputChange={this.handleLegendInputChange} onToggleFilter={this.handleToggleFilter} + onInputChange={this.handleLegendInputChange} />
    { this.graphRef = r this.props.dygraphRef(r) }} - style={this.props.containerStyle} className="dygraph-child-container" + style={this.props.containerStyle} />
    ) @@ -426,6 +414,25 @@ export default class Dygraph extends Component { const {array, arrayOf, bool, func, shape, string} = PropTypes +Dygraph.defaultProps = { + axes: { + y: { + bounds: [null, null], + prefix: '', + suffix: '', + }, + y2: { + bounds: null, + prefix: '', + suffix: '', + }, + }, + containerStyle: {}, + isGraphFilled: true, + overrideLineColors: null, + dygraphRef: () => {}, +} + Dygraph.propTypes = { axes: shape({ y: shape({ diff --git a/ui/src/utils/formatting.js b/ui/src/utils/formatting.js index db1937941..49f8fd72f 100644 --- a/ui/src/utils/formatting.js +++ b/ui/src/utils/formatting.js @@ -41,7 +41,7 @@ const floatFormat = (x, optPrecision) => { } // taken from https://github.com/danvk/dygraphs/blob/aaec6de56dba8ed712fd7b9d949de47b46a76ccd/src/dygraph-utils.js#L1103 -export const numberValueFormatter = (x, opts) => { +export const numberValueFormatter = (x, opts, prefix, suffix) => { const sigFigs = opts('sigFigs') if (sigFigs !== null) { @@ -106,7 +106,7 @@ export const numberValueFormatter = (x, opts) => { } } - return label + return `${prefix}${label}${suffix}` } export const formatBytes = bytes => { From 6eb828b4db60efdedfcb6b4e8fd01b0c8850f082 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Tue, 22 Aug 2017 09:56:21 -0700 Subject: [PATCH 25/47] Cleanup --- ui/src/shared/components/Dygraph.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/ui/src/shared/components/Dygraph.js b/ui/src/shared/components/Dygraph.js index 4a8270134..14abab7a0 100644 --- a/ui/src/shared/components/Dygraph.js +++ b/ui/src/shared/components/Dygraph.js @@ -87,9 +87,8 @@ export default class Dygraph extends Component { axes: { y: { valueRange: getRange(timeSeries, y.bounds, ruleValues), - axisLabelFormatter: (yval, __, opts, d) => { - return numberValueFormatter(yval, opts, y.prefix, y.suffix) - }, + axisLabelFormatter: (yval, __, opts) => + numberValueFormatter(yval, opts, y.prefix, y.suffix), axisLabelWidth: 60 + y.prefix.length * 7 + y.suffix.length * 7, }, y2: { @@ -207,13 +206,6 @@ export default class Dygraph extends Component { this.dygraph.resetZoom() } - if ( - this.props.axes.y.prefix !== nextProps.axes.y.prefix || - this.props.axes.y.suffix !== nextProps.axes.y.suffix - ) { - this.resize() - } - // Will cause componentDidUpdate to fire twice, currently. This could // be reduced by returning false from within the reset conditional above, // though that would be based on the assumption that props for timeRange From 430bc4ee554eb9be81f1d9d2586b7c5af5fd3598 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Tue, 22 Aug 2017 09:56:43 -0700 Subject: [PATCH 26/47] Actually resize Dygraph on component update --- ui/src/shared/components/Dygraph.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ui/src/shared/components/Dygraph.js b/ui/src/shared/components/Dygraph.js index 14abab7a0..620ca054b 100644 --- a/ui/src/shared/components/Dygraph.js +++ b/ui/src/shared/components/Dygraph.js @@ -213,11 +213,6 @@ export default class Dygraph extends Component { return shallowCompare(this, nextProps, nextState) } - resize() { - this.dygraph.resizeElements_() - this.dygraph.predraw_() - } - componentDidUpdate() { const { labels, @@ -279,6 +274,7 @@ export default class Dygraph extends Component { dygraph.updateOptions(updateOptions) const {w} = this.dygraph.getArea() + this.resize() this.props.setResolution(w) } @@ -363,6 +359,11 @@ export default class Dygraph extends Component { handleLegendRef = el => (this.legendRef = el) + resize = () => { + this.dygraph.resizeElements_() + this.dygraph.predraw_() + } + render() { const { legend, From 128750093148e6b06fd06f9fcf7d3b479309badd Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Tue, 22 Aug 2017 10:03:06 -0700 Subject: [PATCH 27/47] Fix incorrect positioning of labels on initial render --- ui/src/shared/components/LineGraph.js | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/ui/src/shared/components/LineGraph.js b/ui/src/shared/components/LineGraph.js index 3bcd69115..26a2ab732 100644 --- a/ui/src/shared/components/LineGraph.js +++ b/ui/src/shared/components/LineGraph.js @@ -159,12 +159,11 @@ export default React.createClass({ : overrideLineColors return ( -
    +
    {isRefreshing ? this.renderSpinner() : null} From e04c7191a07376e129563b726b07df45c160e107 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Tue, 22 Aug 2017 10:47:44 -0700 Subject: [PATCH 28/47] Fix incorrect empty y2 bound --- ui/src/shared/components/Dygraph.js | 2 +- ui/src/shared/parsing/getRangeForDygraph.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/shared/components/Dygraph.js b/ui/src/shared/components/Dygraph.js index 620ca054b..628e0023d 100644 --- a/ui/src/shared/components/Dygraph.js +++ b/ui/src/shared/components/Dygraph.js @@ -415,7 +415,7 @@ Dygraph.defaultProps = { suffix: '', }, y2: { - bounds: null, + bounds: undefined, prefix: '', suffix: '', }, diff --git a/ui/src/shared/parsing/getRangeForDygraph.js b/ui/src/shared/parsing/getRangeForDygraph.js index 7a19fa439..94914682f 100644 --- a/ui/src/shared/parsing/getRangeForDygraph.js +++ b/ui/src/shared/parsing/getRangeForDygraph.js @@ -15,7 +15,7 @@ const considerEmpty = (userNumber, number) => { const getRange = ( timeSeries, userSelectedRange = [null, null], - ruleValues = {value: null, rangeValue: null} + ruleValues = {value: null, rangeValue: null, operator: ''} ) => { const {value, rangeValue, operator} = ruleValues const [userMin, userMax] = userSelectedRange From 80e383a1524e182aaffc4def03911a46eb3ef6f6 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Tue, 22 Aug 2017 11:04:18 -0700 Subject: [PATCH 29/47] Allow set base state on cell --- ui/src/dashboards/components/AxesOptions.js | 17 +++++++++++++++-- ui/src/dashboards/components/DisplayOptions.js | 3 +++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/ui/src/dashboards/components/AxesOptions.js b/ui/src/dashboards/components/AxesOptions.js index 6cfc1cbed..38618bf82 100644 --- a/ui/src/dashboards/components/AxesOptions.js +++ b/ui/src/dashboards/components/AxesOptions.js @@ -5,6 +5,7 @@ import OptIn from 'shared/components/OptIn' const AxesOptions = ({ axes, + onSetBase, onSetLabel, onSetPrefixSuffix, onSetYAxisBoundMin, @@ -16,6 +17,7 @@ const AxesOptions = ({ const defaultYLabel = _.get(axes, ['y', 'defaultYLabel'], '') const prefix = _.get(axes, ['y', 'prefix'], '') const suffix = _.get(axes, ['y', 'suffix'], '') + const base = _.get(axes, ['y', 'base'], '10') return (
    @@ -73,8 +75,18 @@ const AxesOptions = ({
      -
    • K/M/B
    • -
    • K/M/G
    • +
    • + K/M/B +
    • +
    • + K/M/G +
    @@ -96,6 +108,7 @@ AxesOptions.propTypes = { onSetYAxisBoundMin: func.isRequired, onSetYAxisBoundMax: func.isRequired, onSetLabel: func.isRequired, + onSetBase: func.isRequired, axes: shape({ y: shape({ bounds: arrayOf(string), diff --git a/ui/src/dashboards/components/DisplayOptions.js b/ui/src/dashboards/components/DisplayOptions.js index 6be6dca76..b00865c89 100644 --- a/ui/src/dashboards/components/DisplayOptions.js +++ b/ui/src/dashboards/components/DisplayOptions.js @@ -33,6 +33,7 @@ class DisplayOptions extends Component { render() { const { + onSetBase, onSetLabel, selectedGraphType, onSelectGraphType, @@ -46,6 +47,7 @@ class DisplayOptions extends Component {
    Date: Tue, 22 Aug 2017 11:15:00 -0700 Subject: [PATCH 30/47] Update dygraph based on user selected base --- ui/src/shared/components/Dygraph.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ui/src/shared/components/Dygraph.js b/ui/src/shared/components/Dygraph.js index 628e0023d..866ff1f1b 100644 --- a/ui/src/shared/components/Dygraph.js +++ b/ui/src/shared/components/Dygraph.js @@ -90,6 +90,8 @@ export default class Dygraph extends Component { axisLabelFormatter: (yval, __, opts) => numberValueFormatter(yval, opts, y.prefix, y.suffix), axisLabelWidth: 60 + y.prefix.length * 7 + y.suffix.length * 7, + labelsKMB: y.base === '10', + labelsKMG2: y.base === '2', }, y2: { valueRange: getRange(timeSeries, y2.bounds), @@ -257,6 +259,8 @@ export default class Dygraph extends Component { axisLabelFormatter: (yval, __, opts) => numberValueFormatter(yval, opts, y.prefix, y.suffix), axisLabelWidth, + labelsKMB: y.base === '10', + labelsKMG2: y.base === '2', }, y2: { valueRange: getRange(timeSeries, y2.bounds), @@ -413,6 +417,7 @@ Dygraph.defaultProps = { bounds: [null, null], prefix: '', suffix: '', + base: '10', }, y2: { bounds: undefined, From 5e46f7150a69e5a6fd5b0c4003475e2d882eda2b Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Tue, 22 Aug 2017 13:05:24 -0700 Subject: [PATCH 31/47] Use defaultProps instead of _.get() --- ui/src/dashboards/components/AxesOptions.js | 24 +++++++++++++-------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/ui/src/dashboards/components/AxesOptions.js b/ui/src/dashboards/components/AxesOptions.js index 38618bf82..a23221226 100644 --- a/ui/src/dashboards/components/AxesOptions.js +++ b/ui/src/dashboards/components/AxesOptions.js @@ -1,23 +1,16 @@ import React, {PropTypes} from 'react' -import _ from 'lodash' import OptIn from 'shared/components/OptIn' const AxesOptions = ({ - axes, + axes: {y: {bounds, label, prefix, suffix, base, defaultYLabel}}, onSetBase, onSetLabel, onSetPrefixSuffix, onSetYAxisBoundMin, onSetYAxisBoundMax, }) => { - const min = _.get(axes, ['y', 'bounds', '0'], '') - const max = _.get(axes, ['y', 'bounds', '1'], '') - const label = _.get(axes, ['y', 'label'], '') - const defaultYLabel = _.get(axes, ['y', 'defaultYLabel'], '') - const prefix = _.get(axes, ['y', 'prefix'], '') - const suffix = _.get(axes, ['y', 'suffix'], '') - const base = _.get(axes, ['y', 'base'], '10') + const [min, max] = bounds return (
    @@ -103,6 +96,19 @@ const AxesOptions = ({ const {arrayOf, func, shape, string} = PropTypes +AxesOptions.defaultProps = { + axes: { + y: { + bounds: ['', ''], + prefix: '', + suffix: '', + base: '10', + scale: 'linear', + defaultYLabel: '', + }, + }, +} + AxesOptions.propTypes = { onSetPrefixSuffix: func.isRequired, onSetYAxisBoundMin: func.isRequired, From f2ef91053f043fe52c0b59b4f8b2f2a3d3c8bf77 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Tue, 22 Aug 2017 13:51:30 -0700 Subject: [PATCH 32/47] Make input SFC --- ui/src/dashboards/components/AxesOptions.js | 39 ++++++++----------- .../components/DisplayOptionsInput.js | 28 +++++++++++++ 2 files changed, 44 insertions(+), 23 deletions(-) create mode 100644 ui/src/data_explorer/components/DisplayOptionsInput.js diff --git a/ui/src/dashboards/components/AxesOptions.js b/ui/src/dashboards/components/AxesOptions.js index a23221226..c2fb4c813 100644 --- a/ui/src/dashboards/components/AxesOptions.js +++ b/ui/src/dashboards/components/AxesOptions.js @@ -1,6 +1,7 @@ import React, {PropTypes} from 'react' import OptIn from 'shared/components/OptIn' +import Input from 'src/data_explorer/components/DisplayOptionsInput' const AxesOptions = ({ axes: {y: {bounds, label, prefix, suffix, base, defaultYLabel}}, @@ -43,30 +44,22 @@ const AxesOptions = ({ type="number" />
    + +
    - - -
    -
    - - -
    -
    - +
    • +
      + + +
      + +const {func, string} = PropTypes + +DisplayOptionsInput.propTypes = { + name: string.isRequired, + id: string.isRequired, + value: string.isRequired, + onChange: func.isRequired, + labelText: string, +} + +export default DisplayOptionsInput From 72cba23a44b14b69dc4a3c3709a0029445bf860a Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Tue, 22 Aug 2017 15:11:29 -0700 Subject: [PATCH 33/47] Default scale to 'linear' --- bolt/internal/internal.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bolt/internal/internal.go b/bolt/internal/internal.go index c844665ec..ca6df1827 100644 --- a/bolt/internal/internal.go +++ b/bolt/internal/internal.go @@ -290,6 +290,10 @@ func UnmarshalDashboard(data []byte, d *chronograf.Dashboard) error { r.Base = "10" } + if r.Scale == "" { + r.Scale = "linear" + } + if r.Bounds != nil { axes[a] = chronograf.Axis{ Bounds: r.Bounds, @@ -304,6 +308,7 @@ func UnmarshalDashboard(data []byte, d *chronograf.Dashboard) error { axes[a] = chronograf.Axis{ Bounds: []string{}, Base: r.Base, + Scale: r.Scale, } } } From be4ca9fcdacc0153b4277ebc47a7764754bbcaa9 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Tue, 22 Aug 2017 15:12:47 -0700 Subject: [PATCH 34/47] Add ability to toggle between linear and logarithmic scale --- ui/src/dashboards/components/AxesOptions.js | 62 ++++++++++--------- .../dashboards/components/DisplayOptions.js | 3 + ui/src/dashboards/components/Tabber.js | 29 +++++++++ ui/src/dashboards/constants/index.js | 7 +++ ui/src/shared/components/Dygraph.js | 7 ++- 5 files changed, 79 insertions(+), 29 deletions(-) create mode 100644 ui/src/dashboards/components/Tabber.js diff --git a/ui/src/dashboards/components/AxesOptions.js b/ui/src/dashboards/components/AxesOptions.js index c2fb4c813..e39aafaf6 100644 --- a/ui/src/dashboards/components/AxesOptions.js +++ b/ui/src/dashboards/components/AxesOptions.js @@ -1,11 +1,16 @@ import React, {PropTypes} from 'react' import OptIn from 'shared/components/OptIn' -import Input from 'src/data_explorer/components/DisplayOptionsInput' +import Input from 'src/dashboards/components/DisplayOptionsInput' +import {Tabber, Tab} from 'src/dashboards/components/Tabber' +import {DISPLAY_OPTIONS} from 'src/dashboards/constants' + +const {LINEAR, LOG, BASE_2, BASE_10} = DISPLAY_OPTIONS const AxesOptions = ({ - axes: {y: {bounds, label, prefix, suffix, base, defaultYLabel}}, + axes: {y: {bounds, label, prefix, suffix, base, scale, defaultYLabel}}, onSetBase, + onSetScale, onSetLabel, onSetPrefixSuffix, onSetYAxisBoundMin, @@ -58,30 +63,30 @@ const AxesOptions = ({ labelText="Y-Value's Suffix" onChange={onSetPrefixSuffix} /> -
      - -
        -
      • - K/M/B -
      • -
      • - K/M/G -
      • -
      -
      -
      - -
        -
      • Linear
      • -
      • Logarithmic
      • -
      -
      + + + + + + + +
    ) @@ -95,8 +100,8 @@ AxesOptions.defaultProps = { bounds: ['', ''], prefix: '', suffix: '', - base: '10', - scale: 'linear', + base: BASE_10, + scale: LINEAR, defaultYLabel: '', }, }, @@ -107,6 +112,7 @@ AxesOptions.propTypes = { onSetYAxisBoundMin: func.isRequired, onSetYAxisBoundMax: func.isRequired, onSetLabel: func.isRequired, + onSetScale: func.isRequired, onSetBase: func.isRequired, axes: shape({ y: shape({ diff --git a/ui/src/dashboards/components/DisplayOptions.js b/ui/src/dashboards/components/DisplayOptions.js index b00865c89..b10a5885d 100644 --- a/ui/src/dashboards/components/DisplayOptions.js +++ b/ui/src/dashboards/components/DisplayOptions.js @@ -34,6 +34,7 @@ class DisplayOptions extends Component { render() { const { onSetBase, + onSetScale, onSetLabel, selectedGraphType, onSelectGraphType, @@ -49,6 +50,7 @@ class DisplayOptions extends Component { axes={axes} onSetBase={onSetBase} onSetLabel={onSetLabel} + onSetScale={onSetScale} onSetPrefixSuffix={onSetPrefixSuffix} onSetYAxisBoundMin={onSetYAxisBoundMin} onSetYAxisBoundMax={onSetYAxisBoundMax} @@ -69,6 +71,7 @@ DisplayOptions.propTypes = { onSetPrefixSuffix: func.isRequired, onSetYAxisBoundMin: func.isRequired, onSetYAxisBoundMax: func.isRequired, + onSetScale: func.isRequired, onSetLabel: func.isRequired, onSetBase: func.isRequired, axes: shape({}).isRequired, diff --git a/ui/src/dashboards/components/Tabber.js b/ui/src/dashboards/components/Tabber.js new file mode 100644 index 000000000..f995d68d5 --- /dev/null +++ b/ui/src/dashboards/components/Tabber.js @@ -0,0 +1,29 @@ +import React, {PropTypes} from 'react' + +export const Tabber = ({labelText, children}) => +
    + +
      + {children} +
    +
    + +export const Tab = ({isActive, onClickTab, text}) => +
  • + {text} +
  • + +const {bool, func, node, string} = PropTypes + +Tabber.propTypes = { + children: node.isRequired, + labelText: string, +} + +Tab.propTypes = { + onClickTab: func.isRequired, + isActive: bool.isRequired, + text: string.isRequired, +} diff --git a/ui/src/dashboards/constants/index.js b/ui/src/dashboards/constants/index.js index 109234758..5f4adbf51 100644 --- a/ui/src/dashboards/constants/index.js +++ b/ui/src/dashboards/constants/index.js @@ -94,3 +94,10 @@ export const removeUnselectedTemplateValues = templates => { return {...template, values: selectedValues} }) } + +export const DISPLAY_OPTIONS = { + LINEAR: 'linear', + LOG: 'log', + BASE_2: '2', + BASE_10: '10', +} diff --git a/ui/src/shared/components/Dygraph.js b/ui/src/shared/components/Dygraph.js index 866ff1f1b..0afa825e1 100644 --- a/ui/src/shared/components/Dygraph.js +++ b/ui/src/shared/components/Dygraph.js @@ -7,11 +7,13 @@ import _ from 'lodash' import Dygraphs from 'src/external/dygraph' import getRange from 'shared/parsing/getRangeForDygraph' +import {DISPLAY_OPTIONS} from 'src/dashboards/constants' import {LINE_COLORS, multiColumnBarPlotter} from 'src/shared/graphs/helpers' import DygraphLegend from 'src/shared/components/DygraphLegend' import {buildDefaultYLabel} from 'shared/presenters' import {numberValueFormatter} from 'src/utils/formatting' +const {LINEAR, LOG, BASE_10} = DISPLAY_OPTIONS const hasherino = (str, len) => str .split('') @@ -71,6 +73,7 @@ export default class Dygraph extends Component { direction: 'vertical', }), ], + logscale: y.scale === LOG, labelsSeparateLines: false, labelsKMB: true, rightGap: 0, @@ -253,6 +256,7 @@ export default class Dygraph extends Component { labels, file: timeSeries, ylabel, + logscale: y.scale === LOG, axes: { y: { valueRange: getRange(timeSeries, y.bounds, ruleValues), @@ -417,7 +421,8 @@ Dygraph.defaultProps = { bounds: [null, null], prefix: '', suffix: '', - base: '10', + base: BASE_10, + scale: LINEAR, }, y2: { bounds: undefined, From ba442c2556f0f644fd0f4f1ed44acdc7f738b520 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Tue, 22 Aug 2017 15:13:20 -0700 Subject: [PATCH 35/47] Move DisplayOptionsInput into /dashboard dir --- .../components/DisplayOptionsInput.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ui/src/{data_explorer => dashboards}/components/DisplayOptionsInput.js (100%) diff --git a/ui/src/data_explorer/components/DisplayOptionsInput.js b/ui/src/dashboards/components/DisplayOptionsInput.js similarity index 100% rename from ui/src/data_explorer/components/DisplayOptionsInput.js rename to ui/src/dashboards/components/DisplayOptionsInput.js From 87b9e0417ba13bc5d010120a18ef5d09c14cbb9f Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Wed, 23 Aug 2017 10:53:18 -0700 Subject: [PATCH 36/47] Remove magic numbers --- ui/src/shared/components/Dygraph.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ui/src/shared/components/Dygraph.js b/ui/src/shared/components/Dygraph.js index 0afa825e1..84895d102 100644 --- a/ui/src/shared/components/Dygraph.js +++ b/ui/src/shared/components/Dygraph.js @@ -14,6 +14,9 @@ import {buildDefaultYLabel} from 'shared/presenters' import {numberValueFormatter} from 'src/utils/formatting' const {LINEAR, LOG, BASE_10} = DISPLAY_OPTIONS +const labelWidth = 60 +const avgCharPixels = 7 + const hasherino = (str, len) => str .split('') @@ -65,6 +68,11 @@ export default class Dygraph extends Component { hashColorDygraphSeries[seriesName] = {...series, color} } + const axisLabelWidth = + labelWidth + + y.prefix.length * avgCharPixels + + y.suffix.length * avgCharPixels + const defaultOptions = { plugins: isBarGraph ? [] @@ -92,7 +100,7 @@ export default class Dygraph extends Component { valueRange: getRange(timeSeries, y.bounds, ruleValues), axisLabelFormatter: (yval, __, opts) => numberValueFormatter(yval, opts, y.prefix, y.suffix), - axisLabelWidth: 60 + y.prefix.length * 7 + y.suffix.length * 7, + axisLabelWidth, labelsKMB: y.base === '10', labelsKMG2: y.base === '2', }, @@ -250,7 +258,10 @@ export default class Dygraph extends Component { hashColorDygraphSeries[seriesName] = {...series, color} } - const axisLabelWidth = 60 + y.prefix.length * 7 + y.suffix.length * 7 + const axisLabelWidth = + labelWidth + + y.prefix.length * avgCharPixels + + y.suffix.length * avgCharPixels const updateOptions = { labels, From 39bf08acaf653f5258790d5263ff2415e049f8b1 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Wed, 23 Aug 2017 15:43:02 -0700 Subject: [PATCH 37/47] Add a tooltip to value format toggle --- ui/src/dashboards/components/AxesOptions.js | 8 ++++++-- ui/src/dashboards/components/Tabber.js | 8 +++++++- ui/src/dashboards/constants/index.js | 5 +++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/ui/src/dashboards/components/AxesOptions.js b/ui/src/dashboards/components/AxesOptions.js index e39aafaf6..dee8c10c8 100644 --- a/ui/src/dashboards/components/AxesOptions.js +++ b/ui/src/dashboards/components/AxesOptions.js @@ -3,7 +3,7 @@ import React, {PropTypes} from 'react' import OptIn from 'shared/components/OptIn' import Input from 'src/dashboards/components/DisplayOptionsInput' import {Tabber, Tab} from 'src/dashboards/components/Tabber' -import {DISPLAY_OPTIONS} from 'src/dashboards/constants' +import {DISPLAY_OPTIONS, TOOLTIP_CONTENT} from 'src/dashboards/constants' const {LINEAR, LOG, BASE_2, BASE_10} = DISPLAY_OPTIONS @@ -63,7 +63,11 @@ const AxesOptions = ({ labelText="Y-Value's Suffix" onChange={onSetPrefixSuffix} /> - + +export const Tabber = ({labelText, children, tipID, tipContent}) =>
      {children} @@ -20,6 +24,8 @@ const {bool, func, node, string} = PropTypes Tabber.propTypes = { children: node.isRequired, labelText: string, + tipID: string, + tipContent: string, } Tab.propTypes = { diff --git a/ui/src/dashboards/constants/index.js b/ui/src/dashboards/constants/index.js index 5f4adbf51..b458fd737 100644 --- a/ui/src/dashboards/constants/index.js +++ b/ui/src/dashboards/constants/index.js @@ -101,3 +101,8 @@ export const DISPLAY_OPTIONS = { BASE_2: '2', BASE_10: '10', } + +export const TOOLTIP_CONTENT = { + FORMAT: + '

      K/M/B = Thousand / Million / Billion

      K/M/G = Kilo / Mega / Giga

      ', +} From 21288e308fc4f4adb441f113dc7953bb60a92456 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Wed, 23 Aug 2017 15:43:23 -0700 Subject: [PATCH 38/47] Fix graphs not resizing properly in cells --- ui/src/shared/components/Dygraph.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/src/shared/components/Dygraph.js b/ui/src/shared/components/Dygraph.js index 84895d102..627641085 100644 --- a/ui/src/shared/components/Dygraph.js +++ b/ui/src/shared/components/Dygraph.js @@ -294,6 +294,7 @@ export default class Dygraph extends Component { const {w} = this.dygraph.getArea() this.resize() + this.dygraph.resize() this.props.setResolution(w) } From 2990014f024c071e11480723f7ce08fbdb9d4cf6 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Wed, 23 Aug 2017 21:13:19 -0700 Subject: [PATCH 39/47] Update CHANGELOG.md --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28b6cf787..468e66a4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,11 @@ -## v1.3.7.0 [unreleased] +## v1.3.8.0 [unreleased] +### Bug Fixes +### Features +1. [#1928](https://github.com/influxdata/chronograf/pull/1928): Add prefix, suffix, scale, and other y-axis formatting + +### UI Improvements + +## v1.3.7.0 ### Bug Fixes 1. [#1795](https://github.com/influxdata/chronograf/pull/1795): Fix uptime status on Windows hosts running Telegraf 1. [#1715](https://github.com/influxdata/chronograf/pull/1715): Chronograf now renders on IE11. From 1ab6e559654f1a6ca3c6dac58c158ca8087adb20 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Thu, 24 Aug 2017 09:22:57 -0700 Subject: [PATCH 40/47] Update tests for scale to default to linear --- bolt/internal/internal_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bolt/internal/internal_test.go b/bolt/internal/internal_test.go index c57bccd88..937a192d4 100644 --- a/bolt/internal/internal_test.go +++ b/bolt/internal/internal_test.go @@ -246,6 +246,7 @@ func Test_MarshalDashboard_WithLegacyBounds(t *testing.T) { "y": chronograf.Axis{ Bounds: []string{}, Base: "10", + Scale: "linear", }, }, Type: "line", @@ -320,6 +321,7 @@ func Test_MarshalDashboard_WithEmptyLegacyBounds(t *testing.T) { "y": chronograf.Axis{ Bounds: []string{}, Base: "10", + Scale: "linear", }, }, Type: "line", From 7cf47a12f2ad6c182ca96cbb59f76bd466728e15 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Thu, 24 Aug 2017 09:25:46 -0700 Subject: [PATCH 41/47] Remove dup script --- ui/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/package.json b/ui/package.json index c57d4a647..bb9909e6e 100644 --- a/ui/package.json +++ b/ui/package.json @@ -17,7 +17,6 @@ "test:integration": "nightwatch tests --skip", "test:lint": "yarn run lint; yarn run test", "test:dev": "concurrently \"yarn run lint -- --watch\" \"yarn run test -- --no-single-run --reporters=verbose\"", - "test:integration": "nightwatch tests --skip", "clean": "rm -rf build", "storybook": "node ./storybook.js", "prettier": "prettier --single-quote --trailing-comma es5 --bracket-spacing false --semi false --write \"{src,spec}/**/*.js\"; eslint src --fix" From 69cd695dff430893c1c9a3e1255f256440b72cca Mon Sep 17 00:00:00 2001 From: Tim Raymond Date: Thu, 24 Aug 2017 14:42:14 -0400 Subject: [PATCH 42/47] Update commenting on new axis options Existing comments were deemed unclear or inconsistent with convention. --- chronograf.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/chronograf.go b/chronograf.go index 5b77438de..af329eb8b 100644 --- a/chronograf.go +++ b/chronograf.go @@ -644,10 +644,10 @@ type Axis struct { Bounds []string `json:"bounds"` // bounds are an arbitrary list of client-defined strings that specify the viewport for a cell LegacyBounds [2]int64 `json:"-"` // legacy bounds are for testing a migration from an earlier version of axis Label string `json:"label"` // label is a description of this Axis - Prefix string `json:"prefix"` // specifies a prefix for axis values - Suffix string `json:"suffix"` // specifies a suffix for axis values - Base string `json:"base"` // defines the base for axis values - Scale string `json:"scale"` // the magnitude of the numbers for this axis + Prefix string `json:"prefix"` // Prefix represents a label prefix for formatting axis values + Suffix string `json:"suffix"` // Suffix represents a label suffix for formatting axis values + Base string `json:"base"` // Base represents the radix for formatting axis values + Scale string `json:"scale"` // Scale is the axis formatting scale. Supported: "log", "linear" } // DashboardCell holds visual and query information for a cell From 3b51cb8339d13aeca4b11c5d3788f62530e8554c Mon Sep 17 00:00:00 2001 From: Tim Raymond Date: Thu, 24 Aug 2017 14:50:12 -0400 Subject: [PATCH 43/47] Update Swagger for new axes options New options were introduced to control things like scale, base, etc. on axes and these were previously not documented. This adds documentation of the newly supported parameters by the API. --- server/swagger.json | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/server/swagger.json b/server/swagger.json index 8141f7142..d0a4f0de1 100644 --- a/server/swagger.json +++ b/server/swagger.json @@ -3720,13 +3720,13 @@ "type": "object", "properties": { "x": { - "$ref": "#/definitions/DashboardRange" + "$ref": "#/definitions/Axis" }, "y": { - "$ref": "#/definitions/DashboardRange" + "$ref": "#/definitions/Axis" }, "y2": { - "$ref": "#/definitions/DashboardRange" + "$ref": "#/definitions/Axis" } } }, @@ -3811,7 +3811,7 @@ } } }, - "DashboardRange": { + "Axis": { "type": "object", "description": "A description of a particular axis for a visualization", "properties": { @@ -3824,6 +3824,26 @@ "type": "integer", "format": "int64" } + }, + "label": { + "description": "label is a description of this Axis", + "type": "string" + }, + "prefix": { + "description": "Prefix represents a label prefix for formatting axis values.", + "type": "string" + }, + "suffix": { + "description": "Suffix represents a label suffix for formatting axis values.", + "type": "string" + }, + "base": { + "description": "Base represents the radix for formatting axis values.", + "type": "string" + }, + "scale": { + "description": "Scale is the axis formatting scale. Supported: \"log\", \"linear\"", + "type": "string" } } }, From e421bf83d4e51a97889d5719a309644688256b44 Mon Sep 17 00:00:00 2001 From: Tim Raymond Date: Thu, 24 Aug 2017 15:37:19 -0400 Subject: [PATCH 44/47] Add validation around Base and Scale The Base and Scale options on axes can only be one of two parameters. We weren't validating that this was the case. This patch ensures that Base can only ever be "10" or "2", and Scale must be either "linear" or "log". Associated test coverage was also added. --- server/cells.go | 21 +++++++++++-- server/cells_test.go | 72 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/server/cells.go b/server/cells.go index 29d78b000..2b2f15e2f 100644 --- a/server/cells.go +++ b/server/cells.go @@ -76,14 +76,31 @@ func ValidDashboardCellRequest(c *chronograf.DashboardCell) error { // HasCorrectAxes verifies that only permitted axes exist within a DashboardCell func HasCorrectAxes(c *chronograf.DashboardCell) error { - for axis, _ := range c.Axes { - switch axis { + for label, axis := range c.Axes { + switch label { case "x", "y", "y2": // no-op default: return chronograf.ErrInvalidAxis } + + // validate axis scale + switch axis.Scale { + case "linear", "", "log": + // no-op + default: + return chronograf.ErrInvalidAxis + } + + // validate axis base + switch axis.Base { + case "10", "2", "": + // no-op + default: + return chronograf.ErrInvalidAxis + } } + return nil } diff --git a/server/cells_test.go b/server/cells_test.go index c0ade6f5f..12b109679 100644 --- a/server/cells_test.go +++ b/server/cells_test.go @@ -55,6 +55,78 @@ func Test_Cells_CorrectAxis(t *testing.T) { }, true, }, + { + "linear scale value", + &chronograf.DashboardCell{ + Axes: map[string]chronograf.Axis{ + "x": chronograf.Axis{ + Scale: "linear", + Bounds: []string{"0", "100"}, + }, + }, + }, + false, + }, + { + "log scale value", + &chronograf.DashboardCell{ + Axes: map[string]chronograf.Axis{ + "x": chronograf.Axis{ + Scale: "log", + Bounds: []string{"0", "100"}, + }, + }, + }, + false, + }, + { + "invalid scale value", + &chronograf.DashboardCell{ + Axes: map[string]chronograf.Axis{ + "x": chronograf.Axis{ + Scale: "potatoes", + Bounds: []string{"0", "100"}, + }, + }, + }, + true, + }, + { + "base 10 axis", + &chronograf.DashboardCell{ + Axes: map[string]chronograf.Axis{ + "x": chronograf.Axis{ + Base: "10", + Bounds: []string{"0", "100"}, + }, + }, + }, + false, + }, + { + "base 2 axis", + &chronograf.DashboardCell{ + Axes: map[string]chronograf.Axis{ + "x": chronograf.Axis{ + Base: "2", + Bounds: []string{"0", "100"}, + }, + }, + }, + false, + }, + { + "invalid base", + &chronograf.DashboardCell{ + Axes: map[string]chronograf.Axis{ + "x": chronograf.Axis{ + Base: "all your base are belong to us", + Bounds: []string{"0", "100"}, + }, + }, + }, + true, + }, } for _, test := range axisTests { From d559acc0e086f51b5fd08d1354de1c94bff38c8a Mon Sep 17 00:00:00 2001 From: Tim Raymond Date: Thu, 24 Aug 2017 15:45:51 -0400 Subject: [PATCH 45/47] Refactor set membership validation The pattern of using a select with a list of options and a default that returns an error isn't bad for a one-off validation: select myProp { case "validOption1", "validOption2": // no-op default: panic("invalid!") } However, we're doing this multiple times in this method, so it makes sense to pull this out into a new method to make it clearer what's happening. This adds a `oneOf` function that takes some property and a variadic list of valid options and reports whether or not that property is among that list. --- server/cells.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/server/cells.go b/server/cells.go index 2b2f15e2f..2d01b406c 100644 --- a/server/cells.go +++ b/server/cells.go @@ -77,26 +77,15 @@ func ValidDashboardCellRequest(c *chronograf.DashboardCell) error { // HasCorrectAxes verifies that only permitted axes exist within a DashboardCell func HasCorrectAxes(c *chronograf.DashboardCell) error { for label, axis := range c.Axes { - switch label { - case "x", "y", "y2": - // no-op - default: + if !oneOf(label, "x", "y", "y2") { return chronograf.ErrInvalidAxis } - // validate axis scale - switch axis.Scale { - case "linear", "", "log": - // no-op - default: + if !oneOf(axis.Scale, "linear", "log", "") { return chronograf.ErrInvalidAxis } - // validate axis base - switch axis.Base { - case "10", "2", "": - // no-op - default: + if !oneOf(axis.Base, "10", "2", "") { return chronograf.ErrInvalidAxis } } @@ -104,6 +93,17 @@ func HasCorrectAxes(c *chronograf.DashboardCell) error { return nil } +// oneOf reports whether a provided string is a member of a variadic list of +// valid options +func oneOf(prop string, validOpts ...string) bool { + for _, valid := range validOpts { + if prop == valid { + return true + } + } + return false +} + // CorrectWidthHeight changes the cell to have at least the // minimum width and height func CorrectWidthHeight(c *chronograf.DashboardCell) { From cfd8bac7b814774f10081a4dc290133dffcd8d20 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Thu, 24 Aug 2017 12:53:11 -0700 Subject: [PATCH 46/47] Fix spelling --- ui/src/dashboards/components/AxesOptions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/dashboards/components/AxesOptions.js b/ui/src/dashboards/components/AxesOptions.js index dee8c10c8..bcdd746e1 100644 --- a/ui/src/dashboards/components/AxesOptions.js +++ b/ui/src/dashboards/components/AxesOptions.js @@ -86,7 +86,7 @@ const AxesOptions = ({ onClickTab={onSetScale(LINEAR)} /> From 2c72a7b68b26c4da7995f68666889c9f88130385 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Thu, 24 Aug 2017 12:59:39 -0700 Subject: [PATCH 47/47] Add default value prop --- ui/src/dashboards/components/DisplayOptionsInput.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/src/dashboards/components/DisplayOptionsInput.js b/ui/src/dashboards/components/DisplayOptionsInput.js index c52be9ffa..f0f5a61b4 100644 --- a/ui/src/dashboards/components/DisplayOptionsInput.js +++ b/ui/src/dashboards/components/DisplayOptionsInput.js @@ -17,6 +17,10 @@ const DisplayOptionsInput = ({id, name, value, onChange, labelText}) => const {func, string} = PropTypes +DisplayOptionsInput.defaultProps = { + value: '', +} + DisplayOptionsInput.propTypes = { name: string.isRequired, id: string.isRequired,