Commit cd4619da by Torkel Ödegaard

working on react data / query exectution

parent 2e1d45a8
......@@ -8,7 +8,8 @@ import appEvents from 'app/core/app_events';
import Drop from 'tether-drop';
import colors from 'app/core/utils/colors';
import { BackendSrv, setBackendSrv } from 'app/core/services/backend_srv';
import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
import { TimeSrv, setTimeSrv } from 'app/features/dashboard/time_srv';
import { DatasourceSrv, setDatasourceSrv } from 'app/features/plugins/datasource_srv';
import { AngularLoader, setAngularLoader } from 'app/core/services/AngularLoader';
import { configureStore } from 'app/store/configureStore';
......@@ -23,12 +24,15 @@ export class GrafanaCtrl {
contextSrv,
bridgeSrv,
backendSrv: BackendSrv,
timeSrv: TimeSrv,
datasourceSrv: DatasourceSrv,
angularLoader: AngularLoader
) {
// make angular loader service available to react components
setAngularLoader(angularLoader);
setBackendSrv(backendSrv);
setDatasourceSrv(datasourceSrv);
setTimeSrv(timeSrv);
configureStore();
$scope.init = () => {
......
// Library
import React, { Component } from 'react';
import React, { PureComponent } from 'react';
// Services
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
// Types
import { TimeRange, LoadingState } from 'app/types';
interface RenderProps {
loading: LoadingState;
......@@ -9,6 +15,11 @@ interface RenderProps {
export interface Props {
datasource: string | null;
queries: any[];
panelId?: number;
dashboardId?: number;
isVisible?: boolean;
timeRange?: TimeRange;
refreshCounter: number;
children: (r: RenderProps) => JSX.Element;
}
......@@ -18,16 +29,13 @@ export interface State {
data: any;
}
export enum LoadingState {
NotStarted = 'NotStarted',
Loading = 'Loading',
Done = 'Done',
Error = 'Error',
}
export interface PanelProps extends RenderProps {}
export class DataPanel extends PureComponent<Props, State> {
static defaultProps = {
isVisible: true,
panelId: 1,
dashboardId: 1,
};
export class DataPanel extends Component<Props, State> {
constructor(props: Props) {
super(props);
......@@ -44,20 +52,50 @@ export class DataPanel extends Component<Props, State> {
}
issueQueries = async () => {
const { isVisible, queries, datasource, panelId, dashboardId, timeRange } = this.props;
if (!isVisible) {
return;
}
if (!queries.length) {
this.setState({ data: [], loading: LoadingState.Done });
return;
}
this.setState({ loading: LoadingState.Loading });
await new Promise(resolve => {
setTimeout(() => {
this.setState({ loading: LoadingState.Done, data: [{ value: 10 }], isFirstLoad: false });
}, 500);
});
try {
const dataSourceSrv = getDatasourceSrv();
const ds = await dataSourceSrv.get(datasource);
const queryOptions = {
timezone: 'browser',
panelId: panelId,
dashboardId: dashboardId,
range: timeRange,
rangeRaw: timeRange.raw,
interval: '1s',
intervalMs: 1000,
targets: queries,
maxDataPoints: 500,
scopedVars: {},
cacheTimeout: null,
};
const resp = await ds.query(queryOptions);
console.log(resp);
} catch (err) {
console.log('Loading error', err);
this.setState({ loading: LoadingState.Error });
}
};
render() {
const { data, loading, isFirstLoad } = this.state;
console.log('data panel render');
if (isFirstLoad && loading === LoadingState.Loading) {
if (isFirstLoad && (loading === LoadingState.Loading || loading === LoadingState.NotStarted)) {
return (
<div className="loading">
<p>Loading</p>
......
import React, { ComponentClass } from 'react';
// Libraries
import React, { ComponentClass, PureComponent } from 'react';
// Services
import { getTimeSrv } from '../time_srv';
// Components
import { PanelHeader } from './PanelHeader';
import { DataPanel } from './DataPanel';
// Types
import { PanelModel } from '../panel_model';
import { DashboardModel } from '../dashboard_model';
import { PanelHeader } from './PanelHeader';
import { DataPanel, PanelProps } from './DataPanel';
import { TimeRange, PanelProps } from 'app/types';
export interface Props {
panel: PanelModel;
......@@ -10,30 +19,59 @@ export interface Props {
component: ComponentClass<PanelProps>;
}
interface State {}
export class PanelChrome extends React.Component<Props, State> {
panelComponent: DataPanel;
export interface State {
refreshCounter: number;
timeRange?: TimeRange;
}
export class PanelChrome extends PureComponent<Props, State> {
constructor(props) {
super(props);
this.state = {
refreshCounter: 0,
};
}
render() {
const { datasource, targets } = this.props.panel;
const PanelComponent = this.props.component;
componentDidMount() {
this.props.dashboard.panelInitialized(this.props.panel);
this.props.panel.events.on('refresh', this.onRefresh);
}
componentWillUnmount() {
this.props.panel.events.off('refresh', this.onRefresh);
}
onRefresh = () => {
const timeSrv = getTimeSrv();
const timeRange = timeSrv.timeRange();
// if (!PanelComponent) {
// PanelComponent = dataPanels[type] = DataPanelWrapper(this.props.component);
// }
this.setState({
refreshCounter: this.state.refreshCounter + 1,
timeRange: timeRange,
});
};
console.log('PanelChrome render', PanelComponent);
get isVisible() {
return this.props.dashboard.otherPanelInFullscreen(this.props.panel);
}
render() {
const { panel, dashboard } = this.props;
const { datasource, targets } = panel;
const { refreshCounter } = this.state;
const PanelComponent = this.props.component;
return (
<div className="panel-container">
<PanelHeader panel={this.props.panel} dashboard={this.props.dashboard} />
<PanelHeader panel={panel} dashboard={dashboard} />
<div className="panel-content">
<DataPanel datasource={datasource} queries={targets}>
<DataPanel
datasource={datasource}
queries={targets}
isVisible={this.isVisible}
refreshCounter={refreshCounter}
>
{({ loading, data }) => {
return <PanelComponent loading={loading} data={data} />;
}}
......
// Libraries
import moment from 'moment';
import _ from 'lodash';
import coreModule from 'app/core/core_module';
// Utils
import kbn from 'app/core/utils/kbn';
import coreModule from 'app/core/core_module';
import * as dateMath from 'app/core/utils/datemath';
// Types
import { TimeRange } from 'app/types';
export class TimeSrv {
time: any;
refreshTimer: any;
......@@ -200,7 +206,7 @@ export class TimeSrv {
return range;
}
timeRange() {
timeRange(): TimeRange {
// make copies if they are moment (do not want to return out internal moment, because they are mutable!)
const raw = {
from: moment.isMoment(this.time.from) ? moment(this.time.from) : this.time.from,
......@@ -222,17 +228,21 @@ export class TimeSrv {
const timespan = range.to.valueOf() - range.from.valueOf();
const center = range.to.valueOf() - timespan / 2;
let to = center + timespan * factor / 2;
let from = center - timespan * factor / 2;
if (to > Date.now() && range.to <= Date.now()) {
const offset = to - Date.now();
from = from - offset;
to = Date.now();
}
const to = center + timespan * factor / 2;
const from = center - timespan * factor / 2;
this.setTime({ from: moment.utc(from), to: moment.utc(to) });
}
}
let singleton;
export function setTimeSrv(srv: TimeSrv) {
singleton = srv;
}
export function getTimeSrv(): TimeSrv {
return singleton;
}
coreModule.service('timeSrv', TimeSrv);
......@@ -145,7 +145,6 @@ module.directive('grafanaPanel', ($rootScope, $document, $timeout) => {
ctrl.calculatePanelHeight();
ctrl.events.on('render', () => {
console.log('panel_directive: render', ctrl.panel.id);
if (transparentLastState !== ctrl.panel.transparent) {
panelContainer.toggleClass('panel-transparent', ctrl.panel.transparent === true);
transparentLastState = ctrl.panel.transparent;
......
......@@ -162,5 +162,15 @@ export class DatasourceSrv {
}
}
let singleton: DatasourceSrv;
export function setDatasourceSrv(srv: DatasourceSrv) {
singleton = srv;
}
export function getDatasourceSrv(): DatasourceSrv {
return singleton;
}
coreModule.service('datasourceSrv', DatasourceSrv);
export default DatasourceSrv;
import angular from 'angular';
import coreModule from 'app/core/core_module';
import _ from 'lodash';
export class CloudWatchQueryParameter {
......@@ -239,5 +240,5 @@ export class CloudWatchQueryParameterCtrl {
}
}
angular.module('grafana.controllers').directive('cloudwatchQueryParameter', CloudWatchQueryParameter);
angular.module('grafana.controllers').controller('CloudWatchQueryParameterCtrl', CloudWatchQueryParameterCtrl);
coreModule.directive('cloudwatchQueryParameter', CloudWatchQueryParameter);
coreModule.controller('CloudWatchQueryParameterCtrl', CloudWatchQueryParameterCtrl);
import angular from 'angular';
import coreModule from 'app/core/core_module';
import _ from 'lodash';
import * as queryDef from './query_def';
......@@ -226,6 +226,5 @@ export class ElasticBucketAggCtrl {
}
}
const module = angular.module('grafana.directives');
module.directive('elasticBucketAgg', elasticBucketAgg);
module.controller('ElasticBucketAggCtrl', ElasticBucketAggCtrl);
coreModule.directive('elasticBucketAgg', elasticBucketAgg);
coreModule.controller('ElasticBucketAggCtrl', ElasticBucketAggCtrl);
import angular from 'angular';
import coreModule from 'app/core/core_module';
import _ from 'lodash';
import * as queryDef from './query_def';
......@@ -203,6 +203,5 @@ export class ElasticMetricAggCtrl {
}
}
const module = angular.module('grafana.directives');
module.directive('elasticMetricAgg', elasticMetricAgg);
module.controller('ElasticMetricAggCtrl', ElasticMetricAggCtrl);
coreModule.directive('elasticMetricAgg', elasticMetricAgg);
coreModule.controller('ElasticMetricAggCtrl', ElasticMetricAggCtrl);
import angular from 'angular';
import _ from 'lodash';
import $ from 'jquery';
import rst2html from 'rst2html';
import Drop from 'tether-drop';
import coreModule from 'app/core/core_module';
/** @ngInject */
export function graphiteAddFunc($compile) {
......@@ -130,7 +130,7 @@ export function graphiteAddFunc($compile) {
};
}
angular.module('grafana.directives').directive('graphiteAddFunc', graphiteAddFunc);
coreModule.directive('graphiteAddFunc', graphiteAddFunc);
function createFunctionDropDownMenu(funcDefs) {
const categories = {};
......
import angular from 'angular';
import _ from 'lodash';
import $ from 'jquery';
import rst2html from 'rst2html';
import coreModule from 'app/core/core_module';
/** @ngInject */
export function graphiteFuncEditor($compile, templateSrv, popoverSrv) {
......@@ -315,4 +315,4 @@ export function graphiteFuncEditor($compile, templateSrv, popoverSrv) {
};
}
angular.module('grafana.directives').directive('graphiteFuncEditor', graphiteFuncEditor);
coreModule.directive('graphiteFuncEditor', graphiteFuncEditor);
import angular from 'angular';
import coreModule from 'app/core/core_module';
import _ from 'lodash';
import * as options from './constants';
import kbn from 'app/core/utils/kbn';
......@@ -83,5 +83,5 @@ export class StackdriverAggregationCtrl {
}
}
angular.module('grafana.controllers').directive('stackdriverAggregation', StackdriverAggregation);
angular.module('grafana.controllers').controller('StackdriverAggregationCtrl', StackdriverAggregationCtrl);
coreModule.directive('stackdriverAggregation', StackdriverAggregation);
coreModule.controller('StackdriverAggregationCtrl', StackdriverAggregationCtrl);
import angular from 'angular';
import coreModule from 'app/core/core_module';
import _ from 'lodash';
import { FilterSegments, DefaultRemoveFilterValue } from './filter_segments';
import appEvents from 'app/core/app_events';
......@@ -281,5 +281,5 @@ export class StackdriverFilterCtrl {
}
}
angular.module('grafana.controllers').directive('stackdriverFilter', StackdriverFilter);
angular.module('grafana.controllers').controller('StackdriverFilterCtrl', StackdriverFilterCtrl);
coreModule.directive('stackdriverFilter', StackdriverFilter);
coreModule.controller('StackdriverFilterCtrl', StackdriverFilterCtrl);
......@@ -80,7 +80,6 @@ class GraphElement {
this.annotations = this.ctrl.annotations || [];
this.buildFlotPairs(this.data);
const graphHeight = this.elem.height();
console.log('graphHeight', graphHeight);
updateLegendValues(this.data, this.panel, graphHeight);
this.ctrl.events.emit('render-legend');
......
import angular from 'angular';
import _ from 'lodash';
import $ from 'jquery';
import baron from 'baron';
import coreModule from 'app/core/core_module';
const module = angular.module('grafana.directives');
module.directive('graphLegend', (popoverSrv, $timeout) => {
coreModule.directive('graphLegend', (popoverSrv, $timeout) => {
return {
link: (scope, elem) => {
let firstRender = true;
......
import _ from 'lodash';
import angular from 'angular';
import coreModule from 'app/core/core_module';
/** @ngInject */
export function SeriesOverridesCtrl($scope, $element, popoverSrv) {
......@@ -156,4 +156,4 @@ export function SeriesOverridesCtrl($scope, $element, popoverSrv) {
$scope.updateCurrentOverrides();
}
angular.module('grafana.controllers').controller('SeriesOverridesCtrl', SeriesOverridesCtrl);
coreModule.controller('SeriesOverridesCtrl', SeriesOverridesCtrl);
import React, { PureComponent } from 'react';
import { PanelProps } from 'app/features/dashboard/dashgrid/DataPanel';
import { PanelProps } from 'app/types';
interface Options {
showBars: boolean;
......@@ -22,6 +22,8 @@ export class Graph2 extends PureComponent<Props> {
value = data[0].value;
}
console.log('graph2 render');
return <h2>Text Panel {value}</h2>;
}
}
......
import angular from 'angular';
import _ from 'lodash';
import $ from 'jquery';
import * as d3 from 'd3';
import { contextSrv } from 'app/core/core';
import { tickStep } from 'app/core/utils/ticks';
import { getColorScale, getOpacityScale } from './color_scale';
const module = angular.module('grafana.directives');
import coreModule from 'app/core/core_module';
const LEGEND_HEIGHT_PX = 6;
const LEGEND_WIDTH_PX = 100;
......@@ -16,7 +14,7 @@ const LEGEND_VALUE_MARGIN = 0;
/**
* Color legend for heatmap editor.
*/
module.directive('colorLegend', () => {
coreModule.directive('colorLegend', () => {
return {
restrict: 'E',
template: '<div class="heatmap-color-legend"><svg width="16.5rem" height="24px"></svg></div>',
......@@ -52,7 +50,7 @@ module.directive('colorLegend', () => {
/**
* Heatmap legend with scale values.
*/
module.directive('heatmapLegend', () => {
coreModule.directive('heatmapLegend', () => {
return {
restrict: 'E',
template: `<div class="heatmap-color-legend"><svg width="${LEGEND_WIDTH_PX}px" height="${LEGEND_HEIGHT_PX}px"></svg></div>`,
......
import React, { PureComponent } from 'react';
import { PanelProps } from 'app/features/dashboard/dashgrid/DataPanel';
import { PanelProps } from 'app/types';
export class Text2 extends PureComponent<PanelProps> {
constructor(props) {
......@@ -14,7 +14,7 @@ export class Text2 extends PureComponent<PanelProps> {
value = data[0].value;
}
return <h2>Graph Panel! {value}</h2>;
return <h2>Text Panel! {value}</h2>;
}
}
......
......@@ -9,6 +9,8 @@ import { ApiKey, ApiKeysState, NewApiKey } from './apiKeys';
import { Invitee, OrgUser, User, UsersState } from './user';
import { DataSource, DataSourcesState } from './datasources';
import { PluginMeta, Plugin, PluginsState } from './plugins';
import { TimeRange, LoadingState } from './queries';
import { PanelProps } from './panel';
export {
Team,
......@@ -45,6 +47,9 @@ export {
OrgUser,
User,
UsersState,
TimeRange,
LoadingState,
PanelProps,
};
export interface StoreState {
......
import { LoadingState } from './queries';
export interface PanelProps {
data: any;
loading: LoadingState;
}
import { Moment } from 'moment';
export enum LoadingState {
NotStarted = 'NotStarted',
Loading = 'Loading',
Done = 'Done',
Error = 'Error',
}
export interface RawTimeRange {
from: Moment | string;
to: Moment | string;
}
export interface TimeRange {
from: Moment;
to: Moment;
raw: RawTimeRange;
}
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