Merge pull request #1996 from influxdata/feature/source-on-cell
FEATURE: Switch InfluxDB sources per chart in Dashboardspull/10616/head
commit
3c204a4d36
|
@ -5,6 +5,7 @@
|
||||||
1.[#2015](https://github.com/influxdata/chronograf/pull/2015): Chronograf shows real status for windows hosts when metrics are saved in non-default db - thank you, @ar7z1!
|
1.[#2015](https://github.com/influxdata/chronograf/pull/2015): Chronograf shows real status for windows hosts when metrics are saved in non-default db - thank you, @ar7z1!
|
||||||
1.[#2019](https://github.com/influxdata/chronograf/pull/2006): Fix false error warning for duplicate kapacitor name
|
1.[#2019](https://github.com/influxdata/chronograf/pull/2006): Fix false error warning for duplicate kapacitor name
|
||||||
1.[#2018](https://github.com/influxdata/chronograf/pull/2018): Fix unresponsive display options and query builder in dashboards
|
1.[#2018](https://github.com/influxdata/chronograf/pull/2018): Fix unresponsive display options and query builder in dashboards
|
||||||
|
1.[#1996](https://github.com/influxdata/chronograf/pull/1996): Able to switch InfluxDB sources on a per graph basis
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
1. [#1885](https://github.com/influxdata/chronograf/pull/1885): Add `fill` options to data explorer and dashboard queries
|
1. [#1885](https://github.com/influxdata/chronograf/pull/1885): Add `fill` options to data explorer and dashboard queries
|
||||||
|
|
|
@ -195,6 +195,7 @@ func MarshalDashboard(d chronograf.Dashboard) ([]byte, error) {
|
||||||
Command: q.Command,
|
Command: q.Command,
|
||||||
Label: q.Label,
|
Label: q.Label,
|
||||||
Range: r,
|
Range: r,
|
||||||
|
Source: q.Source,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,6 +275,7 @@ func UnmarshalDashboard(data []byte, d *chronograf.Dashboard) error {
|
||||||
queries[j] = chronograf.DashboardQuery{
|
queries[j] = chronograf.DashboardQuery{
|
||||||
Command: q.Command,
|
Command: q.Command,
|
||||||
Label: q.Label,
|
Label: q.Label,
|
||||||
|
Source: q.Source,
|
||||||
}
|
}
|
||||||
if q.Range.Upper != q.Range.Lower {
|
if q.Range.Upper != q.Range.Lower {
|
||||||
queries[j].Range = &chronograf.Range{
|
queries[j].Range = &chronograf.Range{
|
||||||
|
|
|
@ -261,6 +261,7 @@ type Query struct {
|
||||||
Wheres []string `protobuf:"bytes,5,rep,name=Wheres" json:"Wheres,omitempty"`
|
Wheres []string `protobuf:"bytes,5,rep,name=Wheres" json:"Wheres,omitempty"`
|
||||||
Label string `protobuf:"bytes,6,opt,name=Label,proto3" json:"Label,omitempty"`
|
Label string `protobuf:"bytes,6,opt,name=Label,proto3" json:"Label,omitempty"`
|
||||||
Range *Range `protobuf:"bytes,7,opt,name=Range" json:"Range,omitempty"`
|
Range *Range `protobuf:"bytes,7,opt,name=Range" json:"Range,omitempty"`
|
||||||
|
Source string `protobuf:"bytes,8,opt,name=Source,proto3" json:"Source,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Query) Reset() { *m = Query{} }
|
func (m *Query) Reset() { *m = Query{} }
|
||||||
|
@ -327,67 +328,70 @@ func init() {
|
||||||
func init() { proto.RegisterFile("internal.proto", fileDescriptorInternal) }
|
func init() { proto.RegisterFile("internal.proto", fileDescriptorInternal) }
|
||||||
|
|
||||||
var fileDescriptorInternal = []byte{
|
var fileDescriptorInternal = []byte{
|
||||||
// 985 bytes of a gzipped FileDescriptorProto
|
// 1028 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x56, 0xcd, 0x6e, 0x23, 0x45,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x56, 0x4f, 0x6f, 0xe3, 0x44,
|
||||||
0x10, 0x56, 0xcf, 0x8f, 0xed, 0x29, 0x67, 0x03, 0x6a, 0xad, 0xd8, 0x61, 0xb9, 0x98, 0x11, 0x48,
|
0x14, 0xd7, 0xf8, 0x4f, 0x12, 0xbf, 0x74, 0x0b, 0x1a, 0xad, 0x58, 0xb3, 0x5c, 0x82, 0x05, 0x52,
|
||||||
0x06, 0x41, 0x40, 0xbb, 0x42, 0x42, 0xdc, 0x9c, 0x18, 0xad, 0x42, 0xb2, 0x4b, 0x68, 0x27, 0x81,
|
0x40, 0x6c, 0x41, 0xbb, 0x42, 0x42, 0xdc, 0xd2, 0x06, 0xad, 0x4a, 0xbb, 0x4b, 0x99, 0xb4, 0xe5,
|
||||||
0x0b, 0x5a, 0xb5, 0xc7, 0x95, 0x64, 0xb4, 0x63, 0xcf, 0xd0, 0x33, 0x13, 0x7b, 0xde, 0x82, 0x27,
|
0x84, 0x56, 0x13, 0xe7, 0xa5, 0xb5, 0xd6, 0x89, 0xcd, 0xd8, 0x6e, 0xe3, 0x6f, 0xc1, 0x27, 0x40,
|
||||||
0x40, 0x42, 0xe2, 0xc4, 0x81, 0x03, 0x2f, 0xc0, 0x9d, 0xa7, 0x42, 0xd5, 0xdd, 0x33, 0x1e, 0xb3,
|
0x42, 0xe2, 0xc4, 0x81, 0x03, 0x5f, 0x80, 0xfb, 0x7e, 0x2a, 0xf4, 0x66, 0xc6, 0x8e, 0xc3, 0x76,
|
||||||
0x59, 0xb4, 0x17, 0xf6, 0xd6, 0x5f, 0x55, 0xbb, 0xba, 0xe6, 0xab, 0xfa, 0x3e, 0x19, 0xf6, 0x93,
|
0xd1, 0x5e, 0xe0, 0x36, 0xbf, 0xf7, 0xc6, 0x6f, 0x66, 0xde, 0xef, 0xfd, 0x7e, 0x09, 0xec, 0x27,
|
||||||
0x55, 0x89, 0x6a, 0x25, 0xd3, 0x83, 0x5c, 0x65, 0x65, 0xc6, 0x07, 0x0d, 0x8e, 0xfe, 0x70, 0xa0,
|
0xeb, 0x12, 0xd5, 0x5a, 0xa6, 0x07, 0xb9, 0xca, 0xca, 0x8c, 0x0f, 0x1a, 0x1c, 0xfd, 0xe1, 0x40,
|
||||||
0x37, 0xcb, 0x2a, 0x15, 0x23, 0xdf, 0x07, 0xe7, 0x78, 0x1a, 0xb2, 0x11, 0x1b, 0xbb, 0xc2, 0x39,
|
0x6f, 0x96, 0x55, 0x2a, 0x46, 0xbe, 0x0f, 0xce, 0xf1, 0x34, 0x64, 0x23, 0x36, 0x76, 0x85, 0x73,
|
||||||
0x9e, 0x72, 0x0e, 0xde, 0x33, 0xb9, 0xc4, 0xd0, 0x19, 0xb1, 0x71, 0x20, 0xf4, 0x99, 0x62, 0xe7,
|
0x3c, 0xe5, 0x1c, 0xbc, 0xe7, 0x72, 0x85, 0xa1, 0x33, 0x62, 0xe3, 0x40, 0xe8, 0x35, 0xc5, 0xce,
|
||||||
0x75, 0x8e, 0xa1, 0x6b, 0x62, 0x74, 0xe6, 0x0f, 0x61, 0x70, 0x51, 0x50, 0xb5, 0x25, 0x86, 0x9e,
|
0xeb, 0x1c, 0x43, 0xd7, 0xc4, 0x68, 0xcd, 0x1f, 0xc2, 0xe0, 0xa2, 0xa0, 0x6a, 0x2b, 0x0c, 0x3d,
|
||||||
0x8e, 0xb7, 0x98, 0x72, 0x67, 0xb2, 0x28, 0xd6, 0x99, 0x5a, 0x84, 0xbe, 0xc9, 0x35, 0x98, 0xbf,
|
0x1d, 0x6f, 0x31, 0xe5, 0xce, 0x64, 0x51, 0xdc, 0x66, 0x6a, 0x11, 0xfa, 0x26, 0xd7, 0x60, 0xfe,
|
||||||
0x0d, 0xee, 0x85, 0x38, 0x0d, 0x7b, 0x3a, 0x4c, 0x47, 0x1e, 0x42, 0x7f, 0x8a, 0x57, 0xb2, 0x4a,
|
0x2e, 0xb8, 0x17, 0xe2, 0x34, 0xec, 0xe9, 0x30, 0x2d, 0x79, 0x08, 0xfd, 0x29, 0x2e, 0x65, 0x95,
|
||||||
0xcb, 0xb0, 0x3f, 0x62, 0xe3, 0x81, 0x68, 0x20, 0xd5, 0x39, 0xc7, 0x14, 0xaf, 0x95, 0xbc, 0x0a,
|
0x96, 0x61, 0x7f, 0xc4, 0xc6, 0x03, 0xd1, 0x40, 0xaa, 0x73, 0x8e, 0x29, 0x5e, 0x29, 0xb9, 0x0c,
|
||||||
0x07, 0xa6, 0x4e, 0x83, 0xf9, 0x01, 0xf0, 0xe3, 0x55, 0x81, 0x71, 0xa5, 0x70, 0xf6, 0x22, 0xc9,
|
0x07, 0xa6, 0x4e, 0x83, 0xf9, 0x01, 0xf0, 0xe3, 0x75, 0x81, 0x71, 0xa5, 0x70, 0xf6, 0x32, 0xc9,
|
||||||
0x2f, 0x51, 0x25, 0x57, 0x75, 0x18, 0xe8, 0x02, 0x77, 0x64, 0xe8, 0x95, 0xa7, 0x58, 0x4a, 0x7a,
|
0x2f, 0x51, 0x25, 0xcb, 0x3a, 0x0c, 0x74, 0x81, 0x3b, 0x32, 0x74, 0xca, 0x33, 0x2c, 0x25, 0x9d,
|
||||||
0x1b, 0x74, 0xa9, 0x06, 0xf2, 0x08, 0xf6, 0x66, 0x37, 0x52, 0xe1, 0x62, 0x86, 0xb1, 0xc2, 0x32,
|
0x0d, 0xba, 0x54, 0x03, 0x79, 0x04, 0x7b, 0xb3, 0x6b, 0xa9, 0x70, 0x31, 0xc3, 0x58, 0x61, 0x19,
|
||||||
0x1c, 0xea, 0xf4, 0x4e, 0x2c, 0xfa, 0x99, 0x41, 0x30, 0x95, 0xc5, 0xcd, 0x3c, 0x93, 0x6a, 0xf1,
|
0x0e, 0x75, 0x7a, 0x27, 0x16, 0xfd, 0xcc, 0x20, 0x98, 0xca, 0xe2, 0x7a, 0x9e, 0x49, 0xb5, 0x78,
|
||||||
0x5a, 0x9c, 0x7d, 0x0a, 0x7e, 0x8c, 0x69, 0x5a, 0x84, 0xee, 0xc8, 0x1d, 0x0f, 0x1f, 0x3d, 0x38,
|
0xab, 0x9e, 0x3d, 0x02, 0x3f, 0xc6, 0x34, 0x2d, 0x42, 0x77, 0xe4, 0x8e, 0x87, 0x8f, 0x1f, 0x1c,
|
||||||
0x68, 0x87, 0xd1, 0xd6, 0x39, 0xc2, 0x34, 0x15, 0xe6, 0x16, 0xff, 0x1c, 0x82, 0x12, 0x97, 0x79,
|
0xb4, 0x64, 0xb4, 0x75, 0x8e, 0x30, 0x4d, 0x85, 0xd9, 0xc5, 0xbf, 0x80, 0xa0, 0xc4, 0x55, 0x9e,
|
||||||
0x2a, 0x4b, 0x2c, 0x42, 0x4f, 0xff, 0x84, 0x6f, 0x7f, 0x72, 0x6e, 0x53, 0x62, 0x7b, 0x29, 0xfa,
|
0xca, 0x12, 0x8b, 0xd0, 0xd3, 0x9f, 0xf0, 0xed, 0x27, 0xe7, 0x36, 0x25, 0xb6, 0x9b, 0xa2, 0xdf,
|
||||||
0xdd, 0x81, 0x7b, 0x3b, 0xa5, 0xf8, 0x1e, 0xb0, 0x8d, 0xee, 0xca, 0x17, 0x6c, 0x43, 0xa8, 0xd6,
|
0x1d, 0xb8, 0xb7, 0x53, 0x8a, 0xef, 0x01, 0xdb, 0xe8, 0x5b, 0xf9, 0x82, 0x6d, 0x08, 0xd5, 0xfa,
|
||||||
0x1d, 0xf9, 0x82, 0xd5, 0x84, 0xd6, 0x7a, 0x7e, 0xbe, 0x60, 0x6b, 0x42, 0x37, 0x7a, 0x6a, 0xbe,
|
0x46, 0xbe, 0x60, 0x35, 0xa1, 0x5b, 0xcd, 0x9f, 0x2f, 0xd8, 0x2d, 0xa1, 0x6b, 0xcd, 0x9a, 0x2f,
|
||||||
0x60, 0x37, 0xfc, 0x23, 0xe8, 0xff, 0x54, 0xa1, 0x4a, 0xb0, 0x08, 0x7d, 0xfd, 0xf2, 0x5b, 0xdb,
|
0xd8, 0x35, 0xff, 0x04, 0xfa, 0x3f, 0x55, 0xa8, 0x12, 0x2c, 0x42, 0x5f, 0x9f, 0xfc, 0xce, 0xf6,
|
||||||
0x97, 0xbf, 0xab, 0x50, 0xd5, 0xa2, 0xc9, 0xd3, 0x97, 0xea, 0x89, 0x9b, 0xf1, 0xe9, 0x33, 0xc5,
|
0xe4, 0xef, 0x2b, 0x54, 0xb5, 0x68, 0xf2, 0xf4, 0x52, 0xcd, 0xb8, 0xa1, 0x4f, 0xaf, 0x29, 0x56,
|
||||||
0x4a, 0xda, 0x8e, 0xbe, 0x89, 0xd1, 0xd9, 0x32, 0x64, 0x66, 0x46, 0x0c, 0x7d, 0x01, 0x9e, 0xdc,
|
0xd2, 0x74, 0xf4, 0x4d, 0x8c, 0xd6, 0xb6, 0x43, 0x86, 0x33, 0xea, 0xd0, 0x97, 0xe0, 0xc9, 0x0d,
|
||||||
0x60, 0x11, 0x06, 0xba, 0xfe, 0xfb, 0xaf, 0x20, 0xe3, 0x60, 0xb2, 0xc1, 0xe2, 0xeb, 0x55, 0xa9,
|
0x16, 0x61, 0xa0, 0xeb, 0x7f, 0xf8, 0x86, 0x66, 0x1c, 0x4c, 0x36, 0x58, 0x7c, 0xb3, 0x2e, 0x55,
|
||||||
0x6a, 0xa1, 0xaf, 0x3f, 0x7c, 0x02, 0x41, 0x1b, 0xa2, 0xcd, 0x79, 0x81, 0xb5, 0xfe, 0xc0, 0x40,
|
0x2d, 0xf4, 0xf6, 0x87, 0x4f, 0x21, 0x68, 0x43, 0x34, 0x39, 0x2f, 0xb1, 0xd6, 0x0f, 0x0c, 0x04,
|
||||||
0xd0, 0x91, 0x7f, 0x00, 0xfe, 0xad, 0x4c, 0x2b, 0x43, 0xfc, 0xf0, 0xd1, 0xfe, 0xb6, 0xec, 0x64,
|
0x2d, 0xf9, 0x47, 0xe0, 0xdf, 0xc8, 0xb4, 0x32, 0x8d, 0x1f, 0x3e, 0xde, 0xdf, 0x96, 0x9d, 0x6c,
|
||||||
0x93, 0x14, 0xc2, 0x24, 0xbf, 0x72, 0xbe, 0x64, 0xd1, 0x0f, 0xe0, 0x51, 0x88, 0x66, 0x9d, 0xe2,
|
0x92, 0x42, 0x98, 0xe4, 0xd7, 0xce, 0x57, 0x2c, 0xfa, 0x93, 0x81, 0x47, 0x31, 0x22, 0x3b, 0xc5,
|
||||||
0xb5, 0x8c, 0xeb, 0xc3, 0xac, 0x5a, 0x2d, 0x8a, 0x90, 0x8d, 0xdc, 0xb1, 0x2b, 0x76, 0x62, 0xfc,
|
0x2b, 0x19, 0xd7, 0x87, 0x59, 0xb5, 0x5e, 0x14, 0x21, 0x1b, 0xb9, 0x63, 0x57, 0xec, 0xc4, 0xf8,
|
||||||
0x1d, 0xe8, 0xcd, 0x4d, 0xd6, 0x19, 0xb9, 0xe3, 0x40, 0x58, 0xc4, 0xef, 0x83, 0x9f, 0xca, 0x39,
|
0x7b, 0xd0, 0x9b, 0x9b, 0xac, 0x33, 0x72, 0xc7, 0x81, 0xb0, 0x88, 0xdf, 0x07, 0x3f, 0x95, 0x73,
|
||||||
0xa6, 0x56, 0x06, 0x06, 0x44, 0x7f, 0x31, 0x5a, 0x52, 0x33, 0x94, 0xce, 0x62, 0x98, 0xcf, 0x7e,
|
0x4c, 0xad, 0x0e, 0x0c, 0xa0, 0xdd, 0xb9, 0xc2, 0x65, 0xb2, 0xb1, 0x32, 0xb0, 0x88, 0xe2, 0x45,
|
||||||
0x17, 0x06, 0x34, 0xb0, 0xe7, 0xb7, 0x52, 0xd9, 0xe5, 0xe8, 0x13, 0xbe, 0x94, 0x8a, 0x7f, 0x06,
|
0xb5, 0xa4, 0xb8, 0x91, 0x80, 0x45, 0xd4, 0xae, 0xb9, 0x2c, 0xda, 0x16, 0xd2, 0x9a, 0x2a, 0x17,
|
||||||
0x3d, 0xdd, 0xde, 0x1d, 0x0b, 0xd2, 0x94, 0xbb, 0xa4, 0xbc, 0xb0, 0xd7, 0x5a, 0x9a, 0xbd, 0x0e,
|
0xb1, 0x4c, 0x9b, 0x1e, 0x1a, 0x10, 0xfd, 0xc5, 0x68, 0xfe, 0x0d, 0xdf, 0x9d, 0x99, 0x33, 0x1d,
|
||||||
0xcd, 0x6d, 0x4b, 0x7e, 0xa7, 0x25, 0x5a, 0x3d, 0x9a, 0x57, 0xad, 0xa7, 0x74, 0x67, 0x65, 0x33,
|
0x7d, 0x1f, 0x06, 0x34, 0x0b, 0x2f, 0x6e, 0xa4, 0xb2, 0x73, 0xd7, 0x27, 0x7c, 0x29, 0x15, 0xff,
|
||||||
0x55, 0x73, 0x2b, 0xba, 0x80, 0x7b, 0x3b, 0x2f, 0xb6, 0x2f, 0xb1, 0xdd, 0x97, 0xb6, 0x54, 0x07,
|
0x1c, 0x7a, 0xfa, 0xe5, 0x77, 0xcc, 0x5e, 0x53, 0xee, 0x92, 0xf2, 0xc2, 0x6e, 0x6b, 0x19, 0xf4,
|
||||||
0x96, 0x5a, 0x12, 0x68, 0x81, 0x29, 0xc6, 0x25, 0x2e, 0x34, 0x2b, 0x03, 0xd1, 0xe2, 0xe8, 0x57,
|
0x3a, 0x0c, 0xb6, 0x8f, 0xf5, 0xbb, 0x8f, 0x7d, 0x04, 0x3e, 0x8d, 0x42, 0xad, 0x6f, 0x7f, 0x67,
|
||||||
0xb6, 0xad, 0xab, 0xdf, 0x23, 0x09, 0xc6, 0xd9, 0x72, 0x29, 0x57, 0x0b, 0x5b, 0xba, 0x81, 0xc4,
|
0x65, 0x33, 0x30, 0x66, 0x57, 0x74, 0x01, 0xf7, 0x76, 0x4e, 0x6c, 0x4f, 0x62, 0xbb, 0x27, 0x6d,
|
||||||
0xdb, 0x62, 0x6e, 0x4b, 0x3b, 0x8b, 0x39, 0x61, 0x95, 0x5b, 0x9e, 0x1d, 0x95, 0xf3, 0x11, 0x0c,
|
0x59, 0x0c, 0x2c, 0x6b, 0xa4, 0xfd, 0x02, 0x53, 0x8c, 0x4b, 0x5c, 0xe8, 0x7e, 0x0f, 0x44, 0x8b,
|
||||||
0x97, 0x28, 0x8b, 0x4a, 0xe1, 0x12, 0x57, 0xa5, 0xa5, 0xa0, 0x1b, 0xe2, 0x0f, 0xa0, 0x5f, 0xca,
|
0xa3, 0x5f, 0xd9, 0xb6, 0xae, 0x3e, 0x8f, 0xd4, 0x1d, 0x67, 0xab, 0x95, 0x5c, 0x2f, 0x6c, 0xe9,
|
||||||
0xeb, 0xe7, 0xb4, 0x20, 0x86, 0x8b, 0x5e, 0x29, 0xaf, 0x4f, 0xb0, 0xe6, 0xef, 0x41, 0x70, 0x95,
|
0x06, 0x52, 0xdf, 0x16, 0x73, 0x5b, 0xda, 0x59, 0xcc, 0x09, 0xab, 0xdc, 0x32, 0xe8, 0xa8, 0x9c,
|
||||||
0x60, 0xba, 0xd0, 0x29, 0xb3, 0xb6, 0x03, 0x1d, 0x38, 0xc1, 0x3a, 0xfa, 0x8d, 0x41, 0x6f, 0x86,
|
0x8f, 0x60, 0xb8, 0x42, 0x59, 0x54, 0x0a, 0x57, 0xb8, 0x2e, 0x6d, 0x0b, 0xba, 0x21, 0xfe, 0x00,
|
||||||
0xea, 0x16, 0xd5, 0x6b, 0x69, 0xba, 0xeb, 0x79, 0xee, 0x7f, 0x78, 0x9e, 0x77, 0xb7, 0xe7, 0xf9,
|
0xfa, 0xa5, 0xbc, 0x7a, 0x41, 0xb3, 0x67, 0x99, 0x2c, 0xe5, 0xd5, 0x09, 0xd6, 0xfc, 0x03, 0x08,
|
||||||
0x5b, 0xcf, 0xbb, 0x0f, 0xfe, 0x4c, 0xc5, 0xc7, 0x53, 0xdd, 0x91, 0x2b, 0x0c, 0xa0, 0xcd, 0x9b,
|
0x96, 0x09, 0xa6, 0x0b, 0x9d, 0x32, 0x74, 0x0e, 0x74, 0xe0, 0x04, 0xeb, 0xe8, 0x37, 0x06, 0xbd,
|
||||||
0xc4, 0x65, 0x72, 0x8b, 0xd6, 0x08, 0x2d, 0x8a, 0x7e, 0x61, 0xd0, 0x3b, 0x95, 0x75, 0x56, 0x95,
|
0x19, 0xaa, 0x1b, 0x54, 0x6f, 0x65, 0x17, 0x5d, 0x3b, 0x75, 0xff, 0xc5, 0x4e, 0xbd, 0xbb, 0xed,
|
||||||
0x2f, 0x6d, 0xd8, 0x08, 0x86, 0x93, 0x3c, 0x4f, 0x93, 0x58, 0x96, 0x49, 0xb6, 0xb2, 0xdd, 0x76,
|
0xd4, 0xdf, 0xda, 0xe9, 0x7d, 0xf0, 0x67, 0x2a, 0x3e, 0x9e, 0xea, 0x1b, 0xb9, 0xc2, 0x00, 0x9a,
|
||||||
0x43, 0x74, 0xe3, 0x69, 0x87, 0x3b, 0xd3, 0x77, 0x37, 0x44, 0x32, 0x3a, 0xd2, 0x56, 0x65, 0x7c,
|
0xc6, 0x49, 0x5c, 0x26, 0x37, 0x68, 0x3d, 0xd6, 0xa2, 0xe8, 0x17, 0x06, 0xbd, 0x53, 0x59, 0x67,
|
||||||
0xa7, 0x23, 0x23, 0xe3, 0x50, 0x3a, 0x49, 0x1f, 0x38, 0xa9, 0xca, 0xec, 0x2a, 0xcd, 0xd6, 0xfa,
|
0x55, 0xf9, 0xda, 0x84, 0x8d, 0x60, 0x38, 0xc9, 0xf3, 0x34, 0x89, 0x65, 0x99, 0x64, 0x6b, 0x7b,
|
||||||
0x4b, 0x06, 0xa2, 0xc5, 0xd1, 0xdf, 0x0e, 0x78, 0x6f, 0xca, 0x82, 0xf6, 0x80, 0x25, 0x76, 0x90,
|
0xdb, 0x6e, 0x88, 0x76, 0x3c, 0xeb, 0xf4, 0xce, 0xdc, 0xbb, 0x1b, 0x22, 0x85, 0x1e, 0x69, 0x17,
|
||||||
0x2c, 0x69, 0x0d, 0xa9, 0xdf, 0x31, 0xa4, 0x10, 0xfa, 0xb5, 0x92, 0xab, 0x6b, 0x2c, 0xc2, 0x81,
|
0x34, 0x96, 0xd6, 0x51, 0xa8, 0x31, 0x3f, 0x9d, 0xa4, 0x07, 0x4e, 0xaa, 0x32, 0x5b, 0xa6, 0xd9,
|
||||||
0xd6, 0x77, 0x03, 0x75, 0x46, 0x6b, 0xc4, 0x38, 0x51, 0x20, 0x1a, 0xd8, 0xee, 0x3c, 0x74, 0x76,
|
0xad, 0x7e, 0xc9, 0x40, 0xb4, 0x38, 0x7a, 0xe5, 0x80, 0xf7, 0x7f, 0xb9, 0xdb, 0x1e, 0xb0, 0xc4,
|
||||||
0xfe, 0x13, 0x6b, 0x5a, 0x43, 0xdd, 0x51, 0xb8, 0x4b, 0xcb, 0xff, 0xe7, 0x55, 0x7f, 0x32, 0xf0,
|
0x12, 0xc9, 0x92, 0xd6, 0xeb, 0xfa, 0x1d, 0xaf, 0x0b, 0xa1, 0x5f, 0x2b, 0xb9, 0xbe, 0xc2, 0x22,
|
||||||
0x5b, 0xc1, 0x1c, 0xed, 0x0a, 0xe6, 0x68, 0x2b, 0x98, 0xe9, 0x61, 0x23, 0x98, 0xe9, 0x21, 0x61,
|
0x1c, 0x68, 0xe7, 0x68, 0xa0, 0xce, 0x68, 0x8d, 0x18, 0x93, 0x0b, 0x44, 0x03, 0xdb, 0x99, 0x87,
|
||||||
0x71, 0xd6, 0x08, 0x46, 0x9c, 0xd1, 0xb0, 0x9e, 0xa8, 0xac, 0xca, 0x0f, 0x6b, 0x33, 0xd5, 0x40,
|
0xce, 0xcc, 0x7f, 0x66, 0xfd, 0x70, 0xa8, 0x6f, 0x14, 0xee, 0xb6, 0xe5, 0xbf, 0xb3, 0xc1, 0x57,
|
||||||
0xb4, 0x98, 0xb6, 0xec, 0xfb, 0x1b, 0x54, 0x96, 0xea, 0x40, 0x58, 0x44, 0x3b, 0x79, 0xaa, 0xcd,
|
0x0c, 0xfc, 0x56, 0x30, 0x47, 0xbb, 0x82, 0x39, 0xda, 0x0a, 0x66, 0x7a, 0xd8, 0x08, 0x66, 0x7a,
|
||||||
0xc4, 0x90, 0x6b, 0x00, 0xff, 0x10, 0x7c, 0x41, 0xe4, 0x69, 0x86, 0x77, 0xe6, 0xa2, 0xc3, 0xc2,
|
0x48, 0x58, 0x9c, 0x35, 0x82, 0x11, 0x67, 0x44, 0xd6, 0x53, 0x95, 0x55, 0xf9, 0x61, 0x6d, 0x58,
|
||||||
0x64, 0xa3, 0xc7, 0xf6, 0x1a, 0x55, 0xb9, 0xc8, 0x73, 0x54, 0x56, 0x4a, 0x06, 0xe8, 0xda, 0xd9,
|
0x0d, 0x44, 0x8b, 0x69, 0xca, 0x7e, 0xb8, 0x46, 0x65, 0x5b, 0x1d, 0x08, 0x8b, 0x68, 0x26, 0x4f,
|
||||||
0x1a, 0x8d, 0x0b, 0xba, 0xc2, 0x80, 0xe8, 0x47, 0x08, 0x26, 0x29, 0xaa, 0x52, 0x54, 0xe9, 0xcb,
|
0xb5, 0x99, 0x98, 0xe6, 0x1a, 0xc0, 0x3f, 0x06, 0x5f, 0x50, 0xf3, 0x74, 0x87, 0x77, 0x78, 0xd1,
|
||||||
0xde, 0xc9, 0xc1, 0xfb, 0x66, 0xf6, 0xed, 0xb3, 0x46, 0x80, 0x74, 0xde, 0xca, 0xc6, 0xfd, 0x97,
|
0x61, 0x61, 0xb2, 0x54, 0xd4, 0xfc, 0x57, 0xb1, 0xbf, 0x27, 0x16, 0x45, 0x4f, 0xec, 0xe7, 0x54,
|
||||||
0x6c, 0x4e, 0x64, 0x2e, 0x8f, 0xa7, 0x7a, 0x9f, 0x5c, 0x61, 0x51, 0xf4, 0x31, 0x78, 0x24, 0xcf,
|
0xfd, 0x22, 0xcf, 0x51, 0x59, 0x89, 0x19, 0xa0, 0xcf, 0xcc, 0x6e, 0xd1, 0xb8, 0xa3, 0x2b, 0x0c,
|
||||||
0x4e, 0x65, 0xef, 0x55, 0xd2, 0x9e, 0xf7, 0xf4, 0x5f, 0xa4, 0xc7, 0xff, 0x04, 0x00, 0x00, 0xff,
|
0x88, 0x7e, 0x84, 0x60, 0x92, 0xa2, 0x2a, 0x45, 0x95, 0xbe, 0xee, 0xa9, 0x1c, 0xbc, 0x6f, 0x67,
|
||||||
0xff, 0x5a, 0xf0, 0x92, 0xd4, 0x34, 0x09, 0x00, 0x00,
|
0xdf, 0x3d, 0x6f, 0x84, 0x49, 0xeb, 0xad, 0x9c, 0xdc, 0x7f, 0xc8, 0xe9, 0x44, 0xe6, 0xf2, 0x78,
|
||||||
|
0xaa, 0xe7, 0xcc, 0x15, 0x16, 0x45, 0x9f, 0x82, 0x47, 0xb2, 0xed, 0x54, 0xf6, 0xde, 0x24, 0xf9,
|
||||||
|
0x79, 0x4f, 0xff, 0x2b, 0x7b, 0xf2, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb7, 0x59, 0x2e, 0xc0,
|
||||||
|
0xa7, 0x09, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,6 +108,7 @@ message Query {
|
||||||
repeated string Wheres = 5; // Wheres define the restrictions on the query
|
repeated string Wheres = 5; // Wheres define the restrictions on the query
|
||||||
string Label = 6; // Label is the name of the Y-Axis
|
string Label = 6; // Label is the name of the Y-Axis
|
||||||
Range Range = 7; // Range is the upper and lower bound of the Y-Axis
|
Range Range = 7; // Range is the upper and lower bound of the Y-Axis
|
||||||
|
string Source = 8; // Source is the optional URI to the data source
|
||||||
}
|
}
|
||||||
|
|
||||||
message Range {
|
message Range {
|
||||||
|
|
|
@ -162,6 +162,7 @@ func Test_MarshalDashboard(t *testing.T) {
|
||||||
Range: &chronograf.Range{
|
Range: &chronograf.Range{
|
||||||
Upper: int64(100),
|
Upper: int64(100),
|
||||||
},
|
},
|
||||||
|
Source: "/chronograf/v1/sources/1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Axes: map[string]chronograf.Axis{
|
Axes: map[string]chronograf.Axis{
|
||||||
|
|
|
@ -395,6 +395,7 @@ type DashboardQuery struct {
|
||||||
Label string `json:"label,omitempty"` // Label is the Y-Axis label for the data
|
Label string `json:"label,omitempty"` // Label is the Y-Axis label for the data
|
||||||
Range *Range `json:"range,omitempty"` // Range is the default Y-Axis range for the data
|
Range *Range `json:"range,omitempty"` // Range is the default Y-Axis range for the data
|
||||||
QueryConfig QueryConfig `json:"queryConfig,omitempty"` // QueryConfig represents the query state that is understood by the data explorer
|
QueryConfig QueryConfig `json:"queryConfig,omitempty"` // QueryConfig represents the query state that is understood by the data explorer
|
||||||
|
Source string `json:"source"` // Source is the optional URI to the data source for this queryConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// TemplateQuery is used to retrieve choices for template replacement
|
// TemplateQuery is used to retrieve choices for template replacement
|
||||||
|
|
|
@ -217,6 +217,7 @@ func Test_newDashboardResponse(t *testing.T) {
|
||||||
H: 0,
|
H: 0,
|
||||||
Queries: []chronograf.DashboardQuery{
|
Queries: []chronograf.DashboardQuery{
|
||||||
{
|
{
|
||||||
|
Source: "/chronograf/v1/sources/1",
|
||||||
Command: "SELECT donors from hill_valley_preservation_society where time > '1985-10-25 08:00:00'",
|
Command: "SELECT donors from hill_valley_preservation_society where time > '1985-10-25 08:00:00'",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -236,6 +237,7 @@ func Test_newDashboardResponse(t *testing.T) {
|
||||||
H: 0,
|
H: 0,
|
||||||
Queries: []chronograf.DashboardQuery{
|
Queries: []chronograf.DashboardQuery{
|
||||||
{
|
{
|
||||||
|
Source: "/chronograf/v1/sources/2",
|
||||||
Command: "SELECT winning_horses from grays_sports_alamanc where time > now() - 15m",
|
Command: "SELECT winning_horses from grays_sports_alamanc where time > now() - 15m",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -256,6 +258,7 @@ func Test_newDashboardResponse(t *testing.T) {
|
||||||
Queries: []chronograf.DashboardQuery{
|
Queries: []chronograf.DashboardQuery{
|
||||||
{
|
{
|
||||||
Command: "SELECT donors from hill_valley_preservation_society where time > '1985-10-25 08:00:00'",
|
Command: "SELECT donors from hill_valley_preservation_society where time > '1985-10-25 08:00:00'",
|
||||||
|
Source: "/chronograf/v1/sources/1",
|
||||||
QueryConfig: chronograf.QueryConfig{
|
QueryConfig: chronograf.QueryConfig{
|
||||||
RawText: &[]string{"SELECT donors from hill_valley_preservation_society where time > '1985-10-25 08:00:00'"}[0],
|
RawText: &[]string{"SELECT donors from hill_valley_preservation_society where time > '1985-10-25 08:00:00'"}[0],
|
||||||
Fields: []chronograf.Field{},
|
Fields: []chronograf.Field{},
|
||||||
|
@ -303,6 +306,7 @@ func Test_newDashboardResponse(t *testing.T) {
|
||||||
Queries: []chronograf.DashboardQuery{
|
Queries: []chronograf.DashboardQuery{
|
||||||
{
|
{
|
||||||
Command: "SELECT winning_horses from grays_sports_alamanc where time > now() - 15m",
|
Command: "SELECT winning_horses from grays_sports_alamanc where time > now() - 15m",
|
||||||
|
Source: "/chronograf/v1/sources/2",
|
||||||
QueryConfig: chronograf.QueryConfig{
|
QueryConfig: chronograf.QueryConfig{
|
||||||
Measurement: "grays_sports_alamanc",
|
Measurement: "grays_sports_alamanc",
|
||||||
Fields: []chronograf.Field{
|
Fields: []chronograf.Field{
|
||||||
|
|
|
@ -3766,6 +3766,11 @@
|
||||||
"query": {
|
"query": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"source": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "url",
|
||||||
|
"description": "Optional URI for data source for this query"
|
||||||
|
},
|
||||||
"queryConfig": {
|
"queryConfig": {
|
||||||
"$ref": "#/definitions/QueryConfig"
|
"$ref": "#/definitions/QueryConfig"
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,7 +154,7 @@ class AdminPage extends Component {
|
||||||
<h1 className="page-header__title">Admin</h1>
|
<h1 className="page-header__title">Admin</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="page-header__right">
|
<div className="page-header__right">
|
||||||
<SourceIndicator sourceName={source.name} />
|
<SourceIndicator />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -156,7 +156,7 @@ class AlertsApp extends Component {
|
||||||
<h1 className="page-header__title">Alert History</h1>
|
<h1 className="page-header__title">Alert History</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="page-header__right">
|
<div className="page-header__right">
|
||||||
<SourceIndicator sourceName={source.name} />
|
<SourceIndicator />
|
||||||
<CustomTimeRangeDropdown
|
<CustomTimeRangeDropdown
|
||||||
onApplyTimeRange={this.handleApplyTime}
|
onApplyTimeRange={this.handleApplyTime}
|
||||||
timeRange={timeRange}
|
timeRange={timeRange}
|
||||||
|
|
|
@ -19,7 +19,7 @@ const AxesOptions = ({
|
||||||
const [min, max] = bounds
|
const [min, max] = bounds
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="display-options--cell">
|
<div className="display-options--cell y-axis-controls">
|
||||||
<h5 className="display-options--header">Y Axis Controls</h5>
|
<h5 className="display-options--header">Y Axis Controls</h5>
|
||||||
<form autoComplete="off" style={{margin: '0 -6px'}}>
|
<form autoComplete="off" style={{margin: '0 -6px'}}>
|
||||||
<div className="form-group col-sm-12">
|
<div className="form-group col-sm-12">
|
||||||
|
|
|
@ -23,10 +23,17 @@ class CellEditorOverlay extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
const {cell: {name, type, queries, axes}} = props
|
const {cell: {name, type, queries, axes}, sources} = props
|
||||||
|
|
||||||
|
let source = _.get(queries, ['0', 'source'], null)
|
||||||
|
source = sources.find(s => s.links.self === source) || props.source
|
||||||
|
|
||||||
const queriesWorkingDraft = _.cloneDeep(
|
const queriesWorkingDraft = _.cloneDeep(
|
||||||
queries.map(({queryConfig}) => ({...queryConfig, id: uuid.v4()}))
|
queries.map(({queryConfig}) => ({
|
||||||
|
...queryConfig,
|
||||||
|
id: uuid.v4(),
|
||||||
|
source,
|
||||||
|
}))
|
||||||
)
|
)
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -141,6 +148,7 @@ class CellEditorOverlay extends Component {
|
||||||
return {
|
return {
|
||||||
queryConfig: q,
|
queryConfig: q,
|
||||||
query,
|
query,
|
||||||
|
source: _.get(q, ['source', 'links', 'self'], null),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -197,6 +205,15 @@ class CellEditorOverlay extends Component {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleSetQuerySource = source => {
|
||||||
|
const queriesWorkingDraft = this.state.queriesWorkingDraft.map(q => ({
|
||||||
|
..._.cloneDeep(q),
|
||||||
|
source,
|
||||||
|
}))
|
||||||
|
|
||||||
|
this.setState({queriesWorkingDraft})
|
||||||
|
}
|
||||||
|
|
||||||
getActiveQuery = () => {
|
getActiveQuery = () => {
|
||||||
const {queriesWorkingDraft, activeQueryIndex} = this.state
|
const {queriesWorkingDraft, activeQueryIndex} = this.state
|
||||||
const activeQuery = queriesWorkingDraft[activeQueryIndex]
|
const activeQuery = queriesWorkingDraft[activeQueryIndex]
|
||||||
|
@ -221,9 +238,39 @@ class CellEditorOverlay extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
formatSources = this.props.sources.map(s => ({
|
||||||
|
...s,
|
||||||
|
text: `${s.name} @ ${s.url}`,
|
||||||
|
}))
|
||||||
|
|
||||||
|
findSelectedSource = () => {
|
||||||
|
const {source} = this.props
|
||||||
|
const sources = this.formatSources
|
||||||
|
const query = _.get(this.state.queriesWorkingDraft, 0, false)
|
||||||
|
|
||||||
|
if (!query || !query.source) {
|
||||||
|
const defaultSource = sources.find(s => s.id === source.id)
|
||||||
|
return (defaultSource && defaultSource.text) || 'No sources'
|
||||||
|
}
|
||||||
|
|
||||||
|
const selected = sources.find(s => s.id === query.source.id)
|
||||||
|
return (selected && selected.text) || 'No sources'
|
||||||
|
}
|
||||||
|
|
||||||
|
getSource = () => {
|
||||||
|
const {source, sources} = this.props
|
||||||
|
const query = _.get(this.state.queriesWorkingDraft, 0, false)
|
||||||
|
|
||||||
|
if (!query || !query.source) {
|
||||||
|
return source
|
||||||
|
}
|
||||||
|
|
||||||
|
const querySource = sources.find(s => s.id === query.source.id)
|
||||||
|
return querySource || source
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
source,
|
|
||||||
onCancel,
|
onCancel,
|
||||||
templates,
|
templates,
|
||||||
timeRange,
|
timeRange,
|
||||||
|
@ -232,12 +279,12 @@ class CellEditorOverlay extends Component {
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
axes,
|
||||||
activeQueryIndex,
|
activeQueryIndex,
|
||||||
cellWorkingName,
|
cellWorkingName,
|
||||||
cellWorkingType,
|
cellWorkingType,
|
||||||
isDisplayOptionsTabActive,
|
isDisplayOptionsTabActive,
|
||||||
queriesWorkingDraft,
|
queriesWorkingDraft,
|
||||||
axes,
|
|
||||||
} = this.state
|
} = this.state
|
||||||
|
|
||||||
const queryActions = {
|
const queryActions = {
|
||||||
|
@ -271,11 +318,14 @@ class CellEditorOverlay extends Component {
|
||||||
/>
|
/>
|
||||||
<CEOBottom>
|
<CEOBottom>
|
||||||
<OverlayControls
|
<OverlayControls
|
||||||
|
onCancel={onCancel}
|
||||||
|
sources={this.formatSources}
|
||||||
|
onSave={this.handleSaveCell}
|
||||||
|
selected={this.findSelectedSource()}
|
||||||
|
onSetQuerySource={this.handleSetQuerySource}
|
||||||
|
isSavable={queriesWorkingDraft.every(isQuerySavable)}
|
||||||
isDisplayOptionsTabActive={isDisplayOptionsTabActive}
|
isDisplayOptionsTabActive={isDisplayOptionsTabActive}
|
||||||
onClickDisplayOptions={this.handleClickDisplayOptionsTab}
|
onClickDisplayOptions={this.handleClickDisplayOptionsTab}
|
||||||
onCancel={onCancel}
|
|
||||||
onSave={this.handleSaveCell}
|
|
||||||
isSavable={queriesWorkingDraft.every(isQuerySavable)}
|
|
||||||
/>
|
/>
|
||||||
{isDisplayOptionsTabActive
|
{isDisplayOptionsTabActive
|
||||||
? <DisplayOptions
|
? <DisplayOptions
|
||||||
|
@ -291,7 +341,7 @@ class CellEditorOverlay extends Component {
|
||||||
onSetYAxisBoundMax={this.handleSetYAxisBoundMax}
|
onSetYAxisBoundMax={this.handleSetYAxisBoundMax}
|
||||||
/>
|
/>
|
||||||
: <QueryMaker
|
: <QueryMaker
|
||||||
source={source}
|
source={this.getSource()}
|
||||||
templates={templates}
|
templates={templates}
|
||||||
queries={queriesWorkingDraft}
|
queries={queriesWorkingDraft}
|
||||||
actions={queryActions}
|
actions={queryActions}
|
||||||
|
@ -343,6 +393,7 @@ CellEditorOverlay.propTypes = {
|
||||||
status: shape({}),
|
status: shape({}),
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
dashboardID: string.isRequired,
|
dashboardID: string.isRequired,
|
||||||
|
sources: arrayOf(shape()),
|
||||||
}
|
}
|
||||||
|
|
||||||
CEOBottom.propTypes = {
|
CEOBottom.propTypes = {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import FancyScrollbar from 'shared/components/FancyScrollbar'
|
||||||
|
|
||||||
const Dashboard = ({
|
const Dashboard = ({
|
||||||
source,
|
source,
|
||||||
|
sources,
|
||||||
onZoom,
|
onZoom,
|
||||||
dashboard,
|
dashboard,
|
||||||
onAddCell,
|
onAddCell,
|
||||||
|
@ -24,16 +25,11 @@ const Dashboard = ({
|
||||||
}) => {
|
}) => {
|
||||||
const cells = dashboard.cells.map(cell => {
|
const cells = dashboard.cells.map(cell => {
|
||||||
const dashboardCell = {...cell}
|
const dashboardCell = {...cell}
|
||||||
dashboardCell.queries = dashboardCell.queries.map(
|
dashboardCell.queries = dashboardCell.queries.map(q => ({
|
||||||
({label, query, queryConfig, db}) => ({
|
...q,
|
||||||
label,
|
database: q.db,
|
||||||
query,
|
text: q.query,
|
||||||
queryConfig,
|
}))
|
||||||
db,
|
|
||||||
database: db,
|
|
||||||
text: query,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
return dashboardCell
|
return dashboardCell
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -54,17 +50,18 @@ const Dashboard = ({
|
||||||
/>}
|
/>}
|
||||||
{cells.length
|
{cells.length
|
||||||
? <LayoutRenderer
|
? <LayoutRenderer
|
||||||
templates={templatesIncludingDashTime}
|
|
||||||
isEditable={true}
|
|
||||||
cells={cells}
|
cells={cells}
|
||||||
|
onZoom={onZoom}
|
||||||
|
source={source}
|
||||||
|
sources={sources}
|
||||||
|
isEditable={true}
|
||||||
timeRange={timeRange}
|
timeRange={timeRange}
|
||||||
autoRefresh={autoRefresh}
|
autoRefresh={autoRefresh}
|
||||||
source={source}
|
|
||||||
onPositionChange={onPositionChange}
|
|
||||||
onDeleteCell={onDeleteCell}
|
|
||||||
onSummonOverlayTechnologies={onSummonOverlayTechnologies}
|
|
||||||
synchronizer={synchronizer}
|
synchronizer={synchronizer}
|
||||||
onZoom={onZoom}
|
onDeleteCell={onDeleteCell}
|
||||||
|
onPositionChange={onPositionChange}
|
||||||
|
templates={templatesIncludingDashTime}
|
||||||
|
onSummonOverlayTechnologies={onSummonOverlayTechnologies}
|
||||||
/>
|
/>
|
||||||
: <div className="dashboard__empty">
|
: <div className="dashboard__empty">
|
||||||
<p>This Dashboard has no Cells</p>
|
<p>This Dashboard has no Cells</p>
|
||||||
|
@ -112,6 +109,7 @@ Dashboard.propTypes = {
|
||||||
proxy: string,
|
proxy: string,
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
|
sources: arrayOf(shape({})).isRequired,
|
||||||
autoRefresh: number.isRequired,
|
autoRefresh: number.isRequired,
|
||||||
timeRange: shape({}).isRequired,
|
timeRange: shape({}).isRequired,
|
||||||
onOpenTemplateManager: func.isRequired,
|
onOpenTemplateManager: func.isRequired,
|
||||||
|
|
|
@ -18,7 +18,6 @@ const DashboardHeader = ({
|
||||||
handleChooseTimeRange,
|
handleChooseTimeRange,
|
||||||
handleChooseAutoRefresh,
|
handleChooseAutoRefresh,
|
||||||
handleClickPresentationButton,
|
handleClickPresentationButton,
|
||||||
source,
|
|
||||||
onAddCell,
|
onAddCell,
|
||||||
onEditDashboard,
|
onEditDashboard,
|
||||||
onToggleTempVarControls,
|
onToggleTempVarControls,
|
||||||
|
@ -49,7 +48,7 @@ const DashboardHeader = ({
|
||||||
</div>
|
</div>
|
||||||
<div className="page-header__right">
|
<div className="page-header__right">
|
||||||
<GraphTips />
|
<GraphTips />
|
||||||
<SourceIndicator sourceName={source.name} />
|
<SourceIndicator />
|
||||||
{dashboard
|
{dashboard
|
||||||
? <button className="btn btn-primary btn-sm" onClick={onAddCell}>
|
? <button className="btn btn-primary btn-sm" onClick={onAddCell}>
|
||||||
<span className="icon plus" />
|
<span className="icon plus" />
|
||||||
|
@ -107,7 +106,6 @@ DashboardHeader.defaultProps = {
|
||||||
}
|
}
|
||||||
|
|
||||||
DashboardHeader.propTypes = {
|
DashboardHeader.propTypes = {
|
||||||
sourceID: string,
|
|
||||||
children: array,
|
children: array,
|
||||||
buttonText: string,
|
buttonText: string,
|
||||||
dashboard: shape({}),
|
dashboard: shape({}),
|
||||||
|
@ -121,7 +119,6 @@ DashboardHeader.propTypes = {
|
||||||
handleChooseTimeRange: func.isRequired,
|
handleChooseTimeRange: func.isRequired,
|
||||||
handleChooseAutoRefresh: func.isRequired,
|
handleChooseAutoRefresh: func.isRequired,
|
||||||
handleClickPresentationButton: func.isRequired,
|
handleClickPresentationButton: func.isRequired,
|
||||||
source: shape({}),
|
|
||||||
onAddCell: func,
|
onAddCell: func,
|
||||||
onEditDashboard: func,
|
onEditDashboard: func,
|
||||||
onToggleTempVarControls: func,
|
onToggleTempVarControls: func,
|
||||||
|
|
|
@ -1,26 +1,17 @@
|
||||||
import React, {PropTypes} from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import SourceIndicator from 'shared/components/SourceIndicator'
|
import SourceIndicator from 'shared/components/SourceIndicator'
|
||||||
|
|
||||||
const DashboardsHeader = ({sourceName}) => {
|
const DashboardsHeader = () =>
|
||||||
return (
|
|
||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
<div className="page-header__container">
|
<div className="page-header__container">
|
||||||
<div className="page-header__left">
|
<div className="page-header__left">
|
||||||
<h1 className="page-header__title">Dashboards</h1>
|
<h1 className="page-header__title">Dashboards</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="page-header__right">
|
<div className="page-header__right">
|
||||||
<SourceIndicator sourceName={sourceName} />
|
<SourceIndicator />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const {string} = PropTypes
|
|
||||||
|
|
||||||
DashboardsHeader.propTypes = {
|
|
||||||
sourceName: string.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DashboardsHeader
|
export default DashboardsHeader
|
||||||
|
|
|
@ -2,16 +2,24 @@ import React, {PropTypes} from 'react'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
|
|
||||||
import ConfirmButtons from 'shared/components/ConfirmButtons'
|
import ConfirmButtons from 'shared/components/ConfirmButtons'
|
||||||
|
import SourceSelector from 'src/dashboards/components/SourceSelector'
|
||||||
|
|
||||||
const OverlayControls = ({
|
const OverlayControls = ({
|
||||||
onCancel,
|
|
||||||
onSave,
|
onSave,
|
||||||
|
sources,
|
||||||
|
selected,
|
||||||
|
onCancel,
|
||||||
|
isSavable,
|
||||||
|
onSetQuerySource,
|
||||||
isDisplayOptionsTabActive,
|
isDisplayOptionsTabActive,
|
||||||
onClickDisplayOptions,
|
onClickDisplayOptions,
|
||||||
isSavable,
|
|
||||||
}) =>
|
}) =>
|
||||||
<div className="overlay-controls">
|
<div className="overlay-controls">
|
||||||
<h3 className="overlay--graph-name">Cell Editor</h3>
|
<SourceSelector
|
||||||
|
sources={sources}
|
||||||
|
selected={selected}
|
||||||
|
onSetQuerySource={onSetQuerySource}
|
||||||
|
/>
|
||||||
<ul className="nav nav-tablist nav-tablist-sm">
|
<ul className="nav nav-tablist nav-tablist-sm">
|
||||||
<li
|
<li
|
||||||
key="queries"
|
key="queries"
|
||||||
|
@ -29,7 +37,7 @@ const OverlayControls = ({
|
||||||
})}
|
})}
|
||||||
onClick={onClickDisplayOptions(true)}
|
onClick={onClickDisplayOptions(true)}
|
||||||
>
|
>
|
||||||
Display Options
|
Options
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div className="overlay-controls--right">
|
<div className="overlay-controls--right">
|
||||||
|
@ -41,7 +49,7 @@ const OverlayControls = ({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
const {func, bool} = PropTypes
|
const {arrayOf, bool, func, shape, string} = PropTypes
|
||||||
|
|
||||||
OverlayControls.propTypes = {
|
OverlayControls.propTypes = {
|
||||||
onCancel: func.isRequired,
|
onCancel: func.isRequired,
|
||||||
|
@ -49,6 +57,9 @@ OverlayControls.propTypes = {
|
||||||
isDisplayOptionsTabActive: bool.isRequired,
|
isDisplayOptionsTabActive: bool.isRequired,
|
||||||
onClickDisplayOptions: func.isRequired,
|
onClickDisplayOptions: func.isRequired,
|
||||||
isSavable: bool,
|
isSavable: bool,
|
||||||
|
sources: arrayOf(shape()),
|
||||||
|
onSetQuerySource: func,
|
||||||
|
selected: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default OverlayControls
|
export default OverlayControls
|
||||||
|
|
|
@ -13,7 +13,7 @@ const buildText = q =>
|
||||||
q.rawText || buildInfluxQLQuery(q.range || TEMPLATE_RANGE, q) || ''
|
q.rawText || buildInfluxQLQuery(q.range || TEMPLATE_RANGE, q) || ''
|
||||||
|
|
||||||
const QueryMaker = ({
|
const QueryMaker = ({
|
||||||
source: {links},
|
source,
|
||||||
actions,
|
actions,
|
||||||
queries,
|
queries,
|
||||||
timeRange,
|
timeRange,
|
||||||
|
@ -39,7 +39,7 @@ const QueryMaker = ({
|
||||||
query={buildText(activeQuery)}
|
query={buildText(activeQuery)}
|
||||||
config={activeQuery}
|
config={activeQuery}
|
||||||
onUpdate={rawTextBinder(
|
onUpdate={rawTextBinder(
|
||||||
links,
|
source.links,
|
||||||
activeQuery.id,
|
activeQuery.id,
|
||||||
actions.editRawTextAsync
|
actions.editRawTextAsync
|
||||||
)}
|
)}
|
||||||
|
@ -49,6 +49,7 @@ const QueryMaker = ({
|
||||||
query={activeQuery}
|
query={activeQuery}
|
||||||
actions={actions}
|
actions={actions}
|
||||||
onAddQuery={onAddQuery}
|
onAddQuery={onAddQuery}
|
||||||
|
source={source}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
: <EmptyQuery onAddQuery={onAddQuery} />}
|
: <EmptyQuery onAddQuery={onAddQuery} />}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import React, {PropTypes} from 'react'
|
||||||
|
import Dropdown from 'shared/components/Dropdown'
|
||||||
|
|
||||||
|
const SourceSelector = ({sources = [], selected, onSetQuerySource}) =>
|
||||||
|
sources.length > 1
|
||||||
|
? <div className="source-selector">
|
||||||
|
<h3>Source:</h3>
|
||||||
|
<Dropdown
|
||||||
|
items={sources}
|
||||||
|
buttonSize="btn-sm"
|
||||||
|
menuClass="dropdown-astronaut"
|
||||||
|
useAutoComplete={true}
|
||||||
|
selected={selected}
|
||||||
|
onChoose={onSetQuerySource}
|
||||||
|
className="dropdown-240"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
: null
|
||||||
|
|
||||||
|
const {arrayOf, func, shape, string} = PropTypes
|
||||||
|
|
||||||
|
SourceSelector.propTypes = {
|
||||||
|
sources: arrayOf(shape()).isRequired,
|
||||||
|
onSetQuerySource: func.isRequired,
|
||||||
|
selected: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SourceSelector
|
|
@ -190,6 +190,7 @@ class DashboardPage extends Component {
|
||||||
|
|
||||||
const {
|
const {
|
||||||
source,
|
source,
|
||||||
|
sources,
|
||||||
timeRange,
|
timeRange,
|
||||||
timeRange: {lower, upper},
|
timeRange: {lower, upper},
|
||||||
showTemplateControlBar,
|
showTemplateControlBar,
|
||||||
|
@ -277,6 +278,7 @@ class DashboardPage extends Component {
|
||||||
{selectedCell
|
{selectedCell
|
||||||
? <CellEditorOverlay
|
? <CellEditorOverlay
|
||||||
source={source}
|
source={source}
|
||||||
|
sources={sources}
|
||||||
cell={selectedCell}
|
cell={selectedCell}
|
||||||
timeRange={timeRange}
|
timeRange={timeRange}
|
||||||
autoRefresh={autoRefresh}
|
autoRefresh={autoRefresh}
|
||||||
|
@ -324,6 +326,7 @@ class DashboardPage extends Component {
|
||||||
{dashboard
|
{dashboard
|
||||||
? <Dashboard
|
? <Dashboard
|
||||||
source={source}
|
source={source}
|
||||||
|
sources={sources}
|
||||||
dashboard={dashboard}
|
dashboard={dashboard}
|
||||||
timeRange={timeRange}
|
timeRange={timeRange}
|
||||||
autoRefresh={autoRefresh}
|
autoRefresh={autoRefresh}
|
||||||
|
@ -354,6 +357,7 @@ DashboardPage.propTypes = {
|
||||||
self: string,
|
self: string,
|
||||||
}),
|
}),
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
|
sources: arrayOf(shape({})).isRequired,
|
||||||
params: shape({
|
params: shape({
|
||||||
sourceID: string.isRequired,
|
sourceID: string.isRequired,
|
||||||
dashboardID: string.isRequired,
|
dashboardID: string.isRequired,
|
||||||
|
@ -415,6 +419,7 @@ const mapStateToProps = state => {
|
||||||
persisted: {autoRefresh, showTemplateControlBar},
|
persisted: {autoRefresh, showTemplateControlBar},
|
||||||
},
|
},
|
||||||
dashboardUI: {dashboards, timeRange, cellQueryStatus},
|
dashboardUI: {dashboards, timeRange, cellQueryStatus},
|
||||||
|
sources,
|
||||||
} = state
|
} = state
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -424,6 +429,7 @@ const mapStateToProps = state => {
|
||||||
showTemplateControlBar,
|
showTemplateControlBar,
|
||||||
inPresentationMode,
|
inPresentationMode,
|
||||||
cellQueryStatus,
|
cellQueryStatus,
|
||||||
|
sources,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,12 +22,6 @@ const Header = React.createClass({
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
},
|
},
|
||||||
|
|
||||||
contextTypes: {
|
|
||||||
source: shape({
|
|
||||||
name: string,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
|
|
||||||
handleChooseTimeRange(bounds) {
|
handleChooseTimeRange(bounds) {
|
||||||
this.props.actions.setTimeRange(bounds)
|
this.props.actions.setTimeRange(bounds)
|
||||||
},
|
},
|
||||||
|
@ -48,7 +42,7 @@ const Header = React.createClass({
|
||||||
</div>
|
</div>
|
||||||
<div className="page-header__right">
|
<div className="page-header__right">
|
||||||
<GraphTips />
|
<GraphTips />
|
||||||
<SourceIndicator sourceName={this.context.source.name} />
|
<SourceIndicator />
|
||||||
<div
|
<div
|
||||||
className="btn btn-sm btn-default"
|
className="btn btn-sm btn-default"
|
||||||
onClick={showWriteForm}
|
onClick={showWriteForm}
|
||||||
|
|
|
@ -84,7 +84,7 @@ export const HostsPage = React.createClass({
|
||||||
<h1 className="page-header__title">Host List</h1>
|
<h1 className="page-header__title">Host List</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="page-header__right">
|
<div className="page-header__right">
|
||||||
<SourceIndicator sourceName={source.name} />
|
<SourceIndicator />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -99,7 +99,7 @@ const KapacitorRules = ({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const PageContents = ({children, source}) =>
|
const PageContents = ({children}) =>
|
||||||
<div className="page">
|
<div className="page">
|
||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
<div className="page-header__container">
|
<div className="page-header__container">
|
||||||
|
@ -109,7 +109,7 @@ const PageContents = ({children, source}) =>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="page-header__right">
|
<div className="page-header__right">
|
||||||
<SourceIndicator sourceName={source && source.name} />
|
<SourceIndicator />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -139,7 +139,6 @@ KapacitorRules.propTypes = {
|
||||||
|
|
||||||
PageContents.propTypes = {
|
PageContents.propTypes = {
|
||||||
children: node,
|
children: node,
|
||||||
source: shape(),
|
|
||||||
onCloseTickscript: func,
|
onCloseTickscript: func,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,13 @@ import TimeRangeDropdown from 'shared/components/TimeRangeDropdown'
|
||||||
import SourceIndicator from 'shared/components/SourceIndicator'
|
import SourceIndicator from 'shared/components/SourceIndicator'
|
||||||
|
|
||||||
const RuleHeaderSave = ({
|
const RuleHeaderSave = ({
|
||||||
source,
|
|
||||||
onSave,
|
onSave,
|
||||||
timeRange,
|
timeRange,
|
||||||
validationError,
|
validationError,
|
||||||
onChooseTimeRange,
|
onChooseTimeRange,
|
||||||
}) =>
|
}) =>
|
||||||
<div className="page-header__right">
|
<div className="page-header__right">
|
||||||
<SourceIndicator sourceName={source.name} />
|
<SourceIndicator />
|
||||||
<TimeRangeDropdown
|
<TimeRangeDropdown
|
||||||
onChooseTimeRange={onChooseTimeRange}
|
onChooseTimeRange={onChooseTimeRange}
|
||||||
selected={timeRange}
|
selected={timeRange}
|
||||||
|
@ -41,7 +40,6 @@ const RuleHeaderSave = ({
|
||||||
const {func, shape, string} = PropTypes
|
const {func, shape, string} = PropTypes
|
||||||
|
|
||||||
RuleHeaderSave.propTypes = {
|
RuleHeaderSave.propTypes = {
|
||||||
source: shape({}).isRequired,
|
|
||||||
onSave: func.isRequired,
|
onSave: func.isRequired,
|
||||||
validationError: string.isRequired,
|
validationError: string.isRequired,
|
||||||
onChooseTimeRange: func.isRequired,
|
onChooseTimeRange: func.isRequired,
|
||||||
|
|
|
@ -11,7 +11,6 @@ const addName = list => list.map(l => ({...l, name: `${l.db}.${l.rp}`}))
|
||||||
const TickscriptHeader = ({
|
const TickscriptHeader = ({
|
||||||
task: {id, type, dbrps},
|
task: {id, type, dbrps},
|
||||||
task,
|
task,
|
||||||
source: {name},
|
|
||||||
onSave,
|
onSave,
|
||||||
onChangeType,
|
onChangeType,
|
||||||
onChangeID,
|
onChangeID,
|
||||||
|
@ -26,7 +25,7 @@ const TickscriptHeader = ({
|
||||||
: <TickscriptStaticID id={task.name} />}
|
: <TickscriptStaticID id={task.name} />}
|
||||||
</div>
|
</div>
|
||||||
<div className="page-header__right">
|
<div className="page-header__right">
|
||||||
<SourceIndicator sourceName={name} />
|
<SourceIndicator />
|
||||||
<TickscriptType type={type} onChangeType={onChangeType} />
|
<TickscriptType type={type} onChangeType={onChangeType} />
|
||||||
<MultiSelectDBDropdown
|
<MultiSelectDBDropdown
|
||||||
selectedItems={addName(dbrps)}
|
selectedItems={addName(dbrps)}
|
||||||
|
@ -48,7 +47,6 @@ const {arrayOf, bool, func, shape, string} = PropTypes
|
||||||
|
|
||||||
TickscriptHeader.propTypes = {
|
TickscriptHeader.propTypes = {
|
||||||
onSave: func,
|
onSave: func,
|
||||||
source: shape(),
|
|
||||||
onSelectDbrps: func.isRequired,
|
onSelectDbrps: func.isRequired,
|
||||||
task: shape({
|
task: shape({
|
||||||
dbrps: arrayOf(
|
dbrps: arrayOf(
|
||||||
|
|
|
@ -221,8 +221,8 @@ const AutoRefresh = ComposedComponent => {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return data.every(datum => {
|
return data.every(({response}) => {
|
||||||
return datum.response.results.every(result => {
|
return _.get(response, 'results', []).every(result => {
|
||||||
return (
|
return (
|
||||||
Object.keys(result).filter(k => k !== 'statement_id').length === 0
|
Object.keys(result).filter(k => k !== 'statement_id').length === 0
|
||||||
)
|
)
|
||||||
|
|
|
@ -15,7 +15,7 @@ const CustomTimeIndicator = ({queries}) => {
|
||||||
: customLower
|
: customLower
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className="dash-graph--custom-time">
|
<span className="custom-indicator">
|
||||||
{customTimeRange}
|
{customTimeRange}
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,6 +14,17 @@ const DatabaseList = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
query: shape({}).isRequired,
|
query: shape({}).isRequired,
|
||||||
onChooseNamespace: func.isRequired,
|
onChooseNamespace: func.isRequired,
|
||||||
|
querySource: shape({
|
||||||
|
links: shape({
|
||||||
|
proxy: string.isRequired,
|
||||||
|
}).isRequired,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
|
||||||
|
getDefaultProps() {
|
||||||
|
return {
|
||||||
|
source: null,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
contextTypes: {
|
contextTypes: {
|
||||||
|
@ -31,8 +42,23 @@ const DatabaseList = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
this.getDbRp()
|
||||||
|
},
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
if (_.isEqual(prevProps.querySource, this.props.querySource)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getDbRp()
|
||||||
|
},
|
||||||
|
|
||||||
|
getDbRp() {
|
||||||
const {source} = this.context
|
const {source} = this.context
|
||||||
const proxy = source.links.proxy
|
const {querySource} = this.props
|
||||||
|
const proxy =
|
||||||
|
_.get(querySource, ['links', 'proxy'], null) || source.links.proxy
|
||||||
|
|
||||||
showDatabases(proxy).then(resp => {
|
showDatabases(proxy).then(resp => {
|
||||||
const {errors, databases} = showDatabasesParser(resp.data)
|
const {errors, databases} = showDatabasesParser(resp.data)
|
||||||
if (errors.length) {
|
if (errors.length) {
|
||||||
|
|
|
@ -206,6 +206,7 @@ class Dropdown extends Component {
|
||||||
iconName,
|
iconName,
|
||||||
buttonSize,
|
buttonSize,
|
||||||
buttonColor,
|
buttonColor,
|
||||||
|
toggleStyle,
|
||||||
useAutoComplete,
|
useAutoComplete,
|
||||||
} = this.props
|
} = this.props
|
||||||
const {isOpen, searchTerm, filteredItems} = this.state
|
const {isOpen, searchTerm, filteredItems} = this.state
|
||||||
|
@ -222,6 +223,7 @@ class Dropdown extends Component {
|
||||||
{useAutoComplete && isOpen
|
{useAutoComplete && isOpen
|
||||||
? <div
|
? <div
|
||||||
className={`dropdown-autocomplete dropdown-toggle ${buttonSize} ${buttonColor}`}
|
className={`dropdown-autocomplete dropdown-toggle ${buttonSize} ${buttonColor}`}
|
||||||
|
style={toggleStyle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
ref="dropdownAutoComplete"
|
ref="dropdownAutoComplete"
|
||||||
|
@ -236,7 +238,10 @@ class Dropdown extends Component {
|
||||||
/>
|
/>
|
||||||
<span className="caret" />
|
<span className="caret" />
|
||||||
</div>
|
</div>
|
||||||
: <div className={`btn dropdown-toggle ${buttonSize} ${buttonColor}`}>
|
: <div
|
||||||
|
className={`btn dropdown-toggle ${buttonSize} ${buttonColor}`}
|
||||||
|
style={toggleStyle}
|
||||||
|
>
|
||||||
{iconName
|
{iconName
|
||||||
? <span className={classnames('icon', {[iconName]: true})} />
|
? <span className={classnames('icon', {[iconName]: true})} />
|
||||||
: null}
|
: null}
|
||||||
|
@ -291,6 +296,7 @@ Dropdown.propTypes = {
|
||||||
menuLabel: string,
|
menuLabel: string,
|
||||||
menuClass: string,
|
menuClass: string,
|
||||||
useAutoComplete: bool,
|
useAutoComplete: bool,
|
||||||
|
toggleStyle: shape(),
|
||||||
}
|
}
|
||||||
|
|
||||||
export default OnClickOutside(Dropdown)
|
export default OnClickOutside(Dropdown)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React, {PropTypes, Component} from 'react'
|
import React, {PropTypes, Component} from 'react'
|
||||||
|
import _ from 'lodash'
|
||||||
|
|
||||||
import FieldListItem from 'src/data_explorer/components/FieldListItem'
|
import FieldListItem from 'src/data_explorer/components/FieldListItem'
|
||||||
import GroupByTimeDropdown from 'src/data_explorer/components/GroupByTimeDropdown'
|
import GroupByTimeDropdown from 'src/data_explorer/components/GroupByTimeDropdown'
|
||||||
|
@ -26,7 +27,8 @@ class FieldList extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
const {database, measurement, retentionPolicy} = this.props.query
|
const {querySource, query} = this.props
|
||||||
|
const {database, measurement, retentionPolicy} = query
|
||||||
const {
|
const {
|
||||||
database: prevDB,
|
database: prevDB,
|
||||||
measurement: prevMeas,
|
measurement: prevMeas,
|
||||||
|
@ -39,7 +41,8 @@ class FieldList extends Component {
|
||||||
if (
|
if (
|
||||||
database === prevDB &&
|
database === prevDB &&
|
||||||
measurement === prevMeas &&
|
measurement === prevMeas &&
|
||||||
retentionPolicy === prevRP
|
retentionPolicy === prevRP &&
|
||||||
|
_.isEqual(prevProps.querySource, querySource)
|
||||||
) {
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -58,14 +61,12 @@ class FieldList extends Component {
|
||||||
_getFields = () => {
|
_getFields = () => {
|
||||||
const {database, measurement, retentionPolicy} = this.props.query
|
const {database, measurement, retentionPolicy} = this.props.query
|
||||||
const {source} = this.context
|
const {source} = this.context
|
||||||
const proxySource = source.links.proxy
|
const {querySource} = this.props
|
||||||
|
|
||||||
showFieldKeys(
|
const proxy =
|
||||||
proxySource,
|
_.get(querySource, ['links', 'proxy'], null) || source.links.proxy
|
||||||
database,
|
|
||||||
measurement,
|
showFieldKeys(proxy, database, measurement, retentionPolicy).then(resp => {
|
||||||
retentionPolicy
|
|
||||||
).then(resp => {
|
|
||||||
const {errors, fieldSets} = showFieldKeysParser(resp.data)
|
const {errors, fieldSets} = showFieldKeysParser(resp.data)
|
||||||
if (errors.length) {
|
if (errors.length) {
|
||||||
console.error('Error parsing fields keys: ', errors)
|
console.error('Error parsing fields keys: ', errors)
|
||||||
|
@ -171,6 +172,11 @@ FieldList.propTypes = {
|
||||||
applyFuncsToField: func.isRequired,
|
applyFuncsToField: func.isRequired,
|
||||||
isKapacitorRule: bool,
|
isKapacitorRule: bool,
|
||||||
isInDataExplorer: bool,
|
isInDataExplorer: bool,
|
||||||
|
querySource: shape({
|
||||||
|
links: shape({
|
||||||
|
proxy: string.isRequired,
|
||||||
|
}).isRequired,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
export default FieldList
|
export default FieldList
|
||||||
|
|
|
@ -4,7 +4,7 @@ import ReactTooltip from 'react-tooltip'
|
||||||
const GraphTips = React.createClass({
|
const GraphTips = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
const graphTipsText =
|
const graphTipsText =
|
||||||
'<p><b>Graph Tips:</b><br/><br/><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>'
|
'<h1>Graph Tips:</h1><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>'
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="graph-tips"
|
className="graph-tips"
|
||||||
|
|
|
@ -4,11 +4,24 @@ import LayoutCell from 'shared/components/LayoutCell'
|
||||||
import RefreshingGraph from 'shared/components/RefreshingGraph'
|
import RefreshingGraph from 'shared/components/RefreshingGraph'
|
||||||
import {buildQueriesForLayouts} from 'utils/influxql'
|
import {buildQueriesForLayouts} from 'utils/influxql'
|
||||||
|
|
||||||
const Layout = ({
|
import _ from 'lodash'
|
||||||
|
|
||||||
|
const getSource = (cell, source, sources, defaultSource) => {
|
||||||
|
const s = _.get(cell, ['queries', '0', 'source'], null)
|
||||||
|
if (!s) {
|
||||||
|
return source
|
||||||
|
}
|
||||||
|
|
||||||
|
return sources.find(src => src.links.self === s) || defaultSource
|
||||||
|
}
|
||||||
|
|
||||||
|
const Layout = (
|
||||||
|
{
|
||||||
host,
|
host,
|
||||||
cell,
|
cell,
|
||||||
cell: {h, axes, type},
|
cell: {h, axes, type},
|
||||||
source,
|
source,
|
||||||
|
sources,
|
||||||
onZoom,
|
onZoom,
|
||||||
templates,
|
templates,
|
||||||
timeRange,
|
timeRange,
|
||||||
|
@ -20,14 +33,16 @@ const Layout = ({
|
||||||
resizeCoords,
|
resizeCoords,
|
||||||
onCancelEditCell,
|
onCancelEditCell,
|
||||||
onSummonOverlayTechnologies,
|
onSummonOverlayTechnologies,
|
||||||
}) =>
|
},
|
||||||
|
{source: defaultSource}
|
||||||
|
) =>
|
||||||
<LayoutCell
|
<LayoutCell
|
||||||
onCancelEditCell={onCancelEditCell}
|
cell={cell}
|
||||||
isEditable={isEditable}
|
isEditable={isEditable}
|
||||||
onEditCell={onEditCell}
|
onEditCell={onEditCell}
|
||||||
onDeleteCell={onDeleteCell}
|
onDeleteCell={onDeleteCell}
|
||||||
|
onCancelEditCell={onCancelEditCell}
|
||||||
onSummonOverlayTechnologies={onSummonOverlayTechnologies}
|
onSummonOverlayTechnologies={onSummonOverlayTechnologies}
|
||||||
cell={cell}
|
|
||||||
>
|
>
|
||||||
{cell.isWidget
|
{cell.isWidget
|
||||||
? <WidgetCell cell={cell} timeRange={timeRange} source={source} />
|
? <WidgetCell cell={cell} timeRange={timeRange} source={source} />
|
||||||
|
@ -36,17 +51,27 @@ const Layout = ({
|
||||||
type={type}
|
type={type}
|
||||||
cellHeight={h}
|
cellHeight={h}
|
||||||
onZoom={onZoom}
|
onZoom={onZoom}
|
||||||
|
sources={sources}
|
||||||
timeRange={timeRange}
|
timeRange={timeRange}
|
||||||
templates={templates}
|
templates={templates}
|
||||||
autoRefresh={autoRefresh}
|
autoRefresh={autoRefresh}
|
||||||
synchronizer={synchronizer}
|
synchronizer={synchronizer}
|
||||||
resizeCoords={resizeCoords}
|
resizeCoords={resizeCoords}
|
||||||
queries={buildQueriesForLayouts(cell, source, timeRange, host)}
|
queries={buildQueriesForLayouts(
|
||||||
|
cell,
|
||||||
|
getSource(cell, source, sources, defaultSource),
|
||||||
|
timeRange,
|
||||||
|
host
|
||||||
|
)}
|
||||||
/>}
|
/>}
|
||||||
</LayoutCell>
|
</LayoutCell>
|
||||||
|
|
||||||
const {arrayOf, bool, func, number, shape, string} = PropTypes
|
const {arrayOf, bool, func, number, shape, string} = PropTypes
|
||||||
|
|
||||||
|
Layout.contextTypes = {
|
||||||
|
source: shape(),
|
||||||
|
}
|
||||||
|
|
||||||
Layout.propTypes = {
|
Layout.propTypes = {
|
||||||
autoRefresh: number.isRequired,
|
autoRefresh: number.isRequired,
|
||||||
timeRange: shape({
|
timeRange: shape({
|
||||||
|
@ -87,6 +112,7 @@ Layout.propTypes = {
|
||||||
onCancelEditCell: func,
|
onCancelEditCell: func,
|
||||||
resizeCoords: shape(),
|
resizeCoords: shape(),
|
||||||
onZoom: func,
|
onZoom: func,
|
||||||
|
sources: arrayOf(shape()),
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Layout
|
export default Layout
|
||||||
|
|
|
@ -40,16 +40,16 @@ class LayoutCell extends Component {
|
||||||
<div className="dash-graph">
|
<div className="dash-graph">
|
||||||
<LayoutCellMenu
|
<LayoutCellMenu
|
||||||
cell={cell}
|
cell={cell}
|
||||||
onDeleteClick={this.handleDeleteClick}
|
|
||||||
onDelete={this.handleDeleteCell}
|
|
||||||
isDeleting={isDeleting}
|
isDeleting={isDeleting}
|
||||||
isEditable={isEditable}
|
isEditable={isEditable}
|
||||||
handleClickOutside={this.closeMenu}
|
onDelete={this.handleDeleteCell}
|
||||||
onEdit={this.handleSummonOverlay}
|
onEdit={this.handleSummonOverlay}
|
||||||
|
handleClickOutside={this.closeMenu}
|
||||||
|
onDeleteClick={this.handleDeleteClick}
|
||||||
/>
|
/>
|
||||||
<LayoutCellHeader
|
<LayoutCellHeader
|
||||||
cellName={cell.name}
|
|
||||||
queries={queries}
|
queries={queries}
|
||||||
|
cellName={cell.name}
|
||||||
isEditable={isEditable}
|
isEditable={isEditable}
|
||||||
/>
|
/>
|
||||||
<div className="dash-graph--container">
|
<div className="dash-graph--container">
|
||||||
|
@ -69,7 +69,7 @@ class LayoutCell extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const {array, bool, func, node, number, shape, string} = PropTypes
|
const {arrayOf, bool, func, node, number, shape, string} = PropTypes
|
||||||
|
|
||||||
LayoutCell.propTypes = {
|
LayoutCell.propTypes = {
|
||||||
cell: shape({
|
cell: shape({
|
||||||
|
@ -77,7 +77,7 @@ LayoutCell.propTypes = {
|
||||||
isEditing: bool,
|
isEditing: bool,
|
||||||
x: number.isRequired,
|
x: number.isRequired,
|
||||||
y: number.isRequired,
|
y: number.isRequired,
|
||||||
queries: array,
|
queries: arrayOf(shape()),
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
children: node.isRequired,
|
children: node.isRequired,
|
||||||
onDeleteCell: func,
|
onDeleteCell: func,
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React, {PropTypes} from 'react'
|
import React, {PropTypes} from 'react'
|
||||||
import classnames from 'classnames'
|
|
||||||
|
|
||||||
import CustomTimeIndicator from 'shared/components/CustomTimeIndicator'
|
import CustomTimeIndicator from 'shared/components/CustomTimeIndicator'
|
||||||
|
|
||||||
|
@ -8,12 +7,12 @@ import {NEW_DEFAULT_DASHBOARD_CELL} from 'src/dashboards/constants/index'
|
||||||
const LayoutCellHeader = ({queries, isEditable, cellName}) => {
|
const LayoutCellHeader = ({queries, isEditable, cellName}) => {
|
||||||
const cellNameIsDefault = cellName === NEW_DEFAULT_DASHBOARD_CELL.name
|
const cellNameIsDefault = cellName === NEW_DEFAULT_DASHBOARD_CELL.name
|
||||||
|
|
||||||
|
const headingClass = `dash-graph--heading ${isEditable
|
||||||
|
? 'dash-graph--heading-draggable'
|
||||||
|
: ''}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={headingClass}>
|
||||||
className={classnames('dash-graph--heading', {
|
|
||||||
'dash-graph--heading-draggable': isEditable,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<span
|
<span
|
||||||
className={
|
className={
|
||||||
cellNameIsDefault
|
cellNameIsDefault
|
||||||
|
@ -22,18 +21,20 @@ const LayoutCellHeader = ({queries, isEditable, cellName}) => {
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{cellName}
|
{cellName}
|
||||||
|
<div className="dash-graph--custom-indicators">
|
||||||
{queries && queries.length
|
{queries && queries.length
|
||||||
? <CustomTimeIndicator queries={queries} />
|
? <CustomTimeIndicator queries={queries} />
|
||||||
: null}
|
: null}
|
||||||
|
</div>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const {array, bool, string} = PropTypes
|
const {arrayOf, bool, shape, string} = PropTypes
|
||||||
|
|
||||||
LayoutCellHeader.propTypes = {
|
LayoutCellHeader.propTypes = {
|
||||||
queries: array,
|
queries: arrayOf(shape()),
|
||||||
isEditable: bool,
|
isEditable: bool,
|
||||||
cellName: string,
|
cellName: string,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React, {Component, PropTypes} from 'react'
|
import React, {Component, PropTypes} from 'react'
|
||||||
import ReactGridLayout, {WidthProvider} from 'react-grid-layout'
|
import ReactGridLayout, {WidthProvider} from 'react-grid-layout'
|
||||||
import Resizeable from 'react-component-resizable'
|
import Resizeable from 'react-component-resizable'
|
||||||
|
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
|
||||||
import Layout from 'src/shared/components/Layout'
|
import Layout from 'src/shared/components/Layout'
|
||||||
|
@ -26,11 +27,6 @@ class LayoutRenderer extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// idea adopted from https://stackoverflow.com/questions/36862334/get-viewport-window-height-in-reactjs
|
|
||||||
updateWindowDimensions = () => {
|
|
||||||
this.setState({rowHeight: this.calculateRowHeight()})
|
|
||||||
}
|
|
||||||
|
|
||||||
handleLayoutChange = layout => {
|
handleLayoutChange = layout => {
|
||||||
if (!this.props.onPositionChange) {
|
if (!this.props.onPositionChange) {
|
||||||
return
|
return
|
||||||
|
@ -72,6 +68,7 @@ class LayoutRenderer extends Component {
|
||||||
host,
|
host,
|
||||||
cells,
|
cells,
|
||||||
source,
|
source,
|
||||||
|
sources,
|
||||||
onZoom,
|
onZoom,
|
||||||
templates,
|
templates,
|
||||||
timeRange,
|
timeRange,
|
||||||
|
@ -88,7 +85,7 @@ class LayoutRenderer extends Component {
|
||||||
const isDashboard = !!this.props.onPositionChange
|
const isDashboard = !!this.props.onPositionChange
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Resizeable onResize={this.updateWindowDimensions}>
|
<Resizeable onResize={this.handleCellResize}>
|
||||||
<GridLayout
|
<GridLayout
|
||||||
layout={cells}
|
layout={cells}
|
||||||
cols={12}
|
cols={12}
|
||||||
|
@ -110,6 +107,7 @@ class LayoutRenderer extends Component {
|
||||||
host={host}
|
host={host}
|
||||||
source={source}
|
source={source}
|
||||||
onZoom={onZoom}
|
onZoom={onZoom}
|
||||||
|
sources={sources}
|
||||||
templates={templates}
|
templates={templates}
|
||||||
timeRange={timeRange}
|
timeRange={timeRange}
|
||||||
isEditable={isEditable}
|
isEditable={isEditable}
|
||||||
|
@ -172,6 +170,7 @@ LayoutRenderer.propTypes = {
|
||||||
isEditable: bool,
|
isEditable: bool,
|
||||||
onCancelEditCell: func,
|
onCancelEditCell: func,
|
||||||
onZoom: func,
|
onZoom: func,
|
||||||
|
sources: arrayOf(shape({})),
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LayoutRenderer
|
export default LayoutRenderer
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, {PropTypes} from 'react'
|
import React, {PropTypes} from 'react'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
|
import _ from 'lodash'
|
||||||
|
|
||||||
import {showMeasurements} from 'shared/apis/metaQuery'
|
import {showMeasurements} from 'shared/apis/metaQuery'
|
||||||
import showMeasurementsParser from 'shared/parsing/showMeasurements'
|
import showMeasurementsParser from 'shared/parsing/showMeasurements'
|
||||||
|
@ -19,6 +20,11 @@ const MeasurementList = React.createClass({
|
||||||
onChooseTag: func.isRequired,
|
onChooseTag: func.isRequired,
|
||||||
onToggleTagAcceptance: func.isRequired,
|
onToggleTagAcceptance: func.isRequired,
|
||||||
onGroupByTag: func.isRequired,
|
onGroupByTag: func.isRequired,
|
||||||
|
querySource: shape({
|
||||||
|
links: shape({
|
||||||
|
proxy: string.isRequired,
|
||||||
|
}).isRequired,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
|
|
||||||
contextTypes: {
|
contextTypes: {
|
||||||
|
@ -36,6 +42,12 @@ const MeasurementList = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getDefaultProps() {
|
||||||
|
return {
|
||||||
|
querySource: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (!this.props.query.database) {
|
if (!this.props.query.database) {
|
||||||
return
|
return
|
||||||
|
@ -45,13 +57,16 @@ const MeasurementList = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
const {query} = this.props
|
const {query, querySource} = this.props
|
||||||
|
|
||||||
if (!query.database) {
|
if (!query.database) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prevProps.query.database === query.database) {
|
if (
|
||||||
|
prevProps.query.database === query.database &&
|
||||||
|
_.isEqual(prevProps.querySource, querySource)
|
||||||
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +196,11 @@ const MeasurementList = React.createClass({
|
||||||
|
|
||||||
_getMeasurements() {
|
_getMeasurements() {
|
||||||
const {source} = this.context
|
const {source} = this.context
|
||||||
const proxy = source.links.proxy
|
const {querySource} = this.props
|
||||||
|
|
||||||
|
const proxy =
|
||||||
|
_.get(querySource, ['links', 'proxy'], null) || source.links.proxy
|
||||||
|
|
||||||
showMeasurements(proxy, this.props.query.database).then(resp => {
|
showMeasurements(proxy, this.props.query.database).then(resp => {
|
||||||
const {errors, measurementSets} = showMeasurementsParser(resp.data)
|
const {errors, measurementSets} = showMeasurementsParser(resp.data)
|
||||||
if (errors.length) {
|
if (errors.length) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ const actionBinder = (id, action) => item => action(id, item)
|
||||||
const SchemaExplorer = ({
|
const SchemaExplorer = ({
|
||||||
query,
|
query,
|
||||||
query: {id},
|
query: {id},
|
||||||
|
source,
|
||||||
actions: {
|
actions: {
|
||||||
chooseTag,
|
chooseTag,
|
||||||
groupByTag,
|
groupByTag,
|
||||||
|
@ -24,17 +25,22 @@ const SchemaExplorer = ({
|
||||||
<div className="query-builder">
|
<div className="query-builder">
|
||||||
<DatabaseList
|
<DatabaseList
|
||||||
query={query}
|
query={query}
|
||||||
|
querySource={source}
|
||||||
onChooseNamespace={actionBinder(id, chooseNamespace)}
|
onChooseNamespace={actionBinder(id, chooseNamespace)}
|
||||||
/>
|
/>
|
||||||
<MeasurementList
|
<MeasurementList
|
||||||
|
source={source}
|
||||||
query={query}
|
query={query}
|
||||||
|
querySource={source}
|
||||||
onChooseTag={actionBinder(id, chooseTag)}
|
onChooseTag={actionBinder(id, chooseTag)}
|
||||||
onGroupByTag={actionBinder(id, groupByTag)}
|
onGroupByTag={actionBinder(id, groupByTag)}
|
||||||
onChooseMeasurement={actionBinder(id, chooseMeasurement)}
|
onChooseMeasurement={actionBinder(id, chooseMeasurement)}
|
||||||
onToggleTagAcceptance={actionBinder(id, toggleTagAcceptance)}
|
onToggleTagAcceptance={actionBinder(id, toggleTagAcceptance)}
|
||||||
/>
|
/>
|
||||||
<FieldList
|
<FieldList
|
||||||
|
source={source}
|
||||||
query={query}
|
query={query}
|
||||||
|
querySource={source}
|
||||||
onToggleField={actionBinder(id, toggleFieldWithGroupByInterval)}
|
onToggleField={actionBinder(id, toggleFieldWithGroupByInterval)}
|
||||||
onFill={actionBinder(id, fill)}
|
onFill={actionBinder(id, fill)}
|
||||||
onGroupByTime={actionBinder(id, groupByTime)}
|
onGroupByTime={actionBinder(id, groupByTime)}
|
||||||
|
@ -60,6 +66,7 @@ SchemaExplorer.propTypes = {
|
||||||
fill: func.isRequired,
|
fill: func.isRequired,
|
||||||
editRawTextAsync: func.isRequired,
|
editRawTextAsync: func.isRequired,
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
|
source: shape({}),
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SchemaExplorer
|
export default SchemaExplorer
|
||||||
|
|
|
@ -1,26 +1,32 @@
|
||||||
import React, {PropTypes} from 'react'
|
import React, {PropTypes} from 'react'
|
||||||
|
import _ from 'lodash'
|
||||||
|
import uuid from 'node-uuid'
|
||||||
|
|
||||||
import ReactTooltip from 'react-tooltip'
|
import ReactTooltip from 'react-tooltip'
|
||||||
|
|
||||||
const SourceIndicator = React.createClass({
|
const SourceIndicator = ({sourceOverride}, {source: {name, url}}) => {
|
||||||
propTypes: {
|
const sourceName = _.get(sourceOverride, 'name', null)
|
||||||
sourceName: PropTypes.string,
|
? sourceOverride.name
|
||||||
},
|
: name
|
||||||
|
const sourceUrl = _.get(sourceOverride, 'url', null)
|
||||||
|
? sourceOverride.url
|
||||||
|
: url
|
||||||
|
|
||||||
render() {
|
|
||||||
const {sourceName} = this.props
|
|
||||||
if (!sourceName) {
|
if (!sourceName) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const sourceNameTooltip = `Connected to <code>${sourceName}</code>`
|
const sourceNameTooltip = `<h1>Connected to Source:</h1><p><code>${sourceName} @ ${sourceUrl}</code></p>`
|
||||||
|
const uuidTooltip = uuid.v4()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="source-indicator"
|
className="source-indicator"
|
||||||
data-for="source-indicator-tooltip"
|
data-for={uuidTooltip}
|
||||||
data-tip={sourceNameTooltip}
|
data-tip={sourceNameTooltip}
|
||||||
>
|
>
|
||||||
<span className="icon server2" />
|
<span className="icon server2" />
|
||||||
<ReactTooltip
|
<ReactTooltip
|
||||||
id="source-indicator-tooltip"
|
id={uuidTooltip}
|
||||||
effect="solid"
|
effect="solid"
|
||||||
html={true}
|
html={true}
|
||||||
offset={{top: 2}}
|
offset={{top: 2}}
|
||||||
|
@ -29,7 +35,22 @@ const SourceIndicator = React.createClass({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
})
|
|
||||||
|
const {shape, string} = PropTypes
|
||||||
|
|
||||||
|
SourceIndicator.propTypes = {
|
||||||
|
sourceOverride: shape({
|
||||||
|
name: string,
|
||||||
|
url: string,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceIndicator.contextTypes = {
|
||||||
|
source: shape({
|
||||||
|
name: string,
|
||||||
|
url: string,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
export default SourceIndicator
|
export default SourceIndicator
|
||||||
|
|
|
@ -62,7 +62,7 @@ class ManageSources extends Component {
|
||||||
<h1 className="page-header__title">Configuration</h1>
|
<h1 className="page-header__title">Configuration</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="page-header__right">
|
<div className="page-header__right">
|
||||||
<SourceIndicator sourceName={source.name} />
|
<SourceIndicator />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -125,7 +125,7 @@ export const SourcePage = React.createClass({
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="page-header__right">
|
<div className="page-header__right">
|
||||||
<SourceIndicator sourceName={source.name} />
|
<SourceIndicator />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -56,7 +56,7 @@ class StatusPage extends Component {
|
||||||
<h1 className="page-header__title">Status</h1>
|
<h1 className="page-header__title">Status</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="page-header__right">
|
<div className="page-header__right">
|
||||||
<SourceIndicator sourceName={source.name} />
|
<SourceIndicator />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
@import 'components/resizer';
|
@import 'components/resizer';
|
||||||
@import 'components/search-widget';
|
@import 'components/search-widget';
|
||||||
@import 'components/source-indicator';
|
@import 'components/source-indicator';
|
||||||
|
@import 'components/source-selector';
|
||||||
@import 'components/tables';
|
@import 'components/tables';
|
||||||
|
|
||||||
// Pages
|
// Pages
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
flex: 1 0 0;
|
flex: 1 0 0;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
|
|
||||||
&:last-child { margin-right: 0; }
|
|
||||||
}
|
}
|
||||||
.display-options--cellx2 {
|
.display-options--cellx2 {
|
||||||
flex: 2 0 0;
|
flex: 2 0 0;
|
||||||
|
@ -29,8 +27,6 @@
|
||||||
color: $g11-sidewalk;
|
color: $g11-sidewalk;
|
||||||
@include no-user-select();
|
@include no-user-select();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.viz-type-selector {
|
.viz-type-selector {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
|
@ -33,6 +33,15 @@ $tooltip-code-color: $c-potassium;
|
||||||
text-transform: none !important;
|
text-transform: none !important;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0 0 6px 0;
|
||||||
|
line-height: 1.125em;
|
||||||
|
letter-spacing: 0;
|
||||||
|
font-family: $default-font;
|
||||||
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -70,7 +79,6 @@ $tooltip-code-color: $c-potassium;
|
||||||
border-color: transparent transparent $tooltip-accent transparent !important;
|
border-color: transparent transparent $tooltip-accent transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Kapacitor Style Tooltip */
|
/* Kapacitor Style Tooltip */
|
||||||
&.kapacitor-tooltip {
|
&.kapacitor-tooltip {
|
||||||
border-color: $c-rainforest !important;
|
border-color: $c-rainforest !important;
|
||||||
|
@ -90,14 +98,13 @@ $tooltip-code-color: $c-potassium;
|
||||||
|
|
||||||
.influx-tooltip__hover {
|
.influx-tooltip__hover {
|
||||||
@extend .influx-tooltip;
|
@extend .influx-tooltip;
|
||||||
pointer-events: auto!important;
|
pointer-events: auto !important;
|
||||||
&:hover {
|
&:hover {
|
||||||
visibility: visible!important;
|
visibility: visible !important;
|
||||||
opacity: 1!important;
|
opacity: 1 !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Question Mark Tooltip
|
Question Mark Tooltip
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
@ -121,8 +128,7 @@ $qmark-tooltip-size: 15px;
|
||||||
background-color: $g10-wolf;
|
background-color: $g10-wolf;
|
||||||
color: $g0-obsidian;
|
color: $g0-obsidian;
|
||||||
margin: 0 5px;
|
margin: 0 5px;
|
||||||
transition:
|
transition: background-color 0.25s ease;
|
||||||
background-color 0.25s ease;
|
|
||||||
}
|
}
|
||||||
.question-mark-tooltip:hover {
|
.question-mark-tooltip:hover {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
Source Selector component styles
|
||||||
|
----------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
.source-selector {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
flex: 1 0 0;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 0 4px 0 0;
|
||||||
|
font-size: 17px;
|
||||||
|
color: $g13-mist;
|
||||||
|
@include no-user-select();
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,22 +11,49 @@ $dash-graph-options-arrow: 8px;
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@keyframes refreshingSpinnerA {
|
@keyframes refreshingSpinnerA {
|
||||||
0% { transform: translate(-50%,-50%) scale(1.75); background-color: $g7-graphite; }
|
0% {
|
||||||
33% { transform: translate(-50%,-50%) scale(1,1); }
|
transform: translate(-50%, -50%) scale(1.75);
|
||||||
66% { transform: translate(-50%,-50%) scale(1,1); }
|
background-color: $g7-graphite;
|
||||||
100% { transform: translate(-50%,-50%) scale(1,1); }
|
}
|
||||||
|
33% {
|
||||||
|
transform: translate(-50%, -50%) scale(1, 1);
|
||||||
|
}
|
||||||
|
66% {
|
||||||
|
transform: translate(-50%, -50%) scale(1, 1);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate(-50%, -50%) scale(1, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@keyframes refreshingSpinnerB {
|
@keyframes refreshingSpinnerB {
|
||||||
0% { transform: translate(-50%,-50%) scale(1,1); }
|
0% {
|
||||||
33% { transform: translate(-50%,-50%) scale(1.75); background-color: $g7-graphite; }
|
transform: translate(-50%, -50%) scale(1, 1);
|
||||||
66% { transform: translate(-50%,-50%) scale(1,1); }
|
}
|
||||||
100% { transform: translate(-50%,-50%) scale(1,1); }
|
33% {
|
||||||
|
transform: translate(-50%, -50%) scale(1.75);
|
||||||
|
background-color: $g7-graphite;
|
||||||
|
}
|
||||||
|
66% {
|
||||||
|
transform: translate(-50%, -50%) scale(1, 1);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate(-50%, -50%) scale(1, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@keyframes refreshingSpinnerC {
|
@keyframes refreshingSpinnerC {
|
||||||
0% { transform: translate(-50%,-50%) scale(1,1); }
|
0% {
|
||||||
33% { transform: translate(-50%,-50%) scale(1,1); }
|
transform: translate(-50%, -50%) scale(1, 1);
|
||||||
66% { transform: translate(-50%,-50%) scale(1.75); background-color: $g7-graphite; }
|
}
|
||||||
100% { transform: translate(-50%,-50%) scale(1,1); }
|
33% {
|
||||||
|
transform: translate(-50%, -50%) scale(1, 1);
|
||||||
|
}
|
||||||
|
66% {
|
||||||
|
transform: translate(-50%, -50%) scale(1.75);
|
||||||
|
background-color: $g7-graphite;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate(-50%, -50%) scale(1, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -93,7 +120,6 @@ $dash-graph-options-arrow: 8px;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
}
|
}
|
||||||
.dygraph .dygraph-child {
|
.dygraph .dygraph-child {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -124,9 +150,7 @@ $dash-graph-options-arrow: 8px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: $g14-chromium;
|
color: $g14-chromium;
|
||||||
transition:
|
transition: color 0.25s ease, background-color 0.25s ease;
|
||||||
color 0.25s ease,
|
|
||||||
background-color 0.25s ease;
|
|
||||||
&.dash-graph--heading-draggable:hover {
|
&.dash-graph--heading-draggable:hover {
|
||||||
cursor: move;
|
cursor: move;
|
||||||
background-color: $g5-pepper;
|
background-color: $g5-pepper;
|
||||||
|
@ -146,30 +170,41 @@ $dash-graph-options-arrow: 8px;
|
||||||
line-height: $dash-graph-heading;
|
line-height: $dash-graph-heading;
|
||||||
width: calc(100% - 53px);
|
width: calc(100% - 53px);
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
transition:
|
transition: color 0.25s ease, background-color 0.25s ease,
|
||||||
color 0.25s ease,
|
|
||||||
background-color 0.25s ease,
|
|
||||||
border-color 0.25s ease;
|
border-color 0.25s ease;
|
||||||
}
|
}
|
||||||
.dash-graph--name.dash-graph--name__default {
|
.dash-graph--name.dash-graph--name__default {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
.dash-graph--custom-indicators {
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 3px;
|
||||||
|
position: absolute;
|
||||||
|
top: 3px;
|
||||||
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
.dash-graph--custom-time {
|
> .custom-indicator,
|
||||||
|
> .source-indicator {
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 24px;
|
||||||
|
padding: 0 7px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-family: $code-font;
|
font-family: $code-font;
|
||||||
color: $c-pool;
|
color: $c-pool;
|
||||||
background-color: $g2-kevlar;
|
background-color: $g2-kevlar;
|
||||||
height: 24px;
|
margin-right: 2px;
|
||||||
font-size: 10px;
|
|
||||||
line-height: 24px;
|
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 0 7px;
|
}
|
||||||
position: absolute;
|
> .source-indicator {
|
||||||
top: 3px;
|
height: 24px;
|
||||||
right: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
> .icon {
|
||||||
|
font-size: 12px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.dash-graph-context {
|
.dash-graph-context {
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -187,9 +222,7 @@ $dash-graph-options-arrow: 8px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
position: relative;
|
position: relative;
|
||||||
color: $g11-sidewalk;
|
color: $g11-sidewalk;
|
||||||
transition:
|
transition: color 0.25s ease, background-color 0.25s ease;
|
||||||
color 0.25s ease,
|
|
||||||
background-color 0.25s ease;
|
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&.active {
|
&.active {
|
||||||
|
@ -197,13 +230,15 @@ $dash-graph-options-arrow: 8px;
|
||||||
color: $g20-white;
|
color: $g20-white;
|
||||||
background-color: $g5-pepper;
|
background-color: $g5-pepper;
|
||||||
}
|
}
|
||||||
&:first-child {margin-right: 2px;}
|
&:first-child {
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
> .icon {
|
> .icon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%,-50%);
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.dash-graph-context--confirm {
|
.dash-graph-context--confirm {
|
||||||
|
@ -230,7 +265,7 @@ $dash-graph-options-arrow: 8px;
|
||||||
border-bottom-color: $c-curacao;
|
border-bottom-color: $c-curacao;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 0;
|
top: 0;
|
||||||
transform: translate(-50%,-100%);
|
transform: translate(-50%, -100%);
|
||||||
transition: border-color 0.25s ease;
|
transition: border-color 0.25s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +276,6 @@ $dash-graph-options-arrow: 8px;
|
||||||
&:hover:before {
|
&:hover:before {
|
||||||
border-bottom-color: $c-dreamsicle;
|
border-bottom-color: $c-dreamsicle;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Presentation Mode */
|
/* Presentation Mode */
|
||||||
|
@ -257,7 +291,7 @@ $dash-graph-options-arrow: 8px;
|
||||||
.graph-panel__refreshing {
|
.graph-panel__refreshing {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -18px !important;
|
top: -18px !important;
|
||||||
transform: translate(0,0);
|
transform: translate(0, 0);
|
||||||
right: 50%;
|
right: 50%;
|
||||||
transform: translateX(50%);
|
transform: translateX(50%);
|
||||||
width: 16px;
|
width: 16px;
|
||||||
|
@ -270,12 +304,24 @@ $dash-graph-options-arrow: 8px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translate(-50%,-50%);
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
div:nth-child(1) {left: 0; animation: refreshingSpinnerA 0.8s cubic-bezier(0.645, 0.045, 0.355, 1) infinite; }
|
div:nth-child(1) {
|
||||||
div:nth-child(2) {left: 50%; animation: refreshingSpinnerB 0.8s cubic-bezier(0.645, 0.045, 0.355, 1) infinite; }
|
left: 0;
|
||||||
div:nth-child(3) {left: 100%; animation: refreshingSpinnerC 0.8s cubic-bezier(0.645, 0.045, 0.355, 1) infinite;}
|
animation: refreshingSpinnerA 0.8s cubic-bezier(0.645, 0.045, 0.355, 1)
|
||||||
|
infinite;
|
||||||
|
}
|
||||||
|
div:nth-child(2) {
|
||||||
|
left: 50%;
|
||||||
|
animation: refreshingSpinnerB 0.8s cubic-bezier(0.645, 0.045, 0.355, 1)
|
||||||
|
infinite;
|
||||||
|
}
|
||||||
|
div:nth-child(3) {
|
||||||
|
left: 100%;
|
||||||
|
animation: refreshingSpinnerC 0.8s cubic-bezier(0.645, 0.045, 0.355, 1)
|
||||||
|
infinite;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -291,7 +337,7 @@ $dash-graph-options-arrow: 8px;
|
||||||
}
|
}
|
||||||
.react-grid-item {
|
.react-grid-item {
|
||||||
&.resizing {
|
&.resizing {
|
||||||
background-color: fade-out($g3-castle,0.09);
|
background-color: fade-out($g3-castle, 0.09);
|
||||||
border-color: $c-pool;
|
border-color: $c-pool;
|
||||||
border-image-slice: 3%;
|
border-image-slice: 3%;
|
||||||
border-image-repeat: initial;
|
border-image-repeat: initial;
|
||||||
|
@ -301,13 +347,14 @@ $dash-graph-options-arrow: 8px;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
|
|
||||||
& > .react-resizable-handle {
|
& > .react-resizable-handle {
|
||||||
&:before, &:after {
|
&:before,
|
||||||
|
&:after {
|
||||||
background-color: $c-comet;
|
background-color: $c-comet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.react-draggable-dragging {
|
&.react-draggable-dragging {
|
||||||
background-color: fade-out($g3-castle,0.09);
|
background-color: fade-out($g3-castle, 0.09);
|
||||||
border-color: $c-pool;
|
border-color: $c-pool;
|
||||||
border-image-slice: 3%;
|
border-image-slice: 3%;
|
||||||
border-image-repeat: initial;
|
border-image-repeat: initial;
|
||||||
|
@ -341,14 +388,15 @@ $dash-graph-options-arrow: 8px;
|
||||||
}
|
}
|
||||||
&:before {
|
&:before {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
transform: translate(-50%,-50%) rotate(-45deg);
|
transform: translate(-50%, -50%) rotate(-45deg);
|
||||||
}
|
}
|
||||||
&:after {
|
&:after {
|
||||||
width: 12px;
|
width: 12px;
|
||||||
transform: translate(-3px,2px) rotate(-45deg);
|
transform: translate(-3px, 2px) rotate(-45deg);
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
&:before, &:after {
|
&:before,
|
||||||
|
&:after {
|
||||||
background-color: $c-comet;
|
background-color: $c-comet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,10 +44,21 @@ $overlay-z: 100;
|
||||||
border: 0;
|
border: 0;
|
||||||
background-color: $g2-kevlar;
|
background-color: $g2-kevlar;
|
||||||
}
|
}
|
||||||
|
.overlay-controls .nav-tablist {
|
||||||
|
width: 200px;
|
||||||
|
|
||||||
|
li {
|
||||||
|
white-space: nowrap;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 1 0 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
.overlay-controls--right {
|
.overlay-controls--right {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
|
justify-content: flex-end;
|
||||||
|
flex: 1 0 0;
|
||||||
|
|
||||||
.toggle {
|
.toggle {
|
||||||
margin: 0 0 0 5px;
|
margin: 0 0 0 5px;
|
||||||
|
|
|
@ -8,7 +8,17 @@ const buildQueries = (proxy, queryConfigs, timeRange) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const queries = statements.filter(s => s.text !== null).map(s => {
|
const queries = statements.filter(s => s.text !== null).map(s => {
|
||||||
return {host: [proxy], text: s.text, id: s.id, queryConfig: s.queryConfig}
|
let queryProxy = ''
|
||||||
|
if (s.queryConfig.source) {
|
||||||
|
queryProxy = `${s.queryConfig.source.links.proxy}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
host: [queryProxy || proxy],
|
||||||
|
text: s.text,
|
||||||
|
id: s.id,
|
||||||
|
queryConfig: s.queryConfig,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return queries
|
return queries
|
||||||
|
|
Loading…
Reference in New Issue