Merge branch 'master' into ux/dashboard-empty-state
commit
e8ec841902
23
CHANGELOG.md
23
CHANGELOG.md
|
@ -2,6 +2,23 @@
|
|||
|
||||
### Features
|
||||
|
||||
### UI Improvements
|
||||
1. [#3204](https://github.com/influxdata/chronograf/pull/3204): Notify user when a dashboard cell is added, removed, or cloned
|
||||
1. [#3215](https://github.com/influxdata/chronograf/pull/3215): Fix Template Variables Control Bar to top of dashboard page
|
||||
1. [#3214](https://github.com/influxdata/chronograf/pull/3214): Remove extra click when creating dashboard cell
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
## v1.4.4.1 [2018-04-16]
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
1. [#3211](https://github.com/influxdata/chronograf/pull/3211): Snapshot all db struct types in migration files
|
||||
|
||||
## v1.4.4.0 [2018-04-13]
|
||||
|
||||
### Features
|
||||
|
||||
1. [#2526](https://github.com/influxdata/chronograf/pull/2526): Add support for RS256/JWKS verification, support for id_token parsing (as in ADFS)
|
||||
1. [#3060](https://github.com/influxdata/chronograf/pull/3060): Add ability to set a color palette for Line, Stacked, Step-Plot, and Bar graphs
|
||||
1. [#3103](https://github.com/influxdata/chronograf/pull/3103): Add ability to clone dashboards
|
||||
|
@ -17,13 +34,10 @@
|
|||
1. [#3096](https://github.com/influxdata/chronograf/pull/3096): Standardize delete confirmation interactions
|
||||
1. [#3096](https://github.com/influxdata/chronograf/pull/3096): Standardize save & cancel interactions
|
||||
1. [#3116](https://github.com/influxdata/chronograf/pull/3116): Improve cell renaming
|
||||
1. [#3204](https://github.com/influxdata/chronograf/pull/3204): Notify user when a dashboard cell is added, removed, or cloned
|
||||
1. [#3215](https://github.com/influxdata/chronograf/pull/3215): Fix Template Variables Control Bar to top of dashboard page
|
||||
1. [#3214](https://github.com/influxdata/chronograf/pull/3214): Remove extra click when creating dashboard cell
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
1. [#2950](https://github.com/influxdata/chronograf/pull/2094): Always save template variables on first edit
|
||||
1. [#3094](https://github.com/influxdata/chronograf/pull/3094): Always save template variables on first edit
|
||||
1. [#3104](https://github.com/influxdata/chronograf/pull/3104): Query annotations at auto-refresh interval
|
||||
1. [#3109](https://github.com/influxdata/chronograf/pull/3109): Display link to configure Kapacitor on Alerts Page if no configured kapacitor.
|
||||
1. [#3111](https://github.com/influxdata/chronograf/pull/3111): Fix saving of new TICKscripts
|
||||
|
@ -39,6 +53,7 @@
|
|||
1. [#3182](https://github.com/influxdata/chronograf/pull/3182): Send notification when rp creation returns a failure
|
||||
1. [#3181](https://github.com/influxdata/chronograf/pull/3181): Show valid time in custom time range when now is selected
|
||||
1. [#3179](https://github.com/influxdata/chronograf/pull/3179): Default to zero for gauges
|
||||
1. [#3237](https://github.com/influxdata/chronograf/pull/3237): Fixes now() time parsing when requesting annotations
|
||||
|
||||
## v1.4.3.1 [2018-04-02]
|
||||
|
||||
|
|
|
@ -66,7 +66,6 @@
|
|||
"css-loader": "^0.23.1",
|
||||
"envify": "^3.4.0",
|
||||
"enzyme": "^3.3.0",
|
||||
"enzyme-adapter-react-15": "^1.0.5",
|
||||
"eslint": "^3.14.1",
|
||||
"eslint-config-prettier": "^2.9.0",
|
||||
"eslint-loader": "^2.0.0",
|
||||
|
@ -95,8 +94,6 @@
|
|||
"postcss-reporter": "^1.3.1",
|
||||
"precss": "^1.4.0",
|
||||
"prettier": "^1.11.1",
|
||||
"react-addons-test-utils": "^15.0.2",
|
||||
"react-test-renderer": "^15.6.1",
|
||||
"resolve-url-loader": "^2.2.1",
|
||||
"sass-loader": "^6.0.6",
|
||||
"style-loader": "^0.13.0",
|
||||
|
@ -123,6 +120,7 @@
|
|||
"classnames": "^2.2.3",
|
||||
"codemirror": "^5.36.0",
|
||||
"dygraphs": "2.1.0",
|
||||
"enzyme-adapter-react-16": "^1.1.1",
|
||||
"eslint-plugin-babel": "^4.1.2",
|
||||
"fast.js": "^0.1.1",
|
||||
"fixed-data-table": "^0.6.1",
|
||||
|
@ -132,7 +130,7 @@
|
|||
"nano-date": "^2.0.1",
|
||||
"prop-types": "^15.6.1",
|
||||
"query-string": "^5.0.0",
|
||||
"react": "^15.0.2",
|
||||
"react": "^16.3.1",
|
||||
"react-addons-shallow-compare": "^15.0.2",
|
||||
"react-codemirror": "^1.0.0",
|
||||
"react-codemirror2": "^4.2.1",
|
||||
|
@ -140,7 +138,7 @@
|
|||
"react-dimensions": "^1.2.0",
|
||||
"react-dnd": "^2.6.0",
|
||||
"react-dnd-html5-backend": "^2.6.0",
|
||||
"react-dom": "^15.0.2",
|
||||
"react-dom": "^16.3.1",
|
||||
"react-grid-layout": "^0.16.6",
|
||||
"react-onclickoutside": "^5.2.0",
|
||||
"react-redux": "^4.4.0",
|
||||
|
|
|
@ -19,6 +19,7 @@ import TemplateControlBar from 'src/dashboards/components/TemplateControlBar'
|
|||
import {errorThrown as errorThrownAction} from 'shared/actions/errors'
|
||||
import {notify as notifyAction} from 'shared/actions/notifications'
|
||||
import idNormalizer, {TYPE_ID} from 'src/normalizers/id'
|
||||
import {millisecondTimeRange} from 'src/dashboards/utils/time'
|
||||
|
||||
import * as dashboardActionCreators from 'src/dashboards/actions'
|
||||
import * as annotationActions from 'shared/actions/annotations'
|
||||
|
@ -81,7 +82,7 @@ class DashboardPage extends Component {
|
|||
autoRefresh,
|
||||
} = this.props
|
||||
|
||||
const annotationRange = this.millisecondTimeRange(timeRange)
|
||||
const annotationRange = millisecondTimeRange(timeRange)
|
||||
getAnnotationsAsync(source.links.annotations, annotationRange)
|
||||
|
||||
if (autoRefresh) {
|
||||
|
@ -114,7 +115,7 @@ class DashboardPage extends Component {
|
|||
const {source, getAnnotationsAsync, timeRange} = this.props
|
||||
if (this.props.autoRefresh !== nextProps.autoRefresh) {
|
||||
clearInterval(this.intervalID)
|
||||
const annotationRange = this.millisecondTimeRange(timeRange)
|
||||
const annotationRange = millisecondTimeRange(timeRange)
|
||||
if (nextProps.autoRefresh) {
|
||||
this.intervalID = setInterval(() => {
|
||||
getAnnotationsAsync(source.links.annotations, annotationRange)
|
||||
|
@ -183,26 +184,10 @@ class DashboardPage extends Component {
|
|||
format: FORMAT_INFLUXQL,
|
||||
})
|
||||
|
||||
const annotationRange = this.millisecondTimeRange(timeRange)
|
||||
const annotationRange = millisecondTimeRange(timeRange)
|
||||
getAnnotationsAsync(source.links.annotations, annotationRange)
|
||||
}
|
||||
|
||||
millisecondTimeRange({seconds, lower, upper}) {
|
||||
// Is this a relative time range?
|
||||
if (seconds) {
|
||||
return {
|
||||
since: Date.now() - seconds * 1000,
|
||||
until: null,
|
||||
}
|
||||
}
|
||||
|
||||
// No, this is an absolute (custom) time range
|
||||
return {
|
||||
since: Date.parse(lower),
|
||||
until: Date.parse(upper),
|
||||
}
|
||||
}
|
||||
|
||||
handleUpdatePosition = cells => {
|
||||
const {dashboardActions, dashboard, meRole, isUsingAuth} = this.props
|
||||
const newDashboard = {...dashboard, cells}
|
||||
|
|
|
@ -74,6 +74,33 @@ export const isCellUntitled = cellName => {
|
|||
)
|
||||
}
|
||||
|
||||
const numColumns = 12
|
||||
|
||||
const getNextAvailablePosition = (dashboard, newCell) => {
|
||||
const farthestY = dashboard.cells
|
||||
.map(cell => cell.y)
|
||||
.reduce((a, b) => (a > b ? a : b))
|
||||
|
||||
const bottomCells = dashboard.cells.filter(cell => cell.y === farthestY)
|
||||
const farthestX = bottomCells
|
||||
.map(cell => cell.x)
|
||||
.reduce((a, b) => (a > b ? a : b))
|
||||
const lastCell = bottomCells.find(cell => cell.x === farthestX)
|
||||
|
||||
const availableSpace = numColumns - (lastCell.x + lastCell.w)
|
||||
const newCellFits = availableSpace >= newCell.w
|
||||
|
||||
return newCellFits
|
||||
? {
|
||||
x: lastCell.x + lastCell.w,
|
||||
y: farthestY,
|
||||
}
|
||||
: {
|
||||
x: 0,
|
||||
y: lastCell.y + lastCell.h,
|
||||
}
|
||||
}
|
||||
|
||||
export const getNewDashboardCell = (dashboard, cellType) => {
|
||||
const type = cellType || CELL_TYPE_LINE
|
||||
const typedCell = {
|
||||
|
@ -86,30 +113,31 @@ export const getNewDashboardCell = (dashboard, cellType) => {
|
|||
return typedCell
|
||||
}
|
||||
|
||||
const newCellY = dashboard.cells
|
||||
.map(cell => cell.y + cell.h)
|
||||
.reduce((a, b) => (a > b ? a : b))
|
||||
|
||||
const existingCellWidths = dashboard.cells.map(cell => cell.w)
|
||||
const existingCellHeights = dashboard.cells.map(cell => cell.h)
|
||||
|
||||
const mostCommonCellWidth = getMostCommonValue(existingCellWidths)
|
||||
const mostCommonCellHeight = getMostCommonValue(existingCellHeights)
|
||||
|
||||
return {
|
||||
const newCell = {
|
||||
...typedCell,
|
||||
y: newCellY,
|
||||
w: mostCommonCellWidth,
|
||||
h: mostCommonCellHeight,
|
||||
}
|
||||
|
||||
const {x, y} = getNextAvailablePosition(dashboard, newCell)
|
||||
|
||||
return {
|
||||
...newCell,
|
||||
x,
|
||||
y,
|
||||
}
|
||||
}
|
||||
|
||||
export const getClonedDashboardCell = (dashboard, cloneCell) => {
|
||||
const newCellY = dashboard.cells
|
||||
.map(cell => cell.y + cell.h)
|
||||
.reduce((a, b) => (a > b ? a : b))
|
||||
const {x, y} = getNextAvailablePosition(dashboard, cloneCell)
|
||||
|
||||
const name = `${cloneCell.name} (Clone)`
|
||||
|
||||
return {...cloneCell, y: newCellY, name}
|
||||
return {...cloneCell, x, y, name}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
interface InputTimeRange {
|
||||
seconds?: number
|
||||
lower?: string
|
||||
upper?: string
|
||||
}
|
||||
|
||||
interface OutputTimeRange {
|
||||
since: number
|
||||
until: number | null
|
||||
}
|
||||
|
||||
export const millisecondTimeRange = ({
|
||||
seconds,
|
||||
lower,
|
||||
upper,
|
||||
}: InputTimeRange): OutputTimeRange => {
|
||||
// Is this a relative time range?
|
||||
if (seconds) {
|
||||
return {since: Date.now() - seconds * 1000, until: null}
|
||||
}
|
||||
|
||||
const since = Date.parse(lower)
|
||||
let until
|
||||
if (upper === 'now()') {
|
||||
until = Date.now()
|
||||
} else {
|
||||
until = Date.parse(upper)
|
||||
}
|
||||
return {since, until}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
import moment from 'moment'
|
||||
import * as time from 'src/dashboards/utils/time'
|
||||
|
||||
describe('dashboards.utils.time', () => {
|
||||
describe('millisecondTimeRange', () => {
|
||||
it('when upper is now() returns valid dates', () => {
|
||||
const expectedNow = moment()
|
||||
.subtract()
|
||||
.seconds(1)
|
||||
.unix()
|
||||
const timeRange = {upper: 'now()', lower: moment().format()}
|
||||
const result = time.millisecondTimeRange(timeRange)
|
||||
|
||||
expect(result.since).toBeGreaterThanOrEqual(expectedNow)
|
||||
expect(result.until).toBeGreaterThanOrEqual(expectedNow)
|
||||
})
|
||||
|
||||
it('when seconds is present returns valid dates', () => {
|
||||
const timeRange = {seconds: 10}
|
||||
const expectedSince = moment()
|
||||
.subtract()
|
||||
.seconds(10)
|
||||
.unix()
|
||||
const result = time.millisecondTimeRange(timeRange)
|
||||
|
||||
expect(result.since).toBeGreaterThanOrEqual(expectedSince)
|
||||
expect(result.until).toBe(null)
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,9 +1,11 @@
|
|||
import {configure} from 'enzyme'
|
||||
import React from 'react'
|
||||
|
||||
import Adapter from 'enzyme-adapter-react-15'
|
||||
import Adapter from 'enzyme-adapter-react-16'
|
||||
|
||||
configure({adapter: new Adapter()})
|
||||
configure({
|
||||
adapter: new Adapter(),
|
||||
})
|
||||
|
||||
/**
|
||||
* Since React v15.5, there's a warning printed if you access `React.createClass` or `React.PropTypes`
|
||||
|
|
76
ui/yarn.lock
76
ui/yarn.lock
|
@ -1820,11 +1820,7 @@ code-point-at@^1.0.0:
|
|||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||
|
||||
codemirror@^5.18.2:
|
||||
version "5.36.0"
|
||||
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.36.0.tgz#1172ad9dc298056c06e0b34e5ccd23825ca15b40"
|
||||
|
||||
codemirror@^5.36.0:
|
||||
codemirror@^5.18.2, codemirror@^5.36.0:
|
||||
version "5.36.0"
|
||||
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.36.0.tgz#1172ad9dc298056c06e0b34e5ccd23825ca15b40"
|
||||
|
||||
|
@ -2140,7 +2136,7 @@ create-jest-runner@^0.3.0:
|
|||
throat "4.1.0"
|
||||
worker-farm "1.5.0"
|
||||
|
||||
create-react-class@^15.5.1, create-react-class@^15.5.x, create-react-class@^15.6.0, create-react-class@^15.6.2:
|
||||
create-react-class@^15.5.1, create-react-class@^15.5.x, create-react-class@^15.6.2:
|
||||
version "15.6.3"
|
||||
resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.3.tgz#2d73237fb3f970ae6ebe011a9e66f46dbca80036"
|
||||
dependencies:
|
||||
|
@ -2755,17 +2751,19 @@ envify@^3.4.0:
|
|||
jstransform "^11.0.3"
|
||||
through "~2.3.4"
|
||||
|
||||
enzyme-adapter-react-15@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/enzyme-adapter-react-15/-/enzyme-adapter-react-15-1.0.5.tgz#99f9a03ff2c2303e517342935798a6bdfbb75fac"
|
||||
enzyme-adapter-react-16@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.1.1.tgz#a8f4278b47e082fbca14f5bfb1ee50ee650717b4"
|
||||
dependencies:
|
||||
enzyme-adapter-utils "^1.1.0"
|
||||
enzyme-adapter-utils "^1.3.0"
|
||||
lodash "^4.17.4"
|
||||
object.assign "^4.0.4"
|
||||
object.values "^1.0.4"
|
||||
prop-types "^15.5.10"
|
||||
prop-types "^15.6.0"
|
||||
react-reconciler "^0.7.0"
|
||||
react-test-renderer "^16.0.0-0"
|
||||
|
||||
enzyme-adapter-utils@^1.1.0:
|
||||
enzyme-adapter-utils@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.3.0.tgz#d6c85756826c257a8544d362cc7a67e97ea698c7"
|
||||
dependencies:
|
||||
|
@ -7097,10 +7095,6 @@ react-addons-shallow-compare@^15.0.2:
|
|||
fbjs "^0.8.4"
|
||||
object-assign "^4.1.0"
|
||||
|
||||
react-addons-test-utils@^15.0.2:
|
||||
version "15.6.2"
|
||||
resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.6.2.tgz#c12b6efdc2247c10da7b8770d185080a7b047156"
|
||||
|
||||
react-codemirror2@^4.2.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/react-codemirror2/-/react-codemirror2-4.2.1.tgz#4ad3c5c60ebbcb34880f961721b51527324ec021"
|
||||
|
@ -7147,14 +7141,14 @@ react-dnd@^2.6.0:
|
|||
lodash "^4.2.0"
|
||||
prop-types "^15.5.10"
|
||||
|
||||
react-dom@^15.0.2:
|
||||
version "15.6.2"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.6.2.tgz#41cfadf693b757faf2708443a1d1fd5a02bef730"
|
||||
react-dom@^16.3.1:
|
||||
version "16.3.2"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.3.2.tgz#cb90f107e09536d683d84ed5d4888e9640e0e4df"
|
||||
dependencies:
|
||||
fbjs "^0.8.9"
|
||||
fbjs "^0.8.16"
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.0"
|
||||
prop-types "^15.5.10"
|
||||
object-assign "^4.1.1"
|
||||
prop-types "^15.6.0"
|
||||
|
||||
react-draggable@3.x, "react-draggable@^2.2.6 || ^3.0.3":
|
||||
version "3.0.5"
|
||||
|
@ -7173,12 +7167,25 @@ react-grid-layout@^0.16.6:
|
|||
react-draggable "3.x"
|
||||
react-resizable "1.x"
|
||||
|
||||
react-is@^16.3.2:
|
||||
version "16.3.2"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.3.2.tgz#f4d3d0e2f5fbb6ac46450641eb2e25bf05d36b22"
|
||||
|
||||
react-onclickoutside@^5.2.0:
|
||||
version "5.11.1"
|
||||
resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-5.11.1.tgz#00314e52567cf55faba94cabbacd119619070623"
|
||||
dependencies:
|
||||
create-react-class "^15.5.x"
|
||||
|
||||
react-reconciler@^0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.7.0.tgz#9614894103e5f138deeeb5eabaf3ee80eb1d026d"
|
||||
dependencies:
|
||||
fbjs "^0.8.16"
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
prop-types "^15.6.0"
|
||||
|
||||
react-redux@^4.4.0:
|
||||
version "4.4.9"
|
||||
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-4.4.9.tgz#8ca6d4670925a454ce67086c2305e9630670909a"
|
||||
|
@ -7213,12 +7220,14 @@ react-router@^3.0.2:
|
|||
prop-types "^15.5.6"
|
||||
warning "^3.0.0"
|
||||
|
||||
react-test-renderer@^15.6.1:
|
||||
version "15.6.2"
|
||||
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-15.6.2.tgz#d0333434fc2c438092696ca770da5ed48037efa8"
|
||||
react-test-renderer@^16.0.0-0:
|
||||
version "16.3.2"
|
||||
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.3.2.tgz#3d1ed74fda8db42521fdf03328e933312214749a"
|
||||
dependencies:
|
||||
fbjs "^0.8.9"
|
||||
object-assign "^4.1.0"
|
||||
fbjs "^0.8.16"
|
||||
object-assign "^4.1.1"
|
||||
prop-types "^15.6.0"
|
||||
react-is "^16.3.2"
|
||||
|
||||
react-tooltip@^3.2.1:
|
||||
version "3.5.0"
|
||||
|
@ -7237,15 +7246,14 @@ react-virtualized@^9.18.5:
|
|||
loose-envify "^1.3.0"
|
||||
prop-types "^15.6.0"
|
||||
|
||||
react@^15.0.2:
|
||||
version "15.6.2"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-15.6.2.tgz#dba0434ab439cfe82f108f0f511663908179aa72"
|
||||
react@^16.3.1:
|
||||
version "16.3.2"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-16.3.2.tgz#fdc8420398533a1e58872f59091b272ce2f91ea9"
|
||||
dependencies:
|
||||
create-react-class "^15.6.0"
|
||||
fbjs "^0.8.9"
|
||||
fbjs "^0.8.16"
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.0"
|
||||
prop-types "^15.5.10"
|
||||
object-assign "^4.1.1"
|
||||
prop-types "^15.6.0"
|
||||
|
||||
read-pkg-up@^1.0.1:
|
||||
version "1.0.1"
|
||||
|
|
Loading…
Reference in New Issue