Commit 51a95963 by Torkel Ödegaard Committed by GitHub

Merge pull request #14020 from grafana/12759-timeshift

12759 timeshift and panelTimeOverrides
parents 700c9642 6d91e06f
...@@ -81,7 +81,6 @@ export class DataPanel extends Component<Props, State> { ...@@ -81,7 +81,6 @@ export class DataPanel extends Component<Props, State> {
try { try {
const dataSourceSrv = getDatasourceSrv(); const dataSourceSrv = getDatasourceSrv();
const ds = await dataSourceSrv.get(datasource); const ds = await dataSourceSrv.get(datasource);
const queryOptions: DataQueryOptions = { const queryOptions: DataQueryOptions = {
timezone: 'browser', timezone: 'browser',
panelId: panelId, panelId: panelId,
......
...@@ -2,12 +2,15 @@ ...@@ -2,12 +2,15 @@
import React, { ComponentClass, PureComponent } from 'react'; import React, { ComponentClass, PureComponent } from 'react';
// Services // Services
import { getTimeSrv } from '../time_srv'; import { getTimeSrv, TimeSrv } from '../time_srv';
// Components // Components
import { PanelHeader } from './PanelHeader/PanelHeader'; import { PanelHeader } from './PanelHeader/PanelHeader';
import { DataPanel } from './DataPanel'; import { DataPanel } from './DataPanel';
// Utils
import { applyPanelTimeOverrides } from 'app/features/dashboard/utils/panel';
// Types // Types
import { PanelModel } from '../panel_model'; import { PanelModel } from '../panel_model';
import { DashboardModel } from '../dashboard_model'; import { DashboardModel } from '../dashboard_model';
...@@ -22,10 +25,13 @@ export interface Props { ...@@ -22,10 +25,13 @@ export interface Props {
export interface State { export interface State {
refreshCounter: number; refreshCounter: number;
renderCounter: number; renderCounter: number;
timeInfo?: string;
timeRange?: TimeRange; timeRange?: TimeRange;
} }
export class PanelChrome extends PureComponent<Props, State> { export class PanelChrome extends PureComponent<Props, State> {
timeSrv: TimeSrv = getTimeSrv();
constructor(props) { constructor(props) {
super(props); super(props);
...@@ -46,22 +52,26 @@ export class PanelChrome extends PureComponent<Props, State> { ...@@ -46,22 +52,26 @@ export class PanelChrome extends PureComponent<Props, State> {
} }
onRefresh = () => { onRefresh = () => {
const timeSrv = getTimeSrv(); console.log('onRefresh');
const timeRange = timeSrv.timeRange(); if (!this.isVisible) {
return;
}
const { panel } = this.props;
const timeData = applyPanelTimeOverrides(panel, this.timeSrv.timeRange());
this.setState(prevState => ({ this.setState({
...prevState,
refreshCounter: this.state.refreshCounter + 1, refreshCounter: this.state.refreshCounter + 1,
timeRange: timeRange, timeRange: timeData.timeRange,
})); timeInfo: timeData.timeInfo,
});
}; };
onRender = () => { onRender = () => {
console.log('onRender'); console.log('onRender');
this.setState(prevState => ({ this.setState({
...prevState,
renderCounter: this.state.renderCounter + 1, renderCounter: this.state.renderCounter + 1,
})); });
}; };
get isVisible() { get isVisible() {
...@@ -70,7 +80,7 @@ export class PanelChrome extends PureComponent<Props, State> { ...@@ -70,7 +80,7 @@ export class PanelChrome extends PureComponent<Props, State> {
render() { render() {
const { panel, dashboard } = this.props; const { panel, dashboard } = this.props;
const { refreshCounter, timeRange, renderCounter } = this.state; const { refreshCounter, timeRange, timeInfo, renderCounter } = this.state;
const { datasource, targets } = panel; const { datasource, targets } = panel;
const PanelComponent = this.props.component; const PanelComponent = this.props.component;
...@@ -78,7 +88,7 @@ export class PanelChrome extends PureComponent<Props, State> { ...@@ -78,7 +88,7 @@ export class PanelChrome extends PureComponent<Props, State> {
console.log('panelChrome render'); console.log('panelChrome render');
return ( return (
<div className="panel-container"> <div className="panel-container">
<PanelHeader panel={panel} dashboard={dashboard} /> <PanelHeader panel={panel} dashboard={dashboard} timeInfo={timeInfo} />
<div className="panel-content"> <div className="panel-content">
<DataPanel <DataPanel
datasource={datasource} datasource={datasource}
......
...@@ -9,6 +9,7 @@ import { PanelModel } from 'app/features/dashboard/panel_model'; ...@@ -9,6 +9,7 @@ import { PanelModel } from 'app/features/dashboard/panel_model';
export interface Props { export interface Props {
panel: PanelModel; panel: PanelModel;
dashboard: DashboardModel; dashboard: DashboardModel;
timeInfo: string;
} }
export class PanelHeader extends PureComponent<Props> { export class PanelHeader extends PureComponent<Props> {
...@@ -16,7 +17,7 @@ export class PanelHeader extends PureComponent<Props> { ...@@ -16,7 +17,7 @@ export class PanelHeader extends PureComponent<Props> {
const isFullscreen = false; const isFullscreen = false;
const isLoading = false; const isLoading = false;
const panelHeaderClass = classNames({ 'panel-header': true, 'grid-drag-handle': !isFullscreen }); const panelHeaderClass = classNames({ 'panel-header': true, 'grid-drag-handle': !isFullscreen });
const { panel, dashboard } = this.props; const { panel, dashboard, timeInfo } = this.props;
return ( return (
<div className={panelHeaderClass}> <div className={panelHeaderClass}>
...@@ -39,10 +40,11 @@ export class PanelHeader extends PureComponent<Props> { ...@@ -39,10 +40,11 @@ export class PanelHeader extends PureComponent<Props> {
</span> </span>
<PanelHeaderMenu panel={panel} dashboard={dashboard} /> <PanelHeaderMenu panel={panel} dashboard={dashboard} />
{timeInfo && (
<span className="panel-time-info"> <span className="panel-time-info">
<i className="fa fa-clock-o" /> 4m <i className="fa fa-clock-o" /> {timeInfo}
</span> </span>
)}
</div> </div>
</div> </div>
</div> </div>
......
...@@ -42,6 +42,14 @@ export class PanelModel { ...@@ -42,6 +42,14 @@ export class PanelModel {
datasource: string; datasource: string;
thresholds?: any; thresholds?: any;
snapshotData?: any;
timeFrom?: any;
timeShift?: any;
hideTimeOverride?: any;
maxDataPoints?: number;
interval?: string;
// non persisted // non persisted
fullscreen: boolean; fullscreen: boolean;
isEditing: boolean; isEditing: boolean;
......
...@@ -20,7 +20,7 @@ export class TimeSrv { ...@@ -20,7 +20,7 @@ export class TimeSrv {
private autoRefreshBlocked: boolean; private autoRefreshBlocked: boolean;
/** @ngInject */ /** @ngInject */
constructor(private $rootScope, private $timeout, private $location, private timer, private contextSrv) { constructor($rootScope, private $timeout, private $location, private timer, private contextSrv) {
// default time // default time
this.time = { from: '6h', to: 'now' }; this.time = { from: '6h', to: 'now' };
...@@ -189,7 +189,6 @@ export class TimeSrv { ...@@ -189,7 +189,6 @@ export class TimeSrv {
this.$location.search(urlParams); this.$location.search(urlParams);
} }
this.$rootScope.appEvent('time-range-changed', this.time);
this.$timeout(this.refreshDashboard.bind(this), 0); this.$timeout(this.refreshDashboard.bind(this), 0);
} }
......
import appEvents from 'app/core/app_events'; // Store
import store from 'app/core/store';
// Models
import { DashboardModel } from 'app/features/dashboard/dashboard_model'; import { DashboardModel } from 'app/features/dashboard/dashboard_model';
import { PanelModel } from 'app/features/dashboard/panel_model'; import { PanelModel } from 'app/features/dashboard/panel_model';
import store from 'app/core/store'; import { TimeRange } from 'app/types/series';
// Utils
import { isString as _isString } from 'lodash';
import * as rangeUtil from 'app/core/utils/rangeutil';
import * as dateMath from 'app/core/utils/datemath';
import appEvents from 'app/core/app_events';
// Services
import templateSrv from 'app/features/templating/template_srv';
// Constants
import { LS_PANEL_COPY_KEY } from 'app/core/constants'; import { LS_PANEL_COPY_KEY } from 'app/core/constants';
export const removePanel = (dashboard: DashboardModel, panel: PanelModel, ask: boolean) => { export const removePanel = (dashboard: DashboardModel, panel: PanelModel, ask: boolean) => {
...@@ -84,3 +98,70 @@ export const toggleLegend = (panel: PanelModel) => { ...@@ -84,3 +98,70 @@ export const toggleLegend = (panel: PanelModel) => {
// panel.legend.show = !panel.legend.show; // panel.legend.show = !panel.legend.show;
refreshPanel(panel); refreshPanel(panel);
}; };
export interface TimeOverrideResult {
timeRange: TimeRange;
timeInfo: string;
}
export function applyPanelTimeOverrides(panel: PanelModel, timeRange: TimeRange): TimeOverrideResult {
const newTimeData = {
timeInfo: '',
timeRange: timeRange,
};
if (panel.timeFrom) {
const timeFromInterpolated = templateSrv.replace(panel.timeFrom, panel.scopedVars);
const timeFromInfo = rangeUtil.describeTextRange(timeFromInterpolated);
if (timeFromInfo.invalid) {
newTimeData.timeInfo = 'invalid time override';
return newTimeData;
}
if (_isString(timeRange.raw.from)) {
const timeFromDate = dateMath.parse(timeFromInfo.from);
newTimeData.timeInfo = timeFromInfo.display;
newTimeData.timeRange = {
from: timeFromDate,
to: dateMath.parse(timeFromInfo.to),
raw: {
from: timeFromInfo.from,
to: timeFromInfo.to,
},
};
}
}
if (panel.timeShift) {
const timeShiftInterpolated = templateSrv.replace(panel.timeShift, panel.scopedVars);
const timeShiftInfo = rangeUtil.describeTextRange(timeShiftInterpolated);
if (timeShiftInfo.invalid) {
newTimeData.timeInfo = 'invalid timeshift';
return newTimeData;
}
const timeShift = '-' + timeShiftInterpolated;
newTimeData.timeInfo += ' timeshift ' + timeShift;
newTimeData.timeRange = {
from: dateMath.parseDateMath(timeShift, timeRange.from, false),
to: dateMath.parseDateMath(timeShift, timeRange.to, true),
raw: {
from: timeRange.from,
to: timeRange.to,
},
};
}
if (panel.hideTimeOverride) {
newTimeData.timeInfo = '';
}
return newTimeData;
}
export function getResolution(panel: PanelModel): number {
const htmlEl = document.getElementsByTagName('html')[0];
const width = htmlEl.getBoundingClientRect().width; // https://stackoverflow.com/a/21454625
return panel.maxDataPoints ? panel.maxDataPoints : Math.ceil(width * (panel.gridPos.w / 24));
}
import $ from 'jquery';
import _ from 'lodash'; import _ from 'lodash';
import config from 'app/core/config';
import kbn from 'app/core/utils/kbn'; import kbn from 'app/core/utils/kbn';
import config from 'app/core/config';
import { PanelCtrl } from 'app/features/panel/panel_ctrl'; import { PanelCtrl } from 'app/features/panel/panel_ctrl';
import * as rangeUtil from 'app/core/utils/rangeutil';
import * as dateMath from 'app/core/utils/datemath';
import { getExploreUrl } from 'app/core/utils/explore'; import { getExploreUrl } from 'app/core/utils/explore';
import { metricsTabDirective } from './metrics_tab'; import { metricsTabDirective } from './metrics_tab';
import { applyPanelTimeOverrides, getResolution } from 'app/features/dashboard/utils/panel';
class MetricsPanelCtrl extends PanelCtrl { class MetricsPanelCtrl extends PanelCtrl {
scope: any; scope: any;
...@@ -134,14 +133,11 @@ class MetricsPanelCtrl extends PanelCtrl { ...@@ -134,14 +133,11 @@ class MetricsPanelCtrl extends PanelCtrl {
updateTimeRange(datasource?) { updateTimeRange(datasource?) {
this.datasource = datasource || this.datasource; this.datasource = datasource || this.datasource;
this.range = this.timeSrv.timeRange(); this.range = this.timeSrv.timeRange();
this.resolution = getResolution(this.panel);
this.applyPanelTimeOverrides(); const newTimeData = applyPanelTimeOverrides(this.panel, this.range);
this.timeInfo = newTimeData.timeInfo;
if (this.panel.maxDataPoints) { this.range = newTimeData.timeRange;
this.resolution = this.panel.maxDataPoints;
} else {
this.resolution = Math.ceil($(window).width() * (this.panel.gridPos.w / 24));
}
this.calculateInterval(); this.calculateInterval();
...@@ -163,48 +159,6 @@ class MetricsPanelCtrl extends PanelCtrl { ...@@ -163,48 +159,6 @@ class MetricsPanelCtrl extends PanelCtrl {
this.intervalMs = res.intervalMs; this.intervalMs = res.intervalMs;
} }
applyPanelTimeOverrides() {
this.timeInfo = '';
// check panel time overrrides
if (this.panel.timeFrom) {
const timeFromInterpolated = this.templateSrv.replace(this.panel.timeFrom, this.panel.scopedVars);
const timeFromInfo = rangeUtil.describeTextRange(timeFromInterpolated);
if (timeFromInfo.invalid) {
this.timeInfo = 'invalid time override';
return;
}
if (_.isString(this.range.raw.from)) {
const timeFromDate = dateMath.parse(timeFromInfo.from);
this.timeInfo = timeFromInfo.display;
this.range.from = timeFromDate;
this.range.to = dateMath.parse(timeFromInfo.to);
this.range.raw.from = timeFromInfo.from;
this.range.raw.to = timeFromInfo.to;
}
}
if (this.panel.timeShift) {
const timeShiftInterpolated = this.templateSrv.replace(this.panel.timeShift, this.panel.scopedVars);
const timeShiftInfo = rangeUtil.describeTextRange(timeShiftInterpolated);
if (timeShiftInfo.invalid) {
this.timeInfo = 'invalid timeshift';
return;
}
const timeShift = '-' + timeShiftInterpolated;
this.timeInfo += ' timeshift ' + timeShift;
this.range.from = dateMath.parseDateMath(timeShift, this.range.from, false);
this.range.to = dateMath.parseDateMath(timeShift, this.range.to, true);
this.range.raw = { from: this.range.from, to: this.range.to };
}
if (this.panel.hideTimeOverride) {
this.timeInfo = '';
}
}
issueQueries(datasource) { issueQueries(datasource) {
this.datasource = datasource; this.datasource = datasource;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment