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