mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
Add table time input
Signed-off-by: Julius Volz <julius.volz@gmail.com>
This commit is contained in:
parent
032bf86877
commit
b86b91ef2a
11
src/App.css
11
src/App.css
|
@ -71,7 +71,7 @@ button.execute-btn {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.graph-controls {
|
.graph-controls, .table-controls {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,10 +84,17 @@ button.execute-btn {
|
||||||
}
|
}
|
||||||
|
|
||||||
.graph-controls .endtime-input input {
|
.graph-controls .endtime-input input {
|
||||||
width: 160px;
|
|
||||||
border-right: none;
|
border-right: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.endtime-input {
|
||||||
|
width: 270px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-controls input {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.graph-controls input.resolution-input {
|
.graph-controls input.resolution-input {
|
||||||
width: 90px;
|
width: 90px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,53 +8,32 @@ import {
|
||||||
Input,
|
Input,
|
||||||
} from 'reactstrap';
|
} from 'reactstrap';
|
||||||
|
|
||||||
import moment from 'moment-timezone';
|
|
||||||
|
|
||||||
import 'tempusdominus-core';
|
import 'tempusdominus-core';
|
||||||
import 'tempusdominus-bootstrap-4';
|
import 'tempusdominus-bootstrap-4';
|
||||||
import '../node_modules/tempusdominus-bootstrap-4/build/css/tempusdominus-bootstrap-4.min.css';
|
import '../node_modules/tempusdominus-bootstrap-4/build/css/tempusdominus-bootstrap-4.min.css';
|
||||||
|
|
||||||
import { dom, library } from '@fortawesome/fontawesome-svg-core';
|
import { library } from '@fortawesome/fontawesome-svg-core';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import {
|
import {
|
||||||
faChevronLeft,
|
|
||||||
faChevronRight,
|
|
||||||
faPlus,
|
faPlus,
|
||||||
faMinus,
|
faMinus,
|
||||||
faChartArea,
|
faChartArea,
|
||||||
faChartLine,
|
faChartLine,
|
||||||
faClock,
|
|
||||||
faCalendarCheck,
|
|
||||||
faArrowUp,
|
|
||||||
faArrowDown,
|
|
||||||
faTimes,
|
|
||||||
} from '@fortawesome/free-solid-svg-icons';
|
} from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
|
import TimeInput from './TimeInput.js';
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faChevronLeft,
|
|
||||||
faChevronRight,
|
|
||||||
faPlus,
|
faPlus,
|
||||||
faMinus,
|
faMinus,
|
||||||
faChartArea,
|
faChartArea,
|
||||||
faChartLine,
|
faChartLine,
|
||||||
faClock,
|
|
||||||
faCalendarCheck,
|
|
||||||
faArrowUp,
|
|
||||||
faArrowDown,
|
|
||||||
faTimes,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Sadly needed to also replace <i> within the date picker, since it's not a React component.
|
|
||||||
dom.watch();
|
|
||||||
|
|
||||||
class GraphControls extends Component {
|
class GraphControls extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
|
||||||
startDate: Date.now(),
|
|
||||||
};
|
|
||||||
|
|
||||||
this.rangeRef = React.createRef();
|
this.rangeRef = React.createRef();
|
||||||
this.endTimeRef = React.createRef();
|
this.endTimeRef = React.createRef();
|
||||||
this.resolutionRef = React.createRef();
|
this.resolutionRef = React.createRef();
|
||||||
|
@ -67,12 +46,12 @@ class GraphControls extends Component {
|
||||||
'h': 60 * 60,
|
'h': 60 * 60,
|
||||||
'm': 60,
|
'm': 60,
|
||||||
's': 1
|
's': 1
|
||||||
};
|
}
|
||||||
|
|
||||||
rangeSteps = [
|
rangeSteps = [
|
||||||
'1s', '10s', '1m', '5m', '15m', '30m', '1h', '2h', '6h', '12h', '1d', '2d',
|
'1s', '10s', '1m', '5m', '15m', '30m', '1h', '2h', '6h', '12h', '1d', '2d',
|
||||||
'1w', '2w', '4w', '8w', '1y', '2y'
|
'1w', '2w', '4w', '8w', '1y', '2y'
|
||||||
];
|
]
|
||||||
|
|
||||||
parseRange(rangeText) {
|
parseRange(rangeText) {
|
||||||
var rangeRE = new RegExp('^([0-9]+)([ywdhms]+)$');
|
var rangeRE = new RegExp('^([0-9]+)([ywdhms]+)$');
|
||||||
|
@ -107,7 +86,7 @@ class GraphControls extends Component {
|
||||||
this.rangeRef.current.value = rangeText;
|
this.rangeRef.current.value = rangeText;
|
||||||
}
|
}
|
||||||
|
|
||||||
increaseRange = (event) => {
|
increaseRange = () => {
|
||||||
for (let range of this.rangeSteps) {
|
for (let range of this.rangeSteps) {
|
||||||
let rangeSeconds = this.parseRange(range);
|
let rangeSeconds = this.parseRange(range);
|
||||||
if (this.props.range < rangeSeconds) {
|
if (this.props.range < rangeSeconds) {
|
||||||
|
@ -118,7 +97,7 @@ class GraphControls extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
decreaseRange = (event) => {
|
decreaseRange = () => {
|
||||||
for (let range of this.rangeSteps.slice().reverse()) {
|
for (let range of this.rangeSteps.slice().reverse()) {
|
||||||
let rangeSeconds = this.parseRange(range);
|
let rangeSeconds = this.parseRange(range);
|
||||||
if (this.props.range > rangeSeconds) {
|
if (this.props.range > rangeSeconds) {
|
||||||
|
@ -129,60 +108,6 @@ class GraphControls extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getBaseEndTime = () => {
|
|
||||||
return this.props.endTime || moment();
|
|
||||||
}
|
|
||||||
|
|
||||||
increaseEndTime = (event) => {
|
|
||||||
const endTime = moment(this.getBaseEndTime() + this.props.range*1000/2);
|
|
||||||
this.props.onChangeEndTime(endTime);
|
|
||||||
this.$endTime.datetimepicker('date', endTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
decreaseEndTime = (event) => {
|
|
||||||
const endTime = moment(this.getBaseEndTime() - this.props.range*1000/2);
|
|
||||||
this.props.onChangeEndTime(endTime);
|
|
||||||
this.$endTime.datetimepicker('date', endTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
clearEndTime = (event) => {
|
|
||||||
this.props.onChangeEndTime(null);
|
|
||||||
this.$endTime.datetimepicker('date', null);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.$endTime = window.$(this.endTimeRef.current);
|
|
||||||
|
|
||||||
this.$endTime.datetimepicker({
|
|
||||||
icons: {
|
|
||||||
today: 'fas fa-calendar-check',
|
|
||||||
},
|
|
||||||
buttons: {
|
|
||||||
//showClear: true,
|
|
||||||
showClose: true,
|
|
||||||
showToday: true,
|
|
||||||
},
|
|
||||||
sideBySide: true,
|
|
||||||
format: 'YYYY-MM-DD HH:mm:ss',
|
|
||||||
locale: 'en',
|
|
||||||
timeZone: 'UTC',
|
|
||||||
defaultDate: this.props.endTime,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$endTime.on('change.datetimepicker', e => {
|
|
||||||
console.log("CHANGE", e)
|
|
||||||
if (e.date) {
|
|
||||||
this.props.onChangeEndTime(e.date);
|
|
||||||
} else {
|
|
||||||
this.$endTime.datetimepicker('date', e.target.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
this.$endTime.datetimepicker('destroy');
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Form inline className="graph-controls" onSubmit={e => e.preventDefault()}>
|
<Form inline className="graph-controls" onSubmit={e => e.preventDefault()}>
|
||||||
|
@ -191,7 +116,6 @@ class GraphControls extends Component {
|
||||||
<Button title="Decrease range" onClick={this.decreaseRange}><FontAwesomeIcon icon="minus" fixedWidth/></Button>
|
<Button title="Decrease range" onClick={this.decreaseRange}><FontAwesomeIcon icon="minus" fixedWidth/></Button>
|
||||||
</InputGroupAddon>
|
</InputGroupAddon>
|
||||||
|
|
||||||
{/* <Input value={this.state.rangeInput} onChange={(e) => this.changeRangeInput(e.target.value)}/> */}
|
|
||||||
<Input
|
<Input
|
||||||
defaultValue={this.formatRange(this.props.range)}
|
defaultValue={this.formatRange(this.props.range)}
|
||||||
innerRef={this.rangeRef}
|
innerRef={this.rangeRef}
|
||||||
|
@ -203,33 +127,7 @@ class GraphControls extends Component {
|
||||||
</InputGroupAddon>
|
</InputGroupAddon>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
|
|
||||||
<InputGroup className="endtime-input" size="sm">
|
<TimeInput endTime={this.props.endTime} range={this.props.range} onChangeEndTime={this.props.onChangeEndTime} />
|
||||||
<InputGroupAddon addonType="prepend">
|
|
||||||
<Button title="Decrease end time" onClick={this.decreaseEndTime}><FontAwesomeIcon icon="chevron-left" fixedWidth/></Button>
|
|
||||||
</InputGroupAddon>
|
|
||||||
|
|
||||||
<Input
|
|
||||||
placeholder="End time"
|
|
||||||
// value={this.props.endTime ? this.props.endTime : ''}
|
|
||||||
innerRef={this.endTimeRef}
|
|
||||||
// onChange={this.props.onChangeEndTime}
|
|
||||||
onFocus={() => this.$endTime.datetimepicker('show')}
|
|
||||||
onBlur={() => this.$endTime.datetimepicker('hide')}
|
|
||||||
onKeyDown={(e) => ['Escape', 'Enter'].includes(e.key) && this.$endTime.datetimepicker('hide')}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* CAUTION: While the datetimepicker also has an option to show a 'clear' button,
|
|
||||||
that functionality is broken, so we create an external solution instead. */}
|
|
||||||
{this.props.endTime &&
|
|
||||||
<InputGroupAddon addonType="append">
|
|
||||||
<Button className="clear-endtime-btn" title="Clear end time" onClick={this.clearEndTime}><FontAwesomeIcon icon="times" fixedWidth/></Button>
|
|
||||||
</InputGroupAddon>
|
|
||||||
}
|
|
||||||
|
|
||||||
<InputGroupAddon addonType="append">
|
|
||||||
<Button title="Increase end time" onClick={this.increaseEndTime}><FontAwesomeIcon icon="chevron-right" fixedWidth/></Button>
|
|
||||||
</InputGroupAddon>
|
|
||||||
</InputGroup>
|
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
placeholder="Res. (s)"
|
placeholder="Res. (s)"
|
||||||
|
|
|
@ -18,6 +18,7 @@ import ExpressionInput from './ExpressionInput';
|
||||||
import GraphControls from './GraphControls';
|
import GraphControls from './GraphControls';
|
||||||
import Graph from './Graph';
|
import Graph from './Graph';
|
||||||
import DataTable from './DataTable';
|
import DataTable from './DataTable';
|
||||||
|
import TimeInput from './TimeInput';
|
||||||
|
|
||||||
class Panel extends Component {
|
class Panel extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -260,7 +261,12 @@ class Panel extends Component {
|
||||||
</TabPane>
|
</TabPane>
|
||||||
<TabPane tabId="table">
|
<TabPane tabId="table">
|
||||||
{this.state.type === 'table' &&
|
{this.state.type === 'table' &&
|
||||||
|
<>
|
||||||
|
<div class="table-controls">
|
||||||
|
<TimeInput endTime={this.state.endTime} range={this.state.range} onChangeEndTime={this.handleChangeEndTime} />
|
||||||
|
</div>
|
||||||
<DataTable data={this.state.data} />
|
<DataTable data={this.state.data} />
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
</TabPane>
|
</TabPane>
|
||||||
</TabContent>
|
</TabContent>
|
||||||
|
|
127
src/TimeInput.js
Normal file
127
src/TimeInput.js
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import { Button, InputGroup, InputGroupAddon, Input } from 'reactstrap';
|
||||||
|
|
||||||
|
import moment from 'moment-timezone';
|
||||||
|
|
||||||
|
import 'tempusdominus-core';
|
||||||
|
import 'tempusdominus-bootstrap-4';
|
||||||
|
import '../node_modules/tempusdominus-bootstrap-4/build/css/tempusdominus-bootstrap-4.min.css';
|
||||||
|
|
||||||
|
import { dom, library } from '@fortawesome/fontawesome-svg-core';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import {
|
||||||
|
faChevronLeft,
|
||||||
|
faChevronRight,
|
||||||
|
faCalendarCheck,
|
||||||
|
faArrowUp,
|
||||||
|
faArrowDown,
|
||||||
|
faTimes,
|
||||||
|
} from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
|
library.add(
|
||||||
|
faChevronLeft,
|
||||||
|
faChevronRight,
|
||||||
|
faCalendarCheck,
|
||||||
|
faArrowUp,
|
||||||
|
faArrowDown,
|
||||||
|
faTimes,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Sadly needed to also replace <i> within the date picker, since it's not a React component.
|
||||||
|
dom.watch();
|
||||||
|
|
||||||
|
class TimeInput extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.endTimeRef = React.createRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
getBaseEndTime = () => {
|
||||||
|
return this.props.endTime || moment();
|
||||||
|
}
|
||||||
|
|
||||||
|
increaseEndTime = (event) => {
|
||||||
|
const endTime = moment(this.getBaseEndTime() + this.props.range*1000/2);
|
||||||
|
this.props.onChangeEndTime(endTime);
|
||||||
|
this.$endTime.datetimepicker('date', endTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
decreaseEndTime = (event) => {
|
||||||
|
const endTime = moment(this.getBaseEndTime() - this.props.range*1000/2);
|
||||||
|
this.props.onChangeEndTime(endTime);
|
||||||
|
this.$endTime.datetimepicker('date', endTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
clearEndTime = (event) => {
|
||||||
|
this.props.onChangeEndTime(null);
|
||||||
|
this.$endTime.datetimepicker('date', null);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.$endTime = window.$(this.endTimeRef.current);
|
||||||
|
|
||||||
|
this.$endTime.datetimepicker({
|
||||||
|
icons: {
|
||||||
|
today: 'fas fa-calendar-check',
|
||||||
|
},
|
||||||
|
buttons: {
|
||||||
|
//showClear: true,
|
||||||
|
showClose: true,
|
||||||
|
showToday: true,
|
||||||
|
},
|
||||||
|
sideBySide: true,
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
locale: 'en',
|
||||||
|
timeZone: 'UTC',
|
||||||
|
defaultDate: this.props.endTime,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$endTime.on('change.datetimepicker', e => {
|
||||||
|
console.log("CHANGE", e)
|
||||||
|
if (e.date) {
|
||||||
|
this.props.onChangeEndTime(e.date);
|
||||||
|
} else {
|
||||||
|
this.$endTime.datetimepicker('date', e.target.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.$endTime.datetimepicker('destroy');
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<InputGroup className="endtime-input" size="sm">
|
||||||
|
<InputGroupAddon addonType="prepend">
|
||||||
|
<Button title="Decrease end time" onClick={this.decreaseEndTime}><FontAwesomeIcon icon="chevron-left" fixedWidth/></Button>
|
||||||
|
</InputGroupAddon>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
placeholder="End time"
|
||||||
|
// value={this.props.endTime ? this.props.endTime : ''}
|
||||||
|
innerRef={this.endTimeRef}
|
||||||
|
// onChange={this.props.onChangeEndTime}
|
||||||
|
onFocus={() => this.$endTime.datetimepicker('show')}
|
||||||
|
onBlur={() => this.$endTime.datetimepicker('hide')}
|
||||||
|
onKeyDown={(e) => ['Escape', 'Enter'].includes(e.key) && this.$endTime.datetimepicker('hide')}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* CAUTION: While the datetimepicker also has an option to show a 'clear' button,
|
||||||
|
that functionality is broken, so we create an external solution instead. */}
|
||||||
|
{this.props.endTime &&
|
||||||
|
<InputGroupAddon addonType="append">
|
||||||
|
<Button className="clear-endtime-btn" title="Clear end time" onClick={this.clearEndTime}><FontAwesomeIcon icon="times" fixedWidth/></Button>
|
||||||
|
</InputGroupAddon>
|
||||||
|
}
|
||||||
|
|
||||||
|
<InputGroupAddon addonType="append">
|
||||||
|
<Button title="Increase end time" onClick={this.increaseEndTime}><FontAwesomeIcon icon="chevron-right" fixedWidth/></Button>
|
||||||
|
</InputGroupAddon>
|
||||||
|
</InputGroup>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TimeInput;
|
Loading…
Reference in a new issue