Merge pull request #808 from influxdata/feature/614-dashboard-view

Feature/614 dashboard view
pull/10616/head
Jade McGough 2017-01-27 15:49:14 -08:00 committed by GitHub
commit f6fe95827d
11 changed files with 291 additions and 114 deletions

View File

@ -194,6 +194,22 @@ func UnmarshalLayout(data []byte, l *chronograf.Layout) error {
func MarshalDashboard(d chronograf.Dashboard) ([]byte, error) {
cells := make([]*DashboardCell, len(d.Cells))
for i, c := range d.Cells {
queries := make([]*Query, len(c.Queries))
for j, q := range c.Queries {
r := new(Range)
if q.Range != nil {
r.Upper, r.Lower = q.Range.Upper, q.Range.Lower
}
queries[j] = &Query{
Command: q.Command,
DB: q.DB,
RP: q.RP,
GroupBys: q.GroupBys,
Wheres: q.Wheres,
Label: q.Label,
Range: r,
}
}
cells[i] = &DashboardCell{
X: c.X,
@ -201,7 +217,7 @@ func MarshalDashboard(d chronograf.Dashboard) ([]byte, error) {
W: c.W,
H: c.H,
Name: c.Name,
Queries: c.Queries,
Queries: queries,
Type: c.Type,
}
}
@ -220,23 +236,39 @@ func UnmarshalDashboard(data []byte, d *chronograf.Dashboard) error {
return err
}
cells := make([]chronograf.DashboardCell, len(d.Cells))
for i, c := range d.Cells {
cells := make([]chronograf.DashboardCell, len(pb.Cells))
for i, c := range pb.Cells {
queries := make([]chronograf.Query, len(c.Queries))
for j, q := range c.Queries {
queries[j] = chronograf.Query{
Command: q.Command,
DB: q.DB,
RP: q.RP,
GroupBys: q.GroupBys,
Wheres: q.Wheres,
Label: q.Label,
}
if q.Range.Upper != q.Range.Lower {
queries[j].Range = &chronograf.Range{
Upper: q.Range.Upper,
Lower: q.Range.Lower,
}
}
}
cells[i] = chronograf.DashboardCell{
X: c.X,
Y: c.Y,
W: c.W,
H: c.H,
Name: c.Name,
Queries: c.Queries,
Queries: queries,
Type: c.Type,
}
}
d.ID = chronograf.DashboardID(pb.ID)
d.Cells = cells
d.Name = pb.Name
return nil
}

View File

@ -39,13 +39,13 @@ var _ = math.Inf
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
type Exploration struct {
ID int64 `protobuf:"varint,1,opt,name=ID,json=iD,proto3" json:"ID,omitempty"`
Name string `protobuf:"bytes,2,opt,name=Name,json=name,proto3" json:"Name,omitempty"`
UserID int64 `protobuf:"varint,3,opt,name=UserID,json=userID,proto3" json:"UserID,omitempty"`
Data string `protobuf:"bytes,4,opt,name=Data,json=data,proto3" json:"Data,omitempty"`
CreatedAt int64 `protobuf:"varint,5,opt,name=CreatedAt,json=createdAt,proto3" json:"CreatedAt,omitempty"`
UpdatedAt int64 `protobuf:"varint,6,opt,name=UpdatedAt,json=updatedAt,proto3" json:"UpdatedAt,omitempty"`
Default bool `protobuf:"varint,7,opt,name=Default,json=default,proto3" json:"Default,omitempty"`
ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"`
UserID int64 `protobuf:"varint,3,opt,name=UserID,proto3" json:"UserID,omitempty"`
Data string `protobuf:"bytes,4,opt,name=Data,proto3" json:"Data,omitempty"`
CreatedAt int64 `protobuf:"varint,5,opt,name=CreatedAt,proto3" json:"CreatedAt,omitempty"`
UpdatedAt int64 `protobuf:"varint,6,opt,name=UpdatedAt,proto3" json:"UpdatedAt,omitempty"`
Default bool `protobuf:"varint,7,opt,name=Default,proto3" json:"Default,omitempty"`
}
func (m *Exploration) Reset() { *m = Exploration{} }
@ -54,15 +54,15 @@ func (*Exploration) ProtoMessage() {}
func (*Exploration) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{0} }
type Source struct {
ID int64 `protobuf:"varint,1,opt,name=ID,json=iD,proto3" json:"ID,omitempty"`
Name string `protobuf:"bytes,2,opt,name=Name,json=name,proto3" json:"Name,omitempty"`
Type string `protobuf:"bytes,3,opt,name=Type,json=type,proto3" json:"Type,omitempty"`
Username string `protobuf:"bytes,4,opt,name=Username,json=username,proto3" json:"Username,omitempty"`
Password string `protobuf:"bytes,5,opt,name=Password,json=password,proto3" json:"Password,omitempty"`
URL string `protobuf:"bytes,6,opt,name=URL,json=uRL,proto3" json:"URL,omitempty"`
Default bool `protobuf:"varint,7,opt,name=Default,json=default,proto3" json:"Default,omitempty"`
Telegraf string `protobuf:"bytes,8,opt,name=Telegraf,json=telegraf,proto3" json:"Telegraf,omitempty"`
InsecureSkipVerify bool `protobuf:"varint,9,opt,name=InsecureSkipVerify,json=insecureSkipVerify,proto3" json:"InsecureSkipVerify,omitempty"`
ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"`
Type string `protobuf:"bytes,3,opt,name=Type,proto3" json:"Type,omitempty"`
Username string `protobuf:"bytes,4,opt,name=Username,proto3" json:"Username,omitempty"`
Password string `protobuf:"bytes,5,opt,name=Password,proto3" json:"Password,omitempty"`
URL string `protobuf:"bytes,6,opt,name=URL,proto3" json:"URL,omitempty"`
Default bool `protobuf:"varint,7,opt,name=Default,proto3" json:"Default,omitempty"`
Telegraf string `protobuf:"bytes,8,opt,name=Telegraf,proto3" json:"Telegraf,omitempty"`
InsecureSkipVerify bool `protobuf:"varint,9,opt,name=InsecureSkipVerify,proto3" json:"InsecureSkipVerify,omitempty"`
}
func (m *Source) Reset() { *m = Source{} }
@ -71,8 +71,8 @@ func (*Source) ProtoMessage() {}
func (*Source) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{1} }
type Dashboard struct {
ID int64 `protobuf:"varint,1,opt,name=ID,json=iD,proto3" json:"ID,omitempty"`
Name string `protobuf:"bytes,2,opt,name=Name,json=name,proto3" json:"Name,omitempty"`
ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"`
Cells []*DashboardCell `protobuf:"bytes,3,rep,name=cells" json:"cells,omitempty"`
}
@ -93,7 +93,7 @@ type DashboardCell struct {
Y int32 `protobuf:"varint,2,opt,name=y,proto3" json:"y,omitempty"`
W int32 `protobuf:"varint,3,opt,name=w,proto3" json:"w,omitempty"`
H int32 `protobuf:"varint,4,opt,name=h,proto3" json:"h,omitempty"`
Queries []string `protobuf:"bytes,5,rep,name=queries" json:"queries,omitempty"`
Queries []*Query `protobuf:"bytes,5,rep,name=queries" json:"queries,omitempty"`
Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"`
Type string `protobuf:"bytes,7,opt,name=type,proto3" json:"type,omitempty"`
}
@ -103,13 +103,20 @@ func (m *DashboardCell) String() string { return proto.CompactTextStr
func (*DashboardCell) ProtoMessage() {}
func (*DashboardCell) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{3} }
func (m *DashboardCell) GetQueries() []*Query {
if m != nil {
return m.Queries
}
return nil
}
type Server struct {
ID int64 `protobuf:"varint,1,opt,name=ID,json=iD,proto3" json:"ID,omitempty"`
Name string `protobuf:"bytes,2,opt,name=Name,json=name,proto3" json:"Name,omitempty"`
Username string `protobuf:"bytes,3,opt,name=Username,json=username,proto3" json:"Username,omitempty"`
Password string `protobuf:"bytes,4,opt,name=Password,json=password,proto3" json:"Password,omitempty"`
URL string `protobuf:"bytes,5,opt,name=URL,json=uRL,proto3" json:"URL,omitempty"`
SrcID int64 `protobuf:"varint,6,opt,name=SrcID,json=srcID,proto3" json:"SrcID,omitempty"`
ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"`
Username string `protobuf:"bytes,3,opt,name=Username,proto3" json:"Username,omitempty"`
Password string `protobuf:"bytes,4,opt,name=Password,proto3" json:"Password,omitempty"`
URL string `protobuf:"bytes,5,opt,name=URL,proto3" json:"URL,omitempty"`
SrcID int64 `protobuf:"varint,6,opt,name=SrcID,proto3" json:"SrcID,omitempty"`
}
func (m *Server) Reset() { *m = Server{} }
@ -118,11 +125,11 @@ func (*Server) ProtoMessage() {}
func (*Server) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{4} }
type Layout struct {
ID string `protobuf:"bytes,1,opt,name=ID,json=iD,proto3" json:"ID,omitempty"`
Application string `protobuf:"bytes,2,opt,name=Application,json=application,proto3" json:"Application,omitempty"`
Measurement string `protobuf:"bytes,3,opt,name=Measurement,json=measurement,proto3" json:"Measurement,omitempty"`
Cells []*Cell `protobuf:"bytes,4,rep,name=Cells,json=cells" json:"Cells,omitempty"`
Autoflow bool `protobuf:"varint,5,opt,name=Autoflow,json=autoflow,proto3" json:"Autoflow,omitempty"`
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
Application string `protobuf:"bytes,2,opt,name=Application,proto3" json:"Application,omitempty"`
Measurement string `protobuf:"bytes,3,opt,name=Measurement,proto3" json:"Measurement,omitempty"`
Cells []*Cell `protobuf:"bytes,4,rep,name=Cells" json:"Cells,omitempty"`
Autoflow bool `protobuf:"varint,5,opt,name=Autoflow,proto3" json:"Autoflow,omitempty"`
}
func (m *Layout) Reset() { *m = Layout{} }
@ -163,13 +170,13 @@ func (m *Cell) GetQueries() []*Query {
}
type Query struct {
Command string `protobuf:"bytes,1,opt,name=Command,json=command,proto3" json:"Command,omitempty"`
DB string `protobuf:"bytes,2,opt,name=DB,json=dB,proto3" json:"DB,omitempty"`
RP string `protobuf:"bytes,3,opt,name=RP,json=rP,proto3" json:"RP,omitempty"`
GroupBys []string `protobuf:"bytes,4,rep,name=GroupBys,json=groupBys" json:"GroupBys,omitempty"`
Wheres []string `protobuf:"bytes,5,rep,name=Wheres,json=wheres" json:"Wheres,omitempty"`
Label string `protobuf:"bytes,6,opt,name=Label,json=label,proto3" json:"Label,omitempty"`
Range *Range `protobuf:"bytes,7,opt,name=Range,json=range" json:"Range,omitempty"`
Command string `protobuf:"bytes,1,opt,name=Command,proto3" json:"Command,omitempty"`
DB string `protobuf:"bytes,2,opt,name=DB,proto3" json:"DB,omitempty"`
RP string `protobuf:"bytes,3,opt,name=RP,proto3" json:"RP,omitempty"`
GroupBys []string `protobuf:"bytes,4,rep,name=GroupBys" json:"GroupBys,omitempty"`
Wheres []string `protobuf:"bytes,5,rep,name=Wheres" json:"Wheres,omitempty"`
Label string `protobuf:"bytes,6,opt,name=Label,proto3" json:"Label,omitempty"`
Range *Range `protobuf:"bytes,7,opt,name=Range" json:"Range,omitempty"`
}
func (m *Query) Reset() { *m = Query{} }
@ -185,8 +192,8 @@ func (m *Query) GetRange() *Range {
}
type Range struct {
Upper int64 `protobuf:"varint,1,opt,name=Upper,json=upper,proto3" json:"Upper,omitempty"`
Lower int64 `protobuf:"varint,2,opt,name=Lower,json=lower,proto3" json:"Lower,omitempty"`
Upper int64 `protobuf:"varint,1,opt,name=Upper,proto3" json:"Upper,omitempty"`
Lower int64 `protobuf:"varint,2,opt,name=Lower,proto3" json:"Lower,omitempty"`
}
func (m *Range) Reset() { *m = Range{} }
@ -195,10 +202,10 @@ func (*Range) ProtoMessage() {}
func (*Range) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{8} }
type AlertRule struct {
ID string `protobuf:"bytes,1,opt,name=ID,json=iD,proto3" json:"ID,omitempty"`
JSON string `protobuf:"bytes,2,opt,name=JSON,json=jSON,proto3" json:"JSON,omitempty"`
SrcID int64 `protobuf:"varint,3,opt,name=SrcID,json=srcID,proto3" json:"SrcID,omitempty"`
KapaID int64 `protobuf:"varint,4,opt,name=KapaID,json=kapaID,proto3" json:"KapaID,omitempty"`
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
JSON string `protobuf:"bytes,2,opt,name=JSON,proto3" json:"JSON,omitempty"`
SrcID int64 `protobuf:"varint,3,opt,name=SrcID,proto3" json:"SrcID,omitempty"`
KapaID int64 `protobuf:"varint,4,opt,name=KapaID,proto3" json:"KapaID,omitempty"`
}
func (m *AlertRule) Reset() { *m = AlertRule{} }
@ -207,8 +214,8 @@ func (*AlertRule) ProtoMessage() {}
func (*AlertRule) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{9} }
type User struct {
ID uint64 `protobuf:"varint,1,opt,name=ID,json=iD,proto3" json:"ID,omitempty"`
Email string `protobuf:"bytes,2,opt,name=Email,json=email,proto3" json:"Email,omitempty"`
ID uint64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
Email string `protobuf:"bytes,2,opt,name=Email,proto3" json:"Email,omitempty"`
}
func (m *User) Reset() { *m = User{} }
@ -233,52 +240,50 @@ func init() {
func init() { proto.RegisterFile("internal.proto", fileDescriptorInternal) }
var fileDescriptorInternal = []byte{
// 750 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x55, 0x6d, 0x6e, 0xdb, 0x46,
0x10, 0xc5, 0x8a, 0x5c, 0x8a, 0x5c, 0xb9, 0x6e, 0xb1, 0x30, 0x5a, 0xa2, 0xe8, 0x0f, 0x81, 0x68,
0x01, 0x15, 0x68, 0xfd, 0xc3, 0x3e, 0x81, 0x2c, 0x1a, 0x85, 0x5a, 0xd5, 0x76, 0x57, 0x56, 0xfb,
0xab, 0x05, 0xd6, 0xe2, 0xc8, 0x62, 0xbd, 0x22, 0xd9, 0x25, 0x59, 0x99, 0x47, 0x08, 0x90, 0x33,
0xe4, 0x10, 0xc9, 0x51, 0x72, 0x91, 0x1c, 0x21, 0xd8, 0xe1, 0xea, 0x0b, 0x4e, 0x02, 0x03, 0xf9,
0xf9, 0x66, 0x46, 0xc3, 0x37, 0xef, 0x3d, 0x8a, 0xec, 0x38, 0xcd, 0x2a, 0xd0, 0x99, 0x54, 0xa7,
0x85, 0xce, 0xab, 0x9c, 0xfb, 0x1b, 0x1c, 0xbd, 0x21, 0xac, 0x77, 0xf9, 0x58, 0xa8, 0x5c, 0xcb,
0x2a, 0xcd, 0x33, 0x7e, 0xcc, 0x3a, 0xe3, 0x38, 0x24, 0x7d, 0x32, 0x70, 0x44, 0x27, 0x8d, 0x39,
0x67, 0xee, 0x95, 0x5c, 0x41, 0xd8, 0xe9, 0x93, 0x41, 0x20, 0xdc, 0x4c, 0xae, 0x80, 0x7f, 0xcd,
0xbc, 0x59, 0x09, 0x7a, 0x1c, 0x87, 0x0e, 0xce, 0x79, 0x35, 0x22, 0x33, 0x1b, 0xcb, 0x4a, 0x86,
0x6e, 0x3b, 0x9b, 0xc8, 0x4a, 0xf2, 0xef, 0x58, 0x30, 0xd2, 0x20, 0x2b, 0x48, 0x86, 0x55, 0x48,
0x71, 0x3c, 0x98, 0x6f, 0x0a, 0xa6, 0x3b, 0x2b, 0x12, 0xdb, 0xf5, 0xda, 0x6e, 0xbd, 0x29, 0xf0,
0x90, 0x75, 0x63, 0x58, 0xc8, 0x5a, 0x55, 0x61, 0xb7, 0x4f, 0x06, 0xbe, 0xe8, 0x26, 0x2d, 0x8c,
0xde, 0x11, 0xe6, 0x4d, 0xf3, 0x5a, 0xcf, 0xe1, 0x59, 0x84, 0x39, 0x73, 0x6f, 0x9b, 0x02, 0x90,
0x6e, 0x20, 0xdc, 0xaa, 0x29, 0x80, 0x7f, 0xcb, 0x7c, 0x73, 0x84, 0xe9, 0x5b, 0xc2, 0x7e, 0x6d,
0xb1, 0xe9, 0xdd, 0xc8, 0xb2, 0x5c, 0xe7, 0x3a, 0x41, 0xce, 0x81, 0xf0, 0x0b, 0x8b, 0xf9, 0x57,
0xcc, 0x99, 0x89, 0x09, 0x92, 0x0d, 0x84, 0x53, 0x8b, 0xc9, 0xc7, 0x69, 0x9a, 0x3d, 0xb7, 0xa0,
0xe0, 0x5e, 0xcb, 0x45, 0xe8, 0xb7, 0x7b, 0x2a, 0x8b, 0xf9, 0x29, 0xe3, 0xe3, 0xac, 0x84, 0x79,
0xad, 0x61, 0xfa, 0x90, 0x16, 0x7f, 0x82, 0x4e, 0x17, 0x4d, 0x18, 0xe0, 0x02, 0x9e, 0x3e, 0xe9,
0x44, 0xff, 0xb0, 0x20, 0x96, 0xe5, 0xf2, 0x2e, 0x97, 0x3a, 0x79, 0xd6, 0xd1, 0x3f, 0x33, 0x3a,
0x07, 0xa5, 0xca, 0xd0, 0xe9, 0x3b, 0x83, 0xde, 0xd9, 0x37, 0xa7, 0xdb, 0x0c, 0x6c, 0xf7, 0x8c,
0x40, 0x29, 0xd1, 0x4e, 0x45, 0x2f, 0x08, 0xfb, 0xe2, 0xa0, 0xc1, 0x8f, 0x18, 0x79, 0xc4, 0x67,
0x50, 0x41, 0x1e, 0x0d, 0x6a, 0x70, 0x3f, 0x15, 0xa4, 0x31, 0x68, 0x8d, 0x72, 0x52, 0x41, 0xd6,
0x06, 0x2d, 0x51, 0x44, 0x2a, 0xc8, 0xd2, 0xe8, 0xf1, 0x5f, 0x0d, 0x3a, 0x85, 0x32, 0xa4, 0x7d,
0x67, 0x10, 0x88, 0x0d, 0x34, 0x34, 0x51, 0x6f, 0xef, 0xd0, 0x1b, 0xe3, 0x07, 0x4a, 0x67, 0xbd,
0x89, 0x5e, 0x1a, 0x7b, 0x41, 0xff, 0x0f, 0xfa, 0x59, 0x97, 0xee, 0x5b, 0xe9, 0x7c, 0xc2, 0x4a,
0xf7, 0xc3, 0x56, 0xd2, 0x9d, 0x95, 0x27, 0x8c, 0x4e, 0xf5, 0x7c, 0x1c, 0xdb, 0x2c, 0xd2, 0xd2,
0x80, 0xe8, 0x15, 0x61, 0xde, 0x44, 0x36, 0x79, 0x5d, 0xed, 0xd1, 0x09, 0x90, 0x4e, 0x9f, 0xf5,
0x86, 0x45, 0xa1, 0xd2, 0x39, 0xbe, 0x3d, 0x96, 0x55, 0x4f, 0xee, 0x4a, 0x66, 0xe2, 0x77, 0x90,
0x65, 0xad, 0x61, 0x05, 0x59, 0x65, 0xf9, 0xf5, 0x56, 0xbb, 0x12, 0xff, 0x9e, 0xd1, 0x11, 0x1a,
0xe5, 0xa2, 0x51, 0xc7, 0x3b, 0xa3, 0xf6, 0xfc, 0x31, 0x87, 0x0c, 0xeb, 0x2a, 0x5f, 0xa8, 0x7c,
0x8d, 0x8c, 0x7d, 0xe1, 0x4b, 0x8b, 0xa3, 0xb7, 0x84, 0xb9, 0x9f, 0x65, 0xd9, 0x8f, 0x87, 0x96,
0xf5, 0xce, 0xbe, 0xdc, 0x91, 0xf8, 0xa3, 0x06, 0xdd, 0xec, 0x3c, 0x3c, 0x62, 0x24, 0xb5, 0x06,
0x92, 0x74, 0xeb, 0x68, 0x77, 0xcf, 0x8e, 0x90, 0x75, 0x1b, 0x2d, 0xb3, 0x7b, 0x28, 0x43, 0xbf,
0xef, 0x0c, 0x1c, 0xb1, 0x81, 0xd8, 0x51, 0xf2, 0x0e, 0x54, 0x19, 0x06, 0x6d, 0x32, 0x2c, 0xdc,
0xa6, 0x80, 0xed, 0xa5, 0xe0, 0x35, 0x61, 0x14, 0x1f, 0x6e, 0x7e, 0x37, 0xca, 0x57, 0x2b, 0x99,
0x25, 0x56, 0xfa, 0xee, 0xbc, 0x85, 0xc6, 0x8f, 0xf8, 0xc2, 0xca, 0xde, 0x49, 0x2e, 0x0c, 0x16,
0x37, 0x56, 0xe4, 0x8e, 0xbe, 0x31, 0xaa, 0xfd, 0xa2, 0xf3, 0xba, 0xb8, 0x68, 0x5a, 0x79, 0x03,
0xe1, 0xdf, 0x5b, 0x6c, 0xfe, 0xc6, 0xfe, 0x5a, 0x82, 0xde, 0xc6, 0xd4, 0x5b, 0x23, 0x32, 0x21,
0x98, 0x18, 0x56, 0xf6, 0x4a, 0x8a, 0x14, 0xf9, 0x0f, 0x8c, 0x0a, 0x73, 0x05, 0x9e, 0x7a, 0x20,
0x10, 0x96, 0x05, 0xc5, 0x1b, 0xa3, 0x73, 0x3b, 0x66, 0xb6, 0xcc, 0x8a, 0x02, 0xb4, 0xcd, 0x2e,
0xad, 0x0d, 0xc0, 0xdd, 0xf9, 0x1a, 0x34, 0x52, 0x76, 0x04, 0x55, 0x06, 0x44, 0x7f, 0xb3, 0x60,
0xa8, 0x40, 0x57, 0xa2, 0x56, 0xf0, 0x24, 0x62, 0x9c, 0xb9, 0xbf, 0x4e, 0xaf, 0xaf, 0x36, 0x89,
0xff, 0x77, 0x7a, 0x7d, 0xb5, 0xcb, 0xa9, 0xb3, 0x97, 0x53, 0x73, 0xd0, 0x6f, 0xb2, 0x90, 0xe3,
0x18, 0x8d, 0x75, 0x84, 0xf7, 0x80, 0x28, 0xfa, 0x89, 0xb9, 0xe6, 0xfd, 0xd8, 0xdb, 0xec, 0xe2,
0xe6, 0x13, 0x46, 0x2f, 0x57, 0x32, 0x55, 0x76, 0x35, 0x05, 0x03, 0xee, 0x3c, 0xfc, 0x44, 0x9c,
0xbf, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xfb, 0x83, 0xb5, 0x2a, 0x34, 0x06, 0x00, 0x00,
// 712 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x55, 0xd1, 0x6e, 0xd3, 0x4a,
0x10, 0xd5, 0xc6, 0x76, 0x12, 0x4f, 0x7b, 0x7b, 0xaf, 0x56, 0xd5, 0xc5, 0x42, 0x3c, 0x44, 0x16,
0x48, 0x41, 0x82, 0x3e, 0xd0, 0x2f, 0x48, 0xe3, 0x0a, 0x05, 0x4a, 0x29, 0x9b, 0x06, 0x9e, 0x40,
0xda, 0x26, 0x9b, 0xc6, 0xc2, 0xb1, 0xcd, 0xda, 0x26, 0xf5, 0x3f, 0xf0, 0x05, 0x3c, 0xf0, 0x11,
0xf0, 0x29, 0xfc, 0x08, 0x9f, 0x80, 0x66, 0xbc, 0x76, 0x5c, 0x51, 0x50, 0x9f, 0x78, 0x9b, 0x33,
0x33, 0x9d, 0x3d, 0x73, 0xce, 0xb8, 0x81, 0xbd, 0x30, 0xce, 0x95, 0x8e, 0x65, 0x74, 0x90, 0xea,
0x24, 0x4f, 0x78, 0xbf, 0xc6, 0xfe, 0x37, 0x06, 0x3b, 0xc7, 0x57, 0x69, 0x94, 0x68, 0x99, 0x87,
0x49, 0xcc, 0xf7, 0xa0, 0x33, 0x09, 0x3c, 0x36, 0x60, 0x43, 0x4b, 0x74, 0x26, 0x01, 0xe7, 0x60,
0x9f, 0xca, 0xb5, 0xf2, 0x3a, 0x03, 0x36, 0x74, 0x05, 0xc5, 0xfc, 0x7f, 0xe8, 0xce, 0x32, 0xa5,
0x27, 0x81, 0x67, 0x51, 0x9f, 0x41, 0xd8, 0x1b, 0xc8, 0x5c, 0x7a, 0x76, 0xd5, 0x8b, 0x31, 0xbf,
0x07, 0xee, 0x58, 0x2b, 0x99, 0xab, 0xc5, 0x28, 0xf7, 0x1c, 0x6a, 0xdf, 0x26, 0xb0, 0x3a, 0x4b,
0x17, 0xa6, 0xda, 0xad, 0xaa, 0x4d, 0x82, 0x7b, 0xd0, 0x0b, 0xd4, 0x52, 0x16, 0x51, 0xee, 0xf5,
0x06, 0x6c, 0xd8, 0x17, 0x35, 0xf4, 0x7f, 0x30, 0xe8, 0x4e, 0x93, 0x42, 0xcf, 0xd5, 0xad, 0x08,
0x73, 0xb0, 0xcf, 0xcb, 0x54, 0x11, 0x5d, 0x57, 0x50, 0xcc, 0xef, 0x42, 0x1f, 0x69, 0xc7, 0xd8,
0x5b, 0x11, 0x6e, 0x30, 0xd6, 0xce, 0x64, 0x96, 0x6d, 0x12, 0xbd, 0x20, 0xce, 0xae, 0x68, 0x30,
0xff, 0x0f, 0xac, 0x99, 0x38, 0x21, 0xb2, 0xae, 0xc0, 0xf0, 0xf7, 0x34, 0x71, 0xce, 0xb9, 0x8a,
0xd4, 0xa5, 0x96, 0x4b, 0xaf, 0x5f, 0xcd, 0xa9, 0x31, 0x3f, 0x00, 0x3e, 0x89, 0x33, 0x35, 0x2f,
0xb4, 0x9a, 0xbe, 0x0f, 0xd3, 0xd7, 0x4a, 0x87, 0xcb, 0xd2, 0x73, 0x69, 0xc0, 0x0d, 0x15, 0xff,
0x1d, 0xb8, 0x81, 0xcc, 0x56, 0x17, 0x89, 0xd4, 0x8b, 0x5b, 0x2d, 0xfd, 0x18, 0x9c, 0xb9, 0x8a,
0xa2, 0xcc, 0xb3, 0x06, 0xd6, 0x70, 0xe7, 0xc9, 0x9d, 0x83, 0xe6, 0x06, 0x9a, 0x39, 0x63, 0x15,
0x45, 0xa2, 0xea, 0xf2, 0x3f, 0x33, 0xf8, 0xe7, 0x5a, 0x81, 0xef, 0x02, 0xbb, 0xa2, 0x37, 0x1c,
0xc1, 0xae, 0x10, 0x95, 0x34, 0xdf, 0x11, 0xac, 0x44, 0xb4, 0x21, 0x39, 0x1d, 0xc1, 0x36, 0x88,
0x56, 0x24, 0xa2, 0x23, 0xd8, 0x8a, 0x3f, 0x84, 0xde, 0x87, 0x42, 0xe9, 0x50, 0x65, 0x9e, 0x43,
0x4f, 0xff, 0xbb, 0x7d, 0xfa, 0x55, 0xa1, 0x74, 0x29, 0xea, 0x3a, 0xf2, 0x26, 0x03, 0x2a, 0x35,
0x29, 0xc6, 0x5c, 0x8e, 0x66, 0xf5, 0xaa, 0x1c, 0xc6, 0xfe, 0x27, 0xf4, 0x5b, 0xe9, 0x8f, 0x4a,
0xdf, 0x6a, 0xf5, 0xb6, 0xb7, 0xd6, 0x1f, 0xbc, 0xb5, 0x6f, 0xf6, 0xd6, 0xd9, 0x7a, 0xbb, 0x0f,
0xce, 0x54, 0xcf, 0x27, 0x81, 0x39, 0xce, 0x0a, 0xf8, 0x5f, 0x18, 0x74, 0x4f, 0x64, 0x99, 0x14,
0x79, 0x8b, 0x8e, 0x4b, 0x74, 0x06, 0xb0, 0x33, 0x4a, 0xd3, 0x28, 0x9c, 0xd3, 0xe7, 0x64, 0x58,
0xb5, 0x53, 0xd8, 0xf1, 0x42, 0xc9, 0xac, 0xd0, 0x6a, 0xad, 0xe2, 0xdc, 0xf0, 0x6b, 0xa7, 0xf8,
0x7d, 0x70, 0xc6, 0xe4, 0x9c, 0x4d, 0xf2, 0xed, 0x6d, 0xe5, 0xab, 0x0c, 0xa3, 0x22, 0x2e, 0x32,
0x2a, 0xf2, 0x64, 0x19, 0x25, 0x1b, 0x62, 0xdc, 0x17, 0x0d, 0xf6, 0xbf, 0x33, 0xb0, 0xff, 0x96,
0x87, 0xbb, 0xc0, 0x42, 0x63, 0x20, 0x0b, 0x1b, 0x47, 0x7b, 0x2d, 0x47, 0x3d, 0xe8, 0x95, 0x5a,
0xc6, 0x97, 0x2a, 0xf3, 0xfa, 0x03, 0x6b, 0x68, 0x89, 0x1a, 0x52, 0x25, 0x92, 0x17, 0x2a, 0xca,
0x3c, 0x77, 0x60, 0x0d, 0x5d, 0x51, 0xc3, 0xe6, 0x0a, 0xa0, 0x75, 0x05, 0x5f, 0x19, 0x38, 0xf4,
0x38, 0xfe, 0xdd, 0x38, 0x59, 0xaf, 0x65, 0xbc, 0x30, 0xd2, 0xd7, 0x10, 0xfd, 0x08, 0x8e, 0x8c,
0xec, 0x9d, 0xe0, 0x08, 0xb1, 0x38, 0x33, 0x22, 0x77, 0xc4, 0x19, 0xaa, 0xf6, 0x54, 0x27, 0x45,
0x7a, 0x54, 0x56, 0xf2, 0xba, 0xa2, 0xc1, 0xf8, 0x7f, 0xed, 0xcd, 0x4a, 0x69, 0xb3, 0xb3, 0x2b,
0x0c, 0xc2, 0x23, 0x38, 0x41, 0x56, 0x66, 0xcb, 0x0a, 0xf0, 0x07, 0xe0, 0x08, 0xdc, 0x82, 0x56,
0xbd, 0x26, 0x10, 0xa5, 0x45, 0x55, 0xf5, 0x0f, 0x4d, 0x1b, 0x4e, 0x99, 0xa5, 0xa9, 0xd2, 0xe6,
0x76, 0x2b, 0x40, 0xb3, 0x93, 0x8d, 0xd2, 0x44, 0xd9, 0x12, 0x15, 0xf0, 0xdf, 0x82, 0x3b, 0x8a,
0x94, 0xce, 0x45, 0x11, 0xa9, 0x5f, 0x4e, 0x8c, 0x83, 0xfd, 0x6c, 0xfa, 0xf2, 0xb4, 0xbe, 0x78,
0x8c, 0xb7, 0x77, 0x6a, 0xb5, 0xee, 0x14, 0x17, 0x7a, 0x2e, 0x53, 0x39, 0x09, 0xc8, 0x58, 0x4b,
0x18, 0xe4, 0x3f, 0x02, 0x1b, 0xbf, 0x87, 0xd6, 0x64, 0x9b, 0x26, 0xef, 0x83, 0x73, 0xbc, 0x96,
0x61, 0x64, 0x46, 0x57, 0xe0, 0xa2, 0x4b, 0xbf, 0x19, 0x87, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff,
0x6d, 0xf2, 0xe7, 0x54, 0x45, 0x06, 0x00, 0x00,
}

View File

@ -34,7 +34,7 @@ message DashboardCell {
int32 y = 2; // Y-coordinate of Cell in the Dashboard
int32 w = 3; // Width of Cell in the Dashboard
int32 h = 4; // Height of Cell in the Dashboard
repeated string queries = 5; // Time-series data queries for Dashboard
repeated Query queries = 5; // Time-series data queries for Dashboard
string name = 6; // User-facing name for this Dashboard
string type = 7; // Dashboard visualization type
}

View File

@ -243,7 +243,7 @@ type DashboardCell struct {
W int32 `json:"w"`
H int32 `json:"h"`
Name string `json:"name"`
Queries []string `json:"queries"`
Queries []Query `json:"queries"`
Type string `json:"type"`
}

View File

@ -164,10 +164,8 @@ func ValidDashboardRequest(d chronograf.Dashboard) error {
}
for _, c := range d.Cells {
for _, q := range c.Queries {
if len(q) == 0 {
return fmt.Errorf("query required")
}
if (len(c.Queries) == 0) {
return fmt.Errorf("query required")
}
}

View File

@ -115,8 +115,8 @@ func NewMux(opts MuxOpts, service Service) http.Handler {
router.POST("/chronograf/v1/dashboards", service.NewDashboard)
router.GET("/chronograf/v1/dashboards/:id", service.DashboardID)
router.DELETE("/chronograf/v1/dashboard/:id", service.RemoveDashboard)
router.PUT("/chronograf/v1/dashboard/:id", service.UpdateDashboard)
router.DELETE("/chronograf/v1/dashboards/:id", service.RemoveDashboard)
router.PUT("/chronograf/v1/dashboards/:id", service.UpdateDashboard)
/* Authentication */
if opts.UseAuth {

View File

@ -6,3 +6,10 @@ export function getDashboards() {
url: `/chronograf/v1/dashboards`,
});
}
export function getDashboard(id) {
return AJAX({
method: 'GET',
url: `/chronograf/v1/dashboards/${id}`,
});
}

View File

@ -0,0 +1,111 @@
import React, {PropTypes} from 'react';
import ReactTooltip from 'react-tooltip';
import LayoutRenderer from 'shared/components/LayoutRenderer';
import TimeRangeDropdown from '../../shared/components/TimeRangeDropdown';
import timeRanges from 'hson!../../shared/data/timeRanges.hson';
import {getDashboard} from '../apis';
import {getSource} from 'shared/apis';
const DashboardPage = React.createClass({
propTypes: {
params: PropTypes.shape({
sourceID: PropTypes.string.isRequired,
dashboardID: PropTypes.string.isRequired,
}).isRequired,
},
getInitialState() {
const fifteenMinutesIndex = 1;
return {
timeRange: timeRanges[fifteenMinutesIndex],
};
},
componentDidMount() {
getDashboard(this.props.params.dashboardID).then((resp) => {
getSource(this.props.params.sourceID).then(({data: source}) => {
this.setState({
dashboard: resp.data,
source,
});
});
});
},
renderDashboard(dashboard) {
const autoRefreshMs = 15000;
const {timeRange} = this.state;
const {source} = this.state;
const cellWidth = 4;
const cellHeight = 4;
const cells = dashboard.cells.map((cell, i) => {
const dashboardCell = Object.assign(cell, {
w: cellWidth,
h: cellHeight,
queries: cell.queries,
i: i.toString(),
});
dashboardCell.queries.forEach((q) => {
q.text = q.query;
q.database = source.telegraf;
});
return dashboardCell;
});
return (
<LayoutRenderer
timeRange={timeRange}
cells={cells}
autoRefreshMs={autoRefreshMs}
source={source.links.proxy}
/>
);
},
handleChooseTimeRange({lower}) {
const timeRange = timeRanges.find((range) => range.queryValue === lower);
this.setState({timeRange});
},
render() {
const {dashboard, timeRange} = this.state;
const dashboardName = dashboard ? dashboard.name : '';
return (
<div className="page">
<div className="page-header full-width">
<div className="page-header__container">
<div className="page-header__left">
<div className="dropdown page-header-dropdown">
<button className="dropdown-toggle" type="button" data-toggle="dropdown">
<span className="button-text">{dashboardName}</span>
</button>
</div>
</div>
<div className="page-header__right">
<div className="btn btn-info btn-sm" data-for="graph-tips-tooltip" data-tip="<p><code>Click + Drag</code> Zoom in (X or Y)</p><p><code>Shift + Click</code> Pan Graph Window</p><p><code>Double Click</code> Reset Graph Window</p>">
<span className="icon heart"></span>
Graph Tips
</div>
<ReactTooltip id="graph-tips-tooltip" effect="solid" html={true} offset={{top: 2}} place="bottom" class="influx-tooltip place-bottom" />
<TimeRangeDropdown onChooseTimeRange={this.handleChooseTimeRange} selected={timeRange.inputValue} />
</div>
</div>
</div>
<div className="page-contents">
<div className="container-fluid full-width">
{ dashboard ? this.renderDashboard(dashboard) : '' }
</div>
</div>
</div>
);
},
});
export default DashboardPage;

View File

@ -1,26 +1,44 @@
import React from 'react';
import React, {PropTypes} from 'react';
import {Link} from 'react-router';
import {getDashboards} from '../apis';
const DashboardsPage = React.createClass({
propTypes: {
source: PropTypes.shape({
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
type: PropTypes.string,
links: PropTypes.shape({
proxy: PropTypes.string.isRequired,
}).isRequired,
telegraf: PropTypes.string.isRequired,
}),
addFlashMessage: PropTypes.func,
},
getInitialState() {
return {
dashboards: [],
waiting: true,
};
},
componentDidMount() {
getDashboards().then((dashboards) => {
getDashboards().then((resp) => {
this.setState({
dashboards,
dashboards: resp.data.dashboards,
waiting: false,
});
});
},
render() {
let tableHeader;
if (this.state.dashboards.length === 0) {
if (this.state.waiting) {
tableHeader = "Loading Dashboards...";
} else if (this.state.dashboards.length === 0) {
tableHeader = "No Dashboards";
} else {
tableHeader = `${this.state.dashboards.length} Dashboards`;
}
@ -56,7 +74,11 @@ const DashboardsPage = React.createClass({
this.state.dashboards.map((dashboard) => {
return (
<tr key={dashboard.id}>
<td className="monotype">{dashboard.name}</td>
<td className="monotype">
<Link to={`/sources/${this.props.source.id}/dashboards/${dashboard.id}`}>
{dashboard.name}
</Link>
</td>
</tr>
);
})

View File

@ -1,2 +1,3 @@
import DashboardsPage from './containers/DashboardsPage';
export {DashboardsPage};
import DashboardPage from './containers/DashboardPage';
export {DashboardsPage, DashboardPage};

View File

@ -11,7 +11,7 @@ import {KubernetesPage} from 'src/kubernetes';
import {Login} from 'src/auth';
import {KapacitorPage, KapacitorRulePage, KapacitorRulesPage, KapacitorTasksPage} from 'src/kapacitor';
import DataExplorer from 'src/data_explorer';
import {DashboardsPage} from 'src/dashboards';
import {DashboardsPage, DashboardPage} from 'src/dashboards';
import {CreateSource, SourcePage, ManageSources} from 'src/sources';
import NotFound from 'src/shared/components/NotFound';
import configureStore from 'src/store/configureStore';
@ -106,6 +106,7 @@ const Root = React.createClass({
<Route path="kapacitor-tasks" component={KapacitorTasksPage} />
<Route path="alerts" component={AlertsApp} />
<Route path="dashboards" component={DashboardsPage} />
<Route path="dashboards/:dashboardID" component={DashboardPage} />
<Route path="alert-rules" component={KapacitorRulesPage} />
<Route path="alert-rules/:ruleID" component={KapacitorRulePage} />
<Route path="alert-rules/new" component={KapacitorRulePage} />