Merge branch 'master' into ux/dashboard-empty-state

pull/3240/head
Alex P 2018-04-18 13:11:48 -07:00
commit e8ec841902
8 changed files with 170 additions and 74 deletions

View File

@ -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]

View File

@ -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",

View File

@ -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}

View File

@ -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}
}

View File

@ -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}
}

View File

@ -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)
})
})
})

View File

@ -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`

View File

@ -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"