Commit 0d02ceb4 by Ryan McKinley Committed by Torkel Ödegaard

Input Datasource: convert from angular config to react ConfigEditor (#16856)

* use ConfigEditor

* use ConfigEditor

* update readme

* make the jsondata generic
parent ece4d220
......@@ -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<TOptions> {
options: TOptions;
onOptionsChange: (options: TOptions) => void;
}
export class DataSourcePlugin<TOptions = {}, TQuery extends DataQuery = DataQuery> extends GrafanaPlugin<
DataSourcePluginMeta
> {
export class DataSourcePlugin<
TOptions extends DataSourceJsonData = DataSourceJsonData,
TQuery extends DataQuery = DataQuery
> extends GrafanaPlugin<DataSourcePluginMeta> {
DataSourceClass: DataSourceConstructor<TQuery>;
components: DataSourcePluginComponents<TOptions, TQuery>;
......@@ -20,7 +23,7 @@ export class DataSourcePlugin<TOptions = {}, TQuery extends DataQuery = DataQuer
this.components = {};
}
setConfigEditor(editor: React.ComponentType<DataSourcePluginOptionsEditorProps<TOptions>>) {
setConfigEditor(editor: React.ComponentType<DataSourcePluginOptionsEditorProps<DataSourceSettings<TOptions>>>) {
this.components.ConfigEditor = editor;
return this;
}
......@@ -85,14 +88,17 @@ interface PluginMetaQueryOptions {
minInterval?: boolean;
}
export interface DataSourcePluginComponents<TOptions = {}, TQuery extends DataQuery = DataQuery> {
export interface DataSourcePluginComponents<
TOptions extends DataSourceJsonData = DataSourceJsonData,
TQuery extends DataQuery = DataQuery
> {
QueryCtrl?: any;
AnnotationsQueryCtrl?: any;
VariableQueryEditor?: any;
QueryEditor?: ComponentClass<QueryEditorProps<DataSourceApi, TQuery>>;
ExploreQueryField?: ComponentClass<ExploreQueryFieldProps<DataSourceApi, TQuery>>;
ExploreStartPage?: ComponentClass<ExploreStartPageProps>;
ConfigEditor?: React.ComponentType<DataSourcePluginOptionsEditorProps<TOptions>>;
ConfigEditor?: React.ComponentType<DataSourcePluginOptionsEditorProps<DataSourceSettings<TOptions>>>;
}
export interface DataSourceConstructor<TQuery extends DataQuery = DataQuery> {
......@@ -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<T extends DataSourceJsonData = DataSourceJsonData, S = {}> {
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<T extends DataSourceJsonData = DataSourceJsonData> {
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
......
// Libraries
import React, { PureComponent } from 'react';
// Types
import { InputOptions } from './types';
import { DataSourcePluginOptionsEditorProps, DataSourceSettings, SeriesData, TableInputCSV, toCSV } from '@grafana/ui';
type InputSettings = DataSourceSettings<InputOptions>;
interface Props extends DataSourcePluginOptionsEditorProps<InputSettings> {}
interface State {
text: string;
}
export class InputConfigEditor extends PureComponent<Props, State> {
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 (
<div>
<div className="gf-form-group">
<h4>Shared Data:</h4>
<span>Enter CSV</span>
<TableInputCSV text={text} onSeriesParsed={this.onSeriesParsed} width={'100%'} height={200} />
</div>
<div className="grafana-info-box">
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.
<br />
<br />
<b>NOTE:</b> Changes to this data will only be reflected after a browser refresh.
</div>
</div>
);
}
}
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<InputOptions> = {
id: 1,
type: 'x',
name: 'xxx',
......
......@@ -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<InputQuery> {
data: SeriesData[];
......@@ -17,8 +17,7 @@ export class InputDatasource implements DataSourceApi<InputQuery> {
// Filled in by grafana plugin system
id?: number;
/** @ngInject */
constructor(instanceSettings: DataSourceInstanceSettings) {
constructor(instanceSettings: DataSourceInstanceSettings<InputOptions>) {
if (instanceSettings.jsonData) {
this.data = instanceSettings.jsonData.data;
}
......
......@@ -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<Props, State> {
);
}
}
export default InputQueryEditor;
# 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.
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<Props, State> {
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 <TableInputCSV text={text} onSeriesParsed={this.onSeriesParsed} width={'100%'} height={300} />;
}
}
coreModule.directive('csvInput', [
'reactDirective',
reactDirective => {
return reactDirective(Wraper, ['data', 'onParsed']);
},
]);
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;
<div class="gf-form-group">
<h4>Shared Data:</h4>
<span>Enter CSV</span>
<csv-input
data="ctrl.current.jsonData.data"
onParsed="ctrl.onParsed"
></csv-input>
</div>
<div class="grafana-info-box">
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.
<br/><br/>
<b>NOTE:</b> Changes to this data will only be reflected after a browser refresh.
</div>
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<InputOptions, InputQuery>(InputDatasource)
.setConfigEditor(InputConfigEditor)
.setQueryEditor(InputQueryEditor);
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[];
}
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