mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Input Datasource: convert from angular config to react ConfigEditor (#16856)
* use ConfigEditor * use ConfigEditor * update readme * make the jsondata generic
This commit is contained in:
committed by
Torkel Ödegaard
parent
ece4d2201c
commit
0d02ceb452
@@ -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
|
||||
|
||||
|
||||
74
public/app/plugins/datasource/input/InputConfigEditor.tsx
Normal file
74
public/app/plugins/datasource/input/InputConfigEditor.tsx
Normal file
@@ -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<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>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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<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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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<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']);
|
||||
},
|
||||
]);
|
||||
@@ -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;
|
||||
@@ -1,16 +0,0 @@
|
||||
<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>
|
||||
@@ -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<InputOptions, InputQuery>(InputDatasource)
|
||||
.setConfigEditor(InputConfigEditor)
|
||||
.setQueryEditor(InputQueryEditor);
|
||||
|
||||
@@ -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[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user