Merge branch 'master' into bugfix/task_enabled_correct_check
commit
e4088ce61a
|
@ -284,6 +284,7 @@ func MarshalDashboard(d chronograf.Dashboard) ([]byte, error) {
|
|||
SortBy: sortBy,
|
||||
Wrapping: c.TableOptions.Wrapping,
|
||||
ColumnNames: columnNames,
|
||||
FixFirstColumn: c.TableOptions.FixFirstColumn,
|
||||
}
|
||||
|
||||
cells[i] = &DashboardCell{
|
||||
|
@ -447,6 +448,7 @@ func UnmarshalDashboard(data []byte, d *chronograf.Dashboard) error {
|
|||
tableOptions.TimeFormat = c.TableOptions.TimeFormat
|
||||
tableOptions.VerticalTimeAxis = c.TableOptions.VerticalTimeAxis
|
||||
tableOptions.Wrapping = c.TableOptions.Wrapping
|
||||
tableOptions.FixFirstColumn = c.TableOptions.FixFirstColumn
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -321,6 +321,7 @@ type TableOptions struct {
|
|||
SortBy *TableColumn `protobuf:"bytes,3,opt,name=sortBy" json:"sortBy,omitempty"`
|
||||
Wrapping string `protobuf:"bytes,4,opt,name=wrapping,proto3" json:"wrapping,omitempty"`
|
||||
ColumnNames []*TableColumn `protobuf:"bytes,5,rep,name=columnNames" json:"columnNames,omitempty"`
|
||||
FixFirstColumn bool `protobuf:"varint,6,opt,name=fixFirstColumn,proto3" json:"fixFirstColumn,omitempty"`
|
||||
}
|
||||
|
||||
func (m *TableOptions) Reset() { *m = TableOptions{} }
|
||||
|
@ -363,6 +364,13 @@ func (m *TableOptions) GetColumnNames() []*TableColumn {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *TableOptions) GetFixFirstColumn() bool {
|
||||
if m != nil {
|
||||
return m.FixFirstColumn
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type TableColumn struct {
|
||||
InternalName string `protobuf:"bytes,1,opt,name=internalName,proto3" json:"internalName,omitempty"`
|
||||
DisplayName string `protobuf:"bytes,2,opt,name=displayName,proto3" json:"displayName,omitempty"`
|
||||
|
@ -1314,103 +1322,104 @@ func init() {
|
|||
func init() { proto.RegisterFile("internal.proto", fileDescriptorInternal) }
|
||||
|
||||
var fileDescriptorInternal = []byte{
|
||||
// 1558 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x5f, 0x6f, 0xdb, 0x46,
|
||||
0x12, 0x07, 0x25, 0x51, 0x12, 0x47, 0x4e, 0xce, 0xe0, 0xf9, 0x12, 0x5e, 0x0e, 0x38, 0xe8, 0x88,
|
||||
0x3b, 0x9c, 0xee, 0x4f, 0x7c, 0x07, 0x05, 0x45, 0x8b, 0xa0, 0x0d, 0x20, 0x5b, 0x6d, 0xea, 0xc6,
|
||||
0x89, 0x9d, 0x95, 0xed, 0x3e, 0x15, 0xc1, 0x4a, 0x1a, 0x49, 0x44, 0x28, 0x92, 0x5d, 0x92, 0xb6,
|
||||
0xd9, 0x0f, 0x53, 0xa0, 0x40, 0xfb, 0x05, 0x8a, 0xbe, 0xf4, 0xa9, 0xef, 0xfd, 0x10, 0x7d, 0xec,
|
||||
0x57, 0x68, 0x1f, 0x8b, 0xd9, 0x5d, 0x52, 0x2b, 0x4b, 0x09, 0x52, 0xa0, 0xe8, 0xdb, 0xfe, 0x66,
|
||||
0x86, 0xb3, 0xf3, 0x7f, 0x96, 0x70, 0x3b, 0x88, 0x32, 0x14, 0x11, 0x0f, 0xf7, 0x13, 0x11, 0x67,
|
||||
0xb1, 0xdb, 0x2e, 0xb1, 0xff, 0x63, 0x0d, 0x9a, 0xa3, 0x38, 0x17, 0x13, 0x74, 0x6f, 0x43, 0xed,
|
||||
0x68, 0xe8, 0x59, 0x5d, 0xab, 0x57, 0x67, 0xb5, 0xa3, 0xa1, 0xeb, 0x42, 0xe3, 0x19, 0x5f, 0xa2,
|
||||
0x57, 0xeb, 0x5a, 0x3d, 0x87, 0xc9, 0x33, 0xd1, 0xce, 0x8a, 0x04, 0xbd, 0xba, 0xa2, 0xd1, 0xd9,
|
||||
0xbd, 0x07, 0xed, 0xf3, 0x94, 0xb4, 0x2d, 0xd1, 0x6b, 0x48, 0x7a, 0x85, 0x89, 0x77, 0xca, 0xd3,
|
||||
0xf4, 0x2a, 0x16, 0x53, 0xcf, 0x56, 0xbc, 0x12, 0xbb, 0xbb, 0x50, 0x3f, 0x67, 0xc7, 0x5e, 0x53,
|
||||
0x92, 0xe9, 0xe8, 0x7a, 0xd0, 0x1a, 0xe2, 0x8c, 0xe7, 0x61, 0xe6, 0xb5, 0xba, 0x56, 0xaf, 0xcd,
|
||||
0x4a, 0x48, 0x7a, 0xce, 0x30, 0xc4, 0xb9, 0xe0, 0x33, 0xaf, 0xad, 0xf4, 0x94, 0xd8, 0xdd, 0x07,
|
||||
0xf7, 0x28, 0x4a, 0x71, 0x92, 0x0b, 0x1c, 0xbd, 0x0c, 0x92, 0x0b, 0x14, 0xc1, 0xac, 0xf0, 0x1c,
|
||||
0xa9, 0x60, 0x0b, 0x87, 0x6e, 0x79, 0x8a, 0x19, 0xa7, 0xbb, 0x41, 0xaa, 0x2a, 0xa1, 0xeb, 0xc3,
|
||||
0xce, 0x68, 0xc1, 0x05, 0x4e, 0x47, 0x38, 0x11, 0x98, 0x79, 0x1d, 0xc9, 0x5e, 0xa3, 0x91, 0xcc,
|
||||
0x89, 0x98, 0xf3, 0x28, 0xf8, 0x8c, 0x67, 0x41, 0x1c, 0x79, 0x3b, 0x4a, 0xc6, 0xa4, 0x51, 0x94,
|
||||
0x58, 0x1c, 0xa2, 0x77, 0x4b, 0x45, 0x89, 0xce, 0xfe, 0x37, 0x16, 0x38, 0x43, 0x9e, 0x2e, 0xc6,
|
||||
0x31, 0x17, 0xd3, 0x37, 0x8a, 0xf5, 0x7d, 0xb0, 0x27, 0x18, 0x86, 0xa9, 0x57, 0xef, 0xd6, 0x7b,
|
||||
0x9d, 0xfe, 0xdd, 0xfd, 0x2a, 0x89, 0x95, 0x9e, 0x43, 0x0c, 0x43, 0xa6, 0xa4, 0xdc, 0xff, 0x83,
|
||||
0x93, 0xe1, 0x32, 0x09, 0x79, 0x86, 0xa9, 0xd7, 0x90, 0x9f, 0xb8, 0xab, 0x4f, 0xce, 0x34, 0x8b,
|
||||
0xad, 0x84, 0x36, 0x5c, 0xb1, 0x37, 0x5d, 0xf1, 0xbf, 0xad, 0xc3, 0xad, 0xb5, 0xeb, 0xdc, 0x1d,
|
||||
0xb0, 0xae, 0xa5, 0xe5, 0x36, 0xb3, 0xae, 0x09, 0x15, 0xd2, 0x6a, 0x9b, 0x59, 0x05, 0xa1, 0x2b,
|
||||
0x59, 0x1b, 0x36, 0xb3, 0xae, 0x08, 0x2d, 0x64, 0x45, 0xd8, 0xcc, 0x5a, 0xb8, 0xff, 0x82, 0xd6,
|
||||
0xa7, 0x39, 0x8a, 0x00, 0x53, 0xcf, 0x96, 0xd6, 0xfd, 0x61, 0x65, 0xdd, 0xf3, 0x1c, 0x45, 0xc1,
|
||||
0x4a, 0x3e, 0x45, 0x43, 0x56, 0x93, 0x2a, 0x0d, 0x79, 0x26, 0x5a, 0x46, 0x95, 0xd7, 0x52, 0x34,
|
||||
0x3a, 0xeb, 0x28, 0xaa, 0x7a, 0xa0, 0x28, 0xbe, 0x05, 0x0d, 0x7e, 0x8d, 0xa9, 0xe7, 0x48, 0xfd,
|
||||
0x7f, 0x7b, 0x45, 0xc0, 0xf6, 0x07, 0xd7, 0x98, 0xbe, 0x1f, 0x65, 0xa2, 0x60, 0x52, 0xdc, 0xfd,
|
||||
0x27, 0x34, 0x27, 0x71, 0x18, 0x8b, 0xd4, 0x83, 0x9b, 0x86, 0x1d, 0x12, 0x9d, 0x69, 0xb6, 0xdb,
|
||||
0x83, 0x66, 0x88, 0x73, 0x8c, 0xa6, 0xb2, 0x32, 0x3a, 0xfd, 0xdd, 0x95, 0xe0, 0xb1, 0xa4, 0x33,
|
||||
0xcd, 0x77, 0x1f, 0xc2, 0x4e, 0xc6, 0xc7, 0x21, 0x9e, 0x24, 0x14, 0xc5, 0x54, 0x56, 0x49, 0xa7,
|
||||
0x7f, 0xc7, 0xc8, 0x87, 0xc1, 0x65, 0x6b, 0xb2, 0xf7, 0x1e, 0x83, 0x53, 0x59, 0x48, 0x4d, 0xf2,
|
||||
0x12, 0x0b, 0x19, 0x6f, 0x87, 0xd1, 0xd1, 0xfd, 0x3b, 0xd8, 0x97, 0x3c, 0xcc, 0x55, 0xad, 0x74,
|
||||
0xfa, 0xb7, 0x57, 0x3a, 0x07, 0xd7, 0x41, 0xca, 0x14, 0xf3, 0x61, 0xed, 0x1d, 0xcb, 0xff, 0xc1,
|
||||
0x82, 0x1d, 0xf3, 0x1e, 0xf7, 0xaf, 0x00, 0x59, 0xb0, 0xc4, 0x0f, 0x62, 0xb1, 0xe4, 0x99, 0xd6,
|
||||
0x69, 0x50, 0xdc, 0x7f, 0xc3, 0xee, 0x25, 0x8a, 0x2c, 0x98, 0xf0, 0xf0, 0x2c, 0x58, 0x22, 0xe9,
|
||||
0x93, 0xb7, 0xb4, 0xd9, 0x06, 0xdd, 0xbd, 0x0f, 0xcd, 0x34, 0x16, 0xd9, 0x41, 0x21, 0xf3, 0xdd,
|
||||
0xe9, 0xff, 0xe9, 0x86, 0x6f, 0x87, 0x71, 0x98, 0x2f, 0x23, 0xa6, 0x85, 0xa8, 0x81, 0xaf, 0x04,
|
||||
0x4f, 0x92, 0x20, 0x9a, 0x97, 0x43, 0xa2, 0xc4, 0xee, 0xdb, 0xd0, 0x99, 0x48, 0x69, 0x2a, 0xfb,
|
||||
0xb2, 0x3a, 0x5e, 0xa1, 0xcf, 0x94, 0xf4, 0x47, 0xd0, 0x31, 0x78, 0x54, 0xcf, 0xe5, 0x37, 0xb2,
|
||||
0x99, 0x94, 0x83, 0x6b, 0x34, 0xb7, 0x0b, 0x9d, 0x69, 0x90, 0x26, 0x21, 0x2f, 0x8c, 0x7e, 0x33,
|
||||
0x49, 0xfe, 0x1c, 0x6c, 0x99, 0x75, 0xa3, 0x47, 0x9d, 0xb2, 0x47, 0xe5, 0xec, 0xab, 0x19, 0xb3,
|
||||
0x6f, 0x17, 0xea, 0x1f, 0xe2, 0xb5, 0x1e, 0x87, 0x74, 0xac, 0x3a, 0xb9, 0x61, 0x74, 0xf2, 0x1e,
|
||||
0xd8, 0x17, 0x32, 0x65, 0xaa, 0xc3, 0x14, 0xf0, 0x1f, 0x41, 0x53, 0x55, 0x4d, 0xa5, 0xd9, 0x32,
|
||||
0x34, 0x77, 0xa1, 0x73, 0x22, 0x02, 0x8c, 0x32, 0xd5, 0x9b, 0xda, 0x50, 0x83, 0xe4, 0x7f, 0x6d,
|
||||
0x41, 0x43, 0xa6, 0xc2, 0x87, 0x9d, 0x10, 0xe7, 0x7c, 0x52, 0x1c, 0xc4, 0x79, 0x34, 0x4d, 0x3d,
|
||||
0xab, 0x5b, 0xef, 0xd5, 0xd9, 0x1a, 0xcd, 0xbd, 0x03, 0xcd, 0xb1, 0xe2, 0xd6, 0xba, 0xf5, 0x9e,
|
||||
0xc3, 0x34, 0x22, 0xd3, 0x42, 0x3e, 0xc6, 0x50, 0xbb, 0xa0, 0x00, 0x49, 0x27, 0x02, 0x67, 0xc1,
|
||||
0xb5, 0x76, 0x43, 0x23, 0xa2, 0xa7, 0xf9, 0x8c, 0xe8, 0xca, 0x13, 0x8d, 0xc8, 0x81, 0x31, 0x4f,
|
||||
0xab, 0x86, 0xa5, 0x33, 0x69, 0x4e, 0x27, 0x3c, 0x2c, 0x3b, 0x56, 0x01, 0xff, 0x3b, 0x8b, 0x26,
|
||||
0xb9, 0x9a, 0x40, 0x1b, 0x11, 0xfe, 0x33, 0xb4, 0x69, 0x3a, 0xbd, 0xb8, 0xe4, 0x42, 0x3b, 0xdc,
|
||||
0x22, 0x7c, 0xc1, 0x85, 0xfb, 0x3f, 0x68, 0xca, 0xc2, 0xde, 0x32, 0x0d, 0x4b, 0x75, 0x32, 0xaa,
|
||||
0x4c, 0x8b, 0x55, 0xf3, 0xa2, 0x61, 0xcc, 0x8b, 0xca, 0x59, 0xdb, 0x74, 0xf6, 0x3e, 0xd8, 0x34,
|
||||
0x78, 0x0a, 0x69, 0xfd, 0x56, 0xcd, 0x6a, 0x3c, 0x29, 0x29, 0xff, 0x1c, 0x6e, 0xad, 0xdd, 0x58,
|
||||
0xdd, 0x64, 0xad, 0xdf, 0xb4, 0x6a, 0x52, 0x47, 0x37, 0x25, 0x35, 0x41, 0x8a, 0x21, 0x4e, 0x32,
|
||||
0x9c, 0xca, 0x78, 0xb7, 0x59, 0x85, 0xfd, 0x2f, 0xac, 0x95, 0x5e, 0x79, 0x1f, 0xed, 0xa9, 0x49,
|
||||
0xbc, 0x5c, 0xf2, 0x68, 0xaa, 0x55, 0x97, 0x90, 0xe2, 0x36, 0x1d, 0x6b, 0xd5, 0xb5, 0xe9, 0x98,
|
||||
0xb0, 0x48, 0x74, 0x06, 0x6b, 0x22, 0xa1, 0xda, 0x59, 0x22, 0x4f, 0x73, 0x81, 0x4b, 0x8c, 0x32,
|
||||
0x1d, 0x02, 0x93, 0xe4, 0xde, 0x85, 0x56, 0xc6, 0xe7, 0x2f, 0x68, 0xb4, 0xe8, 0x4c, 0x66, 0x7c,
|
||||
0xfe, 0x04, 0x0b, 0xf7, 0x2f, 0xe0, 0xcc, 0x02, 0x0c, 0xa7, 0x92, 0xa5, 0xd2, 0xd9, 0x96, 0x84,
|
||||
0x27, 0x58, 0xf8, 0x3f, 0x5b, 0xd0, 0x1c, 0xa1, 0xb8, 0x44, 0xf1, 0x46, 0x0b, 0xcc, 0x7c, 0x18,
|
||||
0xd4, 0x5f, 0xf3, 0x30, 0x68, 0x6c, 0x7f, 0x18, 0xd8, 0xab, 0x87, 0xc1, 0x1e, 0xd8, 0x23, 0x31,
|
||||
0x39, 0x1a, 0x4a, 0x8b, 0xea, 0x4c, 0x01, 0xaa, 0xc6, 0xc1, 0x24, 0x0b, 0x2e, 0x51, 0xbf, 0x16,
|
||||
0x34, 0xda, 0xd8, 0x6b, 0xed, 0x2d, 0x2b, 0xfa, 0x57, 0x3e, 0x1a, 0xfc, 0xcf, 0x2d, 0x68, 0x1e,
|
||||
0xf3, 0x22, 0xce, 0xb3, 0x8d, 0xaa, 0xed, 0x42, 0x67, 0x90, 0x24, 0x61, 0x30, 0x59, 0xeb, 0x54,
|
||||
0x83, 0x44, 0x12, 0x4f, 0x8d, 0x7c, 0xa8, 0x58, 0x98, 0x24, 0x1a, 0xea, 0x87, 0x72, 0xd7, 0xab,
|
||||
0xc5, 0x6d, 0x0c, 0x75, 0xb5, 0xe2, 0x25, 0x93, 0x82, 0x36, 0xc8, 0xb3, 0x78, 0x16, 0xc6, 0x57,
|
||||
0x32, 0x3a, 0x6d, 0x56, 0x61, 0xff, 0xfb, 0x1a, 0x34, 0x7e, 0xaf, 0xfd, 0xbc, 0x03, 0x56, 0xa0,
|
||||
0x8b, 0xc3, 0x0a, 0xaa, 0x6d, 0xdd, 0x32, 0xb6, 0xb5, 0x07, 0xad, 0x42, 0xf0, 0x68, 0x8e, 0xa9,
|
||||
0xd7, 0x96, 0xd3, 0xa8, 0x84, 0x92, 0x23, 0xfb, 0x4e, 0xad, 0x69, 0x87, 0x95, 0xb0, 0xea, 0x23,
|
||||
0x30, 0xfa, 0xe8, 0xbf, 0x7a, 0xa3, 0x77, 0xa4, 0x45, 0xde, 0x7a, 0x58, 0x6e, 0x2e, 0xf2, 0xdf,
|
||||
0x6e, 0x73, 0xfe, 0x64, 0x81, 0x5d, 0x35, 0xe1, 0xe1, 0x7a, 0x13, 0x1e, 0xae, 0x9a, 0x70, 0x78,
|
||||
0x50, 0x36, 0xe1, 0xf0, 0x80, 0x30, 0x3b, 0x2d, 0x9b, 0x90, 0x9d, 0x52, 0xb2, 0x1e, 0x8b, 0x38,
|
||||
0x4f, 0x0e, 0x0a, 0x95, 0x55, 0x87, 0x55, 0x98, 0x2a, 0xf7, 0xe3, 0x05, 0x0a, 0x1d, 0x6a, 0x87,
|
||||
0x69, 0x44, 0x75, 0x7e, 0x2c, 0x07, 0x94, 0x0a, 0xae, 0x02, 0xee, 0x3f, 0xc0, 0x66, 0x14, 0x3c,
|
||||
0x19, 0xe1, 0xb5, 0xbc, 0x48, 0x32, 0x53, 0x5c, 0x52, 0xaa, 0x5e, 0xf2, 0xba, 0xe0, 0xcb, 0x77,
|
||||
0xfd, 0x7f, 0xa0, 0x39, 0x5a, 0x04, 0xb3, 0xac, 0x7c, 0x17, 0xfd, 0xd1, 0x18, 0x70, 0xc1, 0x12,
|
||||
0x25, 0x8f, 0x69, 0x11, 0xff, 0x39, 0x38, 0x15, 0x71, 0x65, 0x8e, 0x65, 0x9a, 0xe3, 0x42, 0xe3,
|
||||
0x3c, 0x0a, 0xb2, 0xb2, 0xd5, 0xe9, 0x4c, 0xce, 0x3e, 0xcf, 0x79, 0x94, 0x05, 0x59, 0x51, 0xb6,
|
||||
0x7a, 0x89, 0xfd, 0x07, 0xda, 0x7c, 0x52, 0x77, 0x9e, 0x24, 0x28, 0xf4, 0xd8, 0x50, 0x40, 0x5e,
|
||||
0x12, 0x5f, 0xa1, 0x9a, 0xf8, 0x75, 0xa6, 0x80, 0xff, 0x09, 0x38, 0x83, 0x10, 0x45, 0xc6, 0xf2,
|
||||
0x10, 0xb7, 0x6d, 0xe2, 0x8f, 0x46, 0x27, 0xcf, 0x4a, 0x0b, 0xe8, 0xbc, 0x1a, 0x11, 0xf5, 0x1b,
|
||||
0x23, 0xe2, 0x09, 0x4f, 0xf8, 0xd1, 0x50, 0xd6, 0x79, 0x9d, 0x69, 0xe4, 0x7f, 0x69, 0x41, 0x83,
|
||||
0x66, 0x91, 0xa1, 0xba, 0xf1, 0xba, 0x39, 0x76, 0x2a, 0xe2, 0xcb, 0x60, 0x8a, 0xa2, 0x74, 0xae,
|
||||
0xc4, 0x32, 0xe8, 0x93, 0x05, 0x56, 0x0b, 0x5f, 0x23, 0xaa, 0x35, 0x7a, 0xf6, 0x97, 0xbd, 0x64,
|
||||
0xd4, 0x1a, 0x91, 0x99, 0x62, 0xd2, 0x83, 0x6c, 0x94, 0x27, 0x28, 0x06, 0xd3, 0x65, 0x10, 0xc9,
|
||||
0xa4, 0xb7, 0x99, 0x41, 0xf1, 0x1f, 0xa9, 0x1f, 0x89, 0x8d, 0x89, 0x66, 0x6d, 0xff, 0xe9, 0xb8,
|
||||
0x69, 0xb9, 0xff, 0x95, 0x05, 0xad, 0xa7, 0xfa, 0x95, 0x65, 0x7a, 0x61, 0xbd, 0xd2, 0x8b, 0xda,
|
||||
0x9a, 0x17, 0x7d, 0xd8, 0x2b, 0x65, 0xd6, 0xee, 0x57, 0x51, 0xd8, 0xca, 0xd3, 0x11, 0x6d, 0x54,
|
||||
0xc9, 0x7a, 0x93, 0xbf, 0x8c, 0xb3, 0x75, 0x99, 0x6d, 0x09, 0xdf, 0xc8, 0x4a, 0x17, 0x3a, 0xfa,
|
||||
0xef, 0x50, 0xfe, 0x6b, 0xe9, 0xa1, 0x6a, 0x90, 0xfc, 0x3e, 0x34, 0x0f, 0xe3, 0x68, 0x16, 0xcc,
|
||||
0xdd, 0x1e, 0x34, 0x06, 0x79, 0xb6, 0x90, 0x1a, 0x3b, 0xfd, 0x3d, 0xa3, 0xf1, 0xf3, 0x6c, 0xa1,
|
||||
0x64, 0x98, 0x94, 0xf0, 0xdf, 0x05, 0x58, 0xd1, 0x68, 0x4b, 0xac, 0xb2, 0xf1, 0x0c, 0xaf, 0xa8,
|
||||
0x64, 0x52, 0xa9, 0xa5, 0xcd, 0xb6, 0x70, 0xfc, 0xf7, 0xc0, 0x39, 0xc8, 0x83, 0x70, 0x7a, 0x14,
|
||||
0xcd, 0x62, 0x1a, 0x1d, 0x17, 0x28, 0xd2, 0x55, 0xbe, 0x4a, 0x48, 0xe1, 0xa6, 0x29, 0x52, 0xf5,
|
||||
0x90, 0x46, 0xe3, 0xa6, 0xfc, 0x3b, 0x7f, 0xf0, 0x4b, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe8, 0x64,
|
||||
0x6b, 0x1b, 0xaf, 0x0f, 0x00, 0x00,
|
||||
// 1573 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x5f, 0x8f, 0xdb, 0x44,
|
||||
0x10, 0x97, 0x93, 0x38, 0x89, 0x27, 0xd7, 0xe3, 0x64, 0x8e, 0xd6, 0x14, 0x09, 0x05, 0x8b, 0x3f,
|
||||
0xe1, 0x4f, 0x0f, 0x94, 0x0a, 0x81, 0x2a, 0xa8, 0x94, 0xbb, 0xd0, 0x72, 0xf4, 0xda, 0xbb, 0x6e,
|
||||
0xee, 0x8e, 0x27, 0x54, 0x6d, 0x92, 0x4d, 0x62, 0xd5, 0xb1, 0xcd, 0x7a, 0x7d, 0x17, 0xf3, 0x01,
|
||||
0xf8, 0x18, 0x48, 0x48, 0xf0, 0x05, 0x10, 0x2f, 0x3c, 0xf1, 0xce, 0x07, 0xe1, 0x2b, 0xc0, 0x23,
|
||||
0x9a, 0xdd, 0xb5, 0xb3, 0xb9, 0xa4, 0x55, 0x91, 0x10, 0x6f, 0xfb, 0x9b, 0x19, 0xcf, 0xce, 0xce,
|
||||
0xcc, 0x6f, 0x76, 0x0d, 0xdb, 0x41, 0x24, 0x18, 0x8f, 0x68, 0xb8, 0x97, 0xf0, 0x58, 0xc4, 0x6e,
|
||||
0xb3, 0xc0, 0xfe, 0x9f, 0x15, 0xa8, 0x0f, 0xe2, 0x8c, 0x8f, 0x98, 0xbb, 0x0d, 0x95, 0xc3, 0xbe,
|
||||
0x67, 0xb5, 0xad, 0x4e, 0x95, 0x54, 0x0e, 0xfb, 0xae, 0x0b, 0xb5, 0x47, 0x74, 0xce, 0xbc, 0x4a,
|
||||
0xdb, 0xea, 0x38, 0x44, 0xae, 0x51, 0x76, 0x9a, 0x27, 0xcc, 0xab, 0x2a, 0x19, 0xae, 0xdd, 0x9b,
|
||||
0xd0, 0x3c, 0x4b, 0xd1, 0xdb, 0x9c, 0x79, 0x35, 0x29, 0x2f, 0x31, 0xea, 0x4e, 0x68, 0x9a, 0x5e,
|
||||
0xc6, 0x7c, 0xec, 0xd9, 0x4a, 0x57, 0x60, 0x77, 0x07, 0xaa, 0x67, 0xe4, 0xc8, 0xab, 0x4b, 0x31,
|
||||
0x2e, 0x5d, 0x0f, 0x1a, 0x7d, 0x36, 0xa1, 0x59, 0x28, 0xbc, 0x46, 0xdb, 0xea, 0x34, 0x49, 0x01,
|
||||
0xd1, 0xcf, 0x29, 0x0b, 0xd9, 0x94, 0xd3, 0x89, 0xd7, 0x54, 0x7e, 0x0a, 0xec, 0xee, 0x81, 0x7b,
|
||||
0x18, 0xa5, 0x6c, 0x94, 0x71, 0x36, 0x78, 0x1a, 0x24, 0xe7, 0x8c, 0x07, 0x93, 0xdc, 0x73, 0xa4,
|
||||
0x83, 0x0d, 0x1a, 0xdc, 0xe5, 0x21, 0x13, 0x14, 0xf7, 0x06, 0xe9, 0xaa, 0x80, 0xae, 0x0f, 0x5b,
|
||||
0x83, 0x19, 0xe5, 0x6c, 0x3c, 0x60, 0x23, 0xce, 0x84, 0xd7, 0x92, 0xea, 0x15, 0x19, 0xda, 0x1c,
|
||||
0xf3, 0x29, 0x8d, 0x82, 0xef, 0xa8, 0x08, 0xe2, 0xc8, 0xdb, 0x52, 0x36, 0xa6, 0x0c, 0xb3, 0x44,
|
||||
0xe2, 0x90, 0x79, 0xd7, 0x54, 0x96, 0x70, 0xed, 0xff, 0x6a, 0x81, 0xd3, 0xa7, 0xe9, 0x6c, 0x18,
|
||||
0x53, 0x3e, 0x7e, 0xa1, 0x5c, 0xdf, 0x02, 0x7b, 0xc4, 0xc2, 0x30, 0xf5, 0xaa, 0xed, 0x6a, 0xa7,
|
||||
0xd5, 0xbd, 0xb1, 0x57, 0x16, 0xb1, 0xf4, 0x73, 0xc0, 0xc2, 0x90, 0x28, 0x2b, 0xf7, 0x23, 0x70,
|
||||
0x04, 0x9b, 0x27, 0x21, 0x15, 0x2c, 0xf5, 0x6a, 0xf2, 0x13, 0x77, 0xf9, 0xc9, 0xa9, 0x56, 0x91,
|
||||
0xa5, 0xd1, 0xda, 0x51, 0xec, 0xf5, 0xa3, 0xf8, 0xbf, 0x55, 0xe1, 0xda, 0xca, 0x76, 0xee, 0x16,
|
||||
0x58, 0x0b, 0x19, 0xb9, 0x4d, 0xac, 0x05, 0xa2, 0x5c, 0x46, 0x6d, 0x13, 0x2b, 0x47, 0x74, 0x29,
|
||||
0x7b, 0xc3, 0x26, 0xd6, 0x25, 0xa2, 0x99, 0xec, 0x08, 0x9b, 0x58, 0x33, 0xf7, 0x5d, 0x68, 0x7c,
|
||||
0x9b, 0x31, 0x1e, 0xb0, 0xd4, 0xb3, 0x65, 0x74, 0x2f, 0x2d, 0xa3, 0x7b, 0x9c, 0x31, 0x9e, 0x93,
|
||||
0x42, 0x8f, 0xd9, 0x90, 0xdd, 0xa4, 0x5a, 0x43, 0xae, 0x51, 0x26, 0xb0, 0xf3, 0x1a, 0x4a, 0x86,
|
||||
0x6b, 0x9d, 0x45, 0xd5, 0x0f, 0x98, 0xc5, 0x8f, 0xa1, 0x46, 0x17, 0x2c, 0xf5, 0x1c, 0xe9, 0xff,
|
||||
0x8d, 0x67, 0x24, 0x6c, 0xaf, 0xb7, 0x60, 0xe9, 0x17, 0x91, 0xe0, 0x39, 0x91, 0xe6, 0xee, 0x3b,
|
||||
0x50, 0x1f, 0xc5, 0x61, 0xcc, 0x53, 0x0f, 0xae, 0x06, 0x76, 0x80, 0x72, 0xa2, 0xd5, 0x6e, 0x07,
|
||||
0xea, 0x21, 0x9b, 0xb2, 0x68, 0x2c, 0x3b, 0xa3, 0xd5, 0xdd, 0x59, 0x1a, 0x1e, 0x49, 0x39, 0xd1,
|
||||
0x7a, 0xf7, 0x0e, 0x6c, 0x09, 0x3a, 0x0c, 0xd9, 0x71, 0x82, 0x59, 0x4c, 0x65, 0x97, 0xb4, 0xba,
|
||||
0xd7, 0x8d, 0x7a, 0x18, 0x5a, 0xb2, 0x62, 0x7b, 0xf3, 0x3e, 0x38, 0x65, 0x84, 0x48, 0x92, 0xa7,
|
||||
0x2c, 0x97, 0xf9, 0x76, 0x08, 0x2e, 0xdd, 0x37, 0xc1, 0xbe, 0xa0, 0x61, 0xa6, 0x7a, 0xa5, 0xd5,
|
||||
0xdd, 0x5e, 0xfa, 0xec, 0x2d, 0x82, 0x94, 0x28, 0xe5, 0x9d, 0xca, 0xa7, 0x96, 0xff, 0x7d, 0x05,
|
||||
0xb6, 0xcc, 0x7d, 0xdc, 0xd7, 0x01, 0x44, 0x30, 0x67, 0xf7, 0x62, 0x3e, 0xa7, 0x42, 0xfb, 0x34,
|
||||
0x24, 0xee, 0x7b, 0xb0, 0x73, 0xc1, 0xb8, 0x08, 0x46, 0x34, 0x3c, 0x0d, 0xe6, 0x0c, 0xfd, 0xc9,
|
||||
0x5d, 0x9a, 0x64, 0x4d, 0xee, 0xde, 0x82, 0x7a, 0x1a, 0x73, 0xb1, 0x9f, 0xcb, 0x7a, 0xb7, 0xba,
|
||||
0xaf, 0x5c, 0x39, 0xdb, 0x41, 0x1c, 0x66, 0xf3, 0x88, 0x68, 0x23, 0x24, 0xf0, 0x25, 0xa7, 0x49,
|
||||
0x12, 0x44, 0xd3, 0x62, 0x48, 0x14, 0xd8, 0xfd, 0x04, 0x5a, 0x23, 0x69, 0x8d, 0x6d, 0x5f, 0x74,
|
||||
0xc7, 0x33, 0xfc, 0x99, 0x96, 0xee, 0xdb, 0xb0, 0x3d, 0x09, 0x16, 0xf7, 0x02, 0x9e, 0x0a, 0xa5,
|
||||
0x96, 0x1d, 0xd3, 0x24, 0x57, 0xa4, 0xfe, 0x00, 0x5a, 0x86, 0x0f, 0xec, 0xfb, 0xc2, 0xb7, 0x24,
|
||||
0x9d, 0x4a, 0xc4, 0x8a, 0xcc, 0x6d, 0x43, 0x6b, 0x1c, 0xa4, 0x49, 0x48, 0x73, 0x83, 0x97, 0xa6,
|
||||
0xc8, 0x9f, 0x82, 0x2d, 0xbb, 0xc3, 0xe0, 0xb2, 0x53, 0x70, 0x59, 0xce, 0xc8, 0x8a, 0x31, 0x23,
|
||||
0x77, 0xa0, 0xfa, 0x25, 0x5b, 0xe8, 0xb1, 0x89, 0xcb, 0x92, 0xf1, 0x35, 0x83, 0xf1, 0xbb, 0x60,
|
||||
0x9f, 0xcb, 0xd2, 0x2a, 0x26, 0x2a, 0xe0, 0xdf, 0x85, 0xba, 0xea, 0xae, 0xd2, 0xb3, 0x65, 0x78,
|
||||
0x6e, 0x43, 0xeb, 0x98, 0x07, 0x2c, 0x12, 0x8a, 0xc3, 0x3a, 0x50, 0x43, 0xe4, 0xff, 0x62, 0x41,
|
||||
0x4d, 0x96, 0xcc, 0x87, 0xad, 0x90, 0x4d, 0xe9, 0x28, 0xdf, 0x8f, 0xb3, 0x68, 0x9c, 0x7a, 0x56,
|
||||
0xbb, 0xda, 0xa9, 0x92, 0x15, 0x99, 0x7b, 0x1d, 0xea, 0x43, 0xa5, 0xad, 0xb4, 0xab, 0x1d, 0x87,
|
||||
0x68, 0x84, 0xa1, 0x85, 0x74, 0xc8, 0x42, 0x7d, 0x04, 0x05, 0xd0, 0x3a, 0xe1, 0x6c, 0x12, 0x2c,
|
||||
0xf4, 0x31, 0x34, 0x42, 0x79, 0x9a, 0x4d, 0x50, 0xae, 0x4e, 0xa2, 0x11, 0x1e, 0x60, 0x48, 0xd3,
|
||||
0x92, 0xd8, 0xb8, 0x46, 0xcf, 0xe9, 0x88, 0x86, 0x05, 0xb3, 0x15, 0xf0, 0x7f, 0xb7, 0x70, 0xe2,
|
||||
0xab, 0x49, 0xb5, 0x96, 0xe1, 0x57, 0xa1, 0x89, 0x53, 0xec, 0xc9, 0x05, 0xe5, 0xfa, 0xc0, 0x0d,
|
||||
0xc4, 0xe7, 0x94, 0xbb, 0x1f, 0x42, 0x5d, 0x12, 0x60, 0xc3, 0xd4, 0x2c, 0xdc, 0xc9, 0xac, 0x12,
|
||||
0x6d, 0x56, 0xce, 0x95, 0x9a, 0x31, 0x57, 0xca, 0xc3, 0xda, 0xe6, 0x61, 0x6f, 0x81, 0x8d, 0x03,
|
||||
0x2a, 0x97, 0xd1, 0x6f, 0xf4, 0xac, 0xc6, 0x98, 0xb2, 0xf2, 0xcf, 0xe0, 0xda, 0xca, 0x8e, 0xe5,
|
||||
0x4e, 0xd6, 0xea, 0x4e, 0x4b, 0x32, 0x3b, 0x9a, 0xbc, 0x48, 0x96, 0x94, 0x85, 0x6c, 0x24, 0xd8,
|
||||
0x58, 0xe6, 0xbb, 0x49, 0x4a, 0xec, 0xff, 0x68, 0x2d, 0xfd, 0xca, 0xfd, 0xf0, 0x3e, 0x1b, 0xc5,
|
||||
0xf3, 0x39, 0x8d, 0xc6, 0xda, 0x75, 0x01, 0x31, 0x6f, 0xe3, 0xa1, 0x76, 0x5d, 0x19, 0x0f, 0x11,
|
||||
0xf3, 0x44, 0x57, 0xb0, 0xc2, 0x13, 0xec, 0x9d, 0x39, 0xa3, 0x69, 0xc6, 0xd9, 0x9c, 0x45, 0x42,
|
||||
0xa7, 0xc0, 0x14, 0xb9, 0x37, 0xa0, 0x21, 0xe8, 0xf4, 0x09, 0x8e, 0x20, 0x5d, 0x49, 0x41, 0xa7,
|
||||
0x0f, 0x58, 0xee, 0xbe, 0x06, 0xce, 0x24, 0x60, 0xe1, 0x58, 0xaa, 0x54, 0x39, 0x9b, 0x52, 0xf0,
|
||||
0x80, 0xe5, 0xfe, 0xdf, 0x16, 0xd4, 0x07, 0x8c, 0x5f, 0x30, 0xfe, 0x42, 0x17, 0x9d, 0xf9, 0x80,
|
||||
0xa8, 0x3e, 0xe7, 0x01, 0x51, 0xdb, 0xfc, 0x80, 0xb0, 0x97, 0x0f, 0x88, 0x5d, 0xb0, 0x07, 0x7c,
|
||||
0x74, 0xd8, 0x97, 0x11, 0x55, 0x89, 0x02, 0xd8, 0x8d, 0xbd, 0x91, 0x08, 0x2e, 0x98, 0x7e, 0x55,
|
||||
0x68, 0xb4, 0x76, 0xff, 0x35, 0x37, 0x5c, 0xe5, 0xff, 0xf2, 0x71, 0xe1, 0xff, 0x60, 0x41, 0xfd,
|
||||
0x88, 0xe6, 0x71, 0x26, 0xd6, 0xba, 0xb6, 0x0d, 0xad, 0x5e, 0x92, 0x84, 0xc1, 0x68, 0x85, 0xa9,
|
||||
0x86, 0x08, 0x2d, 0x1e, 0x1a, 0xf5, 0x50, 0xb9, 0x30, 0x45, 0x38, 0xfc, 0x0f, 0xe4, 0x9b, 0x40,
|
||||
0x5d, 0xf0, 0xc6, 0xf0, 0x57, 0x4f, 0x01, 0xa9, 0xc4, 0xa4, 0xf5, 0x32, 0x11, 0x4f, 0xc2, 0xf8,
|
||||
0x52, 0x66, 0xa7, 0x49, 0x4a, 0xec, 0xff, 0x51, 0x81, 0xda, 0xff, 0x75, 0x8f, 0x6f, 0x81, 0x15,
|
||||
0xe8, 0xe6, 0xb0, 0x82, 0xf2, 0x56, 0x6f, 0x18, 0xb7, 0xba, 0x07, 0x8d, 0x9c, 0xd3, 0x68, 0xca,
|
||||
0x52, 0xaf, 0x29, 0xa7, 0x51, 0x01, 0xa5, 0x46, 0xf2, 0x4e, 0x5d, 0xe7, 0x0e, 0x29, 0x60, 0xc9,
|
||||
0x23, 0x30, 0x78, 0xf4, 0x81, 0xbe, 0xf9, 0x5b, 0x32, 0x22, 0x6f, 0x35, 0x2d, 0x57, 0x2f, 0xfc,
|
||||
0xff, 0xee, 0x86, 0xfd, 0xcb, 0x02, 0xbb, 0x24, 0xe1, 0xc1, 0x2a, 0x09, 0x0f, 0x96, 0x24, 0xec,
|
||||
0xef, 0x17, 0x24, 0xec, 0xef, 0x23, 0x26, 0x27, 0x05, 0x09, 0xc9, 0x09, 0x16, 0xeb, 0x3e, 0x8f,
|
||||
0xb3, 0x64, 0x3f, 0x57, 0x55, 0x75, 0x48, 0x89, 0xb1, 0x73, 0xbf, 0x9e, 0x31, 0xae, 0x53, 0xed,
|
||||
0x10, 0x8d, 0xb0, 0xcf, 0x8f, 0xe4, 0x80, 0x52, 0xc9, 0x55, 0xc0, 0x7d, 0x0b, 0x6c, 0x82, 0xc9,
|
||||
0x93, 0x19, 0x5e, 0xa9, 0x8b, 0x14, 0x13, 0xa5, 0x45, 0xa7, 0xea, 0xc5, 0xaf, 0x1b, 0xbe, 0x78,
|
||||
0xff, 0xbf, 0x0f, 0xf5, 0xc1, 0x2c, 0x98, 0x88, 0xe2, 0xfd, 0xf4, 0xb2, 0x31, 0xe0, 0x82, 0x39,
|
||||
0x93, 0x3a, 0xa2, 0x4d, 0xfc, 0xc7, 0xe0, 0x94, 0xc2, 0x65, 0x38, 0x96, 0x19, 0x8e, 0x0b, 0xb5,
|
||||
0xb3, 0x28, 0x10, 0x05, 0xd5, 0x71, 0x8d, 0x87, 0x7d, 0x9c, 0xd1, 0x48, 0x04, 0x22, 0x2f, 0xa8,
|
||||
0x5e, 0x60, 0xff, 0xb6, 0x0e, 0x1f, 0xdd, 0x9d, 0x25, 0x09, 0xe3, 0x7a, 0x6c, 0x28, 0x20, 0x37,
|
||||
0x89, 0x2f, 0x99, 0x9a, 0xf8, 0x55, 0xa2, 0x80, 0xff, 0x0d, 0x38, 0xbd, 0x90, 0x71, 0x41, 0xb2,
|
||||
0x90, 0x6d, 0xba, 0x89, 0xbf, 0x1a, 0x1c, 0x3f, 0x2a, 0x22, 0xc0, 0xf5, 0x72, 0x44, 0x54, 0xaf,
|
||||
0x8c, 0x88, 0x07, 0x34, 0xa1, 0x87, 0x7d, 0xd9, 0xe7, 0x55, 0xa2, 0x91, 0xff, 0x93, 0x05, 0x35,
|
||||
0x9c, 0x45, 0x86, 0xeb, 0xda, 0xf3, 0xe6, 0xd8, 0x09, 0x8f, 0x2f, 0x82, 0x31, 0xe3, 0xc5, 0xe1,
|
||||
0x0a, 0x2c, 0x93, 0x3e, 0x9a, 0xb1, 0xf2, 0xc2, 0xd7, 0x08, 0x7b, 0x0d, 0x7f, 0x0f, 0x0a, 0x2e,
|
||||
0x19, 0xbd, 0x86, 0x62, 0xa2, 0x94, 0xf8, 0x70, 0x1b, 0x64, 0x09, 0xe3, 0xbd, 0xf1, 0x3c, 0x28,
|
||||
0x1e, 0x39, 0x86, 0xc4, 0xbf, 0xab, 0x7e, 0x38, 0xd6, 0x26, 0x9a, 0xb5, 0xf9, 0xe7, 0xe4, 0x6a,
|
||||
0xe4, 0xfe, 0xcf, 0x16, 0x34, 0x1e, 0xea, 0xd7, 0x98, 0x79, 0x0a, 0xeb, 0x99, 0xa7, 0xa8, 0xac,
|
||||
0x9c, 0xa2, 0x0b, 0xbb, 0x85, 0xcd, 0xca, 0xfe, 0x2a, 0x0b, 0x1b, 0x75, 0x3a, 0xa3, 0xb5, 0xb2,
|
||||
0x58, 0x2f, 0xf2, 0x37, 0x72, 0xba, 0x6a, 0xb3, 0xa9, 0xe0, 0x6b, 0x55, 0x69, 0x43, 0x4b, 0xff,
|
||||
0x45, 0xca, 0x7f, 0x32, 0x3d, 0x54, 0x0d, 0x91, 0xdf, 0x85, 0xfa, 0x41, 0x1c, 0x4d, 0x82, 0xa9,
|
||||
0xdb, 0x81, 0x5a, 0x2f, 0x13, 0x33, 0xe9, 0xb1, 0xd5, 0xdd, 0x35, 0x88, 0x9f, 0x89, 0x99, 0xb2,
|
||||
0x21, 0xd2, 0xc2, 0xff, 0x0c, 0x60, 0x29, 0xc3, 0x5b, 0x62, 0x59, 0x8d, 0x47, 0xec, 0x12, 0x5b,
|
||||
0x26, 0x95, 0x5e, 0x9a, 0x64, 0x83, 0xc6, 0xff, 0x1c, 0x9c, 0xfd, 0x2c, 0x08, 0xc7, 0x87, 0xd1,
|
||||
0x24, 0xc6, 0xd1, 0x71, 0xce, 0x78, 0xba, 0xac, 0x57, 0x01, 0x31, 0xdd, 0x38, 0x45, 0x4a, 0x0e,
|
||||
0x69, 0x34, 0xac, 0xcb, 0xbf, 0xf8, 0xdb, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0xc4, 0x7e, 0x5e,
|
||||
0x7e, 0xd7, 0x0f, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ message TableOptions {
|
|||
TableColumn sortBy = 3; // which column should a table be sorted by
|
||||
string wrapping = 4; // option for text wrapping
|
||||
repeated TableColumn columnNames = 5; // names and renames for columns
|
||||
bool fixFirstColumn = 6; // first column should be fixed/frozen
|
||||
}
|
||||
|
||||
message TableColumn {
|
||||
|
|
|
@ -573,6 +573,7 @@ type TableOptions struct {
|
|||
SortBy TableColumn `json:"sortBy"`
|
||||
Wrapping string `json:"wrapping"`
|
||||
ColumnNames []TableColumn `json:"columnNames"`
|
||||
FixFirstColumn bool `json:"fixFirstColumn"`
|
||||
}
|
||||
|
||||
// DashboardsStore is the storage and retrieval of dashboards
|
||||
|
|
|
@ -550,7 +550,8 @@ func TestServer(t *testing.T) {
|
|||
"internalName": "",
|
||||
"displayName": ""},
|
||||
"wrapping": "",
|
||||
"columnNames": null
|
||||
"columnNames": null,
|
||||
"fixFirstColumn": false
|
||||
},
|
||||
"links": {
|
||||
"self": "/chronograf/v1/dashboards/1000/cells/8f61c619-dd9b-4761-8aa8-577f27247093"
|
||||
|
@ -799,7 +800,8 @@ func TestServer(t *testing.T) {
|
|||
"displayName":""
|
||||
},
|
||||
"wrapping":"",
|
||||
"columnNames":null
|
||||
"columnNames":null,
|
||||
"fixFirstColumn":false
|
||||
},
|
||||
"legend":{
|
||||
"type": "static",
|
||||
|
|
|
@ -532,7 +532,7 @@ func TestService_ReplaceDashboardCell(t *testing.T) {
|
|||
}
|
||||
}
|
||||
`))),
|
||||
want: `{"i":"3c5c4102-fa40-4585-a8f9-917c77e37192","x":0,"y":0,"w":4,"h":4,"name":"Untitled Cell","queries":[{"query":"SELECT mean(\"usage_user\") AS \"mean_usage_user\" FROM \"telegraf\".\"autogen\".\"cpu\" WHERE time \u003e :dashboardTime: AND \"cpu\"=:cpu: GROUP BY :interval: FILL(null)","queryConfig":{"id":"3cd3eaa4-a4b8-44b3-b69e-0c7bf6b91d9e","database":"telegraf","measurement":"cpu","retentionPolicy":"autogen","fields":[{"value":"mean","type":"func","alias":"mean_usage_user","args":[{"value":"usage_user","type":"field","alias":""}]}],"tags":{"cpu":["ChristohersMBP2.lan"]},"groupBy":{"time":"2s","tags":[]},"areTagsAccepted":true,"fill":"null","rawText":"SELECT mean(\"usage_user\") AS \"mean_usage_user\" FROM \"telegraf\".\"autogen\".\"cpu\" WHERE time \u003e :dashboardTime: AND \"cpu\"=:cpu: GROUP BY :interval: FILL(null)","range":{"upper":"","lower":"now() - 15m"},"shifts":[]},"source":""}],"axes":{"x":{"bounds":["",""],"label":"","prefix":"","suffix":"","base":"","scale":""},"y":{"bounds":["",""],"label":"","prefix":"","suffix":"","base":"","scale":""},"y2":{"bounds":["",""],"label":"","prefix":"","suffix":"","base":"","scale":""}},"type":"line","colors":[{"id":"0","type":"min","hex":"#00C9FF","name":"laser","value":"0"},{"id":"1","type":"max","hex":"#9394FF","name":"comet","value":"100"}],"legend":{},"tableOptions":{"timeFormat":"","verticalTimeAxis":false,"sortBy":{"internalName":"","displayName":""},"wrapping":"","columnNames":null},"links":{"self":"/chronograf/v1/dashboards/1/cells/3c5c4102-fa40-4585-a8f9-917c77e37192"}}
|
||||
want: `{"i":"3c5c4102-fa40-4585-a8f9-917c77e37192","x":0,"y":0,"w":4,"h":4,"name":"Untitled Cell","queries":[{"query":"SELECT mean(\"usage_user\") AS \"mean_usage_user\" FROM \"telegraf\".\"autogen\".\"cpu\" WHERE time \u003e :dashboardTime: AND \"cpu\"=:cpu: GROUP BY :interval: FILL(null)","queryConfig":{"id":"3cd3eaa4-a4b8-44b3-b69e-0c7bf6b91d9e","database":"telegraf","measurement":"cpu","retentionPolicy":"autogen","fields":[{"value":"mean","type":"func","alias":"mean_usage_user","args":[{"value":"usage_user","type":"field","alias":""}]}],"tags":{"cpu":["ChristohersMBP2.lan"]},"groupBy":{"time":"2s","tags":[]},"areTagsAccepted":true,"fill":"null","rawText":"SELECT mean(\"usage_user\") AS \"mean_usage_user\" FROM \"telegraf\".\"autogen\".\"cpu\" WHERE time \u003e :dashboardTime: AND \"cpu\"=:cpu: GROUP BY :interval: FILL(null)","range":{"upper":"","lower":"now() - 15m"},"shifts":[]},"source":""}],"axes":{"x":{"bounds":["",""],"label":"","prefix":"","suffix":"","base":"","scale":""},"y":{"bounds":["",""],"label":"","prefix":"","suffix":"","base":"","scale":""},"y2":{"bounds":["",""],"label":"","prefix":"","suffix":"","base":"","scale":""}},"type":"line","colors":[{"id":"0","type":"min","hex":"#00C9FF","name":"laser","value":"0"},{"id":"1","type":"max","hex":"#9394FF","name":"comet","value":"100"}],"legend":{},"tableOptions":{"timeFormat":"","verticalTimeAxis":false,"sortBy":{"internalName":"","displayName":""},"wrapping":"","columnNames":null,"fixFirstColumn":false},"links":{"self":"/chronograf/v1/dashboards/1/cells/3c5c4102-fa40-4585-a8f9-917c77e37192"}}
|
||||
`,
|
||||
},
|
||||
{
|
||||
|
|
548
ui/.eslintrc
548
ui/.eslintrc
|
@ -1,260 +1,292 @@
|
|||
{
|
||||
"parser": "babel-eslint",
|
||||
plugins: [
|
||||
'react',
|
||||
'prettier',
|
||||
'babel',
|
||||
'jest',
|
||||
],
|
||||
extends: [
|
||||
"prettier",
|
||||
"prettier/react"
|
||||
],
|
||||
env: {
|
||||
browser: true,
|
||||
mocha: true,
|
||||
"jest": true,
|
||||
node: true,
|
||||
es6: true,
|
||||
},
|
||||
globals: {
|
||||
expect: true,
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
arrowFunctions: true,
|
||||
binaryLiterals: true,
|
||||
blockBindings: true,
|
||||
classes: true,
|
||||
defaultParams: false,
|
||||
destructuring: true,
|
||||
forOf: false,
|
||||
generators: false,
|
||||
modules: true,
|
||||
objectLiteralComputedProperties: true,
|
||||
objectLiteralDuplicateProperties: false,
|
||||
objectLiteralShorthandMethods: true,
|
||||
objectLiteralShorthandProperties: true,
|
||||
octalLiterals: false,
|
||||
regexUFlag: false,
|
||||
regexYFlag: false,
|
||||
restParams: true,
|
||||
spread: true,
|
||||
superInFunctions: false,
|
||||
templateStrings: true,
|
||||
unicodeCodePointEscapes: false,
|
||||
globalReturn: false,
|
||||
jsx: true,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'quotes': [1, 'single'],
|
||||
'func-style': 0,
|
||||
'func-names': 0,
|
||||
'arrow-parens': 0,
|
||||
'comma-dangle': [2, 'always-multiline'],
|
||||
'no-cond-assign': 2,
|
||||
'no-console': ['error', {allow: ['error', 'warn']}],
|
||||
'no-constant-condition': 2,
|
||||
'no-control-regex': 2,
|
||||
'no-debugger': 2,
|
||||
'no-dupe-args': 2,
|
||||
'no-dupe-keys': 2,
|
||||
'no-duplicate-case': 2,
|
||||
'no-empty-character-class': 2,
|
||||
'no-empty': 2,
|
||||
'no-ex-assign': 2,
|
||||
'no-extra-boolean-cast': 2,
|
||||
'no-extra-parens': 0,
|
||||
'no-extra-semi': 2,
|
||||
'no-func-assign': 2,
|
||||
'no-inner-declarations': [2, 'both'],
|
||||
'no-invalid-regexp': 2,
|
||||
'no-irregular-whitespace': 2,
|
||||
'no-negated-in-lhs': 2,
|
||||
'no-obj-calls': 2,
|
||||
'no-regex-spaces': 2,
|
||||
'no-sparse-arrays': 2,
|
||||
'no-unexpected-multiline': 2,
|
||||
'no-unreachable': 2,
|
||||
'use-isnan': 2,
|
||||
'valid-jsdoc': 0,
|
||||
'valid-typeof': 2,
|
||||
|
||||
'accessor-pairs': 2,
|
||||
'block-scoped-var': 2,
|
||||
'complexity': 0, // TODO: revisit
|
||||
'consistent-return': 0,
|
||||
'curly': 2,
|
||||
'default-case': 0, // TODO: revisit
|
||||
'dot-location': [2, 'property'],
|
||||
'dot-notation': 2,
|
||||
'eqeqeq': 2,
|
||||
'no-alert': 2,
|
||||
'no-caller': 2,
|
||||
'no-case-declarations': 2,
|
||||
'no-div-regex': 2,
|
||||
'no-else-return': 2,
|
||||
'no-labels': 2,
|
||||
'no-empty-pattern': 2,
|
||||
'no-eq-null': 2,
|
||||
'no-eval': 2,
|
||||
'no-extend-native': 2,
|
||||
'no-extra-bind': 2,
|
||||
'no-fallthrough': 2,
|
||||
'no-floating-decimal': 2,
|
||||
'no-implicit-coercion': 0,
|
||||
'no-implied-eval': 2,
|
||||
'no-iterator': 2,
|
||||
'no-lone-blocks': 2,
|
||||
'no-loop-func': 2,
|
||||
'no-magic-numbers': [0, {ignore: [-1, 0, 1, 2]}],
|
||||
'no-multi-spaces': 2,
|
||||
'no-multi-str': 2,
|
||||
'no-native-reassign': 2,
|
||||
'no-new-func': 2,
|
||||
'no-new-wrappers': 2,
|
||||
'no-new': 2,
|
||||
'no-octal-escape': 2,
|
||||
'no-octal': 2,
|
||||
'no-proto': 2,
|
||||
'no-redeclare': 2,
|
||||
'no-script-url': 2,
|
||||
'no-self-compare': 2,
|
||||
'no-sequences': 2,
|
||||
'no-throw-literal': 2,
|
||||
'no-unused-expressions': 2,
|
||||
'no-useless-call': 2,
|
||||
'no-useless-concat': 2,
|
||||
'no-void': 2,
|
||||
'no-warning-comments': 0,
|
||||
'no-with': 2,
|
||||
'radix': 2,
|
||||
'vars-on-top': 2,
|
||||
|
||||
'strict': [2, 'never'],
|
||||
|
||||
'init-declarations': 0,
|
||||
'no-catch-shadow': 2,
|
||||
'no-delete-var': 2,
|
||||
'no-label-var': 2,
|
||||
'no-shadow-restricted-names': 2,
|
||||
'no-shadow': 2,
|
||||
'no-undef-init': 2,
|
||||
'no-undef': 2,
|
||||
'no-unused-vars': [2, {args: 'after-used', 'argsIgnorePattern': '^_'}],
|
||||
'no-use-before-define': [2, 'nofunc'],
|
||||
|
||||
'array-bracket-spacing': [2, 'never'],
|
||||
'block-spacing': [2, 'always'],
|
||||
'brace-style': [2, '1tbs'],
|
||||
'camelcase': [2, {properties: 'never'}],
|
||||
'comma-spacing': [2, {before: false, after: true}],
|
||||
'comma-style': [2, 'last'],
|
||||
'computed-property-spacing': [2, 'never'],
|
||||
'consistent-this': [2, 'self'],
|
||||
'eol-last': 0, // TODO: revisit
|
||||
'id-length': 0,
|
||||
'id-match': 0,
|
||||
'indent': [0, 2, {SwitchCase: 1}],
|
||||
'key-spacing': [2, {beforeColon: false, afterColon: true}],
|
||||
'linebreak-style': [2, 'unix'],
|
||||
'lines-around-comment': 0,
|
||||
'max-depth': 0,
|
||||
'max-len': 0,
|
||||
'max-nested-callbacks': 0,
|
||||
'max-params': 0,
|
||||
'max-statements': 0,
|
||||
'new-cap': 0,
|
||||
'new-parens': 2,
|
||||
'newline-after-var': 0,
|
||||
'no-array-constructor': 2,
|
||||
'no-negated-condition': 2,
|
||||
'no-inline-comments': 0,
|
||||
'no-lonely-if': 2,
|
||||
'no-mixed-spaces-and-tabs': 2,
|
||||
'no-multiple-empty-lines': 2,
|
||||
'no-nested-ternary': 2,
|
||||
'no-new-object': 2,
|
||||
'no-plusplus': [2, {allowForLoopAfterthoughts: true}],
|
||||
'no-spaced-func': 2,
|
||||
'no-ternary': 0,
|
||||
'no-trailing-spaces': 2,
|
||||
'no-underscore-dangle': 0,
|
||||
'no-unneeded-ternary': 2,
|
||||
'object-curly-spacing': [2, 'never'],
|
||||
'one-var': 0,
|
||||
'operator-assignment': [2, 'always'],
|
||||
'padded-blocks': [2, 'never'],
|
||||
'quote-props': [2, 'as-needed', {keywords: false, numbers: false }],
|
||||
'require-jsdoc': 0,
|
||||
'semi-spacing': [2, {before: false, after: true}],
|
||||
'semi': [2, 'never'],
|
||||
'sort-vars': 0,
|
||||
'keyword-spacing': 'error',
|
||||
'space-before-blocks': [2, 'always'],
|
||||
'space-before-function-paren': [2, 'never'],
|
||||
'space-in-parens': [2, 'never'],
|
||||
'space-infix-ops': 2,
|
||||
'space-unary-ops': 2,
|
||||
'spaced-comment': [2, 'always'],
|
||||
'wrap-regex': 0,
|
||||
'arrow-body-style': 0,
|
||||
'arrow-spacing': [2, {before: true, after: true}],
|
||||
'no-confusing-arrow': 0,
|
||||
'no-class-assign': 2,
|
||||
'no-const-assign': 2,
|
||||
'no-dupe-class-members': 2,
|
||||
'no-this-before-super': 2,
|
||||
'no-var': 2,
|
||||
'object-shorthand': [2, 'always'],
|
||||
'prefer-arrow-callback': 0,
|
||||
'prefer-const': 2,
|
||||
'prefer-template': 2,
|
||||
|
||||
// React
|
||||
'jsx-quotes': [1, "prefer-double"],
|
||||
'react/display-name': 0,
|
||||
'react/jsx-no-bind': [2, {ignoreRefs: true}],
|
||||
'react/jsx-boolean-value': [2, 'always'],
|
||||
'react/jsx-curly-spacing': [2, 'never'],
|
||||
'react/jsx-equals-spacing': [2, 'never'],
|
||||
'react/jsx-key': 2,
|
||||
'react/jsx-no-duplicate-props': 2,
|
||||
'react/jsx-no-undef': 2,
|
||||
'react/jsx-sort-props': 0,
|
||||
'react/jsx-sort-prop-types': 0,
|
||||
'react/jsx-uses-react': 2,
|
||||
'react/jsx-uses-vars': 2,
|
||||
'react/no-danger': 2,
|
||||
'react/no-did-mount-set-state': 0,
|
||||
'react/no-did-update-set-state': 2,
|
||||
'react/no-direct-mutation-state': 2,
|
||||
'react/no-is-mounted': 2,
|
||||
'react/no-multi-comp': 0,
|
||||
'react/no-set-state': 0,
|
||||
'react/no-string-refs': 0, // TODO: 2
|
||||
'react/no-unknown-property': 2,
|
||||
'react/prop-types': 2,
|
||||
'react/prefer-es6-class': [0, 'never'],
|
||||
'react/react-in-jsx-scope': 2,
|
||||
'react/require-extension': 0,
|
||||
'react/self-closing-comp': 0, // TODO: we can re-enable this if some brave soul wants to update the code (mostly spans acting as icons)
|
||||
'react/sort-comp': 0, // TODO: 2
|
||||
|
||||
// Prettier
|
||||
'prettier/prettier': ['error', {
|
||||
'singleQuote': true,
|
||||
'trailingComma': 'es5',
|
||||
'bracketSpacing': false,
|
||||
'semi': false,
|
||||
}],
|
||||
|
||||
// jest
|
||||
'jest/no-disabled-tests': "warn",
|
||||
'jest/no-focused-tests': "error",
|
||||
|
||||
// Babel
|
||||
'babel/no-invalid-this': 1
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"plugins": [
|
||||
"react",
|
||||
"prettier",
|
||||
"babel",
|
||||
"jest"
|
||||
],
|
||||
"extends": [
|
||||
"prettier",
|
||||
"prettier/react"
|
||||
],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"mocha": true,
|
||||
"jest": true,
|
||||
"node": true,
|
||||
"es6": true
|
||||
},
|
||||
"globals": {
|
||||
"expect": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaFeatures": {
|
||||
"arrowFunctions": true,
|
||||
"binaryLiterals": true,
|
||||
"blockBindings": true,
|
||||
"classes": true,
|
||||
"defaultParams": false,
|
||||
"destructuring": true,
|
||||
"forOf": false,
|
||||
"generators": false,
|
||||
"modules": true,
|
||||
"objectLiteralComputedProperties": true,
|
||||
"objectLiteralDuplicateProperties": false,
|
||||
"objectLiteralShorthandMethods": true,
|
||||
"objectLiteralShorthandProperties": true,
|
||||
"octalLiterals": false,
|
||||
"regexUFlag": false,
|
||||
"regexYFlag": false,
|
||||
"restParams": true,
|
||||
"spread": true,
|
||||
"superInFunctions": false,
|
||||
"templateStrings": true,
|
||||
"unicodeCodePointEscapes": false,
|
||||
"globalReturn": false,
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"func-style": 0,
|
||||
"func-names": 0,
|
||||
"arrow-parens": 0,
|
||||
"no-cond-assign": 2,
|
||||
"no-console": [
|
||||
"error",
|
||||
{
|
||||
"allow": [
|
||||
"error",
|
||||
"warn"
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-constant-condition": 2,
|
||||
"no-control-regex": 2,
|
||||
"no-debugger": 2,
|
||||
"no-dupe-args": 2,
|
||||
"no-dupe-keys": 2,
|
||||
"no-duplicate-case": 2,
|
||||
"no-empty-character-class": 2,
|
||||
"no-empty": 2,
|
||||
"no-ex-assign": 2,
|
||||
"no-extra-boolean-cast": 2,
|
||||
"no-extra-parens": 0,
|
||||
"no-func-assign": 2,
|
||||
"no-inner-declarations": [
|
||||
2,
|
||||
"both"
|
||||
],
|
||||
"no-invalid-regexp": 2,
|
||||
"no-irregular-whitespace": 2,
|
||||
"no-negated-in-lhs": 2,
|
||||
"no-obj-calls": 2,
|
||||
"no-regex-spaces": 2,
|
||||
"no-sparse-arrays": 2,
|
||||
"no-unreachable": 2,
|
||||
"use-isnan": 2,
|
||||
"valid-jsdoc": 0,
|
||||
"valid-typeof": 2,
|
||||
"accessor-pairs": 2,
|
||||
"block-scoped-var": 2,
|
||||
"complexity": 0,
|
||||
"consistent-return": 0,
|
||||
"curly": 2,
|
||||
"default-case": 0,
|
||||
"dot-notation": 2,
|
||||
"eqeqeq": 2,
|
||||
"no-alert": 2,
|
||||
"no-caller": 2,
|
||||
"no-case-declarations": 2,
|
||||
"no-div-regex": 2,
|
||||
"no-else-return": 2,
|
||||
"no-labels": 2,
|
||||
"no-empty-pattern": 2,
|
||||
"no-eq-null": 2,
|
||||
"no-eval": 2,
|
||||
"no-extend-native": 2,
|
||||
"no-extra-bind": 2,
|
||||
"no-fallthrough": 2,
|
||||
"no-implicit-coercion": 0,
|
||||
"no-implied-eval": 2,
|
||||
"no-iterator": 2,
|
||||
"no-lone-blocks": 2,
|
||||
"no-loop-func": 2,
|
||||
"no-magic-numbers": [
|
||||
0,
|
||||
{
|
||||
"ignore": [
|
||||
-1,
|
||||
0,
|
||||
1,
|
||||
2
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-multi-str": 2,
|
||||
"no-native-reassign": 2,
|
||||
"no-new-func": 2,
|
||||
"no-new-wrappers": 2,
|
||||
"no-new": 2,
|
||||
"no-octal-escape": 2,
|
||||
"no-octal": 2,
|
||||
"no-proto": 2,
|
||||
"no-redeclare": 2,
|
||||
"no-script-url": 2,
|
||||
"no-self-compare": 2,
|
||||
"no-sequences": 2,
|
||||
"no-throw-literal": 2,
|
||||
"no-unused-expressions": 2,
|
||||
"no-useless-call": 2,
|
||||
"no-useless-concat": 2,
|
||||
"no-void": 2,
|
||||
"no-warning-comments": 0,
|
||||
"no-with": 2,
|
||||
"radix": 2,
|
||||
"vars-on-top": 2,
|
||||
"strict": [
|
||||
2,
|
||||
"never"
|
||||
],
|
||||
"init-declarations": 0,
|
||||
"no-catch-shadow": 2,
|
||||
"no-delete-var": 2,
|
||||
"no-label-var": 2,
|
||||
"no-shadow-restricted-names": 2,
|
||||
"no-shadow": 2,
|
||||
"no-undef-init": 2,
|
||||
"no-undef": 2,
|
||||
"no-unused-vars": [
|
||||
2,
|
||||
{
|
||||
"args": "after-used",
|
||||
"argsIgnorePattern": "^_"
|
||||
}
|
||||
],
|
||||
"no-use-before-define": [
|
||||
2,
|
||||
"nofunc"
|
||||
],
|
||||
"camelcase": [
|
||||
2,
|
||||
{
|
||||
"properties": "never"
|
||||
}
|
||||
],
|
||||
"consistent-this": [
|
||||
2,
|
||||
"self"
|
||||
],
|
||||
"eol-last": 0,
|
||||
"id-length": 0,
|
||||
"id-match": 0,
|
||||
"indent": [
|
||||
0,
|
||||
2,
|
||||
{
|
||||
"SwitchCase": 1
|
||||
}
|
||||
],
|
||||
"linebreak-style": [
|
||||
2,
|
||||
"unix"
|
||||
],
|
||||
"lines-around-comment": 0,
|
||||
"max-depth": 0,
|
||||
"max-len": 0,
|
||||
"max-nested-callbacks": 0,
|
||||
"max-params": 0,
|
||||
"max-statements": 0,
|
||||
"new-cap": 0,
|
||||
"newline-after-var": 0,
|
||||
"no-array-constructor": 2,
|
||||
"no-negated-condition": 2,
|
||||
"no-inline-comments": 0,
|
||||
"no-lonely-if": 2,
|
||||
"no-nested-ternary": 2,
|
||||
"no-new-object": 2,
|
||||
"no-plusplus": [
|
||||
2,
|
||||
{
|
||||
"allowForLoopAfterthoughts": true
|
||||
}
|
||||
],
|
||||
"no-ternary": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-unneeded-ternary": 2,
|
||||
"one-var": 0,
|
||||
"operator-assignment": [
|
||||
2,
|
||||
"always"
|
||||
],
|
||||
"require-jsdoc": 0,
|
||||
"sort-vars": 0,
|
||||
"spaced-comment": [
|
||||
2,
|
||||
"always"
|
||||
],
|
||||
"wrap-regex": 0,
|
||||
"arrow-body-style": 0,
|
||||
"no-confusing-arrow": 0,
|
||||
"no-class-assign": 2,
|
||||
"no-const-assign": 2,
|
||||
"no-dupe-class-members": 2,
|
||||
"no-this-before-super": 2,
|
||||
"no-var": 2,
|
||||
"object-shorthand": [
|
||||
2,
|
||||
"always"
|
||||
],
|
||||
"prefer-arrow-callback": 0,
|
||||
"prefer-const": 2,
|
||||
"prefer-template": 2,
|
||||
"react/display-name": 0,
|
||||
"react/jsx-no-bind": [
|
||||
2,
|
||||
{
|
||||
"ignoreRefs": true
|
||||
}
|
||||
],
|
||||
"react/jsx-boolean-value": [
|
||||
2,
|
||||
"always"
|
||||
],
|
||||
"react/jsx-key": 2,
|
||||
"react/jsx-no-duplicate-props": 2,
|
||||
"react/jsx-no-undef": 2,
|
||||
"react/jsx-sort-props": 0,
|
||||
"react/jsx-sort-prop-types": 0,
|
||||
"react/jsx-uses-react": 2,
|
||||
"react/jsx-uses-vars": 2,
|
||||
"react/no-danger": 2,
|
||||
"react/no-did-mount-set-state": 0,
|
||||
"react/no-did-update-set-state": 2,
|
||||
"react/no-direct-mutation-state": 2,
|
||||
"react/no-is-mounted": 2,
|
||||
"react/no-multi-comp": 0,
|
||||
"react/no-set-state": 0,
|
||||
"react/no-string-refs": 0,
|
||||
"react/no-unknown-property": 2,
|
||||
"react/prop-types": 2,
|
||||
"react/prefer-es6-class": [
|
||||
0,
|
||||
"never"
|
||||
],
|
||||
"react/react-in-jsx-scope": 2,
|
||||
"react/require-extension": 0,
|
||||
"react/self-closing-comp": 0,
|
||||
"react/sort-comp": 0,
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5",
|
||||
"bracketSpacing": false,
|
||||
"semi": false
|
||||
}
|
||||
],
|
||||
"jest/no-disabled-tests": "warn",
|
||||
"jest/no-focused-tests": "error",
|
||||
"babel/no-invalid-this": 1
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,17 @@ module.exports = {
|
|||
},
|
||||
{
|
||||
runner: 'jest-runner-eslint',
|
||||
displayName: 'lint',
|
||||
displayName: 'eslint',
|
||||
testMatch: ['<rootDir>/test/**/*.test.js'],
|
||||
},
|
||||
{
|
||||
runner: 'jest-runner-tslint',
|
||||
displayName: 'tslint',
|
||||
moduleFileExtensions: ['ts', 'tsx'],
|
||||
testMatch: [
|
||||
'<rootDir>/test/**/*.test.ts',
|
||||
'<rootDir>/test/**/*.test.tsx',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
"eslint-config-prettier": "^2.9.0",
|
||||
"eslint-loader": "^2.0.0",
|
||||
"eslint-plugin-jest": "^21.12.2",
|
||||
"eslint-plugin-prettier": "^2.1.2",
|
||||
"eslint-plugin-prettier": "^2.6.0",
|
||||
"eslint-plugin-react": "6.6.0",
|
||||
"eslint-watch": "^3.1.2",
|
||||
"express": "^4.14.0",
|
||||
|
@ -77,6 +77,7 @@
|
|||
"imports-loader": "^0.6.5",
|
||||
"jest": "^22.4.2",
|
||||
"jest-runner-eslint": "^0.4.0",
|
||||
"jest-runner-tslint": "^1.0.3",
|
||||
"jsdom": "^9.0.0",
|
||||
"json-loader": "^0.5.7",
|
||||
"node-sass": "^4.5.3",
|
||||
|
@ -86,7 +87,7 @@
|
|||
"postcss-loader": "^0.8.0",
|
||||
"postcss-reporter": "^1.3.1",
|
||||
"precss": "^1.4.0",
|
||||
"prettier": "1.5.3",
|
||||
"prettier": "^1.11.1",
|
||||
"react-addons-test-utils": "^15.0.2",
|
||||
"react-test-renderer": "^15.6.1",
|
||||
"resolve-url-loader": "^2.2.1",
|
||||
|
@ -96,6 +97,11 @@
|
|||
"ts-jest": "^22.4.1",
|
||||
"ts-loader": "^3.5.0",
|
||||
"tslib": "^1.9.0",
|
||||
"tslint": "^5.9.1",
|
||||
"tslint-config-prettier": "^1.10.0",
|
||||
"tslint-loader": "^3.6.0",
|
||||
"tslint-plugin-prettier": "^1.3.0",
|
||||
"tslint-react": "^3.5.1",
|
||||
"typescript": "^2.7.2",
|
||||
"uglifyjs-webpack-plugin": "^1.2.2",
|
||||
"webpack": "^3.11.0",
|
||||
|
|
|
@ -4,12 +4,13 @@ import PropTypes from 'prop-types'
|
|||
import SideNav from 'src/side_nav'
|
||||
import Notifications from 'shared/components/Notifications'
|
||||
|
||||
const App = ({children}) =>
|
||||
const App = ({children}) => (
|
||||
<div className="chronograf-root">
|
||||
<Notifications />
|
||||
<SideNav />
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
const {node} = PropTypes
|
||||
|
||||
|
|
|
@ -168,9 +168,9 @@ export const createMappingAsync = (url, mapping) => async dispatch => {
|
|||
const {data} = await createMappingAJAX(url, mapping)
|
||||
dispatch(updateMapping(mappingWithTempId, data))
|
||||
} catch (error) {
|
||||
const message = `${_.upperFirst(
|
||||
_.toLower(error.data.message)
|
||||
)}: Scheme: ${mapping.scheme} Provider: ${mapping.provider}`
|
||||
const message = `${_.upperFirst(_.toLower(error.data.message))}: Scheme: ${
|
||||
mapping.scheme
|
||||
} Provider: ${mapping.provider}`
|
||||
dispatch(errorThrown(error, message))
|
||||
setTimeout(
|
||||
() => dispatch(removeMapping(mappingWithTempId)),
|
||||
|
@ -212,9 +212,9 @@ export const createUserAsync = (url, user) => async dispatch => {
|
|||
const {data} = await createUserAJAX(url, user)
|
||||
dispatch(syncUser(userWithTempID, data))
|
||||
} catch (error) {
|
||||
const message = `${_.upperFirst(
|
||||
_.toLower(error.data.message)
|
||||
)}: ${user.scheme}::${user.provider}::${user.name}`
|
||||
const message = `${_.upperFirst(_.toLower(error.data.message))}: ${
|
||||
user.scheme
|
||||
}::${user.provider}::${user.name}`
|
||||
dispatch(errorThrown(error, message))
|
||||
// undo optimistic update
|
||||
setTimeout(() => dispatch(removeUser(userWithTempID)), REVERT_STATE_DELAY)
|
||||
|
@ -277,9 +277,9 @@ export const createOrganizationAsync = (
|
|||
const {data} = await createOrganizationAJAX(url, organization)
|
||||
dispatch(syncOrganization(organization, data))
|
||||
} catch (error) {
|
||||
const message = `${_.upperFirst(
|
||||
_.toLower(error.data.message)
|
||||
)}: ${organization.name}`
|
||||
const message = `${_.upperFirst(_.toLower(error.data.message))}: ${
|
||||
organization.name
|
||||
}`
|
||||
dispatch(errorThrown(error, message))
|
||||
// undo optimistic update
|
||||
setTimeout(
|
||||
|
|
|
@ -89,18 +89,12 @@ const AdminTabs = ({
|
|||
return (
|
||||
<Tabs className="row">
|
||||
<TabList customClass="col-md-2 admin-tabs">
|
||||
{tabs.map((t, i) =>
|
||||
<Tab key={tabs[i].type}>
|
||||
{tabs[i].type}
|
||||
</Tab>
|
||||
)}
|
||||
{tabs.map((t, i) => <Tab key={tabs[i].type}>{tabs[i].type}</Tab>)}
|
||||
</TabList>
|
||||
<TabPanels customClass="col-md-10 admin-tabs--content">
|
||||
{tabs.map((t, i) =>
|
||||
<TabPanel key={tabs[i].type}>
|
||||
{t.component}
|
||||
</TabPanel>
|
||||
)}
|
||||
{tabs.map((t, i) => (
|
||||
<TabPanel key={tabs[i].type}>{t.component}</TabPanel>
|
||||
))}
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
)
|
||||
|
|
|
@ -41,7 +41,7 @@ const DatabaseManager = ({
|
|||
</button>
|
||||
</div>
|
||||
<div className="panel-body">
|
||||
{databases.map(db =>
|
||||
{databases.map(db => (
|
||||
<DatabaseTable
|
||||
key={db.links.self}
|
||||
database={db}
|
||||
|
@ -62,7 +62,7 @@ const DatabaseManager = ({
|
|||
onRemoveRetentionPolicy={onRemoveRetentionPolicy}
|
||||
onDeleteRetentionPolicy={onDeleteRetentionPolicy}
|
||||
/>
|
||||
)}
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -148,19 +148,21 @@ class DatabaseRow extends Component {
|
|||
return (
|
||||
<tr>
|
||||
<td style={{width: `${DATABASE_TABLE.colRetentionPolicy}px`}}>
|
||||
{isNew
|
||||
? <input
|
||||
className="form-control input-xs"
|
||||
type="text"
|
||||
defaultValue={name}
|
||||
placeholder="Name this RP"
|
||||
onKeyDown={this.handleKeyDown}
|
||||
ref={r => (this.name = r)}
|
||||
autoFocus={true}
|
||||
spellCheck={false}
|
||||
autoComplete={false}
|
||||
/>
|
||||
: name}
|
||||
{isNew ? (
|
||||
<input
|
||||
className="form-control input-xs"
|
||||
type="text"
|
||||
defaultValue={name}
|
||||
placeholder="Name this RP"
|
||||
onKeyDown={this.handleKeyDown}
|
||||
ref={r => (this.name = r)}
|
||||
autoFocus={true}
|
||||
spellCheck={false}
|
||||
autoComplete={false}
|
||||
/>
|
||||
) : (
|
||||
name
|
||||
)}
|
||||
</td>
|
||||
<td style={{width: `${DATABASE_TABLE.colDuration}px`}}>
|
||||
<input
|
||||
|
@ -176,22 +178,22 @@ class DatabaseRow extends Component {
|
|||
autoComplete={false}
|
||||
/>
|
||||
</td>
|
||||
{isRFDisplayed
|
||||
? <td style={{width: `${DATABASE_TABLE.colReplication}px`}}>
|
||||
<input
|
||||
className="form-control input-xs"
|
||||
name="name"
|
||||
type="number"
|
||||
min="1"
|
||||
defaultValue={replication || 1}
|
||||
placeholder="# of Nodes"
|
||||
onKeyDown={this.handleKeyDown}
|
||||
ref={r => (this.replication = r)}
|
||||
spellCheck={false}
|
||||
autoComplete={false}
|
||||
/>
|
||||
</td>
|
||||
: null}
|
||||
{isRFDisplayed ? (
|
||||
<td style={{width: `${DATABASE_TABLE.colReplication}px`}}>
|
||||
<input
|
||||
className="form-control input-xs"
|
||||
name="name"
|
||||
type="number"
|
||||
min="1"
|
||||
defaultValue={replication || 1}
|
||||
placeholder="# of Nodes"
|
||||
onKeyDown={this.handleKeyDown}
|
||||
ref={r => (this.replication = r)}
|
||||
spellCheck={false}
|
||||
autoComplete={false}
|
||||
/>
|
||||
</td>
|
||||
) : null}
|
||||
<td
|
||||
className="text-right"
|
||||
style={{width: `${DATABASE_TABLE.colDelete}px`}}
|
||||
|
@ -210,9 +212,9 @@ class DatabaseRow extends Component {
|
|||
<tr>
|
||||
<td>
|
||||
{`${name} `}
|
||||
{isDefault
|
||||
? <span className="default-source-label">default</span>
|
||||
: null}
|
||||
{isDefault ? (
|
||||
<span className="default-source-label">default</span>
|
||||
) : null}
|
||||
</td>
|
||||
<td
|
||||
onClick={this.handleStartEdit}
|
||||
|
@ -220,31 +222,33 @@ class DatabaseRow extends Component {
|
|||
>
|
||||
{formattedDuration}
|
||||
</td>
|
||||
{isRFDisplayed
|
||||
? <td
|
||||
onClick={this.handleStartEdit}
|
||||
style={{width: `${DATABASE_TABLE.colReplication}px`}}
|
||||
>
|
||||
{replication}
|
||||
</td>
|
||||
: null}
|
||||
{isRFDisplayed ? (
|
||||
<td
|
||||
onClick={this.handleStartEdit}
|
||||
style={{width: `${DATABASE_TABLE.colReplication}px`}}
|
||||
>
|
||||
{replication}
|
||||
</td>
|
||||
) : null}
|
||||
<td
|
||||
className="text-right"
|
||||
style={{width: `${DATABASE_TABLE.colDelete}px`}}
|
||||
>
|
||||
{isDeleting
|
||||
? <YesNoButtons
|
||||
onConfirm={onDelete(database, retentionPolicy)}
|
||||
onCancel={this.handleEndDelete}
|
||||
buttonSize="btn-xs"
|
||||
/>
|
||||
: <button
|
||||
className="btn btn-danger btn-xs table--show-on-row-hover"
|
||||
style={isDeletable ? {} : {visibility: 'hidden'}}
|
||||
onClick={this.handleStartDelete}
|
||||
>
|
||||
{`Delete ${name}`}
|
||||
</button>}
|
||||
{isDeleting ? (
|
||||
<YesNoButtons
|
||||
onConfirm={onDelete(database, retentionPolicy)}
|
||||
onCancel={this.handleEndDelete}
|
||||
buttonSize="btn-xs"
|
||||
/>
|
||||
) : (
|
||||
<button
|
||||
className="btn btn-danger btn-xs table--show-on-row-hover"
|
||||
style={isDeletable ? {} : {visibility: 'hidden'}}
|
||||
onClick={this.handleStartDelete}
|
||||
>
|
||||
{`Delete ${name}`}
|
||||
</button>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
|
|
|
@ -57,11 +57,11 @@ const DatabaseTable = ({
|
|||
<th style={{width: `${DATABASE_TABLE.colDuration}px`}}>
|
||||
Duration
|
||||
</th>
|
||||
{isRFDisplayed
|
||||
? <th style={{width: `${DATABASE_TABLE.colReplication}px`}}>
|
||||
Replication Factor
|
||||
</th>
|
||||
: null}
|
||||
{isRFDisplayed ? (
|
||||
<th style={{width: `${DATABASE_TABLE.colReplication}px`}}>
|
||||
Replication Factor
|
||||
</th>
|
||||
) : null}
|
||||
<th style={{width: `${DATABASE_TABLE.colDelete}px`}} />
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
|
@ -68,18 +68,18 @@ const Header = ({
|
|||
>
|
||||
<span className="icon plus" /> Add Retention Policy
|
||||
</button>
|
||||
{database.name === '_internal'
|
||||
? null
|
||||
: <button
|
||||
className="btn btn-xs btn-danger"
|
||||
onClick={onStartDelete(database)}
|
||||
>
|
||||
Delete
|
||||
</button>}
|
||||
{database.name === '_internal' ? null : (
|
||||
<button
|
||||
className="btn btn-xs btn-danger"
|
||||
onClick={onStartDelete(database)}
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
const onConfirm = db => {
|
||||
function onConfirm(db) {
|
||||
if (database.deleteCode !== `DELETE ${database.name}`) {
|
||||
return notify(NOTIFY_DATABASE_DELETE_CONFIRMATION_REQUIRED(database.name))
|
||||
}
|
||||
|
@ -112,15 +112,13 @@ const Header = ({
|
|||
|
||||
return (
|
||||
<div className="db-manager-header">
|
||||
<h4>
|
||||
{database.name}
|
||||
</h4>
|
||||
<h4>{database.name}</h4>
|
||||
{database.hasOwnProperty('deleteCode') ? deleteConfirmation : buttons}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const EditHeader = ({database, onEdit, onKeyDown, onConfirm, onCancel}) =>
|
||||
const EditHeader = ({database, onEdit, onKeyDown, onConfirm, onCancel}) => (
|
||||
<div className="db-manager-header db-manager-header--edit">
|
||||
<input
|
||||
className="form-control input-sm"
|
||||
|
@ -136,6 +134,7 @@ const EditHeader = ({database, onEdit, onKeyDown, onConfirm, onCancel}) =>
|
|||
/>
|
||||
<ConfirmButtons item={database} onConfirm={onConfirm} onCancel={onCancel} />
|
||||
</div>
|
||||
)
|
||||
|
||||
const {func, shape, bool} = PropTypes
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
const EmptyRow = ({tableName}) =>
|
||||
const EmptyRow = ({tableName}) => (
|
||||
<tr className="table-empty-state">
|
||||
<th colSpan="5">
|
||||
<p>
|
||||
|
@ -9,6 +9,7 @@ const EmptyRow = ({tableName}) =>
|
|||
</p>
|
||||
</th>
|
||||
</tr>
|
||||
)
|
||||
|
||||
const {string} = PropTypes
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
|
|||
import QueryRow from 'src/admin/components/QueryRow'
|
||||
import {QUERIES_TABLE} from 'src/admin/constants/tableSizing'
|
||||
|
||||
const QueriesTable = ({queries, onKillQuery}) =>
|
||||
const QueriesTable = ({queries, onKillQuery}) => (
|
||||
<div>
|
||||
<div className="panel panel-solid">
|
||||
<div className="panel-body">
|
||||
|
@ -20,14 +20,15 @@ const QueriesTable = ({queries, onKillQuery}) =>
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{queries.map(q =>
|
||||
{queries.map(q => (
|
||||
<QueryRow key={q.id} query={q} onKill={onKillQuery} />
|
||||
)}
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, func, shape} = PropTypes
|
||||
|
||||
|
|
|
@ -37,9 +37,7 @@ class QueryRow extends Component {
|
|||
{database}
|
||||
</td>
|
||||
<td>
|
||||
<code>
|
||||
{query}
|
||||
</code>
|
||||
<code>{query}</code>
|
||||
</td>
|
||||
<td
|
||||
style={{width: `${QUERIES_TABLE.colRunning}px`}}
|
||||
|
@ -51,18 +49,20 @@ class QueryRow extends Component {
|
|||
style={{width: `${QUERIES_TABLE.colKillQuery}px`}}
|
||||
className="text-right"
|
||||
>
|
||||
{this.state.confirmingKill
|
||||
? <ConfirmButtons
|
||||
onConfirm={this.handleFinishHim}
|
||||
onCancel={this.handleShowMercy}
|
||||
buttonSize="btn-xs"
|
||||
/>
|
||||
: <button
|
||||
className="btn btn-xs btn-danger table--show-on-row-hover"
|
||||
onClick={this.handleInitiateKill}
|
||||
>
|
||||
Kill
|
||||
</button>}
|
||||
{this.state.confirmingKill ? (
|
||||
<ConfirmButtons
|
||||
onConfirm={this.handleFinishHim}
|
||||
onCancel={this.handleShowMercy}
|
||||
buttonSize="btn-xs"
|
||||
/>
|
||||
) : (
|
||||
<button
|
||||
className="btn btn-xs btn-danger table--show-on-row-hover"
|
||||
onClick={this.handleInitiateKill}
|
||||
>
|
||||
Kill
|
||||
</button>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
|
|
|
@ -24,11 +24,11 @@ const RoleRow = ({
|
|||
onUpdateRoleUsers,
|
||||
onUpdateRolePermissions,
|
||||
}) => {
|
||||
const handleUpdateUsers = usrs => {
|
||||
function handleUpdateUsers(usrs) {
|
||||
onUpdateRoleUsers(role, usrs)
|
||||
}
|
||||
|
||||
const handleUpdatePermissions = allowed => {
|
||||
function handleUpdatePermissions(allowed) {
|
||||
onUpdateRolePermissions(role, [
|
||||
{scope: 'all', allowed: allowed.map(({name}) => name)},
|
||||
])
|
||||
|
@ -64,41 +64,36 @@ const RoleRow = ({
|
|||
|
||||
return (
|
||||
<tr>
|
||||
<td style={{width: `${ROLES_TABLE.colName}px`}}>
|
||||
{roleName}
|
||||
<td style={{width: `${ROLES_TABLE.colName}px`}}>{roleName}</td>
|
||||
<td>
|
||||
{allPermissions && allPermissions.length ? (
|
||||
<MultiSelectDropdown
|
||||
items={allPermissions.map(name => ({name}))}
|
||||
selectedItems={perms.map(name => ({name}))}
|
||||
label={perms.length ? '' : 'Select Permissions'}
|
||||
onApply={handleUpdatePermissions}
|
||||
buttonSize="btn-xs"
|
||||
buttonColor="btn-primary"
|
||||
customClass={classnames(`dropdown-${ROLES_TABLE.colPermissions}`, {
|
||||
'admin-table--multi-select-empty': !permissions.length,
|
||||
})}
|
||||
/>
|
||||
) : null}
|
||||
</td>
|
||||
<td>
|
||||
{allPermissions && allPermissions.length
|
||||
? <MultiSelectDropdown
|
||||
items={allPermissions.map(name => ({name}))}
|
||||
selectedItems={perms.map(name => ({name}))}
|
||||
label={perms.length ? '' : 'Select Permissions'}
|
||||
onApply={handleUpdatePermissions}
|
||||
buttonSize="btn-xs"
|
||||
buttonColor="btn-primary"
|
||||
customClass={classnames(
|
||||
`dropdown-${ROLES_TABLE.colPermissions}`,
|
||||
{
|
||||
'admin-table--multi-select-empty': !permissions.length,
|
||||
}
|
||||
)}
|
||||
/>
|
||||
: null}
|
||||
</td>
|
||||
<td>
|
||||
{allUsers && allUsers.length
|
||||
? <MultiSelectDropdown
|
||||
items={allUsers}
|
||||
selectedItems={users}
|
||||
label={users.length ? '' : 'Select Users'}
|
||||
onApply={handleUpdateUsers}
|
||||
buttonSize="btn-xs"
|
||||
buttonColor="btn-primary"
|
||||
customClass={classnames(`dropdown-${ROLES_TABLE.colUsers}`, {
|
||||
'admin-table--multi-select-empty': !users.length,
|
||||
})}
|
||||
/>
|
||||
: null}
|
||||
{allUsers && allUsers.length ? (
|
||||
<MultiSelectDropdown
|
||||
items={allUsers}
|
||||
selectedItems={users}
|
||||
label={users.length ? '' : 'Select Users'}
|
||||
onApply={handleUpdateUsers}
|
||||
buttonSize="btn-xs"
|
||||
buttonColor="btn-primary"
|
||||
customClass={classnames(`dropdown-${ROLES_TABLE.colUsers}`, {
|
||||
'admin-table--multi-select-empty': !users.length,
|
||||
})}
|
||||
/>
|
||||
) : null}
|
||||
</td>
|
||||
<DeleteConfirmTableCell
|
||||
onDelete={onDelete}
|
||||
|
|
|
@ -17,7 +17,7 @@ const RolesTable = ({
|
|||
onFilter,
|
||||
onUpdateRoleUsers,
|
||||
onUpdateRolePermissions,
|
||||
}) =>
|
||||
}) => (
|
||||
<div className="panel panel-solid">
|
||||
<FilterBar
|
||||
type="roles"
|
||||
|
@ -36,30 +36,33 @@ const RolesTable = ({
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{roles.length
|
||||
? roles
|
||||
.filter(r => !r.hidden)
|
||||
.map(role =>
|
||||
<RoleRow
|
||||
key={role.links.self}
|
||||
allUsers={allUsers}
|
||||
allPermissions={permissions}
|
||||
role={role}
|
||||
onEdit={onEdit}
|
||||
onSave={onSave}
|
||||
onCancel={onCancel}
|
||||
onDelete={onDelete}
|
||||
onUpdateRoleUsers={onUpdateRoleUsers}
|
||||
onUpdateRolePermissions={onUpdateRolePermissions}
|
||||
isEditing={role.isEditing}
|
||||
isNew={role.isNew}
|
||||
/>
|
||||
)
|
||||
: <EmptyRow tableName={'Roles'} />}
|
||||
{roles.length ? (
|
||||
roles
|
||||
.filter(r => !r.hidden)
|
||||
.map(role => (
|
||||
<RoleRow
|
||||
key={role.links.self}
|
||||
allUsers={allUsers}
|
||||
allPermissions={permissions}
|
||||
role={role}
|
||||
onEdit={onEdit}
|
||||
onSave={onSave}
|
||||
onCancel={onCancel}
|
||||
onDelete={onDelete}
|
||||
onUpdateRoleUsers={onUpdateRoleUsers}
|
||||
onUpdateRolePermissions={onUpdateRolePermissions}
|
||||
isEditing={role.isEditing}
|
||||
isNew={role.isNew}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<EmptyRow tableName={'Roles'} />
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, bool, func, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -22,19 +22,21 @@ class UserNewPassword extends Component {
|
|||
const {user, isNew} = this.props
|
||||
return (
|
||||
<td style={{width: `${USERS_TABLE.colPassword}px`}}>
|
||||
{isNew
|
||||
? <input
|
||||
className="form-control input-xs"
|
||||
name="password"
|
||||
type="password"
|
||||
value={user.password || ''}
|
||||
placeholder="Password"
|
||||
onChange={this.handleEdit(user)}
|
||||
onKeyPress={this.handleKeyPress(user)}
|
||||
spellCheck={false}
|
||||
autoComplete={false}
|
||||
/>
|
||||
: '--'}
|
||||
{isNew ? (
|
||||
<input
|
||||
className="form-control input-xs"
|
||||
name="password"
|
||||
type="password"
|
||||
value={user.password || ''}
|
||||
placeholder="Password"
|
||||
onChange={this.handleEdit(user)}
|
||||
onKeyPress={this.handleKeyPress(user)}
|
||||
spellCheck={false}
|
||||
autoComplete={false}
|
||||
/>
|
||||
) : (
|
||||
'--'
|
||||
)}
|
||||
</td>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -28,19 +28,19 @@ const UserRow = ({
|
|||
onUpdateRoles,
|
||||
onUpdatePassword,
|
||||
}) => {
|
||||
const handleUpdatePermissions = perms => {
|
||||
function handleUpdatePermissions(perms) {
|
||||
const allowed = perms.map(p => p.name)
|
||||
onUpdatePermissions(user, [{scope: 'all', allowed}])
|
||||
}
|
||||
|
||||
const handleUpdateRoles = roleNames => {
|
||||
function handleUpdateRoles(roleNames) {
|
||||
onUpdateRoles(
|
||||
user,
|
||||
allRoles.filter(r => roleNames.find(rn => rn.name === r.name))
|
||||
)
|
||||
}
|
||||
|
||||
const handleUpdatePassword = () => {
|
||||
function handleUpdatePassword() {
|
||||
onUpdatePassword(user, password)
|
||||
}
|
||||
|
||||
|
@ -75,9 +75,7 @@ const UserRow = ({
|
|||
|
||||
return (
|
||||
<tr>
|
||||
<td style={{width: `${USERS_TABLE.colUsername}px`}}>
|
||||
{name}
|
||||
</td>
|
||||
<td style={{width: `${USERS_TABLE.colUsername}px`}}>{name}</td>
|
||||
<td style={{width: `${USERS_TABLE.colPassword}px`}}>
|
||||
<ChangePassRow
|
||||
onEdit={onEdit}
|
||||
|
@ -86,40 +84,37 @@ const UserRow = ({
|
|||
buttonSize="btn-xs"
|
||||
/>
|
||||
</td>
|
||||
{hasRoles
|
||||
? <td>
|
||||
<MultiSelectDropdown
|
||||
items={allRoles}
|
||||
selectedItems={roles.map(r => ({name: r.name}))}
|
||||
label={roles.length ? '' : 'Select Roles'}
|
||||
onApply={handleUpdateRoles}
|
||||
buttonSize="btn-xs"
|
||||
buttonColor="btn-primary"
|
||||
customClass={classnames(`dropdown-${USERS_TABLE.colRoles}`, {
|
||||
'admin-table--multi-select-empty': !roles.length,
|
||||
})}
|
||||
/>
|
||||
</td>
|
||||
: null}
|
||||
{hasRoles ? (
|
||||
<td>
|
||||
<MultiSelectDropdown
|
||||
items={allRoles}
|
||||
selectedItems={roles.map(r => ({name: r.name}))}
|
||||
label={roles.length ? '' : 'Select Roles'}
|
||||
onApply={handleUpdateRoles}
|
||||
buttonSize="btn-xs"
|
||||
buttonColor="btn-primary"
|
||||
customClass={classnames(`dropdown-${USERS_TABLE.colRoles}`, {
|
||||
'admin-table--multi-select-empty': !roles.length,
|
||||
})}
|
||||
/>
|
||||
</td>
|
||||
) : null}
|
||||
<td>
|
||||
{allPermissions && allPermissions.length
|
||||
? <MultiSelectDropdown
|
||||
items={allPermissions.map(p => ({name: p}))}
|
||||
selectedItems={perms.map(p => ({name: p}))}
|
||||
label={
|
||||
permissions && permissions.length ? '' : 'Select Permissions'
|
||||
}
|
||||
onApply={handleUpdatePermissions}
|
||||
buttonSize="btn-xs"
|
||||
buttonColor="btn-primary"
|
||||
customClass={classnames(
|
||||
`dropdown-${USERS_TABLE.colPermissions}`,
|
||||
{
|
||||
'admin-table--multi-select-empty': !permissions.length,
|
||||
}
|
||||
)}
|
||||
/>
|
||||
: null}
|
||||
{allPermissions && allPermissions.length ? (
|
||||
<MultiSelectDropdown
|
||||
items={allPermissions.map(p => ({name: p}))}
|
||||
selectedItems={perms.map(p => ({name: p}))}
|
||||
label={
|
||||
permissions && permissions.length ? '' : 'Select Permissions'
|
||||
}
|
||||
onApply={handleUpdatePermissions}
|
||||
buttonSize="btn-xs"
|
||||
buttonColor="btn-primary"
|
||||
customClass={classnames(`dropdown-${USERS_TABLE.colPermissions}`, {
|
||||
'admin-table--multi-select-empty': !permissions.length,
|
||||
})}
|
||||
/>
|
||||
) : null}
|
||||
</td>
|
||||
<DeleteConfirmTableCell
|
||||
onDelete={onDelete}
|
||||
|
|
|
@ -20,7 +20,7 @@ const UsersTable = ({
|
|||
onUpdatePermissions,
|
||||
onUpdateRoles,
|
||||
onUpdatePassword,
|
||||
}) =>
|
||||
}) => (
|
||||
<div className="panel panel-solid">
|
||||
<FilterBar
|
||||
type="users"
|
||||
|
@ -40,32 +40,35 @@ const UsersTable = ({
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{users.length
|
||||
? users
|
||||
.filter(u => !u.hidden)
|
||||
.map(user =>
|
||||
<UserRow
|
||||
key={user.links.self}
|
||||
user={user}
|
||||
onEdit={onEdit}
|
||||
onSave={onSave}
|
||||
onCancel={onCancel}
|
||||
onDelete={onDelete}
|
||||
isEditing={user.isEditing}
|
||||
isNew={user.isNew}
|
||||
allRoles={allRoles}
|
||||
hasRoles={hasRoles}
|
||||
allPermissions={permissions}
|
||||
onUpdatePermissions={onUpdatePermissions}
|
||||
onUpdateRoles={onUpdateRoles}
|
||||
onUpdatePassword={onUpdatePassword}
|
||||
/>
|
||||
)
|
||||
: <EmptyRow tableName={'Users'} />}
|
||||
{users.length ? (
|
||||
users
|
||||
.filter(u => !u.hidden)
|
||||
.map(user => (
|
||||
<UserRow
|
||||
key={user.links.self}
|
||||
user={user}
|
||||
onEdit={onEdit}
|
||||
onSave={onSave}
|
||||
onCancel={onCancel}
|
||||
onDelete={onDelete}
|
||||
isEditing={user.isEditing}
|
||||
isNew={user.isNew}
|
||||
allRoles={allRoles}
|
||||
hasRoles={hasRoles}
|
||||
allPermissions={permissions}
|
||||
onUpdatePermissions={onUpdatePermissions}
|
||||
onUpdateRoles={onUpdateRoles}
|
||||
onUpdatePassword={onUpdatePassword}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<EmptyRow tableName={'Users'} />
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, bool, func, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -51,18 +51,12 @@ const AdminTabs = ({
|
|||
return (
|
||||
<Tabs className="row">
|
||||
<TabList customClass="col-md-2 admin-tabs">
|
||||
{tabs.map((t, i) =>
|
||||
<Tab key={tabs[i].type}>
|
||||
{tabs[i].type}
|
||||
</Tab>
|
||||
)}
|
||||
{tabs.map((t, i) => <Tab key={tabs[i].type}>{tabs[i].type}</Tab>)}
|
||||
</TabList>
|
||||
<TabPanels customClass="col-md-10 admin-tabs--content">
|
||||
{tabs.map((t, i) =>
|
||||
<TabPanel key={tabs[i].type}>
|
||||
{t.component}
|
||||
</TabPanel>
|
||||
)}
|
||||
{tabs.map((t, i) => (
|
||||
<TabPanel key={tabs[i].type}>{t.component}</TabPanel>
|
||||
))}
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
)
|
||||
|
|
|
@ -133,33 +133,33 @@ class AllUsersTable extends Component {
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{users.length
|
||||
? users.map(user =>
|
||||
<AllUsersTableRow
|
||||
user={user}
|
||||
key={uuid.v4()}
|
||||
organizations={organizations}
|
||||
onAddToOrganization={this.handleAddToOrganization}
|
||||
onRemoveFromOrganization={
|
||||
this.handleRemoveFromOrganization
|
||||
}
|
||||
onChangeSuperAdmin={this.handleChangeSuperAdmin}
|
||||
onDelete={onDeleteUser}
|
||||
meID={meID}
|
||||
/>
|
||||
)
|
||||
: <tr className="table-empty-state">
|
||||
<th colSpan="6">
|
||||
<p>No Users to display</p>
|
||||
</th>
|
||||
</tr>}
|
||||
{isCreatingUser
|
||||
? <AllUsersTableRowNew
|
||||
{users.length ? (
|
||||
users.map(user => (
|
||||
<AllUsersTableRow
|
||||
user={user}
|
||||
key={uuid.v4()}
|
||||
organizations={organizations}
|
||||
onBlur={this.handleBlurCreateUserRow}
|
||||
onCreateUser={onCreateUser}
|
||||
onAddToOrganization={this.handleAddToOrganization}
|
||||
onRemoveFromOrganization={this.handleRemoveFromOrganization}
|
||||
onChangeSuperAdmin={this.handleChangeSuperAdmin}
|
||||
onDelete={onDeleteUser}
|
||||
meID={meID}
|
||||
/>
|
||||
: null}
|
||||
))
|
||||
) : (
|
||||
<tr className="table-empty-state">
|
||||
<th colSpan="6">
|
||||
<p>No Users to display</p>
|
||||
</th>
|
||||
</tr>
|
||||
)}
|
||||
{isCreatingUser ? (
|
||||
<AllUsersTableRowNew
|
||||
organizations={organizations}
|
||||
onBlur={this.handleBlurCreateUserRow}
|
||||
onCreateUser={onCreateUser}
|
||||
/>
|
||||
) : null}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
@ -12,10 +12,9 @@ const AllUsersTableHeader = ({
|
|||
onChangeAuthConfig,
|
||||
}) => {
|
||||
const numUsersString = `${numUsers} User${numUsers === 1 ? '' : 's'}`
|
||||
const numOrganizationsString = `${numOrganizations} Org${numOrganizations ===
|
||||
1
|
||||
? ''
|
||||
: 's'}`
|
||||
const numOrganizationsString = `${numOrganizations} Org${
|
||||
numOrganizations === 1 ? '' : 's'
|
||||
}`
|
||||
|
||||
return (
|
||||
<div className="panel-heading">
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import _ from 'lodash'
|
||||
|
||||
import Tags from 'shared/components/Tags'
|
||||
import SlideToggle from 'shared/components/SlideToggle'
|
||||
|
@ -37,7 +38,7 @@ const AllUsersTableRow = ({
|
|||
name: organizations.find(o => r.organization === o.id).name,
|
||||
}))
|
||||
|
||||
const wrappedDelete = () => onDelete(user)
|
||||
const wrappedDelete = _.curry(onDelete, user)
|
||||
|
||||
const removeWarning = userIsMe
|
||||
? 'Delete your user record\nand log yourself out?'
|
||||
|
@ -46,14 +47,14 @@ const AllUsersTableRow = ({
|
|||
return (
|
||||
<tr className={'chronograf-admin-table--user'}>
|
||||
<td>
|
||||
{userIsMe
|
||||
? <strong className="chronograf-user--me">
|
||||
<span className="icon user" />
|
||||
{user.name}
|
||||
</strong>
|
||||
: <strong>
|
||||
{user.name}
|
||||
</strong>}
|
||||
{userIsMe ? (
|
||||
<strong className="chronograf-user--me">
|
||||
<span className="icon user" />
|
||||
{user.name}
|
||||
</strong>
|
||||
) : (
|
||||
<strong>{user.name}</strong>
|
||||
)}
|
||||
</td>
|
||||
<td style={{width: colOrganizations}}>
|
||||
<Tags
|
||||
|
@ -64,12 +65,8 @@ const AllUsersTableRow = ({
|
|||
addMenuChoose={onAddToOrganization(user)}
|
||||
/>
|
||||
</td>
|
||||
<td style={{width: colProvider}}>
|
||||
{user.provider}
|
||||
</td>
|
||||
<td style={{width: colScheme}}>
|
||||
{user.scheme}
|
||||
</td>
|
||||
<td style={{width: colProvider}}>{user.provider}</td>
|
||||
<td style={{width: colScheme}}>{user.scheme}</td>
|
||||
<td style={{width: colSuperAdmin}} className="text-center">
|
||||
<SlideToggle
|
||||
active={user.superAdmin}
|
||||
|
@ -83,7 +80,8 @@ const AllUsersTableRow = ({
|
|||
confirmText={removeWarning}
|
||||
confirmAction={wrappedDelete}
|
||||
size="btn-xs"
|
||||
text="Remove"
|
||||
type="btn-danger"
|
||||
text="Delete"
|
||||
customClass="table--show-on-row-hover"
|
||||
/>
|
||||
</td>
|
||||
|
|
|
@ -39,10 +39,9 @@ class OrganizationsTable extends Component {
|
|||
} = this.props
|
||||
const {isCreatingOrganization} = this.state
|
||||
|
||||
const tableTitle = `${organizations.length} Organization${organizations.length ===
|
||||
1
|
||||
? ''
|
||||
: 's'}`
|
||||
const tableTitle = `${organizations.length} Organization${
|
||||
organizations.length === 1 ? '' : 's'
|
||||
}`
|
||||
|
||||
if (!organizations.length) {
|
||||
return (
|
||||
|
@ -56,9 +55,7 @@ class OrganizationsTable extends Component {
|
|||
return (
|
||||
<div className="panel panel-solid">
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">
|
||||
{tableTitle}
|
||||
</h2>
|
||||
<h2 className="panel-title">{tableTitle}</h2>
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
onClick={this.handleClickCreateOrganization}
|
||||
|
@ -76,13 +73,13 @@ class OrganizationsTable extends Component {
|
|||
</div>
|
||||
<div className="fancytable--th orgs-table--delete" />
|
||||
</div>
|
||||
{isCreatingOrganization
|
||||
? <OrganizationsTableRowNew
|
||||
onCreateOrganization={this.handleCreateOrganization}
|
||||
onCancelCreateOrganization={this.handleCancelCreateOrganization}
|
||||
/>
|
||||
: null}
|
||||
{organizations.map(org =>
|
||||
{isCreatingOrganization ? (
|
||||
<OrganizationsTableRowNew
|
||||
onCreateOrganization={this.handleCreateOrganization}
|
||||
onCancelCreateOrganization={this.handleCancelCreateOrganization}
|
||||
/>
|
||||
) : null}
|
||||
{organizations.map(org => (
|
||||
<OrganizationsTableRow
|
||||
key={uuid.v4()}
|
||||
organization={org}
|
||||
|
@ -91,7 +88,7 @@ class OrganizationsTable extends Component {
|
|||
onChooseDefaultRole={onChooseDefaultRole}
|
||||
currentOrganization={currentOrganization}
|
||||
/>
|
||||
)}
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -14,19 +14,21 @@ import {DEFAULT_ORG_ID} from 'src/admin/constants/chronografAdmin'
|
|||
import {USER_ROLES} from 'src/admin/constants/chronografAdmin'
|
||||
|
||||
const OrganizationsTableRowDeleteButton = ({organization, onClickDelete}) =>
|
||||
organization.id === DEFAULT_ORG_ID
|
||||
? <button
|
||||
className="btn btn-sm btn-default btn-square orgs-table--delete"
|
||||
disabled={true}
|
||||
>
|
||||
<span className="icon trash" />
|
||||
</button>
|
||||
: <button
|
||||
className="btn btn-sm btn-default btn-square"
|
||||
onClick={onClickDelete}
|
||||
>
|
||||
<span className="icon trash" />
|
||||
</button>
|
||||
organization.id === DEFAULT_ORG_ID ? (
|
||||
<button
|
||||
className="btn btn-sm btn-default btn-square orgs-table--delete"
|
||||
disabled={true}
|
||||
>
|
||||
<span className="icon trash" />
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
className="btn btn-sm btn-default btn-square"
|
||||
onClick={onClickDelete}
|
||||
>
|
||||
<span className="icon trash" />
|
||||
</button>
|
||||
)
|
||||
|
||||
class OrganizationsTableRow extends Component {
|
||||
constructor(props) {
|
||||
|
@ -81,16 +83,18 @@ class OrganizationsTableRow extends Component {
|
|||
return (
|
||||
<div className="fancytable--row">
|
||||
<div className="fancytable--td orgs-table--active">
|
||||
{organization.id === currentOrganization.id
|
||||
? <button className="btn btn-sm btn-success">
|
||||
<span className="icon checkmark" /> Current
|
||||
</button>
|
||||
: <button
|
||||
className="btn btn-sm btn-default"
|
||||
onClick={this.handleChangeCurrentOrganization}
|
||||
>
|
||||
<span className="icon shuffle" /> Switch to
|
||||
</button>}
|
||||
{organization.id === currentOrganization.id ? (
|
||||
<button className="btn btn-sm btn-success">
|
||||
<span className="icon checkmark" /> Current
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
className="btn btn-sm btn-default"
|
||||
onClick={this.handleChangeCurrentOrganization}
|
||||
>
|
||||
<span className="icon shuffle" /> Switch to
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<InputClickToEdit
|
||||
value={organization.name}
|
||||
|
@ -105,19 +109,21 @@ class OrganizationsTableRow extends Component {
|
|||
className="dropdown-stretch"
|
||||
/>
|
||||
</div>
|
||||
{isDeleting
|
||||
? <ConfirmButtons
|
||||
item={organization}
|
||||
onCancel={this.handleDismissDeleteConfirmation}
|
||||
onConfirm={this.handleDeleteOrg}
|
||||
onClickOutside={this.handleDismissDeleteConfirmation}
|
||||
confirmLeft={true}
|
||||
confirmTitle="Delete"
|
||||
/>
|
||||
: <OrganizationsTableRowDeleteButton
|
||||
organization={organization}
|
||||
onClickDelete={this.handleDeleteClick}
|
||||
/>}
|
||||
{isDeleting ? (
|
||||
<ConfirmButtons
|
||||
item={organization}
|
||||
onCancel={this.handleDismissDeleteConfirmation}
|
||||
onConfirm={this.handleDeleteOrg}
|
||||
onClickOutside={this.handleDismissDeleteConfirmation}
|
||||
confirmLeft={true}
|
||||
confirmTitle="Delete"
|
||||
/>
|
||||
) : (
|
||||
<OrganizationsTableRowDeleteButton
|
||||
organization={organization}
|
||||
onClickDelete={this.handleDeleteClick}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -55,9 +55,7 @@ class ProvidersTable extends Component {
|
|||
return (
|
||||
<div className="panel panel-solid">
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">
|
||||
{tableTitle}
|
||||
</h2>
|
||||
<h2 className="panel-title">{tableTitle}</h2>
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
onClick={this.handleClickCreateMap}
|
||||
|
@ -66,59 +64,58 @@ class ProvidersTable extends Component {
|
|||
<span className="icon plus" /> Create Mapping
|
||||
</button>
|
||||
</div>
|
||||
{mappings.length || isCreatingMap
|
||||
? <div className="panel-body">
|
||||
<div className="fancytable--labels">
|
||||
<div className="fancytable--th provider--scheme">Scheme</div>
|
||||
<div className="fancytable--th provider--provider">
|
||||
Provider
|
||||
</div>
|
||||
<div className="fancytable--th provider--providerorg">
|
||||
Provider Org
|
||||
</div>
|
||||
<div className="fancytable--th provider--arrow" />
|
||||
<div className="fancytable--th provider--redirect">
|
||||
Organization
|
||||
</div>
|
||||
<div className="fancytable--th" />
|
||||
<div className="fancytable--th provider--delete" />
|
||||
{mappings.length || isCreatingMap ? (
|
||||
<div className="panel-body">
|
||||
<div className="fancytable--labels">
|
||||
<div className="fancytable--th provider--scheme">Scheme</div>
|
||||
<div className="fancytable--th provider--provider">Provider</div>
|
||||
<div className="fancytable--th provider--providerorg">
|
||||
Provider Org
|
||||
</div>
|
||||
{mappings.map((mapping, i) =>
|
||||
<ProvidersTableRow
|
||||
key={uuid.v4()}
|
||||
mapping={mapping}
|
||||
organizations={organizations}
|
||||
schemes={SCHEMES}
|
||||
onDelete={onDeleteMap}
|
||||
onUpdate={onUpdateMap}
|
||||
rowIndex={i + 1}
|
||||
/>
|
||||
)}
|
||||
{isCreatingMap
|
||||
? <ProvidersTableRowNew
|
||||
organizations={organizations}
|
||||
schemes={SCHEMES}
|
||||
onCreate={this.handleCreateMap}
|
||||
onCancel={this.handleCancelCreateMap}
|
||||
rowIndex={mappings.length + 1}
|
||||
/>
|
||||
: null}
|
||||
<div className="fancytable--th provider--arrow" />
|
||||
<div className="fancytable--th provider--redirect">
|
||||
Organization
|
||||
</div>
|
||||
<div className="fancytable--th provider--delete" />
|
||||
</div>
|
||||
: <div className="panel-body">
|
||||
<div className="generic-empty-state">
|
||||
<h4 style={{margin: '50px 0'}}>
|
||||
Looks like you have no mappings<br />
|
||||
New users will not be able to sign up automatically
|
||||
</h4>
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
onClick={this.handleClickCreateMap}
|
||||
disabled={isCreatingMap}
|
||||
>
|
||||
<span className="icon plus" /> Create Mapping
|
||||
</button>
|
||||
</div>
|
||||
</div>}
|
||||
{mappings.map((mapping, i) => (
|
||||
<ProvidersTableRow
|
||||
key={uuid.v4()}
|
||||
mapping={mapping}
|
||||
organizations={organizations}
|
||||
schemes={SCHEMES}
|
||||
onDelete={onDeleteMap}
|
||||
onUpdate={onUpdateMap}
|
||||
rowIndex={i + 1}
|
||||
/>
|
||||
))}
|
||||
{isCreatingMap ? (
|
||||
<ProvidersTableRowNew
|
||||
organizations={organizations}
|
||||
schemes={SCHEMES}
|
||||
onCreate={this.handleCreateMap}
|
||||
onCancel={this.handleCancelCreateMap}
|
||||
rowIndex={mappings.length + 1}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
) : (
|
||||
<div className="panel-body">
|
||||
<div className="generic-empty-state">
|
||||
<h4 style={{margin: '50px 0'}}>
|
||||
Looks like you have no mappings<br />
|
||||
New users will not be able to sign up automatically
|
||||
</h4>
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
onClick={this.handleClickCreateMap}
|
||||
disabled={isCreatingMap}
|
||||
>
|
||||
<span className="icon plus" /> Create Mapping
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -71,13 +71,15 @@ class ProvidersTableRow extends Component {
|
|||
const isDefaultMapping = DEFAULT_MAPPING_ID === mapping.id
|
||||
return (
|
||||
<div className="fancytable--row">
|
||||
<Dropdown
|
||||
items={schemes}
|
||||
onChoose={this.handleChooseScheme}
|
||||
selected={scheme}
|
||||
className="fancytable--td provider--scheme"
|
||||
disabled={isDefaultMapping}
|
||||
/>
|
||||
<div className="fancytable--td provider--scheme">
|
||||
<Dropdown
|
||||
items={schemes}
|
||||
onChoose={this.handleChooseScheme}
|
||||
selected={scheme}
|
||||
className="dropdown-stretch"
|
||||
disabled={isDefaultMapping}
|
||||
/>
|
||||
</div>
|
||||
<InputClickToEdit
|
||||
value={provider}
|
||||
wrapperClass="fancytable--td provider--provider"
|
||||
|
@ -104,20 +106,22 @@ class ProvidersTableRow extends Component {
|
|||
disabled={isDefaultMapping}
|
||||
/>
|
||||
</div>
|
||||
{isDeleting
|
||||
? <ConfirmButtons
|
||||
item={mapping}
|
||||
onCancel={this.handleDismissDeleteConfirmation}
|
||||
onConfirm={this.handleDeleteMap}
|
||||
onClickOutside={this.handleDismissDeleteConfirmation}
|
||||
confirmTitle="Delete"
|
||||
/>
|
||||
: <button
|
||||
className="btn btn-sm btn-default btn-square"
|
||||
onClick={this.handleDeleteClick}
|
||||
>
|
||||
<span className="icon trash" />
|
||||
</button>}
|
||||
{isDeleting ? (
|
||||
<ConfirmButtons
|
||||
item={mapping}
|
||||
onCancel={this.handleDismissDeleteConfirmation}
|
||||
onConfirm={this.handleDeleteMap}
|
||||
onClickOutside={this.handleDismissDeleteConfirmation}
|
||||
confirmTitle="Delete"
|
||||
/>
|
||||
) : (
|
||||
<button
|
||||
className="btn btn-sm btn-default btn-square"
|
||||
onClick={this.handleDeleteClick}
|
||||
>
|
||||
<span className="icon trash" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,12 +4,12 @@ import ConfirmButtons from 'src/shared/components/ConfirmButtons'
|
|||
import Dropdown from 'src/shared/components/Dropdown'
|
||||
import InputClickToEdit from 'src/shared/components/InputClickToEdit'
|
||||
|
||||
type Organization = {
|
||||
interface Organization {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
|
||||
type Scheme = {
|
||||
interface Scheme {
|
||||
text: string
|
||||
}
|
||||
|
||||
|
@ -33,10 +33,10 @@ class ProvidersTableRowNew extends PureComponent<Props, State> {
|
|||
super(props)
|
||||
|
||||
this.state = {
|
||||
scheme: '*',
|
||||
organizationId: 'default',
|
||||
provider: null,
|
||||
providerOrganization: null,
|
||||
organizationId: 'default',
|
||||
scheme: '*',
|
||||
}
|
||||
|
||||
this.handleChooseScheme = this.handleChooseScheme.bind(this)
|
||||
|
@ -46,28 +46,7 @@ class ProvidersTableRowNew extends PureComponent<Props, State> {
|
|||
this.handleSaveNewMapping = this.handleSaveNewMapping.bind(this)
|
||||
}
|
||||
|
||||
handleChooseScheme(scheme: Scheme) {
|
||||
this.setState({scheme: scheme.text})
|
||||
}
|
||||
|
||||
handleChangeProvider(provider: string) {
|
||||
this.setState({provider})
|
||||
}
|
||||
|
||||
handleChangeProviderOrg(providerOrganization: string) {
|
||||
this.setState({providerOrganization})
|
||||
}
|
||||
|
||||
handleChooseOrganization(org: Organization) {
|
||||
this.setState({organizationId: org.id})
|
||||
}
|
||||
|
||||
handleSaveNewMapping() {
|
||||
const {onCreate} = this.props
|
||||
onCreate(this.state)
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
const {scheme, provider, providerOrganization, organizationId} = this.state
|
||||
|
||||
const {organizations, onCancel, schemes, rowIndex} = this.props
|
||||
|
@ -83,12 +62,14 @@ class ProvidersTableRowNew extends PureComponent<Props, State> {
|
|||
|
||||
return (
|
||||
<div className="fancytable--row">
|
||||
<Dropdown
|
||||
items={schemes}
|
||||
onChoose={this.handleChooseScheme}
|
||||
selected={scheme}
|
||||
className={'fancytable--td provider--scheme'}
|
||||
/>
|
||||
<div className="fancytable--td provider--scheme">
|
||||
<Dropdown
|
||||
items={schemes}
|
||||
onChoose={this.handleChooseScheme}
|
||||
selected={scheme}
|
||||
className="dropdown-stretch"
|
||||
/>
|
||||
</div>
|
||||
<InputClickToEdit
|
||||
value={provider}
|
||||
wrapperClass="fancytable--td provider--provider"
|
||||
|
@ -124,6 +105,27 @@ class ProvidersTableRowNew extends PureComponent<Props, State> {
|
|||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private handleChooseScheme(scheme: Scheme) {
|
||||
this.setState({scheme: scheme.text})
|
||||
}
|
||||
|
||||
private handleChangeProvider(provider: string) {
|
||||
this.setState({provider})
|
||||
}
|
||||
|
||||
private handleChangeProviderOrg(providerOrganization: string) {
|
||||
this.setState({providerOrganization})
|
||||
}
|
||||
|
||||
private handleChooseOrganization(org: Organization) {
|
||||
this.setState({organizationId: org.id})
|
||||
}
|
||||
|
||||
private handleSaveNewMapping() {
|
||||
const {onCreate} = this.props
|
||||
onCreate(this.state)
|
||||
}
|
||||
}
|
||||
|
||||
export default ProvidersTableRowNew
|
||||
|
|
|
@ -71,29 +71,31 @@ class UsersTable extends Component {
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{isCreatingUser
|
||||
? <UsersTableRowNew
|
||||
{isCreatingUser ? (
|
||||
<UsersTableRowNew
|
||||
organization={organization}
|
||||
onBlur={this.handleBlurCreateUserRow}
|
||||
onCreateUser={onCreateUser}
|
||||
/>
|
||||
) : null}
|
||||
{users.length ? (
|
||||
users.map(user => (
|
||||
<UsersTableRow
|
||||
user={user}
|
||||
key={uuid.v4()}
|
||||
organization={organization}
|
||||
onBlur={this.handleBlurCreateUserRow}
|
||||
onCreateUser={onCreateUser}
|
||||
onChangeUserRole={this.handleChangeUserRole}
|
||||
onDelete={this.handleDeleteUser}
|
||||
meID={meID}
|
||||
/>
|
||||
: null}
|
||||
{users.length
|
||||
? users.map(user =>
|
||||
<UsersTableRow
|
||||
user={user}
|
||||
key={uuid.v4()}
|
||||
organization={organization}
|
||||
onChangeUserRole={this.handleChangeUserRole}
|
||||
onDelete={this.handleDeleteUser}
|
||||
meID={meID}
|
||||
/>
|
||||
)
|
||||
: <tr className="table-empty-state">
|
||||
<th colSpan="5">
|
||||
<p>No Users to display</p>
|
||||
</th>
|
||||
</tr>}
|
||||
))
|
||||
) : (
|
||||
<tr className="table-empty-state">
|
||||
<th colSpan="5">
|
||||
<p>No Users to display</p>
|
||||
</th>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
@ -29,14 +29,14 @@ const UsersTableRow = ({
|
|||
return (
|
||||
<tr className={'chronograf-admin-table--user'}>
|
||||
<td>
|
||||
{userIsMe
|
||||
? <strong className="chronograf-user--me">
|
||||
<span className="icon user" />
|
||||
{user.name}
|
||||
</strong>
|
||||
: <strong>
|
||||
{user.name}
|
||||
</strong>}
|
||||
{userIsMe ? (
|
||||
<strong className="chronograf-user--me">
|
||||
<span className="icon user" />
|
||||
{user.name}
|
||||
</strong>
|
||||
) : (
|
||||
<strong>{user.name}</strong>
|
||||
)}
|
||||
</td>
|
||||
<td style={{width: colRole}}>
|
||||
<span className="chronograf-user--role">
|
||||
|
@ -50,12 +50,8 @@ const UsersTableRow = ({
|
|||
/>
|
||||
</span>
|
||||
</td>
|
||||
<td style={{width: colProvider}}>
|
||||
{user.provider}
|
||||
</td>
|
||||
<td style={{width: colScheme}}>
|
||||
{user.scheme}
|
||||
</td>
|
||||
<td style={{width: colProvider}}>{user.provider}</td>
|
||||
<td style={{width: colScheme}}>{user.scheme}</td>
|
||||
<DeleteConfirmTableCell
|
||||
text="Remove"
|
||||
onDelete={onDelete}
|
||||
|
|
|
@ -165,37 +165,39 @@ class AdminInfluxDBPage extends Component {
|
|||
</div>
|
||||
</div>
|
||||
<FancyScrollbar className="page-contents">
|
||||
{users
|
||||
? <div className="container-fluid">
|
||||
<div className="row">
|
||||
<AdminTabs
|
||||
users={users}
|
||||
roles={roles}
|
||||
source={source}
|
||||
hasRoles={hasRoles}
|
||||
permissions={allowed}
|
||||
onFilterUsers={filterUsers}
|
||||
onFilterRoles={filterRoles}
|
||||
onEditUser={this.handleEditUser}
|
||||
onEditRole={this.handleEditRole}
|
||||
onSaveUser={this.handleSaveUser}
|
||||
onSaveRole={this.handleSaveRole}
|
||||
onDeleteUser={this.handleDeleteUser}
|
||||
onDeleteRole={this.handleDeleteRole}
|
||||
onClickCreate={this.handleClickCreate}
|
||||
onCancelEditUser={this.handleCancelEditUser}
|
||||
onCancelEditRole={this.handleCancelEditRole}
|
||||
isEditingUsers={users.some(u => u.isEditing)}
|
||||
isEditingRoles={roles.some(r => r.isEditing)}
|
||||
onUpdateRoleUsers={this.handleUpdateRoleUsers}
|
||||
onUpdateUserRoles={this.handleUpdateUserRoles}
|
||||
onUpdateUserPassword={this.handleUpdateUserPassword}
|
||||
onUpdateRolePermissions={this.handleUpdateRolePermissions}
|
||||
onUpdateUserPermissions={this.handleUpdateUserPermissions}
|
||||
/>
|
||||
</div>
|
||||
{users ? (
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<AdminTabs
|
||||
users={users}
|
||||
roles={roles}
|
||||
source={source}
|
||||
hasRoles={hasRoles}
|
||||
permissions={allowed}
|
||||
onFilterUsers={filterUsers}
|
||||
onFilterRoles={filterRoles}
|
||||
onEditUser={this.handleEditUser}
|
||||
onEditRole={this.handleEditRole}
|
||||
onSaveUser={this.handleSaveUser}
|
||||
onSaveRole={this.handleSaveRole}
|
||||
onDeleteUser={this.handleDeleteUser}
|
||||
onDeleteRole={this.handleDeleteRole}
|
||||
onClickCreate={this.handleClickCreate}
|
||||
onCancelEditUser={this.handleCancelEditUser}
|
||||
onCancelEditRole={this.handleCancelEditRole}
|
||||
isEditingUsers={users.some(u => u.isEditing)}
|
||||
isEditingRoles={roles.some(r => r.isEditing)}
|
||||
onUpdateRoleUsers={this.handleUpdateRoleUsers}
|
||||
onUpdateUserRoles={this.handleUpdateUserRoles}
|
||||
onUpdateUserPassword={this.handleUpdateUserPassword}
|
||||
onUpdateRolePermissions={this.handleUpdateRolePermissions}
|
||||
onUpdateUserPermissions={this.handleUpdateUserPermissions}
|
||||
/>
|
||||
</div>
|
||||
: <div className="page-spinner" />}
|
||||
</div>
|
||||
) : (
|
||||
<div className="page-spinner" />
|
||||
)}
|
||||
</FancyScrollbar>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -5,7 +5,7 @@ import {connect} from 'react-redux'
|
|||
import AdminTabs from 'src/admin/components/chronograf/AdminTabs'
|
||||
import FancyScrollbar from 'shared/components/FancyScrollbar'
|
||||
|
||||
const AdminChronografPage = ({me}) =>
|
||||
const AdminChronografPage = ({me}) => (
|
||||
<div className="page">
|
||||
<div className="page-header">
|
||||
<div className="page-header__container">
|
||||
|
@ -22,6 +22,7 @@ const AdminChronografPage = ({me}) =>
|
|||
</div>
|
||||
</FancyScrollbar>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import * as configActionCreators from 'src/shared/actions/config'
|
|||
import {notify as notifyAction} from 'src/shared/actions/notifications'
|
||||
|
||||
import AllUsersTable from 'src/admin/components/chronograf/AllUsersTable'
|
||||
import {AuthLinks, User, Role, Organization} from 'src/types'
|
||||
import {AuthLinks, Organization, Role, User} from 'src/types'
|
||||
|
||||
interface Props {
|
||||
notify: () => void
|
||||
|
@ -47,12 +47,12 @@ export class AllUsersPage extends PureComponent<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
public componentDidMount() {
|
||||
const {links, actionsConfig: {getAuthConfigAsync}} = this.props
|
||||
getAuthConfigAsync(links.config.auth)
|
||||
}
|
||||
|
||||
async componentWillMount() {
|
||||
public async componentWillMount() {
|
||||
const {
|
||||
links,
|
||||
actionsAdmin: {loadOrganizationsAsync, loadUsersAsync},
|
||||
|
@ -68,12 +68,12 @@ export class AllUsersPage extends PureComponent<Props, State> {
|
|||
this.setState({isLoading: false})
|
||||
}
|
||||
|
||||
handleCreateUser = (user: User) => {
|
||||
public handleCreateUser = (user: User) => {
|
||||
const {links, actionsAdmin: {createUserAsync}} = this.props
|
||||
createUserAsync(links.allUsers, user)
|
||||
}
|
||||
|
||||
handleUpdateUserRoles = (
|
||||
public handleUpdateUserRoles = (
|
||||
user: User,
|
||||
roles: Role[],
|
||||
successMessage: string
|
||||
|
@ -83,7 +83,7 @@ export class AllUsersPage extends PureComponent<Props, State> {
|
|||
updateUserAsync(user, updatedUser, successMessage)
|
||||
}
|
||||
|
||||
handleUpdateUserSuperAdmin = (user: User, superAdmin: boolean) => {
|
||||
public handleUpdateUserSuperAdmin = (user: User, superAdmin: boolean) => {
|
||||
const {actionsAdmin: {updateUserAsync}} = this.props
|
||||
const updatedUser = {...user, superAdmin}
|
||||
updateUserAsync(
|
||||
|
@ -93,12 +93,12 @@ export class AllUsersPage extends PureComponent<Props, State> {
|
|||
)
|
||||
}
|
||||
|
||||
handleDeleteUser = (user: User) => {
|
||||
public handleDeleteUser = (user: User) => {
|
||||
const {actionsAdmin: {deleteUserAsync}} = this.props
|
||||
deleteUserAsync(user, {isAbsoluteDelete: true})
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
const {
|
||||
meID,
|
||||
users,
|
||||
|
@ -133,10 +133,10 @@ const mapStateToProps = ({
|
|||
adminChronograf: {organizations, users},
|
||||
config: {auth: authConfig},
|
||||
}) => ({
|
||||
authConfig,
|
||||
links,
|
||||
organizations,
|
||||
users,
|
||||
authConfig,
|
||||
})
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
|
|
|
@ -3,8 +3,10 @@ import {proxy} from 'utils/queryUrlGenerator'
|
|||
export const getAlerts = (source, timeRange, limit) =>
|
||||
proxy({
|
||||
source,
|
||||
query: `SELECT host, value, level, alertName FROM alerts WHERE time >= '${timeRange.lower}' AND time <= '${timeRange.upper}' ORDER BY time desc ${limit
|
||||
? `LIMIT ${limit}`
|
||||
: ''}`,
|
||||
query: `SELECT host, value, level, alertName FROM alerts WHERE time >= '${
|
||||
timeRange.lower
|
||||
}' AND time <= '${timeRange.upper}' ORDER BY time desc ${
|
||||
limit ? `LIMIT ${limit}` : ''
|
||||
}`,
|
||||
db: 'chronograf',
|
||||
})
|
||||
|
|
|
@ -79,121 +79,125 @@ class AlertsTable extends Component {
|
|||
this.state.sortDirection
|
||||
)
|
||||
const {colName, colLevel, colTime, colHost, colValue} = ALERTS_TABLE
|
||||
return this.props.alerts.length
|
||||
? <div className="alert-history-table">
|
||||
<div className="alert-history-table--thead">
|
||||
<div
|
||||
onClick={this.changeSort('name')}
|
||||
className={this.sortableClasses('name')}
|
||||
style={{width: colName}}
|
||||
>
|
||||
Name
|
||||
</div>
|
||||
<div
|
||||
onClick={this.changeSort('level')}
|
||||
className={this.sortableClasses('level')}
|
||||
style={{width: colLevel}}
|
||||
>
|
||||
Level
|
||||
</div>
|
||||
<div
|
||||
onClick={this.changeSort('time')}
|
||||
className={this.sortableClasses('time')}
|
||||
style={{width: colTime}}
|
||||
>
|
||||
Time
|
||||
</div>
|
||||
<div
|
||||
onClick={this.changeSort('host')}
|
||||
className={this.sortableClasses('host')}
|
||||
style={{width: colHost}}
|
||||
>
|
||||
Host
|
||||
</div>
|
||||
<div
|
||||
onClick={this.changeSort('value')}
|
||||
className={this.sortableClasses('value')}
|
||||
style={{width: colValue}}
|
||||
>
|
||||
Value
|
||||
</div>
|
||||
return this.props.alerts.length ? (
|
||||
<div className="alert-history-table">
|
||||
<div className="alert-history-table--thead">
|
||||
<div
|
||||
onClick={this.changeSort('name')}
|
||||
className={this.sortableClasses('name')}
|
||||
style={{width: colName}}
|
||||
>
|
||||
Name
|
||||
</div>
|
||||
<div
|
||||
onClick={this.changeSort('level')}
|
||||
className={this.sortableClasses('level')}
|
||||
style={{width: colLevel}}
|
||||
>
|
||||
Level
|
||||
</div>
|
||||
<div
|
||||
onClick={this.changeSort('time')}
|
||||
className={this.sortableClasses('time')}
|
||||
style={{width: colTime}}
|
||||
>
|
||||
Time
|
||||
</div>
|
||||
<div
|
||||
onClick={this.changeSort('host')}
|
||||
className={this.sortableClasses('host')}
|
||||
style={{width: colHost}}
|
||||
>
|
||||
Host
|
||||
</div>
|
||||
<div
|
||||
onClick={this.changeSort('value')}
|
||||
className={this.sortableClasses('value')}
|
||||
style={{width: colValue}}
|
||||
>
|
||||
Value
|
||||
</div>
|
||||
<InfiniteScroll
|
||||
className="alert-history-table--tbody"
|
||||
itemHeight={25}
|
||||
items={alerts.map(({name, level, time, host, value}) => {
|
||||
return (
|
||||
<div className="alert-history-table--tr" key={uuid.v4()}>
|
||||
<div
|
||||
className="alert-history-table--td"
|
||||
style={{width: colName}}
|
||||
>
|
||||
{name}
|
||||
</div>
|
||||
<div
|
||||
className={`alert-history-table--td alert-level-${level.toLowerCase()}`}
|
||||
style={{width: colLevel}}
|
||||
>
|
||||
<span
|
||||
className={classnames(
|
||||
'table-dot',
|
||||
{'dot-critical': level === 'CRITICAL'},
|
||||
{'dot-success': level === 'OK'}
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="alert-history-table--td"
|
||||
style={{width: colTime}}
|
||||
>
|
||||
{new Date(Number(time)).toISOString()}
|
||||
</div>
|
||||
<div
|
||||
className="alert-history-table--td alert-history-table--host"
|
||||
style={{width: colHost}}
|
||||
>
|
||||
<Link to={`/sources/${id}/hosts/${host}`} title={host}>
|
||||
{host}
|
||||
</Link>
|
||||
</div>
|
||||
<div
|
||||
className="alert-history-table--td"
|
||||
style={{width: colValue}}
|
||||
>
|
||||
{value}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
: this.renderTableEmpty()
|
||||
<InfiniteScroll
|
||||
className="alert-history-table--tbody"
|
||||
itemHeight={25}
|
||||
items={alerts.map(({name, level, time, host, value}) => {
|
||||
return (
|
||||
<div className="alert-history-table--tr" key={uuid.v4()}>
|
||||
<div
|
||||
className="alert-history-table--td"
|
||||
style={{width: colName}}
|
||||
>
|
||||
{name}
|
||||
</div>
|
||||
<div
|
||||
className={`alert-history-table--td alert-level-${level.toLowerCase()}`}
|
||||
style={{width: colLevel}}
|
||||
>
|
||||
<span
|
||||
className={classnames(
|
||||
'table-dot',
|
||||
{'dot-critical': level === 'CRITICAL'},
|
||||
{'dot-success': level === 'OK'}
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="alert-history-table--td"
|
||||
style={{width: colTime}}
|
||||
>
|
||||
{new Date(Number(time)).toISOString()}
|
||||
</div>
|
||||
<div
|
||||
className="alert-history-table--td alert-history-table--host"
|
||||
style={{width: colHost}}
|
||||
>
|
||||
<Link to={`/sources/${id}/hosts/${host}`} title={host}>
|
||||
{host}
|
||||
</Link>
|
||||
</div>
|
||||
<div
|
||||
className="alert-history-table--td"
|
||||
style={{width: colValue}}
|
||||
>
|
||||
{value}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
this.renderTableEmpty()
|
||||
)
|
||||
}
|
||||
|
||||
renderTableEmpty() {
|
||||
const {source: {id}, shouldNotBeFilterable} = this.props
|
||||
|
||||
return shouldNotBeFilterable
|
||||
? <div className="graph-empty">
|
||||
<p>
|
||||
Learn how to configure your first <strong>Rule</strong> in<br />
|
||||
the <em>Getting Started</em> guide
|
||||
</p>
|
||||
</div>
|
||||
: <div className="generic-empty-state">
|
||||
<h4 className="no-user-select">There are no Alerts to display</h4>
|
||||
<br />
|
||||
<h6 className="no-user-select">
|
||||
Try changing the Time Range or
|
||||
<Link
|
||||
style={{marginLeft: '10px'}}
|
||||
to={`/sources/${id}/alert-rules/new`}
|
||||
className="btn btn-primary btn-sm"
|
||||
>
|
||||
Create an Alert Rule
|
||||
</Link>
|
||||
</h6>
|
||||
</div>
|
||||
return shouldNotBeFilterable ? (
|
||||
<div className="graph-empty">
|
||||
<p>
|
||||
Learn how to configure your first <strong>Rule</strong> in<br />
|
||||
the <em>Getting Started</em> guide
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="generic-empty-state">
|
||||
<h4 className="no-user-select">There are no Alerts to display</h4>
|
||||
<br />
|
||||
<h6 className="no-user-select">
|
||||
Try changing the Time Range or
|
||||
<Link
|
||||
style={{marginLeft: '10px'}}
|
||||
to={`/sources/${id}/alert-rules/new`}
|
||||
className="btn btn-primary btn-sm"
|
||||
>
|
||||
Create an Alert Rule
|
||||
</Link>
|
||||
</h6>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -205,35 +209,33 @@ class AlertsTable extends Component {
|
|||
alertsCount,
|
||||
} = this.props
|
||||
|
||||
return shouldNotBeFilterable
|
||||
? <div className="alerts-widget">
|
||||
{this.renderTable()}
|
||||
{limit && alertsCount
|
||||
? <button
|
||||
className="btn btn-sm btn-default btn-block"
|
||||
onClick={onGetMoreAlerts}
|
||||
disabled={isAlertsMaxedOut}
|
||||
style={{marginBottom: '20px'}}
|
||||
>
|
||||
{isAlertsMaxedOut
|
||||
? `All ${alertsCount} Alerts displayed`
|
||||
: 'Load next 30 Alerts'}
|
||||
</button>
|
||||
: null}
|
||||
</div>
|
||||
: <div className="panel">
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">
|
||||
{this.props.alerts.length} Alerts
|
||||
</h2>
|
||||
{this.props.alerts.length
|
||||
? <SearchBar onSearch={this.filterAlerts} />
|
||||
: null}
|
||||
</div>
|
||||
<div className="panel-body">
|
||||
{this.renderTable()}
|
||||
</div>
|
||||
return shouldNotBeFilterable ? (
|
||||
<div className="alerts-widget">
|
||||
{this.renderTable()}
|
||||
{limit && alertsCount ? (
|
||||
<button
|
||||
className="btn btn-sm btn-default btn-block"
|
||||
onClick={onGetMoreAlerts}
|
||||
disabled={isAlertsMaxedOut}
|
||||
style={{marginBottom: '20px'}}
|
||||
>
|
||||
{isAlertsMaxedOut
|
||||
? `All ${alertsCount} Alerts displayed`
|
||||
: 'Load next 30 Alerts'}
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
) : (
|
||||
<div className="panel">
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">{this.props.alerts.length} Alerts</h2>
|
||||
{this.props.alerts.length ? (
|
||||
<SearchBar onSearch={this.filterAlerts} />
|
||||
) : null}
|
||||
</div>
|
||||
<div className="panel-body">{this.renderTable()}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,9 @@ class AlertsApp extends Component {
|
|||
alerts: [],
|
||||
timeRange: {
|
||||
upper: moment().format(),
|
||||
lower: moment().subtract(lowerInSec || oneDayInSec, 'seconds').format(),
|
||||
lower: moment()
|
||||
.subtract(lowerInSec || oneDayInSec, 'seconds')
|
||||
.format(),
|
||||
},
|
||||
limit: props.limit || 0, // only used if AlertsApp receives a limit prop
|
||||
limitMultiplier: 1, // only used if AlertsApp receives a limit prop
|
||||
|
@ -118,17 +120,19 @@ class AlertsApp extends Component {
|
|||
const {source, isWidget, limit} = this.props
|
||||
const {isAlertsMaxedOut, alerts} = this.state
|
||||
|
||||
return this.state.hasKapacitor
|
||||
? <AlertsTable
|
||||
source={source}
|
||||
alerts={this.state.alerts}
|
||||
shouldNotBeFilterable={isWidget}
|
||||
limit={limit}
|
||||
onGetMoreAlerts={this.handleGetMoreAlerts}
|
||||
isAlertsMaxedOut={isAlertsMaxedOut}
|
||||
alertsCount={alerts.length}
|
||||
/>
|
||||
: <NoKapacitorError source={source} />
|
||||
return this.state.hasKapacitor ? (
|
||||
<AlertsTable
|
||||
source={source}
|
||||
alerts={this.state.alerts}
|
||||
shouldNotBeFilterable={isWidget}
|
||||
limit={limit}
|
||||
onGetMoreAlerts={this.handleGetMoreAlerts}
|
||||
isAlertsMaxedOut={isAlertsMaxedOut}
|
||||
alertsCount={alerts.length}
|
||||
/>
|
||||
) : (
|
||||
<NoKapacitorError source={source} />
|
||||
)
|
||||
}
|
||||
|
||||
handleApplyTime = timeRange => {
|
||||
|
@ -143,33 +147,33 @@ class AlertsApp extends Component {
|
|||
return <div className="page-spinner" />
|
||||
}
|
||||
|
||||
return isWidget
|
||||
? this.renderSubComponents()
|
||||
: <div className="page alert-history-page">
|
||||
<div className="page-header">
|
||||
<div className="page-header__container">
|
||||
<div className="page-header__left">
|
||||
<h1 className="page-header__title">Alert History</h1>
|
||||
</div>
|
||||
<div className="page-header__right">
|
||||
<SourceIndicator />
|
||||
<CustomTimeRangeDropdown
|
||||
onApplyTimeRange={this.handleApplyTime}
|
||||
timeRange={timeRange}
|
||||
/>
|
||||
</div>
|
||||
return isWidget ? (
|
||||
this.renderSubComponents()
|
||||
) : (
|
||||
<div className="page alert-history-page">
|
||||
<div className="page-header">
|
||||
<div className="page-header__container">
|
||||
<div className="page-header__left">
|
||||
<h1 className="page-header__title">Alert History</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div className="page-contents">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
{this.renderSubComponents()}
|
||||
</div>
|
||||
</div>
|
||||
<div className="page-header__right">
|
||||
<SourceIndicator />
|
||||
<CustomTimeRangeDropdown
|
||||
onApplyTimeRange={this.handleApplyTime}
|
||||
timeRange={timeRange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="page-contents">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-md-12">{this.renderSubComponents()}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,12 +20,12 @@ const Login = ({authData: {auth}}) => {
|
|||
<strong>{VERSION}</strong> / Time-Series Data Visualization
|
||||
</p>
|
||||
{auth.links &&
|
||||
auth.links.map(({name, login, label}) =>
|
||||
auth.links.map(({name, login, label}) => (
|
||||
<a key={name} className="btn btn-primary" href={login}>
|
||||
<span className={`icon ${name}`} />
|
||||
Log in with {label}
|
||||
</a>
|
||||
)}
|
||||
))}
|
||||
</SplashPage>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -65,31 +65,31 @@ class Purgatory extends Component {
|
|||
<Notifications />
|
||||
<SplashPage>
|
||||
<div className="auth--purgatory">
|
||||
<h3>
|
||||
{name}
|
||||
</h3>
|
||||
<h3>{name}</h3>
|
||||
<h6>
|
||||
{subHeading}{' '}
|
||||
<code>
|
||||
{scheme}/{provider}
|
||||
</code>
|
||||
</h6>
|
||||
{rolesAndOrgs.length
|
||||
? <div className="auth--list">
|
||||
{rolesAndOrgs.map((rag, i) =>
|
||||
<PurgatoryAuthItem
|
||||
key={i}
|
||||
roleAndOrg={rag}
|
||||
superAdmin={superAdmin}
|
||||
onClickLogin={handleClickLogin({
|
||||
router,
|
||||
links,
|
||||
meChangeOrganization,
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
: <p>You are a Lost Soul</p>}
|
||||
{rolesAndOrgs.length ? (
|
||||
<div className="auth--list">
|
||||
{rolesAndOrgs.map((rag, i) => (
|
||||
<PurgatoryAuthItem
|
||||
key={i}
|
||||
roleAndOrg={rag}
|
||||
superAdmin={superAdmin}
|
||||
onClickLogin={handleClickLogin({
|
||||
router,
|
||||
links,
|
||||
meChangeOrganization,
|
||||
})}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p>You are a Lost Soul</p>
|
||||
)}
|
||||
<a href={logoutLink} className="btn btn-sm btn-link auth--logout">
|
||||
Log out
|
||||
</a>
|
||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
|||
|
||||
import {isUserAuthorized, VIEWER_ROLE} from 'src/auth/Authorized'
|
||||
|
||||
const PurgatoryAuthItem = ({roleAndOrg, onClickLogin, superAdmin}) =>
|
||||
const PurgatoryAuthItem = ({roleAndOrg, onClickLogin, superAdmin}) => (
|
||||
<div
|
||||
className={
|
||||
roleAndOrg.currentOrganization
|
||||
|
@ -12,24 +12,23 @@ const PurgatoryAuthItem = ({roleAndOrg, onClickLogin, superAdmin}) =>
|
|||
}
|
||||
>
|
||||
<div className="auth--list-info">
|
||||
<div className="auth--list-org">
|
||||
{roleAndOrg.organization.name}
|
||||
</div>
|
||||
<div className="auth--list-role">
|
||||
{roleAndOrg.role}
|
||||
</div>
|
||||
<div className="auth--list-org">{roleAndOrg.organization.name}</div>
|
||||
<div className="auth--list-role">{roleAndOrg.role}</div>
|
||||
</div>
|
||||
{superAdmin || isUserAuthorized(roleAndOrg.role, VIEWER_ROLE)
|
||||
? <button
|
||||
className="btn btn-sm btn-primary"
|
||||
onClick={onClickLogin(roleAndOrg.organization)}
|
||||
>
|
||||
Log in
|
||||
</button>
|
||||
: <span className="auth--list-blocked">
|
||||
Contact your Admin<br />for access
|
||||
</span>}
|
||||
{superAdmin || isUserAuthorized(roleAndOrg.role, VIEWER_ROLE) ? (
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
onClick={onClickLogin(roleAndOrg.organization)}
|
||||
>
|
||||
Log in
|
||||
</button>
|
||||
) : (
|
||||
<span className="auth--list-blocked">
|
||||
Contact your Admin<br />for access
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
const {bool, func, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -91,9 +91,7 @@ class AxesOptions extends Component {
|
|||
autoHide={false}
|
||||
>
|
||||
<div className="display-options--cell-wrapper">
|
||||
<h5 className="display-options--header">
|
||||
{menuOption} Controls
|
||||
</h5>
|
||||
<h5 className="display-options--header">{menuOption} Controls</h5>
|
||||
<form autoComplete="off" className="form-group-wrapper">
|
||||
<div className="form-group col-sm-12">
|
||||
<label htmlFor="prefix">Title</label>
|
||||
|
|
|
@ -318,27 +318,29 @@ class CellEditorOverlay extends Component {
|
|||
isDisplayOptionsTabActive={isDisplayOptionsTabActive}
|
||||
onClickDisplayOptions={this.handleClickDisplayOptionsTab}
|
||||
/>
|
||||
{isDisplayOptionsTabActive
|
||||
? <DisplayOptions
|
||||
queryConfigs={queriesWorkingDraft}
|
||||
onToggleStaticLegend={this.handleToggleStaticLegend}
|
||||
staticLegend={staticLegend}
|
||||
onResetFocus={this.handleResetFocus}
|
||||
/>
|
||||
: <QueryMaker
|
||||
source={this.getSource()}
|
||||
templates={templates}
|
||||
queries={queriesWorkingDraft}
|
||||
actions={queryActions}
|
||||
autoRefresh={autoRefresh}
|
||||
timeRange={timeRange}
|
||||
onDeleteQuery={this.handleDeleteQuery}
|
||||
onAddQuery={this.handleAddQuery}
|
||||
activeQueryIndex={activeQueryIndex}
|
||||
activeQuery={this.getActiveQuery()}
|
||||
setActiveQueryIndex={this.handleSetActiveQueryIndex}
|
||||
initialGroupByTime={AUTO_GROUP_BY}
|
||||
/>}
|
||||
{isDisplayOptionsTabActive ? (
|
||||
<DisplayOptions
|
||||
queryConfigs={queriesWorkingDraft}
|
||||
onToggleStaticLegend={this.handleToggleStaticLegend}
|
||||
staticLegend={staticLegend}
|
||||
onResetFocus={this.handleResetFocus}
|
||||
/>
|
||||
) : (
|
||||
<QueryMaker
|
||||
source={this.getSource()}
|
||||
templates={templates}
|
||||
queries={queriesWorkingDraft}
|
||||
actions={queryActions}
|
||||
autoRefresh={autoRefresh}
|
||||
timeRange={timeRange}
|
||||
onDeleteQuery={this.handleDeleteQuery}
|
||||
onAddQuery={this.handleAddQuery}
|
||||
activeQueryIndex={activeQueryIndex}
|
||||
activeQuery={this.getActiveQuery()}
|
||||
setActiveQueryIndex={this.handleSetActiveQueryIndex}
|
||||
initialGroupByTime={AUTO_GROUP_BY}
|
||||
/>
|
||||
)}
|
||||
</CEOBottom>
|
||||
</ResizeContainer>
|
||||
</div>
|
||||
|
@ -346,10 +348,9 @@ class CellEditorOverlay extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
const CEOBottom = ({children}) =>
|
||||
<div className="overlay-technology--editor">
|
||||
{children}
|
||||
</div>
|
||||
const CEOBottom = ({children}) => (
|
||||
<div className="overlay-technology--editor">{children}</div>
|
||||
)
|
||||
|
||||
const {arrayOf, func, node, number, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -49,37 +49,39 @@ const Dashboard = ({
|
|||
setScrollTop={setScrollTop}
|
||||
>
|
||||
<div className="dashboard container-fluid full-width">
|
||||
{inPresentationMode
|
||||
? null
|
||||
: <TemplateControlBar
|
||||
templates={dashboard.templates}
|
||||
onSelectTemplate={onSelectTemplate}
|
||||
onOpenTemplateManager={onOpenTemplateManager}
|
||||
isOpen={showTemplateControlBar}
|
||||
/>}
|
||||
{cells.length
|
||||
? <LayoutRenderer
|
||||
cells={cells}
|
||||
onZoom={onZoom}
|
||||
source={source}
|
||||
sources={sources}
|
||||
isEditable={true}
|
||||
timeRange={timeRange}
|
||||
autoRefresh={autoRefresh}
|
||||
manualRefresh={manualRefresh}
|
||||
hoverTime={hoverTime}
|
||||
onSetHoverTime={onSetHoverTime}
|
||||
onDeleteCell={onDeleteCell}
|
||||
onPositionChange={onPositionChange}
|
||||
templates={templatesIncludingDashTime}
|
||||
onSummonOverlayTechnologies={onSummonOverlayTechnologies}
|
||||
/>
|
||||
: <div className="dashboard__empty">
|
||||
<p>This Dashboard has no Cells</p>
|
||||
<button className="btn btn-primary btn-m" onClick={onAddCell}>
|
||||
<span className="icon plus" />Add a Cell
|
||||
</button>
|
||||
</div>}
|
||||
{inPresentationMode ? null : (
|
||||
<TemplateControlBar
|
||||
templates={dashboard.templates}
|
||||
onSelectTemplate={onSelectTemplate}
|
||||
onOpenTemplateManager={onOpenTemplateManager}
|
||||
isOpen={showTemplateControlBar}
|
||||
/>
|
||||
)}
|
||||
{cells.length ? (
|
||||
<LayoutRenderer
|
||||
cells={cells}
|
||||
onZoom={onZoom}
|
||||
source={source}
|
||||
sources={sources}
|
||||
isEditable={true}
|
||||
timeRange={timeRange}
|
||||
autoRefresh={autoRefresh}
|
||||
manualRefresh={manualRefresh}
|
||||
hoverTime={hoverTime}
|
||||
onSetHoverTime={onSetHoverTime}
|
||||
onDeleteCell={onDeleteCell}
|
||||
onPositionChange={onPositionChange}
|
||||
templates={templatesIncludingDashTime}
|
||||
onSummonOverlayTechnologies={onSummonOverlayTechnologies}
|
||||
/>
|
||||
) : (
|
||||
<div className="dashboard__empty">
|
||||
<p>This Dashboard has no Cells</p>
|
||||
<button className="btn btn-primary btn-m" onClick={onAddCell}>
|
||||
<span className="icon plus" />Add a Cell
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</FancyScrollbar>
|
||||
)
|
||||
|
|
|
@ -31,90 +31,85 @@ const DashboardHeader = ({
|
|||
handleClickPresentationButton,
|
||||
zoomedTimeRange: {zoomedLower, zoomedUpper},
|
||||
}) =>
|
||||
isHidden
|
||||
? null
|
||||
: <div className="page-header full-width">
|
||||
<div className="page-header__container">
|
||||
<div
|
||||
className={
|
||||
dashboard
|
||||
? 'page-header__left page-header__dash-editable'
|
||||
: 'page-header__left'
|
||||
}
|
||||
>
|
||||
{names && names.length > 1
|
||||
? <DashboardSwitcher
|
||||
names={names}
|
||||
activeDashboard={activeDashboard}
|
||||
/>
|
||||
: null}
|
||||
{dashboard
|
||||
? <Authorized
|
||||
requiredRole={EDITOR_ROLE}
|
||||
replaceWithIfNotAuthorized={
|
||||
<h1 className="page-header__title">
|
||||
{activeDashboard}
|
||||
</h1>
|
||||
}
|
||||
>
|
||||
<DashboardHeaderEdit
|
||||
onSave={onSave}
|
||||
onCancel={onCancel}
|
||||
activeDashboard={activeDashboard}
|
||||
onEditDashboard={onEditDashboard}
|
||||
isEditMode={isEditMode}
|
||||
/>
|
||||
</Authorized>
|
||||
: <h1 className="page-header__title">
|
||||
{activeDashboard}
|
||||
</h1>}
|
||||
</div>
|
||||
<div className="page-header__right">
|
||||
<GraphTips />
|
||||
<SourceIndicator />
|
||||
{dashboard
|
||||
? <Authorized requiredRole={EDITOR_ROLE}>
|
||||
<button
|
||||
className="btn btn-primary btn-sm"
|
||||
onClick={onAddCell}
|
||||
>
|
||||
<span className="icon plus" />
|
||||
Add Cell
|
||||
</button>
|
||||
</Authorized>
|
||||
: null}
|
||||
{dashboard
|
||||
? <div
|
||||
className={classnames('btn btn-default btn-sm', {
|
||||
active: showTemplateControlBar,
|
||||
})}
|
||||
onClick={onToggleTempVarControls}
|
||||
>
|
||||
<span className="icon cube" />Template Variables
|
||||
</div>
|
||||
: null}
|
||||
<AutoRefreshDropdown
|
||||
onChoose={handleChooseAutoRefresh}
|
||||
onManualRefresh={onManualRefresh}
|
||||
selected={autoRefresh}
|
||||
iconName="refresh"
|
||||
isHidden ? null : (
|
||||
<div className="page-header full-width">
|
||||
<div className="page-header__container">
|
||||
<div
|
||||
className={
|
||||
dashboard
|
||||
? 'page-header__left page-header__dash-editable'
|
||||
: 'page-header__left'
|
||||
}
|
||||
>
|
||||
{names && names.length > 1 ? (
|
||||
<DashboardSwitcher
|
||||
names={names}
|
||||
activeDashboard={activeDashboard}
|
||||
/>
|
||||
<TimeRangeDropdown
|
||||
onChooseTimeRange={handleChooseTimeRange}
|
||||
selected={{
|
||||
upper: zoomedUpper || upper,
|
||||
lower: zoomedLower || lower,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="btn btn-default btn-sm btn-square"
|
||||
onClick={handleClickPresentationButton}
|
||||
) : null}
|
||||
{dashboard ? (
|
||||
<Authorized
|
||||
requiredRole={EDITOR_ROLE}
|
||||
replaceWithIfNotAuthorized={
|
||||
<h1 className="page-header__title">{activeDashboard}</h1>
|
||||
}
|
||||
>
|
||||
<span className="icon expand-a" />
|
||||
<DashboardHeaderEdit
|
||||
onSave={onSave}
|
||||
onCancel={onCancel}
|
||||
activeDashboard={activeDashboard}
|
||||
onEditDashboard={onEditDashboard}
|
||||
isEditMode={isEditMode}
|
||||
/>
|
||||
</Authorized>
|
||||
) : (
|
||||
<h1 className="page-header__title">{activeDashboard}</h1>
|
||||
)}
|
||||
</div>
|
||||
<div className="page-header__right">
|
||||
<GraphTips />
|
||||
<SourceIndicator />
|
||||
{dashboard ? (
|
||||
<Authorized requiredRole={EDITOR_ROLE}>
|
||||
<button className="btn btn-primary btn-sm" onClick={onAddCell}>
|
||||
<span className="icon plus" />
|
||||
Add Cell
|
||||
</button>
|
||||
</Authorized>
|
||||
) : null}
|
||||
{dashboard ? (
|
||||
<div
|
||||
className={classnames('btn btn-default btn-sm', {
|
||||
active: showTemplateControlBar,
|
||||
})}
|
||||
onClick={onToggleTempVarControls}
|
||||
>
|
||||
<span className="icon cube" />Template Variables
|
||||
</div>
|
||||
) : null}
|
||||
<AutoRefreshDropdown
|
||||
onChoose={handleChooseAutoRefresh}
|
||||
onManualRefresh={onManualRefresh}
|
||||
selected={autoRefresh}
|
||||
iconName="refresh"
|
||||
/>
|
||||
<TimeRangeDropdown
|
||||
onChooseTimeRange={handleChooseTimeRange}
|
||||
selected={{
|
||||
upper: zoomedUpper || upper,
|
||||
lower: zoomedLower || lower,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="btn btn-default btn-sm btn-square"
|
||||
onClick={handleClickPresentationButton}
|
||||
>
|
||||
<span className="icon expand-a" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, bool, func, number, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -46,24 +46,24 @@ class DashboardEditHeader extends Component {
|
|||
|
||||
return (
|
||||
<div className="dashboard-title">
|
||||
{isEditMode
|
||||
? <input
|
||||
maxLength={DASHBOARD_NAME_MAX_LENGTH}
|
||||
type="text"
|
||||
className="dashboard-title--input form-control input-sm"
|
||||
defaultValue={activeDashboard}
|
||||
autoComplete="off"
|
||||
autoFocus={true}
|
||||
spellCheck={false}
|
||||
onBlur={this.handleInputBlur}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
onFocus={this.handleFocus}
|
||||
placeholder="Name this Dashboard"
|
||||
ref={r => (this.inputRef = r)}
|
||||
/>
|
||||
: <h1 onClick={onEditDashboard}>
|
||||
{activeDashboard}
|
||||
</h1>}
|
||||
{isEditMode ? (
|
||||
<input
|
||||
maxLength={DASHBOARD_NAME_MAX_LENGTH}
|
||||
type="text"
|
||||
className="dashboard-title--input form-control input-sm"
|
||||
defaultValue={activeDashboard}
|
||||
autoComplete="off"
|
||||
autoFocus={true}
|
||||
spellCheck={false}
|
||||
onBlur={this.handleInputBlur}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
onFocus={this.handleFocus}
|
||||
placeholder="Name this Dashboard"
|
||||
ref={r => (this.inputRef = r)}
|
||||
/>
|
||||
) : (
|
||||
<h1 onClick={onEditDashboard}>{activeDashboard}</h1>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ class DashboardSwitcher extends Component {
|
|||
<span className="icon dash-f" />
|
||||
</button>
|
||||
<ul className="dropdown-menu">
|
||||
{sorted.map(({name, link}) =>
|
||||
{sorted.map(({name, link}) => (
|
||||
<NameLink
|
||||
key={link}
|
||||
name={name}
|
||||
|
@ -50,14 +50,14 @@ class DashboardSwitcher extends Component {
|
|||
activeName={activeDashboard}
|
||||
onClose={this.handleCloseMenu}
|
||||
/>
|
||||
)}
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const NameLink = ({name, link, activeName, onClose}) =>
|
||||
const NameLink = ({name, link, activeName, onClose}) => (
|
||||
<li
|
||||
className={classnames('dropdown-item', {
|
||||
active: name === activeName,
|
||||
|
@ -67,6 +67,7 @@ const NameLink = ({name, link, activeName, onClose}) =>
|
|||
{name}
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
|
||||
const {arrayOf, func, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||
|
||||
import SourceIndicator from 'shared/components/SourceIndicator'
|
||||
|
||||
const DashboardsHeader = () =>
|
||||
const DashboardsHeader = () => (
|
||||
<div className="page-header">
|
||||
<div className="page-header__container">
|
||||
<div className="page-header__left">
|
||||
|
@ -13,5 +13,6 @@ const DashboardsHeader = () =>
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
export default DashboardsHeader
|
||||
|
|
|
@ -48,9 +48,7 @@ class DashboardsPageContents extends Component {
|
|||
<div className="col-md-12">
|
||||
<div className="panel">
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">
|
||||
{tableHeader}
|
||||
</h2>
|
||||
<h2 className="panel-title">{tableHeader}</h2>
|
||||
<div className="dashboards-page--actions">
|
||||
<SearchBar
|
||||
placeholder="Filter by Name..."
|
||||
|
|
|
@ -7,7 +7,7 @@ import Authorized, {EDITOR_ROLE} from 'src/auth/Authorized'
|
|||
|
||||
import DeleteConfirmTableCell from 'shared/components/DeleteConfirmTableCell'
|
||||
|
||||
const AuthorizedEmptyState = ({onCreateDashboard}) =>
|
||||
const AuthorizedEmptyState = ({onCreateDashboard}) => (
|
||||
<div className="generic-empty-state">
|
||||
<h4 style={{marginTop: '90px'}}>
|
||||
Looks like you don’t have any dashboards
|
||||
|
@ -21,6 +21,7 @@ const AuthorizedEmptyState = ({onCreateDashboard}) =>
|
|||
<span className="icon plus" /> Create Dashboard
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
|
||||
const unauthorizedEmptyState = (
|
||||
<div className="generic-empty-state">
|
||||
|
@ -34,52 +35,56 @@ const DashboardsTable = ({
|
|||
onCreateDashboard,
|
||||
dashboardLink,
|
||||
}) => {
|
||||
return dashboards && dashboards.length
|
||||
? <table className="table v-center admin-table table-highlight">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Template Variables</th>
|
||||
<th />
|
||||
return dashboards && dashboards.length ? (
|
||||
<table className="table v-center admin-table table-highlight">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Template Variables</th>
|
||||
<th />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{_.sortBy(dashboards, d => d.name.toLowerCase()).map(dashboard => (
|
||||
<tr key={dashboard.id}>
|
||||
<td>
|
||||
<Link to={`${dashboardLink}/dashboards/${dashboard.id}`}>
|
||||
{dashboard.name}
|
||||
</Link>
|
||||
</td>
|
||||
<td>
|
||||
{dashboard.templates.length ? (
|
||||
dashboard.templates.map(tv => (
|
||||
<code className="table--temp-var" key={tv.id}>
|
||||
{tv.tempVar}
|
||||
</code>
|
||||
))
|
||||
) : (
|
||||
<span className="empty-string">None</span>
|
||||
)}
|
||||
</td>
|
||||
<Authorized
|
||||
requiredRole={EDITOR_ROLE}
|
||||
replaceWithIfNotAuthorized={<td />}
|
||||
>
|
||||
<DeleteConfirmTableCell
|
||||
onDelete={onDeleteDashboard}
|
||||
item={dashboard}
|
||||
buttonSize="btn-xs"
|
||||
/>
|
||||
</Authorized>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{_.sortBy(dashboards, d => d.name.toLowerCase()).map(dashboard =>
|
||||
<tr key={dashboard.id}>
|
||||
<td>
|
||||
<Link to={`${dashboardLink}/dashboards/${dashboard.id}`}>
|
||||
{dashboard.name}
|
||||
</Link>
|
||||
</td>
|
||||
<td>
|
||||
{dashboard.templates.length
|
||||
? dashboard.templates.map(tv =>
|
||||
<code className="table--temp-var" key={tv.id}>
|
||||
{tv.tempVar}
|
||||
</code>
|
||||
)
|
||||
: <span className="empty-string">None</span>}
|
||||
</td>
|
||||
<Authorized
|
||||
requiredRole={EDITOR_ROLE}
|
||||
replaceWithIfNotAuthorized={<td />}
|
||||
>
|
||||
<DeleteConfirmTableCell
|
||||
onDelete={onDeleteDashboard}
|
||||
item={dashboard}
|
||||
buttonSize="btn-xs"
|
||||
/>
|
||||
</Authorized>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
: <Authorized
|
||||
requiredRole={EDITOR_ROLE}
|
||||
replaceWithIfNotAuthorized={unauthorizedEmptyState}
|
||||
>
|
||||
<AuthorizedEmptyState onCreateDashboard={onCreateDashboard} />
|
||||
</Authorized>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
) : (
|
||||
<Authorized
|
||||
requiredRole={EDITOR_ROLE}
|
||||
replaceWithIfNotAuthorized={unauthorizedEmptyState}
|
||||
>
|
||||
<AuthorizedEmptyState onCreateDashboard={onCreateDashboard} />
|
||||
</Authorized>
|
||||
)
|
||||
}
|
||||
|
||||
const {arrayOf, func, shape, string} = PropTypes
|
||||
|
|
|
@ -9,11 +9,9 @@ const DisplayOptionsInput = ({
|
|||
labelText,
|
||||
colWidth,
|
||||
placeholder,
|
||||
}) =>
|
||||
}) => (
|
||||
<div className={`form-group ${colWidth}`}>
|
||||
<label htmlFor={name}>
|
||||
{labelText}
|
||||
</label>
|
||||
<label htmlFor={name}>{labelText}</label>
|
||||
<input
|
||||
className="form-control input-sm"
|
||||
type="text"
|
||||
|
@ -24,6 +22,7 @@ const DisplayOptionsInput = ({
|
|||
placeholder={placeholder}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {func, string} = PropTypes
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ class GaugeOptions extends Component {
|
|||
>
|
||||
<span className="icon plus" /> Add Threshold
|
||||
</button>
|
||||
{gaugeColors.map(color =>
|
||||
{gaugeColors.map(color => (
|
||||
<Threshold
|
||||
isMin={color.value === gaugeColors[0].value}
|
||||
isMax={
|
||||
|
@ -189,7 +189,7 @@ class GaugeOptions extends Component {
|
|||
onDeleteThreshold={this.handleDeleteThreshold}
|
||||
onSortColors={this.handleSortColors}
|
||||
/>
|
||||
)}
|
||||
))}
|
||||
</div>
|
||||
<div className="graph-options-group form-group-wrapper">
|
||||
<div className="form-group col-xs-6">
|
||||
|
|
|
@ -2,7 +2,7 @@ import React, {PureComponent} from 'react'
|
|||
|
||||
import InputClickToEdit from 'src/shared/components/InputClickToEdit'
|
||||
|
||||
type Column = {
|
||||
interface Column {
|
||||
internalName: string
|
||||
displayName: string
|
||||
}
|
||||
|
@ -20,19 +20,17 @@ class GraphOptionsCustomizableColumn extends PureComponent<Props, {}> {
|
|||
this.handleColumnRename = this.handleColumnRename.bind(this)
|
||||
}
|
||||
|
||||
handleColumnRename(rename) {
|
||||
public handleColumnRename(rename) {
|
||||
const {onColumnRename, internalName} = this.props
|
||||
onColumnRename({internalName, displayName: rename})
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
const {internalName, displayName} = this.props
|
||||
|
||||
return (
|
||||
<div className="column-controls--section">
|
||||
<div className="column-controls--label">
|
||||
{internalName}
|
||||
</div>
|
||||
<div className="column-controls--label">{internalName}</div>
|
||||
<InputClickToEdit
|
||||
value={displayName}
|
||||
wrapperClass="column-controls-input"
|
||||
|
|
|
@ -3,7 +3,7 @@ import React, {SFC} from 'react'
|
|||
import GraphOptionsCustomizableColumn from 'src/dashboards/components/GraphOptionsCustomizableColumn'
|
||||
import uuid from 'uuid'
|
||||
|
||||
type Column = {
|
||||
interface Column {
|
||||
internalName: string
|
||||
displayName: string
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import React, {SFC} from 'react'
|
||||
|
||||
interface Props {
|
||||
fixed: boolean
|
||||
onToggleFixFirstColumn: () => void
|
||||
}
|
||||
|
||||
const GraphOptionsFixFirstColumn: SFC<Props> = ({
|
||||
fixed,
|
||||
onToggleFixFirstColumn,
|
||||
}) => (
|
||||
<div className="form-group col-xs-12">
|
||||
<div className="form-control-static">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="fixFirstColumnCheckbox"
|
||||
checked={!!fixed}
|
||||
onChange={onToggleFixFirstColumn}
|
||||
/>
|
||||
<label htmlFor="fixFirstColumnCheckbox">Fix First Column</label>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
export default GraphOptionsFixFirstColumn
|
|
@ -1,29 +0,0 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Dropdown from 'shared/components/Dropdown'
|
||||
|
||||
const GraphOptionsSortBy = ({sortByOptions, onChooseSortBy}) =>
|
||||
<div className="form-group col-xs-6">
|
||||
<label>Sort By</label>
|
||||
<Dropdown
|
||||
items={sortByOptions}
|
||||
selected={sortByOptions[0].text}
|
||||
buttonColor="btn-default"
|
||||
buttonSize="btn-sm"
|
||||
className="dropdown-stretch"
|
||||
onChoose={onChooseSortBy}
|
||||
/>
|
||||
</div>
|
||||
|
||||
const {arrayOf, func, shape, string} = PropTypes
|
||||
|
||||
GraphOptionsSortBy.propTypes = {
|
||||
sortByOptions: arrayOf(
|
||||
shape({
|
||||
text: string.isRequired,
|
||||
}).isRequired
|
||||
),
|
||||
onChooseSortBy: func,
|
||||
}
|
||||
|
||||
export default GraphOptionsSortBy
|
|
@ -0,0 +1,42 @@
|
|||
import React from 'react'
|
||||
import Dropdown from 'src/shared/components/Dropdown'
|
||||
|
||||
interface Option {
|
||||
text: string
|
||||
key: string
|
||||
}
|
||||
|
||||
interface TableColumn {
|
||||
internalName: string
|
||||
displayName: string
|
||||
}
|
||||
|
||||
interface Props {
|
||||
sortByOptions: any[]
|
||||
onChooseSortBy: (option: Option) => void
|
||||
selected: TableColumn
|
||||
}
|
||||
|
||||
const GraphOptionsSortBy = ({
|
||||
sortByOptions,
|
||||
onChooseSortBy,
|
||||
selected,
|
||||
}: Props) => {
|
||||
const selectedValue = selected.displayName || selected.internalName
|
||||
|
||||
return (
|
||||
<div className="form-group col-xs-6">
|
||||
<label>Sort By</label>
|
||||
<Dropdown
|
||||
items={sortByOptions}
|
||||
selected={selectedValue}
|
||||
buttonColor="btn-default"
|
||||
buttonSize="btn-sm"
|
||||
className="dropdown-stretch"
|
||||
onChoose={onChooseSortBy}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default GraphOptionsSortBy
|
|
@ -16,25 +16,25 @@ const GraphOptionsTextWrapping = ({
|
|||
<label>Text Wrapping</label>
|
||||
<ul className="nav nav-tablist nav-tablist-sm">
|
||||
<li
|
||||
className={`${thresholdsListType === THRESHOLD_TYPE_BG
|
||||
? 'active'
|
||||
: ''}`}
|
||||
className={`${
|
||||
thresholdsListType === THRESHOLD_TYPE_BG ? 'active' : ''
|
||||
}`}
|
||||
onClick={onToggleTextWrapping}
|
||||
>
|
||||
Truncate
|
||||
</li>
|
||||
<li
|
||||
className={`${thresholdsListType === THRESHOLD_TYPE_TEXT
|
||||
? 'active'
|
||||
: ''}`}
|
||||
className={`${
|
||||
thresholdsListType === THRESHOLD_TYPE_TEXT ? 'active' : ''
|
||||
}`}
|
||||
onClick={onToggleTextWrapping}
|
||||
>
|
||||
Wrap
|
||||
</li>
|
||||
<li
|
||||
className={`${thresholdsListType === THRESHOLD_TYPE_BG
|
||||
? 'active'
|
||||
: ''}`}
|
||||
className={`${
|
||||
thresholdsListType === THRESHOLD_TYPE_BG ? 'active' : ''
|
||||
}`}
|
||||
onClick={onToggleTextWrapping}
|
||||
>
|
||||
Single Line
|
||||
|
|
|
@ -1,29 +1,31 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
const VERTICAL = 'VERTICAL'
|
||||
const HORIZONTAL = 'HORIZONTAL'
|
||||
const GraphOptionsTimeAxis = ({TimeAxis, onToggleTimeAxis}) =>
|
||||
const GraphOptionsTimeAxis = ({verticalTimeAxis, onToggleVerticalTimeAxis}) => (
|
||||
<div className="form-group col-xs-12 col-sm-6">
|
||||
<label>Time Axis</label>
|
||||
<ul className="nav nav-tablist nav-tablist-sm">
|
||||
<li
|
||||
className={`${TimeAxis === VERTICAL ? 'active' : ''}`}
|
||||
onClick={onToggleTimeAxis}
|
||||
className={verticalTimeAxis ? 'active' : ''}
|
||||
onClick={onToggleVerticalTimeAxis(true)}
|
||||
>
|
||||
Vertical
|
||||
</li>
|
||||
<li
|
||||
className={`${TimeAxis === HORIZONTAL ? 'active' : ''}`}
|
||||
onClick={onToggleTimeAxis}
|
||||
className={verticalTimeAxis ? '' : 'active'}
|
||||
onClick={onToggleVerticalTimeAxis(false)}
|
||||
>
|
||||
Horizontal
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {func, string} = PropTypes
|
||||
const {bool, func} = PropTypes
|
||||
|
||||
GraphOptionsTimeAxis.propTypes = {TimeAxis: string, onToggleTimeAxis: func}
|
||||
GraphOptionsTimeAxis.propTypes = {
|
||||
verticalTimeAxis: bool,
|
||||
onToggleVerticalTimeAxis: func,
|
||||
}
|
||||
|
||||
export default GraphOptionsTimeAxis
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import React, {PureComponent} from 'react'
|
||||
import InputClickToEdit from 'src/shared/components/InputClickToEdit'
|
||||
import {Dropdown} from 'src/shared/components/Dropdown'
|
||||
import InputClickToEdit from 'src/shared/components/InputClickToEdit'
|
||||
import QuestionMarkTooltip from 'src/shared/components/QuestionMarkTooltip'
|
||||
import {
|
||||
FORMAT_OPTIONS,
|
||||
TIME_FORMAT_DEFAULT,
|
||||
TIME_FORMAT_CUSTOM,
|
||||
TIME_FORMAT_DEFAULT,
|
||||
} from 'src/shared/constants/tableGraph'
|
||||
|
||||
interface TimeFormatOptions {
|
||||
|
@ -26,8 +26,8 @@ class GraphOptionsTimeFormat extends PureComponent<Props, State> {
|
|||
constructor(props: Props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
format: this.props.timeFormat || TIME_FORMAT_DEFAULT,
|
||||
customFormat: false,
|
||||
format: this.props.timeFormat || TIME_FORMAT_DEFAULT,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ class GraphOptionsTimeFormat extends PureComponent<Props, State> {
|
|||
return this.props.onTimeFormatChange
|
||||
}
|
||||
|
||||
handleChooseFormat = (formatOption: TimeFormatOptions) => {
|
||||
public handleChooseFormat = (formatOption: TimeFormatOptions) => {
|
||||
if (formatOption.text === TIME_FORMAT_CUSTOM) {
|
||||
this.setState({customFormat: true})
|
||||
} else {
|
||||
|
@ -44,7 +44,7 @@ class GraphOptionsTimeFormat extends PureComponent<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
const {format, customFormat} = this.state
|
||||
const {onTimeFormatChange} = this.props
|
||||
const tipContent =
|
||||
|
@ -57,21 +57,22 @@ class GraphOptionsTimeFormat extends PureComponent<Props, State> {
|
|||
<div className="form-group col-xs-12">
|
||||
<label>
|
||||
Time Format
|
||||
{customFormat &&
|
||||
{customFormat && (
|
||||
<QuestionMarkTooltip
|
||||
tipID="Time Axis Format"
|
||||
tipContent={tipContent}
|
||||
/>}
|
||||
/>
|
||||
)}
|
||||
</label>
|
||||
<Dropdown
|
||||
items={FORMAT_OPTIONS}
|
||||
selected={showCustom ? TIME_FORMAT_CUSTOM : format}
|
||||
buttonColor="btn-default"
|
||||
buttonSize="btn-xs"
|
||||
buttonSize="btn-sm"
|
||||
className="dropdown-stretch"
|
||||
onChoose={this.handleChooseFormat}
|
||||
/>
|
||||
{showCustom &&
|
||||
{showCustom && (
|
||||
<div className="column-controls--section">
|
||||
<InputClickToEdit
|
||||
wrapperClass="column-controls-input "
|
||||
|
@ -81,7 +82,8 @@ class GraphOptionsTimeFormat extends PureComponent<Props, State> {
|
|||
placeholder="Enter custom format..."
|
||||
appearAsNormalInput={true}
|
||||
/>
|
||||
</div>}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ const GraphTypeSelector = ({type, handleChangeCellType}) => {
|
|||
<div className="display-options--cell-wrapper">
|
||||
<h5 className="display-options--header">Visualization Type</h5>
|
||||
<div className="viz-type-selector">
|
||||
{GRAPH_TYPES.map(graphType =>
|
||||
{GRAPH_TYPES.map(graphType => (
|
||||
<div
|
||||
key={graphType.type}
|
||||
className={classnames('viz-type-selector--option', {
|
||||
|
@ -32,12 +32,10 @@ const GraphTypeSelector = ({type, handleChangeCellType}) => {
|
|||
>
|
||||
<div onClick={onChangeCellType(graphType.type)}>
|
||||
{graphType.graphic}
|
||||
<p>
|
||||
{graphType.menuOption}
|
||||
</p>
|
||||
<p>{graphType.menuOption}</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</FancyScrollbar>
|
||||
|
|
|
@ -15,7 +15,7 @@ const OverlayControls = ({
|
|||
onSetQuerySource,
|
||||
isDisplayOptionsTabActive,
|
||||
onClickDisplayOptions,
|
||||
}) =>
|
||||
}) => (
|
||||
<div className="overlay-controls">
|
||||
<SourceSelector
|
||||
sources={sources}
|
||||
|
@ -51,6 +51,7 @@ const OverlayControls = ({
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, bool, func, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ const QueryMaker = ({
|
|||
activeQueryIndex,
|
||||
initialGroupByTime,
|
||||
setActiveQueryIndex,
|
||||
}) =>
|
||||
}) => (
|
||||
<div className="query-maker query-maker--panel">
|
||||
<QueryTabList
|
||||
queries={queries}
|
||||
|
@ -36,28 +36,31 @@ const QueryMaker = ({
|
|||
activeQueryIndex={activeQueryIndex}
|
||||
setActiveQueryIndex={setActiveQueryIndex}
|
||||
/>
|
||||
{activeQuery && activeQuery.id
|
||||
? <div className="query-maker--tab-contents">
|
||||
<QueryTextArea
|
||||
query={buildText(activeQuery)}
|
||||
config={activeQuery}
|
||||
onUpdate={rawTextBinder(
|
||||
source.links,
|
||||
activeQuery.id,
|
||||
actions.editRawTextAsync
|
||||
)}
|
||||
templates={templates}
|
||||
/>
|
||||
<SchemaExplorer
|
||||
source={source}
|
||||
actions={actions}
|
||||
query={activeQuery}
|
||||
onAddQuery={onAddQuery}
|
||||
initialGroupByTime={initialGroupByTime}
|
||||
/>
|
||||
</div>
|
||||
: <EmptyQuery onAddQuery={onAddQuery} />}
|
||||
{activeQuery && activeQuery.id ? (
|
||||
<div className="query-maker--tab-contents">
|
||||
<QueryTextArea
|
||||
query={buildText(activeQuery)}
|
||||
config={activeQuery}
|
||||
onUpdate={rawTextBinder(
|
||||
source.links,
|
||||
activeQuery.id,
|
||||
actions.editRawTextAsync
|
||||
)}
|
||||
templates={templates}
|
||||
/>
|
||||
<SchemaExplorer
|
||||
source={source}
|
||||
actions={actions}
|
||||
query={activeQuery}
|
||||
onAddQuery={onAddQuery}
|
||||
initialGroupByTime={initialGroupByTime}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<EmptyQuery onAddQuery={onAddQuery} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, func, number, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -215,15 +215,15 @@ class QueryTextArea extends Component {
|
|||
<QueryStatus status={status} />
|
||||
</div>
|
||||
<div className="varmoji-back">
|
||||
{isTemplating
|
||||
? <TemplateDrawer
|
||||
onClickTempVar={this.handleClickTempVar}
|
||||
templates={filteredTemplates}
|
||||
selected={selectedTemplate}
|
||||
onMouseOverTempVar={this.handleMouseOverTempVar}
|
||||
handleClickOutside={this.handleCloseDrawer}
|
||||
/>
|
||||
: null}
|
||||
{isTemplating ? (
|
||||
<TemplateDrawer
|
||||
onClickTempVar={this.handleClickTempVar}
|
||||
templates={filteredTemplates}
|
||||
selected={selectedTemplate}
|
||||
onMouseOverTempVar={this.handleMouseOverTempVar}
|
||||
handleClickOutside={this.handleCloseDrawer}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -3,20 +3,22 @@ import PropTypes from 'prop-types'
|
|||
import Dropdown from 'shared/components/Dropdown'
|
||||
|
||||
const SourceSelector = ({sources = [], selected, onSetQuerySource, queries}) =>
|
||||
sources.length > 1 && queries.length
|
||||
? <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>
|
||||
: <div className="source-selector" />
|
||||
sources.length > 1 && queries.length ? (
|
||||
<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>
|
||||
) : (
|
||||
<div className="source-selector" />
|
||||
)
|
||||
|
||||
const {array, arrayOf, func, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -2,23 +2,23 @@ import React from 'react'
|
|||
import PropTypes from 'prop-types'
|
||||
import QuestionMarkTooltip from 'src/shared/components/QuestionMarkTooltip'
|
||||
|
||||
export const Tabber = ({labelText, children, tipID, tipContent}) =>
|
||||
export const Tabber = ({labelText, children, tipID, tipContent}) => (
|
||||
<div className="form-group col-md-6">
|
||||
<label>
|
||||
{labelText}
|
||||
{tipID
|
||||
? <QuestionMarkTooltip tipID={tipID} tipContent={tipContent} />
|
||||
: null}
|
||||
{tipID ? (
|
||||
<QuestionMarkTooltip tipID={tipID} tipContent={tipContent} />
|
||||
) : null}
|
||||
</label>
|
||||
<ul className="nav nav-tablist nav-tablist-sm">
|
||||
{children}
|
||||
</ul>
|
||||
<ul className="nav nav-tablist nav-tablist-sm">{children}</ul>
|
||||
</div>
|
||||
)
|
||||
|
||||
export const Tab = ({isActive, onClickTab, text}) =>
|
||||
export const Tab = ({isActive, onClickTab, text}) => (
|
||||
<li className={isActive ? 'active' : ''} onClick={onClickTab}>
|
||||
{text}
|
||||
</li>
|
||||
)
|
||||
|
||||
const {bool, func, node, string} = PropTypes
|
||||
|
||||
|
|
|
@ -4,39 +4,45 @@ import {bindActionCreators} from 'redux'
|
|||
|
||||
import _ from 'lodash'
|
||||
|
||||
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
|
||||
import GraphOptionsTimeFormat from 'src/dashboards/components/GraphOptionsTimeFormat'
|
||||
import GraphOptionsTimeAxis from 'src/dashboards/components/GraphOptionsTimeAxis'
|
||||
import GraphOptionsCustomizeColumns from 'src/dashboards/components/GraphOptionsCustomizeColumns'
|
||||
import GraphOptionsFixFirstColumn from 'src/dashboards/components/GraphOptionsFixFirstColumn'
|
||||
import GraphOptionsSortBy from 'src/dashboards/components/GraphOptionsSortBy'
|
||||
import GraphOptionsTextWrapping from 'src/dashboards/components/GraphOptionsTextWrapping'
|
||||
import GraphOptionsCustomizeColumns from 'src/dashboards/components/GraphOptionsCustomizeColumns'
|
||||
import GraphOptionsTimeAxis from 'src/dashboards/components/GraphOptionsTimeAxis'
|
||||
import GraphOptionsTimeFormat from 'src/dashboards/components/GraphOptionsTimeFormat'
|
||||
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
|
||||
|
||||
import ThresholdsList from 'src/shared/components/ThresholdsList'
|
||||
import ThresholdsListTypeToggle from 'src/shared/components/ThresholdsListTypeToggle'
|
||||
|
||||
import {TIME_COLUMN_DEFAULT} from 'src/shared/constants/tableGraph'
|
||||
import {updateTableOptions} from 'src/dashboards/actions/cellEditorOverlay'
|
||||
import {TIME_COLUMN_DEFAULT} from 'src/shared/constants/tableGraph'
|
||||
|
||||
type TableColumn = {
|
||||
interface Option {
|
||||
text: string
|
||||
key: string
|
||||
}
|
||||
|
||||
interface TableColumn {
|
||||
internalName: string
|
||||
displayName: string
|
||||
}
|
||||
|
||||
type Options = {
|
||||
interface Options {
|
||||
timeFormat: string
|
||||
verticalTimeAxis: boolean
|
||||
sortBy: TableColumn
|
||||
wrapping: string
|
||||
columnNames: TableColumn[]
|
||||
fixFirstColumn: boolean
|
||||
}
|
||||
|
||||
type QueryConfig = {
|
||||
interface QueryConfig {
|
||||
measurement: string
|
||||
fields: [
|
||||
{
|
||||
alias: string
|
||||
value: string
|
||||
}
|
||||
]
|
||||
fields: Array<{
|
||||
alias: string
|
||||
value: string
|
||||
}>
|
||||
}
|
||||
|
||||
interface Props {
|
||||
|
@ -51,44 +57,68 @@ export class TableOptions extends PureComponent<Props, {}> {
|
|||
super(props)
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const {queryConfigs, handleUpdateTableOptions, tableOptions} = this.props
|
||||
const {columnNames} = tableOptions
|
||||
const timeColumn =
|
||||
(columnNames && columnNames.find(c => c.internalName === 'time')) ||
|
||||
TIME_COLUMN_DEFAULT
|
||||
|
||||
const columns = [
|
||||
timeColumn,
|
||||
..._.flatten(
|
||||
queryConfigs.map(qc => {
|
||||
const {measurement, fields} = qc
|
||||
return fields.map(f => {
|
||||
const internalName = `${measurement}.${f.alias}`
|
||||
const existing = columnNames.find(
|
||||
c => c.internalName === internalName
|
||||
)
|
||||
return existing || {internalName, displayName: ''}
|
||||
})
|
||||
})
|
||||
),
|
||||
]
|
||||
|
||||
handleUpdateTableOptions({...tableOptions, columnNames: columns})
|
||||
get columnNames() {
|
||||
const {tableOptions: {columnNames}} = this.props
|
||||
return columnNames || []
|
||||
}
|
||||
|
||||
handleChooseSortBy = () => {}
|
||||
get timeColumn() {
|
||||
return (
|
||||
this.columnNames.find(c => c.internalName === 'time') ||
|
||||
TIME_COLUMN_DEFAULT
|
||||
)
|
||||
}
|
||||
|
||||
handleTimeFormatChange = timeFormat => {
|
||||
get computedColumnNames() {
|
||||
const {queryConfigs} = this.props
|
||||
|
||||
const queryFields = _.flatten(
|
||||
queryConfigs.map(({measurement, fields}) => {
|
||||
return fields.map(({alias}) => {
|
||||
const internalName = `${measurement}.${alias}`
|
||||
const existing = this.columnNames.find(
|
||||
c => c.internalName === internalName
|
||||
)
|
||||
return existing || {internalName, displayName: ''}
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
return [this.timeColumn, ...queryFields]
|
||||
}
|
||||
|
||||
public componentWillMount() {
|
||||
const {handleUpdateTableOptions, tableOptions} = this.props
|
||||
handleUpdateTableOptions({
|
||||
...tableOptions,
|
||||
columnNames: this.computedColumnNames,
|
||||
})
|
||||
}
|
||||
|
||||
public handleChooseSortBy = (option: Option) => {
|
||||
const {tableOptions, handleUpdateTableOptions} = this.props
|
||||
const sortBy = {displayName: option.text, internalName: option.key}
|
||||
|
||||
handleUpdateTableOptions({...tableOptions, sortBy})
|
||||
}
|
||||
|
||||
public handleTimeFormatChange = timeFormat => {
|
||||
const {tableOptions, handleUpdateTableOptions} = this.props
|
||||
handleUpdateTableOptions({...tableOptions, timeFormat})
|
||||
}
|
||||
|
||||
handleToggleTimeAxis = () => {}
|
||||
public handleToggleVerticalTimeAxis = verticalTimeAxis => () => {
|
||||
const {tableOptions, handleUpdateTableOptions} = this.props
|
||||
handleUpdateTableOptions({...tableOptions, verticalTimeAxis})
|
||||
}
|
||||
|
||||
handleToggleTextWrapping = () => {}
|
||||
public handleToggleFixFirstColumn = () => {
|
||||
const {handleUpdateTableOptions, tableOptions} = this.props
|
||||
const fixFirstColumn = !tableOptions.fixFirstColumn
|
||||
handleUpdateTableOptions({...tableOptions, fixFirstColumn})
|
||||
}
|
||||
|
||||
handleColumnRename = column => {
|
||||
public handleColumnRename = column => {
|
||||
const {handleUpdateTableOptions, tableOptions} = this.props
|
||||
const {columnNames} = tableOptions
|
||||
const updatedColumns = columnNames.map(
|
||||
|
@ -97,19 +127,24 @@ export class TableOptions extends PureComponent<Props, {}> {
|
|||
handleUpdateTableOptions({...tableOptions, columnNames: updatedColumns})
|
||||
}
|
||||
|
||||
render() {
|
||||
public handleToggleTextWrapping = () => {}
|
||||
|
||||
public render() {
|
||||
const {
|
||||
tableOptions: {timeFormat, columnNames: columns},
|
||||
tableOptions: {
|
||||
timeFormat,
|
||||
columnNames: columns,
|
||||
verticalTimeAxis,
|
||||
fixFirstColumn,
|
||||
},
|
||||
onResetFocus,
|
||||
tableOptions,
|
||||
} = this.props
|
||||
|
||||
const TimeAxis = 'vertical'
|
||||
|
||||
const tableSortByOptions = [
|
||||
'cpu.mean_usage_system',
|
||||
'cpu.mean_usage_idle',
|
||||
'cpu.mean_usage_user',
|
||||
].map(col => ({text: col}))
|
||||
const tableSortByOptions = this.computedColumnNames.map(col => ({
|
||||
key: col.internalName,
|
||||
text: col.displayName || col.internalName,
|
||||
}))
|
||||
|
||||
return (
|
||||
<FancyScrollbar
|
||||
|
@ -124,10 +159,11 @@ export class TableOptions extends PureComponent<Props, {}> {
|
|||
onTimeFormatChange={this.handleTimeFormatChange}
|
||||
/>
|
||||
<GraphOptionsTimeAxis
|
||||
TimeAxis={TimeAxis}
|
||||
onToggleTimeAxis={this.handleToggleTimeAxis}
|
||||
verticalTimeAxis={verticalTimeAxis}
|
||||
onToggleVerticalTimeAxis={this.handleToggleVerticalTimeAxis}
|
||||
/>
|
||||
<GraphOptionsSortBy
|
||||
selected={tableOptions.sortBy || TIME_COLUMN_DEFAULT}
|
||||
sortByOptions={tableSortByOptions}
|
||||
onChooseSortBy={this.handleChooseSortBy}
|
||||
/>
|
||||
|
@ -135,6 +171,10 @@ export class TableOptions extends PureComponent<Props, {}> {
|
|||
thresholdsListType="background"
|
||||
onToggleTextWrapping={this.handleToggleTextWrapping}
|
||||
/>
|
||||
<GraphOptionsFixFirstColumn
|
||||
fixed={fixFirstColumn}
|
||||
onToggleFixFirstColumn={this.handleToggleFixFirstColumn}
|
||||
/>
|
||||
</div>
|
||||
<GraphOptionsCustomizeColumns
|
||||
columns={columns}
|
||||
|
|
|
@ -16,67 +16,67 @@ const TemplateControlBar = ({
|
|||
templates,
|
||||
onSelectTemplate,
|
||||
onOpenTemplateManager,
|
||||
}) =>
|
||||
}) => (
|
||||
<div className={classnames('template-control-bar', {show: isOpen})}>
|
||||
<div className="template-control--container">
|
||||
<div className="template-control--controls">
|
||||
{templates.length
|
||||
? templates.map(({id, values, tempVar}) => {
|
||||
const items = values.map(value => ({...value, text: value.value}))
|
||||
const itemValues = values.map(value => value.value)
|
||||
const selectedItem = items.find(item => item.selected) || items[0]
|
||||
const selectedText = selectedItem && selectedItem.text
|
||||
let customDropdownWidth = 0
|
||||
if (itemValues.length > 1) {
|
||||
const longest = itemValues.reduce(
|
||||
(a, b) => (a.length > b.length ? a : b)
|
||||
)
|
||||
const longestLengthPixels =
|
||||
calculateSize(longest, {
|
||||
font: 'Monospace',
|
||||
fontSize: '12px',
|
||||
}).width + tempVarDropdownPadding
|
||||
|
||||
if (
|
||||
longestLengthPixels > minTempVarDropdownWidth &&
|
||||
longestLengthPixels < maxTempVarDropdownWidth
|
||||
) {
|
||||
customDropdownWidth = longestLengthPixels
|
||||
} else if (longestLengthPixels > maxTempVarDropdownWidth) {
|
||||
customDropdownWidth = maxTempVarDropdownWidth
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: change Dropdown to a MultiSelectDropdown, `selected` to
|
||||
// the full array, and [item] to all `selected` values when we update
|
||||
// this component to support multiple values
|
||||
return (
|
||||
<div
|
||||
key={id}
|
||||
className="template-control--dropdown"
|
||||
style={
|
||||
customDropdownWidth > 0
|
||||
? {minWidth: customDropdownWidth}
|
||||
: null
|
||||
}
|
||||
>
|
||||
<Dropdown
|
||||
items={items}
|
||||
buttonSize="btn-xs"
|
||||
menuClass="dropdown-astronaut"
|
||||
useAutoComplete={true}
|
||||
selected={selectedText || '(No values)'}
|
||||
onChoose={onSelectTemplate(id)}
|
||||
/>
|
||||
<label className="template-control--label">
|
||||
{tempVar}
|
||||
</label>
|
||||
</div>
|
||||
{templates.length ? (
|
||||
templates.map(({id, values, tempVar}) => {
|
||||
const items = values.map(value => ({...value, text: value.value}))
|
||||
const itemValues = values.map(value => value.value)
|
||||
const selectedItem = items.find(item => item.selected) || items[0]
|
||||
const selectedText = selectedItem && selectedItem.text
|
||||
let customDropdownWidth = 0
|
||||
if (itemValues.length > 1) {
|
||||
const longest = itemValues.reduce(
|
||||
(a, b) => (a.length > b.length ? a : b)
|
||||
)
|
||||
})
|
||||
: <div className="template-control--empty">
|
||||
This dashboard does not have any Template Variables
|
||||
</div>}
|
||||
const longestLengthPixels =
|
||||
calculateSize(longest, {
|
||||
font: 'Monospace',
|
||||
fontSize: '12px',
|
||||
}).width + tempVarDropdownPadding
|
||||
|
||||
if (
|
||||
longestLengthPixels > minTempVarDropdownWidth &&
|
||||
longestLengthPixels < maxTempVarDropdownWidth
|
||||
) {
|
||||
customDropdownWidth = longestLengthPixels
|
||||
} else if (longestLengthPixels > maxTempVarDropdownWidth) {
|
||||
customDropdownWidth = maxTempVarDropdownWidth
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: change Dropdown to a MultiSelectDropdown, `selected` to
|
||||
// the full array, and [item] to all `selected` values when we update
|
||||
// this component to support multiple values
|
||||
return (
|
||||
<div
|
||||
key={id}
|
||||
className="template-control--dropdown"
|
||||
style={
|
||||
customDropdownWidth > 0
|
||||
? {minWidth: customDropdownWidth}
|
||||
: null
|
||||
}
|
||||
>
|
||||
<Dropdown
|
||||
items={items}
|
||||
buttonSize="btn-xs"
|
||||
menuClass="dropdown-astronaut"
|
||||
useAutoComplete={true}
|
||||
selected={selectedText || '(No values)'}
|
||||
onChoose={onSelectTemplate(id)}
|
||||
/>
|
||||
<label className="template-control--label">{tempVar}</label>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
) : (
|
||||
<div className="template-control--empty">
|
||||
This dashboard does not have any Template Variables
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Authorized requiredRole={EDITOR_ROLE}>
|
||||
<button
|
||||
|
@ -89,6 +89,7 @@ const TemplateControlBar = ({
|
|||
</Authorized>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, bool, func, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -78,17 +78,15 @@ class Threshold extends Component {
|
|||
|
||||
return (
|
||||
<div className="threshold-item">
|
||||
<div className={labelClass}>
|
||||
{label}
|
||||
</div>
|
||||
{canBeDeleted
|
||||
? <button
|
||||
className="btn btn-default btn-sm btn-square"
|
||||
onClick={onDeleteThreshold(threshold)}
|
||||
>
|
||||
<span className="icon remove" />
|
||||
</button>
|
||||
: null}
|
||||
<div className={labelClass}>{label}</div>
|
||||
{canBeDeleted ? (
|
||||
<button
|
||||
className="btn btn-default btn-sm btn-square"
|
||||
onClick={onDeleteThreshold(threshold)}
|
||||
>
|
||||
<span className="icon remove" />
|
||||
</button>
|
||||
) : null}
|
||||
<input
|
||||
value={workingValue}
|
||||
className={inputClass}
|
||||
|
|
|
@ -55,21 +55,23 @@ class VisualizationName extends Component {
|
|||
|
||||
return (
|
||||
<div className="graph-heading">
|
||||
{isEditing
|
||||
? <input
|
||||
type="text"
|
||||
className="form-control input-sm"
|
||||
defaultValue={name}
|
||||
onBlur={this.handleInputBlur}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
autoFocus={true}
|
||||
onFocus={this.handleFocus}
|
||||
placeholder="Name this Cell..."
|
||||
spellCheck={false}
|
||||
/>
|
||||
: <div className={graphNameClass} onClick={this.handleInputClick}>
|
||||
{name}
|
||||
</div>}
|
||||
{isEditing ? (
|
||||
<input
|
||||
type="text"
|
||||
className="form-control input-sm"
|
||||
defaultValue={name}
|
||||
onBlur={this.handleInputBlur}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
autoFocus={true}
|
||||
onFocus={this.handleFocus}
|
||||
placeholder="Name this Cell..."
|
||||
spellCheck={false}
|
||||
/>
|
||||
) : (
|
||||
<div className={graphNameClass} onClick={this.handleInputClick}>
|
||||
{name}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ const TemplateVariableManager = ({
|
|||
tempVarAlreadyExists,
|
||||
onSaveTemplatesSuccess,
|
||||
onEditTemplateVariables,
|
||||
}) =>
|
||||
}) => (
|
||||
<div className="template-variable-manager">
|
||||
<div className="template-variable-manager--header">
|
||||
<div className="page-header__left">
|
||||
|
@ -56,6 +56,7 @@ const TemplateVariableManager = ({
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
class TemplateVariableManagerWrapper extends Component {
|
||||
constructor(props) {
|
||||
|
|
|
@ -45,7 +45,7 @@ const TemplateVariableRow = ({
|
|||
onSubmit,
|
||||
onErrorThrown,
|
||||
onDeleteTempVar,
|
||||
}) =>
|
||||
}) => (
|
||||
<form
|
||||
className={classnames('template-variable-manager--table-row', {
|
||||
editing: isEditing,
|
||||
|
@ -106,6 +106,7 @@ const TemplateVariableRow = ({
|
|||
/>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
|
||||
class RowWrapper extends Component {
|
||||
constructor(props) {
|
||||
|
|
|
@ -10,36 +10,39 @@ const TemplateVariableTable = ({
|
|||
onRunQueryFailure,
|
||||
onDelete,
|
||||
tempVarAlreadyExists,
|
||||
}) =>
|
||||
}) => (
|
||||
<div className="template-variable-manager--table">
|
||||
{templates.length
|
||||
? <div className="template-variable-manager--table-container">
|
||||
<div className="template-variable-manager--table-heading">
|
||||
<div className="tvm--col-1">Variable</div>
|
||||
<div className="tvm--col-2">Type</div>
|
||||
<div className="tvm--col-3">Definition / Values</div>
|
||||
<div className="tvm--col-4" />
|
||||
</div>
|
||||
<div className="template-variable-manager--table-rows">
|
||||
{templates.map(t =>
|
||||
<TemplateVariableRow
|
||||
key={t.id}
|
||||
source={source}
|
||||
template={t}
|
||||
onRunQuerySuccess={onRunQuerySuccess}
|
||||
onRunQueryFailure={onRunQueryFailure}
|
||||
onDelete={onDelete}
|
||||
tempVarAlreadyExists={tempVarAlreadyExists}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{templates.length ? (
|
||||
<div className="template-variable-manager--table-container">
|
||||
<div className="template-variable-manager--table-heading">
|
||||
<div className="tvm--col-1">Variable</div>
|
||||
<div className="tvm--col-2">Type</div>
|
||||
<div className="tvm--col-3">Definition / Values</div>
|
||||
<div className="tvm--col-4" />
|
||||
</div>
|
||||
: <div className="generic-empty-state">
|
||||
<h4 style={{margin: '60px 0'}} className="no-user-select">
|
||||
You have no Template Variables, why not create one?
|
||||
</h4>
|
||||
</div>}
|
||||
<div className="template-variable-manager--table-rows">
|
||||
{templates.map(t => (
|
||||
<TemplateVariableRow
|
||||
key={t.id}
|
||||
source={source}
|
||||
template={t}
|
||||
onRunQuerySuccess={onRunQuerySuccess}
|
||||
onRunQueryFailure={onRunQueryFailure}
|
||||
onDelete={onDelete}
|
||||
tempVarAlreadyExists={tempVarAlreadyExists}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="generic-empty-state">
|
||||
<h4 style={{margin: '60px 0'}} className="no-user-select">
|
||||
You have no Template Variables, why not create one?
|
||||
</h4>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, bool, func, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -8,26 +8,26 @@ const TableInput = ({
|
|||
onStartEdit,
|
||||
autoFocusTarget,
|
||||
}) => {
|
||||
return isEditing
|
||||
? <div name={name} style={{width: '100%'}}>
|
||||
<input
|
||||
required={true}
|
||||
name={name}
|
||||
autoFocus={name === autoFocusTarget}
|
||||
className="form-control input-sm tvm-input-edit"
|
||||
type="text"
|
||||
defaultValue={
|
||||
name === 'tempVar'
|
||||
? defaultValue.replace(/\u003a/g, '') // remove ':'s
|
||||
: defaultValue
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
: <div style={{width: '100%'}} onClick={onStartEdit(name)}>
|
||||
<div className="tvm-input">
|
||||
{defaultValue}
|
||||
</div>
|
||||
</div>
|
||||
return isEditing ? (
|
||||
<div name={name} style={{width: '100%'}}>
|
||||
<input
|
||||
required={true}
|
||||
name={name}
|
||||
autoFocus={name === autoFocusTarget}
|
||||
className="form-control input-sm tvm-input-edit"
|
||||
type="text"
|
||||
defaultValue={
|
||||
name === 'tempVar'
|
||||
? defaultValue.replace(/\u003a/g, '') // remove ':'s
|
||||
: defaultValue
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div style={{width: '100%'}} onClick={onStartEdit(name)}>
|
||||
<div className="tvm-input">{defaultValue}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const {bool, func, string} = PropTypes
|
||||
|
|
|
@ -46,15 +46,17 @@ const TemplateQueryBuilder = ({
|
|||
onErrorThrown={onErrorThrown}
|
||||
/>
|
||||
<span className="tvm-query-builder--text">FROM</span>
|
||||
{selectedDatabase
|
||||
? <MeasurementDropdown
|
||||
database={selectedDatabase}
|
||||
measurement={selectedMeasurement}
|
||||
onSelectMeasurement={onSelectMeasurement}
|
||||
onStartEdit={onStartEdit}
|
||||
onErrorThrown={onErrorThrown}
|
||||
/>
|
||||
: <div>No database selected</div>}
|
||||
{selectedDatabase ? (
|
||||
<MeasurementDropdown
|
||||
database={selectedDatabase}
|
||||
measurement={selectedMeasurement}
|
||||
onSelectMeasurement={onSelectMeasurement}
|
||||
onStartEdit={onStartEdit}
|
||||
onErrorThrown={onErrorThrown}
|
||||
/>
|
||||
) : (
|
||||
<div>No database selected</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
case 'tagValues':
|
||||
|
@ -68,26 +70,30 @@ const TemplateQueryBuilder = ({
|
|||
onErrorThrown={onErrorThrown}
|
||||
/>
|
||||
<span className="tvm-query-builder--text">FROM</span>
|
||||
{selectedDatabase
|
||||
? <MeasurementDropdown
|
||||
database={selectedDatabase}
|
||||
measurement={selectedMeasurement}
|
||||
onSelectMeasurement={onSelectMeasurement}
|
||||
onStartEdit={onStartEdit}
|
||||
onErrorThrown={onErrorThrown}
|
||||
/>
|
||||
: 'Pick a DB'}
|
||||
{selectedDatabase ? (
|
||||
<MeasurementDropdown
|
||||
database={selectedDatabase}
|
||||
measurement={selectedMeasurement}
|
||||
onSelectMeasurement={onSelectMeasurement}
|
||||
onStartEdit={onStartEdit}
|
||||
onErrorThrown={onErrorThrown}
|
||||
/>
|
||||
) : (
|
||||
'Pick a DB'
|
||||
)}
|
||||
<span className="tvm-query-builder--text">WITH KEY =</span>
|
||||
{selectedMeasurement
|
||||
? <TagKeyDropdown
|
||||
database={selectedDatabase}
|
||||
measurement={selectedMeasurement}
|
||||
tagKey={selectedTagKey}
|
||||
onSelectTagKey={onSelectTagKey}
|
||||
onStartEdit={onStartEdit}
|
||||
onErrorThrown={onErrorThrown}
|
||||
/>
|
||||
: 'Pick a Tag Key'}
|
||||
{selectedMeasurement ? (
|
||||
<TagKeyDropdown
|
||||
database={selectedDatabase}
|
||||
measurement={selectedMeasurement}
|
||||
tagKey={selectedTagKey}
|
||||
onSelectTagKey={onSelectTagKey}
|
||||
onStartEdit={onStartEdit}
|
||||
onErrorThrown={onErrorThrown}
|
||||
/>
|
||||
) : (
|
||||
'Pick a Tag Key'
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
default:
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import {DEFAULT_TABLE_OPTIONS} from 'src/shared/constants/tableGraph'
|
||||
|
||||
export const EMPTY_DASHBOARD = {
|
||||
id: 0,
|
||||
name: '',
|
||||
|
@ -20,6 +22,7 @@ export const NEW_DEFAULT_DASHBOARD_CELL = {
|
|||
name: 'Untitled Cell',
|
||||
type: 'line',
|
||||
queries: [],
|
||||
tableOptions: DEFAULT_TABLE_OPTIONS,
|
||||
}
|
||||
|
||||
export const NEW_DASHBOARD = {
|
||||
|
|
|
@ -356,35 +356,35 @@ class DashboardPage extends Component {
|
|||
|
||||
return (
|
||||
<div className="page">
|
||||
{isTemplating
|
||||
? <OverlayTechnologies>
|
||||
<TemplateVariableManager
|
||||
source={source}
|
||||
templates={dashboard.templates}
|
||||
onClose={this.handleCloseTemplateManager}
|
||||
onRunQueryFailure={this.handleRunQueryFailure}
|
||||
onEditTemplateVariables={this.handleEditTemplateVariables}
|
||||
/>
|
||||
</OverlayTechnologies>
|
||||
: null}
|
||||
{selectedCell
|
||||
? <CellEditorOverlay
|
||||
{isTemplating ? (
|
||||
<OverlayTechnologies>
|
||||
<TemplateVariableManager
|
||||
source={source}
|
||||
sources={sources}
|
||||
cell={selectedCell}
|
||||
timeRange={timeRange}
|
||||
autoRefresh={autoRefresh}
|
||||
dashboardID={dashboardID}
|
||||
queryStatus={cellQueryStatus}
|
||||
onSave={this.handleSaveEditedCell}
|
||||
onCancel={handleHideCellEditorOverlay}
|
||||
templates={templatesIncludingDashTime}
|
||||
editQueryStatus={dashboardActions.editCellQueryStatus}
|
||||
thresholdsListType={thresholdsListType}
|
||||
thresholdsListColors={thresholdsListColors}
|
||||
gaugeColors={gaugeColors}
|
||||
templates={dashboard.templates}
|
||||
onClose={this.handleCloseTemplateManager}
|
||||
onRunQueryFailure={this.handleRunQueryFailure}
|
||||
onEditTemplateVariables={this.handleEditTemplateVariables}
|
||||
/>
|
||||
: null}
|
||||
</OverlayTechnologies>
|
||||
) : null}
|
||||
{selectedCell ? (
|
||||
<CellEditorOverlay
|
||||
source={source}
|
||||
sources={sources}
|
||||
cell={selectedCell}
|
||||
timeRange={timeRange}
|
||||
autoRefresh={autoRefresh}
|
||||
dashboardID={dashboardID}
|
||||
queryStatus={cellQueryStatus}
|
||||
onSave={this.handleSaveEditedCell}
|
||||
onCancel={handleHideCellEditorOverlay}
|
||||
templates={templatesIncludingDashTime}
|
||||
editQueryStatus={dashboardActions.editCellQueryStatus}
|
||||
thresholdsListType={thresholdsListType}
|
||||
thresholdsListColors={thresholdsListColors}
|
||||
gaugeColors={gaugeColors}
|
||||
/>
|
||||
) : null}
|
||||
<DashboardHeader
|
||||
names={names}
|
||||
sourceID={sourceID}
|
||||
|
@ -407,30 +407,30 @@ class DashboardPage extends Component {
|
|||
onToggleTempVarControls={this.handleToggleTempVarControls}
|
||||
handleClickPresentationButton={handleClickPresentationButton}
|
||||
/>
|
||||
{dashboard
|
||||
? <Dashboard
|
||||
source={source}
|
||||
sources={sources}
|
||||
setScrollTop={this.setScrollTop}
|
||||
inView={this.inView}
|
||||
dashboard={dashboard}
|
||||
timeRange={timeRange}
|
||||
autoRefresh={autoRefresh}
|
||||
manualRefresh={manualRefresh}
|
||||
onZoom={this.handleZoomedTimeRange}
|
||||
onAddCell={this.handleAddCell}
|
||||
hoverTime={hoverTime}
|
||||
onSetHoverTime={this.handleSetHoverTime}
|
||||
inPresentationMode={inPresentationMode}
|
||||
onPositionChange={this.handleUpdatePosition}
|
||||
onSelectTemplate={this.handleSelectTemplate}
|
||||
onDeleteCell={this.handleDeleteDashboardCell}
|
||||
showTemplateControlBar={showTemplateControlBar}
|
||||
onOpenTemplateManager={this.handleOpenTemplateManager}
|
||||
templatesIncludingDashTime={templatesIncludingDashTime}
|
||||
onSummonOverlayTechnologies={handleShowCellEditorOverlay}
|
||||
/>
|
||||
: null}
|
||||
{dashboard ? (
|
||||
<Dashboard
|
||||
source={source}
|
||||
sources={sources}
|
||||
setScrollTop={this.setScrollTop}
|
||||
inView={this.inView}
|
||||
dashboard={dashboard}
|
||||
timeRange={timeRange}
|
||||
autoRefresh={autoRefresh}
|
||||
manualRefresh={manualRefresh}
|
||||
onZoom={this.handleZoomedTimeRange}
|
||||
onAddCell={this.handleAddCell}
|
||||
hoverTime={hoverTime}
|
||||
onSetHoverTime={this.handleSetHoverTime}
|
||||
inPresentationMode={inPresentationMode}
|
||||
onPositionChange={this.handleUpdatePosition}
|
||||
onSelectTemplate={this.handleSelectTemplate}
|
||||
onDeleteCell={this.handleDeleteDashboardCell}
|
||||
showTemplateControlBar={showTemplateControlBar}
|
||||
onOpenTemplateManager={this.handleOpenTemplateManager}
|
||||
templatesIncludingDashTime={templatesIncludingDashTime}
|
||||
onSummonOverlayTechnologies={handleShowCellEditorOverlay}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import _ from 'lodash'
|
||||
|
||||
import {
|
||||
THRESHOLD_TYPE_TEXT,
|
||||
DEFAULT_THRESHOLDS_LIST_COLORS,
|
||||
|
@ -28,7 +30,11 @@ export default function cellEditorOverlay(state = initialState, action) {
|
|||
)
|
||||
const gaugeColors = validateGaugeColors(colors)
|
||||
|
||||
const tableOptions = cell.tableOptions || initializeOptions('table')
|
||||
const tableOptions = _.get(
|
||||
cell,
|
||||
'tableOptions',
|
||||
initializeOptions('table')
|
||||
)
|
||||
|
||||
return {
|
||||
...state,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {SFC} from 'react'
|
||||
|
||||
import moment from 'moment'
|
||||
|
||||
export interface CustomCellProps {
|
||||
|
@ -10,18 +11,10 @@ const CustomCell: SFC<CustomCellProps> = ({data, columnName}) => {
|
|||
if (columnName === 'time') {
|
||||
const date = moment(new Date(data)).format('MM/DD/YY hh:mm:ssA')
|
||||
|
||||
return (
|
||||
<span>
|
||||
{date}
|
||||
</span>
|
||||
)
|
||||
return <span>{date}</span>
|
||||
}
|
||||
|
||||
return (
|
||||
<span>
|
||||
{data}
|
||||
</span>
|
||||
)
|
||||
return <span>{data}</span>
|
||||
}
|
||||
|
||||
export default CustomCell
|
||||
|
|
|
@ -90,27 +90,27 @@ class FieldListItem extends Component {
|
|||
<div className="query-builder--checkbox" />
|
||||
{fieldName}
|
||||
</span>
|
||||
{isSelected
|
||||
? <div
|
||||
className={classnames('btn btn-xs', {
|
||||
active: isOpen,
|
||||
'btn-default': !num,
|
||||
'btn-primary': num,
|
||||
})}
|
||||
onClick={this.toggleFunctionsMenu}
|
||||
data-test={`query-builder-list-item-function-${fieldName}`}
|
||||
>
|
||||
{fieldFuncsLabel}
|
||||
</div>
|
||||
: null}
|
||||
{isSelected ? (
|
||||
<div
|
||||
className={classnames('btn btn-xs', {
|
||||
active: isOpen,
|
||||
'btn-default': !num,
|
||||
'btn-primary': num,
|
||||
})}
|
||||
onClick={this.toggleFunctionsMenu}
|
||||
data-test={`query-builder-list-item-function-${fieldName}`}
|
||||
>
|
||||
{fieldFuncsLabel}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{isSelected && isOpen
|
||||
? <FunctionSelector
|
||||
onApply={this.handleApplyFunctions}
|
||||
selectedItems={funcs}
|
||||
singleSelect={isKapacitorRule}
|
||||
/>
|
||||
: null}
|
||||
{isSelected && isOpen ? (
|
||||
<FunctionSelector
|
||||
onApply={this.handleApplyFunctions}
|
||||
selectedItems={funcs}
|
||||
singleSelect={isKapacitorRule}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ const GroupByTimeDropdown = ({
|
|||
selected,
|
||||
onChooseGroupByTime,
|
||||
location: {pathname},
|
||||
}) =>
|
||||
}) => (
|
||||
<div className="group-by-time">
|
||||
<label className="group-by-time--label">Group by:</label>
|
||||
<Dropdown
|
||||
|
@ -34,6 +34,7 @@ const GroupByTimeDropdown = ({
|
|||
selected={selected || 'Time'}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {func, string, shape} = PropTypes
|
||||
|
||||
|
|
|
@ -8,12 +8,8 @@ const NoDataNodeError = React.createClass({
|
|||
render() {
|
||||
return (
|
||||
<ClusterError>
|
||||
<PanelHeading>
|
||||
{errorCopy.noData.head}
|
||||
</PanelHeading>
|
||||
<PanelBody>
|
||||
{errorCopy.noData.body}
|
||||
</PanelBody>
|
||||
<PanelHeading>{errorCopy.noData.head}</PanelHeading>
|
||||
<PanelBody>{errorCopy.noData.body}</PanelBody>
|
||||
</ClusterError>
|
||||
)
|
||||
},
|
||||
|
|
|
@ -14,7 +14,7 @@ const QueryMaker = ({
|
|||
timeRange,
|
||||
activeQuery,
|
||||
initialGroupByTime,
|
||||
}) =>
|
||||
}) => (
|
||||
<div className="query-maker query-maker--panel">
|
||||
<div className="query-maker--tab-contents">
|
||||
<QueryEditor
|
||||
|
@ -33,6 +33,7 @@ const QueryMaker = ({
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {func, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -31,9 +31,7 @@ const QueryMakerTab = React.createClass({
|
|||
})}
|
||||
onClick={this.handleSelect}
|
||||
>
|
||||
<label>
|
||||
{this.props.queryTabText}
|
||||
</label>
|
||||
<label>{this.props.queryTabText}</label>
|
||||
<span
|
||||
className="query-maker--delete"
|
||||
onClick={this.handleDelete}
|
||||
|
|
|
@ -134,60 +134,60 @@ class ChronoTable extends Component {
|
|||
|
||||
return (
|
||||
<div style={{width: '100%', height: '100%', position: 'relative'}}>
|
||||
{series.length < maximumTabsCount
|
||||
? <div className="table--tabs">
|
||||
{series.map((s, i) =>
|
||||
<TabItem
|
||||
isActive={i === activeSeriesIndex}
|
||||
key={i}
|
||||
name={this.makeTabName(s)}
|
||||
index={i}
|
||||
onClickTab={this.handleClickTab}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
: <Dropdown
|
||||
className="dropdown-160 table--tabs-dropdown"
|
||||
items={series.map((s, index) => ({
|
||||
...s,
|
||||
text: this.makeTabName(s),
|
||||
index,
|
||||
}))}
|
||||
onChoose={this.handleClickDropdown}
|
||||
selected={this.makeTabName(series[activeSeriesIndex])}
|
||||
buttonSize="btn-xs"
|
||||
/>}
|
||||
{series.length < maximumTabsCount ? (
|
||||
<div className="table--tabs">
|
||||
{series.map((s, i) => (
|
||||
<TabItem
|
||||
isActive={i === activeSeriesIndex}
|
||||
key={i}
|
||||
name={this.makeTabName(s)}
|
||||
index={i}
|
||||
onClickTab={this.handleClickTab}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<Dropdown
|
||||
className="dropdown-160 table--tabs-dropdown"
|
||||
items={series.map((s, index) => ({
|
||||
...s,
|
||||
text: this.makeTabName(s),
|
||||
index,
|
||||
}))}
|
||||
onChoose={this.handleClickDropdown}
|
||||
selected={this.makeTabName(series[activeSeriesIndex])}
|
||||
buttonSize="btn-xs"
|
||||
/>
|
||||
)}
|
||||
<div className="table--tabs-content">
|
||||
{(columns && !columns.length) || (values && !values.length)
|
||||
? <div className="generic-empty-state">This series is empty</div>
|
||||
: <Table
|
||||
onColumnResizeEndCallback={this.handleColumnResize}
|
||||
isColumnResizing={false}
|
||||
rowHeight={rowHeight}
|
||||
rowsCount={values.length}
|
||||
width={containerWidth}
|
||||
ownerHeight={styleAdjustedHeight}
|
||||
height={styleAdjustedHeight}
|
||||
headerHeight={headerHeight}
|
||||
>
|
||||
{columns.map((columnName, colIndex) => {
|
||||
return (
|
||||
<Column
|
||||
isResizable={true}
|
||||
key={columnName}
|
||||
columnKey={columnName}
|
||||
header={
|
||||
<Cell>
|
||||
{columnName}
|
||||
</Cell>
|
||||
}
|
||||
cell={this.handleCustomCell(columnName, values, colIndex)}
|
||||
width={columnWidths[columnName] || width}
|
||||
minWidth={minWidth}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Table>}
|
||||
{(columns && !columns.length) || (values && !values.length) ? (
|
||||
<div className="generic-empty-state">This series is empty</div>
|
||||
) : (
|
||||
<Table
|
||||
onColumnResizeEndCallback={this.handleColumnResize}
|
||||
isColumnResizing={false}
|
||||
rowHeight={rowHeight}
|
||||
rowsCount={values.length}
|
||||
width={containerWidth}
|
||||
ownerHeight={styleAdjustedHeight}
|
||||
height={styleAdjustedHeight}
|
||||
headerHeight={headerHeight}
|
||||
>
|
||||
{columns.map((columnName, colIndex) => {
|
||||
return (
|
||||
<Column
|
||||
isResizable={true}
|
||||
key={columnName}
|
||||
columnKey={columnName}
|
||||
header={<Cell>{columnName}</Cell>}
|
||||
cell={this.handleCustomCell(columnName, values, colIndex)}
|
||||
width={columnWidths[columnName] || width}
|
||||
minWidth={minWidth}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Table>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -2,13 +2,14 @@ import React from 'react'
|
|||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
|
||||
const TableTabItem = ({name, index, onClickTab, isActive}) =>
|
||||
const TableTabItem = ({name, index, onClickTab, isActive}) => (
|
||||
<div
|
||||
className={classnames('table--tab', {active: isActive})}
|
||||
onClick={onClickTab(index)}
|
||||
>
|
||||
{name}
|
||||
</div>
|
||||
)
|
||||
|
||||
const {bool, func, number, string} = PropTypes
|
||||
|
||||
|
|
|
@ -27,32 +27,33 @@ const getCSV = (query, errorThrown) => async () => {
|
|||
}
|
||||
}
|
||||
|
||||
const VisHeader = ({views, view, onToggleView, query, errorThrown}) =>
|
||||
const VisHeader = ({views, view, onToggleView, query, errorThrown}) => (
|
||||
<div className="graph-heading">
|
||||
{views.length
|
||||
? <ul className="nav nav-tablist nav-tablist-sm">
|
||||
{views.map(v =>
|
||||
<li
|
||||
key={v}
|
||||
onClick={onToggleView(v)}
|
||||
className={classnames({active: view === v})}
|
||||
data-test={`data-${v}`}
|
||||
>
|
||||
{_.upperFirst(v)}
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
: null}
|
||||
{query
|
||||
? <div
|
||||
className="btn btn-sm btn-default dlcsv"
|
||||
onClick={getCSV(query, errorThrown)}
|
||||
>
|
||||
<span className="icon download dlcsv" />
|
||||
.csv
|
||||
</div>
|
||||
: null}
|
||||
{views.length ? (
|
||||
<ul className="nav nav-tablist nav-tablist-sm">
|
||||
{views.map(v => (
|
||||
<li
|
||||
key={v}
|
||||
onClick={onToggleView(v)}
|
||||
className={classnames({active: view === v})}
|
||||
data-test={`data-${v}`}
|
||||
>
|
||||
{_.upperFirst(v)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : null}
|
||||
{query ? (
|
||||
<div
|
||||
className="btn btn-sm btn-default dlcsv"
|
||||
onClick={getCSV(query, errorThrown)}
|
||||
>
|
||||
<span className="icon download dlcsv" />
|
||||
.csv
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, func, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -15,70 +15,75 @@ const WriteDataBody = ({
|
|||
fileInput,
|
||||
handleFileOpen,
|
||||
isUploading,
|
||||
}) =>
|
||||
}) => (
|
||||
<div className="write-data-form--body">
|
||||
{isManual
|
||||
? <textarea
|
||||
className="form-control write-data-form--input"
|
||||
autoComplete="off"
|
||||
spellCheck="false"
|
||||
placeholder="<measurement>,<tag_key>=<tag_value> <field_key>=<field_value>"
|
||||
onKeyUp={handleKeyUp}
|
||||
onChange={handleEdit}
|
||||
autoFocus={true}
|
||||
data-test="manual-entry-field"
|
||||
/>
|
||||
: <div
|
||||
{isManual ? (
|
||||
<textarea
|
||||
className="form-control write-data-form--input"
|
||||
autoComplete="off"
|
||||
spellCheck="false"
|
||||
placeholder="<measurement>,<tag_key>=<tag_value> <field_key>=<field_value>"
|
||||
onKeyUp={handleKeyUp}
|
||||
onChange={handleEdit}
|
||||
autoFocus={true}
|
||||
data-test="manual-entry-field"
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className={
|
||||
uploadContent
|
||||
? 'write-data-form--file'
|
||||
: 'write-data-form--file write-data-form--file_active'
|
||||
}
|
||||
onClick={handleFileOpen}
|
||||
>
|
||||
{uploadContent ? (
|
||||
<h3 className="write-data-form--filepath_selected">{fileName}</h3>
|
||||
) : (
|
||||
<h3 className="write-data-form--filepath_empty">
|
||||
Drop a file here or click to upload
|
||||
</h3>
|
||||
)}
|
||||
<div
|
||||
className={
|
||||
uploadContent
|
||||
? 'write-data-form--file'
|
||||
: 'write-data-form--file write-data-form--file_active'
|
||||
? 'write-data-form--graphic write-data-form--graphic_success'
|
||||
: 'write-data-form--graphic'
|
||||
}
|
||||
onClick={handleFileOpen}
|
||||
>
|
||||
{uploadContent
|
||||
? <h3 className="write-data-form--filepath_selected">
|
||||
{fileName}
|
||||
</h3>
|
||||
: <h3 className="write-data-form--filepath_empty">
|
||||
Drop a file here or click to upload
|
||||
</h3>}
|
||||
<div
|
||||
className={
|
||||
uploadContent
|
||||
? 'write-data-form--graphic write-data-form--graphic_success'
|
||||
: 'write-data-form--graphic'
|
||||
}
|
||||
/>
|
||||
<input
|
||||
type="file"
|
||||
onChange={handleFile(false)}
|
||||
className="write-data-form--upload"
|
||||
ref={fileInput}
|
||||
accept="text/*, application/gzip"
|
||||
/>
|
||||
{uploadContent &&
|
||||
<span className="write-data-form--file-submit">
|
||||
<button className="btn btn-md btn-success" onClick={handleSubmit}>
|
||||
Write this File
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-md btn-default"
|
||||
onClick={handleCancelFile}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</span>}
|
||||
</div>}
|
||||
{isManual &&
|
||||
/>
|
||||
<input
|
||||
type="file"
|
||||
onChange={handleFile(false)}
|
||||
className="write-data-form--upload"
|
||||
ref={fileInput}
|
||||
accept="text/*, application/gzip"
|
||||
/>
|
||||
{uploadContent && (
|
||||
<span className="write-data-form--file-submit">
|
||||
<button className="btn btn-md btn-success" onClick={handleSubmit}>
|
||||
Write this File
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-md btn-default"
|
||||
onClick={handleCancelFile}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{isManual && (
|
||||
<WriteDataFooter
|
||||
isUploading={isUploading}
|
||||
isManual={isManual}
|
||||
inputContent={inputContent}
|
||||
handleSubmit={handleSubmit}
|
||||
uploadContent={uploadContent}
|
||||
/>}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
const {func, string, bool} = PropTypes
|
||||
|
||||
|
|
|
@ -10,26 +10,28 @@ const WriteDataFooter = ({
|
|||
uploadContent,
|
||||
handleSubmit,
|
||||
isUploading,
|
||||
}) =>
|
||||
}) => (
|
||||
<div className="write-data-form--footer">
|
||||
{isManual
|
||||
? <span className="write-data-form--helper">
|
||||
Need help writing InfluxDB Line Protocol? -
|
||||
<a
|
||||
href="https://docs.influxdata.com/influxdb/latest/write_protocols/line_protocol_tutorial/"
|
||||
target="_blank"
|
||||
>
|
||||
See Documentation
|
||||
</a>
|
||||
</span>
|
||||
: <span className="write-data-form--helper">
|
||||
<a
|
||||
href="https://docs.influxdata.com/influxdb/v1.2//tools/shell/#import-data-from-a-file-with-import"
|
||||
target="_blank"
|
||||
>
|
||||
File Upload Documentation
|
||||
</a>
|
||||
</span>}
|
||||
{isManual ? (
|
||||
<span className="write-data-form--helper">
|
||||
Need help writing InfluxDB Line Protocol? -
|
||||
<a
|
||||
href="https://docs.influxdata.com/influxdb/latest/write_protocols/line_protocol_tutorial/"
|
||||
target="_blank"
|
||||
>
|
||||
See Documentation
|
||||
</a>
|
||||
</span>
|
||||
) : (
|
||||
<span className="write-data-form--helper">
|
||||
<a
|
||||
href="https://docs.influxdata.com/influxdb/v1.2//tools/shell/#import-data-from-a-file-with-import"
|
||||
target="_blank"
|
||||
>
|
||||
File Upload Documentation
|
||||
</a>
|
||||
</span>
|
||||
)}
|
||||
<button
|
||||
className={isUploading ? `${submitButton} ${spinner}` : submitButton}
|
||||
onClick={handleSubmit}
|
||||
|
@ -43,6 +45,7 @@ const WriteDataFooter = ({
|
|||
Write
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {bool, func, string} = PropTypes
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ const WriteDataHeader = ({
|
|||
toggleWriteView,
|
||||
isManual,
|
||||
onClose,
|
||||
}) =>
|
||||
}) => (
|
||||
<div className="write-data-form--header">
|
||||
<div className="page-header__left">
|
||||
<h1 className="page-header__title">Write Data To</h1>
|
||||
|
@ -38,6 +38,7 @@ const WriteDataHeader = ({
|
|||
<span className="page-header__dismiss" onClick={onClose} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {func, string, bool} = PropTypes
|
||||
|
||||
|
|
|
@ -95,17 +95,17 @@ class DataExplorer extends Component {
|
|||
const selectedDatabase = _.get(queryConfigs, ['0', 'database'], null)
|
||||
return (
|
||||
<div className="data-explorer">
|
||||
{showWriteForm
|
||||
? <OverlayTechnologies>
|
||||
<WriteDataForm
|
||||
source={source}
|
||||
errorThrown={errorThrownAction}
|
||||
selectedDatabase={selectedDatabase}
|
||||
onClose={this.handleCloseWriteData}
|
||||
writeLineProtocol={writeLineProtocol}
|
||||
/>
|
||||
</OverlayTechnologies>
|
||||
: null}
|
||||
{showWriteForm ? (
|
||||
<OverlayTechnologies>
|
||||
<WriteDataForm
|
||||
source={source}
|
||||
errorThrown={errorThrownAction}
|
||||
selectedDatabase={selectedDatabase}
|
||||
onClose={this.handleCloseWriteData}
|
||||
writeLineProtocol={writeLineProtocol}
|
||||
/>
|
||||
</OverlayTechnologies>
|
||||
) : null}
|
||||
<Header
|
||||
timeRange={timeRange}
|
||||
autoRefresh={autoRefresh}
|
||||
|
|
|
@ -16,7 +16,7 @@ const Header = ({
|
|||
onManualRefresh,
|
||||
onChooseTimeRange,
|
||||
onChooseAutoRefresh,
|
||||
}) =>
|
||||
}) => (
|
||||
<div className="page-header full-width">
|
||||
<div className="page-header__container">
|
||||
<div className="page-header__left">
|
||||
|
@ -47,6 +47,7 @@ const Header = ({
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
Header.propTypes = {
|
||||
onChooseAutoRefresh: func.isRequired,
|
||||
|
|
|
@ -37,7 +37,10 @@ const download = (data, strFileName, strMimeType) => {
|
|||
|
||||
if (url && url.length < 2048) {
|
||||
// if no filename and no mime, assume a url was passed as the only argument
|
||||
fileName = url.split('/').pop().split('?')[0]
|
||||
fileName = url
|
||||
.split('/')
|
||||
.pop()
|
||||
.split('?')[0]
|
||||
anchor.href = url // assign href prop to temp anchor
|
||||
if (anchor.href.indexOf(url) !== -1) {
|
||||
// if the browser determines that it's a potentially valid url path:
|
||||
|
|
|
@ -23,9 +23,7 @@ class HostRow extends Component {
|
|||
return (
|
||||
<div className="hosts-table--tr">
|
||||
<div className="hosts-table--td" style={{width: colName}}>
|
||||
<Link to={`/sources/${source.id}/hosts/${name}`}>
|
||||
{name}
|
||||
</Link>
|
||||
<Link to={`/sources/${source.id}/hosts/${name}`}>{name}</Link>
|
||||
</div>
|
||||
<div className="hosts-table--td" style={{width: colStatus}}>
|
||||
<div
|
||||
|
|
|
@ -102,61 +102,61 @@ class HostsTable extends Component {
|
|||
return (
|
||||
<div className="panel">
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">
|
||||
{hostsTitle}
|
||||
</h2>
|
||||
<h2 className="panel-title">{hostsTitle}</h2>
|
||||
<SearchBar
|
||||
placeholder="Filter by Host..."
|
||||
onSearch={this.updateSearchTerm}
|
||||
/>
|
||||
</div>
|
||||
<div className="panel-body">
|
||||
{hostCount > 0 && !hostsError.length
|
||||
? <div className="hosts-table">
|
||||
<div className="hosts-table--thead">
|
||||
<div className="hosts-table--tr">
|
||||
<div
|
||||
onClick={this.updateSort('name')}
|
||||
className={this.sortableClasses('name')}
|
||||
style={{width: colName}}
|
||||
>
|
||||
Host
|
||||
</div>
|
||||
<div
|
||||
onClick={this.updateSort('deltaUptime')}
|
||||
className={this.sortableClasses('deltaUptime')}
|
||||
style={{width: colStatus}}
|
||||
>
|
||||
Status
|
||||
</div>
|
||||
<div
|
||||
onClick={this.updateSort('cpu')}
|
||||
className={this.sortableClasses('cpu')}
|
||||
style={{width: colCPU}}
|
||||
>
|
||||
CPU
|
||||
</div>
|
||||
<div
|
||||
onClick={this.updateSort('load')}
|
||||
className={this.sortableClasses('load')}
|
||||
style={{width: colLoad}}
|
||||
>
|
||||
Load
|
||||
</div>
|
||||
<div className="hosts-table--th">Apps</div>
|
||||
{hostCount > 0 && !hostsError.length ? (
|
||||
<div className="hosts-table">
|
||||
<div className="hosts-table--thead">
|
||||
<div className="hosts-table--tr">
|
||||
<div
|
||||
onClick={this.updateSort('name')}
|
||||
className={this.sortableClasses('name')}
|
||||
style={{width: colName}}
|
||||
>
|
||||
Host
|
||||
</div>
|
||||
<div
|
||||
onClick={this.updateSort('deltaUptime')}
|
||||
className={this.sortableClasses('deltaUptime')}
|
||||
style={{width: colStatus}}
|
||||
>
|
||||
Status
|
||||
</div>
|
||||
<div
|
||||
onClick={this.updateSort('cpu')}
|
||||
className={this.sortableClasses('cpu')}
|
||||
style={{width: colCPU}}
|
||||
>
|
||||
CPU
|
||||
</div>
|
||||
<div
|
||||
onClick={this.updateSort('load')}
|
||||
className={this.sortableClasses('load')}
|
||||
style={{width: colLoad}}
|
||||
>
|
||||
Load
|
||||
</div>
|
||||
<div className="hosts-table--th">Apps</div>
|
||||
</div>
|
||||
<InfiniteScroll
|
||||
items={sortedHosts.map(h =>
|
||||
<HostRow key={h.name} host={h} source={source} />
|
||||
)}
|
||||
itemHeight={26}
|
||||
className="hosts-table--tbody"
|
||||
/>
|
||||
</div>
|
||||
: <div className="generic-empty-state">
|
||||
<h4 style={{margin: '90px 0'}}>No Hosts found</h4>
|
||||
</div>}
|
||||
<InfiniteScroll
|
||||
items={sortedHosts.map(h => (
|
||||
<HostRow key={h.name} host={h} source={source} />
|
||||
))}
|
||||
itemHeight={26}
|
||||
className="hosts-table--tbody"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="generic-empty-state">
|
||||
<h4 style={{margin: '90px 0'}}>No Hosts found</h4>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -96,7 +96,7 @@ class HostPage extends Component {
|
|||
const autoflowCells = autoflowLayouts.reduce((allCells, layout) => {
|
||||
return allCells.concat(
|
||||
layout.cells.map(cell => {
|
||||
const x = cellCount * cellWidth % pageWidth
|
||||
const x = (cellCount * cellWidth) % pageWidth
|
||||
const y = Math.floor(cellCount * cellWidth / pageWidth) * cellHeight
|
||||
cellCount += 1
|
||||
return Object.assign(cell, {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue