Merge pull request #1898 from influxdata/feature/typee-calendar
FEATURE: Typee calendar (with extra credit)pull/1899/head
commit
b41cd95fb1
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
1. [#1863](https://github.com/influxdata/chronograf/pull/1863): Improve 'new-sources' server flag example by adding 'type' key
|
1. [#1863](https://github.com/influxdata/chronograf/pull/1863): Improve 'new-sources' server flag example by adding 'type' key
|
||||||
|
1. [#1898](https://github.com/influxdata/chronograf/pull/1898): Add an input and validation to custom time range calendar dropdowns
|
||||||
|
|
||||||
### UI Improvements
|
### UI Improvements
|
||||||
1. [#1862](https://github.com/influxdata/chronograf/pull/1862): Show "Add Graph" button on cells with no queries
|
1. [#1862](https://github.com/influxdata/chronograf/pull/1862): Show "Add Graph" button on cells with no queries
|
||||||
|
|
|
@ -3,71 +3,69 @@ import rome from 'rome'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
|
||||||
import shortcuts from 'hson!shared/data/timeRangeShortcuts.hson'
|
import shortcuts from 'hson!shared/data/timeRangeShortcuts.hson'
|
||||||
|
const dateFormat = 'YYYY-MM-DD HH:mm'
|
||||||
|
|
||||||
class CustomTimeRange extends Component {
|
class CustomTimeRange extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
this.handleClick = ::this.handleClick
|
|
||||||
this._formatTimeRange = ::this._formatTimeRange
|
|
||||||
this.handleTimeRangeShortcut = ::this.handleTimeRangeShortcut
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const {timeRange} = this.props
|
const {timeRange} = this.props
|
||||||
|
|
||||||
const lower = rome(this.lower, {
|
const lower = rome(this.lower, {
|
||||||
initialValue: this._formatTimeRange(timeRange.lower),
|
dateValidator: rome.val.beforeEq(this.upper),
|
||||||
|
appendTo: this.lowerContainer,
|
||||||
|
initialValue: this.getInitialDate(timeRange.lower),
|
||||||
|
autoClose: false,
|
||||||
|
autoHideOnBlur: false,
|
||||||
|
autoHideOnClick: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const upper = rome(this.upper, {
|
const upper = rome(this.upper, {
|
||||||
initialValue: this._formatTimeRange(timeRange.upper),
|
dateValidator: rome.val.afterEq(this.lower),
|
||||||
|
appendTo: this.upperContainer,
|
||||||
|
autoClose: false,
|
||||||
|
initialValue: this.getInitialDate(timeRange.upper),
|
||||||
|
autoHideOnBlur: false,
|
||||||
|
autoHideOnClick: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
this.lowerCal = lower
|
this.lowerCal = lower
|
||||||
this.upperCal = upper
|
this.upperCal = upper
|
||||||
|
|
||||||
|
this.lowerCal.show()
|
||||||
|
this.upperCal.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is an upper or lower time range set, set the corresponding calendar's value.
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const {lower, upper} = nextProps.timeRange
|
const {lower, upper} = nextProps.timeRange
|
||||||
if (lower) {
|
if (lower) {
|
||||||
|
const formattedLower = this._formatTimeRange(lower)
|
||||||
this.lowerCal.setValue(this._formatTimeRange(lower))
|
this.lowerCal.setValue(this._formatTimeRange(lower))
|
||||||
|
this.lower.value = formattedLower
|
||||||
}
|
}
|
||||||
|
|
||||||
if (upper) {
|
if (upper) {
|
||||||
|
const formattedUpper = this._formatTimeRange(upper)
|
||||||
this.upperCal.setValue(this._formatTimeRange(upper))
|
this.upperCal.setValue(this._formatTimeRange(upper))
|
||||||
|
this.upper.value = formattedUpper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
getInitialDate = time => {
|
||||||
return (
|
const {upper, lower} = this.props.timeRange
|
||||||
<div className="custom-time--container">
|
|
||||||
<div className="custom-time--shortcuts">
|
if (upper || lower) {
|
||||||
<div className="custom-time--shortcuts-header">Shortcuts</div>
|
return this._formatTimeRange(time)
|
||||||
{shortcuts.map(({id, name}) =>
|
}
|
||||||
<div
|
|
||||||
key={id}
|
return moment(new Date()).format(dateFormat)
|
||||||
className="custom-time--shortcut"
|
}
|
||||||
onClick={this.handleTimeRangeShortcut(id)}
|
|
||||||
>
|
handleRefreshCals = () => {
|
||||||
{name}
|
this.lowerCal.refresh()
|
||||||
</div>
|
this.upperCal.refresh()
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="custom-time--wrap">
|
|
||||||
<div className="custom-time--dates">
|
|
||||||
<div className="custom-time--lower" ref={r => (this.lower = r)} />
|
|
||||||
<div className="custom-time--upper" ref={r => (this.upper = r)} />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="custom-time--apply btn btn-sm btn-primary"
|
|
||||||
onClick={this.handleClick}
|
|
||||||
>
|
|
||||||
Apply
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -75,7 +73,7 @@ class CustomTimeRange extends Component {
|
||||||
* the string literal, i.e. "'2015-09-23T18:00:00.000Z'". Remove them
|
* the string literal, i.e. "'2015-09-23T18:00:00.000Z'". Remove them
|
||||||
* before passing the string to be parsed.
|
* before passing the string to be parsed.
|
||||||
*/
|
*/
|
||||||
_formatTimeRange(timeRange) {
|
_formatTimeRange = timeRange => {
|
||||||
if (!timeRange) {
|
if (!timeRange) {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
@ -86,10 +84,10 @@ class CustomTimeRange extends Component {
|
||||||
moment().subtract(duration, unitOfTime)
|
moment().subtract(duration, unitOfTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
return moment(timeRange.replace(/\'/g, '')).format('YYYY-MM-DD HH:mm')
|
return moment(timeRange.replace(/\'/g, '')).format(dateFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClick() {
|
handleClick = () => {
|
||||||
const {onApplyTimeRange, onClose} = this.props
|
const {onApplyTimeRange, onClose} = this.props
|
||||||
const lower = this.lowerCal.getDate().toISOString()
|
const lower = this.lowerCal.getDate().toISOString()
|
||||||
const upper = this.upperCal.getDate().toISOString()
|
const upper = this.upperCal.getDate().toISOString()
|
||||||
|
@ -101,7 +99,7 @@ class CustomTimeRange extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTimeRangeShortcut(shortcut) {
|
handleTimeRangeShortcut = shortcut => {
|
||||||
return () => {
|
return () => {
|
||||||
let lower
|
let lower
|
||||||
const upper = moment()
|
const upper = moment()
|
||||||
|
@ -133,10 +131,66 @@ class CustomTimeRange extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.lower.value = lower.format(dateFormat)
|
||||||
|
this.upper.value = upper.format(dateFormat)
|
||||||
|
|
||||||
this.lowerCal.setValue(lower)
|
this.lowerCal.setValue(lower)
|
||||||
this.upperCal.setValue(upper)
|
this.upperCal.setValue(upper)
|
||||||
|
|
||||||
|
this.handleRefreshCals()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="custom-time--container">
|
||||||
|
<div className="custom-time--shortcuts">
|
||||||
|
<div className="custom-time--shortcuts-header">Shortcuts</div>
|
||||||
|
{shortcuts.map(({id, name}) =>
|
||||||
|
<div
|
||||||
|
key={id}
|
||||||
|
className="custom-time--shortcut"
|
||||||
|
onClick={this.handleTimeRangeShortcut(id)}
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="custom-time--wrap">
|
||||||
|
<div className="custom-time--dates" onClick={this.handleRefreshCals}>
|
||||||
|
<div
|
||||||
|
className="lower-container"
|
||||||
|
ref={r => (this.lowerContainer = r)}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
className="custom-time--lower form-control input-sm"
|
||||||
|
ref={r => (this.lower = r)}
|
||||||
|
placeholder="from"
|
||||||
|
onKeyUp={this.handleRefreshCals}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="upper-container"
|
||||||
|
ref={r => (this.upperContainer = r)}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
className="custom-time--upper form-control input-sm"
|
||||||
|
ref={r => (this.upper = r)}
|
||||||
|
placeholder="to"
|
||||||
|
onKeyUp={this.handleRefreshCals}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="custom-time--apply btn btn-sm btn-primary"
|
||||||
|
onClick={this.handleClick}
|
||||||
|
>
|
||||||
|
Apply
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const {func, shape, string} = PropTypes
|
const {func, shape, string} = PropTypes
|
||||||
|
|
|
@ -35,9 +35,11 @@
|
||||||
}
|
}
|
||||||
.custom-time--lower {
|
.custom-time--lower {
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
.custom-time--upper {
|
.custom-time--upper {
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
.custom-time--shortcuts {
|
.custom-time--shortcuts {
|
||||||
@include no-user-select();
|
@include no-user-select();
|
||||||
|
@ -179,13 +181,16 @@ $rd-cell-size: 30px;
|
||||||
&.rd-day-next-month,
|
&.rd-day-next-month,
|
||||||
&.rd-day-prev-month {
|
&.rd-day-prev-month {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
color: $g8-storm !important;
|
visibility: hidden;
|
||||||
background-color: $g5-pepper !important;
|
|
||||||
}
|
}
|
||||||
&.rd-day-selected {
|
&.rd-day-selected {
|
||||||
background-color: $c-pool !important;
|
background-color: $c-pool !important;
|
||||||
color: $g20-white !important;
|
color: $g20-white !important;
|
||||||
}
|
}
|
||||||
|
&.rd-day-disabled {
|
||||||
|
color: $g8-storm !important;
|
||||||
|
background-color: $g5-pepper !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue