Przeglądaj źródła

Merge pull request #14936 from grafana/plugin-types-refactor

Plugin types refactor
Torkel Ödegaard 7 lat temu
rodzic
commit
bc8f3374a3
50 zmienionych plików z 505 dodań i 388 usunięć
  1. 71 0
      packages/grafana-ui/src/types/datasource.ts
  2. 2 0
      packages/grafana-ui/src/types/index.ts
  3. 115 0
      packages/grafana-ui/src/types/plugin.ts
  4. 1 1
      public/app/core/components/Select/DataSourcePicker.tsx
  5. 6 3
      public/app/core/utils/explore.ts
  6. 1 2
      public/app/features/dashboard/dashgrid/DataPanel.tsx
  7. 1 1
      public/app/features/dashboard/panel_editor/QueriesTab.tsx
  8. 19 2
      public/app/features/dashboard/panel_editor/QueryEditorRow.tsx
  9. 2 1
      public/app/features/dashboard/panel_editor/QueryOptions.tsx
  10. 5 2
      public/app/features/dashboard/panel_model.ts
  11. 3 2
      public/app/features/datasources/DataSourceDashboards.test.tsx
  12. 10 2
      public/app/features/datasources/DataSourceDashboards.tsx
  13. 7 2
      public/app/features/datasources/DataSourcesList.tsx
  14. 2 2
      public/app/features/datasources/DataSourcesListItem.tsx
  15. 3 2
      public/app/features/datasources/DataSourcesListPage.test.tsx
  16. 10 2
      public/app/features/datasources/DataSourcesListPage.tsx
  17. 3 3
      public/app/features/datasources/__mocks__/dataSourcesMocks.ts
  18. 5 4
      public/app/features/datasources/settings/DataSourceSettingsPage.test.tsx
  19. 12 6
      public/app/features/datasources/settings/DataSourceSettingsPage.tsx
  20. 7 6
      public/app/features/datasources/settings/PluginSettings.tsx
  21. 0 0
      public/app/features/datasources/settings/__snapshots__/DataSourceSettingsPage.test.tsx.snap
  22. 7 6
      public/app/features/datasources/state/actions.ts
  23. 3 2
      public/app/features/datasources/state/navModel.ts
  24. 5 4
      public/app/features/datasources/state/reducers.ts
  25. 3 3
      public/app/features/datasources/state/selectors.ts
  26. 19 14
      public/app/features/explore/Explore.tsx
  27. 7 3
      public/app/features/explore/QueryEditor.tsx
  28. 11 7
      public/app/features/explore/QueryRow.tsx
  29. 7 3
      public/app/features/explore/QueryRows.tsx
  30. 2 4
      public/app/features/explore/state/actionTypes.ts
  31. 12 8
      public/app/features/explore/state/actions.ts
  32. 1 1
      public/app/features/explore/state/reducers.ts
  33. 6 4
      public/app/features/plugins/datasource_srv.ts
  34. 1 1
      public/app/features/plugins/plugin_loader.ts
  35. 8 2
      public/app/features/plugins/state/navModel.ts
  36. 1 1
      public/app/plugins/datasource/loki/components/LokiQueryField.tsx
  37. 1 1
      public/app/plugins/datasource/loki/datasource.ts
  38. 1 1
      public/app/plugins/datasource/loki/language_provider.ts
  39. 1 1
      public/app/plugins/datasource/prometheus/components/PromQueryField.tsx
  40. 1 1
      public/app/plugins/datasource/prometheus/datasource.ts
  41. 1 2
      public/app/plugins/datasource/prometheus/query_hints.ts
  42. 66 0
      public/app/plugins/datasource/testdata/QueryEditor.tsx
  43. 2 1
      public/app/plugins/datasource/testdata/module.ts
  44. 2 2
      public/app/routes/routes.ts
  45. 4 32
      public/app/types/datasources.ts
  46. 2 27
      public/app/types/explore.ts
  47. 18 89
      public/app/types/index.ts
  48. 1 69
      public/app/types/plugins.ts
  49. 0 56
      public/app/types/series.ts
  50. 27 0
      public/app/types/store.ts

+ 71 - 0
packages/grafana-ui/src/types/datasource.ts

@@ -0,0 +1,71 @@
+import { TimeRange, RawTimeRange } from './time';
+import { TimeSeries } from './series';
+import { PluginMeta } from './plugin';
+
+export interface DataQueryResponse {
+  data: TimeSeries[];
+}
+
+export interface DataQuery {
+  refId: string;
+  [key: string]: any;
+}
+
+export interface DataQueryOptions {
+  timezone: string;
+  range: TimeRange;
+  rangeRaw: RawTimeRange;
+  targets: DataQuery[];
+  panelId: number;
+  dashboardId: number;
+  cacheTimeout?: string;
+  interval: string;
+  intervalMs: number;
+  maxDataPoints: number;
+  scopedVars: object;
+}
+
+export interface QueryFix {
+  type: string;
+  label: string;
+  action?: QueryFixAction;
+}
+
+export interface QueryFixAction {
+  type: string;
+  query?: string;
+  preventSubmit?: boolean;
+}
+
+export interface QueryHint {
+  type: string;
+  label: string;
+  fix?: QueryFix;
+}
+
+export interface DataSourceSettings {
+  id: number;
+  orgId: number;
+  name: string;
+  typeLogoUrl: string;
+  type: string;
+  access: string;
+  url: string;
+  password: string;
+  user: string;
+  database: string;
+  basicAuth: boolean;
+  basicAuthPassword: string;
+  basicAuthUser: string;
+  isDefault: boolean;
+  jsonData: { authType: string; defaultRegion: string };
+  readOnly: boolean;
+  withCredentials: boolean;
+}
+
+export interface DataSourceSelectItem {
+  name: string;
+  value: string | null;
+  meta: PluginMeta;
+  sort: string;
+}

+ 2 - 0
packages/grafana-ui/src/types/index.ts

@@ -1,3 +1,5 @@
 export * from './series';
 export * from './time';
 export * from './panel';
+export * from './plugin';
+export * from './datasource';

+ 115 - 0
packages/grafana-ui/src/types/plugin.ts

