Queries: Extract queries from dashboard (#29349)

* Moving query stuff out of dashboard folder

* Moved more stuff

* Moving more stuff

* Update

* WIP test page

* Minor change

* Before big changes

* Fixed test
This commit is contained in:
Torkel Ödegaard 2020-11-26 18:12:02 +01:00 committed by GitHub
parent 43bd492565
commit 2179aa0fa7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 156 additions and 105 deletions

View File

@ -25,7 +25,7 @@ import { Observable, of } from 'rxjs';
import { map, mergeMap } from 'rxjs/operators';
import { AnnotationQueryOptions, AnnotationQueryResponse } from './types';
import { standardAnnotationSupport } from './standardAnnotationSupport';
import { runRequest } from '../dashboard/state/runRequest';
import { runRequest } from '../query/state/runRequest';
let counter = 100;
function getNextRequestId() {

View File

@ -12,7 +12,7 @@ import { InspectStatsTab } from './InspectStatsTab';
import { QueryInspector } from './QueryInspector';
import { InspectTab } from './types';
import { DashboardModel, PanelModel } from '../../state';
import { GetDataOptions } from '../../state/PanelQueryRunner';
import { GetDataOptions } from '../../../query/state/PanelQueryRunner';
interface Props {
dashboard: DashboardModel;

View File

@ -19,7 +19,7 @@ import { getPanelInspectorStyles } from './styles';
import { config } from 'app/core/config';
import { saveAs } from 'file-saver';
import { css } from 'emotion';
import { GetDataOptions } from '../../state/PanelQueryRunner';
import { GetDataOptions } from '../../../query/state/PanelQueryRunner';
import { QueryOperationRow } from 'app/core/components/QueryOperationRow/QueryOperationRow';
import { PanelModel } from 'app/features/dashboard/state';
import { DetailText } from './DetailText';

View File

@ -5,7 +5,7 @@ import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
import { PanelPlugin } from '@grafana/data';
import { StoreState } from 'app/types';
import { GetDataOptions } from '../../state/PanelQueryRunner';
import { GetDataOptions } from '../../../query/state/PanelQueryRunner';
import { usePanelLatestData } from '../PanelEditor/usePanelLatestData';
import { InspectContent } from './InspectContent';
import { useDatasourceMetadata, useInspectTabs } from './hooks';

View File

@ -0,0 +1,16 @@
import React, { PureComponent } from 'react';
import { QueriesTab } from 'app/features/query/components/QueriesTab';
import { DashboardModel, PanelModel } from '../../state';
interface Props {
panel: PanelModel;
dashboard: DashboardModel;
}
export class PanelEditorQueries extends PureComponent<Props> {
render() {
const { panel, dashboard } = this.props;
return <QueriesTab panel={panel} dashboard={dashboard} />;
}
}

View File

@ -2,13 +2,13 @@ import React, { PureComponent } from 'react';
import { config } from 'app/core/config';
import { css } from 'emotion';
import { IconName, stylesFactory, Tab, TabContent, TabsBar } from '@grafana/ui';
import { QueriesTab } from '../../panel_editor/QueriesTab';
import { AlertTab } from 'app/features/alerting/AlertTab';
import { TransformationsEditor } from '../TransformationsEditor/TransformationsEditor';
import { DashboardModel, PanelModel } from '../../state';
import { PanelEditorTab, PanelEditorTabId } from './types';
import { Subscription } from 'rxjs';
import { PanelQueriesChangedEvent, PanelTransformationsChangedEvent } from 'app/types/events';
import { PanelEditorQueries } from './PanelEditorQueries';
interface PanelEditorTabsProps {
panel: PanelModel;
@ -76,7 +76,7 @@ export class PanelEditorTabs extends PureComponent<PanelEditorTabsProps> {
})}
</TabsBar>
<TabContent className={styles.tabContent}>
{activeTab.id === PanelEditorTabId.Query && <QueriesTab panel={panel} dashboard={dashboard} />}
{activeTab.id === PanelEditorTabId.Query && <PanelEditorQueries panel={panel} dashboard={dashboard} />}
{activeTab.id === PanelEditorTabId.Alert && <AlertTab panel={panel} dashboard={dashboard} />}
{activeTab.id === PanelEditorTabId.Transform && <TransformationsEditor panel={panel} />}
</TabContent>

View File

@ -6,7 +6,7 @@ import { changePanelPlugin } from '../../state/actions';
import { StoreState } from 'app/types';
import { PanelModel } from '../../state/PanelModel';
import { connect, MapStateToProps, MapDispatchToProps } from 'react-redux';
import { VizTypePicker, getAllPanelPluginMeta, filterPluginList } from '../../panel_editor/VizTypePicker';
import { VizTypePicker, getAllPanelPluginMeta, filterPluginList } from '../VizTypePicker/VizTypePicker';
import { Field } from '@grafana/ui/src/components/Forms/Field';
interface OwnProps {

View File

@ -2,7 +2,7 @@ import { DataQueryError, LoadingState, PanelData } from '@grafana/data';
import { useEffect, useRef, useState } from 'react';
import { PanelModel } from '../../state';
import { Unsubscribable } from 'rxjs';
import { GetDataOptions } from '../../state/PanelQueryRunner';
import { GetDataOptions } from '../../../query/state/PanelQueryRunner';
interface UsePanelLatestData {
data?: PanelData;

View File

@ -3,7 +3,7 @@ import { GrafanaTheme, PanelPluginMeta, PluginState } from '@grafana/data';
import { Badge, BadgeProps, styleMixins, stylesFactory, useTheme } from '@grafana/ui';
import { css, cx } from 'emotion';
import { selectors } from '@grafana/e2e-selectors';
import { isUnsignedPluginSignature, PluginSignatureBadge } from '../../plugins/PluginSignatureBadge';
import { isUnsignedPluginSignature, PluginSignatureBadge } from '../../../plugins/PluginSignatureBadge';
interface Props {
isCurrent: boolean;

View File

@ -12,7 +12,7 @@ import {
FieldColorConfigSettings,
} from '@grafana/data';
import { ComponentClass } from 'react';
import { PanelQueryRunner } from './PanelQueryRunner';
import { PanelQueryRunner } from '../../query/state/PanelQueryRunner';
import { setDataSourceSrv } from '@grafana/runtime';
class TablePanelCtrl {}

View File

@ -25,7 +25,7 @@ import {
} from '@grafana/data';
import { EDIT_PANEL_ID } from 'app/core/constants';
import config from 'app/core/config';
import { PanelQueryRunner } from './PanelQueryRunner';
import { PanelQueryRunner } from '../../query/state/PanelQueryRunner';
import { getDatasourceSrv } from '../../plugins/datasource_srv';
import { PanelOptionsChangedEvent, PanelQueriesChangedEvent, PanelTransformationsChangedEvent } from 'app/types/events';

View File

@ -1,67 +1,5 @@
import { getDashboardSrv } from '../services/DashboardSrv';
import { DashboardModel } from './DashboardModel';
import { PanelData, LoadingState, DataSourceApi, CoreApp, urlUtil } from '@grafana/data';
import {
reportMetaAnalytics,
MetaAnalyticsEventName,
DataRequestEventPayload,
DashboardViewEventPayload,
} from '@grafana/runtime';
export function emitDataRequestEvent(datasource: DataSourceApi) {
let done = false;
return (data: PanelData) => {
if (!data.request || done || data.request.app === CoreApp.Explore) {
return;
}
const params = urlUtil.getUrlSearchParams();
if (params.editPanel != null) {
return;
}
if (data.state !== LoadingState.Done && data.state !== LoadingState.Error) {
return;
}
const eventData: DataRequestEventPayload = {
eventName: MetaAnalyticsEventName.DataRequest,
datasourceName: datasource.name,
datasourceId: datasource.id,
panelId: data.request.panelId,
dashboardId: data.request.dashboardId,
dataSize: 0,
duration: data.request.endTime! - data.request.startTime,
};
// enrich with dashboard info
const dashboard = getDashboardSrv().getCurrent();
if (dashboard) {
eventData.dashboardId = dashboard.id;
eventData.dashboardName = dashboard.title;
eventData.dashboardUid = dashboard.uid;
eventData.folderName = dashboard.meta.folderTitle;
}
if (data.series && data.series.length > 0) {
// estimate size
eventData.dataSize = data.series.length;
}
if (data.error) {
eventData.error = data.error.message;
}
reportMetaAnalytics(eventData);
// this done check is to make sure we do not double emit events in case
// there are multiple responses with done state
done = true;
};
}
import { reportMetaAnalytics, MetaAnalyticsEventName, DashboardViewEventPayload } from '@grafana/runtime';
export function emitDashboardViewEvent(dashboard: DashboardModel) {
const eventData: DashboardViewEventPayload = {

View File

@ -2,7 +2,7 @@ import { applyFieldOverrides, DefaultTimeRange, LoadingState, PanelData } from '
import { config } from 'app/core/config';
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
import { DashboardModel, PanelModel } from '../state';
import { getProcessedDataFrames } from '../state/runRequest';
import { getProcessedDataFrames } from '../../query/state/runRequest';
export function loadSnapshotData(panel: PanelModel, dashboard: DashboardModel): PanelData {
const data = getProcessedDataFrames(panel.snapshotData);

View File

@ -27,7 +27,7 @@ import { ExploreId, QueryOptions } from 'app/types/explore';
import { getTimeZone } from 'app/features/profile/state/selectors';
import { getShiftedTimeRange } from 'app/core/utils/timePicker';
import { notifyApp } from '../../../core/actions';
import { preProcessPanelData, runRequest } from '../../dashboard/state/runRequest';
import { preProcessPanelData, runRequest } from '../../query/state/runRequest';
import {
decorateWithGraphLogsTraceAndTable,
decorateWithGraphResult,

View File

@ -16,7 +16,7 @@ import {
} from '@grafana/data';
import { Unsubscribable } from 'rxjs';
import { PanelModel } from 'app/features/dashboard/state';
import { PanelQueryRunner } from '../dashboard/state/PanelQueryRunner';
import { PanelQueryRunner } from '../query/state/PanelQueryRunner';
class MetricsPanelCtrl extends PanelCtrl {
scope: any;

View File

@ -11,8 +11,8 @@ import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
import { backendSrv } from 'app/core/services/backend_srv';
import config from 'app/core/config';
// Types
import { PanelModel } from '../state/PanelModel';
import { DashboardModel } from '../state/DashboardModel';
import { PanelModel } from '../../dashboard/state/PanelModel';
import { DashboardModel } from '../../dashboard/state/DashboardModel';
import {
DataQuery,
DataSourceSelectItem,
@ -31,7 +31,7 @@ import { selectors } from '@grafana/e2e-selectors';
interface Props {
panel: PanelModel;
dashboard: DashboardModel;
dashboard?: DashboardModel;
}
interface State {
@ -153,10 +153,6 @@ export class QueriesTab extends PureComponent<Props, State> {
});
};
renderHelp = () => {
return;
};
/**
* Sets the queries for the panel
*/

View File

@ -7,7 +7,7 @@ import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
import { AngularComponent, getAngularLoader } from '@grafana/runtime';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
// Types
import { PanelModel } from '../state/PanelModel';
import { PanelModel } from '../../dashboard/state/PanelModel';
import { ErrorBoundaryAlert, HorizontalGroup } from '@grafana/ui';
import {
@ -23,14 +23,14 @@ import {
import { QueryEditorRowTitle } from './QueryEditorRowTitle';
import { QueryOperationRow } from 'app/core/components/QueryOperationRow/QueryOperationRow';
import { QueryOperationAction } from 'app/core/components/QueryOperationRow/QueryOperationAction';
import { DashboardModel } from '../state/DashboardModel';
import { DashboardModel } from '../../dashboard/state/DashboardModel';
import { selectors } from '@grafana/e2e-selectors';
interface Props {
panel: PanelModel;
data: PanelData;
query: DataQuery;
dashboard: DashboardModel;
dashboard?: DashboardModel;
dataSourceValue: string | null;
inMixedMode?: boolean;
id: string;
@ -79,9 +79,9 @@ export class QueryEditorRow extends PureComponent<Props, State> {
datasource: datasource,
target: query,
panel: panel,
dashboard: dashboard,
dashboard: dashboard!,
refresh: () => panel.refresh(),
render: () => panel.render(),
render: () => () => console.log('legacy render function called, it does nothing'),
events: panel.events,
range: getTimeSrv().timeRange(),
};
@ -141,13 +141,16 @@ export class QueryEditorRow extends PureComponent<Props, State> {
if (!this.element) {
return;
}
if (this.angularQueryEditor) {
this.angularQueryEditor.destroy();
this.angularQueryEditor = null;
}
const loader = getAngularLoader();
const template = '<plugin-component type="query-ctrl" />';
const scopeProps = { ctrl: this.getAngularQueryComponentScope() };
this.angularQueryEditor = loader.load(this.element, scopeProps, template);
this.angularScope = scopeProps.ctrl;
};

View File

@ -2,9 +2,9 @@
import React, { PureComponent } from 'react';
// Types
import { PanelModel } from '../state/PanelModel';
import { PanelModel } from '../../dashboard/state/PanelModel';
import { DataQuery, PanelData, DataSourceSelectItem } from '@grafana/data';
import { DashboardModel } from '../state/DashboardModel';
import { DashboardModel } from '../../dashboard/state/DashboardModel';
import { QueryEditorRow } from './QueryEditorRow';
import { addQuery } from 'app/core/utils/query';
import { DragDropContext, Droppable, DropResult } from 'react-beautiful-dnd';
@ -20,7 +20,7 @@ interface Props {
// Dashboard Configs
panel: PanelModel;
dashboard: DashboardModel;
dashboard?: DashboardModel;
// Query Response Data
data: PanelData;

View File

@ -8,7 +8,7 @@ import { rangeUtil, PanelData, DataSourceApi } from '@grafana/data';
import { Switch, Input, InlineField, InlineFormLabel, stylesFactory } from '@grafana/ui';
// Types
import { PanelModel } from '../state';
import { PanelModel } from '../../dashboard/state';
import { QueryOperationRow } from 'app/core/components/QueryOperationRow/QueryOperationRow';
import { config } from 'app/core/config';
import { css } from 'emotion';

View File

@ -17,7 +17,7 @@ import {
PanelData,
ScopedVars,
} from '@grafana/data';
import { DashboardModel } from './index';
import { DashboardModel } from '../../dashboard/state/index';
import { setDataSourceSrv, setEchoSrv } from '@grafana/runtime';
import { Echo } from '../../../core/services/echo/Echo';

View File

@ -1,7 +1,7 @@
import { MetaAnalyticsEventName, reportMetaAnalytics } from '@grafana/runtime';
import { CoreApp, DataQueryRequest, DataSourceApi, dateTime, LoadingState, PanelData } from '@grafana/data';
import { emitDataRequestEvent } from './analyticsProcessor';
import { DashboardModel } from './DashboardModel';
import { emitDataRequestEvent } from './queryAnalytics';
import { DashboardModel } from '../../dashboard/state/DashboardModel';
beforeEach(() => {
jest.clearAllMocks();

View File

@ -0,0 +1,56 @@
import { getDashboardSrv } from '../../dashboard/services/DashboardSrv';
import { PanelData, LoadingState, DataSourceApi, CoreApp, urlUtil } from '@grafana/data';
import { reportMetaAnalytics, MetaAnalyticsEventName, DataRequestEventPayload } from '@grafana/runtime';
export function emitDataRequestEvent(datasource: DataSourceApi) {
let done = false;
return (data: PanelData) => {
if (!data.request || done || data.request.app === CoreApp.Explore) {
return;
}
const params = urlUtil.getUrlSearchParams();
if (params.editPanel != null) {
return;
}
if (data.state !== LoadingState.Done && data.state !== LoadingState.Error) {
return;
}
const eventData: DataRequestEventPayload = {
eventName: MetaAnalyticsEventName.DataRequest,
datasourceName: datasource.name,
datasourceId: datasource.id,
panelId: data.request.panelId,
dashboardId: data.request.dashboardId,
dataSize: 0,
duration: data.request.endTime! - data.request.startTime,
};
// enrich with dashboard info
const dashboard = getDashboardSrv().getCurrent();
if (dashboard) {
eventData.dashboardId = dashboard.id;
eventData.dashboardName = dashboard.title;
eventData.dashboardUid = dashboard.uid;
eventData.folderName = dashboard.meta.folderTitle;
}
if (data.series && data.series.length > 0) {
// estimate size
eventData.dataSize = data.series.length;
}
if (data.error) {
eventData.error = data.error.message;
}
reportMetaAnalytics(eventData);
// this done check is to make sure we do not double emit events in case
// there are multiple responses with done state
done = true;
};
}

View File

@ -11,7 +11,7 @@ import {
import { Observable, Subscriber, Subscription } from 'rxjs';
import { runRequest } from './runRequest';
import { deepFreeze } from '../../../../test/core/redux/reducerTester';
import { DashboardModel } from './DashboardModel';
import { DashboardModel } from '../../dashboard/state/DashboardModel';
import { setEchoSrv } from '@grafana/runtime';
import { Echo } from '../../../core/services/echo/Echo';

View File

@ -20,7 +20,7 @@ import {
toDataFrame,
} from '@grafana/data';
import { toDataQueryError } from '@grafana/runtime';
import { emitDataRequestEvent } from './analyticsProcessor';
import { emitDataRequestEvent } from './queryAnalytics';
import { expressionDatasource, ExpressionDatasourceID } from 'app/features/expressions/ExpressionDatasource';
import { ExpressionQuery } from 'app/features/expressions/types';

View File

@ -0,0 +1,33 @@
import React, { FC, useState } from 'react';
import { PanelModel } from '../dashboard/state';
import { QueriesTab } from '../query/components/QueriesTab';
interface State {
panel: PanelModel;
}
export const TestStuffPage: FC = () => {
const [state] = useState<State>(getDefaultState());
return (
<div style={{ padding: '50px', height: '100%', flexGrow: 1 }} className="page-scrollbar-wrapper">
<h2>Hello</h2>
<QueriesTab panel={state.panel} />
</div>
);
};
export function getDefaultState(): State {
const panel = new PanelModel({
datasource: 'gdev-testdata',
id: 10,
targets: [],
});
return {
panel,
};
}
export default TestStuffPage;

View File

@ -19,7 +19,7 @@ import { getTemplatedRegex } from '../utils';
import { v4 as uuidv4 } from 'uuid';
import { getTimeSrv } from '../../dashboard/services/TimeSrv';
import { QueryRunners } from './queryRunners';
import { runRequest } from '../../dashboard/state/runRequest';
import { runRequest } from '../../query/state/runRequest';
import {
runUpdateTagsRequest,
toMetricFindValues,

View File

@ -11,7 +11,8 @@ import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
import { PanelModel } from 'app/features/dashboard/state';
import { SHARED_DASHBODARD_QUERY } from './types';
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
import { filterPanelDataToQuery } from 'app/features/dashboard/panel_editor/QueryEditorRow';
import { filterPanelDataToQuery } from 'app/features/query/components/QueryEditorRow';
const { Select } = LegacyForms;
type ResultInfo = {

View File

@ -1,5 +1,5 @@
import { Observable } from 'rxjs';
import { QueryRunnerOptions } from 'app/features/dashboard/state/PanelQueryRunner';
import { QueryRunnerOptions } from 'app/features/query/state/PanelQueryRunner';
import { DashboardQuery, SHARED_DASHBODARD_QUERY } from './types';
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
import { LoadingState, DefaultTimeRange, DataQuery, PanelData, DataSourceApi, DataQueryRequest } from '@grafana/data';

View File

@ -11,7 +11,7 @@ import { DataProcessor } from './data_processor';
import { axesEditorComponent } from './axes_editor';
import config from 'app/core/config';
import TimeSeries from 'app/core/time_series2';
import { getProcessedDataFrames } from 'app/features/dashboard/state/runRequest';
import { getProcessedDataFrames } from 'app/features/query/state/runRequest';
import { DataFrame, FieldConfigProperty, getColorForTheme, PanelEvents, PanelPlugin } from '@grafana/data';
import { GraphContextMenuCtrl } from './GraphContextMenuCtrl';

View File

@ -1,5 +1,5 @@
import { DataProcessor } from '../data_processor';
import { getProcessedDataFrames } from 'app/features/dashboard/state/runRequest';
import { getProcessedDataFrames } from 'app/features/query/state/runRequest';
describe('Graph DataProcessor', () => {
const panel: any = {

View File

@ -13,7 +13,7 @@ import {
sortSeriesByLabel,
} from './heatmap_data_converter';
import { auto } from 'angular';
import { getProcessedDataFrames } from 'app/features/dashboard/state/runRequest';
import { getProcessedDataFrames } from 'app/features/query/state/runRequest';
import { DataProcessor } from '../graph/data_processor';
import { LegacyResponseData, PanelEvents, DataFrame, rangeUtil } from '@grafana/data';
import { CoreEvents } from 'app/types';

View File

@ -31,7 +31,7 @@ import { convertOldAngularValueMapping } from '@grafana/ui';
import config from 'app/core/config';
import { MetricsPanelCtrl } from 'app/plugins/sdk';
import { LinkSrv } from 'app/features/panel/panellinks/link_srv';
import { getProcessedDataFrames } from 'app/features/dashboard/state/runRequest';
import { getProcessedDataFrames } from 'app/features/query/state/runRequest';
const BASE_FONT_SIZE = 38;

View File

@ -237,6 +237,14 @@ export function setupAngularRoutes($routeProvider: route.IRouteProvider, $locati
component: () => SafeDynamicImport(import(/* webpackChunkName: "explore" */ 'app/features/explore/Wrapper')),
},
})
.when('/sandbox/test', {
template: '<react-container />',
reloadOnSearch: false,
resolve: {
component: () =>
SafeDynamicImport(import(/* webpackChunkName: "sandbox" */ 'app/features/sandbox/TestStuffPage')),
},
})
.when('/a/:pluginId/', {
// Someday * and will get a ReactRouter under that path!
template: '<react-container />',