Merge branch 'master' into feature/status_page-1556
commit
f7bc85f708
|
@ -179,7 +179,7 @@
|
|||
'one-var': 0,
|
||||
'operator-assignment': [2, 'always'],
|
||||
'padded-blocks': [2, 'never'],
|
||||
'quote-props': [2, 'as-needed', {keywords: true, numbers: false }],
|
||||
'quote-props': [2, 'as-needed', {keywords: false, numbers: false }],
|
||||
'require-jsdoc': 0,
|
||||
'semi-spacing': [2, {before: false, after: true}],
|
||||
'semi': [2, 'never'],
|
||||
|
@ -234,6 +234,5 @@
|
|||
'react/require-extension': 0,
|
||||
'react/self-closing-comp': 0, // TODO: we can re-enable this if some brave soul wants to update the code (mostly spans acting as icons)
|
||||
'react/sort-comp': 0, // TODO: 2
|
||||
'react/jsx-wrap-multilines': ['error', {'declaration': false, 'assignment': false}],
|
||||
},
|
||||
}
|
||||
|
|
|
@ -144,11 +144,7 @@ describe('Admin.Reducers', () => {
|
|||
|
||||
it('can add a database', () => {
|
||||
const actual = reducer(state, addDatabase())
|
||||
const expected = [
|
||||
{...NEW_DEFAULT_DATABASE, isEditing: true},
|
||||
db1,
|
||||
db2,
|
||||
]
|
||||
const expected = [{...NEW_DEFAULT_DATABASE, isEditing: true}, db1, db2]
|
||||
|
||||
expect(actual.databases).to.deep.equal(expected)
|
||||
})
|
||||
|
@ -170,10 +166,7 @@ describe('Admin.Reducers', () => {
|
|||
|
||||
it('can add a database delete code', () => {
|
||||
const actual = reducer(state, addDatabaseDeleteCode(db1))
|
||||
const expected = [
|
||||
{...db1, deleteCode: ''},
|
||||
db2,
|
||||
]
|
||||
const expected = [{...db1, deleteCode: ''}, db2]
|
||||
|
||||
expect(actual.databases).to.deep.equal(expected)
|
||||
})
|
||||
|
@ -181,10 +174,7 @@ describe('Admin.Reducers', () => {
|
|||
it('can remove the delete code', () => {
|
||||
const actual = reducer(state, removeDatabaseDeleteCode(db2))
|
||||
delete db2.deleteCode
|
||||
const expected = [
|
||||
db1,
|
||||
db2,
|
||||
]
|
||||
const expected = [db1, db2]
|
||||
|
||||
expect(actual.databases).to.deep.equal(expected)
|
||||
})
|
||||
|
@ -195,18 +185,14 @@ describe('Admin.Reducers', () => {
|
|||
|
||||
it('can add a retention policy', () => {
|
||||
const actual = reducer(state, addRetentionPolicy(db1))
|
||||
const expected = [
|
||||
{...db1, retentionPolicies: [NEW_EMPTY_RP, rp1]},
|
||||
]
|
||||
const expected = [{...db1, retentionPolicies: [NEW_EMPTY_RP, rp1]}]
|
||||
|
||||
expect(actual.databases).to.deep.equal(expected)
|
||||
})
|
||||
|
||||
it('can remove a retention policy', () => {
|
||||
const actual = reducer(state, removeRetentionPolicy(db1, rp1))
|
||||
const expected = [
|
||||
{...db1, retentionPolicies: []},
|
||||
]
|
||||
const expected = [{...db1, retentionPolicies: []}]
|
||||
|
||||
expect(actual.databases).to.deep.equal(expected)
|
||||
})
|
||||
|
@ -214,9 +200,7 @@ describe('Admin.Reducers', () => {
|
|||
it('can edit a retention policy', () => {
|
||||
const updates = {name: 'rpOne', duration: '100y', replication: '42'}
|
||||
const actual = reducer(state, editRetentionPolicy(db1, rp1, updates))
|
||||
const expected = [
|
||||
{...db1, retentionPolicies: [{...rp1, ...updates}]},
|
||||
]
|
||||
const expected = [{...db1, retentionPolicies: [{...rp1, ...updates}]}]
|
||||
|
||||
expect(actual.databases).to.deep.equal(expected)
|
||||
})
|
||||
|
@ -224,17 +208,12 @@ describe('Admin.Reducers', () => {
|
|||
|
||||
it('it can add a user', () => {
|
||||
state = {
|
||||
users: [
|
||||
u1,
|
||||
],
|
||||
users: [u1],
|
||||
}
|
||||
|
||||
const actual = reducer(state, addUser())
|
||||
const expected = {
|
||||
users: [
|
||||
{...NEW_DEFAULT_USER, isEditing: true},
|
||||
u1,
|
||||
],
|
||||
users: [{...NEW_DEFAULT_USER, isEditing: true}, u1],
|
||||
}
|
||||
|
||||
expect(actual.users).to.deep.equal(expected.users)
|
||||
|
@ -268,17 +247,12 @@ describe('Admin.Reducers', () => {
|
|||
|
||||
it('it can add a role', () => {
|
||||
state = {
|
||||
roles: [
|
||||
r1,
|
||||
],
|
||||
roles: [r1],
|
||||
}
|
||||
|
||||
const actual = reducer(state, addRole())
|
||||
const expected = {
|
||||
roles: [
|
||||
{...NEW_DEFAULT_ROLE, isEditing: true},
|
||||
r1,
|
||||
],
|
||||
roles: [{...NEW_DEFAULT_ROLE, isEditing: true}, r1],
|
||||
}
|
||||
|
||||
expect(actual.roles).to.deep.equal(expected.roles)
|
||||
|
@ -321,9 +295,7 @@ describe('Admin.Reducers', () => {
|
|||
|
||||
it('it can delete a role', () => {
|
||||
state = {
|
||||
roles: [
|
||||
r1,
|
||||
],
|
||||
roles: [r1],
|
||||
}
|
||||
|
||||
const actual = reducer(state, deleteRole(r1))
|
||||
|
@ -336,9 +308,7 @@ describe('Admin.Reducers', () => {
|
|||
|
||||
it('it can delete a user', () => {
|
||||
state = {
|
||||
users: [
|
||||
u1,
|
||||
],
|
||||
users: [u1],
|
||||
}
|
||||
|
||||
const actual = reducer(state, deleteUser(u1))
|
||||
|
@ -358,10 +328,7 @@ describe('Admin.Reducers', () => {
|
|||
|
||||
const actual = reducer(state, filterRoles(text))
|
||||
const expected = {
|
||||
roles: [
|
||||
{...r1, hidden: false},
|
||||
{...r2, hidden: true},
|
||||
],
|
||||
roles: [{...r1, hidden: false}, {...r2, hidden: true}],
|
||||
}
|
||||
|
||||
expect(actual.roles).to.deep.equal(expected.roles)
|
||||
|
@ -376,10 +343,7 @@ describe('Admin.Reducers', () => {
|
|||
|
||||
const actual = reducer(state, filterUsers(text))
|
||||
const expected = {
|
||||
users: [
|
||||
{...u1, hidden: true},
|
||||
{...u2, hidden: false},
|
||||
],
|
||||
users: [{...u1, hidden: true}, {...u2, hidden: false}],
|
||||
}
|
||||
|
||||
expect(actual.users).to.deep.equal(expected.users)
|
||||
|
|
|
@ -10,61 +10,103 @@ describe('buildInfluxQLQuery', () => {
|
|||
describe('when information is missing', () => {
|
||||
it('returns a null select statement', () => {
|
||||
expect(buildInfluxQLQuery({}, mergeConfig())).to.equal(null)
|
||||
expect(buildInfluxQLQuery({}, mergeConfig({database: 'db1'}))).to.equal(null) // no measurement
|
||||
expect(buildInfluxQLQuery({}, mergeConfig({database: 'db1', measurement: 'm1'}))).to.equal(null) // no fields
|
||||
expect(buildInfluxQLQuery({}, mergeConfig({database: 'db1'}))).to.equal(
|
||||
null
|
||||
) // no measurement
|
||||
expect(
|
||||
buildInfluxQLQuery(
|
||||
{},
|
||||
mergeConfig({database: 'db1', measurement: 'm1'})
|
||||
)
|
||||
).to.equal(null) // no fields
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a database, measurement, field, and NO retention policy', () => {
|
||||
beforeEach(() => {
|
||||
config = mergeConfig({database: 'db1', measurement: 'm1', fields: [{field: 'f1', func: null}]})
|
||||
config = mergeConfig({
|
||||
database: 'db1',
|
||||
measurement: 'm1',
|
||||
fields: [{field: 'f1', func: null}],
|
||||
})
|
||||
})
|
||||
|
||||
it('builds the right query', () => {
|
||||
expect(buildInfluxQLQuery({}, config)).to.equal('SELECT "f1" FROM "db1".."m1"')
|
||||
expect(buildInfluxQLQuery({}, config)).to.equal(
|
||||
'SELECT "f1" FROM "db1".."m1"'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a database, measurement, retention policy, and field', () => {
|
||||
beforeEach(() => {
|
||||
config = mergeConfig({database: 'db1', measurement: 'm1', retentionPolicy: 'rp1', fields: [{field: 'f1', func: null}]})
|
||||
config = mergeConfig({
|
||||
database: 'db1',
|
||||
measurement: 'm1',
|
||||
retentionPolicy: 'rp1',
|
||||
fields: [{field: 'f1', func: null}],
|
||||
})
|
||||
timeBounds = {lower: 'now() - 1hr'}
|
||||
})
|
||||
|
||||
it('builds the right query', () => {
|
||||
expect(buildInfluxQLQuery({}, config)).to.equal('SELECT "f1" FROM "db1"."rp1"."m1"')
|
||||
expect(buildInfluxQLQuery({}, config)).to.equal(
|
||||
'SELECT "f1" FROM "db1"."rp1"."m1"'
|
||||
)
|
||||
})
|
||||
|
||||
it('builds the right query with a time range', () => {
|
||||
expect(buildInfluxQLQuery(timeBounds, config)).to.equal('SELECT "f1" FROM "db1"."rp1"."m1" WHERE time > now() - 1hr')
|
||||
expect(buildInfluxQLQuery(timeBounds, config)).to.equal(
|
||||
'SELECT "f1" FROM "db1"."rp1"."m1" WHERE time > now() - 1hr'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the field is *', () => {
|
||||
beforeEach(() => {
|
||||
config = mergeConfig({database: 'db1', measurement: 'm1', retentionPolicy: 'rp1', fields: [{field: '*', func: null}]})
|
||||
config = mergeConfig({
|
||||
database: 'db1',
|
||||
measurement: 'm1',
|
||||
retentionPolicy: 'rp1',
|
||||
fields: [{field: '*', func: null}],
|
||||
})
|
||||
})
|
||||
|
||||
it('does not quote the star', () => {
|
||||
expect(buildInfluxQLQuery({}, config)).to.equal('SELECT * FROM "db1"."rp1"."m1"')
|
||||
expect(buildInfluxQLQuery({}, config)).to.equal(
|
||||
'SELECT * FROM "db1"."rp1"."m1"'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a measurement and one field, an aggregate, and a GROUP BY time()', () => {
|
||||
beforeEach(() => {
|
||||
config = mergeConfig({database: 'db1', measurement: 'm0', retentionPolicy: 'rp1', fields: [{field: 'value', funcs: ['min']}], groupBy: {time: '10m', tags: []}})
|
||||
config = mergeConfig({
|
||||
database: 'db1',
|
||||
measurement: 'm0',
|
||||
retentionPolicy: 'rp1',
|
||||
fields: [{field: 'value', funcs: ['min']}],
|
||||
groupBy: {time: '10m', tags: []},
|
||||
})
|
||||
timeBounds = {lower: 'now() - 12h'}
|
||||
})
|
||||
|
||||
it('builds the right query', () => {
|
||||
const expected = 'SELECT min("value") AS "min_value" FROM "db1"."rp1"."m0" WHERE time > now() - 12h GROUP BY time(10m)'
|
||||
const expected =
|
||||
'SELECT min("value") AS "min_value" FROM "db1"."rp1"."m0" WHERE time > now() - 12h GROUP BY time(10m)'
|
||||
expect(buildInfluxQLQuery(timeBounds, config)).to.equal(expected)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a measurement and one field, an aggregate, and a GROUP BY tags', () => {
|
||||
beforeEach(() => {
|
||||
config = mergeConfig({database: 'db1', measurement: 'm0', retentionPolicy: 'rp1', fields: [{field: 'value', funcs: ['min']}], groupBy: {time: null, tags: ['t1', 't2']}})
|
||||
config = mergeConfig({
|
||||
database: 'db1',
|
||||
measurement: 'm0',
|
||||
retentionPolicy: 'rp1',
|
||||
fields: [{field: 'value', funcs: ['min']}],
|
||||
groupBy: {time: null, tags: ['t1', 't2']},
|
||||
})
|
||||
timeBounds = {lower: 'now() - 12h'}
|
||||
})
|
||||
|
||||
|
@ -76,36 +118,59 @@ describe('buildInfluxQLQuery', () => {
|
|||
|
||||
describe('with a measurement, one field, and an upper / lower absolute time range', () => {
|
||||
beforeEach(() => {
|
||||
config = mergeConfig({database: 'db1', retentionPolicy: 'rp1', measurement: 'm0', fields: [{field: 'value', funcs: []}]})
|
||||
timeBounds = {lower: "'2015-07-23T15:52:24.447Z'", upper: "'2015-07-24T15:52:24.447Z'"}
|
||||
config = mergeConfig({
|
||||
database: 'db1',
|
||||
retentionPolicy: 'rp1',
|
||||
measurement: 'm0',
|
||||
fields: [{field: 'value', funcs: []}],
|
||||
})
|
||||
timeBounds = {
|
||||
lower: "'2015-07-23T15:52:24.447Z'",
|
||||
upper: "'2015-07-24T15:52:24.447Z'",
|
||||
}
|
||||
})
|
||||
|
||||
it('builds the right query', () => {
|
||||
const expected = 'SELECT "value" FROM "db1"."rp1"."m0" WHERE time > \'2015-07-23T15:52:24.447Z\' AND time < \'2015-07-24T15:52:24.447Z\''
|
||||
const expected =
|
||||
'SELECT "value" FROM "db1"."rp1"."m0" WHERE time > \'2015-07-23T15:52:24.447Z\' AND time < \'2015-07-24T15:52:24.447Z\''
|
||||
expect(buildInfluxQLQuery(timeBounds, config)).to.equal(expected)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a measurement and one field, an aggregate, and a GROUP BY time(), and tags', () => {
|
||||
beforeEach(() => {
|
||||
config = mergeConfig({database: 'db1', retentionPolicy: 'rp1', measurement: 'm0', fields: [{field: 'value', funcs: ['min']}], groupBy: {time: '10m', tags: ['t1', 't2']}})
|
||||
config = mergeConfig({
|
||||
database: 'db1',
|
||||
retentionPolicy: 'rp1',
|
||||
measurement: 'm0',
|
||||
fields: [{field: 'value', funcs: ['min']}],
|
||||
groupBy: {time: '10m', tags: ['t1', 't2']},
|
||||
})
|
||||
timeBounds = {lower: 'now() - 12h'}
|
||||
})
|
||||
|
||||
it('builds the right query', () => {
|
||||
const expected = 'SELECT min("value") AS "min_value" FROM "db1"."rp1"."m0" WHERE time > now() - 12h GROUP BY time(10m), "t1", "t2"'
|
||||
const expected =
|
||||
'SELECT min("value") AS "min_value" FROM "db1"."rp1"."m0" WHERE time > now() - 12h GROUP BY time(10m), "t1", "t2"'
|
||||
expect(buildInfluxQLQuery(timeBounds, config)).to.equal(expected)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a measurement and two fields', () => {
|
||||
beforeEach(() => {
|
||||
config = mergeConfig({database: 'db1', retentionPolicy: 'rp1', measurement: 'm0', fields: [{field: 'f0', funcs: []}, {field: 'f1', funcs: []}]})
|
||||
config = mergeConfig({
|
||||
database: 'db1',
|
||||
retentionPolicy: 'rp1',
|
||||
measurement: 'm0',
|
||||
fields: [{field: 'f0', funcs: []}, {field: 'f1', funcs: []}],
|
||||
})
|
||||
timeBounds = {upper: "'2015-02-24T00:00:00Z'"}
|
||||
})
|
||||
|
||||
it('builds the right query', () => {
|
||||
expect(buildInfluxQLQuery({}, config)).to.equal('SELECT "f0", "f1" FROM "db1"."rp1"."m0"')
|
||||
expect(buildInfluxQLQuery({}, config)).to.equal(
|
||||
'SELECT "f0", "f1" FROM "db1"."rp1"."m0"'
|
||||
)
|
||||
})
|
||||
|
||||
it('builds the right query with a time range', () => {
|
||||
|
@ -121,14 +186,8 @@ describe('buildInfluxQLQuery', () => {
|
|||
retentionPolicy: 'rp1',
|
||||
fields: [{field: 'f0', funcs: []}],
|
||||
tags: {
|
||||
k1: [
|
||||
'v1',
|
||||
'v3',
|
||||
'v4',
|
||||
],
|
||||
k2: [
|
||||
'v2',
|
||||
],
|
||||
k1: ['v1', 'v3', 'v4'],
|
||||
k2: ['v2'],
|
||||
},
|
||||
})
|
||||
timeBounds = {lower: 'now() - 6h'}
|
||||
|
|
|
@ -3,31 +3,31 @@ import InfluxQL from 'src/influxql'
|
|||
describe('influxql astToString', () => {
|
||||
it('simple query', () => {
|
||||
const ast = InfluxQL({
|
||||
"fields": [
|
||||
fields: [
|
||||
{
|
||||
"column": {
|
||||
"expr": "binary",
|
||||
"op": "+",
|
||||
"lhs": {
|
||||
"expr": "literal",
|
||||
"val": "1",
|
||||
"type": "integer"
|
||||
column: {
|
||||
expr: 'binary',
|
||||
op: '+',
|
||||
lhs: {
|
||||
expr: 'literal',
|
||||
val: '1',
|
||||
type: 'integer',
|
||||
},
|
||||
"rhs": {
|
||||
"expr": "reference",
|
||||
"val": "A"
|
||||
}
|
||||
}
|
||||
}
|
||||
rhs: {
|
||||
expr: 'reference',
|
||||
val: 'A',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"sources": [
|
||||
sources: [
|
||||
{
|
||||
"database": "",
|
||||
"retentionPolicy": "",
|
||||
"name": "howdy",
|
||||
"type": "measurement"
|
||||
}
|
||||
]
|
||||
database: '',
|
||||
retentionPolicy: '',
|
||||
name: 'howdy',
|
||||
type: 'measurement',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const expected = `SELECT 1 + "A" FROM "howdy"`
|
||||
|
@ -40,37 +40,37 @@ describe('influxql astToString', () => {
|
|||
|
||||
it('simple query w/ multiple sources', () => {
|
||||
const ast = InfluxQL({
|
||||
"fields": [
|
||||
fields: [
|
||||
{
|
||||
"column": {
|
||||
"expr": "binary",
|
||||
"op": "+",
|
||||
"lhs": {
|
||||
"expr": "literal",
|
||||
"val": "1",
|
||||
"type": "integer"
|
||||
column: {
|
||||
expr: 'binary',
|
||||
op: '+',
|
||||
lhs: {
|
||||
expr: 'literal',
|
||||
val: '1',
|
||||
type: 'integer',
|
||||
},
|
||||
"rhs": {
|
||||
"expr": "reference",
|
||||
"val": "A"
|
||||
}
|
||||
}
|
||||
}
|
||||
rhs: {
|
||||
expr: 'reference',
|
||||
val: 'A',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"sources": [
|
||||
sources: [
|
||||
{
|
||||
"database": "",
|
||||
"retentionPolicy": "",
|
||||
"name": "howdy",
|
||||
"type": "measurement"
|
||||
database: '',
|
||||
retentionPolicy: '',
|
||||
name: 'howdy',
|
||||
type: 'measurement',
|
||||
},
|
||||
{
|
||||
"database": "telegraf",
|
||||
"retentionPolicy": "autogen",
|
||||
"name": "doody",
|
||||
"type": "measurement"
|
||||
}
|
||||
]
|
||||
database: 'telegraf',
|
||||
retentionPolicy: 'autogen',
|
||||
name: 'doody',
|
||||
type: 'measurement',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const expected = `SELECT 1 + "A" FROM "howdy", "telegraf"."autogen"."doody"`
|
||||
|
@ -84,32 +84,32 @@ describe('influxql astToString', () => {
|
|||
|
||||
it('query with AS', () => {
|
||||
const ast = InfluxQL({
|
||||
"fields": [
|
||||
fields: [
|
||||
{
|
||||
"alias": "B",
|
||||
"column": {
|
||||
"expr": "binary",
|
||||
"op": "+",
|
||||
"lhs": {
|
||||
"expr": "literal",
|
||||
"val": "1",
|
||||
"type": "integer"
|
||||
alias: 'B',
|
||||
column: {
|
||||
expr: 'binary',
|
||||
op: '+',
|
||||
lhs: {
|
||||
expr: 'literal',
|
||||
val: '1',
|
||||
type: 'integer',
|
||||
},
|
||||
"rhs": {
|
||||
"expr": "reference",
|
||||
"val": "A"
|
||||
}
|
||||
}
|
||||
}
|
||||
rhs: {
|
||||
expr: 'reference',
|
||||
val: 'A',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"sources": [
|
||||
sources: [
|
||||
{
|
||||
"database": "",
|
||||
"retentionPolicy": "",
|
||||
"name": "howdy",
|
||||
"type": "measurement"
|
||||
}
|
||||
]
|
||||
database: '',
|
||||
retentionPolicy: '',
|
||||
name: 'howdy',
|
||||
type: 'measurement',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const expected = `SELECT 1 + "A" AS "B" FROM "howdy"`
|
||||
|
@ -122,52 +122,52 @@ describe('influxql astToString', () => {
|
|||
|
||||
it('query with 2x func', () => {
|
||||
const ast = InfluxQL({
|
||||
"fields": [
|
||||
fields: [
|
||||
{
|
||||
"column": {
|
||||
"expr": "binary",
|
||||
"op": "/",
|
||||
"lhs": {
|
||||
"expr": "call",
|
||||
"name": "derivative",
|
||||
"args": [
|
||||
column: {
|
||||
expr: 'binary',
|
||||
op: '/',
|
||||
lhs: {
|
||||
expr: 'call',
|
||||
name: 'derivative',
|
||||
args: [
|
||||
{
|
||||
"expr": "reference",
|
||||
"val": "field1"
|
||||
expr: 'reference',
|
||||
val: 'field1',
|
||||
},
|
||||
{
|
||||
"expr": "literal",
|
||||
"val": "1h",
|
||||
"type": "duration"
|
||||
}
|
||||
]
|
||||
expr: 'literal',
|
||||
val: '1h',
|
||||
type: 'duration',
|
||||
},
|
||||
],
|
||||
},
|
||||
"rhs": {
|
||||
"expr": "call",
|
||||
"name": "derivative",
|
||||
"args": [
|
||||
rhs: {
|
||||
expr: 'call',
|
||||
name: 'derivative',
|
||||
args: [
|
||||
{
|
||||
"expr": "reference",
|
||||
"val": "field2"
|
||||
expr: 'reference',
|
||||
val: 'field2',
|
||||
},
|
||||
{
|
||||
"expr": "literal",
|
||||
"val": "1h",
|
||||
"type": "duration"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
expr: 'literal',
|
||||
val: '1h',
|
||||
type: 'duration',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"sources": [
|
||||
sources: [
|
||||
{
|
||||
"database": "",
|
||||
"retentionPolicy": "",
|
||||
"name": "myseries",
|
||||
"type": "measurement"
|
||||
}
|
||||
]
|
||||
database: '',
|
||||
retentionPolicy: '',
|
||||
name: 'myseries',
|
||||
type: 'measurement',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const expected = `SELECT derivative("field1", 1h) / derivative("field2", 1h) FROM "myseries"`
|
||||
|
@ -181,121 +181,119 @@ describe('influxql astToString', () => {
|
|||
|
||||
it('query with where and groupby', () => {
|
||||
const ast = InfluxQL({
|
||||
"condition": {
|
||||
"expr": "binary",
|
||||
"op": "AND",
|
||||
"lhs": {
|
||||
"expr": "binary",
|
||||
"op": "AND",
|
||||
"lhs": {
|
||||
"expr": "binary",
|
||||
"op": "=~",
|
||||
"lhs": {
|
||||
"expr": "reference",
|
||||
"val": "cluster_id"
|
||||
condition: {
|
||||
expr: 'binary',
|
||||
op: 'AND',
|
||||
lhs: {
|
||||
expr: 'binary',
|
||||
op: 'AND',
|
||||
lhs: {
|
||||
expr: 'binary',
|
||||
op: '=~',
|
||||
lhs: {
|
||||
expr: 'reference',
|
||||
val: 'cluster_id',
|
||||
},
|
||||
rhs: {
|
||||
expr: 'literal',
|
||||
val: '/^23/',
|
||||
type: 'regex',
|
||||
},
|
||||
"rhs": {
|
||||
"expr": "literal",
|
||||
"val": "/^23/",
|
||||
"type": "regex"
|
||||
}
|
||||
},
|
||||
"rhs": {
|
||||
"expr": "binary",
|
||||
"op": "=",
|
||||
"lhs": {
|
||||
"expr": "reference",
|
||||
"val": "host"
|
||||
rhs: {
|
||||
expr: 'binary',
|
||||
op: '=',
|
||||
lhs: {
|
||||
expr: 'reference',
|
||||
val: 'host',
|
||||
},
|
||||
"rhs": {
|
||||
"expr": "literal",
|
||||
"val": "prod-2ccccc04-us-east-1-data-3",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
rhs: {
|
||||
expr: 'literal',
|
||||
val: 'prod-2ccccc04-us-east-1-data-3',
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
"rhs": {
|
||||
"expr": "binary",
|
||||
"op": "\u003e",
|
||||
"lhs": {
|
||||
"expr": "reference",
|
||||
"val": "time"
|
||||
rhs: {
|
||||
expr: 'binary',
|
||||
op: '\u003e',
|
||||
lhs: {
|
||||
expr: 'reference',
|
||||
val: 'time',
|
||||
},
|
||||
"rhs": {
|
||||
"expr": "binary",
|
||||
"op": "-",
|
||||
"lhs": {
|
||||
"expr": "call",
|
||||
"name": "now"
|
||||
rhs: {
|
||||
expr: 'binary',
|
||||
op: '-',
|
||||
lhs: {
|
||||
expr: 'call',
|
||||
name: 'now',
|
||||
},
|
||||
"rhs": {
|
||||
"expr": "literal",
|
||||
"val": "15m",
|
||||
"type": "duration"
|
||||
}
|
||||
}
|
||||
}
|
||||
rhs: {
|
||||
expr: 'literal',
|
||||
val: '15m',
|
||||
type: 'duration',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"fields": [
|
||||
fields: [
|
||||
{
|
||||
"alias": "max_cpus",
|
||||
"column": {
|
||||
"expr": "call",
|
||||
"name": "max",
|
||||
"args": [
|
||||
alias: 'max_cpus',
|
||||
column: {
|
||||
expr: 'call',
|
||||
name: 'max',
|
||||
args: [
|
||||
{
|
||||
"expr": "reference",
|
||||
"val": "n_cpus"
|
||||
}
|
||||
]
|
||||
}
|
||||
expr: 'reference',
|
||||
val: 'n_cpus',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"column": {
|
||||
"expr": "call",
|
||||
"name": "non_negative_derivative",
|
||||
"args": [
|
||||
column: {
|
||||
expr: 'call',
|
||||
name: 'non_negative_derivative',
|
||||
args: [
|
||||
{
|
||||
"expr": "call",
|
||||
"name": "median",
|
||||
"args": [
|
||||
expr: 'call',
|
||||
name: 'median',
|
||||
args: [
|
||||
{
|
||||
"expr": "reference",
|
||||
"val": "n_users"
|
||||
}
|
||||
]
|
||||
expr: 'reference',
|
||||
val: 'n_users',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"expr": "literal",
|
||||
"val": "5m",
|
||||
"type": "duration"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"groupBy": {
|
||||
"time": {
|
||||
"interval": "15m",
|
||||
"offset": "10s"
|
||||
expr: 'literal',
|
||||
val: '5m',
|
||||
type: 'duration',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"tags": [
|
||||
"host",
|
||||
"tag_x"
|
||||
],
|
||||
"fill": "10"
|
||||
],
|
||||
groupBy: {
|
||||
time: {
|
||||
interval: '15m',
|
||||
offset: '10s',
|
||||
},
|
||||
tags: ['host', 'tag_x'],
|
||||
fill: '10',
|
||||
},
|
||||
"sources": [
|
||||
sources: [
|
||||
{
|
||||
"database": "",
|
||||
"retentionPolicy": "",
|
||||
"name": "system",
|
||||
"type": "measurement"
|
||||
}
|
||||
]
|
||||
database: '',
|
||||
retentionPolicy: '',
|
||||
name: 'system',
|
||||
type: 'measurement',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const expected = "SELECT max(\"n_cpus\") AS \"max_cpus\", non_negative_derivative(median(\"n_users\"), 5m) FROM \"system\" WHERE \"cluster_id\" =~ /^23/ AND \"host\" = 'prod-2ccccc04-us-east-1-data-3' AND time > now() - 15m GROUP BY time(15m, 10s),host,tag_x fill(10)"
|
||||
const expected =
|
||||
'SELECT max("n_cpus") AS "max_cpus", non_negative_derivative(median("n_users"), 5m) FROM "system" WHERE "cluster_id" =~ /^23/ AND "host" = \'prod-2ccccc04-us-east-1-data-3\' AND time > now() - 15m GROUP BY time(15m, 10s),host,tag_x fill(10)'
|
||||
const actual = ast.toString()
|
||||
|
||||
// console.log('actual ', actual)
|
||||
|
@ -306,98 +304,98 @@ describe('influxql astToString', () => {
|
|||
|
||||
it('query with orderby and limit', () => {
|
||||
const ast = InfluxQL({
|
||||
"condition": {
|
||||
"expr": "binary",
|
||||
"op": "AND",
|
||||
"lhs": {
|
||||
"expr": "binary",
|
||||
"op": "=",
|
||||
"lhs": {
|
||||
"expr": "reference",
|
||||
"val": "host"
|
||||
condition: {
|
||||
expr: 'binary',
|
||||
op: 'AND',
|
||||
lhs: {
|
||||
expr: 'binary',
|
||||
op: '=',
|
||||
lhs: {
|
||||
expr: 'reference',
|
||||
val: 'host',
|
||||
},
|
||||
"rhs": {
|
||||
"expr": "literal",
|
||||
"val": "hosta.influxdb.org",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"rhs": {
|
||||
"expr": "binary",
|
||||
"op": "\u003e",
|
||||
"lhs": {
|
||||
"expr": "reference",
|
||||
"val": "time"
|
||||
rhs: {
|
||||
expr: 'literal',
|
||||
val: 'hosta.influxdb.org',
|
||||
type: 'string',
|
||||
},
|
||||
"rhs": {
|
||||
"expr": "literal",
|
||||
"val": "2017-02-07T01:43:02.245407693Z",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
rhs: {
|
||||
expr: 'binary',
|
||||
op: '\u003e',
|
||||
lhs: {
|
||||
expr: 'reference',
|
||||
val: 'time',
|
||||
},
|
||||
rhs: {
|
||||
expr: 'literal',
|
||||
val: '2017-02-07T01:43:02.245407693Z',
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
"fields": [
|
||||
fields: [
|
||||
{
|
||||
"column": {
|
||||
"expr": "call",
|
||||
"name": "mean",
|
||||
"args": [
|
||||
column: {
|
||||
expr: 'call',
|
||||
name: 'mean',
|
||||
args: [
|
||||
{
|
||||
"expr": "reference",
|
||||
"val": "field1"
|
||||
}
|
||||
]
|
||||
}
|
||||
expr: 'reference',
|
||||
val: 'field1',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"column": {
|
||||
"expr": "call",
|
||||
"name": "sum",
|
||||
"args": [
|
||||
column: {
|
||||
expr: 'call',
|
||||
name: 'sum',
|
||||
args: [
|
||||
{
|
||||
"expr": "reference",
|
||||
"val": "field2"
|
||||
}
|
||||
]
|
||||
}
|
||||
expr: 'reference',
|
||||
val: 'field2',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"alias": "field_x",
|
||||
"column": {
|
||||
"expr": "call",
|
||||
"name": "count",
|
||||
"args": [
|
||||
alias: 'field_x',
|
||||
column: {
|
||||
expr: 'call',
|
||||
name: 'count',
|
||||
args: [
|
||||
{
|
||||
"expr": "reference",
|
||||
"val": "field3"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
expr: 'reference',
|
||||
val: 'field3',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
"groupBy": {
|
||||
"time": {
|
||||
"interval": "10h"
|
||||
}
|
||||
groupBy: {
|
||||
time: {
|
||||
interval: '10h',
|
||||
},
|
||||
},
|
||||
"limits": {
|
||||
"limit": 20,
|
||||
"offset": 10
|
||||
limits: {
|
||||
limit: 20,
|
||||
offset: 10,
|
||||
},
|
||||
"orderbys": [
|
||||
orderbys: [
|
||||
{
|
||||
"name": "time",
|
||||
"order": "descending"
|
||||
}
|
||||
name: 'time',
|
||||
order: 'descending',
|
||||
},
|
||||
],
|
||||
"sources": [
|
||||
sources: [
|
||||
{
|
||||
"database": "",
|
||||
"retentionPolicy": "",
|
||||
"name": "myseries",
|
||||
"type": "measurement"
|
||||
}
|
||||
]
|
||||
database: '',
|
||||
retentionPolicy: '',
|
||||
name: 'myseries',
|
||||
type: 'measurement',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const expected = `SELECT mean("field1"), sum("field2"), count("field3") AS "field_x" FROM "myseries" WHERE "host" = 'hosta.influxdb.org' AND time > '2017-02-07T01:43:02.245407693Z' GROUP BY time(10h) ORDER BY time DESC LIMIT 20 OFFSET 10`
|
||||
|
|
|
@ -1,11 +1,52 @@
|
|||
import {diskBytesFromShard, diskBytesFromShardForDatabase} from 'shared/parsing/diskBytes'
|
||||
import {
|
||||
diskBytesFromShard,
|
||||
diskBytesFromShardForDatabase,
|
||||
} from 'shared/parsing/diskBytes'
|
||||
|
||||
describe('diskBytesFromShard', () => {
|
||||
it('sums all the disk bytes in multiple series', () => {
|
||||
const response = {results: [
|
||||
{series: [{name: "shard", tags: {clusterID: "6272208615254493595", database: "_internal", engine: "tsm1", hostname: "WattsInfluxDB", id: "1", nodeID: "localhost:8088", path: "/Users/watts/.influxdb/data/_internal/monitor/1", retentionPolicy: "monitor"}, columns: ["time", "last"], values: [[1464811503000000000, 100]]}]},
|
||||
{series: [{name: "shard", tags: {clusterID: "6272208615254493595", database: "telegraf", engine: "tsm1", hostname: "WattsInfluxDB", id: "2", nodeID: "localhost:8088", path: "/Users/watts/.influxdb/data/telegraf/default/2", retentionPolicy: "default"}, columns: ["time", "last"], values: [[1464811503000000000, 200]]}]},
|
||||
]}
|
||||
const response = {
|
||||
results: [
|
||||
{
|
||||
series: [
|
||||
{
|
||||
name: 'shard',
|
||||
tags: {
|
||||
clusterID: '6272208615254493595',
|
||||
database: '_internal',
|
||||
engine: 'tsm1',
|
||||
hostname: 'WattsInfluxDB',
|
||||
id: '1',
|
||||
nodeID: 'localhost:8088',
|
||||
path: '/Users/watts/.influxdb/data/_internal/monitor/1',
|
||||
retentionPolicy: 'monitor',
|
||||
},
|
||||
columns: ['time', 'last'],
|
||||
values: [[1464811503000000000, 100]],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
series: [
|
||||
{
|
||||
name: 'shard',
|
||||
tags: {
|
||||
clusterID: '6272208615254493595',
|
||||
database: 'telegraf',
|
||||
engine: 'tsm1',
|
||||
hostname: 'WattsInfluxDB',
|
||||
id: '2',
|
||||
nodeID: 'localhost:8088',
|
||||
path: '/Users/watts/.influxdb/data/telegraf/default/2',
|
||||
retentionPolicy: 'default',
|
||||
},
|
||||
columns: ['time', 'last'],
|
||||
values: [[1464811503000000000, 200]],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const result = diskBytesFromShard(response)
|
||||
const expectedTotal = 300
|
||||
|
@ -24,7 +65,7 @@ describe('diskBytesFromShard', () => {
|
|||
})
|
||||
|
||||
it('exposes the server error', () => {
|
||||
const response = {results: [{error: "internal server error?"}]}
|
||||
const response = {results: [{error: 'internal server error?'}]}
|
||||
|
||||
const result = diskBytesFromShard(response)
|
||||
|
||||
|
@ -35,17 +76,65 @@ describe('diskBytesFromShard', () => {
|
|||
|
||||
describe('diskBytesFromShardForDatabase', () => {
|
||||
it('return parses data as expected', () => {
|
||||
const response = {results: [{series: [
|
||||
{name: "shard", tags: {nodeID: "localhost:8088", path: "/Users/watts/.influxdb/data/_internal/monitor/1", retentionPolicy: "monitor"}, columns: ["time", "last"], values: [["2016-06-02T01:06:13Z", 100]]},
|
||||
{name: "shard", tags: {nodeID: "localhost:8088", path: "/Users/watts/.influxdb/data/_internal/monitor/3", retentionPolicy: "monitor"}, columns: ["time", "last"], values: [["2016-06-02T01:06:13Z", 200]]},
|
||||
{name: "shard", tags: {nodeID: "localhost:8188", path: "/Users/watts/.influxdb/data/_internal/monitor/1", retentionPolicy: "monitor"}, columns: ["time", "last"], values: [["2016-06-02T01:06:13Z", 100]]},
|
||||
{name: "shard", tags: {nodeID: "localhost:8188", path: "/Users/watts/.influxdb/data/_internal/monitor/3", retentionPolicy: "monitor"}, columns: ["time", "last"], values: [["2016-06-02T01:06:13Z", 200]]},
|
||||
]}]}
|
||||
const response = {
|
||||
results: [
|
||||
{
|
||||
series: [
|
||||
{
|
||||
name: 'shard',
|
||||
tags: {
|
||||
nodeID: 'localhost:8088',
|
||||
path: '/Users/watts/.influxdb/data/_internal/monitor/1',
|
||||
retentionPolicy: 'monitor',
|
||||
},
|
||||
columns: ['time', 'last'],
|
||||
values: [['2016-06-02T01:06:13Z', 100]],
|
||||
},
|
||||
{
|
||||
name: 'shard',
|
||||
tags: {
|
||||
nodeID: 'localhost:8088',
|
||||
path: '/Users/watts/.influxdb/data/_internal/monitor/3',
|
||||
retentionPolicy: 'monitor',
|
||||
},
|
||||
columns: ['time', 'last'],
|
||||
values: [['2016-06-02T01:06:13Z', 200]],
|
||||
},
|
||||
{
|
||||
name: 'shard',
|
||||
tags: {
|
||||
nodeID: 'localhost:8188',
|
||||
path: '/Users/watts/.influxdb/data/_internal/monitor/1',
|
||||
retentionPolicy: 'monitor',
|
||||
},
|
||||
columns: ['time', 'last'],
|
||||
values: [['2016-06-02T01:06:13Z', 100]],
|
||||
},
|
||||
{
|
||||
name: 'shard',
|
||||
tags: {
|
||||
nodeID: 'localhost:8188',
|
||||
path: '/Users/watts/.influxdb/data/_internal/monitor/3',
|
||||
retentionPolicy: 'monitor',
|
||||
},
|
||||
columns: ['time', 'last'],
|
||||
values: [['2016-06-02T01:06:13Z', 200]],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const result = diskBytesFromShardForDatabase(response)
|
||||
const expected = {
|
||||
1: [{nodeID: 'localhost:8088', diskUsage: 100}, {nodeID: 'localhost:8188', diskUsage: 100}],
|
||||
3: [{nodeID: 'localhost:8088', diskUsage: 200}, {nodeID: 'localhost:8188', diskUsage: 200}],
|
||||
1: [
|
||||
{nodeID: 'localhost:8088', diskUsage: 100},
|
||||
{nodeID: 'localhost:8188', diskUsage: 100},
|
||||
],
|
||||
3: [
|
||||
{nodeID: 'localhost:8088', diskUsage: 200},
|
||||
{nodeID: 'localhost:8188', diskUsage: 200},
|
||||
],
|
||||
}
|
||||
|
||||
expect(result.shardData).to.deep.equal(expected)
|
||||
|
@ -61,7 +150,7 @@ describe('diskBytesFromShardForDatabase', () => {
|
|||
})
|
||||
|
||||
it('exposes the server error', () => {
|
||||
const response = {results: [{error: "internal server error?"}]}
|
||||
const response = {results: [{error: 'internal server error?'}]}
|
||||
|
||||
const result = diskBytesFromShardForDatabase(response)
|
||||
|
||||
|
|
|
@ -43,14 +43,20 @@ describe('getRangeForDygraphSpec', () => {
|
|||
const timeSeries = [[date, max], [date, mid], [date, min]]
|
||||
|
||||
it('can pad positive values', () => {
|
||||
const [actualMin, actualMax] = getRange(timeSeries, undefined, {...kapacitor, value: 20})
|
||||
const [actualMin, actualMax] = getRange(timeSeries, undefined, {
|
||||
...kapacitor,
|
||||
value: 20,
|
||||
})
|
||||
|
||||
expect(actualMin).to.equal(min)
|
||||
expect(actualMax).to.be.above(max)
|
||||
})
|
||||
|
||||
it('can pad negative values', () => {
|
||||
const [actualMin, actualMax] = getRange(timeSeries, undefined, {...kapacitor, value: -10})
|
||||
const [actualMin, actualMax] = getRange(timeSeries, undefined, {
|
||||
...kapacitor,
|
||||
value: -10,
|
||||
})
|
||||
|
||||
expect(actualMin).to.be.below(min)
|
||||
expect(actualMax).to.equal(max)
|
||||
|
@ -60,7 +66,10 @@ describe('getRangeForDygraphSpec', () => {
|
|||
it('subtracts from a positive value', () => {
|
||||
const value = 2
|
||||
const opAndValue = {operator: 'less than', value}
|
||||
const [actualMin, actualMax] = getRange(timeSeries, undefined, {...kapacitor, ...opAndValue})
|
||||
const [actualMin, actualMax] = getRange(timeSeries, undefined, {
|
||||
...kapacitor,
|
||||
...opAndValue,
|
||||
})
|
||||
|
||||
expect(actualMin).to.be.lessThan(value)
|
||||
expect(actualMax).to.equal(max)
|
||||
|
@ -72,14 +81,20 @@ describe('getRangeForDygraphSpec', () => {
|
|||
const timeSeries = [[date, max], [date, min], [date, mid]]
|
||||
|
||||
it('can pad positive values', () => {
|
||||
const [actualMin, actualMax] = getRange(timeSeries, undefined, {...kapacitor, rangeValue: 20})
|
||||
const [actualMin, actualMax] = getRange(timeSeries, undefined, {
|
||||
...kapacitor,
|
||||
rangeValue: 20,
|
||||
})
|
||||
|
||||
expect(actualMin).to.equal(min)
|
||||
expect(actualMax).to.be.above(max)
|
||||
})
|
||||
|
||||
it('can pad negative values', () => {
|
||||
const [actualMin, actualMax] = getRange(timeSeries, undefined, {...kapacitor, rangeValue: -10})
|
||||
const [actualMin, actualMax] = getRange(timeSeries, undefined, {
|
||||
...kapacitor,
|
||||
rangeValue: -10,
|
||||
})
|
||||
|
||||
expect(actualMin).to.be.below(min)
|
||||
expect(actualMax).to.equal(max)
|
||||
|
|
|
@ -15,36 +15,24 @@ it('can parse an alerta tick script', () => {
|
|||
|
||||
const expectedObj = [
|
||||
{
|
||||
name: "resource",
|
||||
args: [
|
||||
"Hostname or service",
|
||||
],
|
||||
name: 'resource',
|
||||
args: ['Hostname or service'],
|
||||
},
|
||||
{
|
||||
name: "event",
|
||||
args: [
|
||||
"Something went wrong",
|
||||
],
|
||||
name: 'event',
|
||||
args: ['Something went wrong'],
|
||||
},
|
||||
{
|
||||
name: "environment",
|
||||
args: [
|
||||
"Development",
|
||||
],
|
||||
name: 'environment',
|
||||
args: ['Development'],
|
||||
},
|
||||
{
|
||||
name: "group",
|
||||
args: [
|
||||
"Dev. Servers",
|
||||
],
|
||||
name: 'group',
|
||||
args: ['Dev. Servers'],
|
||||
},
|
||||
{
|
||||
name: "services",
|
||||
args: [
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
],
|
||||
name: 'services',
|
||||
args: ['a', 'b', 'c'],
|
||||
},
|
||||
]
|
||||
|
||||
|
|
|
@ -2,7 +2,11 @@ import showDatabases from 'shared/parsing/showDatabases'
|
|||
|
||||
describe('showDatabases', () => {
|
||||
it('exposes all the database properties', () => {
|
||||
const response = {results: [{series: [{columns: ["name"], values: [["mydb1"], ["mydb2"]]}]}]}
|
||||
const response = {
|
||||
results: [
|
||||
{series: [{columns: ['name'], values: [['mydb1'], ['mydb2']]}]},
|
||||
],
|
||||
}
|
||||
|
||||
const result = showDatabases(response)
|
||||
|
||||
|
@ -13,7 +17,7 @@ describe('showDatabases', () => {
|
|||
})
|
||||
|
||||
it('returns an empty array when there are no databases', () => {
|
||||
const response = {results: [{series: [{columns: ["name"]}]}]}
|
||||
const response = {results: [{series: [{columns: ['name']}]}]}
|
||||
|
||||
const result = showDatabases(response)
|
||||
|
||||
|
@ -22,7 +26,7 @@ describe('showDatabases', () => {
|
|||
})
|
||||
|
||||
it('exposes the server error', () => {
|
||||
const response = {results: [{error: "internal server error?"}]}
|
||||
const response = {results: [{error: 'internal server error?'}]}
|
||||
|
||||
const result = showDatabases(response)
|
||||
|
||||
|
|
|
@ -2,7 +2,15 @@ import parseShowFieldKeys from 'shared/parsing/showFieldKeys'
|
|||
|
||||
describe('parseShowFieldKeys', () => {
|
||||
it('parses a single result', () => {
|
||||
const response = {results: [{series: [{name: "m1", columns: ["fieldKey"], values: [["f1"], ["f2"]]}]}]}
|
||||
const response = {
|
||||
results: [
|
||||
{
|
||||
series: [
|
||||
{name: 'm1', columns: ['fieldKey'], values: [['f1'], ['f2']]},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const result = parseShowFieldKeys(response)
|
||||
expect(result.errors).to.eql([])
|
||||
|
@ -12,7 +20,20 @@ describe('parseShowFieldKeys', () => {
|
|||
})
|
||||
|
||||
it('parses multiple results', () => {
|
||||
const response = {results: [{series: [{name: "m1", columns: ["fieldKey"], values: [["f1"], ["f2"]]}]}, {series: [{name: "m2", columns: ["fieldKey"], values: [["f3"], ["f4"]]}]}]}
|
||||
const response = {
|
||||
results: [
|
||||
{
|
||||
series: [
|
||||
{name: 'm1', columns: ['fieldKey'], values: [['f1'], ['f2']]},
|
||||
],
|
||||
},
|
||||
{
|
||||
series: [
|
||||
{name: 'm2', columns: ['fieldKey'], values: [['f3'], ['f4']]},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
const result = parseShowFieldKeys(response)
|
||||
expect(result.errors).to.eql([])
|
||||
expect(result.fieldSets).to.eql({
|
||||
|
@ -22,14 +43,31 @@ describe('parseShowFieldKeys', () => {
|
|||
})
|
||||
|
||||
it('parses multiple errors', () => {
|
||||
const response = {results: [{error: "measurement not found: m1"}, {error: "measurement not found: m2"}]}
|
||||
const response = {
|
||||
results: [
|
||||
{error: 'measurement not found: m1'},
|
||||
{error: 'measurement not found: m2'},
|
||||
],
|
||||
}
|
||||
const result = parseShowFieldKeys(response)
|
||||
expect(result.errors).to.eql(['measurement not found: m1', 'measurement not found: m2'])
|
||||
expect(result.errors).to.eql([
|
||||
'measurement not found: m1',
|
||||
'measurement not found: m2',
|
||||
])
|
||||
expect(result.fieldSets).to.eql({})
|
||||
})
|
||||
|
||||
it('parses a mix of results and errors', () => {
|
||||
const response = {results: [{series: [{name: "m1", columns: ["fieldKey"], values: [["f1"], ["f2"]]}]}, {error: "measurement not found: m2"}]}
|
||||
const response = {
|
||||
results: [
|
||||
{
|
||||
series: [
|
||||
{name: 'm1', columns: ['fieldKey'], values: [['f1'], ['f2']]},
|
||||
],
|
||||
},
|
||||
{error: 'measurement not found: m2'},
|
||||
],
|
||||
}
|
||||
const result = parseShowFieldKeys(response)
|
||||
expect(result.errors).to.eql(['measurement not found: m2'])
|
||||
expect(result.fieldSets).to.eql({
|
||||
|
|
|
@ -2,7 +2,21 @@ import showQueriesParser from 'shared/parsing/showQueries'
|
|||
|
||||
describe('showQueriesParser', () => {
|
||||
it('exposes all currently running queries', () => {
|
||||
const response = {results: [{series: [{columns: ["qid", "query", "database", "duration"], values: [[1, "SHOW QUERIES", "db1", "1s"], [2, "SELECT foo FROM bar", "db1", "2s"]]}]}]}
|
||||
const response = {
|
||||
results: [
|
||||
{
|
||||
series: [
|
||||
{
|
||||
columns: ['qid', 'query', 'database', 'duration'],
|
||||
values: [
|
||||
[1, 'SHOW QUERIES', 'db1', '1s'],
|
||||
[2, 'SELECT foo FROM bar', 'db1', '2s'],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const result = showQueriesParser(response)
|
||||
|
||||
|
@ -24,7 +38,7 @@ describe('showQueriesParser', () => {
|
|||
})
|
||||
|
||||
it('exposes the server error', () => {
|
||||
const response = {results: [{error: "internal server error?"}]}
|
||||
const response = {results: [{error: 'internal server error?'}]}
|
||||
|
||||
const result = showQueriesParser(response)
|
||||
|
||||
|
|
|
@ -2,7 +2,15 @@ import parseShowTagKeys from 'shared/parsing/showTagKeys'
|
|||
|
||||
describe('parseShowTagKeys', () => {
|
||||
it('parses the tag keys', () => {
|
||||
const response = {results: [{series: [{name: "cpu", columns: ["tagKey"], values: [["cpu"], ["host"]]}]}]}
|
||||
const response = {
|
||||
results: [
|
||||
{
|
||||
series: [
|
||||
{name: 'cpu', columns: ['tagKey'], values: [['cpu'], ['host']]},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const result = parseShowTagKeys(response)
|
||||
expect(result.errors).to.eql([])
|
||||
|
@ -18,7 +26,7 @@ describe('parseShowTagKeys', () => {
|
|||
})
|
||||
|
||||
it('handles errors', () => {
|
||||
const response = {results: [{error: "influxdb error"}]}
|
||||
const response = {results: [{error: 'influxdb error'}]}
|
||||
|
||||
const result = parseShowTagKeys(response)
|
||||
expect(result.errors).to.eql([response.results[0].error])
|
||||
|
|
|
@ -16,13 +16,13 @@ describe('showTagValuesParser', () => {
|
|||
{
|
||||
series: [
|
||||
{
|
||||
name: "measurementA",
|
||||
columns: ["key", "value"],
|
||||
name: 'measurementA',
|
||||
columns: ['key', 'value'],
|
||||
values: [
|
||||
["host", "hostA"],
|
||||
["host", "hostB"],
|
||||
["cpu", "cpu0"],
|
||||
["cpu", "cpu1"],
|
||||
['host', 'hostA'],
|
||||
['host', 'hostB'],
|
||||
['cpu', 'cpu0'],
|
||||
['cpu', 'cpu1'],
|
||||
],
|
||||
},
|
||||
],
|
||||
|
@ -34,14 +34,8 @@ describe('showTagValuesParser', () => {
|
|||
|
||||
expect(result.errors).to.eql([])
|
||||
expect(result.tags).to.eql({
|
||||
host: [
|
||||
'hostA',
|
||||
'hostB',
|
||||
],
|
||||
cpu: [
|
||||
'cpu0',
|
||||
'cpu1',
|
||||
],
|
||||
host: ['hostA', 'hostB'],
|
||||
cpu: ['cpu0', 'cpu1'],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
import {
|
||||
buildRoles,
|
||||
buildClusterAccounts,
|
||||
} from 'shared/presenters'
|
||||
import {buildRoles, buildClusterAccounts} from 'shared/presenters'
|
||||
|
||||
describe('Presenters', function() {
|
||||
describe('roles utils', function() {
|
||||
describe('buildRoles', function() {
|
||||
describe('when a role has no users', function() {
|
||||
it('sets a role\'s users as an empty array', function() {
|
||||
it("sets a role's users as an empty array", function() {
|
||||
const roles = [
|
||||
{
|
||||
name: "Marketing",
|
||||
name: 'Marketing',
|
||||
permissions: {
|
||||
"": [
|
||||
"ViewAdmin",
|
||||
],
|
||||
'': ['ViewAdmin'],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
@ -26,14 +21,11 @@ describe('Presenters', function() {
|
|||
})
|
||||
|
||||
describe('when a role has no permissions', function() {
|
||||
it('set\'s a roles permission as an empty array', function() {
|
||||
it("set's a roles permission as an empty array", function() {
|
||||
const roles = [
|
||||
{
|
||||
name: "Marketing",
|
||||
users: [
|
||||
"roley@influxdb.com",
|
||||
"will@influxdb.com",
|
||||
],
|
||||
name: 'Marketing',
|
||||
users: ['roley@influxdb.com', 'will@influxdb.com'],
|
||||
},
|
||||
]
|
||||
|
||||
|
@ -47,23 +39,13 @@ describe('Presenters', function() {
|
|||
beforeEach(function() {
|
||||
const roles = [
|
||||
{
|
||||
name: "Marketing",
|
||||
name: 'Marketing',
|
||||
permissions: {
|
||||
"": [
|
||||
"ViewAdmin",
|
||||
],
|
||||
db1: [
|
||||
"ReadData",
|
||||
],
|
||||
db2: [
|
||||
"ReadData",
|
||||
"AddRemoveNode",
|
||||
],
|
||||
'': ['ViewAdmin'],
|
||||
db1: ['ReadData'],
|
||||
db2: ['ReadData', 'AddRemoveNode'],
|
||||
},
|
||||
users: [
|
||||
"roley@influxdb.com",
|
||||
"will@influxdb.com",
|
||||
],
|
||||
users: ['roley@influxdb.com', 'will@influxdb.com'],
|
||||
},
|
||||
]
|
||||
|
||||
|
@ -73,8 +55,8 @@ describe('Presenters', function() {
|
|||
it('each role has a name and a list of users (if they exist)', function() {
|
||||
const role = this.roles[0]
|
||||
expect(role.name).to.equal('Marketing')
|
||||
expect(role.users).to.contain("roley@influxdb.com")
|
||||
expect(role.users).to.contain("will@influxdb.com")
|
||||
expect(role.users).to.contain('roley@influxdb.com')
|
||||
expect(role.users).to.contain('will@influxdb.com')
|
||||
})
|
||||
|
||||
it('transforms permissions into a list of objects and each permission has a list of resources', function() {
|
||||
|
@ -109,46 +91,33 @@ describe('Presenters', function() {
|
|||
it('adds role information to each cluster account and parses permissions', function() {
|
||||
const users = [
|
||||
{
|
||||
name: "jon@example.com",
|
||||
hash: "xxxxx",
|
||||
name: 'jon@example.com',
|
||||
hash: 'xxxxx',
|
||||
permissions: {
|
||||
"": [
|
||||
"ViewAdmin",
|
||||
],
|
||||
db1: [
|
||||
"ReadData",
|
||||
],
|
||||
'': ['ViewAdmin'],
|
||||
db1: ['ReadData'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ned@example.com",
|
||||
hash: "xxxxx",
|
||||
name: 'ned@example.com',
|
||||
hash: 'xxxxx',
|
||||
},
|
||||
]
|
||||
|
||||
const roles = [
|
||||
{
|
||||
name: "Admin",
|
||||
name: 'Admin',
|
||||
permissions: {
|
||||
db2: [
|
||||
"ViewAdmin",
|
||||
],
|
||||
db2: ['ViewAdmin'],
|
||||
},
|
||||
users: [
|
||||
"jon@example.com",
|
||||
"ned@example.com",
|
||||
],
|
||||
users: ['jon@example.com', 'ned@example.com'],
|
||||
},
|
||||
{
|
||||
name: "Marketing",
|
||||
name: 'Marketing',
|
||||
permissions: {
|
||||
db3: [
|
||||
"ReadData",
|
||||
],
|
||||
db3: ['ReadData'],
|
||||
},
|
||||
users: [
|
||||
"jon@example.com",
|
||||
],
|
||||
users: ['jon@example.com'],
|
||||
},
|
||||
]
|
||||
|
||||
|
@ -156,8 +125,8 @@ describe('Presenters', function() {
|
|||
|
||||
const expected = [
|
||||
{
|
||||
name: "jon@example.com",
|
||||
hash: "xxxxx",
|
||||
name: 'jon@example.com',
|
||||
hash: 'xxxxx',
|
||||
permissions: [
|
||||
{
|
||||
name: 'ViewAdmin',
|
||||
|
@ -174,7 +143,7 @@ describe('Presenters', function() {
|
|||
],
|
||||
roles: [
|
||||
{
|
||||
name: "Admin",
|
||||
name: 'Admin',
|
||||
permissions: [
|
||||
{
|
||||
name: 'ViewAdmin',
|
||||
|
@ -183,13 +152,10 @@ describe('Presenters', function() {
|
|||
resources: ['db2'],
|
||||
},
|
||||
],
|
||||
users: [
|
||||
"jon@example.com",
|
||||
"ned@example.com",
|
||||
],
|
||||
users: ['jon@example.com', 'ned@example.com'],
|
||||
},
|
||||
{
|
||||
name: "Marketing",
|
||||
name: 'Marketing',
|
||||
permissions: [
|
||||
{
|
||||
name: 'ReadData',
|
||||
|
@ -198,19 +164,17 @@ describe('Presenters', function() {
|
|||
resources: ['db3'],
|
||||
},
|
||||
],
|
||||
users: [
|
||||
"jon@example.com",
|
||||
],
|
||||
users: ['jon@example.com'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "ned@example.com",
|
||||
hash: "xxxxx",
|
||||
name: 'ned@example.com',
|
||||
hash: 'xxxxx',
|
||||
permissions: [],
|
||||
roles: [
|
||||
{
|
||||
name: "Admin",
|
||||
name: 'Admin',
|
||||
permissions: [
|
||||
{
|
||||
name: 'ViewAdmin',
|
||||
|
@ -219,10 +183,7 @@ describe('Presenters', function() {
|
|||
resources: ['db2'],
|
||||
},
|
||||
],
|
||||
users: [
|
||||
"jon@example.com",
|
||||
"ned@example.com",
|
||||
],
|
||||
users: ['jon@example.com', 'ned@example.com'],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -241,10 +202,12 @@ describe('Presenters', function() {
|
|||
})
|
||||
|
||||
it('sets roles to an empty array if a user has no roles', function() {
|
||||
const users = [{
|
||||
name: "ned@example.com",
|
||||
hash: "xxxxx",
|
||||
}]
|
||||
const users = [
|
||||
{
|
||||
name: 'ned@example.com',
|
||||
hash: 'xxxxx',
|
||||
},
|
||||
]
|
||||
const roles = []
|
||||
|
||||
const actual = buildClusterAccounts(users, roles)
|
||||
|
|
|
@ -5,56 +5,51 @@ import {errorThrown} from 'shared/actions/errors'
|
|||
import {HTTP_FORBIDDEN} from 'shared/constants'
|
||||
|
||||
const errorForbidden = {
|
||||
"data":"",
|
||||
"status":403,
|
||||
"statusText":"Forbidden",
|
||||
"headers":{
|
||||
"date":"Mon, 17 Apr 2017 18:35:34 GMT",
|
||||
"content-length":"0",
|
||||
"x-chronograf-version":"1.2.0-beta8-71-gd875ea4a",
|
||||
"content-type":"text/plain; charset=utf-8"
|
||||
},
|
||||
"config":{
|
||||
"transformRequest":{
|
||||
|
||||
data: '',
|
||||
status: 403,
|
||||
statusText: 'Forbidden',
|
||||
headers: {
|
||||
date: 'Mon, 17 Apr 2017 18:35:34 GMT',
|
||||
'content-length': '0',
|
||||
'x-chronograf-version': '1.2.0-beta8-71-gd875ea4a',
|
||||
'content-type': 'text/plain; charset=utf-8',
|
||||
},
|
||||
config: {
|
||||
transformRequest: {},
|
||||
transformResponse: {},
|
||||
headers: {
|
||||
Accept: 'application/json, text/plain, */*',
|
||||
'Content-Type': 'application/json;charset=utf-8',
|
||||
},
|
||||
timeout: 0,
|
||||
xsrfCookieName: 'XSRF-TOKEN',
|
||||
xsrfHeaderName: 'X-XSRF-TOKEN',
|
||||
maxContentLength: -1,
|
||||
method: 'GET',
|
||||
url: '/chronograf/v1/me',
|
||||
data: '{}',
|
||||
params: {},
|
||||
},
|
||||
request: {},
|
||||
auth: {
|
||||
links: [
|
||||
{
|
||||
name: 'github',
|
||||
label: 'Github',
|
||||
login: '/oauth/github/login',
|
||||
logout: '/oauth/github/logout',
|
||||
callback: '/oauth/github/callback',
|
||||
},
|
||||
"transformResponse":{
|
||||
|
||||
},
|
||||
"headers":{
|
||||
"Accept":"application/json, text/plain, *\/*",
|
||||
"Content-Type":"application/json;charset=utf-8"
|
||||
},
|
||||
"timeout":0,
|
||||
"xsrfCookieName":"XSRF-TOKEN",
|
||||
"xsrfHeaderName":"X-XSRF-TOKEN",
|
||||
"maxContentLength":-1,
|
||||
"method":"GET",
|
||||
"url":"/chronograf/v1/me",
|
||||
"data":"{}",
|
||||
"params":{
|
||||
|
||||
}
|
||||
},
|
||||
"request":{
|
||||
|
||||
},
|
||||
"auth":{
|
||||
"links":[
|
||||
{
|
||||
"name":"github",
|
||||
"label":"Github",
|
||||
"login":"/oauth/github/login",
|
||||
"logout":"/oauth/github/logout",
|
||||
"callback":"/oauth/github/callback"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
describe('Shared.Reducers.errorsReducer', () => {
|
||||
it('should handle ERROR_THROWN', () => {
|
||||
const reducedState = errorsReducer(initialState, errorThrown(errorForbidden))
|
||||
const reducedState = errorsReducer(
|
||||
initialState,
|
||||
errorThrown(errorForbidden)
|
||||
)
|
||||
|
||||
expect(reducedState.error.status).to.equal(HTTP_FORBIDDEN)
|
||||
})
|
||||
|
|
|
@ -1,45 +1,56 @@
|
|||
import reducer from 'shared/reducers/sources'
|
||||
|
||||
import {
|
||||
loadSources,
|
||||
updateSource,
|
||||
addSource,
|
||||
} from 'shared/actions/sources'
|
||||
import {loadSources, updateSource, addSource} from 'shared/actions/sources'
|
||||
|
||||
describe('Shared.Reducers.sources', () => {
|
||||
it('can correctly show default sources when adding a source', () => {
|
||||
let state = []
|
||||
|
||||
state = reducer(state, addSource({
|
||||
id: '1',
|
||||
"default": true,
|
||||
}))
|
||||
state = reducer(
|
||||
state,
|
||||
addSource({
|
||||
id: '1',
|
||||
default: true,
|
||||
})
|
||||
)
|
||||
|
||||
state = reducer(state, addSource({
|
||||
id: '2',
|
||||
"default": true,
|
||||
}))
|
||||
state = reducer(
|
||||
state,
|
||||
addSource({
|
||||
id: '2',
|
||||
default: true,
|
||||
})
|
||||
)
|
||||
|
||||
expect(state.filter((s) => s.default).length).to.equal(1)
|
||||
expect(state.filter(s => s.default).length).to.equal(1)
|
||||
})
|
||||
|
||||
it('can correctly show default sources when updating a source', () => {
|
||||
let state = []
|
||||
|
||||
state = reducer(state, addSource({
|
||||
id: '1',
|
||||
"default": true,
|
||||
}))
|
||||
state = reducer(
|
||||
state,
|
||||
addSource({
|
||||
id: '1',
|
||||
default: true,
|
||||
})
|
||||
)
|
||||
|
||||
state = reducer(state, addSource({
|
||||
id: '2',
|
||||
"default": true,
|
||||
}))
|
||||
state = reducer(
|
||||
state,
|
||||
addSource({
|
||||
id: '2',
|
||||
default: true,
|
||||
})
|
||||
)
|
||||
|
||||
state = reducer(state, updateSource({
|
||||
id: '1',
|
||||
"default": true,
|
||||
}))
|
||||
state = reducer(
|
||||
state,
|
||||
updateSource({
|
||||
id: '1',
|
||||
default: true,
|
||||
})
|
||||
)
|
||||
|
||||
expect(state.find(({id}) => id === '1').default).to.equal(true)
|
||||
expect(state.find(({id}) => id === '2').default).to.equal(false)
|
||||
|
|
|
@ -14,7 +14,7 @@ describe('Formatting helpers', () => {
|
|||
expect(actual).to.equal('0 Bytes')
|
||||
})
|
||||
|
||||
it('converts a raw byte value into it\'s most appropriate unit', () => {
|
||||
it("converts a raw byte value into it's most appropriate unit", () => {
|
||||
expect(formatBytes(1000)).to.equal('1 KB')
|
||||
expect(formatBytes(1000000)).to.equal('1 MB')
|
||||
expect(formatBytes(1000000000)).to.equal('1 GB')
|
||||
|
|
|
@ -4,14 +4,13 @@ describe('timeSeriesToDygraph', () => {
|
|||
it('parses a raw InfluxDB response into a dygraph friendly data format', () => {
|
||||
const influxResponse = [
|
||||
{
|
||||
response:
|
||||
{
|
||||
response: {
|
||||
results: [
|
||||
{
|
||||
series: [
|
||||
{
|
||||
name: "m1",
|
||||
columns: ["time", "f1"],
|
||||
name: 'm1',
|
||||
columns: ['time', 'f1'],
|
||||
values: [[1000, 1], [2000, 2]],
|
||||
},
|
||||
],
|
||||
|
@ -19,8 +18,8 @@ describe('timeSeriesToDygraph', () => {
|
|||
{
|
||||
series: [
|
||||
{
|
||||
name: "m1",
|
||||
columns: ["time", "f2"],
|
||||
name: 'm1',
|
||||
columns: ['time', 'f2'],
|
||||
values: [[2000, 3], [4000, 4]],
|
||||
},
|
||||
],
|
||||
|
@ -33,11 +32,7 @@ describe('timeSeriesToDygraph', () => {
|
|||
const actual = timeSeriesToDygraph(influxResponse)
|
||||
|
||||
const expected = {
|
||||
labels: [
|
||||
'time',
|
||||
`m1.f1`,
|
||||
`m1.f2`,
|
||||
],
|
||||
labels: ['time', `m1.f1`, `m1.f2`],
|
||||
timeSeries: [
|
||||
[new Date(1000), 1, null],
|
||||
[new Date(2000), 2, 3],
|
||||
|
@ -59,14 +54,13 @@ describe('timeSeriesToDygraph', () => {
|
|||
it('can sort numerical timestamps correctly', () => {
|
||||
const influxResponse = [
|
||||
{
|
||||
response:
|
||||
{
|
||||
response: {
|
||||
results: [
|
||||
{
|
||||
series: [
|
||||
{
|
||||
name: "m1",
|
||||
columns: ["time", "f1"],
|
||||
name: 'm1',
|
||||
columns: ['time', 'f1'],
|
||||
values: [[100, 1], [3000, 3], [200, 2]],
|
||||
},
|
||||
],
|
||||
|
@ -76,19 +70,11 @@ describe('timeSeriesToDygraph', () => {
|
|||
},
|
||||
]
|
||||
|
||||
|
||||
const actual = timeSeriesToDygraph(influxResponse)
|
||||
|
||||
const expected = {
|
||||
labels: [
|
||||
'time',
|
||||
'm1.f1',
|
||||
],
|
||||
timeSeries: [
|
||||
[new Date(100), 1],
|
||||
[new Date(200), 2],
|
||||
[new Date(3000), 3],
|
||||
],
|
||||
labels: ['time', 'm1.f1'],
|
||||
timeSeries: [[new Date(100), 1], [new Date(200), 2], [new Date(3000), 3]],
|
||||
}
|
||||
|
||||
expect(actual.timeSeries).to.deep.equal(expected.timeSeries)
|
||||
|
@ -97,14 +83,13 @@ describe('timeSeriesToDygraph', () => {
|
|||
it('can parse multiple responses into two axes', () => {
|
||||
const influxResponse = [
|
||||
{
|
||||
response:
|
||||
{
|
||||
response: {
|
||||
results: [
|
||||
{
|
||||
series: [
|
||||
{
|
||||
name: "m1",
|
||||
columns: ["time", "f1"],
|
||||
name: 'm1',
|
||||
columns: ['time', 'f1'],
|
||||
values: [[1000, 1], [2000, 2]],
|
||||
},
|
||||
],
|
||||
|
@ -112,8 +97,8 @@ describe('timeSeriesToDygraph', () => {
|
|||
{
|
||||
series: [
|
||||
{
|
||||
name: "m1",
|
||||
columns: ["time", "f2"],
|
||||
name: 'm1',
|
||||
columns: ['time', 'f2'],
|
||||
values: [[2000, 3], [4000, 4]],
|
||||
},
|
||||
],
|
||||
|
@ -122,14 +107,13 @@ describe('timeSeriesToDygraph', () => {
|
|||
},
|
||||
},
|
||||
{
|
||||
response:
|
||||
{
|
||||
response: {
|
||||
results: [
|
||||
{
|
||||
series: [
|
||||
{
|
||||
name: "m3",
|
||||
columns: ["time", "f3"],
|
||||
name: 'm3',
|
||||
columns: ['time', 'f3'],
|
||||
values: [[1000, 1], [2000, 2]],
|
||||
},
|
||||
],
|
||||
|
@ -159,14 +143,13 @@ describe('timeSeriesToDygraph', () => {
|
|||
it('can parse multiple responses with the same field and measurement', () => {
|
||||
const influxResponse = [
|
||||
{
|
||||
response:
|
||||
{
|
||||
response: {
|
||||
results: [
|
||||
{
|
||||
series: [
|
||||
{
|
||||
name: "m1",
|
||||
columns: ["time", "f1"],
|
||||
name: 'm1',
|
||||
columns: ['time', 'f1'],
|
||||
values: [[1000, 1], [2000, 2]],
|
||||
},
|
||||
],
|
||||
|
@ -175,14 +158,13 @@ describe('timeSeriesToDygraph', () => {
|
|||
},
|
||||
},
|
||||
{
|
||||
response:
|
||||
{
|
||||
response: {
|
||||
results: [
|
||||
{
|
||||
series: [
|
||||
{
|
||||
name: "m1",
|
||||
columns: ["time", "f1"],
|
||||
name: 'm1',
|
||||
columns: ['time', 'f1'],
|
||||
values: [[2000, 3], [4000, 4]],
|
||||
},
|
||||
],
|
||||
|
@ -195,11 +177,7 @@ describe('timeSeriesToDygraph', () => {
|
|||
const actual = timeSeriesToDygraph(influxResponse)
|
||||
|
||||
const expected = {
|
||||
labels: [
|
||||
'time',
|
||||
`m1.f1`,
|
||||
`m1.f1`,
|
||||
],
|
||||
labels: ['time', `m1.f1`, `m1.f1`],
|
||||
timeSeries: [
|
||||
[new Date(1000), 1, null],
|
||||
[new Date(2000), 2, 3],
|
||||
|
@ -218,14 +196,13 @@ describe('timeSeriesToDygraph', () => {
|
|||
it('it does not use multiple axes if being used for the DataExplorer', () => {
|
||||
const influxResponse = [
|
||||
{
|
||||
response:
|
||||
{
|
||||
response: {
|
||||
results: [
|
||||
{
|
||||
series: [
|
||||
{
|
||||
name: "m1",
|
||||
columns: ["time", "f1"],
|
||||
name: 'm1',
|
||||
columns: ['time', 'f1'],
|
||||
values: [[1000, 1], [2000, 2]],
|
||||
},
|
||||
],
|
||||
|
@ -234,14 +211,13 @@ describe('timeSeriesToDygraph', () => {
|
|||
},
|
||||
},
|
||||
{
|
||||
response:
|
||||
{
|
||||
response: {
|
||||
results: [
|
||||
{
|
||||
series: [
|
||||
{
|
||||
name: "m1",
|
||||
columns: ["time", "f2"],
|
||||
name: 'm1',
|
||||
columns: ['time', 'f2'],
|
||||
values: [[2000, 3], [4000, 4]],
|
||||
},
|
||||
],
|
||||
|
@ -252,7 +228,11 @@ describe('timeSeriesToDygraph', () => {
|
|||
]
|
||||
|
||||
const isInDataExplorer = true
|
||||
const actual = timeSeriesToDygraph(influxResponse, undefined, isInDataExplorer)
|
||||
const actual = timeSeriesToDygraph(
|
||||
influxResponse,
|
||||
undefined,
|
||||
isInDataExplorer
|
||||
)
|
||||
|
||||
const expected = {}
|
||||
|
||||
|
@ -262,14 +242,13 @@ describe('timeSeriesToDygraph', () => {
|
|||
it('parses a raw InfluxDB response into a dygraph friendly data format', () => {
|
||||
const influxResponse = [
|
||||
{
|
||||
response:
|
||||
{
|
||||
response: {
|
||||
results: [
|
||||
{
|
||||
series: [
|
||||
{
|
||||
name: "mb",
|
||||
columns: ["time", "f1"],
|
||||
name: 'mb',
|
||||
columns: ['time', 'f1'],
|
||||
values: [[1000, 1], [2000, 2]],
|
||||
},
|
||||
],
|
||||
|
@ -277,8 +256,8 @@ describe('timeSeriesToDygraph', () => {
|
|||
{
|
||||
series: [
|
||||
{
|
||||
name: "ma",
|
||||
columns: ["time", "f1"],
|
||||
name: 'ma',
|
||||
columns: ['time', 'f1'],
|
||||
values: [[1000, 1], [2000, 2]],
|
||||
},
|
||||
],
|
||||
|
@ -286,8 +265,8 @@ describe('timeSeriesToDygraph', () => {
|
|||
{
|
||||
series: [
|
||||
{
|
||||
name: "mc",
|
||||
columns: ["time", "f2"],
|
||||
name: 'mc',
|
||||
columns: ['time', 'f2'],
|
||||
values: [[2000, 3], [4000, 4]],
|
||||
},
|
||||
],
|
||||
|
@ -295,8 +274,8 @@ describe('timeSeriesToDygraph', () => {
|
|||
{
|
||||
series: [
|
||||
{
|
||||
name: "mc",
|
||||
columns: ["time", "f1"],
|
||||
name: 'mc',
|
||||
columns: ['time', 'f1'],
|
||||
values: [[2000, 3], [4000, 4]],
|
||||
},
|
||||
],
|
||||
|
@ -308,13 +287,7 @@ describe('timeSeriesToDygraph', () => {
|
|||
|
||||
const actual = timeSeriesToDygraph(influxResponse)
|
||||
|
||||
const expected = [
|
||||
'time',
|
||||
`ma.f1`,
|
||||
`mb.f1`,
|
||||
`mc.f1`,
|
||||
`mc.f2`,
|
||||
]
|
||||
const expected = ['time', `ma.f1`, `mb.f1`, `mc.f1`, `mc.f2`]
|
||||
|
||||
expect(actual.labels).to.deep.equal(expected)
|
||||
})
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
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 RolesTable from 'src/admin/components/RolesTable'
|
||||
import QueriesPage from 'src/admin/containers/QueriesPage'
|
||||
|
@ -97,9 +91,9 @@ const AdminTabs = ({
|
|||
{tabs.map((t, i) => <Tab key={tabs[i].type}>{tabs[i].type}</Tab>)}
|
||||
</TabList>
|
||||
<TabPanels customClass="col-md-10 admin-tabs--content">
|
||||
{tabs.map((t, i) => (
|
||||
{tabs.map((t, i) =>
|
||||
<TabPanel key={tabs[i].type}>{t.component}</TabPanel>
|
||||
))}
|
||||
)}
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
)
|
||||
|
|
|
@ -41,7 +41,7 @@ const DatabaseManager = ({
|
|||
</button>
|
||||
</div>
|
||||
<div className="panel-body">
|
||||
{databases.map(db => (
|
||||
{databases.map(db =>
|
||||
<DatabaseTable
|
||||
key={db.links.self}
|
||||
database={db}
|
||||
|
@ -63,7 +63,7 @@ const DatabaseManager = ({
|
|||
onRemoveRetentionPolicy={onRemoveRetentionPolicy}
|
||||
onDeleteRetentionPolicy={onDeleteRetentionPolicy}
|
||||
/>
|
||||
))}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -54,7 +54,7 @@ class DatabaseRow extends Component {
|
|||
defaultValue={name}
|
||||
placeholder="Name this RP"
|
||||
onKeyDown={e => this.handleKeyDown(e, database)}
|
||||
ref={r => this.name = r}
|
||||
ref={r => (this.name = r)}
|
||||
autoFocus={true}
|
||||
spellCheck={false}
|
||||
autoComplete={false}
|
||||
|
@ -69,7 +69,7 @@ class DatabaseRow extends Component {
|
|||
defaultValue={formattedDuration}
|
||||
placeholder="How long should Data last"
|
||||
onKeyDown={e => this.handleKeyDown(e, database)}
|
||||
ref={r => this.duration = r}
|
||||
ref={r => (this.duration = r)}
|
||||
autoFocus={!isNew}
|
||||
spellCheck={false}
|
||||
autoComplete={false}
|
||||
|
@ -85,7 +85,7 @@ class DatabaseRow extends Component {
|
|||
defaultValue={replication || 1}
|
||||
placeholder="# of Nodes"
|
||||
onKeyDown={e => this.handleKeyDown(e, database)}
|
||||
ref={r => this.replication = r}
|
||||
ref={r => (this.replication = r)}
|
||||
spellCheck={false}
|
||||
autoComplete={false}
|
||||
/>
|
||||
|
|
|
@ -111,7 +111,7 @@ const Header = ({
|
|||
)
|
||||
}
|
||||
|
||||
const EditHeader = ({database, onEdit, onKeyDown, onConfirm, onCancel}) => (
|
||||
const EditHeader = ({database, onEdit, onKeyDown, onConfirm, onCancel}) =>
|
||||
<div className="db-manager-header db-manager-header--edit">
|
||||
<input
|
||||
className="form-control input-sm"
|
||||
|
@ -127,7 +127,6 @@ const EditHeader = ({database, onEdit, onKeyDown, onConfirm, onCancel}) => (
|
|||
/>
|
||||
<ConfirmButtons item={database} onConfirm={onConfirm} onCancel={onCancel} />
|
||||
</div>
|
||||
)
|
||||
|
||||
const {func, shape, bool} = PropTypes
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
|
||||
const EmptyRow = ({tableName}) => (
|
||||
const EmptyRow = ({tableName}) =>
|
||||
<tr className="table-empty-state">
|
||||
<th colSpan="5">
|
||||
<p>You don't have any {tableName},<br />why not create one?</p>
|
||||
</th>
|
||||
</tr>
|
||||
)
|
||||
|
||||
const {string} = PropTypes
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import React, {PropTypes} from 'react'
|
|||
import QueryRow from 'src/admin/components/QueryRow'
|
||||
import {QUERIES_TABLE} from 'src/admin/constants/tableSizing'
|
||||
|
||||
const QueriesTable = ({queries, onKillQuery}) => (
|
||||
const QueriesTable = ({queries, onKillQuery}) =>
|
||||
<div>
|
||||
<div className="panel panel-default">
|
||||
<div className="panel-body">
|
||||
|
@ -21,15 +21,14 @@ const QueriesTable = ({queries, onKillQuery}) => (
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{queries.map(q => (
|
||||
{queries.map(q =>
|
||||
<QueryRow key={q.id} query={q} onKill={onKillQuery} />
|
||||
))}
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, func, shape} = PropTypes
|
||||
|
||||
|
|
|
@ -89,12 +89,9 @@ const RoleRow = ({
|
|||
onApply={handleUpdateUsers}
|
||||
buttonSize="btn-xs"
|
||||
buttonColor="btn-primary"
|
||||
customClass={classnames(
|
||||
`dropdown-${ROLES_TABLE.colUsers}`,
|
||||
{
|
||||
'admin-table--multi-select-empty': !users.length,
|
||||
}
|
||||
)}
|
||||
customClass={classnames(`dropdown-${ROLES_TABLE.colUsers}`, {
|
||||
'admin-table--multi-select-empty': !users.length,
|
||||
})}
|
||||
/>
|
||||
: null}
|
||||
</td>
|
||||
|
|
|
@ -16,7 +16,7 @@ const RolesTable = ({
|
|||
onFilter,
|
||||
onUpdateRoleUsers,
|
||||
onUpdateRolePermissions,
|
||||
}) => (
|
||||
}) =>
|
||||
<div className="panel panel-default">
|
||||
<FilterBar
|
||||
type="roles"
|
||||
|
@ -38,7 +38,7 @@ const RolesTable = ({
|
|||
{roles.length
|
||||
? roles
|
||||
.filter(r => !r.hidden)
|
||||
.map(role => (
|
||||
.map(role =>
|
||||
<RoleRow
|
||||
key={role.links.self}
|
||||
allUsers={allUsers}
|
||||
|
@ -53,13 +53,12 @@ const RolesTable = ({
|
|||
isEditing={role.isEditing}
|
||||
isNew={role.isNew}
|
||||
/>
|
||||
))
|
||||
)
|
||||
: <EmptyRow tableName={'Roles'} />}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, bool, func, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -93,12 +93,9 @@ const UserRow = ({
|
|||
onApply={handleUpdateRoles}
|
||||
buttonSize="btn-xs"
|
||||
buttonColor="btn-primary"
|
||||
customClass={classnames(
|
||||
`dropdown-${USERS_TABLE.colRoles}`,
|
||||
{
|
||||
'admin-table--multi-select-empty': !roles.length,
|
||||
}
|
||||
)}
|
||||
customClass={classnames(`dropdown-${USERS_TABLE.colRoles}`, {
|
||||
'admin-table--multi-select-empty': !roles.length,
|
||||
})}
|
||||
/>
|
||||
</td>
|
||||
: null}
|
||||
|
|
|
@ -19,7 +19,7 @@ const UsersTable = ({
|
|||
onUpdatePermissions,
|
||||
onUpdateRoles,
|
||||
onUpdatePassword,
|
||||
}) => (
|
||||
}) =>
|
||||
<div className="panel panel-default">
|
||||
<FilterBar
|
||||
type="users"
|
||||
|
@ -42,7 +42,7 @@ const UsersTable = ({
|
|||
{users.length
|
||||
? users
|
||||
.filter(u => !u.hidden)
|
||||
.map(user => (
|
||||
.map(user =>
|
||||
<UserRow
|
||||
key={user.links.self}
|
||||
user={user}
|
||||
|
@ -59,13 +59,12 @@ const UsersTable = ({
|
|||
onUpdateRoles={onUpdateRoles}
|
||||
onUpdatePassword={onUpdatePassword}
|
||||
/>
|
||||
))
|
||||
)
|
||||
: <EmptyRow tableName={'Users'} />}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, bool, func, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ export default function admin(state = initialState, action) {
|
|||
const {database} = action.payload
|
||||
const databases = state.databases.map(
|
||||
db =>
|
||||
(db.links.self === database.links.self
|
||||
db.links.self === database.links.self
|
||||
? {
|
||||
...database,
|
||||
retentionPolicies: [
|
||||
|
@ -70,7 +70,7 @@ export default function admin(state = initialState, action) {
|
|||
...database.retentionPolicies,
|
||||
],
|
||||
}
|
||||
: db)
|
||||
: db
|
||||
)
|
||||
|
||||
return {...state, databases}
|
||||
|
@ -112,15 +112,15 @@ export default function admin(state = initialState, action) {
|
|||
const newState = {
|
||||
databases: state.databases.map(
|
||||
db =>
|
||||
(db.links.self === database.links.self
|
||||
db.links.self === database.links.self
|
||||
? {
|
||||
...db,
|
||||
retentionPolicies: db.retentionPolicies.map(
|
||||
rp =>
|
||||
(rp.links.self === stale.links.self ? {...synced} : rp)
|
||||
rp.links.self === stale.links.self ? {...synced} : rp
|
||||
),
|
||||
}
|
||||
: db)
|
||||
: db
|
||||
),
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ export default function admin(state = initialState, action) {
|
|||
const newState = {
|
||||
databases: state.databases.map(
|
||||
db =>
|
||||
(db.links.self === database.links.self ? {...db, ...updates} : db)
|
||||
db.links.self === database.links.self ? {...db, ...updates} : db
|
||||
),
|
||||
}
|
||||
|
||||
|
@ -165,17 +165,17 @@ export default function admin(state = initialState, action) {
|
|||
const newState = {
|
||||
databases: state.databases.map(
|
||||
db =>
|
||||
(db.links.self === database.links.self
|
||||
db.links.self === database.links.self
|
||||
? {
|
||||
...db,
|
||||
retentionPolicies: db.retentionPolicies.map(
|
||||
rp =>
|
||||
(rp.links.self === retentionPolicy.links.self
|
||||
rp.links.self === retentionPolicy.links.self
|
||||
? {...rp, ...updates}
|
||||
: rp)
|
||||
: rp
|
||||
),
|
||||
}
|
||||
: db)
|
||||
: db
|
||||
),
|
||||
}
|
||||
|
||||
|
@ -216,14 +216,14 @@ export default function admin(state = initialState, action) {
|
|||
const newState = {
|
||||
databases: state.databases.map(
|
||||
db =>
|
||||
(db.links.self === database.links.self
|
||||
db.links.self === database.links.self
|
||||
? {
|
||||
...db,
|
||||
retentionPolicies: db.retentionPolicies.filter(
|
||||
rp => rp.links.self !== retentionPolicy.links.self
|
||||
),
|
||||
}
|
||||
: db)
|
||||
: db
|
||||
),
|
||||
}
|
||||
|
||||
|
@ -235,9 +235,7 @@ export default function admin(state = initialState, action) {
|
|||
const newState = {
|
||||
databases: state.databases.map(
|
||||
db =>
|
||||
(db.links.self === database.links.self
|
||||
? {...db, deleteCode: ''}
|
||||
: db)
|
||||
db.links.self === database.links.self ? {...db, deleteCode: ''} : db
|
||||
),
|
||||
}
|
||||
|
||||
|
|
|
@ -17,12 +17,12 @@ const Login = ({authData: {auth}}) => {
|
|||
<h1 className="auth-text-logo">Chronograf</h1>
|
||||
<p><strong>{VERSION}</strong> / Time-Series Data Visualization</p>
|
||||
{auth.links &&
|
||||
auth.links.map(({name, login, label}) => (
|
||||
auth.links.map(({name, login, label}) =>
|
||||
<a key={name} className="btn btn-primary" href={login}>
|
||||
<span className={`icon ${name}`} />
|
||||
Login with {label}
|
||||
</a>
|
||||
))}
|
||||
)}
|
||||
</div>
|
||||
<p className="auth-credits">
|
||||
Made by <span className="icon cubo-uniform" />InfluxData
|
||||
|
|
|
@ -19,7 +19,7 @@ const OverlayControls = props => {
|
|||
<div className="overlay-controls--right">
|
||||
<p>Visualization Type:</p>
|
||||
<ul className="nav nav-tablist nav-tablist-sm">
|
||||
{graphTypes.map(graphType => (
|
||||
{graphTypes.map(graphType =>
|
||||
<li
|
||||
key={graphType.type}
|
||||
className={classnames({
|
||||
|
@ -29,7 +29,7 @@ const OverlayControls = props => {
|
|||
>
|
||||
{graphType.menuOption}
|
||||
</li>
|
||||
))}
|
||||
)}
|
||||
</ul>
|
||||
<ConfirmButtons
|
||||
onCancel={onCancel}
|
||||
|
|
|
@ -10,7 +10,7 @@ const TemplateControlBar = ({
|
|||
onSelectTemplate,
|
||||
onOpenTemplateManager,
|
||||
isOpen,
|
||||
}) => (
|
||||
}) =>
|
||||
<div className={classnames('template-control-bar', {show: isOpen})}>
|
||||
<div className="template-control--container">
|
||||
<div className="template-control--controls">
|
||||
|
@ -53,7 +53,6 @@ const TemplateControlBar = ({
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, bool, func, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -2,8 +2,7 @@ import React, {Component, PropTypes} from 'react'
|
|||
import classnames from 'classnames'
|
||||
import uuid from 'node-uuid'
|
||||
|
||||
import TemplateVariableTable
|
||||
from 'src/dashboards/components/TemplateVariableTable'
|
||||
import TemplateVariableTable from 'src/dashboards/components/TemplateVariableTable'
|
||||
|
||||
import {TEMPLATE_VARIABLE_TYPES} from 'src/dashboards/constants'
|
||||
|
||||
|
@ -19,7 +18,7 @@ const TemplateVariableManager = ({
|
|||
onDelete,
|
||||
tempVarAlreadyExists,
|
||||
isEdited,
|
||||
}) => (
|
||||
}) =>
|
||||
<div className="template-variable-manager">
|
||||
<div className="template-variable-manager--header">
|
||||
<div className="page-header__left">
|
||||
|
@ -59,7 +58,6 @@ const TemplateVariableManager = ({
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
class TemplateVariableManagerWrapper extends Component {
|
||||
constructor(props) {
|
||||
|
|
|
@ -9,18 +9,14 @@ import classnames from 'classnames'
|
|||
|
||||
import Dropdown from 'shared/components/Dropdown'
|
||||
import DeleteConfirmButtons from 'shared/components/DeleteConfirmButtons'
|
||||
import TemplateQueryBuilder
|
||||
from 'src/dashboards/components/TemplateQueryBuilder'
|
||||
import TemplateQueryBuilder from 'src/dashboards/components/TemplateQueryBuilder'
|
||||
|
||||
import {
|
||||
runTemplateVariableQuery as runTemplateVariableQueryAJAX,
|
||||
} from 'src/dashboards/apis'
|
||||
import {runTemplateVariableQuery as runTemplateVariableQueryAJAX} from 'src/dashboards/apis'
|
||||
|
||||
import parsers from 'shared/parsing'
|
||||
|
||||
import {TEMPLATE_TYPES} from 'src/dashboards/constants'
|
||||
import generateTemplateVariableQuery
|
||||
from 'src/dashboards/utils/templateVariableQueryGenerator'
|
||||
import generateTemplateVariableQuery from 'src/dashboards/utils/templateVariableQueryGenerator'
|
||||
|
||||
import {errorThrown as errorThrownAction} from 'shared/actions/errors'
|
||||
import {publishAutoDismissingNotification} from 'shared/dispatchers'
|
||||
|
@ -117,7 +113,7 @@ const TemplateVariableRow = ({
|
|||
onSubmit,
|
||||
onDelete,
|
||||
onErrorThrown,
|
||||
}) => (
|
||||
}) =>
|
||||
<form
|
||||
className={classnames('template-variable-manager--table-row', {
|
||||
editing: isEditing,
|
||||
|
@ -178,7 +174,6 @@ const TemplateVariableRow = ({
|
|||
/>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
|
||||
const TableInput = ({
|
||||
name,
|
||||
|
|
|
@ -9,7 +9,7 @@ const TemplateVariableTable = ({
|
|||
onRunQueryFailure,
|
||||
onDelete,
|
||||
tempVarAlreadyExists,
|
||||
}) => (
|
||||
}) =>
|
||||
<div className="template-variable-manager--table">
|
||||
{templates.length
|
||||
? <div className="template-variable-manager--table-container">
|
||||
|
@ -20,7 +20,7 @@ const TemplateVariableTable = ({
|
|||
<div className="tvm--col-4" />
|
||||
</div>
|
||||
<div className="template-variable-manager--table-rows">
|
||||
{templates.map(t => (
|
||||
{templates.map(t =>
|
||||
<TemplateVariableRow
|
||||
key={t.id}
|
||||
source={source}
|
||||
|
@ -30,7 +30,7 @@ const TemplateVariableTable = ({
|
|||
onDelete={onDelete}
|
||||
tempVarAlreadyExists={tempVarAlreadyExists}
|
||||
/>
|
||||
))}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
: <div className="generic-empty-state">
|
||||
|
@ -39,7 +39,6 @@ const TemplateVariableTable = ({
|
|||
</h4>
|
||||
</div>}
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, bool, func, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -68,7 +68,8 @@ export const TEMPLATE_VARIABLE_QUERIES = {
|
|||
measurements: 'SHOW MEASUREMENTS ON :database:',
|
||||
fieldKeys: 'SHOW FIELD KEYS ON :database: FROM :measurement:',
|
||||
tagKeys: 'SHOW TAG KEYS ON :database: FROM :measurement:',
|
||||
tagValues: 'SHOW TAG VALUES ON :database: FROM :measurement: WITH KEY=:tagKey:',
|
||||
tagValues:
|
||||
'SHOW TAG VALUES ON :database: FROM :measurement: WITH KEY=:tagKey:',
|
||||
}
|
||||
|
||||
export const MATCH_INCOMPLETE_TEMPLATES = /:[\w-]*/g
|
||||
|
|
|
@ -10,8 +10,7 @@ import CellEditorOverlay from 'src/dashboards/components/CellEditorOverlay'
|
|||
import DashboardHeader from 'src/dashboards/components/DashboardHeader'
|
||||
import DashboardHeaderEdit from 'src/dashboards/components/DashboardHeaderEdit'
|
||||
import Dashboard from 'src/dashboards/components/Dashboard'
|
||||
import TemplateVariableManager
|
||||
from 'src/dashboards/components/TemplateVariableManager'
|
||||
import TemplateVariableManager from 'src/dashboards/components/TemplateVariableManager'
|
||||
|
||||
import {errorThrown as errorThrownAction} from 'shared/actions/errors'
|
||||
|
||||
|
@ -257,8 +256,8 @@ class DashboardPage extends Component {
|
|||
],
|
||||
}
|
||||
|
||||
const templatesIncludingDashTime = (dashboard &&
|
||||
dashboard.templates.concat(dashboardTime)) || []
|
||||
const templatesIncludingDashTime =
|
||||
(dashboard && dashboard.templates.concat(dashboardTime)) || []
|
||||
|
||||
const {selectedCell, isEditMode, isTemplating} = this.state
|
||||
|
||||
|
@ -311,13 +310,13 @@ class DashboardPage extends Component {
|
|||
showTemplateControlBar={showTemplateControlBar}
|
||||
>
|
||||
{dashboards
|
||||
? dashboards.map((d, i) => (
|
||||
? dashboards.map((d, i) =>
|
||||
<li className="dropdown-item" key={i}>
|
||||
<Link to={`/sources/${sourceID}/dashboards/${d.id}`}>
|
||||
{d.name}
|
||||
</Link>
|
||||
</li>
|
||||
))
|
||||
)
|
||||
: null}
|
||||
</DashboardHeader>}
|
||||
{dashboard
|
||||
|
|
|
@ -97,7 +97,7 @@ const DashboardsPage = React.createClass({
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{dashboards.map(dashboard => (
|
||||
{dashboards.map(dashboard =>
|
||||
<tr key={dashboard.id} className="">
|
||||
<td className="monotype">
|
||||
<Link
|
||||
|
@ -112,7 +112,7 @@ const DashboardsPage = React.createClass({
|
|||
buttonSize="btn-xs"
|
||||
/>
|
||||
</tr>
|
||||
))}
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
: <div className="generic-empty-state">
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import {
|
||||
writeLineProtocol as writeLineProtocolAJAX,
|
||||
} from 'src/data_explorer/apis'
|
||||
import {writeLineProtocol as writeLineProtocolAJAX} from 'src/data_explorer/apis'
|
||||
|
||||
import {errorThrown} from 'shared/actions/errors'
|
||||
import {publishAutoDismissingNotification} from 'shared/dispatchers'
|
||||
|
|
|
@ -66,9 +66,16 @@ const DatabaseDropdown = React.createClass({
|
|||
return (
|
||||
<Dropdown
|
||||
className="dropdown-160 query-builder--db-dropdown"
|
||||
items={namespaces.map(n => ({...n, text: `${n.database}.${n.retentionPolicy}`}))}
|
||||
items={namespaces.map(n => ({
|
||||
...n,
|
||||
text: `${n.database}.${n.retentionPolicy}`,
|
||||
}))}
|
||||
onChoose={onChooseNamespace}
|
||||
selected={(query.database && query.retentionPolicy) ? `${query.database}.${query.retentionPolicy}` : 'Choose a DB & RP'}
|
||||
selected={
|
||||
query.database && query.retentionPolicy
|
||||
? `${query.database}.${query.retentionPolicy}`
|
||||
: 'Choose a DB & RP'
|
||||
}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
|
||||
import FieldListItem from 'src/data_explorer/components/FieldListItem'
|
||||
import GroupByTimeDropdown
|
||||
from 'src/data_explorer/components/GroupByTimeDropdown'
|
||||
import GroupByTimeDropdown from 'src/data_explorer/components/GroupByTimeDropdown'
|
||||
import FancyScrollbar from 'shared/components/FancyScrollbar'
|
||||
|
||||
import {showFieldKeys} from 'shared/apis/metaQuery'
|
||||
|
|
|
@ -69,7 +69,12 @@ const QueryMaker = React.createClass({
|
|||
render() {
|
||||
const {height, top, layout} = this.props
|
||||
return (
|
||||
<div className={classnames('query-maker', {'query-maker--panel': layout === 'panel'})} style={{height, top}}>
|
||||
<div
|
||||
className={classnames('query-maker', {
|
||||
'query-maker--panel': layout === 'panel',
|
||||
})}
|
||||
style={{height, top}}
|
||||
>
|
||||
{this.renderQueryTabList()}
|
||||
{this.renderQueryBuilder()}
|
||||
</div>
|
||||
|
@ -77,7 +82,14 @@ const QueryMaker = React.createClass({
|
|||
},
|
||||
|
||||
renderQueryBuilder() {
|
||||
const {timeRange, actions, source, templates, layout, isInDataExplorer} = this.props
|
||||
const {
|
||||
timeRange,
|
||||
actions,
|
||||
source,
|
||||
templates,
|
||||
layout,
|
||||
isInDataExplorer,
|
||||
} = this.props
|
||||
const query = this.getActiveQuery()
|
||||
|
||||
if (!query) {
|
||||
|
@ -145,8 +157,8 @@ const QueryMaker = React.createClass({
|
|||
onDelete={onDeleteQuery}
|
||||
queryTabText={
|
||||
q.rawText ||
|
||||
buildInfluxQLQuery(timeRange, q) ||
|
||||
`Query ${i + 1}`
|
||||
buildInfluxQLQuery(timeRange, q) ||
|
||||
`Query ${i + 1}`
|
||||
}
|
||||
/>
|
||||
)
|
||||
|
|
|
@ -153,7 +153,7 @@ const ChronoTable = React.createClass({
|
|||
<div style={{width: '100%', height: '100%', position: 'relative'}}>
|
||||
{series.length < maximumTabsCount
|
||||
? <div className="table--tabs">
|
||||
{series.map(({name}, i) => (
|
||||
{series.map(({name}, i) =>
|
||||
<TabItem
|
||||
isActive={i === activeSeriesIndex}
|
||||
key={i}
|
||||
|
@ -161,7 +161,7 @@ const ChronoTable = React.createClass({
|
|||
index={i}
|
||||
onClickTab={this.handleClickTab}
|
||||
/>
|
||||
))}
|
||||
)}
|
||||
</div>
|
||||
: <Dropdown
|
||||
className="dropdown-160 table--tabs-dropdown"
|
||||
|
@ -192,12 +192,11 @@ const ChronoTable = React.createClass({
|
|||
key={columnName}
|
||||
columnKey={columnName}
|
||||
header={<Cell>{columnName}</Cell>}
|
||||
cell={({rowIndex}) => (
|
||||
cell={({rowIndex}) =>
|
||||
<CustomCell
|
||||
columnName={columnName}
|
||||
data={values[rowIndex][colIndex]}
|
||||
/>
|
||||
)}
|
||||
/>}
|
||||
width={columnWidths[columnName] || width}
|
||||
minWidth={minWidth}
|
||||
/>
|
||||
|
@ -210,14 +209,13 @@ const ChronoTable = React.createClass({
|
|||
},
|
||||
})
|
||||
|
||||
const TabItem = ({name, index, onClickTab, isActive}) => (
|
||||
const TabItem = ({name, index, onClickTab, isActive}) =>
|
||||
<div
|
||||
className={classnames('table--tab', {active: isActive})}
|
||||
onClick={() => onClickTab(index)}
|
||||
>
|
||||
{name}
|
||||
</div>
|
||||
)
|
||||
|
||||
TabItem.propTypes = {
|
||||
name: string,
|
||||
|
|
|
@ -2,11 +2,11 @@ import React, {PropTypes} from 'react'
|
|||
import classnames from 'classnames'
|
||||
import _ from 'lodash'
|
||||
|
||||
const VisHeader = ({views, view, onToggleView, name}) => (
|
||||
const VisHeader = ({views, view, onToggleView, name}) =>
|
||||
<div className="graph-heading">
|
||||
{views.length
|
||||
? <ul className="nav nav-tablist nav-tablist-sm">
|
||||
{views.map(v => (
|
||||
{views.map(v =>
|
||||
<li
|
||||
key={v}
|
||||
onClick={() => onToggleView(v)}
|
||||
|
@ -14,12 +14,11 @@ const VisHeader = ({views, view, onToggleView, name}) => (
|
|||
>
|
||||
{_.upperFirst(v)}
|
||||
</li>
|
||||
))}
|
||||
)}
|
||||
</ul>
|
||||
: null}
|
||||
<div className="graph-title">{name}</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, func, string} = PropTypes
|
||||
|
||||
|
|
|
@ -34,7 +34,8 @@ export const QUERY_TEMPLATES = [
|
|||
},
|
||||
{
|
||||
text: 'Show Tag Values',
|
||||
query: 'SHOW TAG VALUES ON "db_name" FROM "measurement_name" WITH KEY = "tag_key"',
|
||||
query:
|
||||
'SHOW TAG VALUES ON "db_name" FROM "measurement_name" WITH KEY = "tag_key"',
|
||||
},
|
||||
{text: `${SEPARATOR}`},
|
||||
{
|
||||
|
@ -43,7 +44,8 @@ export const QUERY_TEMPLATES = [
|
|||
},
|
||||
{
|
||||
text: 'Create Retention Policy',
|
||||
query: 'CREATE RETENTION POLICY "rp_name" ON "db_name" DURATION 30d REPLICATION 1 DEFAULT',
|
||||
query:
|
||||
'CREATE RETENTION POLICY "rp_name" ON "db_name" DURATION 30d REPLICATION 1 DEFAULT',
|
||||
},
|
||||
{
|
||||
text: 'Drop Retention Policy',
|
||||
|
@ -56,7 +58,8 @@ export const QUERY_TEMPLATES = [
|
|||
},
|
||||
{
|
||||
text: 'Create Continuous Query',
|
||||
query: 'CREATE CONTINUOUS QUERY "cq_name" ON "db_name" BEGIN SELECT min("field") INTO "target_measurement" FROM "current_measurement" GROUP BY time(30m) END',
|
||||
query:
|
||||
'CREATE CONTINUOUS QUERY "cq_name" ON "db_name" BEGIN SELECT min("field") INTO "target_measurement" FROM "current_measurement" GROUP BY time(30m) END',
|
||||
},
|
||||
{
|
||||
text: 'Drop Continuous Query',
|
||||
|
@ -70,7 +73,8 @@ export const QUERY_TEMPLATES = [
|
|||
},
|
||||
{
|
||||
text: 'Create Admin User',
|
||||
query: 'CREATE USER "username" WITH PASSWORD \'password\' WITH ALL PRIVILEGES',
|
||||
query:
|
||||
'CREATE USER "username" WITH PASSWORD \'password\' WITH ALL PRIVILEGES',
|
||||
},
|
||||
{text: 'Drop User', query: 'DROP USER "username"'},
|
||||
{text: `${SEPARATOR}`},
|
||||
|
|
|
@ -231,9 +231,9 @@ class AlertTabs extends Component {
|
|||
{tabs.map((t, i) => <Tab key={tabs[i].type}>{tabs[i].type}</Tab>)}
|
||||
</TabList>
|
||||
<TabPanels customClass="config-endpoint--tab-contents">
|
||||
{tabs.map((t, i) => (
|
||||
{tabs.map((t, i) =>
|
||||
<TabPanel key={tabs[i].type}>{t.component}</TabPanel>
|
||||
))}
|
||||
)}
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
</div>
|
||||
|
|
|
@ -129,7 +129,8 @@ class KapacitorForm extends Component {
|
|||
<div className="panel-body">
|
||||
<div className="generic-empty-state">
|
||||
<h4 className="no-user-select">
|
||||
Connect to an active Kapacitor instance to configure alerting endpoints
|
||||
Connect to an active Kapacitor instance to configure alerting
|
||||
endpoints
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -29,7 +29,9 @@ const KapacitorRules = ({
|
|||
</PageContents>
|
||||
)
|
||||
}
|
||||
const tableHeader = rules.length === 1 ? '1 Alert Rule' : `${rules.length} Alert Rules`
|
||||
const tableHeader = rules.length === 1
|
||||
? '1 Alert Rule'
|
||||
: `${rules.length} Alert Rules`
|
||||
return (
|
||||
<PageContents source={source}>
|
||||
<div className="panel-heading u-flex u-ai-center u-jc-space-between">
|
||||
|
@ -51,7 +53,7 @@ const KapacitorRules = ({
|
|||
)
|
||||
}
|
||||
|
||||
const PageContents = ({children, source}) => (
|
||||
const PageContents = ({children, source}) =>
|
||||
<div className="page">
|
||||
<div className="page-header">
|
||||
<div className="page-header__container">
|
||||
|
@ -75,7 +77,6 @@ const PageContents = ({children, source}) => (
|
|||
</div>
|
||||
</FancyScrollbar>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, bool, func, shape, node} = PropTypes
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import {Link} from 'react-router'
|
||||
|
||||
const KapacitorRulesTable = ({rules, source, onDelete, onChangeRuleStatus}) => (
|
||||
const KapacitorRulesTable = ({rules, source, onDelete, onChangeRuleStatus}) =>
|
||||
<div className="panel-body">
|
||||
<table className="table v-center">
|
||||
<thead>
|
||||
|
@ -29,9 +29,8 @@ const KapacitorRulesTable = ({rules, source, onDelete, onChangeRuleStatus}) => (
|
|||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)
|
||||
|
||||
const RuleRow = ({rule, source, onDelete, onChangeRuleStatus}) => (
|
||||
const RuleRow = ({rule, source, onDelete, onChangeRuleStatus}) =>
|
||||
<tr key={rule.id}>
|
||||
<td className="monotype">
|
||||
<RuleTitle rule={rule} source={source} />
|
||||
|
@ -57,7 +56,6 @@ const RuleRow = ({rule, source, onDelete, onChangeRuleStatus}) => (
|
|||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
|
||||
const RuleTitle = ({rule: {id, name, query}, source}) => {
|
||||
// no queryConfig means the rule was manually created outside of Chronograf
|
||||
|
|
|
@ -2,8 +2,7 @@ import React, {PropTypes} from 'react'
|
|||
import classnames from 'classnames'
|
||||
import ReactTooltip from 'react-tooltip'
|
||||
|
||||
import RuleMessageAlertConfig
|
||||
from 'src/kapacitor/components/RuleMessageAlertConfig'
|
||||
import RuleMessageAlertConfig from 'src/kapacitor/components/RuleMessageAlertConfig'
|
||||
|
||||
import {RULE_MESSAGE_TEMPLATES as templates, DEFAULT_ALERTS} from '../constants'
|
||||
|
||||
|
@ -59,7 +58,7 @@ export const RuleMessage = React.createClass({
|
|||
<div className="rule-section--row rule-section--row-first rule-section--border-bottom">
|
||||
<p>Send this Alert to:</p>
|
||||
<ul className="nav nav-tablist nav-tablist-sm nav-tablist-malachite">
|
||||
{alerts.map(alert => (
|
||||
{alerts.map(alert =>
|
||||
<li
|
||||
key={alert.text}
|
||||
className={classnames({
|
||||
|
@ -69,7 +68,7 @@ export const RuleMessage = React.createClass({
|
|||
>
|
||||
{alert.text}
|
||||
</li>
|
||||
))}
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
<RuleMessageAlertConfig
|
||||
|
|
|
@ -27,9 +27,9 @@ export const ValuesSection = React.createClass({
|
|||
<div className="rule-section--body">
|
||||
<Tabs initialIndex={initialIndex} onSelect={this.handleChooseTrigger}>
|
||||
<TabList isKapacitorTabs="true">
|
||||
{TABS.map(tab => (
|
||||
{TABS.map(tab =>
|
||||
<Tab key={tab} isKapacitorTab={true}>{tab}</Tab>
|
||||
))}
|
||||
)}
|
||||
</TabList>
|
||||
|
||||
<TabPanels>
|
||||
|
|
|
@ -157,7 +157,8 @@ const TelegramConfig = React.createClass({
|
|||
ref={r => (this.disableNotification = r)}
|
||||
/>
|
||||
<label htmlFor="disableNotification">
|
||||
Disable notifications on iOS devices and disable sounds on Android devices. Android users continue to receive notifications.
|
||||
Disable notifications on iOS devices and disable sounds on Android
|
||||
devices. Android users continue to receive notifications.
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -56,19 +56,23 @@ export const RULE_MESSAGE_TEMPLATES = {
|
|||
taskName: {label: '{{.TaskName}}', text: 'The name of the task'},
|
||||
group: {
|
||||
label: '{{.Group}}',
|
||||
text: 'Concatenation of all group-by tags of the form <code>[key=value,]+</code>. If no groupBy is performed equal to literal "nil"',
|
||||
text:
|
||||
'Concatenation of all group-by tags of the form <code>[key=value,]+</code>. If no groupBy is performed equal to literal "nil"',
|
||||
},
|
||||
tags: {
|
||||
label: '{{.Tags}}',
|
||||
text: 'Map of tags. Use <code>{{ index .Tags "key" }}</code> to get a specific tag value',
|
||||
text:
|
||||
'Map of tags. Use <code>{{ index .Tags "key" }}</code> to get a specific tag value',
|
||||
},
|
||||
level: {
|
||||
label: '{{.Level}}',
|
||||
text: 'Alert Level, one of: <code>INFO</code><code>WARNING</code><code>CRITICAL</code>',
|
||||
text:
|
||||
'Alert Level, one of: <code>INFO</code><code>WARNING</code><code>CRITICAL</code>',
|
||||
},
|
||||
fields: {
|
||||
label: '{{ index .Fields "value" }}',
|
||||
text: 'Map of fields. Use <code>{{ index .Fields "key" }}</code> to get a specific field value',
|
||||
text:
|
||||
'Map of fields. Use <code>{{ index .Fields "key" }}</code> to get a specific field value',
|
||||
},
|
||||
time: {
|
||||
label: '{{.Time}}',
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import classnames from 'classnames'
|
||||
|
||||
const ConfirmButtons = ({
|
||||
onConfirm,
|
||||
item,
|
||||
onCancel,
|
||||
buttonSize,
|
||||
isDisabled,
|
||||
}) => (
|
||||
const ConfirmButtons = ({onConfirm, item, onCancel, buttonSize, isDisabled}) =>
|
||||
<div className="confirm-buttons">
|
||||
<button
|
||||
className={classnames('btn btn-info btn-square', {
|
||||
|
@ -28,7 +22,6 @@ const ConfirmButtons = ({
|
|||
<span className="icon checkmark" />
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {func, oneOfType, shape, string, bool} = PropTypes
|
||||
|
||||
|
|
|
@ -54,7 +54,9 @@ class CustomTimeRangeDropdown extends Component {
|
|||
onClick={onToggle}
|
||||
>
|
||||
<span className="icon clock" />
|
||||
<span className="dropdown-selected">{`${moment(lower).format('MMM Do HH:mm')} — ${moment(upper).format('MMM Do HH:mm')}`}</span>
|
||||
<span className="dropdown-selected">{`${moment(lower).format(
|
||||
'MMM Do HH:mm'
|
||||
)} — ${moment(upper).format('MMM Do HH:mm')}`}</span>
|
||||
<span className="caret" />
|
||||
</button>
|
||||
<div className="custom-time--container">
|
||||
|
|
|
@ -4,7 +4,7 @@ import classnames from 'classnames'
|
|||
import OnClickOutside from 'shared/components/OnClickOutside'
|
||||
import ConfirmButtons from 'shared/components/ConfirmButtons'
|
||||
|
||||
const DeleteButton = ({onClickDelete, buttonSize}) => (
|
||||
const DeleteButton = ({onClickDelete, buttonSize}) =>
|
||||
<button
|
||||
className={classnames('btn btn-danger table--show-on-row-hover', {
|
||||
[buttonSize]: buttonSize,
|
||||
|
@ -13,7 +13,6 @@ const DeleteButton = ({onClickDelete, buttonSize}) => (
|
|||
>
|
||||
Delete
|
||||
</button>
|
||||
)
|
||||
|
||||
class DeleteConfirmButtons extends Component {
|
||||
constructor(props) {
|
||||
|
|
|
@ -3,10 +3,9 @@ import React from 'react'
|
|||
import DeleteConfirmButtons from 'shared/components/DeleteConfirmButtons'
|
||||
import {ADMIN_TABLE} from 'src/admin/constants/tableSizing'
|
||||
|
||||
const DeleteConfirmTableCell = props => (
|
||||
const DeleteConfirmTableCell = props =>
|
||||
<td className="text-right" style={{width: `${ADMIN_TABLE.colDelete}px`}}>
|
||||
<DeleteConfirmButtons {...props} />
|
||||
</td>
|
||||
)
|
||||
|
||||
export default DeleteConfirmTableCell
|
||||
|
|
|
@ -25,18 +25,14 @@ class FancyScrollbar extends Component {
|
|||
autoHideDuration={250}
|
||||
autoHeight={autoHeight}
|
||||
autoHeightMax={maxHeight}
|
||||
renderTrackHorizontal={props => (
|
||||
<div {...props} className="fancy-scroll--track-h" />
|
||||
)}
|
||||
renderTrackVertical={props => (
|
||||
<div {...props} className="fancy-scroll--track-v" />
|
||||
)}
|
||||
renderThumbHorizontal={props => (
|
||||
<div {...props} className="fancy-scroll--thumb-h" />
|
||||
)}
|
||||
renderThumbVertical={props => (
|
||||
<div {...props} className="fancy-scroll--thumb-v" />
|
||||
)}
|
||||
renderTrackHorizontal={props =>
|
||||
<div {...props} className="fancy-scroll--track-h" />}
|
||||
renderTrackVertical={props =>
|
||||
<div {...props} className="fancy-scroll--track-v" />}
|
||||
renderThumbHorizontal={props =>
|
||||
<div {...props} className="fancy-scroll--thumb-h" />}
|
||||
renderThumbVertical={props =>
|
||||
<div {...props} className="fancy-scroll--thumb-v" />}
|
||||
>
|
||||
{children}
|
||||
</Scrollbars>
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
|
||||
const LoadingDots = ({className}) => (
|
||||
const LoadingDots = ({className}) =>
|
||||
<div className={`loading-dots ${className}`}>
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
</div>
|
||||
)
|
||||
|
||||
const {string} = PropTypes
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ const NameableGraph = React.createClass({
|
|||
})
|
||||
|
||||
const ContextMenu = OnClickOutside(
|
||||
({isOpen, toggleMenu, onEdit, onRename, onDelete, cell}) => (
|
||||
({isOpen, toggleMenu, onEdit, onRename, onDelete, cell}) =>
|
||||
<div
|
||||
className={classnames('dash-graph--options', {
|
||||
'dash-graph--options-show': isOpen,
|
||||
|
@ -132,6 +132,5 @@ const ContextMenu = OnClickOutside(
|
|||
<li onClick={() => onDelete(cell)}>Delete</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
export default NameableGraph
|
||||
|
|
|
@ -13,7 +13,8 @@ const NoKapacitorError = React.createClass({
|
|||
return (
|
||||
<div>
|
||||
<p>
|
||||
The current source does not have an associated Kapacitor instance, please configure one.
|
||||
The current source does not have an associated Kapacitor instance,
|
||||
please configure one.
|
||||
</p>
|
||||
<Link to={path}>Add Kapacitor</Link>
|
||||
</div>
|
||||
|
|
|
@ -2,9 +2,8 @@ import React, {PropTypes} from 'react'
|
|||
|
||||
import {OVERLAY_TECHNOLOGY} from 'shared/constants/classNames'
|
||||
|
||||
const OverlayTechnologies = ({children}) => (
|
||||
const OverlayTechnologies = ({children}) =>
|
||||
<div className={OVERLAY_TECHNOLOGY}>{children}</div>
|
||||
)
|
||||
|
||||
const {node} = PropTypes
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import ReactTooltip from 'react-tooltip'
|
||||
|
||||
const QuestionMarkTooltip = ({tipID, tipContent}) => (
|
||||
const QuestionMarkTooltip = ({tipID, tipContent}) =>
|
||||
<div className="question-mark-tooltip">
|
||||
<div
|
||||
className="question-mark-tooltip--icon"
|
||||
|
@ -19,7 +19,6 @@ const QuestionMarkTooltip = ({tipID, tipContent}) => (
|
|||
class="influx-tooltip__hover place-bottom"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {string} = PropTypes
|
||||
|
||||
|
|
|
@ -7,9 +7,9 @@ const TemplateDrawer = ({
|
|||
selected,
|
||||
onMouseOverTempVar,
|
||||
onClickTempVar,
|
||||
}) => (
|
||||
}) =>
|
||||
<div className="template-drawer">
|
||||
{templates.map(t => (
|
||||
{templates.map(t =>
|
||||
<div
|
||||
className={classnames('template-drawer--item', {
|
||||
'template-drawer--selected': t.tempVar === selected.tempVar,
|
||||
|
@ -22,9 +22,8 @@ const TemplateDrawer = ({
|
|||
>
|
||||
{' '}{t.tempVar}{' '}
|
||||
</div>
|
||||
))}
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, func, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import ReactTooltip from 'react-tooltip'
|
||||
|
||||
const Tooltip = ({tip, children}) => (
|
||||
const Tooltip = ({tip, children}) =>
|
||||
<div>
|
||||
<div data-tip={tip}>{children}</div>
|
||||
<ReactTooltip
|
||||
|
@ -12,7 +12,6 @@ const Tooltip = ({tip, children}) => (
|
|||
class="influx-tooltip place-bottom"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import classnames from 'classnames'
|
||||
|
||||
const YesNoButtons = ({onConfirm, onCancel, buttonSize}) => (
|
||||
const YesNoButtons = ({onConfirm, onCancel, buttonSize}) =>
|
||||
<div>
|
||||
<button
|
||||
className={classnames('btn btn-square btn-info', {
|
||||
|
@ -20,7 +20,6 @@ const YesNoButtons = ({onConfirm, onCancel, buttonSize}) => (
|
|||
<span className="icon checkmark" />
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {func, string} = PropTypes
|
||||
|
||||
|
|
|
@ -41,7 +41,8 @@ const RenameCluster = React.createClass({
|
|||
<div className="row">
|
||||
<div className="col-md-8 col-md-offset-2 text-center">
|
||||
<p>
|
||||
A cluster can have an alias that replaces its ID in the interface.
|
||||
A cluster can have an alias that replaces its ID in the
|
||||
interface.
|
||||
<br />
|
||||
This does not affect the cluster ID.
|
||||
</p>
|
||||
|
|
|
@ -73,7 +73,7 @@ const InfluxTable = ({
|
|||
router,
|
||||
setActiveKapacitor,
|
||||
handleDeleteKapacitor,
|
||||
}) => (
|
||||
}) =>
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<div className="panel panel-minimal">
|
||||
|
@ -146,7 +146,6 @@ const InfluxTable = ({
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const {array, func, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ export const SourceForm = React.createClass({
|
|||
name: this.sourceName.value,
|
||||
username: this.sourceUsername.value,
|
||||
password: this.sourcePassword.value,
|
||||
'default': this.sourceDefault.checked,
|
||||
default: this.sourceDefault.checked,
|
||||
telegraf: this.sourceTelegraf.value,
|
||||
insecureSkipVerify: this.sourceInsecureSkipVerify
|
||||
? this.sourceInsecureSkipVerify.checked
|
||||
|
|
Loading…
Reference in New Issue