Merge pull request #1898 from influxdata/feature/typee-calendar

FEATURE:  Typee calendar (with extra credit)
pull/1899/head
Andrew Watkins 2017-08-17 15:04:18 -07:00 committed by GitHub
commit b41cd95fb1
3 changed files with 102 additions and 42 deletions

View File

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

View File

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

View File

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