@@ -0,0 +1,115 @@
+import { ComponentClass } from 'react';
+import { PanelProps, PanelOptionsProps } from './panel';
+import { DataQueryOptions, DataQuery, DataQueryResponse, QueryHint } from './datasource';
+
+export interface DataSourceApi {
+  name: string;
+  meta: PluginMeta;
+  pluginExports: PluginExports;
+
+  /**
+   *  min interval range
+   */
+  interval?: string;
+
+  /**
+   * Imports queries from a different datasource
+   */
+  importQueries?(queries: DataQuery[], originMeta: PluginMeta): Promise<DataQuery[]>;
+
+  /**
+   * Initializes a datasource after instantiation
+   */
+  init?: () => void;
+
+  /**
+   * Main metrics / data query action
+   */
+  query(options: DataQueryOptions): Promise<DataQueryResponse>;
+
+  /**
+   * Test & verify datasource settings & connection details
+   */
+  testDatasource(): Promise<any>;
+
+  /**
+   *  Get hints for query improvements
+   */
+  getQueryHints(query: DataQuery, results: any[], ...rest: any): QueryHint[];
+}
+
+export interface QueryEditorProps {
+  datasource: DataSourceApi;
+  query: DataQuery;
+  onExecuteQuery?: () => void;
+  onQueryChange?: (value: DataQuery) => void;
+}
+
+export interface PluginExports {
+  Datasource?: any;
+  QueryCtrl?: any;
+  QueryEditor?: ComponentClass<QueryEditorProps>;
+  ConfigCtrl?: any;
+  AnnotationsQueryCtrl?: any;
+  VariableQueryEditor?: any;
+  ExploreQueryField?: any;
+  ExploreStartPage?: any;
+
+  // Panel plugin
+  PanelCtrl?: any;
+  Panel?: ComponentClass<PanelProps>;
+  PanelOptions?: ComponentClass<PanelOptionsProps>;
+  PanelDefaults?: any;
+}
+
+export interface PluginMeta {
+  id: string;
+  name: string;
+  info: PluginMetaInfo;
+  includes: PluginInclude[];
+
+  // Datasource-specific
+  metrics?: boolean;
+  tables?: boolean;
+  logs?: boolean;
+  explore?: boolean;
+  annotations?: boolean;
+  mixed?: boolean;
+  hasQueryHelp?: boolean;
+  queryOptions?: PluginMetaQueryOptions;
+}
+
+interface PluginMetaQueryOptions {
+  cacheTimeout?: boolean;
+  maxDataPoints?: boolean;
+  minInterval?: boolean;
+}
+
+export interface PluginInclude {
+  type: string;
+  name: string;
+  path: string;
+}
+
+interface PluginMetaInfoLink {
+  name: string;
+  url: string;
+}
+
+export interface PluginMetaInfo {
+  author: {
+    name: string;
+    url?: string;
+  };
+  description: string;
+  links: PluginMetaInfoLink[];
+  logos: {
+    large: string;
+    small: string;
+  };
+  screenshots: any[];
+  updated: string;
+  version: string;
+}
+
+

+ 1 - 1
public/app/core/components/Select/DataSourcePicker.tsx

@@ -6,7 +6,7 @@ import _ from 'lodash';
 import { Select } from '@grafana/ui';
 
 // Types
