Merge branch 'master' into moar-colors-n-stuff
commit
a98cc90fa3
|
@ -1,5 +1,5 @@
|
|||
[bumpversion]
|
||||
current_version = 1.4.1.3
|
||||
current_version = 1.4.2.3
|
||||
files = README.md server/swagger.json
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\.(?P<release>\d+)
|
||||
serialize = {major}.{minor}.{patch}.{release}
|
||||
|
|
|
@ -22,3 +22,4 @@ chronograf*.db
|
|||
*_gen.go
|
||||
canned/apps_gen.go
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
|
1205
CHANGELOG.md
1205
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
|
@ -21,7 +21,7 @@ We really like to receive feature requests, as it helps us prioritize our work.
|
|||
|
||||
Contributing to the source code
|
||||
-------------------------------
|
||||
Chronograf is built using Go for its API backend and serving the front-end assets. The front-end visualization is built with React and uses Yarn for package management. The assumption is that all your Go development are done in `$GOPATH/src`. `GOPATH` can be any directory under which Chronograf and all its dependencies will be cloned. For full details on the project structure, follow along below.
|
||||
Chronograf is built using Go for its API backend and serving the front-end assets, and uses Dep for dependency management. The front-end visualization is built with React (JavaScript) and uses Yarn for dependency management. The assumption is that all your Go development are done in `$GOPATH/src`. `GOPATH` can be any directory under which Chronograf and all its dependencies will be cloned. For full details on the project structure, follow along below.
|
||||
|
||||
Submitting a pull request
|
||||
-------------------------
|
||||
|
@ -43,9 +43,13 @@ Signing the CLA
|
|||
If you are going to be contributing back to Chronograf please take a second to sign our CLA, which can be found
|
||||
[on our website](https://influxdata.com/community/cla/).
|
||||
|
||||
Installing Yarn
|
||||
Installing & Using Yarn
|
||||
--------------
|
||||
You'll need to install Yarn to manage the JavaScript modules that the front-end uses. This varies depending on what platform you're developing on, but you should be able to find an installer on [the Yarn installation page](https://yarnpkg.com/en/docs/install).
|
||||
You'll need to install Yarn to manage the frontend (JavaScript) dependencies.
|
||||
|
||||
* [Install Yarn](https://yarnpkg.com/en/docs/install)
|
||||
|
||||
To add a dependency via Yarn, for example, run `yarn add <dependency>` from within the `/chronograf/ui` directory.
|
||||
|
||||
Installing Go
|
||||
-------------
|
||||
|
@ -62,13 +66,13 @@ running the following:
|
|||
gvm use go1.7.5 --default
|
||||
```
|
||||
|
||||
Installing GDM
|
||||
Installing & Using Dep
|
||||
--------------
|
||||
Chronograf uses [gdm](https://github.com/sparrc/gdm) to manage dependencies. Install it by running the following:
|
||||
You'll need to install Dep to manage the backend (Go) dependencies.
|
||||
|
||||
```bash
|
||||
go get github.com/sparrc/gdm
|
||||
```
|
||||
* [Install Dep](https://github.com/golang/dep)
|
||||
|
||||
To add a dependency via Dep, for example, run `dep ensure -add <dependency>` from within the `/chronograf` directory. _Note that as of this writing, `dep ensure` will modify many extraneous vendor files, so you'll need to run `dep prune` to clean this up before committing your changes. Apparently, the next version of `dep` will take care of this step for you._
|
||||
|
||||
Revision Control Systems
|
||||
------------------------
|
||||
|
|
|
@ -39,34 +39,7 @@
|
|||
|
||||
[[projects]]
|
||||
name = "github.com/gogo/protobuf"
|
||||
packages = [
|
||||
"gogoproto",
|
||||
"jsonpb",
|
||||
"plugin/compare",
|
||||
"plugin/defaultcheck",
|
||||
"plugin/description",
|
||||
"plugin/embedcheck",
|
||||
"plugin/enumstringer",
|
||||
"plugin/equal",
|
||||
"plugin/face",
|
||||
"plugin/gostring",
|
||||
"plugin/marshalto",
|
||||
"plugin/oneofcheck",
|
||||
"plugin/populate",
|
||||
"plugin/size",
|
||||
"plugin/stringer",
|
||||
"plugin/testgen",
|
||||
"plugin/union",
|
||||
"plugin/unmarshal",
|
||||
"proto",
|
||||
"protoc-gen-gogo",
|
||||
"protoc-gen-gogo/descriptor",
|
||||
"protoc-gen-gogo/generator",
|
||||
"protoc-gen-gogo/grpc",
|
||||
"protoc-gen-gogo/plugin",
|
||||
"vanity",
|
||||
"vanity/command"
|
||||
]
|
||||
packages = ["gogoproto","jsonpb","plugin/compare","plugin/defaultcheck","plugin/description","plugin/embedcheck","plugin/enumstringer","plugin/equal","plugin/face","plugin/gostring","plugin/marshalto","plugin/oneofcheck","plugin/populate","plugin/size","plugin/stringer","plugin/testgen","plugin/union","plugin/unmarshal","proto","protoc-gen-gogo","protoc-gen-gogo/descriptor","protoc-gen-gogo/generator","protoc-gen-gogo/grpc","protoc-gen-gogo/plugin","vanity","vanity/command"]
|
||||
revision = "6abcf94fd4c97dcb423fdafd42fe9f96ca7e421b"
|
||||
|
||||
[[projects]]
|
||||
|
@ -77,13 +50,7 @@
|
|||
|
||||
[[projects]]
|
||||
name = "github.com/google/go-cmp"
|
||||
packages = [
|
||||
"cmp",
|
||||
"cmp/cmpopts",
|
||||
"cmp/internal/diff",
|
||||
"cmp/internal/function",
|
||||
"cmp/internal/value"
|
||||
]
|
||||
packages = ["cmp","cmp/cmpopts","cmp/internal/diff","cmp/internal/function","cmp/internal/value"]
|
||||
revision = "8099a9787ce5dc5984ed879a3bda47dc730a8e97"
|
||||
version = "v0.1.0"
|
||||
|
||||
|
@ -100,28 +67,13 @@
|
|||
|
||||
[[projects]]
|
||||
name = "github.com/influxdata/influxdb"
|
||||
packages = [
|
||||
"influxql",
|
||||
"influxql/internal",
|
||||
"influxql/neldermead",
|
||||
"models",
|
||||
"pkg/escape"
|
||||
]
|
||||
packages = ["influxql","influxql/internal","influxql/neldermead","models","pkg/escape"]
|
||||
revision = "cd9363b52cac452113b95554d98a6be51beda24e"
|
||||
version = "v1.1.5"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/influxdata/kapacitor"
|
||||
packages = [
|
||||
"client/v1",
|
||||
"pipeline",
|
||||
"pipeline/tick",
|
||||
"services/k8s/client",
|
||||
"tick",
|
||||
"tick/ast",
|
||||
"tick/stateful",
|
||||
"udf/agent"
|
||||
]
|
||||
packages = ["client/v1","pipeline","pipeline/tick","services/k8s/client","tick","tick/ast","tick/stateful","udf/agent"]
|
||||
revision = "6de30070b39afde111fea5e041281126fe8aae31"
|
||||
|
||||
[[projects]]
|
||||
|
@ -163,21 +115,13 @@
|
|||
|
||||
[[projects]]
|
||||
name = "golang.org/x/net"
|
||||
packages = [
|
||||
"context",
|
||||
"context/ctxhttp"
|
||||
]
|
||||
packages = ["context","context/ctxhttp"]
|
||||
revision = "749a502dd1eaf3e5bfd4f8956748c502357c0bbe"
|
||||
|
||||
[[projects]]
|
||||
name = "golang.org/x/oauth2"
|
||||
packages = [
|
||||
".",
|
||||
"github",
|
||||
"heroku",
|
||||
"internal"
|
||||
]
|
||||
revision = "1e695b1c8febf17aad3bfa7bf0a819ef94b98ad5"
|
||||
packages = [".","github","heroku","internal"]
|
||||
revision = "2f32c3ac0fa4fb807a0fcefb0b6f2468a0d99bd0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -187,31 +131,18 @@
|
|||
|
||||
[[projects]]
|
||||
name = "google.golang.org/api"
|
||||
packages = [
|
||||
"gensupport",
|
||||
"googleapi",
|
||||
"googleapi/internal/uritemplates",
|
||||
"oauth2/v2"
|
||||
]
|
||||
packages = ["gensupport","googleapi","googleapi/internal/uritemplates","oauth2/v2"]
|
||||
revision = "bc20c61134e1d25265dd60049f5735381e79b631"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/appengine"
|
||||
packages = [
|
||||
"internal",
|
||||
"internal/base",
|
||||
"internal/datastore",
|
||||
"internal/log",
|
||||
"internal/remote_api",
|
||||
"internal/urlfetch",
|
||||
"urlfetch"
|
||||
]
|
||||
packages = ["internal","internal/base","internal/datastore","internal/log","internal/remote_api","internal/urlfetch","urlfetch"]
|
||||
revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a"
|
||||
version = "v1.0.0"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "11df631364d11bc05c8f71af1aa735360b5a40a793d32d47d1f1d8c694a55f6f"
|
||||
inputs-digest = "a4df1b0953349e64a89581f4b83ac3a2f40e17681e19f8de3cbf828b6375a3ba"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
|
@ -62,7 +62,7 @@ required = ["github.com/kevinburke/go-bindata","github.com/gogo/protobuf/proto",
|
|||
|
||||
[[constraint]]
|
||||
name = "golang.org/x/oauth2"
|
||||
revision = "1e695b1c8febf17aad3bfa7bf0a819ef94b98ad5"
|
||||
revision = "2f32c3ac0fa4fb807a0fcefb0b6f2468a0d99bd0"
|
||||
|
||||
[[constraint]]
|
||||
name = "google.golang.org/api"
|
||||
|
|
2
Makefile
2
Makefile
|
@ -101,7 +101,7 @@ gotestrace:
|
|||
go test -race ./...
|
||||
|
||||
jstest:
|
||||
cd ui && yarn test
|
||||
cd ui && yarn test --runInBand
|
||||
|
||||
run: ${BINARY}
|
||||
./chronograf
|
||||
|
|
|
@ -136,7 +136,7 @@ option.
|
|||
## Versions
|
||||
|
||||
The most recent version of Chronograf is
|
||||
[v1.4.1.3](https://www.influxdata.com/downloads/).
|
||||
[v1.4.2.3](https://www.influxdata.com/downloads/).
|
||||
|
||||
Spotted a bug or have a feature request? Please open
|
||||
[an issue](https://github.com/influxdata/chronograf/issues/new)!
|
||||
|
@ -178,7 +178,7 @@ By default, chronograf runs on port `8888`.
|
|||
To get started right away with Docker, you can pull down our latest release:
|
||||
|
||||
```sh
|
||||
docker pull chronograf:1.4.1.3
|
||||
docker pull chronograf:1.4.2.3
|
||||
```
|
||||
|
||||
### From Source
|
||||
|
|
|
@ -75,14 +75,15 @@ func UnmarshalSource(data []byte, s *chronograf.Source) error {
|
|||
// MarshalServer encodes a server to binary protobuf format.
|
||||
func MarshalServer(s chronograf.Server) ([]byte, error) {
|
||||
return proto.Marshal(&Server{
|
||||
ID: int64(s.ID),
|
||||
SrcID: int64(s.SrcID),
|
||||
Name: s.Name,
|
||||
Username: s.Username,
|
||||
Password: s.Password,
|
||||
URL: s.URL,
|
||||
Active: s.Active,
|
||||
Organization: s.Organization,
|
||||
ID: int64(s.ID),
|
||||
SrcID: int64(s.SrcID),
|
||||
Name: s.Name,
|
||||
Username: s.Username,
|
||||
Password: s.Password,
|
||||
URL: s.URL,
|
||||
Active: s.Active,
|
||||
Organization: s.Organization,
|
||||
InsecureSkipVerify: s.InsecureSkipVerify,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -101,6 +102,7 @@ func UnmarshalServer(data []byte, s *chronograf.Server) error {
|
|||
s.URL = pb.URL
|
||||
s.Active = pb.Active
|
||||
s.Organization = pb.Organization
|
||||
s.InsecureSkipVerify = pb.InsecureSkipVerify
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -263,6 +265,27 @@ func MarshalDashboard(d chronograf.Dashboard) ([]byte, error) {
|
|||
}
|
||||
}
|
||||
|
||||
sortBy := &TableColumn{
|
||||
InternalName: c.TableOptions.SortBy.InternalName,
|
||||
DisplayName: c.TableOptions.SortBy.DisplayName,
|
||||
}
|
||||
|
||||
columnNames := make([]*TableColumn, len(c.TableOptions.ColumnNames))
|
||||
for i, column := range c.TableOptions.ColumnNames {
|
||||
columnNames[i] = &TableColumn{
|
||||
InternalName: column.InternalName,
|
||||
DisplayName: column.DisplayName,
|
||||
}
|
||||
}
|
||||
|
||||
tableOptions := &TableOptions{
|
||||
TimeFormat: c.TableOptions.TimeFormat,
|
||||
VerticalTimeAxis: c.TableOptions.VerticalTimeAxis,
|
||||
SortBy: sortBy,
|
||||
Wrapping: c.TableOptions.Wrapping,
|
||||
ColumnNames: columnNames,
|
||||
}
|
||||
|
||||
cells[i] = &DashboardCell{
|
||||
ID: c.ID,
|
||||
X: c.X,
|
||||
|
@ -278,6 +301,7 @@ func MarshalDashboard(d chronograf.Dashboard) ([]byte, error) {
|
|||
Type: c.Legend.Type,
|
||||
Orientation: c.Legend.Orientation,
|
||||
},
|
||||
TableOptions: tableOptions,
|
||||
}
|
||||
}
|
||||
templates := make([]*Template, len(d.Templates))
|
||||
|
@ -404,18 +428,48 @@ func UnmarshalDashboard(data []byte, d *chronograf.Dashboard) error {
|
|||
legend.Orientation = c.Legend.Orientation
|
||||
}
|
||||
|
||||
tableOptions := chronograf.TableOptions{}
|
||||
if c.TableOptions != nil {
|
||||
sortBy := chronograf.TableColumn{}
|
||||
if c.TableOptions.SortBy != nil {
|
||||
sortBy.InternalName = c.TableOptions.SortBy.InternalName
|
||||
sortBy.DisplayName = c.TableOptions.SortBy.DisplayName
|
||||
}
|
||||
tableOptions.SortBy = sortBy
|
||||
|
||||
columnNames := make([]chronograf.TableColumn, len(c.TableOptions.ColumnNames))
|
||||
for i, column := range c.TableOptions.ColumnNames {
|
||||
columnNames[i] = chronograf.TableColumn{}
|
||||
columnNames[i].InternalName = column.InternalName
|
||||
columnNames[i].DisplayName = column.DisplayName
|
||||
}
|
||||
tableOptions.ColumnNames = columnNames
|
||||
tableOptions.TimeFormat = c.TableOptions.TimeFormat
|
||||
tableOptions.VerticalTimeAxis = c.TableOptions.VerticalTimeAxis
|
||||
tableOptions.Wrapping = c.TableOptions.Wrapping
|
||||
|
||||
}
|
||||
|
||||
// FIXME: this is merely for legacy cells and
|
||||
// should be removed as soon as possible
|
||||
cellType := c.Type
|
||||
if cellType == "" {
|
||||
cellType = "line"
|
||||
}
|
||||
|
||||
cells[i] = chronograf.DashboardCell{
|
||||
ID: c.ID,
|
||||
X: c.X,
|
||||
Y: c.Y,
|
||||
W: c.W,
|
||||
H: c.H,
|
||||
Name: c.Name,
|
||||
Queries: queries,
|
||||
Type: c.Type,
|
||||
Axes: axes,
|
||||
CellColors: colors,
|
||||
Legend: legend,
|
||||
ID: c.ID,
|
||||
X: c.X,
|
||||
Y: c.Y,
|
||||
W: c.W,
|
||||
H: c.H,
|
||||
Name: c.Name,
|
||||
Queries: queries,
|
||||
Type: cellType,
|
||||
Axes: axes,
|
||||
CellColors: colors,
|
||||
Legend: legend,
|
||||
TableOptions: tableOptions,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ It has these top-level messages:
|
|||
Source
|
||||
Dashboard
|
||||
DashboardCell
|
||||
TableOptions
|
||||
TableColumn
|
||||
Color
|
||||
Legend
|
||||
Axis
|
||||
|
@ -210,17 +212,18 @@ func (m *Dashboard) GetOrganization() string {
|
|||
}
|
||||
|
||||
type DashboardCell struct {
|
||||
X int32 `protobuf:"varint,1,opt,name=x,proto3" json:"x,omitempty"`
|
||||
Y int32 `protobuf:"varint,2,opt,name=y,proto3" json:"y,omitempty"`
|
||||
W int32 `protobuf:"varint,3,opt,name=w,proto3" json:"w,omitempty"`
|
||||
H int32 `protobuf:"varint,4,opt,name=h,proto3" json:"h,omitempty"`
|
||||
Queries []*Query `protobuf:"bytes,5,rep,name=queries" json:"queries,omitempty"`
|
||||
Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Type string `protobuf:"bytes,7,opt,name=type,proto3" json:"type,omitempty"`
|
||||
ID string `protobuf:"bytes,8,opt,name=ID,proto3" json:"ID,omitempty"`
|
||||
Axes map[string]*Axis `protobuf:"bytes,9,rep,name=axes" json:"axes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
|
||||
Colors []*Color `protobuf:"bytes,10,rep,name=colors" json:"colors,omitempty"`
|
||||
Legend *Legend `protobuf:"bytes,11,opt,name=legend" json:"legend,omitempty"`
|
||||
X int32 `protobuf:"varint,1,opt,name=x,proto3" json:"x,omitempty"`
|
||||
Y int32 `protobuf:"varint,2,opt,name=y,proto3" json:"y,omitempty"`
|
||||
W int32 `protobuf:"varint,3,opt,name=w,proto3" json:"w,omitempty"`
|
||||
H int32 `protobuf:"varint,4,opt,name=h,proto3" json:"h,omitempty"`
|
||||
Queries []*Query `protobuf:"bytes,5,rep,name=queries" json:"queries,omitempty"`
|
||||
Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Type string `protobuf:"bytes,7,opt,name=type,proto3" json:"type,omitempty"`
|
||||
ID string `protobuf:"bytes,8,opt,name=ID,proto3" json:"ID,omitempty"`
|
||||
Axes map[string]*Axis `protobuf:"bytes,9,rep,name=axes" json:"axes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
|
||||
Colors []*Color `protobuf:"bytes,10,rep,name=colors" json:"colors,omitempty"`
|
||||
Legend *Legend `protobuf:"bytes,11,opt,name=legend" json:"legend,omitempty"`
|
||||
TableOptions *TableOptions `protobuf:"bytes,12,opt,name=tableOptions" json:"tableOptions,omitempty"`
|
||||
}
|
||||
|
||||
func (m *DashboardCell) Reset() { *m = DashboardCell{} }
|
||||
|
@ -305,6 +308,85 @@ func (m *DashboardCell) GetLegend() *Legend {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *DashboardCell) GetTableOptions() *TableOptions {
|
||||
if m != nil {
|
||||
return m.TableOptions
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type TableOptions struct {
|
||||
TimeFormat string `protobuf:"bytes,1,opt,name=timeFormat,proto3" json:"timeFormat,omitempty"`
|
||||
VerticalTimeAxis bool `protobuf:"varint,2,opt,name=verticalTimeAxis,proto3" json:"verticalTimeAxis,omitempty"`
|
||||
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"`
|
||||
}
|
||||
|
||||
func (m *TableOptions) Reset() { *m = TableOptions{} }
|
||||
func (m *TableOptions) String() string { return proto.CompactTextString(m) }
|
||||
func (*TableOptions) ProtoMessage() {}
|
||||
func (*TableOptions) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{3} }
|
||||
|
||||
func (m *TableOptions) GetTimeFormat() string {
|
||||
if m != nil {
|
||||
return m.TimeFormat
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *TableOptions) GetVerticalTimeAxis() bool {
|
||||
if m != nil {
|
||||
return m.VerticalTimeAxis
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *TableOptions) GetSortBy() *TableColumn {
|
||||
if m != nil {
|
||||
return m.SortBy
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *TableOptions) GetWrapping() string {
|
||||
if m != nil {
|
||||
return m.Wrapping
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *TableOptions) GetColumnNames() []*TableColumn {
|
||||
if m != nil {
|
||||
return m.ColumnNames
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
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"`
|
||||
}
|
||||
|
||||
func (m *TableColumn) Reset() { *m = TableColumn{} }
|
||||
func (m *TableColumn) String() string { return proto.CompactTextString(m) }
|
||||
func (*TableColumn) ProtoMessage() {}
|
||||
func (*TableColumn) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{4} }
|
||||
|
||||
func (m *TableColumn) GetInternalName() string {
|
||||
if m != nil {
|
||||
return m.InternalName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *TableColumn) GetDisplayName() string {
|
||||
if m != nil {
|
||||
return m.DisplayName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Color struct {
|
||||
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
|
||||
Type string `protobuf:"bytes,2,opt,name=Type,proto3" json:"Type,omitempty"`
|
||||
|
@ -316,7 +398,7 @@ type Color struct {
|
|||
func (m *Color) Reset() { *m = Color{} }
|
||||
func (m *Color) String() string { return proto.CompactTextString(m) }
|
||||
func (*Color) ProtoMessage() {}
|
||||
func (*Color) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{3} }
|
||||
func (*Color) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{5} }
|
||||
|
||||
func (m *Color) GetID() string {
|
||||
if m != nil {
|
||||
|
@ -361,7 +443,7 @@ type Legend struct {
|
|||
func (m *Legend) Reset() { *m = Legend{} }
|
||||
func (m *Legend) String() string { return proto.CompactTextString(m) }
|
||||
func (*Legend) ProtoMessage() {}
|
||||
func (*Legend) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{4} }
|
||||
func (*Legend) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{6} }
|
||||
|
||||
func (m *Legend) GetType() string {
|
||||
if m != nil {
|
||||
|
@ -390,7 +472,7 @@ type Axis struct {
|
|||
func (m *Axis) Reset() { *m = Axis{} }
|
||||
func (m *Axis) String() string { return proto.CompactTextString(m) }
|
||||
func (*Axis) ProtoMessage() {}
|
||||
func (*Axis) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{5} }
|
||||
func (*Axis) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{7} }
|
||||
|
||||
func (m *Axis) GetLegacyBounds() []int64 {
|
||||
if m != nil {
|
||||
|
@ -453,7 +535,7 @@ type Template struct {
|
|||
func (m *Template) Reset() { *m = Template{} }
|
||||
func (m *Template) String() string { return proto.CompactTextString(m) }
|
||||
func (*Template) ProtoMessage() {}
|
||||
func (*Template) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{6} }
|
||||
func (*Template) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{8} }
|
||||
|
||||
func (m *Template) GetID() string {
|
||||
if m != nil {
|
||||
|
@ -506,7 +588,7 @@ type TemplateValue struct {
|
|||
func (m *TemplateValue) Reset() { *m = TemplateValue{} }
|
||||
func (m *TemplateValue) String() string { return proto.CompactTextString(m) }
|
||||
func (*TemplateValue) ProtoMessage() {}
|
||||
func (*TemplateValue) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{7} }
|
||||
func (*TemplateValue) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{9} }
|
||||
|
||||
func (m *TemplateValue) GetType() string {
|
||||
if m != nil {
|
||||
|
@ -541,7 +623,7 @@ type TemplateQuery struct {
|
|||
func (m *TemplateQuery) Reset() { *m = TemplateQuery{} }
|
||||
func (m *TemplateQuery) String() string { return proto.CompactTextString(m) }
|
||||
func (*TemplateQuery) ProtoMessage() {}
|
||||
func (*TemplateQuery) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{8} }
|
||||
func (*TemplateQuery) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{10} }
|
||||
|
||||
func (m *TemplateQuery) GetCommand() string {
|
||||
if m != nil {
|
||||
|
@ -586,20 +668,21 @@ func (m *TemplateQuery) GetFieldKey() string {
|
|||
}
|
||||
|
||||
type Server struct {
|
||||
ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
|
||||
Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"`
|
||||
Username string `protobuf:"bytes,3,opt,name=Username,proto3" json:"Username,omitempty"`
|
||||
Password string `protobuf:"bytes,4,opt,name=Password,proto3" json:"Password,omitempty"`
|
||||
URL string `protobuf:"bytes,5,opt,name=URL,proto3" json:"URL,omitempty"`
|
||||
SrcID int64 `protobuf:"varint,6,opt,name=SrcID,proto3" json:"SrcID,omitempty"`
|
||||
Active bool `protobuf:"varint,7,opt,name=Active,proto3" json:"Active,omitempty"`
|
||||
Organization string `protobuf:"bytes,8,opt,name=Organization,proto3" json:"Organization,omitempty"`
|
||||
ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
|
||||
Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"`
|
||||
Username string `protobuf:"bytes,3,opt,name=Username,proto3" json:"Username,omitempty"`
|
||||
Password string `protobuf:"bytes,4,opt,name=Password,proto3" json:"Password,omitempty"`
|
||||
URL string `protobuf:"bytes,5,opt,name=URL,proto3" json:"URL,omitempty"`
|
||||
SrcID int64 `protobuf:"varint,6,opt,name=SrcID,proto3" json:"SrcID,omitempty"`
|
||||
Active bool `protobuf:"varint,7,opt,name=Active,proto3" json:"Active,omitempty"`
|
||||
Organization string `protobuf:"bytes,8,opt,name=Organization,proto3" json:"Organization,omitempty"`
|
||||
InsecureSkipVerify bool `protobuf:"varint,9,opt,name=InsecureSkipVerify,proto3" json:"InsecureSkipVerify,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Server) Reset() { *m = Server{} }
|
||||
func (m *Server) String() string { return proto.CompactTextString(m) }
|
||||
func (*Server) ProtoMessage() {}
|
||||
func (*Server) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{9} }
|
||||
func (*Server) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{11} }
|
||||
|
||||
func (m *Server) GetID() int64 {
|
||||
if m != nil {
|
||||
|
@ -657,6 +740,13 @@ func (m *Server) GetOrganization() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func (m *Server) GetInsecureSkipVerify() bool {
|
||||
if m != nil {
|
||||
return m.InsecureSkipVerify
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type Layout struct {
|
||||
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
|
||||
Application string `protobuf:"bytes,2,opt,name=Application,proto3" json:"Application,omitempty"`
|
||||
|
@ -668,7 +758,7 @@ type Layout struct {
|
|||
func (m *Layout) Reset() { *m = Layout{} }
|
||||
func (m *Layout) String() string { return proto.CompactTextString(m) }
|
||||
func (*Layout) ProtoMessage() {}
|
||||
func (*Layout) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{10} }
|
||||
func (*Layout) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{12} }
|
||||
|
||||
func (m *Layout) GetID() string {
|
||||
if m != nil {
|
||||
|
@ -722,7 +812,7 @@ type Cell struct {
|
|||
func (m *Cell) Reset() { *m = Cell{} }
|
||||
func (m *Cell) String() string { return proto.CompactTextString(m) }
|
||||
func (*Cell) ProtoMessage() {}
|
||||
func (*Cell) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{11} }
|
||||
func (*Cell) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{13} }
|
||||
|
||||
func (m *Cell) GetX() int32 {
|
||||
if m != nil {
|
||||
|
@ -816,7 +906,7 @@ type Query struct {
|
|||
func (m *Query) Reset() { *m = Query{} }
|
||||
func (m *Query) String() string { return proto.CompactTextString(m) }
|
||||
func (*Query) ProtoMessage() {}
|
||||
func (*Query) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{12} }
|
||||
func (*Query) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{14} }
|
||||
|
||||
func (m *Query) GetCommand() string {
|
||||
if m != nil {
|
||||
|
@ -890,7 +980,7 @@ type TimeShift struct {
|
|||
func (m *TimeShift) Reset() { *m = TimeShift{} }
|
||||
func (m *TimeShift) String() string { return proto.CompactTextString(m) }
|
||||
func (*TimeShift) ProtoMessage() {}
|
||||
func (*TimeShift) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{13} }
|
||||
func (*TimeShift) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{15} }
|
||||
|
||||
func (m *TimeShift) GetLabel() string {
|
||||
if m != nil {
|
||||
|
@ -921,7 +1011,7 @@ type Range struct {
|
|||
func (m *Range) Reset() { *m = Range{} }
|
||||
func (m *Range) String() string { return proto.CompactTextString(m) }
|
||||
func (*Range) ProtoMessage() {}
|
||||
func (*Range) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{14} }
|
||||
func (*Range) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{16} }
|
||||
|
||||
func (m *Range) GetUpper() int64 {
|
||||
if m != nil {
|
||||
|
@ -947,7 +1037,7 @@ type AlertRule struct {
|
|||
func (m *AlertRule) Reset() { *m = AlertRule{} }
|
||||
func (m *AlertRule) String() string { return proto.CompactTextString(m) }
|
||||
func (*AlertRule) ProtoMessage() {}
|
||||
func (*AlertRule) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{15} }
|
||||
func (*AlertRule) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{17} }
|
||||
|
||||
func (m *AlertRule) GetID() string {
|
||||
if m != nil {
|
||||
|
@ -989,7 +1079,7 @@ type User struct {
|
|||
func (m *User) Reset() { *m = User{} }
|
||||
func (m *User) String() string { return proto.CompactTextString(m) }
|
||||
func (*User) ProtoMessage() {}
|
||||
func (*User) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{16} }
|
||||
func (*User) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{18} }
|
||||
|
||||
func (m *User) GetID() uint64 {
|
||||
if m != nil {
|
||||
|
@ -1041,7 +1131,7 @@ type Role struct {
|
|||
func (m *Role) Reset() { *m = Role{} }
|
||||
func (m *Role) String() string { return proto.CompactTextString(m) }
|
||||
func (*Role) ProtoMessage() {}
|
||||
func (*Role) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{17} }
|
||||
func (*Role) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{19} }
|
||||
|
||||
func (m *Role) GetOrganization() string {
|
||||
if m != nil {
|
||||
|
@ -1068,7 +1158,7 @@ type Mapping struct {
|
|||
func (m *Mapping) Reset() { *m = Mapping{} }
|
||||
func (m *Mapping) String() string { return proto.CompactTextString(m) }
|
||||
func (*Mapping) ProtoMessage() {}
|
||||
func (*Mapping) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{18} }
|
||||
func (*Mapping) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{20} }
|
||||
|
||||
func (m *Mapping) GetProvider() string {
|
||||
if m != nil {
|
||||
|
@ -1114,7 +1204,7 @@ type Organization struct {
|
|||
func (m *Organization) Reset() { *m = Organization{} }
|
||||
func (m *Organization) String() string { return proto.CompactTextString(m) }
|
||||
func (*Organization) ProtoMessage() {}
|
||||
func (*Organization) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{19} }
|
||||
func (*Organization) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{21} }
|
||||
|
||||
func (m *Organization) GetID() string {
|
||||
if m != nil {
|
||||
|
@ -1144,7 +1234,7 @@ type Config struct {
|
|||
func (m *Config) Reset() { *m = Config{} }
|
||||
func (m *Config) String() string { return proto.CompactTextString(m) }
|
||||
func (*Config) ProtoMessage() {}
|
||||
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{20} }
|
||||
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{22} }
|
||||
|
||||
func (m *Config) GetAuth() *AuthConfig {
|
||||
if m != nil {
|
||||
|
@ -1160,7 +1250,7 @@ type AuthConfig struct {
|
|||
func (m *AuthConfig) Reset() { *m = AuthConfig{} }
|
||||
func (m *AuthConfig) String() string { return proto.CompactTextString(m) }
|
||||
func (*AuthConfig) ProtoMessage() {}
|
||||
func (*AuthConfig) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{21} }
|
||||
func (*AuthConfig) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{23} }
|
||||
|
||||
func (m *AuthConfig) GetSuperAdminNewUsers() bool {
|
||||
if m != nil {
|
||||
|
@ -1177,7 +1267,7 @@ type BuildInfo struct {
|
|||
func (m *BuildInfo) Reset() { *m = BuildInfo{} }
|
||||
func (m *BuildInfo) String() string { return proto.CompactTextString(m) }
|
||||
func (*BuildInfo) ProtoMessage() {}
|
||||
func (*BuildInfo) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{22} }
|
||||
func (*BuildInfo) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{24} }
|
||||
|
||||
func (m *BuildInfo) GetVersion() string {
|
||||
if m != nil {
|
||||
|
@ -1197,6 +1287,8 @@ func init() {
|
|||
proto.RegisterType((*Source)(nil), "internal.Source")
|
||||
proto.RegisterType((*Dashboard)(nil), "internal.Dashboard")
|
||||
proto.RegisterType((*DashboardCell)(nil), "internal.DashboardCell")
|
||||
proto.RegisterType((*TableOptions)(nil), "internal.TableOptions")
|
||||
proto.RegisterType((*TableColumn)(nil), "internal.TableColumn")
|
||||
proto.RegisterType((*Color)(nil), "internal.Color")
|
||||
proto.RegisterType((*Legend)(nil), "internal.Legend")
|
||||
proto.RegisterType((*Axis)(nil), "internal.Axis")
|
||||
|
@ -1222,93 +1314,103 @@ func init() {
|
|||
func init() { proto.RegisterFile("internal.proto", fileDescriptorInternal) }
|
||||
|
||||
var fileDescriptorInternal = []byte{
|
||||
// 1406 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x5f, 0x8f, 0xdb, 0x44,
|
||||
0x10, 0x97, 0x63, 0x3b, 0x89, 0x27, 0xd7, 0x52, 0x99, 0x13, 0x35, 0x45, 0x42, 0xc1, 0x02, 0x11,
|
||||
0x04, 0x3d, 0xd0, 0x55, 0x48, 0x08, 0x41, 0xa5, 0xdc, 0x05, 0x95, 0xa3, 0xd7, 0xf6, 0xba, 0xb9,
|
||||
0x3b, 0x9e, 0x50, 0xb5, 0x97, 0x4c, 0x12, 0xab, 0x8e, 0x6d, 0xd6, 0xf6, 0x5d, 0xcc, 0x87, 0x41,
|
||||
0x42, 0x82, 0x2f, 0x80, 0x78, 0xe7, 0x15, 0xf1, 0x41, 0xf8, 0x0a, 0x3c, 0x21, 0xa1, 0xd9, 0x5d,
|
||||
0xff, 0xc9, 0x25, 0xad, 0xfa, 0x80, 0x78, 0xdb, 0xdf, 0xcc, 0x66, 0x76, 0xfe, 0xfc, 0x66, 0xc6,
|
||||
0x81, 0x9b, 0x41, 0x94, 0xa1, 0x88, 0x78, 0xb8, 0x97, 0x88, 0x38, 0x8b, 0xdd, 0x6e, 0x89, 0xfd,
|
||||
0xbf, 0x5a, 0xd0, 0x1e, 0xc7, 0xb9, 0x98, 0xa0, 0x7b, 0x13, 0x5a, 0x47, 0x23, 0xcf, 0xe8, 0x1b,
|
||||
0x03, 0x93, 0xb5, 0x8e, 0x46, 0xae, 0x0b, 0xd6, 0x63, 0xbe, 0x44, 0xaf, 0xd5, 0x37, 0x06, 0x0e,
|
||||
0x93, 0x67, 0x92, 0x9d, 0x16, 0x09, 0x7a, 0xa6, 0x92, 0xd1, 0xd9, 0xbd, 0x03, 0xdd, 0xb3, 0x94,
|
||||
0xac, 0x2d, 0xd1, 0xb3, 0xa4, 0xbc, 0xc2, 0xa4, 0x3b, 0xe1, 0x69, 0x7a, 0x15, 0x8b, 0xa9, 0x67,
|
||||
0x2b, 0x5d, 0x89, 0xdd, 0x5b, 0x60, 0x9e, 0xb1, 0x63, 0xaf, 0x2d, 0xc5, 0x74, 0x74, 0x3d, 0xe8,
|
||||
0x8c, 0x70, 0xc6, 0xf3, 0x30, 0xf3, 0x3a, 0x7d, 0x63, 0xd0, 0x65, 0x25, 0x24, 0x3b, 0xa7, 0x18,
|
||||
0xe2, 0x5c, 0xf0, 0x99, 0xd7, 0x55, 0x76, 0x4a, 0xec, 0xee, 0x81, 0x7b, 0x14, 0xa5, 0x38, 0xc9,
|
||||
0x05, 0x8e, 0x9f, 0x07, 0xc9, 0x39, 0x8a, 0x60, 0x56, 0x78, 0x8e, 0x34, 0xb0, 0x45, 0x43, 0xaf,
|
||||
0x3c, 0xc2, 0x8c, 0xd3, 0xdb, 0x20, 0x4d, 0x95, 0xd0, 0xf5, 0x61, 0x67, 0xbc, 0xe0, 0x02, 0xa7,
|
||||
0x63, 0x9c, 0x08, 0xcc, 0xbc, 0x9e, 0x54, 0xaf, 0xc9, 0xe8, 0xce, 0x13, 0x31, 0xe7, 0x51, 0xf0,
|
||||
0x03, 0xcf, 0x82, 0x38, 0xf2, 0x76, 0xd4, 0x9d, 0xa6, 0x8c, 0xb2, 0xc4, 0xe2, 0x10, 0xbd, 0x1b,
|
||||
0x2a, 0x4b, 0x74, 0xf6, 0x7f, 0x33, 0xc0, 0x19, 0xf1, 0x74, 0x71, 0x11, 0x73, 0x31, 0x7d, 0xa5,
|
||||
0x5c, 0xdf, 0x05, 0x7b, 0x82, 0x61, 0x98, 0x7a, 0x66, 0xdf, 0x1c, 0xf4, 0xf6, 0x6f, 0xef, 0x55,
|
||||
0x45, 0xac, 0xec, 0x1c, 0x62, 0x18, 0x32, 0x75, 0xcb, 0xfd, 0x04, 0x9c, 0x0c, 0x97, 0x49, 0xc8,
|
||||
0x33, 0x4c, 0x3d, 0x4b, 0xfe, 0xc4, 0xad, 0x7f, 0x72, 0xaa, 0x55, 0xac, 0xbe, 0xb4, 0x11, 0x8a,
|
||||
0xbd, 0x19, 0x8a, 0xff, 0x4f, 0x0b, 0x6e, 0xac, 0x3d, 0xe7, 0xee, 0x80, 0xb1, 0x92, 0x9e, 0xdb,
|
||||
0xcc, 0x58, 0x11, 0x2a, 0xa4, 0xd7, 0x36, 0x33, 0x0a, 0x42, 0x57, 0x92, 0x1b, 0x36, 0x33, 0xae,
|
||||
0x08, 0x2d, 0x24, 0x23, 0x6c, 0x66, 0x2c, 0xdc, 0x0f, 0xa0, 0xf3, 0x7d, 0x8e, 0x22, 0xc0, 0xd4,
|
||||
0xb3, 0xa5, 0x77, 0xaf, 0xd5, 0xde, 0x3d, 0xcd, 0x51, 0x14, 0xac, 0xd4, 0x53, 0x36, 0x24, 0x9b,
|
||||
0x14, 0x35, 0xe4, 0x99, 0x64, 0x19, 0x31, 0xaf, 0xa3, 0x64, 0x74, 0xd6, 0x59, 0x54, 0x7c, 0xa0,
|
||||
0x2c, 0x7e, 0x0a, 0x16, 0x5f, 0x61, 0xea, 0x39, 0xd2, 0xfe, 0x3b, 0x2f, 0x48, 0xd8, 0xde, 0x70,
|
||||
0x85, 0xe9, 0x57, 0x51, 0x26, 0x0a, 0x26, 0xaf, 0xbb, 0xef, 0x43, 0x7b, 0x12, 0x87, 0xb1, 0x48,
|
||||
0x3d, 0xb8, 0xee, 0xd8, 0x21, 0xc9, 0x99, 0x56, 0xbb, 0x03, 0x68, 0x87, 0x38, 0xc7, 0x68, 0x2a,
|
||||
0x99, 0xd1, 0xdb, 0xbf, 0x55, 0x5f, 0x3c, 0x96, 0x72, 0xa6, 0xf5, 0x77, 0x1e, 0x80, 0x53, 0xbd,
|
||||
0x42, 0x44, 0x7f, 0x8e, 0x85, 0xcc, 0x99, 0xc3, 0xe8, 0xe8, 0xbe, 0x0b, 0xf6, 0x25, 0x0f, 0x73,
|
||||
0x55, 0xef, 0xde, 0xfe, 0xcd, 0xda, 0xce, 0x70, 0x15, 0xa4, 0x4c, 0x29, 0x3f, 0x6f, 0x7d, 0x66,
|
||||
0xf8, 0x73, 0xb0, 0xa5, 0x0f, 0x0d, 0xc6, 0x38, 0x25, 0x63, 0x64, 0x27, 0xb6, 0x1a, 0x9d, 0x78,
|
||||
0x0b, 0xcc, 0xaf, 0x71, 0xa5, 0x9b, 0x93, 0x8e, 0x15, 0xaf, 0xac, 0x06, 0xaf, 0x76, 0xc1, 0x3e,
|
||||
0x97, 0x8f, 0xab, 0x7a, 0x2b, 0xe0, 0xdf, 0x87, 0xb6, 0x8a, 0xa1, 0xb2, 0x6c, 0x34, 0x2c, 0xf7,
|
||||
0xa1, 0xf7, 0x44, 0x04, 0x18, 0x65, 0x8a, 0x29, 0xea, 0xd1, 0xa6, 0xc8, 0xff, 0xd5, 0x00, 0x8b,
|
||||
0x9c, 0x27, 0x56, 0x85, 0x38, 0xe7, 0x93, 0xe2, 0x20, 0xce, 0xa3, 0x69, 0xea, 0x19, 0x7d, 0x73,
|
||||
0x60, 0xb2, 0x35, 0x99, 0xfb, 0x06, 0xb4, 0x2f, 0x94, 0xb6, 0xd5, 0x37, 0x07, 0x0e, 0xd3, 0x88,
|
||||
0x5c, 0x0b, 0xf9, 0x05, 0x86, 0x3a, 0x04, 0x05, 0xe8, 0x76, 0x22, 0x70, 0x16, 0xac, 0x74, 0x18,
|
||||
0x1a, 0x91, 0x3c, 0xcd, 0x67, 0x24, 0x57, 0x91, 0x68, 0x44, 0x01, 0x5c, 0xf0, 0xb4, 0xa2, 0x0f,
|
||||
0x9d, 0xc9, 0x72, 0x3a, 0xe1, 0x61, 0xc9, 0x1f, 0x05, 0xfc, 0xdf, 0x0d, 0x9a, 0x2b, 0xaa, 0x1f,
|
||||
0x36, 0x32, 0xfc, 0x26, 0x74, 0xa9, 0x57, 0x9e, 0x5d, 0x72, 0xa1, 0x03, 0xee, 0x10, 0x3e, 0xe7,
|
||||
0xc2, 0xfd, 0x18, 0xda, 0xb2, 0x44, 0x5b, 0x7a, 0xb3, 0x34, 0x27, 0xb3, 0xca, 0xf4, 0xb5, 0x8a,
|
||||
0xbd, 0x56, 0x83, 0xbd, 0x55, 0xb0, 0x76, 0x33, 0xd8, 0xbb, 0x60, 0x53, 0x1b, 0x14, 0xd2, 0xfb,
|
||||
0xad, 0x96, 0x55, 0xb3, 0xa8, 0x5b, 0xfe, 0x19, 0xdc, 0x58, 0x7b, 0xb1, 0x7a, 0xc9, 0x58, 0x7f,
|
||||
0xa9, 0xa6, 0x9b, 0xa3, 0xe9, 0x45, 0x33, 0x35, 0xc5, 0x10, 0x27, 0x19, 0x4e, 0x65, 0xbe, 0xbb,
|
||||
0xac, 0xc2, 0xfe, 0x4f, 0x46, 0x6d, 0x57, 0xbe, 0x47, 0x53, 0x73, 0x12, 0x2f, 0x97, 0x3c, 0x9a,
|
||||
0x6a, 0xd3, 0x25, 0xa4, 0xbc, 0x4d, 0x2f, 0xb4, 0xe9, 0xd6, 0xf4, 0x82, 0xb0, 0x48, 0x74, 0x05,
|
||||
0x5b, 0x22, 0x21, 0xee, 0x2c, 0x91, 0xa7, 0xb9, 0xc0, 0x25, 0x46, 0x99, 0x4e, 0x41, 0x53, 0xe4,
|
||||
0xde, 0x86, 0x4e, 0xc6, 0xe7, 0xcf, 0xa8, 0x49, 0x74, 0x25, 0x33, 0x3e, 0x7f, 0x88, 0x85, 0xfb,
|
||||
0x16, 0x38, 0xb3, 0x00, 0xc3, 0xa9, 0x54, 0xa9, 0x72, 0x76, 0xa5, 0xe0, 0x21, 0x16, 0xfe, 0x1f,
|
||||
0x06, 0xb4, 0xc7, 0x28, 0x2e, 0x51, 0xbc, 0xd2, 0x38, 0x6d, 0xae, 0x29, 0xf3, 0x25, 0x6b, 0xca,
|
||||
0xda, 0xbe, 0xa6, 0xec, 0x7a, 0x4d, 0xed, 0x82, 0x3d, 0x16, 0x93, 0xa3, 0x91, 0xf4, 0xc8, 0x64,
|
||||
0x0a, 0x10, 0x1b, 0x87, 0x93, 0x2c, 0xb8, 0x44, 0xbd, 0xbb, 0x34, 0xda, 0x98, 0xb2, 0xdd, 0x2d,
|
||||
0x53, 0xf6, 0x47, 0x03, 0xda, 0xc7, 0xbc, 0x88, 0xf3, 0x6c, 0x83, 0x85, 0x7d, 0xe8, 0x0d, 0x93,
|
||||
0x24, 0x0c, 0x26, 0x6b, 0x9d, 0xd7, 0x10, 0xd1, 0x8d, 0x47, 0x8d, 0xfc, 0xaa, 0xd8, 0x9a, 0x22,
|
||||
0x1a, 0x37, 0x87, 0x72, 0x93, 0xa8, 0xb5, 0xd0, 0x18, 0x37, 0x6a, 0x81, 0x48, 0x25, 0x25, 0x61,
|
||||
0x98, 0x67, 0xf1, 0x2c, 0x8c, 0xaf, 0x64, 0xb4, 0x5d, 0x56, 0x61, 0xff, 0xcf, 0x16, 0x58, 0xff,
|
||||
0xd7, 0xf4, 0xdf, 0x01, 0x23, 0xd0, 0xc5, 0x36, 0x82, 0x6a, 0x17, 0x74, 0x1a, 0xbb, 0xc0, 0x83,
|
||||
0x4e, 0x21, 0x78, 0x34, 0xc7, 0xd4, 0xeb, 0xca, 0xe9, 0x52, 0x42, 0xa9, 0x91, 0x7d, 0xa4, 0x96,
|
||||
0x80, 0xc3, 0x4a, 0x58, 0xf5, 0x05, 0x34, 0xfa, 0xe2, 0x23, 0xbd, 0x2f, 0x7a, 0xd2, 0x23, 0x6f,
|
||||
0x3d, 0x2d, 0xd7, 0xd7, 0xc4, 0x7f, 0x37, 0xd3, 0xff, 0x36, 0xc0, 0xae, 0x9a, 0xea, 0x70, 0xbd,
|
||||
0xa9, 0x0e, 0xeb, 0xa6, 0x1a, 0x1d, 0x94, 0x4d, 0x35, 0x3a, 0x20, 0xcc, 0x4e, 0xca, 0xa6, 0x62,
|
||||
0x27, 0x54, 0xac, 0x07, 0x22, 0xce, 0x93, 0x83, 0x42, 0x55, 0xd5, 0x61, 0x15, 0x26, 0x26, 0x7e,
|
||||
0xbb, 0x40, 0xa1, 0x53, 0xed, 0x30, 0x8d, 0x88, 0xb7, 0xc7, 0x72, 0xe0, 0xa8, 0xe4, 0x2a, 0xe0,
|
||||
0xbe, 0x07, 0x36, 0xa3, 0xe4, 0xc9, 0x0c, 0xaf, 0xd5, 0x45, 0x8a, 0x99, 0xd2, 0x92, 0x51, 0xf5,
|
||||
0x9d, 0xa8, 0x09, 0x5c, 0x7e, 0x35, 0x7e, 0x08, 0xed, 0xf1, 0x22, 0x98, 0x65, 0xe5, 0xd6, 0x7d,
|
||||
0xbd, 0x31, 0xb0, 0x82, 0x25, 0x4a, 0x1d, 0xd3, 0x57, 0xfc, 0xa7, 0xe0, 0x54, 0xc2, 0xda, 0x1d,
|
||||
0xa3, 0xe9, 0x8e, 0x0b, 0xd6, 0x59, 0x14, 0x64, 0x65, 0xeb, 0xd2, 0x99, 0x82, 0x7d, 0x9a, 0xf3,
|
||||
0x28, 0x0b, 0xb2, 0xa2, 0x6c, 0xdd, 0x12, 0xfb, 0xf7, 0xb4, 0xfb, 0x64, 0xee, 0x2c, 0x49, 0x50,
|
||||
0xe8, 0x31, 0xa0, 0x80, 0x7c, 0x24, 0xbe, 0x42, 0x35, 0xc1, 0x4d, 0xa6, 0x80, 0xff, 0x1d, 0x38,
|
||||
0xc3, 0x10, 0x45, 0xc6, 0xf2, 0x10, 0xb7, 0x6d, 0xd6, 0x6f, 0xc6, 0x4f, 0x1e, 0x97, 0x1e, 0xd0,
|
||||
0xb9, 0x6e, 0x79, 0xf3, 0x5a, 0xcb, 0x3f, 0xe4, 0x09, 0x3f, 0x1a, 0x49, 0x9e, 0x9b, 0x4c, 0x23,
|
||||
0xff, 0x67, 0x03, 0x2c, 0x9a, 0x2d, 0x0d, 0xd3, 0xd6, 0xcb, 0xe6, 0xd2, 0x89, 0x88, 0x2f, 0x83,
|
||||
0x29, 0x8a, 0x32, 0xb8, 0x12, 0xcb, 0xa4, 0x4f, 0x16, 0x58, 0x2d, 0x70, 0x8d, 0x88, 0x6b, 0xf4,
|
||||
0x51, 0x59, 0xf6, 0x52, 0x83, 0x6b, 0x24, 0x66, 0x4a, 0xe9, 0xbe, 0x0d, 0x30, 0xce, 0x13, 0x14,
|
||||
0xc3, 0xe9, 0x32, 0x88, 0x64, 0xd1, 0xbb, 0xac, 0x21, 0xf1, 0xef, 0xab, 0xcf, 0xd4, 0x8d, 0x09,
|
||||
0x65, 0x6c, 0xff, 0xa4, 0xbd, 0xee, 0xb9, 0xff, 0x8b, 0x01, 0x9d, 0x47, 0x3c, 0x49, 0x82, 0x68,
|
||||
0xbe, 0x16, 0x85, 0xf1, 0xc2, 0x28, 0x5a, 0x6b, 0x51, 0xec, 0xc3, 0x6e, 0x79, 0x67, 0xed, 0x7d,
|
||||
0x95, 0x85, 0xad, 0x3a, 0x9d, 0x51, 0xab, 0x2a, 0xd6, 0xab, 0x7c, 0xc3, 0x9e, 0xae, 0xdf, 0xd9,
|
||||
0x56, 0xf0, 0x8d, 0xaa, 0xf4, 0xa1, 0xa7, 0xff, 0x7b, 0xc8, 0x2f, 0x79, 0x3d, 0x54, 0x1b, 0x22,
|
||||
0x7f, 0x1f, 0xda, 0x87, 0x71, 0x34, 0x0b, 0xe6, 0xee, 0x00, 0xac, 0x61, 0x9e, 0x2d, 0xa4, 0xc5,
|
||||
0xde, 0xfe, 0x6e, 0xa3, 0xf1, 0xf3, 0x6c, 0xa1, 0xee, 0x30, 0x79, 0xc3, 0xff, 0x02, 0xa0, 0x96,
|
||||
0xd1, 0x1f, 0x97, 0xba, 0x1a, 0x8f, 0xf1, 0x8a, 0x28, 0x93, 0x4a, 0x2b, 0x5d, 0xb6, 0x45, 0xe3,
|
||||
0x7f, 0x09, 0xce, 0x41, 0x1e, 0x84, 0xd3, 0xa3, 0x68, 0x16, 0xd3, 0xe8, 0x38, 0x47, 0x91, 0xd6,
|
||||
0xf5, 0x2a, 0x21, 0xa5, 0x9b, 0xa6, 0x48, 0xd5, 0x43, 0x1a, 0x5d, 0xb4, 0xe5, 0x7f, 0xbf, 0x7b,
|
||||
0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xe9, 0xd1, 0x8f, 0x0d, 0x0e, 0x00, 0x00,
|
||||
// 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,
|
||||
}
|
||||
|
|
|
@ -37,6 +37,20 @@ message DashboardCell {
|
|||
map<string, Axis> axes = 9; // Axes represent the graphical viewport for a cell's visualizations
|
||||
repeated Color colors = 10; // Colors represent encoding data values to color
|
||||
Legend legend = 11; // Legend is summary information for a cell
|
||||
TableOptions tableOptions = 12; // TableOptions for visualization of cell with type 'table'
|
||||
}
|
||||
|
||||
message TableOptions {
|
||||
string timeFormat = 1; // format for time
|
||||
bool verticalTimeAxis = 2; // time axis should be a column not row
|
||||
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
|
||||
}
|
||||
|
||||
message TableColumn {
|
||||
string internalName = 1; // name of column
|
||||
string displayName = 2; // what column is renamed to
|
||||
}
|
||||
|
||||
message Color {
|
||||
|
@ -95,6 +109,7 @@ message Server {
|
|||
int64 SrcID = 6; // SrcID is the ID of the data source
|
||||
bool Active = 7; // is this the currently active server for the source
|
||||
string Organization = 8; // Organization is the organization ID that resource belongs to
|
||||
bool InsecureSkipVerify = 9; // InsecureSkipVerify accepts any certificate from the client
|
||||
}
|
||||
|
||||
message Layout {
|
||||
|
|
|
@ -76,12 +76,13 @@ func TestMarshalSourceWithSecret(t *testing.T) {
|
|||
|
||||
func TestMarshalServer(t *testing.T) {
|
||||
v := chronograf.Server{
|
||||
ID: 12,
|
||||
SrcID: 2,
|
||||
Name: "Fountain of Truth",
|
||||
Username: "docbrown",
|
||||
Password: "1 point twenty-one g1g@w@tts",
|
||||
URL: "http://oldmanpeabody.mall.io:9092",
|
||||
ID: 12,
|
||||
SrcID: 2,
|
||||
Name: "Fountain of Truth",
|
||||
Username: "docbrown",
|
||||
Password: "1 point twenty-one g1g@w@tts",
|
||||
URL: "http://oldmanpeabody.mall.io:9092",
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
|
||||
var vv chronograf.Server
|
||||
|
@ -193,6 +194,10 @@ func Test_MarshalDashboard(t *testing.T) {
|
|||
Value: "100",
|
||||
},
|
||||
},
|
||||
TableOptions: chronograf.TableOptions{
|
||||
TimeFormat: "",
|
||||
ColumnNames: []chronograf.TableColumn{},
|
||||
},
|
||||
},
|
||||
},
|
||||
Templates: []chronograf.Template{},
|
||||
|
@ -255,6 +260,9 @@ func Test_MarshalDashboard_WithLegacyBounds(t *testing.T) {
|
|||
Type: "static",
|
||||
Orientation: "bottom",
|
||||
},
|
||||
TableOptions: chronograf.TableOptions{
|
||||
TimeFormat: "MM:DD:YYYY",
|
||||
},
|
||||
Type: "line",
|
||||
},
|
||||
},
|
||||
|
@ -309,6 +317,10 @@ func Test_MarshalDashboard_WithLegacyBounds(t *testing.T) {
|
|||
Type: "static",
|
||||
Orientation: "bottom",
|
||||
},
|
||||
TableOptions: chronograf.TableOptions{
|
||||
TimeFormat: "MM:DD:YYYY",
|
||||
ColumnNames: []chronograf.TableColumn{},
|
||||
},
|
||||
Type: "line",
|
||||
},
|
||||
},
|
||||
|
@ -369,6 +381,9 @@ func Test_MarshalDashboard_WithEmptyLegacyBounds(t *testing.T) {
|
|||
},
|
||||
},
|
||||
Type: "line",
|
||||
TableOptions: chronograf.TableOptions{
|
||||
TimeFormat: "MM:DD:YYYY",
|
||||
},
|
||||
},
|
||||
},
|
||||
Templates: []chronograf.Template{},
|
||||
|
@ -418,6 +433,10 @@ func Test_MarshalDashboard_WithEmptyLegacyBounds(t *testing.T) {
|
|||
Value: "100",
|
||||
},
|
||||
},
|
||||
TableOptions: chronograf.TableOptions{
|
||||
TimeFormat: "MM:DD:YYYY",
|
||||
ColumnNames: []chronograf.TableColumn{},
|
||||
},
|
||||
Type: "line",
|
||||
},
|
||||
},
|
||||
|
@ -434,3 +453,40 @@ func Test_MarshalDashboard_WithEmptyLegacyBounds(t *testing.T) {
|
|||
t.Fatalf("Dashboard protobuf copy error: diff follows:\n%s", cmp.Diff(expected, actual))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_MarshalDashboard_WithEmptyCellType(t *testing.T) {
|
||||
dashboard := chronograf.Dashboard{
|
||||
ID: 1,
|
||||
Cells: []chronograf.DashboardCell{
|
||||
{
|
||||
ID: "9b5367de-c552-4322-a9e8-7f384cbd235c",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := chronograf.Dashboard{
|
||||
ID: 1,
|
||||
Cells: []chronograf.DashboardCell{
|
||||
{
|
||||
ID: "9b5367de-c552-4322-a9e8-7f384cbd235c",
|
||||
Type: "line",
|
||||
Queries: []chronograf.DashboardQuery{},
|
||||
Axes: map[string]chronograf.Axis{},
|
||||
CellColors: []chronograf.CellColor{},
|
||||
TableOptions: chronograf.TableOptions{
|
||||
ColumnNames: []chronograf.TableColumn{},
|
||||
},
|
||||
},
|
||||
},
|
||||
Templates: []chronograf.Template{},
|
||||
}
|
||||
|
||||
var actual chronograf.Dashboard
|
||||
if buf, err := internal.MarshalDashboard(dashboard); err != nil {
|
||||
t.Fatal("Error marshaling dashboard: err", err)
|
||||
} else if err := internal.UnmarshalDashboard(buf, &actual); err != nil {
|
||||
t.Fatal("Error unmarshaling dashboard: err:", err)
|
||||
} else if !cmp.Equal(expected, actual) {
|
||||
t.Fatalf("Dashboard protobuf copy error: diff follows:\n%s", cmp.Diff(expected, actual))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,22 +20,24 @@ func TestServerStore(t *testing.T) {
|
|||
|
||||
srcs := []chronograf.Server{
|
||||
chronograf.Server{
|
||||
Name: "Of Truth",
|
||||
SrcID: 10,
|
||||
Username: "marty",
|
||||
Password: "I❤️ jennifer parker",
|
||||
URL: "toyota-hilux.lyon-estates.local",
|
||||
Active: false,
|
||||
Organization: "133",
|
||||
Name: "Of Truth",
|
||||
SrcID: 10,
|
||||
Username: "marty",
|
||||
Password: "I❤️ jennifer parker",
|
||||
URL: "toyota-hilux.lyon-estates.local",
|
||||
Active: false,
|
||||
Organization: "133",
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
chronograf.Server{
|
||||
Name: "HipToBeSquare",
|
||||
SrcID: 12,
|
||||
Username: "calvinklein",
|
||||
Password: "chuck b3rry",
|
||||
URL: "toyota-hilux.lyon-estates.local",
|
||||
Active: false,
|
||||
Organization: "133",
|
||||
Name: "HipToBeSquare",
|
||||
SrcID: 12,
|
||||
Username: "calvinklein",
|
||||
Password: "chuck b3rry",
|
||||
URL: "toyota-hilux.lyon-estates.local",
|
||||
Active: false,
|
||||
Organization: "133",
|
||||
InsecureSkipVerify: false,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -150,26 +150,26 @@ func (s *UsersStore) Add(ctx context.Context, u *chronograf.User) (*chronograf.U
|
|||
}
|
||||
|
||||
// Delete a user from the UsersStore
|
||||
func (s *UsersStore) Delete(ctx context.Context, usr *chronograf.User) error {
|
||||
_, err := s.get(ctx, usr.ID)
|
||||
func (s *UsersStore) Delete(ctx context.Context, u *chronograf.User) error {
|
||||
_, err := s.get(ctx, u.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.client.db.Update(func(tx *bolt.Tx) error {
|
||||
return tx.Bucket(UsersBucket).Delete(u64tob(usr.ID))
|
||||
return tx.Bucket(UsersBucket).Delete(u64tob(u.ID))
|
||||
})
|
||||
}
|
||||
|
||||
// Update a user
|
||||
func (s *UsersStore) Update(ctx context.Context, usr *chronograf.User) error {
|
||||
_, err := s.get(ctx, usr.ID)
|
||||
func (s *UsersStore) Update(ctx context.Context, u *chronograf.User) error {
|
||||
_, err := s.get(ctx, u.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.client.db.Update(func(tx *bolt.Tx) error {
|
||||
if v, err := internal.MarshalUser(usr); err != nil {
|
||||
if v, err := internal.MarshalUser(u); err != nil {
|
||||
return err
|
||||
} else if err := tx.Bucket(UsersBucket).Put(u64tob(usr.ID), v); err != nil {
|
||||
} else if err := tx.Bucket(UsersBucket).Put(u64tob(u.ID), v); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
]
|
||||
}
|
||||
],
|
||||
"colors": [],
|
||||
"type": "single-stat"
|
||||
},
|
||||
{
|
||||
|
@ -73,6 +74,7 @@
|
|||
]
|
||||
}
|
||||
],
|
||||
"colors": [],
|
||||
"type": "single-stat"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -117,6 +117,7 @@
|
|||
"h": 4,
|
||||
"i": "0fa47984-825b-46f1-9ca5-0366e3220008",
|
||||
"name": "Mesos Master Uptime",
|
||||
"colors": [],
|
||||
"type": "single-stat",
|
||||
"queries": [
|
||||
{
|
||||
|
|
|
@ -35,6 +35,9 @@ const (
|
|||
ErrCannotDeleteDefaultOrganization = Error("cannot delete default organization")
|
||||
ErrConfigNotFound = Error("cannot find configuration")
|
||||
ErrAnnotationNotFound = Error("annotation not found")
|
||||
ErrInvalidCellOptionsText = Error("invalid text wrapping option. Valid wrappings are 'truncate', 'wrap', and 'single line'")
|
||||
ErrInvalidCellOptionsSort = Error("cell options sortby cannot be empty'")
|
||||
ErrInvalidCellOptionsColumns = Error("cell options columns cannot be empty'")
|
||||
)
|
||||
|
||||
// Error is a domain error encountered while processing chronograf requests
|
||||
|
@ -543,17 +546,33 @@ type Legend struct {
|
|||
|
||||
// DashboardCell holds visual and query information for a cell
|
||||
type DashboardCell struct {
|
||||
ID string `json:"i"`
|
||||
X int32 `json:"x"`
|
||||
Y int32 `json:"y"`
|
||||
W int32 `json:"w"`
|
||||
H int32 `json:"h"`
|
||||
Name string `json:"name"`
|
||||
Queries []DashboardQuery `json:"queries"`
|
||||
Axes map[string]Axis `json:"axes"`
|
||||
Type string `json:"type"`
|
||||
CellColors []CellColor `json:"colors"`
|
||||
Legend Legend `json:"legend"`
|
||||
ID string `json:"i"`
|
||||
X int32 `json:"x"`
|
||||
Y int32 `json:"y"`
|
||||
W int32 `json:"w"`
|
||||
H int32 `json:"h"`
|
||||
Name string `json:"name"`
|
||||
Queries []DashboardQuery `json:"queries"`
|
||||
Axes map[string]Axis `json:"axes"`
|
||||
Type string `json:"type"`
|
||||
CellColors []CellColor `json:"colors"`
|
||||
Legend Legend `json:"legend"`
|
||||
TableOptions TableOptions `json:"tableOptions,omitempty"`
|
||||
}
|
||||
|
||||
// TableColumn is a column in a DashboardCell of type Table
|
||||
type TableColumn struct {
|
||||
InternalName string `json:"internalName"`
|
||||
DisplayName string `json:"displayName"`
|
||||
}
|
||||
|
||||
// TableOptions is a type of options for a DashboardCell with type Table
|
||||
type TableOptions struct {
|
||||
TimeFormat string `json:"timeFormat"`
|
||||
VerticalTimeAxis bool `json:"verticalTimeAxis"`
|
||||
SortBy TableColumn `json:"sortBy"`
|
||||
Wrapping string `json:"wrapping"`
|
||||
ColumnNames []TableColumn `json:"columnNames"`
|
||||
}
|
||||
|
||||
// DashboardsStore is the storage and retrieval of dashboards
|
||||
|
@ -572,15 +591,16 @@ type DashboardsStore interface {
|
|||
|
||||
// Cell is a rectangle and multiple time series queries to visualize.
|
||||
type Cell struct {
|
||||
X int32 `json:"x"`
|
||||
Y int32 `json:"y"`
|
||||
W int32 `json:"w"`
|
||||
H int32 `json:"h"`
|
||||
I string `json:"i"`
|
||||
Name string `json:"name"`
|
||||
Queries []Query `json:"queries"`
|
||||
Axes map[string]Axis `json:"axes"`
|
||||
Type string `json:"type"`
|
||||
X int32 `json:"x"`
|
||||
Y int32 `json:"y"`
|
||||
W int32 `json:"w"`
|
||||
H int32 `json:"h"`
|
||||
I string `json:"i"`
|
||||
Name string `json:"name"`
|
||||
Queries []Query `json:"queries"`
|
||||
Axes map[string]Axis `json:"axes"`
|
||||
Type string `json:"type"`
|
||||
CellColors []CellColor `json:"colors"`
|
||||
}
|
||||
|
||||
// Layout is a collection of Cells for visualization
|
||||
|
|
|
@ -1 +1 @@
|
|||
**We've moved our documentation!** Check out the latest [authentication content](https://docs.influxdata.com/chronograf/latest/administration/security-best-practices/#chronograf-with-oauth-2-0-authentication) on InfluxData's [main docs site](https://docs.influxdata.com/chronograf/latest/).
|
||||
**We've moved our documentation!** Check out the latest [authentication content](https://docs.influxdata.com/chronograf/latest/administration/managing-security/#oauth-2-0-providers-with-jwt-tokens) on InfluxData's [main docs site](https://docs.influxdata.com/chronograf/latest/).
|
||||
|
|
|
@ -12,10 +12,6 @@ import (
|
|||
// SortTemplates the templates by size, then type, then value.
|
||||
func SortTemplates(ts []chronograf.TemplateVar) []chronograf.TemplateVar {
|
||||
sort.Slice(ts, func(i, j int) bool {
|
||||
if ts[i].Var == ":interval:" {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(ts[i].Values) != len(ts[j].Values) {
|
||||
return len(ts[i].Values) < len(ts[j].Values)
|
||||
}
|
||||
|
@ -63,20 +59,6 @@ func RenderTemplate(query string, t chronograf.TemplateVar, now time.Time) (stri
|
|||
tv[t.Values[i].Type] = t.Values[i].Value
|
||||
}
|
||||
|
||||
if pts, ok := tv["points"]; ok {
|
||||
points, err := strconv.ParseInt(pts, 0, 64)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
dur, err := ParseTime(query, now)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
interval := AutoInterval(points, dur)
|
||||
return strings.Replace(query, t.Var, interval, -1), nil
|
||||
}
|
||||
|
||||
if res, ok := tv["resolution"]; ok {
|
||||
resolution, err := strconv.ParseInt(res, 0, 64)
|
||||
if err != nil {
|
||||
|
@ -101,22 +83,6 @@ func RenderTemplate(query string, t chronograf.TemplateVar, now time.Time) (stri
|
|||
return query, nil
|
||||
}
|
||||
|
||||
func AutoInterval(points int64, duration time.Duration) string {
|
||||
// The function is: ((total_seconds * millisecond_converstion) / group_by) = pixels / 3
|
||||
// Number of points given the pixels
|
||||
pixels := float64(points)
|
||||
msPerPixel := float64(duration/time.Millisecond) / pixels
|
||||
secPerPixel := float64(duration/time.Second) / pixels
|
||||
if secPerPixel < 1.0 {
|
||||
if msPerPixel < 1.0 {
|
||||
msPerPixel = 1.0
|
||||
}
|
||||
return strconv.FormatInt(int64(msPerPixel), 10) + "ms"
|
||||
}
|
||||
// If groupby is more than 1 second round to the second
|
||||
return strconv.FormatInt(int64(secPerPixel), 10) + "s"
|
||||
}
|
||||
|
||||
// AutoGroupBy generates the time to group by in order to decimate the number of
|
||||
// points returned in a query
|
||||
func AutoGroupBy(resolution, pixelsPerPoint int64, duration time.Duration) string {
|
||||
|
|
|
@ -125,38 +125,6 @@ func TestTemplateReplace(t *testing.T) {
|
|||
},
|
||||
want: `SELECT :field: FROM "cpu"`,
|
||||
},
|
||||
{
|
||||
name: "auto interval",
|
||||
query: `SELECT mean(usage_idle) from "cpu" where time > now() - 4320h group by time(:interval:)`,
|
||||
vars: []chronograf.TemplateVar{
|
||||
{
|
||||
Var: ":interval:",
|
||||
Values: []chronograf.TemplateValue{
|
||||
{
|
||||
Value: "333",
|
||||
Type: "points",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: `SELECT mean(usage_idle) from "cpu" where time > now() - 4320h group by time(46702s)`,
|
||||
},
|
||||
{
|
||||
name: "auto interval",
|
||||
query: `SELECT derivative(mean(usage_idle),:interval:) from "cpu" where time > now() - 4320h group by time(:interval:)`,
|
||||
vars: []chronograf.TemplateVar{
|
||||
{
|
||||
Var: ":interval:",
|
||||
Values: []chronograf.TemplateValue{
|
||||
{
|
||||
Value: "333",
|
||||
Type: "points",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: `SELECT derivative(mean(usage_idle),46702s) from "cpu" where time > now() - 4320h group by time(46702s)`,
|
||||
},
|
||||
{
|
||||
name: "auto group by",
|
||||
query: `SELECT mean(usage_idle) from "cpu" where time > now() - 4320h group by :interval:`,
|
||||
|
@ -165,7 +133,7 @@ func TestTemplateReplace(t *testing.T) {
|
|||
Var: ":interval:",
|
||||
Values: []chronograf.TemplateValue{
|
||||
{
|
||||
Value: "999",
|
||||
Value: "1000",
|
||||
Type: "resolution",
|
||||
},
|
||||
{
|
||||
|
@ -175,7 +143,7 @@ func TestTemplateReplace(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
want: `SELECT mean(usage_idle) from "cpu" where time > now() - 4320h group by time(46702s)`,
|
||||
want: `SELECT mean(usage_idle) from "cpu" where time > now() - 4320h group by time(46655s)`,
|
||||
},
|
||||
{
|
||||
name: "auto group by without duration",
|
||||
|
@ -185,7 +153,7 @@ func TestTemplateReplace(t *testing.T) {
|
|||
Var: ":interval:",
|
||||
Values: []chronograf.TemplateValue{
|
||||
{
|
||||
Value: "999",
|
||||
Value: "1000",
|
||||
Type: "resolution",
|
||||
},
|
||||
{
|
||||
|
@ -195,7 +163,7 @@ func TestTemplateReplace(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
want: `SELECT mean(usage_idle) from "cpu" WHERE time > now() - 4320h group by time(46702s)`,
|
||||
want: `SELECT mean(usage_idle) from "cpu" WHERE time > now() - 4320h group by time(46655s)`,
|
||||
},
|
||||
{
|
||||
name: "auto group by with :dashboardTime:",
|
||||
|
|
|
@ -164,7 +164,8 @@ func TestServer(t *testing.T) {
|
|||
"id": "5000",
|
||||
"name": "Kapa 1",
|
||||
"url": "http://localhost:9092",
|
||||
"active": true,
|
||||
"active": true,
|
||||
"insecureSkipVerify": false,
|
||||
"links": {
|
||||
"proxy": "/chronograf/v1/sources/5000/kapacitors/5000/proxy",
|
||||
"self": "/chronograf/v1/sources/5000/kapacitors/5000",
|
||||
|
@ -222,7 +223,8 @@ func TestServer(t *testing.T) {
|
|||
"id": "5000",
|
||||
"name": "Kapa 1",
|
||||
"url": "http://localhost:9092",
|
||||
"active": true,
|
||||
"active": true,
|
||||
"insecureSkipVerify": false,
|
||||
"links": {
|
||||
"proxy": "/chronograf/v1/sources/5000/kapacitors/5000/proxy",
|
||||
"self": "/chronograf/v1/sources/5000/kapacitors/5000",
|
||||
|
@ -540,7 +542,16 @@ func TestServer(t *testing.T) {
|
|||
"legend":{
|
||||
"type": "static",
|
||||
"orientation": "bottom"
|
||||
},
|
||||
},
|
||||
"tableOptions":{
|
||||
"timeFormat": "",
|
||||
"verticalTimeAxis": false,
|
||||
"sortBy":{
|
||||
"internalName": "",
|
||||
"displayName": ""},
|
||||
"wrapping": "",
|
||||
"columnNames": null
|
||||
},
|
||||
"links": {
|
||||
"self": "/chronograf/v1/dashboards/1000/cells/8f61c619-dd9b-4761-8aa8-577f27247093"
|
||||
}
|
||||
|
@ -779,7 +790,17 @@ func TestServer(t *testing.T) {
|
|||
"name": "comet",
|
||||
"value": "100"
|
||||
}
|
||||
],
|
||||
],
|
||||
"tableOptions":{
|
||||
"timeFormat":"",
|
||||
"verticalTimeAxis":false,
|
||||
"sortBy":{
|
||||
"internalName":"",
|
||||
"displayName":""
|
||||
},
|
||||
"wrapping":"",
|
||||
"columnNames":null
|
||||
},
|
||||
"legend":{
|
||||
"type": "static",
|
||||
"orientation": "bottom"
|
||||
|
|
|
@ -2,6 +2,7 @@ package oauth2
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/influxdata/chronograf"
|
||||
|
@ -61,7 +62,19 @@ func (h *Heroku) PrincipalID(provider *http.Client) (string, error) {
|
|||
DefaultOrganization DefaultOrg `json:"default_organization"`
|
||||
}
|
||||
|
||||
resp, err := provider.Get(HerokuAccountRoute)
|
||||
req, err := http.NewRequest("GET", HerokuAccountRoute, nil)
|
||||
// Requests fail to Heroku unless this Accept header is set.
|
||||
req.Header.Set("Accept", "application/vnd.heroku+json; version=3")
|
||||
resp, err := provider.Do(req)
|
||||
if resp.StatusCode/100 != 2 {
|
||||
err := fmt.Errorf(
|
||||
"Unable to GET user data from %s. Status: %s",
|
||||
HerokuAccountRoute,
|
||||
resp.Status,
|
||||
)
|
||||
h.Logger.Error("", err)
|
||||
return "", err
|
||||
}
|
||||
if err != nil {
|
||||
h.Logger.Error("Unable to communicate with Heroku. err:", err)
|
||||
return "", err
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package oauth2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"net/http/httptest"
|
||||
|
@ -13,15 +14,24 @@ import (
|
|||
|
||||
var testTime = time.Date(1985, time.October, 25, 18, 0, 0, 0, time.UTC)
|
||||
|
||||
type mockCallbackResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
}
|
||||
|
||||
// setupMuxTest produces an http.Client and an httptest.Server configured to
|
||||
// use a particular http.Handler selected from a AuthMux. As this selection is
|
||||
// done during the setup process, this configuration is performed by providing
|
||||
// a function, and returning the desired handler. Cleanup is still the
|
||||
// responsibility of the test writer, so the httptest.Server's Close() method
|
||||
// should be deferred.
|
||||
func setupMuxTest(selector func(*AuthMux) http.Handler) (*http.Client, *httptest.Server, *httptest.Server) {
|
||||
func setupMuxTest(response interface{}, selector func(*AuthMux) http.Handler) (*http.Client, *httptest.Server, *httptest.Server) {
|
||||
provider := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.Header().Set("content-type", "application/json")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
|
||||
body, _ := json.Marshal(response)
|
||||
|
||||
rw.Write(body)
|
||||
}))
|
||||
|
||||
now := func() time.Time {
|
||||
|
@ -63,7 +73,9 @@ func teardownMuxTest(hc *http.Client, backend *httptest.Server, provider *httpte
|
|||
func Test_AuthMux_Logout_DeletesSessionCookie(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
hc, ts, prov := setupMuxTest(func(j *AuthMux) http.Handler {
|
||||
var response interface{}
|
||||
|
||||
hc, ts, prov := setupMuxTest(response, func(j *AuthMux) http.Handler {
|
||||
return j.Logout()
|
||||
})
|
||||
defer teardownMuxTest(hc, ts, prov)
|
||||
|
@ -100,7 +112,9 @@ func Test_AuthMux_Logout_DeletesSessionCookie(t *testing.T) {
|
|||
func Test_AuthMux_Login_RedirectsToCorrectURL(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
hc, ts, prov := setupMuxTest(func(j *AuthMux) http.Handler {
|
||||
var response interface{}
|
||||
|
||||
hc, ts, prov := setupMuxTest(response, func(j *AuthMux) http.Handler {
|
||||
return j.Login() // Use Login handler for httptest server.
|
||||
})
|
||||
defer teardownMuxTest(hc, ts, prov)
|
||||
|
@ -126,7 +140,8 @@ func Test_AuthMux_Login_RedirectsToCorrectURL(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_AuthMux_Callback_SetsCookie(t *testing.T) {
|
||||
hc, ts, prov := setupMuxTest(func(j *AuthMux) http.Handler {
|
||||
response := mockCallbackResponse{AccessToken: "123"}
|
||||
hc, ts, prov := setupMuxTest(response, func(j *AuthMux) http.Handler {
|
||||
return j.Callback()
|
||||
})
|
||||
defer teardownMuxTest(hc, ts, prov)
|
||||
|
|
|
@ -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":{},"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},"links":{"self":"/chronograf/v1/dashboards/1/cells/3c5c4102-fa40-4585-a8f9-917c77e37192"}}
|
||||
`,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@ type postKapacitorRequest struct {
|
|||
URL *string `json:"url"` // URL for the kapacitor backend (e.g. http://localhost:9092);/ Required: true
|
||||
Username string `json:"username,omitempty"` // Username for authentication to kapacitor
|
||||
Password string `json:"password,omitempty"`
|
||||
InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"` // InsecureSkipVerify as true means any certificate presented by the kapacitor is accepted.
|
||||
InsecureSkipVerify bool `json:"insecureSkipVerify"` // InsecureSkipVerify as true means any certificate presented by the kapacitor is accepted.
|
||||
Active bool `json:"active"`
|
||||
Organization string `json:"organization"` // Organization is the organization ID that resource belongs to
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ type kapacitor struct {
|
|||
URL string `json:"url"` // URL for the kapacitor backend (e.g. http://localhost:9092)
|
||||
Username string `json:"username,omitempty"` // Username for authentication to kapacitor
|
||||
Password string `json:"password,omitempty"`
|
||||
InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"` // InsecureSkipVerify as true means any certificate presented by the kapacitor is accepted.
|
||||
InsecureSkipVerify bool `json:"insecureSkipVerify"` // InsecureSkipVerify as true means any certificate presented by the kapacitor is accepted.
|
||||
Active bool `json:"active"`
|
||||
Links kapaLinks `json:"links"` // Links are URI locations related to kapacitor
|
||||
}
|
||||
|
@ -225,7 +225,7 @@ type patchKapacitorRequest struct {
|
|||
URL *string `json:"url,omitempty"` // URL for the kapacitor
|
||||
Username *string `json:"username,omitempty"` // Username for kapacitor auth
|
||||
Password *string `json:"password,omitempty"`
|
||||
InsecureSkipVerify *bool `json:"insecureSkipVerify,omitempty"` // InsecureSkipVerify as true means any certificate presented by the kapacitor is accepted.
|
||||
InsecureSkipVerify *bool `json:"insecureSkipVerify"` // InsecureSkipVerify as true means any certificate presented by the kapacitor is accepted.
|
||||
Active *bool `json:"active"`
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,10 @@ func newLayoutResponse(layout chronograf.Layout) layoutResponse {
|
|||
layout.Cells[idx].Axes = make(map[string]chronograf.Axis, len(axes))
|
||||
}
|
||||
|
||||
if cell.CellColors == nil {
|
||||
layout.Cells[idx].CellColors = []chronograf.CellColor{}
|
||||
}
|
||||
|
||||
for _, axis := range axes {
|
||||
if _, found := cell.Axes[axis]; !found {
|
||||
layout.Cells[idx].Axes[axis] = chronograf.Axis{
|
||||
|
|
|
@ -76,12 +76,13 @@ func Test_Layouts(t *testing.T) {
|
|||
Measurement: "influxdb",
|
||||
Cells: []chronograf.Cell{
|
||||
{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
W: 4,
|
||||
H: 4,
|
||||
I: "3b0e646b-2ca3-4df2-95a5-fd80915459dd",
|
||||
Name: "A Graph",
|
||||
X: 0,
|
||||
Y: 0,
|
||||
W: 4,
|
||||
H: 4,
|
||||
I: "3b0e646b-2ca3-4df2-95a5-fd80915459dd",
|
||||
Name: "A Graph",
|
||||
CellColors: []chronograf.CellColor{},
|
||||
Axes: map[string]chronograf.Axis{
|
||||
"x": chronograf.Axis{
|
||||
Bounds: []string{},
|
||||
|
@ -103,12 +104,13 @@ func Test_Layouts(t *testing.T) {
|
|||
Measurement: "influxdb",
|
||||
Cells: []chronograf.Cell{
|
||||
{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
W: 4,
|
||||
H: 4,
|
||||
I: "3b0e646b-2ca3-4df2-95a5-fd80915459dd",
|
||||
Name: "A Graph",
|
||||
X: 0,
|
||||
Y: 0,
|
||||
W: 4,
|
||||
H: 4,
|
||||
I: "3b0e646b-2ca3-4df2-95a5-fd80915459dd",
|
||||
CellColors: []chronograf.CellColor{},
|
||||
Name: "A Graph",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"info": {
|
||||
"title": "Chronograf",
|
||||
"description": "API endpoints for Chronograf",
|
||||
"version": "1.4.1.3"
|
||||
"version": "1.4.2.3"
|
||||
},
|
||||
"schemes": ["http"],
|
||||
"basePath": "/chronograf/v1",
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"transform-runtime",
|
||||
"lodash"
|
||||
],
|
||||
"presets": ["es2015", "react", "stage-0"],
|
||||
"presets": ["env", "react", "stage-0"],
|
||||
"env": {
|
||||
"production": {
|
||||
"plugins": [
|
||||
|
|
14
ui/.eslintrc
14
ui/.eslintrc
|
@ -1,20 +1,26 @@
|
|||
{
|
||||
parser: 'babel-eslint',
|
||||
"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": {
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
arrowFunctions: true,
|
||||
binaryLiterals: true,
|
||||
|
@ -244,6 +250,10 @@
|
|||
'semi': false,
|
||||
}],
|
||||
|
||||
// jest
|
||||
'jest/no-disabled-tests': "warn",
|
||||
'jest/no-focused-tests': "error",
|
||||
|
||||
// Babel
|
||||
'babel/no-invalid-this': 1
|
||||
},
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
module.exports = {
|
||||
projects: [
|
||||
{
|
||||
displayName: 'test',
|
||||
testPathIgnorePatterns: [
|
||||
'build',
|
||||
'<rootDir>/node_modules/(?!(jest-test))',
|
||||
],
|
||||
modulePaths: ['<rootDir>', '<rootDir>/node_modules/'],
|
||||
moduleDirectories: ['src'],
|
||||
setupFiles: ['<rootDir>/test/setupTests.js'],
|
||||
transform: {
|
||||
'^.+\\.tsx?$': 'ts-jest',
|
||||
'^.+\\.js$': 'babel-jest',
|
||||
},
|
||||
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$',
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
||||
},
|
||||
{
|
||||
runner: 'jest-runner-eslint',
|
||||
displayName: 'lint',
|
||||
testMatch: ['<rootDir>/test/**/*.test.js'],
|
||||
},
|
||||
],
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
var webpack = require('webpack')
|
||||
var path = require('path')
|
||||
const webpack = require('webpack')
|
||||
const path = require('path')
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
browsers: ['PhantomJS'],
|
||||
singleRun: true,
|
||||
frameworks: ['mocha', 'sinon-chai'],
|
||||
frameworks: ['mocha'],
|
||||
files: [
|
||||
'node_modules/babel-polyfill/dist/polyfill.js',
|
||||
'spec/spec-helper.js',
|
||||
|
@ -42,10 +41,6 @@ module.exports = function(config) {
|
|||
test: /sinon\/pkg\/sinon\.js/,
|
||||
loader: 'imports?define=>false,require=>false',
|
||||
},
|
||||
{
|
||||
test: /\.json$/,
|
||||
loader: 'json',
|
||||
},
|
||||
],
|
||||
},
|
||||
externals: {
|
||||
|
@ -61,7 +56,6 @@ module.exports = function(config) {
|
|||
shared: path.resolve(__dirname, 'src', 'shared'),
|
||||
style: path.resolve(__dirname, 'src', 'style'),
|
||||
utils: path.resolve(__dirname, 'src', 'utils'),
|
||||
sinon: 'sinon/pkg/sinon',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
export const source = {
|
||||
id: '2',
|
||||
name: 'minikube-influx',
|
||||
type: 'influx',
|
||||
url: 'http://192.168.99.100:30400',
|
||||
default: true,
|
||||
telegraf: 'telegraf',
|
||||
organization: 'default',
|
||||
role: 'viewer',
|
||||
links: {
|
||||
self: '/chronograf/v1/sources/2',
|
||||
kapacitors: '/chronograf/v1/sources/2/kapacitors',
|
||||
proxy: '/chronograf/v1/sources/2/proxy',
|
||||
queries: '/chronograf/v1/sources/2/queries',
|
||||
write: '/chronograf/v1/sources/2/write',
|
||||
permissions: '/chronograf/v1/sources/2/permissions',
|
||||
users: '/chronograf/v1/sources/2/users',
|
||||
databases: '/chronograf/v1/sources/2/dbs',
|
||||
annotations: '/chronograf/v1/sources/2/annotations',
|
||||
},
|
||||
}
|
||||
|
||||
export const kapacitor = {
|
||||
id: '1',
|
||||
name: 'Test Kapacitor',
|
||||
url: 'http://localhost:9092',
|
||||
insecureSkipVerify: false,
|
||||
active: true,
|
||||
links: {
|
||||
self: '/chronograf/v1/sources/47/kapacitors/1',
|
||||
proxy: '/chronograf/v1/sources/47/kapacitors/1/proxy',
|
||||
},
|
||||
}
|
||||
|
||||
export const createKapacitorBody = {
|
||||
name: 'Test Kapacitor',
|
||||
url: 'http://localhost:9092',
|
||||
insecureSkipVerify: false,
|
||||
username: 'user',
|
||||
password: 'pass',
|
||||
}
|
||||
|
||||
export const updateKapacitorBody = {
|
||||
name: 'Test Kapacitor',
|
||||
url: 'http://localhost:9092',
|
||||
insecureSkipVerify: false,
|
||||
username: 'user',
|
||||
password: 'pass',
|
||||
active: true,
|
||||
links: {
|
||||
self: '/chronograf/v1/sources/47/kapacitors/1',
|
||||
proxy: '/chronograf/v1/sources/47/kapacitors/1/proxy',
|
||||
},
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import {kapacitor} from 'mocks/dummy'
|
||||
|
||||
export const getKapacitor = jest.fn(() => Promise.resolve(kapacitor))
|
||||
export const createKapacitor = jest.fn(() => Promise.resolve({data: kapacitor}))
|
||||
export const updateKapacitor = jest.fn(() => Promise.resolve({data: kapacitor}))
|
||||
export const pingKapacitor = jest.fn(() => Promise.resolve())
|
|
@ -0,0 +1 @@
|
|||
export default jest.fn(() => Promise.resolve())
|
|
@ -1,37 +0,0 @@
|
|||
{
|
||||
"src_folders": ["tests"],
|
||||
"output_folder": "reports",
|
||||
"custom_commands_path": "",
|
||||
"custom_assertions_path": "",
|
||||
"page_objects_path": "",
|
||||
"globals_path": "",
|
||||
|
||||
"selenium": {
|
||||
"start_process": false,
|
||||
"host": "hub-cloud.browserstack.com",
|
||||
"port": 80
|
||||
},
|
||||
|
||||
"live_output" : true,
|
||||
|
||||
"test_settings": {
|
||||
"default": {
|
||||
"selenium_port": 80,
|
||||
"selenium_host": "hub-cloud.browserstack.com",
|
||||
"silent": false,
|
||||
"screenshots": {
|
||||
"enabled": true,
|
||||
"path": "screenshots"
|
||||
},
|
||||
"desiredCapabilities": {
|
||||
"browser": "chrome",
|
||||
"build": "nightwatch-browserstack",
|
||||
"browserstack.user": "${BROWSERSTACK_USER}",
|
||||
"browserstack.key": "${BROWSERSTACK_KEY}",
|
||||
"browserstack.debug": true,
|
||||
"browserstack.local": true,
|
||||
"resolution": "1280x1024"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
102
ui/package.json
102
ui/package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "chronograf-ui",
|
||||
"version": "1.4.1-3",
|
||||
"version": "1.4.2-3",
|
||||
"private": false,
|
||||
"license": "AGPL-3.0",
|
||||
"description": "",
|
||||
|
@ -9,17 +9,19 @@
|
|||
"url": "github:influxdata/chronograf"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yarn run clean && env NODE_ENV=production webpack --optimize-minimize --config ./webpack/prodConfig.js",
|
||||
"build:dev": "webpack --config ./webpack/devConfig.js",
|
||||
"start": "yarn run clean && webpack --watch --config ./webpack/devConfig.js",
|
||||
"start:hmr": "webpack-dev-server --open --config ./webpack/devConfig.js",
|
||||
"build": "yarn run clean && webpack --config ./webpack/prod.config.js",
|
||||
"build:dev": "webpack --config ./webpack/dev.config.js",
|
||||
"build:vendor": "webpack --config webpack/vendor.config.js",
|
||||
"start": "yarn run clean && yarn run build:vendor && webpack --watch --config ./webpack/dev.config.js",
|
||||
"start:fast": "webpack --watch --config ./webpack/dev.config.js",
|
||||
"start:hmr": "webpack-dev-server --open --config ./webpack/dev.config.js",
|
||||
"lint": "esw src/",
|
||||
"test": "karma start",
|
||||
"test:integration": "nightwatch tests --skip",
|
||||
"test": "jest",
|
||||
"test:lint": "yarn run lint; yarn run test",
|
||||
"test:dev": "concurrently \"yarn run lint --watch\" \"yarn run test --no-single-run --reporters=verbose\"",
|
||||
"clean": "rm -rf build/*",
|
||||
"prettier": "prettier --single-quote --trailing-comma es5 --bracket-spacing false --semi false --write \"{src,spec}/**/*.js\"; eslint src --fix"
|
||||
"test:watch": "jest --watch",
|
||||
"clean": "rm -rf ./build/*",
|
||||
"prettier": "prettier --single-quote --trailing-comma es5 --bracket-spacing false --semi false --write \"{src,spec}/**/*.js\"; eslint src --fix",
|
||||
"eslint-check": "eslint --print-config .eslintrc | eslint-config-prettier-check"
|
||||
},
|
||||
"author": "",
|
||||
"eslintConfig": {
|
||||
|
@ -28,10 +30,18 @@
|
|||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.1.2",
|
||||
"@types/enzyme": "^3.1.9",
|
||||
"@types/jest": "^22.1.4",
|
||||
"@types/lodash": "^4.14.104",
|
||||
"@types/node": "^9.4.6",
|
||||
"@types/prop-types": "^15.5.2",
|
||||
"@types/react": "^16.0.38",
|
||||
"autoprefixer": "^6.3.1",
|
||||
"babel-core": "^6.5.1",
|
||||
"babel-eslint": "6.1.2",
|
||||
"babel-loader": "^6.2.2",
|
||||
"babel-jest": "^22.4.1",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-plugin-lodash": "^2.0.1",
|
||||
"babel-plugin-syntax-trailing-function-commas": "^6.5.0",
|
||||
"babel-plugin-transform-decorators-legacy": "^1.3.4",
|
||||
|
@ -39,42 +49,36 @@
|
|||
"babel-plugin-transform-react-remove-prop-types": "^0.2.1",
|
||||
"babel-plugin-transform-runtime": "^6.5.0",
|
||||
"babel-polyfill": "^6.13.0",
|
||||
"babel-preset-es2015": "^6.5.0",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"babel-preset-react": "^6.5.0",
|
||||
"babel-preset-stage-0": "^6.16.0",
|
||||
"babel-runtime": "^6.5.0",
|
||||
"bower": "^1.7.7",
|
||||
"chai": "^3.5.0",
|
||||
"compression-webpack-plugin": "^1.1.8",
|
||||
"concurrently": "^3.5.0",
|
||||
"core-js": "^2.1.3",
|
||||
"css-loader": "^0.23.1",
|
||||
"envify": "^3.4.0",
|
||||
"enzyme": "^2.4.1",
|
||||
"enzyme": "^3.3.0",
|
||||
"enzyme-adapter-react-15": "^1.0.5",
|
||||
"eslint": "^3.14.1",
|
||||
"eslint-loader": "1.6.1",
|
||||
"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-react": "6.6.0",
|
||||
"eslint-watch": "^3.1.2",
|
||||
"express": "^4.14.0",
|
||||
"extract-text-webpack-plugin": "^1.0.1",
|
||||
"file-loader": "^0.8.5",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"file-loader": "^1.1.7",
|
||||
"fork-ts-checker-webpack-plugin": "^0.3.0",
|
||||
"hanson": "^1.1.1",
|
||||
"hson-loader": "^1.0.0",
|
||||
"html-webpack-plugin": "^2.22.0",
|
||||
"html-webpack-include-assets-plugin": "^1.0.2",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"imports-loader": "^0.6.5",
|
||||
"jest": "^22.4.2",
|
||||
"jest-runner-eslint": "^0.4.0",
|
||||
"jsdom": "^9.0.0",
|
||||
"json-loader": "^0.5.4",
|
||||
"karma": "^1.3.0",
|
||||
"karma-cli": "^1.0.1",
|
||||
"karma-mocha": "^1.1.1",
|
||||
"karma-phantomjs-launcher": "^1.0.2",
|
||||
"karma-sinon-chai": "^1.2.4",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-verbose-reporter": "^0.0.6",
|
||||
"karma-webpack": "^1.8.0",
|
||||
"mocha": "^2.4.5",
|
||||
"mocha-loader": "^0.7.1",
|
||||
"mustache": "^2.2.1",
|
||||
"json-loader": "^0.5.7",
|
||||
"node-sass": "^4.5.3",
|
||||
"on-build-webpack": "^0.1.0",
|
||||
"postcss-browser-reporter": "^0.4.0",
|
||||
|
@ -82,23 +86,26 @@
|
|||
"postcss-loader": "^0.8.0",
|
||||
"postcss-reporter": "^1.3.1",
|
||||
"precss": "^1.4.0",
|
||||
"prettier": "^1.5.3",
|
||||
"prettier": "1.5.3",
|
||||
"react-addons-test-utils": "^15.0.2",
|
||||
"resolve-url-loader": "^1.6.0",
|
||||
"sass-loader": "^3.2.0",
|
||||
"sinon": "^1.17.4",
|
||||
"sinon-chai": "^2.8.0",
|
||||
"react-test-renderer": "^15.6.1",
|
||||
"resolve-url-loader": "^2.2.1",
|
||||
"sass-loader": "^6.0.6",
|
||||
"style-loader": "^0.13.0",
|
||||
"testem": "^1.2.1",
|
||||
"uglify-js": "^2.6.1",
|
||||
"webpack": "^1.13.0",
|
||||
"webpack-dev-server": "^1.14.1"
|
||||
"thread-loader": "^1.1.5",
|
||||
"ts-jest": "^22.4.1",
|
||||
"ts-loader": "^3.5.0",
|
||||
"tslib": "^1.9.0",
|
||||
"typescript": "^2.7.2",
|
||||
"uglifyjs-webpack-plugin": "^1.2.2",
|
||||
"webpack": "^3.11.0",
|
||||
"webpack-bundle-analyzer": "^2.10.1",
|
||||
"webpack-dev-server": "^2.11.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@skidding/react-codemirror": "^1.0.1",
|
||||
"axios": "^0.13.1",
|
||||
"bignumber.js": "^4.0.2",
|
||||
"bootstrap": "^3.3.7",
|
||||
"calculate-size": "^1.1.1",
|
||||
"classnames": "^2.2.3",
|
||||
"dygraphs": "2.1.0",
|
||||
|
@ -106,30 +113,29 @@
|
|||
"fast.js": "^0.1.1",
|
||||
"fixed-data-table": "^0.6.1",
|
||||
"he": "^1.1.1",
|
||||
"jquery": "^3.1.0",
|
||||
"lodash": "^4.3.0",
|
||||
"moment": "^2.13.0",
|
||||
"nano-date": "^2.0.1",
|
||||
"node-uuid": "^1.4.7",
|
||||
"prop-types": "^15.6.1",
|
||||
"query-string": "^5.0.0",
|
||||
"react": "^15.0.2",
|
||||
"react-addons-shallow-compare": "^15.0.2",
|
||||
"react-codemirror": "^1.0.0",
|
||||
"react-component-resizable": "^1.1.0-rc1",
|
||||
"react-custom-scrollbars": "^4.1.1",
|
||||
"react-dimensions": "^1.2.0",
|
||||
"react-dom": "^15.0.2",
|
||||
"react-grid-layout": "^0.13.9",
|
||||
"react-grid-layout": "^0.16.6",
|
||||
"react-onclickoutside": "^5.2.0",
|
||||
"react-redux": "^4.4.0",
|
||||
"react-resizable": "^1.7.5",
|
||||
"react-router": "^3.0.2",
|
||||
"react-router-redux": "^4.0.8",
|
||||
"react-sparklines": "^1.4.2",
|
||||
"react-tooltip": "^3.2.1",
|
||||
"react-virtualized": "^9.18.5",
|
||||
"redux": "^3.3.1",
|
||||
"redux-auth-wrapper": "^1.0.0",
|
||||
"redux-thunk": "^1.0.3",
|
||||
"rome": "^2.1.22",
|
||||
"updeep": "^0.13.0"
|
||||
"uuid": "^3.2.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
const context = require.context('./', true, /Spec\.js$/)
|
||||
context.keys().forEach(context)
|
||||
module.exports = context
|
|
@ -1,13 +0,0 @@
|
|||
window.then = function(cb, done) {
|
||||
window.setTimeout(function() {
|
||||
cb()
|
||||
if (typeof done === 'function') {
|
||||
done()
|
||||
}
|
||||
}, 0)
|
||||
}
|
||||
|
||||
const chai = require('chai')
|
||||
chai.use(require('sinon-chai'))
|
||||
|
||||
global.expect = chai.expect
|
|
@ -1,42 +1,20 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import SideNav from 'src/side_nav'
|
||||
import Notifications from 'shared/components/Notifications'
|
||||
|
||||
import {publishNotification} from 'shared/actions/notifications'
|
||||
const App = ({children}) =>
|
||||
<div className="chronograf-root">
|
||||
<Notifications />
|
||||
<SideNav />
|
||||
{children}
|
||||
</div>
|
||||
|
||||
const {func, node} = PropTypes
|
||||
const {node} = PropTypes
|
||||
|
||||
const App = React.createClass({
|
||||
propTypes: {
|
||||
children: node.isRequired,
|
||||
notify: func.isRequired,
|
||||
},
|
||||
App.propTypes = {
|
||||
children: node.isRequired,
|
||||
}
|
||||
|
||||
handleAddFlashMessage({type, text}) {
|
||||
const {notify} = this.props
|
||||
|
||||
notify(type, text)
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="chronograf-root">
|
||||
<Notifications />
|
||||
<SideNav />
|
||||
{this.props.children &&
|
||||
React.cloneElement(this.props.children, {
|
||||
addFlashMessage: this.handleAddFlashMessage,
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
notify: bindActionCreators(publishNotification, dispatch),
|
||||
})
|
||||
|
||||
export default connect(null, mapDispatchToProps)(App)
|
||||
export default App
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {withRouter} from 'react-router'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
|
@ -14,9 +15,17 @@ import {showDatabases} from 'shared/apis/metaQuery'
|
|||
|
||||
import {getSourcesAsync} from 'shared/actions/sources'
|
||||
import {errorThrown as errorThrownAction} from 'shared/actions/errors'
|
||||
import {publishNotification} from 'shared/actions/notifications'
|
||||
import {notify as notifyAction} from 'shared/actions/notifications'
|
||||
|
||||
import {DEFAULT_HOME_PAGE} from 'shared/constants'
|
||||
import {
|
||||
NOTIFY_SOURCE_NO_LONGER_AVAILABLE,
|
||||
NOTIFY_NO_SOURCES_AVAILABLE,
|
||||
NOTIFY_UNABLE_TO_RETRIEVE_SOURCES,
|
||||
NOTIFY_USER_REMOVED_FROM_ALL_ORGS,
|
||||
NOTIFY_USER_REMOVED_FROM_CURRENT_ORG,
|
||||
NOTIFY_ORG_HAS_NO_SOURCES,
|
||||
} from 'shared/copy/notifications'
|
||||
|
||||
// Acts as a 'router middleware'. The main `App` component is responsible for
|
||||
// getting the list of data nodes, but not every page requires them to function.
|
||||
|
@ -84,10 +93,7 @@ class CheckSources extends Component {
|
|||
}
|
||||
|
||||
if (!isFetching && isUsingAuth && !organizations.length) {
|
||||
notify(
|
||||
'error',
|
||||
'You have been removed from all organizations. Please contact your administrator.'
|
||||
)
|
||||
notify(NOTIFY_USER_REMOVED_FROM_ALL_ORGS)
|
||||
return router.push('/purgatory')
|
||||
}
|
||||
|
||||
|
@ -95,7 +101,7 @@ class CheckSources extends Component {
|
|||
me.superAdmin &&
|
||||
!organizations.find(o => o.id === currentOrganization.id)
|
||||
) {
|
||||
notify('error', 'You were removed from your current organization')
|
||||
notify(NOTIFY_USER_REMOVED_FROM_CURRENT_ORG)
|
||||
return router.push('/purgatory')
|
||||
}
|
||||
|
||||
|
@ -117,7 +123,7 @@ class CheckSources extends Component {
|
|||
return router.push(`/sources/${sources[0].id}/${restString}`)
|
||||
}
|
||||
// if you're a viewer and there are no sources, go to purgatory.
|
||||
notify('error', 'Organization has no sources configured')
|
||||
notify(NOTIFY_ORG_HAS_NO_SOURCES)
|
||||
return router.push('/purgatory')
|
||||
}
|
||||
|
||||
|
@ -142,18 +148,12 @@ class CheckSources extends Component {
|
|||
try {
|
||||
const newSources = await getSources()
|
||||
if (newSources.length) {
|
||||
errorThrown(
|
||||
error,
|
||||
`Source ${source.name} is no longer available. Successfully connected to another source.`
|
||||
)
|
||||
errorThrown(error, NOTIFY_SOURCE_NO_LONGER_AVAILABLE(source.name))
|
||||
} else {
|
||||
errorThrown(
|
||||
error,
|
||||
`Unable to connect to source ${source.name}. No other sources available.`
|
||||
)
|
||||
errorThrown(error, NOTIFY_NO_SOURCES_AVAILABLE(source.name))
|
||||
}
|
||||
} catch (error2) {
|
||||
errorThrown(error2, 'Unable to retrieve sources')
|
||||
errorThrown(error2, NOTIFY_UNABLE_TO_RETRIEVE_SOURCES)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -247,7 +247,7 @@ const mapStateToProps = ({sources, auth}) => ({
|
|||
const mapDispatchToProps = dispatch => ({
|
||||
getSources: bindActionCreators(getSourcesAsync, dispatch),
|
||||
errorThrown: bindActionCreators(errorThrownAction, dispatch),
|
||||
notify: bindActionCreators(publishNotification, dispatch),
|
||||
notify: bindActionCreators(notifyAction, dispatch),
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import _ from 'lodash'
|
||||
import uuid from 'node-uuid'
|
||||
import uuid from 'uuid'
|
||||
|
||||
import {
|
||||
getUsers as getUsersAJAX,
|
||||
|
@ -16,8 +16,14 @@ import {
|
|||
deleteMapping as deleteMappingAJAX,
|
||||
} from 'src/admin/apis/chronograf'
|
||||
|
||||
import {publishAutoDismissingNotification} from 'shared/dispatchers'
|
||||
import {notify} from 'shared/actions/notifications'
|
||||
import {errorThrown} from 'shared/actions/errors'
|
||||
import {
|
||||
NOTIFY_MAPPING_DELETED,
|
||||
NOTIFY_CHRONOGRAF_ORG_DELETED,
|
||||
NOTIFY_CHRONOGRAF_USER_UPDATED,
|
||||
NOTIFY_CHRONOGRAF_USER_DELETED,
|
||||
} from 'shared/copy/notifications'
|
||||
|
||||
import {REVERT_STATE_DELAY} from 'shared/constants'
|
||||
|
||||
|
@ -177,12 +183,7 @@ export const deleteMappingAsync = mapping => async dispatch => {
|
|||
dispatch(removeMapping(mapping))
|
||||
try {
|
||||
await deleteMappingAJAX(mapping)
|
||||
dispatch(
|
||||
publishAutoDismissingNotification(
|
||||
'success',
|
||||
`Mapping deleted: ${mapping.id} ${mapping.scheme}`
|
||||
)
|
||||
)
|
||||
dispatch(notify(NOTIFY_MAPPING_DELETED(mapping.id, mapping.scheme)))
|
||||
} catch (error) {
|
||||
dispatch(errorThrown(error))
|
||||
dispatch(addMapping(mapping))
|
||||
|
@ -238,7 +239,7 @@ export const updateUserAsync = (
|
|||
provider: null,
|
||||
scheme: null,
|
||||
})
|
||||
dispatch(publishAutoDismissingNotification('success', successMessage))
|
||||
dispatch(notify(NOTIFY_CHRONOGRAF_USER_UPDATED(successMessage)))
|
||||
// it's not necessary to syncUser again but it's useful for good
|
||||
// measure and for the clarity of insight in the redux story
|
||||
dispatch(syncUser(user, data))
|
||||
|
@ -256,12 +257,7 @@ export const deleteUserAsync = (
|
|||
try {
|
||||
await deleteUserAJAX(user)
|
||||
dispatch(
|
||||
publishAutoDismissingNotification(
|
||||
'success',
|
||||
`${user.name} has been removed from ${isAbsoluteDelete
|
||||
? 'all organizations and deleted'
|
||||
: 'the current organization'}`
|
||||
)
|
||||
notify(NOTIFY_CHRONOGRAF_USER_DELETED(user.name, isAbsoluteDelete))
|
||||
)
|
||||
} catch (error) {
|
||||
dispatch(errorThrown(error))
|
||||
|
@ -313,12 +309,7 @@ export const deleteOrganizationAsync = organization => async dispatch => {
|
|||
dispatch(removeOrganization(organization))
|
||||
try {
|
||||
await deleteOrganizationAJAX(organization)
|
||||
dispatch(
|
||||
publishAutoDismissingNotification(
|
||||
'success',
|
||||
`Organization deleted: ${organization.name}`
|
||||
)
|
||||
)
|
||||
dispatch(notify(NOTIFY_CHRONOGRAF_ORG_DELETED(organization.name)))
|
||||
} catch (error) {
|
||||
dispatch(errorThrown(error))
|
||||
dispatch(addOrganization(organization))
|
||||
|
|
|
@ -18,9 +18,40 @@ import {
|
|||
|
||||
import {killQuery as killQueryProxy} from 'shared/apis/metaQuery'
|
||||
|
||||
import {publishAutoDismissingNotification} from 'shared/dispatchers'
|
||||
import {notify} from 'shared/actions/notifications'
|
||||
import {errorThrown} from 'shared/actions/errors'
|
||||
|
||||
import {
|
||||
NOTIFY_DB_USER_CREATED,
|
||||
NOTIFY_DB_USER_CREATION_FAILED,
|
||||
NOTIFY_DB_USER_DELETED,
|
||||
NOTIFY_DB_USER_DELETION_FAILED,
|
||||
NOTIFY_DB_USER_PERMISSIONS_UPDATED,
|
||||
NOTIFY_DB_USER_PERMISSIONS_UPDATE_FAILED,
|
||||
NOTIFY_DB_USER_ROLES_UPDATED,
|
||||
NOTIFY_DB_USER_ROLES_UPDATE_FAILED,
|
||||
NOTIFY_DB_USER_PASSWORD_UPDATED,
|
||||
NOTIFY_DB_USER_PASSWORD_UPDATE_FAILED,
|
||||
NOTIFY_DATABASE_CREATED,
|
||||
NOTIFY_DATABASE_CREATION_FAILED,
|
||||
NOTIFY_DATABASE_DELETED,
|
||||
NOTIFY_DATABASE_DELETION_FAILED,
|
||||
NOTIFY_ROLE_CREATED,
|
||||
NOTIFY_ROLE_CREATION_FAILED,
|
||||
NOTIFY_ROLE_DELETED,
|
||||
NOTIFY_ROLE_DELETION_FAILED,
|
||||
NOTIFY_ROLE_USERS_UPDATED,
|
||||
NOTIFY_ROLE_USERS_UPDATE_FAILED,
|
||||
NOTIFY_ROLE_PERMISSIONS_UPDATED,
|
||||
NOTIFY_ROLE_PERMISSIONS_UPDATE_FAILED,
|
||||
NOTIFY_RETENTION_POLICY_CREATED,
|
||||
NOTIFY_RETENTION_POLICY_CREATION_FAILED,
|
||||
NOTIFY_RETENTION_POLICY_DELETED,
|
||||
NOTIFY_RETENTION_POLICY_DELETION_FAILED,
|
||||
NOTIFY_RETENTION_POLICY_UPDATED,
|
||||
NOTIFY_RETENTION_POLICY_UPDATE_FAILED,
|
||||
} from 'shared/copy/notifications'
|
||||
|
||||
import {REVERT_STATE_DELAY} from 'shared/constants'
|
||||
import _ from 'lodash'
|
||||
|
||||
|
@ -276,12 +307,12 @@ export const loadDBsAndRPsAsync = url => async dispatch => {
|
|||
export const createUserAsync = (url, user) => async dispatch => {
|
||||
try {
|
||||
const {data} = await createUserAJAX(url, user)
|
||||
dispatch(
|
||||
publishAutoDismissingNotification('success', 'User created successfully')
|
||||
)
|
||||
dispatch(notify(NOTIFY_DB_USER_CREATED))
|
||||
dispatch(syncUser(user, data))
|
||||
} catch (error) {
|
||||
dispatch(errorThrown(error, `Failed to create user: ${error.data.message}`))
|
||||
dispatch(
|
||||
errorThrown(error, NOTIFY_DB_USER_CREATION_FAILED(error.data.message))
|
||||
)
|
||||
// undo optimistic update
|
||||
setTimeout(() => dispatch(deleteUser(user)), REVERT_STATE_DELAY)
|
||||
}
|
||||
|
@ -290,12 +321,12 @@ export const createUserAsync = (url, user) => async dispatch => {
|
|||
export const createRoleAsync = (url, role) => async dispatch => {
|
||||
try {
|
||||
const {data} = await createRoleAJAX(url, role)
|
||||
dispatch(
|
||||
publishAutoDismissingNotification('success', 'Role created successfully')
|
||||
)
|
||||
dispatch(notify(NOTIFY_ROLE_CREATED))
|
||||
dispatch(syncRole(role, data))
|
||||
} catch (error) {
|
||||
dispatch(errorThrown(error, `Failed to create role: ${error.data.message}`))
|
||||
dispatch(
|
||||
errorThrown(error, NOTIFY_ROLE_CREATION_FAILED(error.data.message))
|
||||
)
|
||||
// undo optimistic update
|
||||
setTimeout(() => dispatch(deleteRole(role)), REVERT_STATE_DELAY)
|
||||
}
|
||||
|
@ -305,15 +336,10 @@ export const createDatabaseAsync = (url, database) => async dispatch => {
|
|||
try {
|
||||
const {data} = await createDatabaseAJAX(url, database)
|
||||
dispatch(syncDatabase(database, data))
|
||||
dispatch(
|
||||
publishAutoDismissingNotification(
|
||||
'success',
|
||||
'Database created successfully'
|
||||
)
|
||||
)
|
||||
dispatch(notify(NOTIFY_DATABASE_CREATED))
|
||||
} catch (error) {
|
||||
dispatch(
|
||||
errorThrown(error, `Failed to create database: ${error.data.message}`)
|
||||
errorThrown(error, NOTIFY_DATABASE_CREATION_FAILED(error.data.message))
|
||||
)
|
||||
// undo optimistic update
|
||||
setTimeout(() => dispatch(removeDatabase(database)), REVERT_STATE_DELAY)
|
||||
|
@ -329,19 +355,11 @@ export const createRetentionPolicyAsync = (
|
|||
database.links.retentionPolicies,
|
||||
retentionPolicy
|
||||
)
|
||||
dispatch(
|
||||
publishAutoDismissingNotification(
|
||||
'success',
|
||||
'Retention policy created successfully'
|
||||
)
|
||||
)
|
||||
dispatch(notify(NOTIFY_RETENTION_POLICY_CREATED))
|
||||
dispatch(syncRetentionPolicy(database, retentionPolicy, data))
|
||||
} catch (error) {
|
||||
dispatch(
|
||||
errorThrown(
|
||||
error,
|
||||
`Failed to create retention policy: ${error.data.message}`
|
||||
)
|
||||
errorThrown(NOTIFY_RETENTION_POLICY_CREATION_FAILED(error.data.message))
|
||||
)
|
||||
// undo optimistic update
|
||||
setTimeout(
|
||||
|
@ -360,18 +378,13 @@ export const updateRetentionPolicyAsync = (
|
|||
dispatch(editRetentionPolicyRequested(database, oldRP, newRP))
|
||||
const {data} = await updateRetentionPolicyAJAX(oldRP.links.self, newRP)
|
||||
dispatch(editRetentionPolicyCompleted(database, oldRP, data))
|
||||
dispatch(
|
||||
publishAutoDismissingNotification(
|
||||
'success',
|
||||
'Retention policy updated successfully'
|
||||
)
|
||||
)
|
||||
dispatch(notify(NOTIFY_RETENTION_POLICY_UPDATED))
|
||||
} catch (error) {
|
||||
dispatch(editRetentionPolicyFailed(database, oldRP))
|
||||
dispatch(
|
||||
errorThrown(
|
||||
error,
|
||||
`Failed to update retention policy: ${error.data.message}`
|
||||
NOTIFY_RETENTION_POLICY_UPDATE_FAILED(error.data.message)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -394,9 +407,11 @@ export const deleteRoleAsync = role => async dispatch => {
|
|||
dispatch(deleteRole(role))
|
||||
try {
|
||||
await deleteRoleAJAX(role.links.self)
|
||||
dispatch(publishAutoDismissingNotification('success', 'Role deleted'))
|
||||
dispatch(notify(NOTIFY_ROLE_DELETED(role.name)))
|
||||
} catch (error) {
|
||||
dispatch(errorThrown(error, `Failed to delete role: ${error.data.message}`))
|
||||
dispatch(
|
||||
errorThrown(error, NOTIFY_ROLE_DELETION_FAILED(error.data.message))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -404,9 +419,11 @@ export const deleteUserAsync = user => async dispatch => {
|
|||
dispatch(deleteUser(user))
|
||||
try {
|
||||
await deleteUserAJAX(user.links.self)
|
||||
dispatch(publishAutoDismissingNotification('success', 'User deleted'))
|
||||
dispatch(notify(NOTIFY_DB_USER_DELETED(user.name)))
|
||||
} catch (error) {
|
||||
dispatch(errorThrown(error, `Failed to delete user: ${error.data.message}`))
|
||||
dispatch(
|
||||
errorThrown(error, NOTIFY_DB_USER_DELETION_FAILED(error.data.message))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -414,10 +431,10 @@ export const deleteDatabaseAsync = database => async dispatch => {
|
|||
dispatch(removeDatabase(database))
|
||||
try {
|
||||
await deleteDatabaseAJAX(database.links.self)
|
||||
dispatch(publishAutoDismissingNotification('success', 'Database deleted'))
|
||||
dispatch(notify(NOTIFY_DATABASE_DELETED(database.name)))
|
||||
} catch (error) {
|
||||
dispatch(
|
||||
errorThrown(error, `Failed to delete database: ${error.data.message}`)
|
||||
errorThrown(error, NOTIFY_DATABASE_DELETION_FAILED(error.data.message))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -429,17 +446,12 @@ export const deleteRetentionPolicyAsync = (
|
|||
dispatch(removeRetentionPolicy(database, retentionPolicy))
|
||||
try {
|
||||
await deleteRetentionPolicyAJAX(retentionPolicy.links.self)
|
||||
dispatch(
|
||||
publishAutoDismissingNotification(
|
||||
'success',
|
||||
`Retention policy ${retentionPolicy.name} deleted`
|
||||
)
|
||||
)
|
||||
dispatch(notify(NOTIFY_RETENTION_POLICY_DELETED(retentionPolicy.name)))
|
||||
} catch (error) {
|
||||
dispatch(
|
||||
errorThrown(
|
||||
error,
|
||||
`Failed to delete retentionPolicy: ${error.data.message}`
|
||||
NOTIFY_RETENTION_POLICY_DELETION_FAILED(error.data.message)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -452,10 +464,12 @@ export const updateRoleUsersAsync = (role, users) => async dispatch => {
|
|||
users,
|
||||
role.permissions
|
||||
)
|
||||
dispatch(publishAutoDismissingNotification('success', 'Role users updated'))
|
||||
dispatch(notify(NOTIFY_ROLE_USERS_UPDATED))
|
||||
dispatch(syncRole(role, data))
|
||||
} catch (error) {
|
||||
dispatch(errorThrown(error, `Failed to update role: ${error.data.message}`))
|
||||
dispatch(
|
||||
errorThrown(error, NOTIFY_ROLE_USERS_UPDATE_FAILED(error.data.message))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -469,13 +483,14 @@ export const updateRolePermissionsAsync = (
|
|||
role.users,
|
||||
permissions
|
||||
)
|
||||
dispatch(
|
||||
publishAutoDismissingNotification('success', 'Role permissions updated')
|
||||
)
|
||||
dispatch(notify(NOTIFY_ROLE_PERMISSIONS_UPDATED))
|
||||
dispatch(syncRole(role, data))
|
||||
} catch (error) {
|
||||
dispatch(
|
||||
errorThrown(error, `Failed to update role: ${error.data.message}`)
|
||||
errorThrown(
|
||||
error,
|
||||
NOTIFY_ROLE_PERMISSIONS_UPDATE_FAILED(error.data.message)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -486,13 +501,14 @@ export const updateUserPermissionsAsync = (
|
|||
) => async dispatch => {
|
||||
try {
|
||||
const {data} = await updateUserAJAX(user.links.self, {permissions})
|
||||
dispatch(
|
||||
publishAutoDismissingNotification('success', 'User permissions updated')
|
||||
)
|
||||
dispatch(notify(NOTIFY_DB_USER_PERMISSIONS_UPDATED))
|
||||
dispatch(syncUser(user, data))
|
||||
} catch (error) {
|
||||
dispatch(
|
||||
errorThrown(error, `Failed to update user: ${error.data.message}`)
|
||||
errorThrown(
|
||||
error,
|
||||
NOTIFY_DB_USER_PERMISSIONS_UPDATE_FAILED(error.data.message)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -500,11 +516,11 @@ export const updateUserPermissionsAsync = (
|
|||
export const updateUserRolesAsync = (user, roles) => async dispatch => {
|
||||
try {
|
||||
const {data} = await updateUserAJAX(user.links.self, {roles})
|
||||
dispatch(publishAutoDismissingNotification('success', 'User roles updated'))
|
||||
dispatch(notify(NOTIFY_DB_USER_ROLES_UPDATED))
|
||||
dispatch(syncUser(user, data))
|
||||
} catch (error) {
|
||||
dispatch(
|
||||
errorThrown(error, `Failed to update user: ${error.data.message}`)
|
||||
errorThrown(error, NOTIFY_DB_USER_ROLES_UPDATE_FAILED(error.data.message))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -512,13 +528,14 @@ export const updateUserRolesAsync = (user, roles) => async dispatch => {
|
|||
export const updateUserPasswordAsync = (user, password) => async dispatch => {
|
||||
try {
|
||||
const {data} = await updateUserAJAX(user.links.self, {password})
|
||||
dispatch(
|
||||
publishAutoDismissingNotification('success', 'User password updated')
|
||||
)
|
||||
dispatch(notify(NOTIFY_DB_USER_PASSWORD_UPDATED))
|
||||
dispatch(syncUser(user, data))
|
||||
} catch (error) {
|
||||
dispatch(
|
||||
errorThrown(error, `Failed to update user: ${error.data.message}`)
|
||||
errorThrown(
|
||||
error,
|
||||
NOTIFY_DB_USER_PASSWORD_UPDATE_FAILED(error.data.message)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {Tab, Tabs, TabPanel, TabPanels, TabList} from 'shared/components/Tabs'
|
||||
import UsersTable from 'src/admin/components/UsersTable'
|
||||
import RolesTable from 'src/admin/components/RolesTable'
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import OnClickOutside from 'shared/components/OnClickOutside'
|
||||
import ConfirmButtons from 'shared/components/ConfirmButtons'
|
||||
|
@ -9,18 +10,13 @@ class ChangePassRow extends Component {
|
|||
this.state = {
|
||||
showForm: false,
|
||||
}
|
||||
this.showForm = ::this.showForm
|
||||
this.handleCancel = ::this.handleCancel
|
||||
this.handleKeyPress = ::this.handleKeyPress
|
||||
this.handleEdit = ::this.handleEdit
|
||||
this.handleSubmit = ::this.handleSubmit
|
||||
}
|
||||
|
||||
showForm() {
|
||||
showForm = () => {
|
||||
this.setState({showForm: true})
|
||||
}
|
||||
|
||||
handleCancel() {
|
||||
handleCancel = () => {
|
||||
this.setState({showForm: false})
|
||||
}
|
||||
|
||||
|
@ -28,12 +24,12 @@ class ChangePassRow extends Component {
|
|||
this.setState({showForm: false})
|
||||
}
|
||||
|
||||
handleSubmit(user) {
|
||||
handleSubmit = user => {
|
||||
this.props.onApply(user)
|
||||
this.setState({showForm: false})
|
||||
}
|
||||
|
||||
handleKeyPress(user) {
|
||||
handleKeyPress = user => {
|
||||
return e => {
|
||||
if (e.key === 'Enter') {
|
||||
this.handleSubmit(user)
|
||||
|
@ -41,7 +37,7 @@ class ChangePassRow extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
handleEdit(user) {
|
||||
handleEdit = user => {
|
||||
return e => {
|
||||
this.props.onEdit(user, {[e.target.name]: e.target.value})
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import DatabaseTable from 'src/admin/components/DatabaseTable'
|
||||
|
||||
const DatabaseManager = ({
|
||||
databases,
|
||||
notify,
|
||||
isRFDisplayed,
|
||||
isAddDBDisabled,
|
||||
addDatabase,
|
||||
|
@ -25,8 +25,8 @@ const DatabaseManager = ({
|
|||
onDeleteRetentionPolicy,
|
||||
}) => {
|
||||
return (
|
||||
<div className="panel panel-default">
|
||||
<div className="panel-heading u-flex u-ai-center u-jc-space-between">
|
||||
<div className="panel panel-solid">
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">
|
||||
{databases.length === 1
|
||||
? '1 Database'
|
||||
|
@ -45,7 +45,6 @@ const DatabaseManager = ({
|
|||
<DatabaseTable
|
||||
key={db.links.self}
|
||||
database={db}
|
||||
notify={notify}
|
||||
isRFDisplayed={isRFDisplayed}
|
||||
onEditDatabase={onEditDatabase}
|
||||
onKeyDownDatabase={onKeyDownDatabase}
|
||||
|
@ -73,7 +72,6 @@ const {arrayOf, bool, func, shape} = PropTypes
|
|||
|
||||
DatabaseManager.propTypes = {
|
||||
databases: arrayOf(shape()),
|
||||
notify: func,
|
||||
addDatabase: func,
|
||||
isRFDisplayed: bool,
|
||||
isAddDBDisabled: bool,
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
import React, {PropTypes, Component} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
|
||||
import onClickOutside from 'react-onclickoutside'
|
||||
|
||||
import {notify as notifyAction} from 'shared/actions/notifications'
|
||||
|
||||
import {formatRPDuration} from 'utils/formatting'
|
||||
import YesNoButtons from 'shared/components/YesNoButtons'
|
||||
import {DATABASE_TABLE} from 'src/admin/constants/tableSizing'
|
||||
import {NOTIFY_RETENTION_POLICY_CANT_HAVE_EMPTY_FIELDS} from 'shared/copy/notifications'
|
||||
|
||||
class DatabaseRow extends Component {
|
||||
constructor(props) {
|
||||
|
@ -109,7 +116,7 @@ class DatabaseRow extends Component {
|
|||
const replication = isRFDisplayed ? +this.replication.value.trim() : 1
|
||||
|
||||
if (!duration || (isRFDisplayed && !replication)) {
|
||||
notify('error', 'Fields cannot be empty')
|
||||
notify(NOTIFY_RETENTION_POLICY_CANT_HAVE_EMPTY_FIELDS)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -260,8 +267,12 @@ DatabaseRow.propTypes = {
|
|||
onCreate: func,
|
||||
onUpdate: func,
|
||||
onDelete: func,
|
||||
notify: func,
|
||||
notify: func.isRequired,
|
||||
isRFDisplayed: bool,
|
||||
}
|
||||
|
||||
export default onClickOutside(DatabaseRow)
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
notify: bindActionCreators(notifyAction, dispatch),
|
||||
})
|
||||
|
||||
export default connect(null, mapDispatchToProps)(onClickOutside(DatabaseRow))
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import _ from 'lodash'
|
||||
import classnames from 'classnames'
|
||||
|
@ -11,7 +12,6 @@ const {func, shape, bool} = PropTypes
|
|||
|
||||
const DatabaseTable = ({
|
||||
database,
|
||||
notify,
|
||||
isRFDisplayed,
|
||||
onEditDatabase,
|
||||
onKeyDownDatabase,
|
||||
|
@ -35,7 +35,6 @@ const DatabaseTable = ({
|
|||
>
|
||||
<DatabaseTableHeader
|
||||
database={database}
|
||||
notify={notify}
|
||||
onEdit={onEditDatabase}
|
||||
onCancel={onCancelDatabase}
|
||||
onDelete={onDeleteDatabase}
|
||||
|
@ -73,7 +72,6 @@ const DatabaseTable = ({
|
|||
return (
|
||||
<DatabaseRow
|
||||
key={rp.links.self}
|
||||
notify={notify}
|
||||
database={database}
|
||||
retentionPolicy={rp}
|
||||
onCreate={onCreateRetentionPolicy}
|
||||
|
@ -95,7 +93,6 @@ const DatabaseTable = ({
|
|||
DatabaseTable.propTypes = {
|
||||
onEditDatabase: func,
|
||||
database: shape(),
|
||||
notify: func,
|
||||
isRFDisplayed: bool,
|
||||
isAddRPDisabled: bool,
|
||||
onKeyDownDatabase: func,
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
|
||||
import {notify as notifyAction} from 'shared/actions/notifications'
|
||||
import ConfirmButtons from 'shared/components/ConfirmButtons'
|
||||
import {NOTIFY_DATABASE_DELETE_CONFIRMATION_REQUIRED} from 'shared/copy/notifications'
|
||||
|
||||
const DatabaseTableHeader = ({
|
||||
database,
|
||||
|
@ -53,7 +60,7 @@ const Header = ({
|
|||
onDatabaseDeleteConfirm,
|
||||
}) => {
|
||||
const buttons = (
|
||||
<div className="text-right db-manager-header--actions">
|
||||
<div className="db-manager-header--actions text-right">
|
||||
<button
|
||||
className="btn btn-xs btn-primary"
|
||||
disabled={isAddRPDisabled}
|
||||
|
@ -74,7 +81,7 @@ const Header = ({
|
|||
|
||||
const onConfirm = db => {
|
||||
if (database.deleteCode !== `DELETE ${database.name}`) {
|
||||
return notify('error', `Type DELETE ${database.name} to confirm`)
|
||||
return notify(NOTIFY_DATABASE_DELETE_CONFIRMATION_REQUIRED(database.name))
|
||||
}
|
||||
|
||||
onDelete(db)
|
||||
|
@ -134,7 +141,7 @@ const {func, shape, bool} = PropTypes
|
|||
|
||||
DatabaseTableHeader.propTypes = {
|
||||
onEdit: func,
|
||||
notify: func,
|
||||
notify: func.isRequired,
|
||||
database: shape(),
|
||||
onKeyDown: func,
|
||||
onCancel: func,
|
||||
|
@ -148,7 +155,7 @@ DatabaseTableHeader.propTypes = {
|
|||
}
|
||||
|
||||
Header.propTypes = {
|
||||
notify: func,
|
||||
notify: func.isRequired,
|
||||
onConfirm: func,
|
||||
onCancel: func,
|
||||
onDelete: func,
|
||||
|
@ -168,4 +175,8 @@ EditHeader.propTypes = {
|
|||
isRFDisplayed: bool,
|
||||
}
|
||||
|
||||
export default DatabaseTableHeader
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
notify: bindActionCreators(notifyAction, dispatch),
|
||||
})
|
||||
|
||||
export default connect(null, mapDispatchToProps)(DatabaseTableHeader)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
const EmptyRow = ({tableName}) =>
|
||||
<tr className="table-empty-state">
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
class FilterBar extends Component {
|
||||
constructor(props) {
|
||||
|
@ -26,8 +27,8 @@ class FilterBar extends Component {
|
|||
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
|
||||
})
|
||||
return (
|
||||
<div className="panel-heading u-flex u-ai-center u-jc-space-between">
|
||||
<div className="users__search-widget input-group admin__search-widget">
|
||||
<div className="panel-heading">
|
||||
<div className="search-widget" style={{width: '300px'}}>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control input-sm"
|
||||
|
@ -35,9 +36,7 @@ class FilterBar extends Component {
|
|||
value={this.state.filterText}
|
||||
onChange={this.handleText}
|
||||
/>
|
||||
<div className="input-group-addon">
|
||||
<span className="icon search" aria-hidden="true" />
|
||||
</div>
|
||||
<span className="icon search" />
|
||||
</div>
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import QueryRow from 'src/admin/components/QueryRow'
|
||||
import {QUERIES_TABLE} from 'src/admin/constants/tableSizing'
|
||||
|
||||
const QueriesTable = ({queries, onKillQuery}) =>
|
||||
<div>
|
||||
<div className="panel panel-default">
|
||||
<div className="panel panel-solid">
|
||||
<div className="panel-body">
|
||||
<table className="table v-center admin-table table-highlight">
|
||||
<thead>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes, Component} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import ConfirmButtons from 'shared/components/ConfirmButtons'
|
||||
import {QUERIES_TABLE} from 'src/admin/constants/tableSizing'
|
||||
|
@ -7,24 +8,20 @@ class QueryRow extends Component {
|
|||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.handleInitiateKill = ::this.handleInitiateKill
|
||||
this.handleFinishHim = ::this.handleFinishHim
|
||||
this.handleShowMercy = ::this.handleShowMercy
|
||||
|
||||
this.state = {
|
||||
confirmingKill: false,
|
||||
}
|
||||
}
|
||||
|
||||
handleInitiateKill() {
|
||||
handleInitiateKill = () => {
|
||||
this.setState({confirmingKill: true})
|
||||
}
|
||||
|
||||
handleFinishHim() {
|
||||
handleFinishHim = () => {
|
||||
this.props.onKill(this.props.query.id)
|
||||
}
|
||||
|
||||
handleShowMercy() {
|
||||
handleShowMercy = () => {
|
||||
this.setState({confirmingKill: false})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import {ROLES_TABLE} from 'src/admin/constants/tableSizing'
|
||||
|
||||
class RoleEditingRow extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.handleKeyPress = ::this.handleKeyPress
|
||||
this.handleEdit = ::this.handleEdit
|
||||
}
|
||||
|
||||
handleKeyPress(role) {
|
||||
handleKeyPress = role => {
|
||||
return e => {
|
||||
if (e.key === 'Enter') {
|
||||
this.props.onSave(role)
|
||||
|
@ -18,7 +16,7 @@ class RoleEditingRow extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
handleEdit(role) {
|
||||
handleEdit = role => {
|
||||
return e => {
|
||||
this.props.onEdit(role, {[e.target.name]: e.target.value})
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import _ from 'lodash'
|
||||
import classnames from 'classnames'
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import RoleRow from 'src/admin/components/RoleRow'
|
||||
import EmptyRow from 'src/admin/components/EmptyRow'
|
||||
import FilterBar from 'src/admin/components/FilterBar'
|
||||
|
@ -17,7 +18,7 @@ const RolesTable = ({
|
|||
onUpdateRoleUsers,
|
||||
onUpdateRolePermissions,
|
||||
}) =>
|
||||
<div className="panel panel-default">
|
||||
<div className="panel panel-solid">
|
||||
<FilterBar
|
||||
type="roles"
|
||||
onFilter={onFilter}
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import {USERS_TABLE} from 'src/admin/constants/tableSizing'
|
||||
|
||||
class UserEditName extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.handleKeyPress = ::this.handleKeyPress
|
||||
this.handleEdit = ::this.handleEdit
|
||||
}
|
||||
|
||||
handleKeyPress(user) {
|
||||
handleKeyPress = user => {
|
||||
return e => {
|
||||
if (e.key === 'Enter') {
|
||||
this.props.onSave(user)
|
||||
|
@ -18,7 +16,7 @@ class UserEditName extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
handleEdit(user) {
|
||||
handleEdit = user => {
|
||||
return e => {
|
||||
this.props.onEdit(user, {[e.target.name]: e.target.value})
|
||||
}
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import {USERS_TABLE} from 'src/admin/constants/tableSizing'
|
||||
|
||||
class UserNewPassword extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.handleKeyPress = ::this.handleKeyPress
|
||||
this.handleEdit = ::this.handleEdit
|
||||
}
|
||||
|
||||
handleKeyPress(user) {
|
||||
handleKeyPress = user => {
|
||||
return e => {
|
||||
if (e.key === 'Enter') {
|
||||
this.props.onSave(user)
|
||||
|
@ -18,7 +12,7 @@ class UserNewPassword extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
handleEdit(user) {
|
||||
handleEdit = user => {
|
||||
return e => {
|
||||
this.props.onEdit(user, {[e.target.name]: e.target.value})
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import _ from 'lodash'
|
||||
import classnames from 'classnames'
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import UserRow from 'src/admin/components/UserRow'
|
||||
import EmptyRow from 'src/admin/components/EmptyRow'
|
||||
|
@ -20,7 +21,7 @@ const UsersTable = ({
|
|||
onUpdateRoles,
|
||||
onUpdatePassword,
|
||||
}) =>
|
||||
<div className="panel panel-default">
|
||||
<div className="panel panel-solid">
|
||||
<FilterBar
|
||||
type="users"
|
||||
onFilter={onFilter}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import {
|
||||
isUserAuthorized,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import uuid from 'node-uuid'
|
||||
import uuid from 'uuid'
|
||||
|
||||
import AllUsersTableHeader from 'src/admin/components/chronograf/AllUsersTableHeader'
|
||||
import AllUsersTableRowNew from 'src/admin/components/chronograf/AllUsersTableRowNew'
|
||||
|
@ -15,6 +16,11 @@ const {
|
|||
colActions,
|
||||
} = ALL_USERS_TABLE
|
||||
|
||||
import {
|
||||
NOTIFY_CHRONOGRAF_USER_ADDED_TO_ORG,
|
||||
NOTIFY_CHRONOGRAF_USER_REMOVED_FROM_ORG,
|
||||
} from 'shared/copy/notifications'
|
||||
|
||||
class AllUsersTable extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
@ -46,7 +52,7 @@ class AllUsersTable extends Component {
|
|||
this.props.onUpdateUserRoles(
|
||||
user,
|
||||
newRoles,
|
||||
`${user.name} has been added to ${organization.name}`
|
||||
NOTIFY_CHRONOGRAF_USER_ADDED_TO_ORG(user.name, organization.name)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -60,7 +66,7 @@ class AllUsersTable extends Component {
|
|||
this.props.onUpdateUserRoles(
|
||||
user,
|
||||
newRoles,
|
||||
`${user.name} has been removed from ${name}`
|
||||
NOTIFY_CHRONOGRAF_USER_REMOVED_FROM_ORG(user.name, name)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -83,7 +89,6 @@ class AllUsersTable extends Component {
|
|||
onCreateUser,
|
||||
authConfig,
|
||||
meID,
|
||||
notify,
|
||||
onDeleteUser,
|
||||
isLoading,
|
||||
} = this.props
|
||||
|
@ -91,7 +96,7 @@ class AllUsersTable extends Component {
|
|||
const {isCreatingUser} = this.state
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="panel panel-default">
|
||||
<div className="panel panel-solid">
|
||||
<div className="panel-body">
|
||||
<div className="page-spinner" />
|
||||
</div>
|
||||
|
@ -99,7 +104,7 @@ class AllUsersTable extends Component {
|
|||
)
|
||||
}
|
||||
return (
|
||||
<div className="panel panel-default">
|
||||
<div className="panel panel-solid">
|
||||
<AllUsersTableHeader
|
||||
numUsers={users.length}
|
||||
numOrganizations={organizations.length}
|
||||
|
@ -153,7 +158,6 @@ class AllUsersTable extends Component {
|
|||
organizations={organizations}
|
||||
onBlur={this.handleBlurCreateUserRow}
|
||||
onCreateUser={onCreateUser}
|
||||
notify={notify}
|
||||
/>
|
||||
: null}
|
||||
</tbody>
|
||||
|
@ -208,7 +212,6 @@ AllUsersTable.propTypes = {
|
|||
superAdminNewUsers: bool,
|
||||
}),
|
||||
meID: string.isRequired,
|
||||
notify: func.isRequired,
|
||||
isLoading: bool.isRequired,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import SlideToggle from 'shared/components/SlideToggle'
|
||||
|
||||
|
@ -17,7 +18,7 @@ const AllUsersTableHeader = ({
|
|||
: 's'}`
|
||||
|
||||
return (
|
||||
<div className="panel-heading u-flex u-ai-center u-jc-space-between">
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">
|
||||
{numUsersString} across {numOrganizationsString}
|
||||
</h2>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Tags from 'shared/components/Tags'
|
||||
import SlideToggle from 'shared/components/SlideToggle'
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
|
||||
import {notify as notifyAction} from 'shared/actions/notifications'
|
||||
import Dropdown from 'shared/components/Dropdown'
|
||||
|
||||
import {NOTIFY_CHRONOGRAF_USER_MISSING_NAME_AND_PROVIDER} from 'shared/copy/notifications'
|
||||
import {ALL_USERS_TABLE} from 'src/admin/constants/chronografTableSizing'
|
||||
const {
|
||||
colOrganizations,
|
||||
|
@ -79,8 +84,7 @@ class AllUsersTableRowNew extends Component {
|
|||
if (e.key === 'Enter') {
|
||||
if (preventCreate) {
|
||||
return this.props.notify(
|
||||
'warning',
|
||||
'User must have a name and provider'
|
||||
NOTIFY_CHRONOGRAF_USER_MISSING_NAME_AND_PROVIDER
|
||||
)
|
||||
}
|
||||
this.handleConfirmCreateUser()
|
||||
|
@ -180,4 +184,8 @@ AllUsersTableRowNew.propTypes = {
|
|||
notify: func.isRequired,
|
||||
}
|
||||
|
||||
export default AllUsersTableRowNew
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
notify: bindActionCreators(notifyAction, dispatch),
|
||||
})
|
||||
|
||||
export default connect(null, mapDispatchToProps)(AllUsersTableRowNew)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import uuid from 'node-uuid'
|
||||
import uuid from 'uuid'
|
||||
|
||||
import OrganizationsTableRow from 'src/admin/components/chronograf/OrganizationsTableRow'
|
||||
import OrganizationsTableRowNew from 'src/admin/components/chronograf/OrganizationsTableRowNew'
|
||||
|
@ -45,7 +46,7 @@ class OrganizationsTable extends Component {
|
|||
|
||||
if (!organizations.length) {
|
||||
return (
|
||||
<div className="panel panel-default">
|
||||
<div className="panel panel-solid">
|
||||
<div className="panel-body">
|
||||
<div className="page-spinner" />
|
||||
</div>
|
||||
|
@ -53,8 +54,8 @@ class OrganizationsTable extends Component {
|
|||
)
|
||||
}
|
||||
return (
|
||||
<div className="panel panel-default">
|
||||
<div className="panel-heading u-flex u-ai-center u-jc-space-between">
|
||||
<div className="panel panel-solid">
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">
|
||||
{tableTitle}
|
||||
</h2>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
import {withRouter} from 'react-router'
|
||||
|
@ -94,7 +95,7 @@ class OrganizationsTableRow extends Component {
|
|||
<InputClickToEdit
|
||||
value={organization.name}
|
||||
wrapperClass="fancytable--td orgs-table--name"
|
||||
onUpdate={this.handleUpdateOrgName}
|
||||
onBlur={this.handleUpdateOrgName}
|
||||
/>
|
||||
<div className={defaultRoleClassName}>
|
||||
<Dropdown
|
||||
|
@ -111,6 +112,7 @@ class OrganizationsTableRow extends Component {
|
|||
onConfirm={this.handleDeleteOrg}
|
||||
onClickOutside={this.handleDismissDeleteConfirmation}
|
||||
confirmLeft={true}
|
||||
confirmTitle="Delete"
|
||||
/>
|
||||
: <OrganizationsTableRowDeleteButton
|
||||
organization={organization}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import ConfirmButtons from 'shared/components/ConfirmButtons'
|
||||
import Dropdown from 'shared/components/Dropdown'
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import uuid from 'node-uuid'
|
||||
import uuid from 'uuid'
|
||||
import ProvidersTableRow from 'src/admin/components/chronograf/ProvidersTableRow'
|
||||
import ProvidersTableRowNew from 'src/admin/components/chronograf/ProvidersTableRowNew'
|
||||
|
||||
|
@ -43,7 +44,7 @@ class ProvidersTable extends Component {
|
|||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="panel panel-default">
|
||||
<div className="panel panel-solid">
|
||||
<div className="panel-body">
|
||||
<div className="page-spinner" />
|
||||
</div>
|
||||
|
@ -52,8 +53,8 @@ class ProvidersTable extends Component {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="panel panel-default">
|
||||
<div className="panel-heading u-flex u-ai-center u-jc-space-between">
|
||||
<div className="panel panel-solid">
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">
|
||||
{tableTitle}
|
||||
</h2>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import ConfirmButtons from 'shared/components/ConfirmButtons'
|
||||
import Dropdown from 'shared/components/Dropdown'
|
||||
|
@ -80,14 +81,14 @@ class ProvidersTableRow extends Component {
|
|||
<InputClickToEdit
|
||||
value={provider}
|
||||
wrapperClass="fancytable--td provider--provider"
|
||||
onUpdate={this.handleChangeProvider}
|
||||
onBlur={this.handleChangeProvider}
|
||||
disabled={isDefaultMapping}
|
||||
tabIndex={rowIndex}
|
||||
/>
|
||||
<InputClickToEdit
|
||||
value={providerOrganization}
|
||||
wrapperClass="fancytable--td provider--providerorg"
|
||||
onUpdate={this.handleChangeProviderOrg}
|
||||
onBlur={this.handleChangeProviderOrg}
|
||||
disabled={isDefaultMapping}
|
||||
tabIndex={rowIndex}
|
||||
/>
|
||||
|
@ -109,6 +110,7 @@ class ProvidersTableRow extends Component {
|
|||
onCancel={this.handleDismissDeleteConfirmation}
|
||||
onConfirm={this.handleDeleteMap}
|
||||
onClickOutside={this.handleDismissDeleteConfirmation}
|
||||
confirmTitle="Delete"
|
||||
/>
|
||||
: <button
|
||||
className="btn btn-sm btn-default btn-square"
|
||||
|
|
|
@ -1,10 +1,34 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {PureComponent} from 'react'
|
||||
|
||||
import ConfirmButtons from 'shared/components/ConfirmButtons'
|
||||
import Dropdown from 'shared/components/Dropdown'
|
||||
import InputClickToEdit from 'shared/components/InputClickToEdit'
|
||||
import ConfirmButtons from 'src/shared/components/ConfirmButtons'
|
||||
import Dropdown from 'src/shared/components/Dropdown'
|
||||
import InputClickToEdit from 'src/shared/components/InputClickToEdit'
|
||||
|
||||
class ProvidersTableRowNew extends Component {
|
||||
type Organization = {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
|
||||
type Scheme = {
|
||||
text: string
|
||||
}
|
||||
|
||||
interface Props {
|
||||
organizations: Organization[]
|
||||
schemes?: Scheme[]
|
||||
rowIndex?: number
|
||||
onCreate: (state: State) => void
|
||||
onCancel: () => void
|
||||
}
|
||||
|
||||
interface State {
|
||||
scheme: string
|
||||
provider: string
|
||||
providerOrganization: string
|
||||
organizationId: string
|
||||
}
|
||||
|
||||
class ProvidersTableRowNew extends PureComponent<Props, State> {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
|
@ -14,25 +38,31 @@ class ProvidersTableRowNew extends Component {
|
|||
providerOrganization: null,
|
||||
organizationId: 'default',
|
||||
}
|
||||
|
||||
this.handleChooseScheme = this.handleChooseScheme.bind(this)
|
||||
this.handleChangeProvider = this.handleChangeProvider.bind(this)
|
||||
this.handleChangeProviderOrg = this.handleChangeProviderOrg.bind(this)
|
||||
this.handleChooseOrganization = this.handleChooseOrganization.bind(this)
|
||||
this.handleSaveNewMapping = this.handleSaveNewMapping.bind(this)
|
||||
}
|
||||
|
||||
handleChooseScheme = scheme => {
|
||||
handleChooseScheme(scheme: Scheme) {
|
||||
this.setState({scheme: scheme.text})
|
||||
}
|
||||
|
||||
handleChangeProvider = provider => {
|
||||
handleChangeProvider(provider: string) {
|
||||
this.setState({provider})
|
||||
}
|
||||
|
||||
handleChangeProviderOrg = providerOrganization => {
|
||||
handleChangeProviderOrg(providerOrganization: string) {
|
||||
this.setState({providerOrganization})
|
||||
}
|
||||
|
||||
handleChooseOrganization = org => {
|
||||
handleChooseOrganization(org: Organization) {
|
||||
this.setState({organizationId: org.id})
|
||||
}
|
||||
|
||||
handleSaveNewMapping = () => {
|
||||
handleSaveNewMapping() {
|
||||
const {onCreate} = this.props
|
||||
onCreate(this.state)
|
||||
}
|
||||
|
@ -62,14 +92,16 @@ class ProvidersTableRowNew extends Component {
|
|||
<InputClickToEdit
|
||||
value={provider}
|
||||
wrapperClass="fancytable--td provider--provider"
|
||||
onUpdate={this.handleChangeProvider}
|
||||
onChange={this.handleChangeProvider}
|
||||
onBlur={this.handleChangeProvider}
|
||||
tabIndex={rowIndex}
|
||||
placeholder="google"
|
||||
/>
|
||||
<InputClickToEdit
|
||||
value={providerOrganization}
|
||||
wrapperClass="fancytable--td provider--providerorg"
|
||||
onUpdate={this.handleChangeProviderOrg}
|
||||
onChange={this.handleChangeProviderOrg}
|
||||
onBlur={this.handleChangeProviderOrg}
|
||||
tabIndex={rowIndex}
|
||||
placeholder="*"
|
||||
/>
|
||||
|
@ -94,23 +126,4 @@ class ProvidersTableRowNew extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
const {arrayOf, func, number, shape, string} = PropTypes
|
||||
|
||||
ProvidersTableRowNew.propTypes = {
|
||||
organizations: arrayOf(
|
||||
shape({
|
||||
id: string.isRequired,
|
||||
name: string.isRequired,
|
||||
})
|
||||
).isRequired,
|
||||
schemes: arrayOf(
|
||||
shape({
|
||||
text: string.isRequired,
|
||||
})
|
||||
),
|
||||
rowIndex: number,
|
||||
onCreate: func.isRequired,
|
||||
onCancel: func.isRequired,
|
||||
}
|
||||
|
||||
export default ProvidersTableRowNew
|
|
@ -1,6 +1,7 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import uuid from 'node-uuid'
|
||||
import uuid from 'uuid'
|
||||
|
||||
import UsersTableHeader from 'src/admin/components/chronograf/UsersTableHeader'
|
||||
import UsersTableRowNew from 'src/admin/components/chronograf/UsersTableRowNew'
|
||||
|
@ -34,21 +35,14 @@ class UsersTable extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
organization,
|
||||
users,
|
||||
onCreateUser,
|
||||
meID,
|
||||
notify,
|
||||
isLoading,
|
||||
} = this.props
|
||||
const {organization, users, onCreateUser, meID, isLoading} = this.props
|
||||
|
||||
const {isCreatingUser} = this.state
|
||||
const {colRole, colProvider, colScheme, colActions} = USERS_TABLE
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="panel panel-default">
|
||||
<div className="panel panel-solid">
|
||||
<div className="panel-body">
|
||||
<div className="page-spinner" />
|
||||
</div>
|
||||
|
@ -56,7 +50,7 @@ class UsersTable extends Component {
|
|||
)
|
||||
}
|
||||
return (
|
||||
<div className="panel panel-default">
|
||||
<div className="panel panel-solid">
|
||||
<UsersTableHeader
|
||||
numUsers={users.length}
|
||||
onClickCreateUser={this.handleClickCreateUser}
|
||||
|
@ -82,7 +76,6 @@ class UsersTable extends Component {
|
|||
organization={organization}
|
||||
onBlur={this.handleBlurCreateUserRow}
|
||||
onCreateUser={onCreateUser}
|
||||
notify={notify}
|
||||
/>
|
||||
: null}
|
||||
{users.length
|
||||
|
@ -137,7 +130,6 @@ UsersTable.propTypes = {
|
|||
onUpdateUserRole: func.isRequired,
|
||||
onDeleteUser: func.isRequired,
|
||||
meID: string.isRequired,
|
||||
notify: func.isRequired,
|
||||
isLoading: bool.isRequired,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
class UsersTableHeader extends Component {
|
||||
constructor(props) {
|
||||
|
@ -16,7 +17,7 @@ class UsersTableHeader extends Component {
|
|||
const panelTitle = numUsers === 1 ? `${numUsers} User` : `${numUsers} Users`
|
||||
|
||||
return (
|
||||
<div className="panel-heading u-flex u-ai-center u-jc-space-between">
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">
|
||||
{panelTitle} in <em>{organization.name}</em>
|
||||
</h2>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Dropdown from 'shared/components/Dropdown'
|
||||
import DeleteConfirmTableCell from 'shared/components/DeleteConfirmTableCell'
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
|
||||
import {notify as notifyAction} from 'shared/actions/notifications'
|
||||
|
||||
import Dropdown from 'shared/components/Dropdown'
|
||||
|
||||
import {NOTIFY_CHRONOGRAF_USER_MISSING_NAME_AND_PROVIDER} from 'shared/copy/notifications'
|
||||
import {USERS_TABLE} from 'src/admin/constants/chronografTableSizing'
|
||||
import {USER_ROLES} from 'src/admin/constants/chronografAdmin'
|
||||
|
||||
|
@ -60,8 +66,7 @@ class UsersTableRowNew extends Component {
|
|||
if (e.key === 'Enter') {
|
||||
if (preventCreate) {
|
||||
return this.props.notify(
|
||||
'warning',
|
||||
'User must have a name and provider'
|
||||
NOTIFY_CHRONOGRAF_USER_MISSING_NAME_AND_PROVIDER
|
||||
)
|
||||
}
|
||||
this.handleConfirmCreateUser()
|
||||
|
@ -147,4 +152,8 @@ UsersTableRowNew.propTypes = {
|
|||
notify: func.isRequired,
|
||||
}
|
||||
|
||||
export default UsersTableRowNew
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
notify: bindActionCreators(notifyAction, dispatch),
|
||||
})
|
||||
|
||||
export default connect(null, mapDispatchToProps)(UsersTableRowNew)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
import {
|
||||
|
@ -28,7 +29,12 @@ import AdminTabs from 'src/admin/components/AdminTabs'
|
|||
import SourceIndicator from 'shared/components/SourceIndicator'
|
||||
import FancyScrollbar from 'shared/components/FancyScrollbar'
|
||||
|
||||
import {publishAutoDismissingNotification} from 'shared/dispatchers'
|
||||
import {notify as notifyAction} from 'shared/actions/notifications'
|
||||
|
||||
import {
|
||||
NOTIFY_ROLE_NAME_INVALID,
|
||||
NOTIFY_DB_USER_NAME_PASSWORD_INVALID,
|
||||
} from 'shared/copy/notifications'
|
||||
|
||||
const isValidUser = user => {
|
||||
const minLen = 3
|
||||
|
@ -74,7 +80,7 @@ class AdminInfluxDBPage extends Component {
|
|||
handleSaveUser = async user => {
|
||||
const {notify} = this.props
|
||||
if (!isValidUser(user)) {
|
||||
notify('error', 'Username and/or password too short')
|
||||
notify(NOTIFY_DB_USER_NAME_PASSWORD_INVALID)
|
||||
return
|
||||
}
|
||||
if (user.isNew) {
|
||||
|
@ -87,7 +93,7 @@ class AdminInfluxDBPage extends Component {
|
|||
handleSaveRole = async role => {
|
||||
const {notify} = this.props
|
||||
if (!isValidRole(role)) {
|
||||
notify('error', 'Role name too short')
|
||||
notify(NOTIFY_ROLE_NAME_INVALID)
|
||||
return
|
||||
}
|
||||
if (role.isNew) {
|
||||
|
@ -228,7 +234,7 @@ AdminInfluxDBPage.propTypes = {
|
|||
updateUserPermissions: func,
|
||||
updateUserRoles: func,
|
||||
updateUserPassword: func,
|
||||
notify: func,
|
||||
notify: func.isRequired,
|
||||
}
|
||||
|
||||
const mapStateToProps = ({adminInfluxDB: {users, roles, permissions}}) => ({
|
||||
|
@ -264,7 +270,7 @@ const mapDispatchToProps = dispatch => ({
|
|||
),
|
||||
updateUserRoles: bindActionCreators(updateUserRolesAsync, dispatch),
|
||||
updateUserPassword: bindActionCreators(updateUserPasswordAsync, dispatch),
|
||||
notify: bindActionCreators(publishAutoDismissingNotification, dispatch),
|
||||
notify: bindActionCreators(notifyAction, dispatch),
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(AdminInfluxDBPage)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes, Component} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
import _ from 'lodash'
|
||||
|
@ -6,7 +7,13 @@ import _ from 'lodash'
|
|||
import DatabaseManager from 'src/admin/components/DatabaseManager'
|
||||
|
||||
import * as adminActionCreators from 'src/admin/actions/influxdb'
|
||||
import {publishAutoDismissingNotification} from 'shared/dispatchers'
|
||||
import {notify as notifyAction} from 'shared/actions/notifications'
|
||||
|
||||
import {
|
||||
NOTIFY_DATABASE_DELETE_CONFIRMATION_REQUIRED,
|
||||
NOTIFY_DATABASE_NAME_ALREADY_EXISTS,
|
||||
NOTIFY_DATABASE_NAME_INVALID,
|
||||
} from 'shared/copy/notifications'
|
||||
|
||||
class DatabaseManagerPage extends Component {
|
||||
constructor(props) {
|
||||
|
@ -34,11 +41,11 @@ class DatabaseManagerPage extends Component {
|
|||
handleCreateDatabase = database => {
|
||||
const {actions, notify, source, databases} = this.props
|
||||
if (!database.name) {
|
||||
return notify('error', 'Database name cannot be blank')
|
||||
return notify(NOTIFY_DATABASE_NAME_INVALID)
|
||||
}
|
||||
|
||||
if (_.findIndex(databases, {name: database.name}, 1) !== -1) {
|
||||
return notify('error', 'A database by this name already exists')
|
||||
return notify(NOTIFY_DATABASE_NAME_ALREADY_EXISTS)
|
||||
}
|
||||
|
||||
actions.createDatabaseAsync(source.links.databases, database)
|
||||
|
@ -59,11 +66,11 @@ class DatabaseManagerPage extends Component {
|
|||
|
||||
if (key === 'Enter') {
|
||||
if (!database.name) {
|
||||
return notify('error', 'Database name cannot be blank')
|
||||
return notify(NOTIFY_DATABASE_NAME_INVALID)
|
||||
}
|
||||
|
||||
if (_.findIndex(databases, {name: database.name}, 1) !== -1) {
|
||||
return notify('error', 'A database by this name already exists')
|
||||
return notify(NOTIFY_DATABASE_NAME_ALREADY_EXISTS)
|
||||
}
|
||||
|
||||
actions.createDatabaseAsync(source.links.databases, database)
|
||||
|
@ -80,7 +87,9 @@ class DatabaseManagerPage extends Component {
|
|||
|
||||
if (key === 'Enter') {
|
||||
if (database.deleteCode !== `DELETE ${database.name}`) {
|
||||
return notify('error', `Please type DELETE ${database.name} to confirm`)
|
||||
return notify(
|
||||
NOTIFY_DATABASE_DELETE_CONFIRMATION_REQUIRED(database.name)
|
||||
)
|
||||
}
|
||||
|
||||
return actions.deleteDatabaseAsync(database)
|
||||
|
@ -152,7 +161,7 @@ DatabaseManagerPage.propTypes = {
|
|||
removeRetentionPolicy: func,
|
||||
deleteRetentionPolicyAsync: func,
|
||||
}),
|
||||
notify: func,
|
||||
notify: func.isRequired,
|
||||
}
|
||||
|
||||
const mapStateToProps = ({adminInfluxDB: {databases, retentionPolicies}}) => ({
|
||||
|
@ -162,7 +171,7 @@ const mapStateToProps = ({adminInfluxDB: {databases, retentionPolicies}}) => ({
|
|||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
actions: bindActionCreators(adminActionCreators, dispatch),
|
||||
notify: bindActionCreators(publishAutoDismissingNotification, dispatch),
|
||||
notify: bindActionCreators(notifyAction, dispatch),
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(DatabaseManagerPage)
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
|
||||
import * as adminChronografActionCreators from 'src/admin/actions/chronograf'
|
||||
import {publishAutoDismissingNotification} from 'shared/dispatchers'
|
||||
import {notify as notifyAction} from 'shared/actions/notifications'
|
||||
|
||||
import ProvidersTable from 'src/admin/components/chronograf/ProvidersTable'
|
||||
|
||||
|
@ -95,7 +96,7 @@ const mapStateToProps = ({
|
|||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
actions: bindActionCreators(adminChronografActionCreators, dispatch),
|
||||
notify: bindActionCreators(publishAutoDismissingNotification, dispatch),
|
||||
notify: bindActionCreators(notifyAction, dispatch),
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ProvidersPage)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes, Component} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
|
||||
|
@ -11,21 +12,17 @@ import QueriesTable from 'src/admin/components/QueriesTable'
|
|||
import showDatabasesParser from 'shared/parsing/showDatabases'
|
||||
import showQueriesParser from 'shared/parsing/showQueries'
|
||||
import {TIMES} from 'src/admin/constants'
|
||||
import {NOTIFY_QUERIES_ERROR} from 'shared/copy/notifications'
|
||||
|
||||
import {
|
||||
loadQueries as loadQueriesAction,
|
||||
setQueryToKill as setQueryToKillAction,
|
||||
killQueryAsync,
|
||||
} from 'src/admin/actions/influxdb'
|
||||
|
||||
import {publishAutoDismissingNotification} from 'shared/dispatchers'
|
||||
import {notify as notifyAction} from 'shared/actions/notifications'
|
||||
|
||||
class QueriesPage extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.updateQueries = ::this.updateQueries
|
||||
this.handleKillQuery = ::this.handleKillQuery
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateQueries()
|
||||
const updateInterval = 5000
|
||||
|
@ -42,12 +39,12 @@ class QueriesPage extends Component {
|
|||
return <QueriesTable queries={queries} onKillQuery={this.handleKillQuery} />
|
||||
}
|
||||
|
||||
updateQueries() {
|
||||
updateQueries = () => {
|
||||
const {source, notify, loadQueries} = this.props
|
||||
showDatabases(source.links.proxy).then(resp => {
|
||||
const {databases, errors} = showDatabasesParser(resp.data)
|
||||
if (errors.length) {
|
||||
errors.forEach(message => notify('error', message))
|
||||
errors.forEach(message => notify(NOTIFY_QUERIES_ERROR(message)))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -58,7 +55,9 @@ class QueriesPage extends Component {
|
|||
queryResponses.forEach(queryResponse => {
|
||||
const result = showQueriesParser(queryResponse.data)
|
||||
if (result.errors.length) {
|
||||
result.errors.forEach(message => notify('error', message))
|
||||
result.errors.forEach(message =>
|
||||
notify(NOTIFY_QUERIES_ERROR(message))
|
||||
)
|
||||
}
|
||||
|
||||
allQueries.push(...result.queries)
|
||||
|
@ -78,7 +77,7 @@ class QueriesPage extends Component {
|
|||
})
|
||||
}
|
||||
|
||||
handleKillQuery(id) {
|
||||
handleKillQuery = id => {
|
||||
const {source, killQuery} = this.props
|
||||
killQuery(source.links.proxy, id)
|
||||
}
|
||||
|
@ -97,7 +96,7 @@ QueriesPage.propTypes = {
|
|||
queryIDToKill: string,
|
||||
setQueryToKill: func,
|
||||
killQuery: func,
|
||||
notify: func,
|
||||
notify: func.isRequired,
|
||||
}
|
||||
|
||||
const mapStateToProps = ({adminInfluxDB: {queries, queryIDToKill}}) => ({
|
||||
|
@ -109,7 +108,7 @@ const mapDispatchToProps = dispatch => ({
|
|||
loadQueries: bindActionCreators(loadQueriesAction, dispatch),
|
||||
setQueryToKill: bindActionCreators(setQueryToKillAction, dispatch),
|
||||
killQuery: bindActionCreators(killQueryAsync, dispatch),
|
||||
notify: bindActionCreators(publishAutoDismissingNotification, dispatch),
|
||||
notify: bindActionCreators(notifyAction, dispatch),
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(QueriesPage)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
|
||||
import AdminTabs from 'src/admin/components/chronograf/AdminTabs'
|
||||
|
|
|
@ -1,14 +1,44 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {PureComponent} from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
|
||||
import * as adminChronografActionCreators from 'src/admin/actions/chronograf'
|
||||
import * as configActionCreators from 'shared/actions/config'
|
||||
import {publishAutoDismissingNotification} from 'shared/dispatchers'
|
||||
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'
|
||||
|
||||
class AllUsersPage extends Component {
|
||||
interface Props {
|
||||
notify: () => void
|
||||
links: AuthLinks
|
||||
meID: string
|
||||
users: User[]
|
||||
organizations: Organization[]
|
||||
actionsAdmin: {
|
||||
loadUsersAsync: (link: string) => void
|
||||
loadOrganizationsAsync: (link: string) => void
|
||||
createUserAsync: (link: string, user: User) => void
|
||||
updateUserAsync: (user: User, updatedUser: User, message: string) => void
|
||||
deleteUserAsync: (
|
||||
user: User,
|
||||
deleteObj: {isAbsoluteDelete: boolean}
|
||||
) => void
|
||||
}
|
||||
actionsConfig: {
|
||||
getAuthConfigAsync: (link: string) => void
|
||||
updateAuthConfigAsync: () => void
|
||||
}
|
||||
authConfig: {
|
||||
superAdminNewUsers: boolean
|
||||
}
|
||||
}
|
||||
|
||||
interface State {
|
||||
isLoading: boolean
|
||||
}
|
||||
|
||||
export class AllUsersPage extends PureComponent<Props, State> {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
|
@ -22,32 +52,6 @@ class AllUsersPage extends Component {
|
|||
getAuthConfigAsync(links.config.auth)
|
||||
}
|
||||
|
||||
handleCreateUser = user => {
|
||||
const {links, actionsAdmin: {createUserAsync}} = this.props
|
||||
createUserAsync(links.allUsers, user)
|
||||
}
|
||||
|
||||
handleUpdateUserRoles = (user, roles, successMessage) => {
|
||||
const {actionsAdmin: {updateUserAsync}} = this.props
|
||||
const updatedUser = {...user, roles}
|
||||
updateUserAsync(user, updatedUser, successMessage)
|
||||
}
|
||||
|
||||
handleUpdateUserSuperAdmin = (user, superAdmin) => {
|
||||
const {actionsAdmin: {updateUserAsync}} = this.props
|
||||
const updatedUser = {...user, superAdmin}
|
||||
updateUserAsync(
|
||||
user,
|
||||
updatedUser,
|
||||
`${user.name}'s SuperAdmin status has been updated`
|
||||
)
|
||||
}
|
||||
|
||||
handleDeleteUser = user => {
|
||||
const {actionsAdmin: {deleteUserAsync}} = this.props
|
||||
deleteUserAsync(user, {isAbsoluteDelete: true})
|
||||
}
|
||||
|
||||
async componentWillMount() {
|
||||
const {
|
||||
links,
|
||||
|
@ -64,65 +68,66 @@ class AllUsersPage extends Component {
|
|||
this.setState({isLoading: false})
|
||||
}
|
||||
|
||||
handleCreateUser = (user: User) => {
|
||||
const {links, actionsAdmin: {createUserAsync}} = this.props
|
||||
createUserAsync(links.allUsers, user)
|
||||
}
|
||||
|
||||
handleUpdateUserRoles = (
|
||||
user: User,
|
||||
roles: Role[],
|
||||
successMessage: string
|
||||
) => {
|
||||
const {actionsAdmin: {updateUserAsync}} = this.props
|
||||
const updatedUser = {...user, roles}
|
||||
updateUserAsync(user, updatedUser, successMessage)
|
||||
}
|
||||
|
||||
handleUpdateUserSuperAdmin = (user: User, superAdmin: boolean) => {
|
||||
const {actionsAdmin: {updateUserAsync}} = this.props
|
||||
const updatedUser = {...user, superAdmin}
|
||||
updateUserAsync(
|
||||
user,
|
||||
updatedUser,
|
||||
`${user.name}'s SuperAdmin status has been updated`
|
||||
)
|
||||
}
|
||||
|
||||
handleDeleteUser = (user: User) => {
|
||||
const {actionsAdmin: {deleteUserAsync}} = this.props
|
||||
deleteUserAsync(user, {isAbsoluteDelete: true})
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
organizations,
|
||||
meID,
|
||||
users,
|
||||
authConfig,
|
||||
actionsConfig,
|
||||
links,
|
||||
notify,
|
||||
authConfig,
|
||||
actionsConfig,
|
||||
organizations,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<AllUsersTable
|
||||
meID={meID}
|
||||
users={users}
|
||||
links={links}
|
||||
notify={notify}
|
||||
authConfig={authConfig}
|
||||
actionsConfig={actionsConfig}
|
||||
organizations={organizations}
|
||||
isLoading={this.state.isLoading}
|
||||
onDeleteUser={this.handleDeleteUser}
|
||||
onCreateUser={this.handleCreateUser}
|
||||
onUpdateUserRoles={this.handleUpdateUserRoles}
|
||||
onUpdateUserSuperAdmin={this.handleUpdateUserSuperAdmin}
|
||||
onDeleteUser={this.handleDeleteUser}
|
||||
links={links}
|
||||
authConfig={authConfig}
|
||||
actionsConfig={actionsConfig}
|
||||
notify={notify}
|
||||
isLoading={this.state.isLoading}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const {arrayOf, bool, func, shape, string} = PropTypes
|
||||
|
||||
AllUsersPage.propTypes = {
|
||||
links: shape({
|
||||
users: string.isRequired,
|
||||
config: shape({
|
||||
auth: string.isRequired,
|
||||
}).isRequired,
|
||||
}),
|
||||
meID: string.isRequired,
|
||||
users: arrayOf(shape),
|
||||
organizations: arrayOf(shape),
|
||||
actionsAdmin: shape({
|
||||
loadUsersAsync: func.isRequired,
|
||||
loadOrganizationsAsync: func.isRequired,
|
||||
createUserAsync: func.isRequired,
|
||||
updateUserAsync: func.isRequired,
|
||||
deleteUserAsync: func.isRequired,
|
||||
}),
|
||||
actionsConfig: shape({
|
||||
getAuthConfigAsync: func.isRequired,
|
||||
updateAuthConfigAsync: func.isRequired,
|
||||
}),
|
||||
authConfig: shape({
|
||||
superAdminNewUsers: bool,
|
||||
}),
|
||||
notify: func.isRequired,
|
||||
}
|
||||
|
||||
const mapStateToProps = ({
|
||||
links,
|
||||
adminChronograf: {organizations, users},
|
||||
|
@ -137,7 +142,7 @@ const mapStateToProps = ({
|
|||
const mapDispatchToProps = dispatch => ({
|
||||
actionsAdmin: bindActionCreators(adminChronografActionCreators, dispatch),
|
||||
actionsConfig: bindActionCreators(configActionCreators, dispatch),
|
||||
notify: bindActionCreators(publishAutoDismissingNotification, dispatch),
|
||||
notify: bindActionCreators(notifyAction, dispatch),
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(AllUsersPage)
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
|
||||
import * as adminChronografActionCreators from 'src/admin/actions/chronograf'
|
||||
import {publishAutoDismissingNotification} from 'shared/dispatchers'
|
||||
import {notify as notifyAction} from 'shared/actions/notifications'
|
||||
|
||||
import UsersTable from 'src/admin/components/chronograf/UsersTable'
|
||||
|
||||
|
@ -115,7 +116,7 @@ const mapStateToProps = ({links, adminChronograf: {organizations, users}}) => ({
|
|||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
actions: bindActionCreators(adminChronografActionCreators, dispatch),
|
||||
notify: bindActionCreators(publishAutoDismissingNotification, dispatch),
|
||||
notify: bindActionCreators(notifyAction, dispatch),
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(UsersPage)
|
||||
|
|
|
@ -5,7 +5,7 @@ import {
|
|||
NEW_DEFAULT_DATABASE,
|
||||
NEW_EMPTY_RP,
|
||||
} from 'src/admin/constants'
|
||||
import uuid from 'node-uuid'
|
||||
import uuid from 'uuid'
|
||||
|
||||
const initialState = {
|
||||
users: null,
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import _ from 'lodash'
|
||||
import classnames from 'classnames'
|
||||
import {Link} from 'react-router'
|
||||
import uuid from 'node-uuid'
|
||||
import uuid from 'uuid'
|
||||
|
||||
import InfiniteScroll from 'shared/components/InfiniteScroll'
|
||||
|
||||
|
@ -220,8 +221,8 @@ class AlertsTable extends Component {
|
|||
</button>
|
||||
: null}
|
||||
</div>
|
||||
: <div className="panel panel-minimal">
|
||||
<div className="panel-heading u-flex u-ai-center u-jc-space-between">
|
||||
: <div className="panel">
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">
|
||||
{this.props.alerts.length} Alerts
|
||||
</h2>
|
||||
|
@ -243,9 +244,6 @@ class SearchBar extends Component {
|
|||
this.state = {
|
||||
searchTerm: '',
|
||||
}
|
||||
|
||||
this.handleSearch = ::this.handleSearch
|
||||
this.handleChange = ::this.handleChange
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
|
@ -253,27 +251,25 @@ class SearchBar extends Component {
|
|||
this.handleSearch = _.debounce(this.handleSearch, waitPeriod)
|
||||
}
|
||||
|
||||
handleSearch() {
|
||||
handleSearch = () => {
|
||||
this.props.onSearch(this.state.searchTerm)
|
||||
}
|
||||
|
||||
handleChange(e) {
|
||||
handleChange = e => {
|
||||
this.setState({searchTerm: e.target.value}, this.handleSearch)
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="users__search-widget input-group">
|
||||
<div className="search-widget" style={{width: '260px'}}>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
className="form-control input-sm"
|
||||
placeholder="Filter Alerts..."
|
||||
onChange={this.handleChange}
|
||||
value={this.state.searchTerm}
|
||||
/>
|
||||
<div className="input-group-addon">
|
||||
<span className="icon search" />
|
||||
</div>
|
||||
<span className="icon search" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes, Component} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import SourceIndicator from 'shared/components/SourceIndicator'
|
||||
import AlertsTable from 'src/alerts/components/AlertsTable'
|
||||
|
@ -11,7 +12,7 @@ import AJAX from 'utils/ajax'
|
|||
import _ from 'lodash'
|
||||
import moment from 'moment'
|
||||
|
||||
import timeRanges from 'hson!shared/data/timeRanges.hson'
|
||||
import {timeRanges} from 'shared/data/timeRanges'
|
||||
|
||||
class AlertsApp extends Component {
|
||||
constructor(props) {
|
||||
|
@ -35,11 +36,6 @@ class AlertsApp extends Component {
|
|||
limitMultiplier: 1, // only used if AlertsApp receives a limit prop
|
||||
isAlertsMaxedOut: false, // only used if AlertsApp receives a limit prop
|
||||
}
|
||||
|
||||
this.fetchAlerts = ::this.fetchAlerts
|
||||
this.renderSubComponents = ::this.renderSubComponents
|
||||
this.handleGetMoreAlerts = ::this.handleGetMoreAlerts
|
||||
this.handleApplyTime = ::this.handleApplyTime
|
||||
}
|
||||
|
||||
// TODO: show a loading screen until we figure out if there is a kapacitor and fetch the alerts
|
||||
|
@ -65,7 +61,7 @@ class AlertsApp extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
fetchAlerts() {
|
||||
fetchAlerts = () => {
|
||||
getAlerts(
|
||||
this.props.source.links.proxy,
|
||||
this.state.timeRange,
|
||||
|
@ -112,13 +108,13 @@ class AlertsApp extends Component {
|
|||
})
|
||||
}
|
||||
|
||||
handleGetMoreAlerts() {
|
||||
handleGetMoreAlerts = () => {
|
||||
this.setState({limitMultiplier: this.state.limitMultiplier + 1}, () => {
|
||||
this.fetchAlerts(this.state.limitMultiplier)
|
||||
})
|
||||
}
|
||||
|
||||
renderSubComponents() {
|
||||
renderSubComponents = () => {
|
||||
const {source, isWidget, limit} = this.props
|
||||
const {isAlertsMaxedOut, alerts} = this.state
|
||||
|
||||
|
@ -135,7 +131,7 @@ class AlertsApp extends Component {
|
|||
: <NoKapacitorError source={source} />
|
||||
}
|
||||
|
||||
handleApplyTime(timeRange) {
|
||||
handleApplyTime = timeRange => {
|
||||
this.setState({timeRange})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
import {withRouter} from 'react-router'
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* global VERSION */
|
||||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Notifications from 'shared/components/Notifications'
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes, Component} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
import {withRouter} from 'react-router'
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import {isUserAuthorized, VIEWER_ROLE} from 'src/auth/Authorized'
|
||||
|
||||
|
|
|
@ -23,17 +23,17 @@ export const renameCell = cellName => ({
|
|||
},
|
||||
})
|
||||
|
||||
export const updateSingleStatColors = singleStatColors => ({
|
||||
type: 'UPDATE_SINGLE_STAT_COLORS',
|
||||
export const updateThresholdsListColors = thresholdsListColors => ({
|
||||
type: 'UPDATE_THRESHOLDS_LIST_COLORS',
|
||||
payload: {
|
||||
singleStatColors,
|
||||
thresholdsListColors,
|
||||
},
|
||||
})
|
||||
|
||||
export const updateSingleStatType = singleStatType => ({
|
||||
type: 'UPDATE_SINGLE_STAT_TYPE',
|
||||
export const updateThresholdsListType = thresholdsListType => ({
|
||||
type: 'UPDATE_THRESHOLDS_LIST_TYPE',
|
||||
payload: {
|
||||
singleStatType,
|
||||
thresholdsListType,
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -50,3 +50,10 @@ export const updateAxes = axes => ({
|
|||
axes,
|
||||
},
|
||||
})
|
||||
|
||||
export const updateTableOptions = tableOptions => ({
|
||||
type: 'UPDATE_TABLE_OPTIONS',
|
||||
payload: {
|
||||
tableOptions,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -8,10 +8,14 @@ import {
|
|||
runTemplateVariableQuery,
|
||||
} from 'src/dashboards/apis'
|
||||
|
||||
import {publishAutoDismissingNotification} from 'shared/dispatchers'
|
||||
import {notify} from 'shared/actions/notifications'
|
||||
import {errorThrown} from 'shared/actions/errors'
|
||||
|
||||
import {NEW_DEFAULT_DASHBOARD_CELL} from 'src/dashboards/constants'
|
||||
import {
|
||||
NOTIFY_DASHBOARD_DELETED,
|
||||
NOTIFY_DASHBOARD_DELETE_FAILED,
|
||||
} from 'shared/copy/notifications'
|
||||
|
||||
import {
|
||||
TEMPLATE_VARIABLE_SELECTED,
|
||||
|
@ -257,15 +261,13 @@ export const deleteDashboardAsync = dashboard => async dispatch => {
|
|||
dispatch(deleteDashboard(dashboard))
|
||||
try {
|
||||
await deleteDashboardAJAX(dashboard)
|
||||
dispatch(
|
||||
publishAutoDismissingNotification(
|
||||
'success',
|
||||
'Dashboard deleted successfully.'
|
||||
)
|
||||
)
|
||||
dispatch(notify(NOTIFY_DASHBOARD_DELETED(dashboard.name)))
|
||||
} catch (error) {
|
||||
dispatch(
|
||||
errorThrown(error, `Failed to delete dashboard: ${error.data.message}.`)
|
||||
errorThrown(
|
||||
error,
|
||||
NOTIFY_DASHBOARD_DELETE_FAILED(dashboard.name, error.data.message)
|
||||
)
|
||||
)
|
||||
dispatch(deleteDashboardFailed(dashboard))
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
|
||||
|
@ -7,12 +8,15 @@ import Input from 'src/dashboards/components/DisplayOptionsInput'
|
|||
import {Tabber, Tab} from 'src/dashboards/components/Tabber'
|
||||
import FancyScrollbar from 'shared/components/FancyScrollbar'
|
||||
|
||||
import {DISPLAY_OPTIONS, TOOLTIP_CONTENT} from 'src/dashboards/constants'
|
||||
import {
|
||||
AXES_SCALE_OPTIONS,
|
||||
TOOLTIP_Y_VALUE_FORMAT,
|
||||
} from 'src/dashboards/constants/cellEditor'
|
||||
import {GRAPH_TYPES} from 'src/dashboards/graphics/graph'
|
||||
|
||||
import {updateAxes} from 'src/dashboards/actions/cellEditorOverlay'
|
||||
|
||||
const {LINEAR, LOG, BASE_2, BASE_10} = DISPLAY_OPTIONS
|
||||
const {LINEAR, LOG, BASE_2, BASE_10} = AXES_SCALE_OPTIONS
|
||||
const getInputMin = scale => (scale === LOG ? '0' : null)
|
||||
|
||||
class AxesOptions extends Component {
|
||||
|
@ -90,7 +94,7 @@ class AxesOptions extends Component {
|
|||
<h5 className="display-options--header">
|
||||
{menuOption} Controls
|
||||
</h5>
|
||||
<form autoComplete="off" style={{margin: '0 -6px'}}>
|
||||
<form autoComplete="off" className="form-group-wrapper">
|
||||
<div className="form-group col-sm-12">
|
||||
<label htmlFor="prefix">Title</label>
|
||||
<OptIn
|
||||
|
@ -139,7 +143,7 @@ class AxesOptions extends Component {
|
|||
<Tabber
|
||||
labelText="Y-Value's Format"
|
||||
tipID="Y-Values's Format"
|
||||
tipContent={TOOLTIP_CONTENT.FORMAT}
|
||||
tipContent={TOOLTIP_Y_VALUE_FORMAT}
|
||||
>
|
||||
<Tab
|
||||
text="K/M/B"
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import _ from 'lodash'
|
||||
import uuid from 'node-uuid'
|
||||
import uuid from 'uuid'
|
||||
|
||||
import ResizeContainer from 'shared/components/ResizeContainer'
|
||||
import ResizeContainer from 'src/shared/components/ResizeContainer'
|
||||
import QueryMaker from 'src/dashboards/components/QueryMaker'
|
||||
import Visualization from 'src/dashboards/components/Visualization'
|
||||
import OverlayControls from 'src/dashboards/components/OverlayControls'
|
||||
|
@ -20,10 +21,10 @@ import {
|
|||
removeUnselectedTemplateValues,
|
||||
TYPE_QUERY_CONFIG,
|
||||
} from 'src/dashboards/constants'
|
||||
import {OVERLAY_TECHNOLOGY} from 'shared/constants/classNames'
|
||||
import {OVERLAY_TECHNOLOGY} from 'src/shared/constants/classNames'
|
||||
import {MINIMUM_HEIGHTS, INITIAL_HEIGHTS} from 'src/data_explorer/constants'
|
||||
import {AUTO_GROUP_BY} from 'shared/constants'
|
||||
import {stringifyColorValues} from 'src/dashboards/constants/gaugeColors'
|
||||
import {AUTO_GROUP_BY} from 'src/shared/constants'
|
||||
import {stringifyColorValues} from 'src/shared/constants/colorOperations'
|
||||
|
||||
class CellEditorOverlay extends Component {
|
||||
constructor(props) {
|
||||
|
@ -105,7 +106,7 @@ class CellEditorOverlay extends Component {
|
|||
|
||||
handleSaveCell = () => {
|
||||
const {queriesWorkingDraft, staticLegend} = this.state
|
||||
const {cell, singleStatColors, gaugeColors} = this.props
|
||||
const {cell, thresholdsListColors, gaugeColors} = this.props
|
||||
|
||||
const queries = queriesWorkingDraft.map(q => {
|
||||
const timeRange = q.range || {upper: null, lower: ':dashboardTime:'}
|
||||
|
@ -119,13 +120,18 @@ class CellEditorOverlay extends Component {
|
|||
})
|
||||
|
||||
let colors = []
|
||||
if (cell.type === 'gauge') {
|
||||
colors = stringifyColorValues(gaugeColors)
|
||||
} else if (
|
||||
cell.type === 'single-stat' ||
|
||||
cell.type === 'line-plus-single-stat'
|
||||
) {
|
||||
colors = stringifyColorValues(singleStatColors)
|
||||
|
||||
switch (cell.type) {
|
||||
case 'gauge': {
|
||||
colors = stringifyColorValues(gaugeColors)
|
||||
break
|
||||
}
|
||||
case 'single-stat':
|
||||
case 'line-plus-single-stat':
|
||||
case 'table': {
|
||||
colors = stringifyColorValues(thresholdsListColors)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
this.props.onSave({
|
||||
|
@ -374,8 +380,8 @@ CellEditorOverlay.propTypes = {
|
|||
}).isRequired,
|
||||
dashboardID: string.isRequired,
|
||||
sources: arrayOf(shape()),
|
||||
singleStatType: string.isRequired,
|
||||
singleStatColors: arrayOf(shape({}).isRequired).isRequired,
|
||||
thresholdsListType: string.isRequired,
|
||||
thresholdsListColors: arrayOf(shape({}).isRequired).isRequired,
|
||||
gaugeColors: arrayOf(shape({}).isRequired).isRequired,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
|
||||
import TemplateControlBar from 'src/dashboards/components/TemplateControlBar'
|
||||
|
@ -15,7 +16,6 @@ const Dashboard = ({
|
|||
autoRefresh,
|
||||
manualRefresh,
|
||||
onDeleteCell,
|
||||
synchronizer,
|
||||
onPositionChange,
|
||||
inPresentationMode,
|
||||
onOpenTemplateManager,
|
||||
|
@ -25,6 +25,8 @@ const Dashboard = ({
|
|||
showTemplateControlBar,
|
||||
setScrollTop,
|
||||
inView,
|
||||
onSetHoverTime,
|
||||
hoverTime,
|
||||
}) => {
|
||||
const cells = dashboard.cells.map(cell => {
|
||||
const dashboardCell = {
|
||||
|
@ -65,7 +67,8 @@ const Dashboard = ({
|
|||
timeRange={timeRange}
|
||||
autoRefresh={autoRefresh}
|
||||
manualRefresh={manualRefresh}
|
||||
synchronizer={synchronizer}
|
||||
hoverTime={hoverTime}
|
||||
onSetHoverTime={onSetHoverTime}
|
||||
onDeleteCell={onDeleteCell}
|
||||
onPositionChange={onPositionChange}
|
||||
templates={templatesIncludingDashTime}
|
||||
|
@ -111,7 +114,8 @@ Dashboard.propTypes = {
|
|||
onPositionChange: func,
|
||||
onDeleteCell: func,
|
||||
onSummonOverlayTechnologies: func,
|
||||
synchronizer: func,
|
||||
hoverTime: string,
|
||||
onSetHoverTime: func,
|
||||
source: shape({
|
||||
links: shape({
|
||||
proxy: string,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
|
||||
import Authorized, {EDITOR_ROLE} from 'src/auth/Authorized'
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes, Component} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {
|
||||
DASHBOARD_NAME_MAX_LENGTH,
|
||||
NEW_DASHBOARD,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {Link} from 'react-router'
|
||||
import _ from 'lodash'
|
||||
import classnames from 'classnames'
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes, Component} from 'react'
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Authorized, {EDITOR_ROLE} from 'src/auth/Authorized'
|
||||
|
||||
|
@ -45,12 +46,12 @@ class DashboardsPageContents extends Component {
|
|||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<div className="panel panel-minimal">
|
||||
<div className="panel-heading u-flex u-ai-center u-jc-space-between">
|
||||
<div className="panel">
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">
|
||||
{tableHeader}
|
||||
</h2>
|
||||
<div className="u-flex u-ai-center dashboards-page--actions">
|
||||
<div className="dashboards-page--actions">
|
||||
<SearchBar
|
||||
placeholder="Filter by Name..."
|
||||
onSearch={this.filterDashboards}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {Link} from 'react-router'
|
||||
import _ from 'lodash'
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue