From 0d02ceb4527fcdfb532166bef8b82a9afec52153 Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Thu, 2 May 2019 21:56:54 -0700 Subject: [PATCH] Input Datasource: convert from angular config to react ConfigEditor (#16856) * use ConfigEditor * use ConfigEditor * update readme * make the jsondata generic --- packages/grafana-ui/src/types/datasource.ts | 32 +++++--- .../datasource/input/InputConfigEditor.tsx | 74 +++++++++++++++++++ ...source.test.ts => InputDatasource.test.ts} | 6 +- .../{datasource.ts => InputDatasource.ts} | 5 +- .../datasource/input/InputQueryEditor.tsx | 4 +- public/app/plugins/datasource/input/README.md | 2 +- .../input/legacy/CSVInputWrapper.tsx | 45 ----------- .../input/legacy/InputConfigCtrl.ts | 21 ------ .../datasource/input/legacy/config.html | 16 ---- public/app/plugins/datasource/input/module.ts | 13 +++- public/app/plugins/datasource/input/types.ts | 7 +- 11 files changed, 118 insertions(+), 107 deletions(-) create mode 100644 public/app/plugins/datasource/input/InputConfigEditor.tsx rename public/app/plugins/datasource/input/{datasource.test.ts => InputDatasource.test.ts} (82%) rename public/app/plugins/datasource/input/{datasource.ts => InputDatasource.ts} (95%) delete mode 100644 public/app/plugins/datasource/input/legacy/CSVInputWrapper.tsx delete mode 100644 public/app/plugins/datasource/input/legacy/InputConfigCtrl.ts delete mode 100644 public/app/plugins/datasource/input/legacy/config.html diff --git a/packages/grafana-ui/src/types/datasource.ts b/packages/grafana-ui/src/types/datasource.ts index 299545a0cda..f918063d06b 100644 --- a/packages/grafana-ui/src/types/datasource.ts +++ b/packages/grafana-ui/src/types/datasource.ts @@ -4,13 +4,16 @@ import { PluginMeta, GrafanaPlugin } from './plugin'; import { TableData, TimeSeries, SeriesData, LoadingState } from './data'; import { PanelData } from './panel'; +// NOTE: this seems more general than just DataSource export interface DataSourcePluginOptionsEditorProps { options: TOptions; onOptionsChange: (options: TOptions) => void; } -export class DataSourcePlugin extends GrafanaPlugin< - DataSourcePluginMeta -> { + +export class DataSourcePlugin< + TOptions extends DataSourceJsonData = DataSourceJsonData, + TQuery extends DataQuery = DataQuery +> extends GrafanaPlugin { DataSourceClass: DataSourceConstructor; components: DataSourcePluginComponents; @@ -20,7 +23,7 @@ export class DataSourcePlugin>) { + setConfigEditor(editor: React.ComponentType>>) { this.components.ConfigEditor = editor; return this; } @@ -85,14 +88,17 @@ interface PluginMetaQueryOptions { minInterval?: boolean; } -export interface DataSourcePluginComponents { +export interface DataSourcePluginComponents< + TOptions extends DataSourceJsonData = DataSourceJsonData, + TQuery extends DataQuery = DataQuery +> { QueryCtrl?: any; AnnotationsQueryCtrl?: any; VariableQueryEditor?: any; QueryEditor?: ComponentClass>; ExploreQueryField?: ComponentClass>; ExploreStartPage?: ComponentClass; - ConfigEditor?: React.ComponentType>; + ConfigEditor?: React.ComponentType>>; } export interface DataSourceConstructor { @@ -329,11 +335,16 @@ export interface QueryHint { fix?: QueryFix; } +export interface DataSourceJsonData { + authType?: string; + defaultRegion?: string; +} + /** * Data Source instance edit model. This is returned from: * /api/datasources */ -export interface DataSourceSettings { +export interface DataSourceSettings { id: number; orgId: number; name: string; @@ -348,7 +359,8 @@ export interface DataSourceSettings { basicAuthPassword: string; basicAuthUser: string; isDefault: boolean; - jsonData: { authType: string; defaultRegion: string }; + jsonData: T; + secureJsonData?: S; readOnly: boolean; withCredentials: boolean; } @@ -358,13 +370,13 @@ export interface DataSourceSettings { * as this data model is available to every user who has access to a data source (Viewers+). This is loaded * in bootData (on page load), or from: /api/frontend/settings */ -export interface DataSourceInstanceSettings { +export interface DataSourceInstanceSettings { id: number; type: string; name: string; meta: DataSourcePluginMeta; url?: string; - jsonData: { [str: string]: any }; + jsonData: T; username?: string; password?: string; // when access is direct, for some legacy datasources diff --git a/public/app/plugins/datasource/input/InputConfigEditor.tsx b/public/app/plugins/datasource/input/InputConfigEditor.tsx new file mode 100644 index 00000000000..47faf67bd48 --- /dev/null +++ b/public/app/plugins/datasource/input/InputConfigEditor.tsx @@ -0,0 +1,74 @@ +// Libraries +import React, { PureComponent } from 'react'; + +// Types +import { InputOptions } from './types'; + +import { DataSourcePluginOptionsEditorProps, DataSourceSettings, SeriesData, TableInputCSV, toCSV } from '@grafana/ui'; + +type InputSettings = DataSourceSettings; + +interface Props extends DataSourcePluginOptionsEditorProps {} + +interface State { + text: string; +} + +export class InputConfigEditor extends PureComponent { + state = { + text: '', + }; + + componentDidMount() { + const { options } = this.props; + if (options.jsonData.data) { + const text = toCSV(options.jsonData.data); + this.setState({ text }); + } + } + + onSeriesParsed = (data: SeriesData[], text: string) => { + const { options, onOptionsChange } = this.props; + if (!data) { + data = [ + { + fields: [], + rows: [], + }, + ]; + } + // data is a property on 'jsonData' + const jsonData = { + ...options.jsonData, + data, + }; + + onOptionsChange({ + ...options, + jsonData, + }); + this.setState({ text }); + }; + + render() { + const { text } = this.state; + return ( +
+
+

Shared Data:

+ Enter CSV + +
+ +
+ This data is stored in the datasource json and is returned to every user in the initial request for any + datasource. This is an appropriate place to enter a few values. Large datasets will perform better in other + datasources. +
+
+ NOTE: Changes to this data will only be reflected after a browser refresh. +
+
+ ); + } +} diff --git a/public/app/plugins/datasource/input/datasource.test.ts b/public/app/plugins/datasource/input/InputDatasource.test.ts similarity index 82% rename from public/app/plugins/datasource/input/datasource.test.ts rename to public/app/plugins/datasource/input/InputDatasource.test.ts index 164ba2d05c9..2a8412dca88 100644 --- a/public/app/plugins/datasource/input/datasource.test.ts +++ b/public/app/plugins/datasource/input/InputDatasource.test.ts @@ -1,11 +1,11 @@ -import InputDatasource from './datasource'; -import { InputQuery } from './types'; +import InputDatasource from './InputDatasource'; +import { InputQuery, InputOptions } from './types'; import { readCSV, DataSourceInstanceSettings, PluginMeta } from '@grafana/ui'; import { getQueryOptions } from 'test/helpers/getQueryOptions'; describe('InputDatasource', () => { const data = readCSV('a,b,c\n1,2,3\n4,5,6'); - const instanceSettings: DataSourceInstanceSettings = { + const instanceSettings: DataSourceInstanceSettings = { id: 1, type: 'x', name: 'xxx', diff --git a/public/app/plugins/datasource/input/datasource.ts b/public/app/plugins/datasource/input/InputDatasource.ts similarity index 95% rename from public/app/plugins/datasource/input/datasource.ts rename to public/app/plugins/datasource/input/InputDatasource.ts index bf78bfb6173..72b6190a670 100644 --- a/public/app/plugins/datasource/input/datasource.ts +++ b/public/app/plugins/datasource/input/InputDatasource.ts @@ -6,7 +6,7 @@ import { DataSourceApi, DataSourceInstanceSettings, } from '@grafana/ui/src/types'; -import { InputQuery } from './types'; +import { InputQuery, InputOptions } from './types'; export class InputDatasource implements DataSourceApi { data: SeriesData[]; @@ -17,8 +17,7 @@ export class InputDatasource implements DataSourceApi { // Filled in by grafana plugin system id?: number; - /** @ngInject */ - constructor(instanceSettings: DataSourceInstanceSettings) { + constructor(instanceSettings: DataSourceInstanceSettings) { if (instanceSettings.jsonData) { this.data = instanceSettings.jsonData.data; } diff --git a/public/app/plugins/datasource/input/InputQueryEditor.tsx b/public/app/plugins/datasource/input/InputQueryEditor.tsx index c4244435288..1bbfb76f50b 100644 --- a/public/app/plugins/datasource/input/InputQueryEditor.tsx +++ b/public/app/plugins/datasource/input/InputQueryEditor.tsx @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; // Types -import { InputDatasource } from './datasource'; +import { InputDatasource } from './InputDatasource'; import { InputQuery } from './types'; import { FormLabel, Select, QueryEditorProps, SelectOptionItem, SeriesData, TableInputCSV, toCSV } from '@grafana/ui'; @@ -94,5 +94,3 @@ export class InputQueryEditor extends PureComponent { ); } } - -export default InputQueryEditor; diff --git a/public/app/plugins/datasource/input/README.md b/public/app/plugins/datasource/input/README.md index facfeca8faf..fbe38ae66cc 100644 --- a/public/app/plugins/datasource/input/README.md +++ b/public/app/plugins/datasource/input/README.md @@ -1,3 +1,3 @@ -# Table Datasource - Native Plugin +# Direct Input Datasource - Native Plugin This datasource lets you define results directly in CSV. The values are stored either in a shared datasource, or directly in panels. diff --git a/public/app/plugins/datasource/input/legacy/CSVInputWrapper.tsx b/public/app/plugins/datasource/input/legacy/CSVInputWrapper.tsx deleted file mode 100644 index 0974a9f44c1..00000000000 --- a/public/app/plugins/datasource/input/legacy/CSVInputWrapper.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import React, { Component } from 'react'; - -import coreModule from 'app/core/core_module'; - -import { TableInputCSV, SeriesData, toCSV } from '@grafana/ui'; - -interface Props { - data: SeriesData[]; - onParsed: (data: SeriesData[]) => void; -} - -interface State { - data: SeriesData[]; - text: string; -} - -/** - * Angular wrapper around TableInputCSV - */ -class Wraper extends Component { - constructor(props) { - super(props); - this.state = { - text: toCSV(props.data), - data: props.data, - }; - } - - onSeriesParsed = (data: SeriesData[], text: string) => { - this.setState({ data, text }); - this.props.onParsed(data); - }; - - render() { - const { text } = this.state; - return ; - } -} - -coreModule.directive('csvInput', [ - 'reactDirective', - reactDirective => { - return reactDirective(Wraper, ['data', 'onParsed']); - }, -]); diff --git a/public/app/plugins/datasource/input/legacy/InputConfigCtrl.ts b/public/app/plugins/datasource/input/legacy/InputConfigCtrl.ts deleted file mode 100644 index acca7e94327..00000000000 --- a/public/app/plugins/datasource/input/legacy/InputConfigCtrl.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { SeriesData } from '@grafana/ui'; - -// Loads the angular wrapping directive -import './CSVInputWrapper'; - -export class TableConfigCtrl { - static templateUrl = 'legacy/config.html'; - - current: any; // the Current Configuration (set by the plugin infra) - - /** @ngInject */ - constructor($scope: any, $injector: any) { - console.log('TableConfigCtrl Init', this); - } - - onParsed = (data: SeriesData[]) => { - this.current.jsonData.data = data; - }; -} - -export default TableConfigCtrl; diff --git a/public/app/plugins/datasource/input/legacy/config.html b/public/app/plugins/datasource/input/legacy/config.html deleted file mode 100644 index 7760879e4b7..00000000000 --- a/public/app/plugins/datasource/input/legacy/config.html +++ /dev/null @@ -1,16 +0,0 @@ -
-

Shared Data:

- Enter CSV - -
- -
- This data is stored in the datasource json and is returned to every user - in the initial request for any datasource. This is an appropriate place - to enter a few values. Large datasets will perform better in other datasources. -

- NOTE: Changes to this data will only be reflected after a browser refresh. -
diff --git a/public/app/plugins/datasource/input/module.ts b/public/app/plugins/datasource/input/module.ts index f7cfceeaa02..05a48c965ca 100644 --- a/public/app/plugins/datasource/input/module.ts +++ b/public/app/plugins/datasource/input/module.ts @@ -1,6 +1,11 @@ -import Datasource from './datasource'; +import { DataSourcePlugin } from '@grafana/ui'; -import InputQueryEditor from './InputQueryEditor'; -import InputConfigCtrl from './legacy/InputConfigCtrl'; +import { InputDatasource } from './InputDatasource'; -export { Datasource, InputQueryEditor as QueryEditor, InputConfigCtrl as ConfigCtrl }; +import { InputQueryEditor } from './InputQueryEditor'; +import { InputConfigEditor } from './InputConfigEditor'; +import { InputOptions, InputQuery } from './types'; + +export const plugin = new DataSourcePlugin(InputDatasource) + .setConfigEditor(InputConfigEditor) + .setQueryEditor(InputQueryEditor); diff --git a/public/app/plugins/datasource/input/types.ts b/public/app/plugins/datasource/input/types.ts index 7aedb8e1192..15b19f2dca2 100644 --- a/public/app/plugins/datasource/input/types.ts +++ b/public/app/plugins/datasource/input/types.ts @@ -1,6 +1,11 @@ -import { DataQuery, SeriesData } from '@grafana/ui/src/types'; +import { DataQuery, SeriesData, DataSourceJsonData } from '@grafana/ui/src/types'; export interface InputQuery extends DataQuery { // Data saved in the panel data?: SeriesData[]; } + +export interface InputOptions extends DataSourceJsonData { + // Saved in the datasource and download with bootData + data?: SeriesData[]; +}