-import { DataSourceSelectItem } from 'app/types';
+import { DataSourceSelectItem } from '@grafana/ui/src/types';
 
 export interface Props {
   onChange: (ds: DataSourceSelectItem) => void;

+ 6 - 3
public/app/core/utils/explore.ts

@@ -1,14 +1,18 @@
+// Libraries
 import _ from 'lodash';
-import { colors, RawTimeRange, IntervalValues } from '@grafana/ui';
 
+// Services & Utils
 import * as dateMath from 'app/core/utils/datemath';
 import { renderUrl } from 'app/core/utils/url';
 import kbn from 'app/core/utils/kbn';
 import store from 'app/core/store';
 import { parse as parseDate } from 'app/core/utils/datemath';
+import { colors } from '@grafana/ui';
+import TableModel, { mergeTablesIntoModel } from 'app/core/table_model';
 
+// Types
+import { RawTimeRange, IntervalValues, DataQuery } from '@grafana/ui/src/types';
 import TimeSeries from 'app/core/time_series2';
-import TableModel, { mergeTablesIntoModel } from 'app/core/table_model';
 import {
   ExploreUrlState,
   HistoryItem,
@@ -17,7 +21,6 @@ import {
   QueryIntervals,
   QueryOptions,
 } from 'app/types/explore';
-import { DataQuery } from 'app/types/series';
 
 export const DEFAULT_RANGE = {
   from: 'now-6h',

+ 1 - 2
public/app/features/dashboard/dashgrid/DataPanel.tsx

@@ -12,8 +12,7 @@ import { getDatasourceSrv, DatasourceSrv } from 'app/features/plugins/datasource
 import kbn from 'app/core/utils/kbn';
 
 // Types
-import { DataQueryOptions, DataQueryResponse } from 'app/types';
-import { TimeRange, TimeSeries, LoadingState } from '@grafana/ui';
+import { TimeRange, TimeSeries, LoadingState, DataQueryResponse, DataQueryOptions } from '@grafana/ui/src/types';
 
 const DEFAULT_PLUGIN_ERROR = 'Error in plugin';
 

+ 1 - 1
public/app/features/dashboard/panel_editor/QueriesTab.tsx

@@ -18,7 +18,7 @@ import config from 'app/core/config';
 // Types
 import { PanelModel } from '../panel_model';
 import { DashboardModel } from '../dashboard_model';
-import { DataQuery, DataSourceSelectItem } from 'app/types';
+import { DataQuery, DataSourceSelectItem  } from '@grafana/ui/src/types';
 import { PluginHelp } from 'app/core/components/PluginHelp/PluginHelp';
 
 interface Props {

+ 19 - 2
public/app/features/dashboard/panel_editor/QueryEditorRow.tsx

@@ -10,7 +10,7 @@ import { Emitter } from 'app/core/utils/emitter';
 
 // Types
 import { PanelModel } from '../panel_model';
-import { DataQuery, DataSourceApi } from 'app/types/series';
+import { DataQuery, DataSourceApi } from '@grafana/ui';
 
 interface Props {
   panel: PanelModel;
@@ -103,7 +103,17 @@ export class QueryEditorRow extends PureComponent<Props, State> {
     this.setState({ isCollapsed: !this.state.isCollapsed });
   };
 
+  onQueryChange = (query: DataQuery) => {
+    Object.assign(this.props.query, query);
+    this.onExecuteQuery();
+  };
+
+  onExecuteQuery = () => {
+    this.props.panel.refresh();
+  };
+
   renderPluginEditor() {
+    const { query } = this.props;
     const { datasource } = this.state;
 
     if (datasource.pluginExports.QueryCtrl) {
@@ -112,7 +122,14 @@ export class QueryEditorRow extends PureComponent<Props, State> {
 
     if (datasource.pluginExports.QueryEditor) {
       const QueryEditor = datasource.pluginExports.QueryEditor;
-      return <QueryEditor />;
+      return (
+        <QueryEditor
+          query={query}
+          datasource={datasource}
+          onQueryChange={this.onQueryChange}
+          onExecuteQuery={this.onExecuteQuery}
+        />
+      );
     }
 
     return <div>Data source plugin does not export any Query Editor component</div>;

+ 2 - 1
public/app/features/dashboard/panel_editor/QueryOptions.tsx

@@ -14,7 +14,8 @@ import { FormLabel } from '@grafana/ui';
 
 // Types
 import { PanelModel } from '../panel_model';
-import { ValidationEvents, DataSourceSelectItem } from 'app/types';
+import { DataSourceSelectItem } from '@grafana/ui/src/types';
+import { ValidationEvents } from 'app/types';
 
 const timeRangeValidationEvents: ValidationEvents = {
   [EventsWithValidation.onBlur]: [

+ 5 - 2
public/app/features/dashboard/panel_model.ts

@@ -1,7 +1,10 @@
-import { Emitter } from 'app/core/utils/emitter';
+// Libraries
 import _ from 'lodash';
+
+// Types
+import { Emitter } from 'app/core/utils/emitter';
 import { PANEL_OPTIONS_KEY_PREFIX } from 'app/core/constants';
-import { DataQuery } from 'app/types';
+import { DataQuery } from '@grafana/ui/src/types';
 
 export interface GridPos {
   x: number;

+ 3 - 2
public/app/features/datasources/DataSourceDashboards.test.tsx

@@ -1,13 +1,14 @@
 import React from 'react';
 import { shallow } from 'enzyme';
 import { DataSourceDashboards, Props } from './DataSourceDashboards';
-import { DataSource, NavModel, PluginDashboard } from 'app/types';
+import { DataSourceSettings } from '@grafana/ui/src/types';
+import { NavModel, PluginDashboard } from 'app/types';
 
 const setup = (propOverrides?: object) => {
   const props: Props = {
     navModel: {} as NavModel,
     dashboards: [] as PluginDashboard[],
-    dataSource: {} as DataSource,
+    dataSource: {} as DataSourceSettings,
     pageId: 1,
     importDashboard: jest.fn(),
     loadDataSource: jest.fn(),

+ 10 - 2
public/app/features/datasources/DataSourceDashboards.tsx

@@ -1,9 +1,13 @@
+// Libraries
 import React, { PureComponent } from 'react';
 import { hot } from 'react-hot-loader';
 import { connect } from 'react-redux';
+
+// Components
 import PageHeader from 'app/core/components/PageHeader/PageHeader';
 import DashboardTable from './DashboardsTable';
-import { DataSource, NavModel, PluginDashboard } from 'app/types';
+
+// Actions & Selectors
 import { getNavModel } from 'app/core/selectors/navModel';
 import { getRouteParamsId } from 'app/core/selectors/location';
 import { loadDataSource } from './state/actions';
@@ -11,10 +15,14 @@ import { loadPluginDashboards } from '../plugins/state/actions';
 import { importDashboard, removeDashboard } from '../dashboard/state/actions';
 import { getDataSource } from './state/selectors';
 
+// Types
+import { NavModel, PluginDashboard } from 'app/types';
+import { DataSourceSettings } from '@grafana/ui/src/types';
+
 export interface Props {
   navModel: NavModel;
   dashboards: PluginDashboard[];
-  dataSource: DataSource;
+  dataSource: DataSourceSettings;
   pageId: number;
   importDashboard: typeof importDashboard;
   loadDataSource: typeof loadDataSource;

+ 7 - 2
public/app/features/datasources/DataSourcesList.tsx

@@ -1,11 +1,16 @@
+// Libraries
 import React, { PureComponent } from 'react';
 import classNames from 'classnames';
+
+// Components
 import DataSourcesListItem from './DataSourcesListItem';
-import { DataSource } from 'app/types';
+
+// Types
+import { DataSourceSettings } from '@grafana/ui/src/types';
 import { LayoutMode, LayoutModes } from '../../core/components/LayoutSelector/LayoutSelector';
 
 export interface Props {
-  dataSources: DataSource[];
+  dataSources: DataSourceSettings[];
   layoutMode: LayoutMode;
 }
 

+ 2 - 2
public/app/features/datasources/DataSourcesListItem.tsx

@@ -1,8 +1,8 @@
 import React, { PureComponent } from 'react';
-import { DataSource } from 'app/types';
+import { DataSourceSettings } from '@grafana/ui/src/types';
 
 export interface Props {
-  dataSource: DataSource;
+  dataSource: DataSourceSettings;
 }
 
 export class DataSourcesListItem extends PureComponent<Props> {

+ 3 - 2
public/app/features/datasources/DataSourcesListPage.test.tsx

@@ -1,13 +1,14 @@
 import React from 'react';
 import { shallow } from 'enzyme';
 import { DataSourcesListPage, Props } from './DataSourcesListPage';
-import { DataSource, NavModel } from 'app/types';
+import { NavModel } from 'app/types';
+import { DataSourceSettings } from '@grafana/ui/src/types';
 import { LayoutModes } from '../../core/components/LayoutSelector/LayoutSelector';
 import { getMockDataSources } from './__mocks__/dataSourcesMocks';
 
 const setup = (propOverrides?: object) => {
   const props: Props = {
-    dataSources: [] as DataSource[],
+    dataSources: [] as DataSourceSettings[],
     layoutMode: LayoutModes.Grid,
     loadDataSources: jest.fn(),
     navModel: {

+ 10 - 2
public/app/features/datasources/DataSourcesListPage.tsx

@@ -1,12 +1,20 @@
+// Libraries
 import React, { PureComponent } from 'react';
 import { connect } from 'react-redux';
 import { hot } from 'react-hot-loader';
+
+// Components
 import Page from 'app/core/components/Page/Page';
 import OrgActionBar from 'app/core/components/OrgActionBar/OrgActionBar';
 import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
 import DataSourcesList from './DataSourcesList';
-import { DataSource, NavModel, StoreState } from 'app/types';
+
+// Types
+import { DataSourceSettings } from '@grafana/ui/src/types';
+import { NavModel, StoreState } from 'app/types';
 import { LayoutMode } from 'app/core/components/LayoutSelector/LayoutSelector';
+
+// Actions
 import { loadDataSources, setDataSourcesLayoutMode, setDataSourcesSearchQuery } from './state/actions';
 import { getNavModel } from 'app/core/selectors/navModel';
 
@@ -19,7 +27,7 @@ import {
 
 export interface Props {
   navModel: NavModel;
-  dataSources: DataSource[];
+  dataSources: DataSourceSettings[];
   dataSourcesCount: number;
   layoutMode: LayoutMode;
   searchQuery: string;

+ 3 - 3
public/app/features/datasources/__mocks__/dataSourcesMocks.ts

@@ -1,6 +1,6 @@
-import { DataSource } from 'app/types';
+import { DataSourceSettings } from '@grafana/ui/src/types';
 
-export const getMockDataSources = (amount: number): DataSource[] => {
+export const getMockDataSources = (amount: number): DataSourceSettings[] => {
   const dataSources = [];
 
   for (let i = 0; i <= amount; i++) {
@@ -25,7 +25,7 @@ export const getMockDataSources = (amount: number): DataSource[] => {
   return dataSources;
 };
 
-export const getMockDataSource = (): DataSource => {
+export const getMockDataSource = (): DataSourceSettings => {
   return {
     access: '',
     basicAuth: false,

+ 5 - 4
public/app/features/datasources/settings/DataSourceSettings.test.tsx → public/app/features/datasources/settings/DataSourceSettingsPage.test.tsx

@@ -1,7 +1,8 @@
 import React from 'react';
 import { shallow } from 'enzyme';
-import { DataSourceSettings, Props } from './DataSourceSettings';
-import { DataSource, NavModel } from '../../../types';
+import { DataSourceSettingsPage, Props } from './DataSourceSettingsPage';
+import { NavModel } from 'app/types';
+import { DataSourceSettings } from '@grafana/ui';
 import { getMockDataSource } from '../__mocks__/dataSourcesMocks';
 import { getMockPlugin } from '../../plugins/__mocks__/pluginMocks';
 
@@ -20,7 +21,7 @@ const setup = (propOverrides?: object) => {
 
   Object.assign(props, propOverrides);
 
-  return shallow(<DataSourceSettings {...props} />);
+  return shallow(<DataSourceSettingsPage {...props} />);
 };
 
 describe('Render', () => {
@@ -32,7 +33,7 @@ describe('Render', () => {
 
   it('should render loader', () => {
     const wrapper = setup({
-      dataSource: {} as DataSource,
+      dataSource: {} as DataSourceSettings,
     });
 
     expect(wrapper).toMatchSnapshot();

+ 12 - 6
public/app/features/datasources/settings/DataSourceSettings.tsx → public/app/features/datasources/settings/DataSourceSettingsPage.tsx

@@ -1,28 +1,34 @@
+// Libraries
 import React, { PureComponent } from 'react';
 import { hot } from 'react-hot-loader';
 import { connect } from 'react-redux';
 
+// Components
 import PageHeader from 'app/core/components/PageHeader/PageHeader';
 import PageLoader from 'app/core/components/PageLoader/PageLoader';
 import PluginSettings from './PluginSettings';
 import BasicSettings from './BasicSettings';
 import ButtonRow from './ButtonRow';
 
+// Services & Utils
 import appEvents from 'app/core/app_events';
 import { getBackendSrv } from 'app/core/services/backend_srv';
 import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
 
+// Actions & selectors
 import { getDataSource, getDataSourceMeta } from '../state/selectors';
 import { deleteDataSource, loadDataSource, setDataSourceName, setIsDefault, updateDataSource } from '../state/actions';
 import { getNavModel } from 'app/core/selectors/navModel';
 import { getRouteParamsId } from 'app/core/selectors/location';
 
-import { DataSource, NavModel, Plugin } from 'app/types/';
+// Types
+import { NavModel, Plugin } from 'app/types/';
+import { DataSourceSettings } from '@grafana/ui/src/types/';
 import { getDataSourceLoadingNav } from '../state/navModel';
 
 export interface Props {
   navModel: NavModel;
-  dataSource: DataSource;
+  dataSource: DataSourceSettings;
   dataSourceMeta: Plugin;
   pageId: number;
   deleteDataSource: typeof deleteDataSource;
@@ -33,7 +39,7 @@ export interface Props {
 }
 
 interface State {
-  dataSource: DataSource;
+  dataSource: DataSourceSettings;
   isTesting?: boolean;
   testingMessage?: string;
   testingStatus?: string;
@@ -44,12 +50,12 @@ enum DataSourceStates {
   Beta = 'beta',
 }
 
-export class DataSourceSettings extends PureComponent<Props, State> {
+export class DataSourceSettingsPage extends PureComponent<Props, State> {
   constructor(props) {
     super(props);
 
     this.state = {
-      dataSource: {} as DataSource,
+      dataSource: {} as DataSourceSettings,
     };
   }
 
@@ -246,4 +252,4 @@ const mapDispatchToProps = {
   setIsDefault,
 };
 
-export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(DataSourceSettings));
+export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(DataSourceSettingsPage));

+ 7 - 6
public/app/features/datasources/settings/PluginSettings.tsx

@@ -1,20 +1,21 @@
 import React, { PureComponent } from 'react';
 import _ from 'lodash';
-import { DataSource, Plugin } from 'app/types/';
+import { Plugin } from 'app/types';
+import { DataSourceSettings } from '@grafana/ui/src/types';
 import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader';
 
 export interface Props {
-  dataSource: DataSource;
+  dataSource: DataSourceSettings;
   dataSourceMeta: Plugin;
-  onModelChange: (dataSource: DataSource) => void;
+  onModelChange: (dataSource: DataSourceSettings) => void;
 }
 
 export class PluginSettings extends PureComponent<Props> {
   element: any;
   component: AngularComponent;
   scopeProps: {
-    ctrl: { datasourceMeta: Plugin; current: DataSource };
-    onModelChanged: (dataSource: DataSource) => void;
+    ctrl: { datasourceMeta: Plugin; current: DataSourceSettings };
+    onModelChanged: (dataSource: DataSourceSettings) => void;
   };
 
   constructor(props) {
@@ -51,7 +52,7 @@ export class PluginSettings extends PureComponent<Props> {
     }
   }
 
-  onModelChanged = (dataSource: DataSource) => {
+  onModelChanged = (dataSource: DataSourceSettings) => {
     this.props.onModelChange(dataSource);
   };
 

+ 0 - 0
public/app/features/datasources/settings/__snapshots__/DataSourceSettings.test.tsx.snap → public/app/features/datasources/settings/__snapshots__/DataSourceSettingsPage.test.tsx.snap


+ 7 - 6
public/app/features/datasources/state/actions.ts

@@ -6,7 +6,8 @@ import { LayoutMode } from 'app/core/components/LayoutSelector/LayoutSelector';
 import { updateLocation, updateNavIndex, UpdateNavIndexAction } from 'app/core/actions';
 import { UpdateLocationAction } from 'app/core/actions/location';
 import { buildNavModel } from './navModel';
-import { DataSource, Plugin, StoreState } from 'app/types';
+import { DataSourceSettings } from '@grafana/ui/src/types';
+import { Plugin, StoreState } from 'app/types';
 
 export enum ActionTypes {
   LoadDataSources = 'LOAD_DATA_SOURCES',
@@ -22,7 +23,7 @@ export enum ActionTypes {
 
 interface LoadDataSourcesAction {
   type: ActionTypes.LoadDataSources;
-  payload: DataSource[];
+  payload: DataSourceSettings[];
 }
 
 interface SetDataSourcesSearchQueryAction {
@@ -47,7 +48,7 @@ interface SetDataSourceTypeSearchQueryAction {
 
 interface LoadDataSourceAction {
   type: ActionTypes.LoadDataSource;
-  payload: DataSource;
+  payload: DataSourceSettings;
 }
 
 interface LoadDataSourceMetaAction {
@@ -65,12 +66,12 @@ interface SetIsDefaultAction {
   payload: boolean;
 }
 
-const dataSourcesLoaded = (dataSources: DataSource[]): LoadDataSourcesAction => ({
+const dataSourcesLoaded = (dataSources: DataSourceSettings[]): LoadDataSourcesAction => ({
   type: ActionTypes.LoadDataSources,
   payload: dataSources,
 });
 
-const dataSourceLoaded = (dataSource: DataSource): LoadDataSourceAction => ({
+const dataSourceLoaded = (dataSource: DataSourceSettings): LoadDataSourceAction => ({
   type: ActionTypes.LoadDataSource,
   payload: dataSource,
 });
@@ -171,7 +172,7 @@ export function loadDataSourceTypes(): ThunkResult<void> {
   };
 }
 
-export function updateDataSource(dataSource: DataSource): ThunkResult<void> {
+export function updateDataSource(dataSource: DataSourceSettings): ThunkResult<void> {
   return async dispatch => {
     await getBackendSrv().put(`/api/datasources/${dataSource.id}`, dataSource);
     await updateFrontendSettings();

+ 3 - 2
public/app/features/datasources/state/navModel.ts

@@ -1,7 +1,8 @@
-import { DataSource, NavModel, NavModelItem, PluginMeta } from 'app/types';
+import { NavModel, NavModelItem } from 'app/types';
+import { PluginMeta, DataSourceSettings } from '@grafana/ui/src/types';
 import config from 'app/core/config';
 
-export function buildNavModel(dataSource: DataSource, pluginMeta: PluginMeta): NavModelItem {
+export function buildNavModel(dataSource: DataSourceSettings, pluginMeta: PluginMeta): NavModelItem {
   const navModel = {
     img: pluginMeta.info.logos.large,
     id: 'datasource-' + dataSource.id,

+ 5 - 4
public/app/features/datasources/state/reducers.ts

@@ -1,10 +1,11 @@
-import { DataSource, DataSourcesState, Plugin } from 'app/types';
+import { DataSourcesState, Plugin } from 'app/types';
+import { DataSourceSettings } from '@grafana/ui/src/types';
 import { Action, ActionTypes } from './actions';
-import { LayoutModes } from '../../../core/components/LayoutSelector/LayoutSelector';
+import { LayoutModes } from 'app/core/components/LayoutSelector/LayoutSelector';
 
 const initialState: DataSourcesState = {
-  dataSources: [] as DataSource[],
-  dataSource: {} as DataSource,
+  dataSources: [] as DataSourceSettings[],
+  dataSource: {} as DataSourceSettings,
   layoutMode: LayoutModes.List,
   searchQuery: '',
   dataSourcesCount: 0,

+ 3 - 3
public/app/features/datasources/state/selectors.ts

@@ -1,4 +1,4 @@
-import { DataSource } from '../../../types';
+import { DataSourceSettings } from '@grafana/ui/src/types';
 
 export const getDataSources = state => {
   const regex = new RegExp(state.searchQuery, 'i');
@@ -16,11 +16,11 @@ export const getDataSourceTypes = state => {
   });
 };
 
-export const getDataSource = (state, dataSourceId): DataSource | null => {
+export const getDataSource = (state, dataSourceId): DataSourceSettings | null => {
   if (state.dataSource.id === parseInt(dataSourceId, 10)) {
     return state.dataSource;
   }
-  return {} as DataSource;
+  return {} as DataSourceSettings;
 };
 
 export const getDataSourceMeta = (state, type): Plugin => {

+ 19 - 14
public/app/features/explore/Explore.tsx

@@ -1,19 +1,25 @@
+// Libraries
 import React from 'react';
 import { hot } from 'react-hot-loader';
 import { connect } from 'react-redux';
 import _ from 'lodash';
 import { AutoSizer } from 'react-virtualized';
-import { RawTimeRange, TimeRange } from '@grafana/ui';
 
-import { DataSourceSelectItem } from 'app/types/datasources';
-import { ExploreItemState, ExploreUrlState, RangeScanner, ExploreId } from 'app/types/explore';
-import { DataQuery } from 'app/types/series';
-import { StoreState } from 'app/types';
+// Services & Utils
 import store from 'app/core/store';
-import { LAST_USED_DATASOURCE_KEY, ensureQueries, DEFAULT_RANGE } from 'app/core/utils/explore';
+
+// Components
+import { DataSourceSelectItem } from '@grafana/ui/src/types';
 import { DataSourcePicker } from 'app/core/components/Select/DataSourcePicker';
-import { Emitter } from 'app/core/utils/emitter';
+import { Alert } from './Error';
+import ErrorBoundary from './ErrorBoundary';
+import GraphContainer from './GraphContainer';
+import LogsContainer from './LogsContainer';
+import QueryRows from './QueryRows';
+import TableContainer from './TableContainer';
+import TimePicker, { parseTime } from './TimePicker';
 
+// Actions
 import {
   changeDatasource,
   changeSize,
@@ -29,13 +35,12 @@ import {
   splitOpen,
 } from './state/actions';
 
-import { Alert } from './Error';
-import ErrorBoundary from './ErrorBoundary';
-import GraphContainer from './GraphContainer';
-import LogsContainer from './LogsContainer';
-import QueryRows from './QueryRows';
-import TableContainer from './TableContainer';
-import TimePicker, { parseTime } from './TimePicker';
+// Types
+import { RawTimeRange, TimeRange, DataQuery } from '@grafana/ui';
+import { ExploreItemState, ExploreUrlState, RangeScanner, ExploreId } from 'app/types/explore';
+import { StoreState } from 'app/types';
+import { LAST_USED_DATASOURCE_KEY, ensureQueries, DEFAULT_RANGE } from 'app/core/utils/explore';
+import { Emitter } from 'app/core/utils/emitter';
 
 interface ExploreProps {
   StartPage?: any;

+ 7 - 3
public/app/features/explore/QueryEditor.tsx

@@ -1,10 +1,14 @@
+// Libraries
 import React, { PureComponent } from 'react';
+
+// Services
 import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader';
-import { Emitter } from 'app/core/utils/emitter';
 import { getIntervals } from 'app/core/utils/explore';
-import { DataQuery } from 'app/types';
-import { RawTimeRange } from '@grafana/ui';
 import { getTimeSrv } from 'app/features/dashboard/time_srv';
+
+// Types
+import { Emitter } from 'app/core/utils/emitter';
+import { RawTimeRange, DataQuery } from '@grafana/ui';
 import 'app/features/plugins/plugin_loader';
 
 interface QueryEditorProps {

+ 11 - 7
public/app/features/explore/QueryRow.tsx

@@ -1,16 +1,14 @@
+// Libraries
 import React, { PureComponent } from 'react';
+import _ from 'lodash';
 import { hot } from 'react-hot-loader';
 import { connect } from 'react-redux';
-import { RawTimeRange } from '@grafana/ui';
-import _ from 'lodash';
-
-import { QueryTransaction, HistoryItem, QueryHint, ExploreItemState, ExploreId } from 'app/types/explore';
-import { Emitter } from 'app/core/utils/emitter';
-import { DataQuery, StoreState } from 'app/types';
 
-// import DefaultQueryField from './QueryField';
+// Components
 import QueryEditor from './QueryEditor';
 import QueryTransactionStatus from './QueryTransactionStatus';
+
+// Actions
 import {
   addQueryRow,
   changeQuery,
@@ -20,6 +18,12 @@ import {
   runQueries,
 } from './state/actions';
 
+// Types
+import { StoreState } from 'app/types';
+import { RawTimeRange, DataQuery, QueryHint } from '@grafana/ui';
+import { QueryTransaction, HistoryItem, ExploreItemState, ExploreId } from 'app/types/explore';
+import { Emitter } from 'app/core/utils/emitter';
+
 function getFirstHintFromTransactions(transactions: QueryTransaction[]): QueryHint {
   const transaction = transactions.find(qt => qt.hints && qt.hints.length > 0);
   if (transaction) {

+ 7 - 3
public/app/features/explore/QueryRows.tsx

@@ -1,17 +1,21 @@
+// Libraries
 import React, { PureComponent } from 'react';
 
+// Components
+import QueryRow from './QueryRow';
+
+// Types
 import { Emitter } from 'app/core/utils/emitter';
-import { DataQuery } from 'app/types';
+import { DataQuery } from '@grafana/ui/src/types';
 import { ExploreId } from 'app/types/explore';
 
-import QueryRow from './QueryRow';
-
 interface QueryRowsProps {
   className?: string;
   exploreEvents: Emitter;
   exploreId: ExploreId;
   initialQueries: DataQuery[];
 }
+
 export default class QueryRows extends PureComponent<QueryRowsProps> {
   render() {
     const { className = '', exploreEvents, exploreId, initialQueries } = this.props;

+ 2 - 4
public/app/features/explore/state/actionTypes.ts

@@ -1,6 +1,6 @@
-import { RawTimeRange, TimeRange } from '@grafana/ui';
-
+// Types
 import { Emitter } from 'app/core/core';
+import { RawTimeRange, TimeRange, DataQuery, DataSourceSelectItem  } from '@grafana/ui/src/types';
 import {
   ExploreId,
   ExploreItemState,
@@ -9,8 +9,6 @@ import {
   ResultType,
   QueryTransaction,
 } from 'app/types/explore';
-import { DataSourceSelectItem } from 'app/types/datasources';
-import { DataQuery } from 'app/types';
 
 export enum ActionTypes {
   AddQueryRow = 'explore/ADD_QUERY_ROW',

+ 12 - 8
public/app/features/explore/state/actions.ts

@@ -1,7 +1,9 @@
+// Libraries
 import _ from 'lodash';
 import { ThunkAction } from 'redux-thunk';
-import { RawTimeRange, TimeRange } from '@grafana/ui';
 
+// Services & Utils
+import store from 'app/core/store';
 import {
   LAST_USED_DATASOURCE_KEY,
   clearQueryKeys,
@@ -14,10 +16,12 @@ import {
   serializeStateToUrlParam,
 } from 'app/core/utils/explore';
 
+// Actions
 import { updateLocation } from 'app/core/actions';
-import store from 'app/core/store';
-import { DataSourceSelectItem } from 'app/types/datasources';
-import { DataQuery, StoreState } from 'app/types';
+
+// Types
+import { StoreState } from 'app/types';
+import { DataQuery, DataSourceSelectItem, QueryHint  } from '@grafana/ui/src/types';
 import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
 import {
   ExploreId,
@@ -26,11 +30,10 @@ import {
   ResultType,
   QueryOptions,
   QueryTransaction,
-  QueryHint,
-  QueryHintGetter,
 } from 'app/types/explore';
-import { Emitter } from 'app/core/core';
 
+import { Emitter } from 'app/core/core';
+import { RawTimeRange, TimeRange } from '@grafana/ui';
 import {
   Action as ThunkableAction,
   ActionTypes,
@@ -45,6 +48,7 @@ import {
   ScanStopAction,
 } from './actionTypes';
 
+
 type ThunkResult<R> = ThunkAction<R, StoreState, undefined, ThunkableAction>;
 
 /**
@@ -460,7 +464,7 @@ export function queryTransactionSuccess(
 
     // Get query hints
     let hints: QueryHint[];
-    if (datasourceInstance.getQueryHints as QueryHintGetter) {
+    if (datasourceInstance.getQueryHints) {
       hints = datasourceInstance.getQueryHints(transaction.query, result);
     }
 

+ 1 - 1
public/app/features/explore/state/reducers.ts

@@ -5,7 +5,7 @@ import {
   ensureQueries,
 } from 'app/core/utils/explore';
 import { ExploreItemState, ExploreState, QueryTransaction } from 'app/types/explore';
-import { DataQuery } from 'app/types/series';
+import { DataQuery } from '@grafana/ui/src/types';
 
 import { Action, ActionTypes } from './actionTypes';
 

+ 6 - 4
public/app/features/plugins/datasource_srv.ts

@@ -1,14 +1,16 @@
+// Libraries
 import _ from 'lodash';
 import coreModule from 'app/core/core_module';
 
+// Services & Utils
 import config from 'app/core/config';
 import { importPluginModule } from './plugin_loader';
 
-import { DataSourceApi } from 'app/types/series';
-import { DataSource, DataSourceSelectItem } from 'app/types';
+// Types
+import { DataSourceApi, DataSourceSelectItem  } from '@grafana/ui/src/types';
 
 export class DatasourceSrv {
-  datasources: { [name: string]: DataSource };
+  datasources: { [name: string]: DataSourceApi };
 
   /** @ngInject */
   constructor(private $q, private $injector, private $rootScope, private templateSrv) {
@@ -59,7 +61,7 @@ export class DatasourceSrv {
           throw new Error('Plugin module is missing Datasource constructor');
         }
 
-        const instance: DataSource = this.$injector.instantiate(plugin.Datasource, { instanceSettings: dsConfig });
+        const instance: DataSourceApi = this.$injector.instantiate(plugin.Datasource, { instanceSettings: dsConfig });
         instance.meta = pluginDef;
         instance.name = name;
         instance.pluginExports = plugin;

+ 1 - 1
public/app/features/plugins/plugin_loader.ts

@@ -18,7 +18,7 @@ import config from 'app/core/config';
 import TimeSeries from 'app/core/time_series2';
 import TableModel from 'app/core/table_model';
 import { coreModule, appEvents, contextSrv } from 'app/core/core';
-import { PluginExports } from 'app/types/plugins';
+import { PluginExports } from '@grafana/ui';
 import * as datemath from 'app/core/utils/datemath';
 import * as fileExport from 'app/core/utils/file_export';
 import * as flatten from 'app/core/utils/flatten';

+ 8 - 2
public/app/features/plugins/state/navModel.ts

@@ -1,8 +1,14 @@
+// Libraries
 import _ from 'lodash';
-import { DataSource, PluginMeta, NavModel } from 'app/types';
+
+// Utils & Services
 import config from 'app/core/config';
 
-export function buildNavModel(ds: DataSource, plugin: PluginMeta, currentPage: string): NavModel {
+// Types
+import { NavModel } from 'app/types';
+import { PluginMeta, DataSourceSettings } from '@grafana/ui/src/types';
+
+export function buildNavModel(ds: DataSourceSettings, plugin: PluginMeta, currentPage: string): NavModel {
   let title = 'New';
   const subTitle = `Type: ${plugin.name}`;
 

+ 1 - 1
public/app/plugins/datasource/loki/components/LokiQueryField.tsx

@@ -3,6 +3,7 @@ import Cascader from 'rc-cascader';
 import PluginPrism from 'slate-prism';
 import Prism from 'prismjs';
 
+import { DataQuery } from '@grafana/ui/src/types';
 import { TypeaheadOutput } from 'app/types/explore';
 
 // dom also includes Element polyfills
@@ -10,7 +11,6 @@ import { getNextCharacter, getPreviousCousin } from 'app/features/explore/utils/
 import BracesPlugin from 'app/features/explore/slate-plugins/braces';
 import RunnerPlugin from 'app/features/explore/slate-plugins/runner';
 import QueryField, { TypeaheadInput, QueryFieldState } from 'app/features/explore/QueryField';
-import { DataQuery } from 'app/types';
 
 const PRISM_SYNTAX = 'promql';
 

+ 1 - 1
public/app/plugins/datasource/loki/datasource.ts

@@ -2,7 +2,7 @@ import _ from 'lodash';
 
 import * as dateMath from 'app/core/utils/datemath';
 import { LogsStream, LogsModel, makeSeriesForLogs } from 'app/core/logs_model';
-import { PluginMeta, DataQuery } from 'app/types';
+import { PluginMeta, DataQuery } from '@grafana/ui/src/types';
 import { addLabelToSelector } from 'app/plugins/datasource/prometheus/add_label_to_query';
 
 import LanguageProvider from './language_provider';

+ 1 - 1
public/app/plugins/datasource/loki/language_provider.ts

@@ -11,7 +11,7 @@ import {
 } from 'app/types/explore';
 import { parseSelector, labelRegexp, selectorRegexp } from 'app/plugins/datasource/prometheus/language_utils';
 import syntax from './syntax';
-import { DataQuery } from 'app/types';
+import { DataQuery } from '@grafana/ui/src/types';
 
 const DEFAULT_KEYS = ['job', 'namespace'];
 const EMPTY_SELECTOR = '{}';

+ 1 - 1
public/app/plugins/datasource/prometheus/components/PromQueryField.tsx

@@ -11,7 +11,7 @@ import { getNextCharacter, getPreviousCousin } from 'app/features/explore/utils/
 import BracesPlugin from 'app/features/explore/slate-plugins/braces';
 import RunnerPlugin from 'app/features/explore/slate-plugins/runner';
 import QueryField, { TypeaheadInput, QueryFieldState } from 'app/features/explore/QueryField';
-import { DataQuery } from 'app/types';
+import { DataQuery } from '@grafana/ui/src/types';
 
 const HISTOGRAM_GROUP = '__histograms__';
 const METRIC_MARK = 'metric';

+ 1 - 1
public/app/plugins/datasource/prometheus/datasource.ts

@@ -11,7 +11,7 @@ import { BackendSrv } from 'app/core/services/backend_srv';
 import addLabelToQuery from './add_label_to_query';
 import { getQueryHints } from './query_hints';
 import { expandRecordingRules } from './language_utils';
-import { DataQuery } from 'app/types';
+import { DataQuery } from '@grafana/ui/src/types';
 import { ExploreUrlState } from 'app/types/explore';
 
 export function alignRange(start, end, step) {

+ 1 - 2
public/app/plugins/datasource/prometheus/query_hints.ts

@@ -1,6 +1,5 @@
 import _ from 'lodash';
-
-import { QueryHint } from 'app/types/explore';
+import { QueryHint } from '@grafana/ui/src/types';
 
 /**
  * Number of time series results needed before starting to suggest sum aggregation hints

+ 66 - 0
public/app/plugins/datasource/testdata/QueryEditor.tsx

@@ -0,0 +1,66 @@
+// Libraries
+import React, { PureComponent } from 'react';
+import _ from 'lodash';
+
+// Services & Utils
+import { getBackendSrv, BackendSrv } from 'app/core/services/backend_srv';
+
+// Components
+import { FormLabel, Select, SelectOptionItem } from '@grafana/ui';
+
+// Types
+import { QueryEditorProps } from '@grafana/ui/src/types';
+
+interface Scenario {
+  id: string;
+  name: string;
+}
+
+interface State {
+  scenarioList: Scenario[];
+  current: Scenario | null;
+}
+
+export class QueryEditor extends PureComponent<QueryEditorProps> {
+  backendSrv: BackendSrv = getBackendSrv();
+
+  state: State = {
+    scenarioList: [],
+    current: null,
+  };
+
+  async componentDidMount() {
+    const { query } = this.props;
+
+    query.scenarioId = query.scenarioId || 'random_walk';
+
+    const scenarioList = await this.backendSrv.get('/api/tsdb/testdata/scenarios');
+    const current = _.find(scenarioList, { id: query.scenarioId });
+
+    this.setState({ scenarioList: scenarioList, current: current });
+  }
+
+  onScenarioChange = (item: SelectOptionItem) => {
+    this.props.onQueryChange({
+      scenarioId: item.value,
+      ...this.props.query
+    });
+  }
+
+  render() {
+    const { query } = this.props;
+    const options = this.state.scenarioList.map(item => ({ label: item.name, value: item.id }));
+    const current = options.find(item => item.value === query.scenarioId);
+
+    return (
+      <div className="gf-form-inline">
+        <div className="gf-form">
+          <FormLabel className="query-keyword" width={7}>
+            Scenario
+          </FormLabel>
+          <Select options={options} value={current} onChange={this.onScenarioChange} />
+        </div>
+      </div>
+    );
+  }
+}

+ 2 - 1
public/app/plugins/datasource/testdata/module.ts

@@ -1,5 +1,6 @@
 import { TestDataDatasource } from './datasource';
 import { TestDataQueryCtrl } from './query_ctrl';
+// import { QueryEditor } from './QueryEditor';
 
 class TestDataAnnotationsQueryCtrl {
   annotation: any;
@@ -10,7 +11,7 @@ class TestDataAnnotationsQueryCtrl {
 }
 
 export {
-  TestDataDatasource,
+  // QueryEditor,
   TestDataDatasource as Datasource,
   TestDataQueryCtrl as QueryCtrl,
   TestDataAnnotationsQueryCtrl as AnnotationsQueryCtrl,

+ 2 - 2
public/app/routes/routes.ts

@@ -14,7 +14,7 @@ import DataSourcesListPage from 'app/features/datasources/DataSourcesListPage';
 import NewDataSourcePage from '../features/datasources/NewDataSourcePage';
 import UsersListPage from 'app/features/users/UsersListPage';
 import DataSourceDashboards from 'app/features/datasources/DataSourceDashboards';
-import DataSourceSettings from '../features/datasources/settings/DataSourceSettings';
+import DataSourceSettingsPage from '../features/datasources/settings/DataSourceSettingsPage';
 import OrgDetailsPage from '../features/org/OrgDetailsPage';
 
 /** @ngInject */
@@ -78,7 +78,7 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
     .when('/datasources/edit/:id/', {
       template: '<react-container />',
       resolve: {
-        component: () => DataSourceSettings,
+        component: () => DataSourceSettingsPage,
       },
     })
     .when('/datasources/edit/:id/dashboards', {

+ 4 - 32
public/app/types/datasources.ts

@@ -1,43 +1,15 @@
 import { LayoutMode } from '../core/components/LayoutSelector/LayoutSelector';
-import { Plugin, PluginExports, PluginMeta } from './plugins';
-
-export interface DataSource {
-  id: number;
-  orgId: number;
-  name: string;
-  typeLogoUrl: string;
-  type: string;
-  access: string;
-  url: string;
-  password: string;
-  user: string;
-  database: string;
-  basicAuth: boolean;
-  basicAuthPassword: string;
-  basicAuthUser: string;
-  isDefault: boolean;
-  jsonData: { authType: string; defaultRegion: string };
-  readOnly: boolean;
-  withCredentials: boolean;
-  meta?: PluginMeta;
-  pluginExports?: PluginExports;
-}
-
-export interface DataSourceSelectItem {
-  name: string;
-  value: string | null;
-  meta: PluginMeta;
-  sort: string;
-}
+import { Plugin } from './plugins';
+import { DataSourceSettings } from '@grafana/ui/src/types';
 
 export interface DataSourcesState {
-  dataSources: DataSource[];
+  dataSources: DataSourceSettings[];
   searchQuery: string;
   dataSourceTypeSearchQuery: string;
   layoutMode: LayoutMode;
   dataSourcesCount: number;
   dataSourceTypes: Plugin[];
-  dataSource: DataSource;
+  dataSource: DataSourceSettings;
   dataSourceMeta: Plugin;
   hasFetched: boolean;
 }

+ 2 - 27
public/app/types/explore.ts

@@ -1,12 +1,9 @@
 import { Value } from 'slate';
-import { RawTimeRange, TimeRange } from '@grafana/ui';
+import { RawTimeRange, TimeRange, DataQuery, DataSourceSelectItem, DataSourceApi, QueryHint } from '@grafana/ui';
 
 import { Emitter } from 'app/core/core';
 import { LogsModel } from 'app/core/logs_model';
 import TableModel from 'app/core/table_model';
-import { DataSourceSelectItem } from 'app/types/datasources';
-
-import { DataQuery } from './series';
 
 export interface CompletionItem {
   /**
@@ -113,7 +110,7 @@ export interface ExploreItemState {
   /**
    * Datasource instance that has been selected. Datasource-specific logic can be run on this object.
    */
-  datasourceInstance: any;
+  datasourceInstance: DataSourceApi;
   /**
    * Error to be shown when datasource loading or testing failed.
    */
@@ -276,28 +273,6 @@ export interface TypeaheadOutput {
   suggestions: CompletionItemGroup[];
 }
 
-export interface QueryFix {
-  type: string;
-  label: string;
-  action?: QueryFixAction;
-}
-
-export interface QueryFixAction {
-  type: string;
-  query?: string;
-  preventSubmit?: boolean;
-}
-
-export interface QueryHint {
-  type: string;
-  label: string;
-  fix?: QueryFix;
-}
-
-export interface QueryHintGetter {
-  (query: DataQuery, results: any[], ...rest: any): QueryHint[];
-}
-
 export interface QueryIntervals {
   interval: string;
   intervalMs: number;

+ 18 - 89
public/app/types/index.ts

@@ -1,90 +1,19 @@
-import { Team, TeamsState, TeamState, TeamGroup, TeamMember } from './teams';
-import { AlertRuleDTO, AlertRule, AlertRulesState } from './alerting';
-import { LocationState, LocationUpdate, UrlQueryMap, UrlQueryValue } from './location';
-import { NavModel, NavModelItem, NavIndex } from './navModel';
-import { FolderDTO, FolderState, FolderInfo } from './folders';
-import { DashboardState } from './dashboard';
-import { DashboardAcl, OrgRole, PermissionLevel } from './acl';
-import { ApiKey, ApiKeysState, NewApiKey } from './apiKeys';
-import { Invitee, OrgUser, User, UsersState, UserState } from './user';
-import { DataSource, DataSourceSelectItem, DataSourcesState } from './datasources';
-import { DataQuery, DataQueryResponse, DataQueryOptions } from './series';
-import { PluginDashboard, PluginMeta, Plugin, PanelPlugin, PluginsState } from './plugins';
-import { Organization, OrganizationState } from './organization';
-import {
-  AppNotification,
-  AppNotificationSeverity,
-  AppNotificationsState,
-  AppNotificationTimeout,
-} from './appNotifications';
-import { DashboardSearchHit } from './search';
-import { ValidationEvents, ValidationRule } from './form';
-import { ExploreState } from './explore';
-export {
-  Team,
-  TeamsState,
-  TeamState,
-  TeamGroup,
-  TeamMember,
-  AlertRuleDTO,
-  AlertRule,
-  AlertRulesState,
-  LocationState,
-  LocationUpdate,
-  NavModel,
-  NavModelItem,
-  NavIndex,
-  UrlQueryMap,
-  UrlQueryValue,
-  FolderDTO,
-  FolderState,
-  FolderInfo,
-  DashboardState,
-  DashboardAcl,
-  OrgRole,
-  PermissionLevel,
-  DataSource,
-  DataSourceSelectItem,
-  PluginMeta,
-  ApiKey,
-  ApiKeysState,
-  NewApiKey,
-  Plugin,
-  PluginsState,
-  DataSourcesState,
-  Invitee,
-  OrgUser,
-  User,
-  UsersState,
-  PanelPlugin,
-  DataQuery,
-  DataQueryResponse,
-  DataQueryOptions,
-  PluginDashboard,
-  Organization,
-  OrganizationState,
-  AppNotification,
-  AppNotificationsState,
-  AppNotificationSeverity,
-  AppNotificationTimeout,
-  DashboardSearchHit,
-  UserState,
-  ValidationEvents,
-  ValidationRule,
-};
+export * from './teams';
+export * from './alerting';
+export * from './location';
+export * from './navModel';
+export * from './folders';
+export * from './dashboard';
+export * from './acl';
+export * from './apiKeys';
+export * from './user';
+export * from './datasources';
+export * from './plugins';
+export * from './organization';
+export * from './appNotifications';
+export * from './search';
+export * from './form';
+export * from './explore';
+export * from './store';
+
 
-export interface StoreState {
-  navIndex: NavIndex;
-  location: LocationState;
-  alertRules: AlertRulesState;
-  teams: TeamsState;
-  team: TeamState;
-  folder: FolderState;
-  dashboard: DashboardState;
-  dataSources: DataSourcesState;
-  explore: ExploreState;
-  users: UsersState;
-  organization: OrganizationState;
-  appNotifications: AppNotificationsState;
-  user: UserState;
-}

+ 1 - 69
public/app/types/plugins.ts

@@ -1,22 +1,4 @@
-import { ComponentClass } from 'react';
-import { PanelProps, PanelOptionsProps } from '@grafana/ui';
-
-export interface PluginExports {
-  Datasource?: any;
-  QueryCtrl?: any;
-  QueryEditor?: any;
-  ConfigCtrl?: any;
-  AnnotationsQueryCtrl?: any;
-  VariableQueryEditor?: any;
-  ExploreQueryField?: any;
-  ExploreStartPage?: any;
-
-  // Panel plugin
-  PanelCtrl?;
-  Panel?: ComponentClass<PanelProps>;
-  PanelOptions?: ComponentClass<PanelOptionsProps>;
-  PanelDefaults?: any;
-}
+import { PluginExports, PluginMetaInfo } from '@grafana/ui/src/types';
 
 export interface PanelPlugin {
   id: string;
@@ -29,56 +11,6 @@ export interface PanelPlugin {
   exports?: PluginExports;
 }
 
-interface PluginMetaQueryOptions {
-  cacheTimeout?: boolean;
-  maxDataPoints?: boolean;
-  minInterval?: boolean;
-}
-
-export interface PluginMeta {
-  id: string;
-  name: string;
-  info: PluginMetaInfo;
-  includes: PluginInclude[];
-
-  // Datasource-specific
-  metrics?: boolean;
-  tables?: boolean;
-  logs?: boolean;
-  explore?: boolean;
-  annotations?: boolean;
-  mixed?: boolean;
-  hasQueryHelp?: boolean;
-  queryOptions?: PluginMetaQueryOptions;
-}
-
-export interface PluginInclude {
-  type: string;
-  name: string;
-  path: string;
-}
-
-interface PluginMetaInfoLink {
-  name: string;
-  url: string;
-}
-
-export interface PluginMetaInfo {
-  author: {
-    name: string;
-    url?: string;
-  };
-  description: string;
-  links: PluginMetaInfoLink[];
-  logos: {
-    large: string;
-    small: string;
-  };
-  screenshots: any[];
-  updated: string;
-  version: string;
-}
-
 export interface Plugin {
   defaultNavUrl: string;
   enabled: boolean;

+ 0 - 56
public/app/types/series.ts

@@ -1,56 +0,0 @@
-import { PluginMeta, PluginExports } from './plugins';
-import { TimeSeries, TimeRange, RawTimeRange } from '@grafana/ui';
-
-export interface DataQueryResponse {
-  data: TimeSeries[];
-}
-
-export interface DataQuery {
-  refId: string;
-  [key: string]: any;
-}
-
-export interface DataQueryOptions {
-  timezone: string;
-  range: TimeRange;
-  rangeRaw: RawTimeRange;
-  targets: DataQuery[];
-  panelId: number;
-  dashboardId: number;
-  cacheTimeout?: string;
-  interval: string;
-  intervalMs: number;
-  maxDataPoints: number;
-  scopedVars: object;
-}
-
-export interface DataSourceApi {
-  name: string;
-  meta: PluginMeta;
-  pluginExports: PluginExports;
-
-  /**
-   *  min interval range
-   */
-  interval?: string;
-
-  /**
-   * Imports queries from a different datasource
-   */
-  importQueries?(queries: DataQuery[], originMeta: PluginMeta): Promise<DataQuery[]>;
-
-  /**
-   * Initializes a datasource after instantiation
-   */
-  init?: () => void;
-
-  /**
-   * Main metrics / data query action
-   */
-  query(options: DataQueryOptions): Promise<DataQueryResponse>;
-
-  /**
-   * Test & verify datasource settings & connection details
-   */
-  testDatasource(): Promise<any>;
-}

+ 27 - 0
public/app/types/store.ts

@@ -0,0 +1,27 @@
+import { NavIndex } from './navModel';
+import { LocationState } from './location';
+import { AlertRulesState } from './alerting';
+import { TeamsState, TeamState } from './teams';
+import { FolderState } from './folders';
+import { DashboardState } from './dashboard';
+import { DataSourcesState } from './datasources';
+import { ExploreState } from './explore';
+import { UsersState, UserState } from './user';
+import { OrganizationState } from './organization';
+import { AppNotificationsState } from './appNotifications';
+
+export interface StoreState {
+  navIndex: NavIndex;
+  location: LocationState;
+  alertRules: AlertRulesState;
+  teams: TeamsState;
+  team: TeamState;
+  folder: FolderState;
+  dashboard: DashboardState;
+  dataSources: DataSourcesState;
+  explore: ExploreState;
+  users: UsersState;
+  organization: OrganizationState;
+  appNotifications: AppNotificationsState;
+  user: UserState;
+}