Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create plugin: Update data source templates #836

Merged
merged 4 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export function QueryEditor({ query, onChange, onRunQuery }: Props) {
const { upperLimit, lowerLimit, tickInterval } = query;

return (
<div className="gf-form">
<>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could potentially use the new Box component here, but it does not change appearance so don't think we need it.

<InlineField label="Lower Limit" labelWidth={16} tooltip="Random numbers lower limit">
<Input onChange={onLowerLimitChange} onBlur={onRunQuery} value={lowerLimit || ''} type="number" />
</InlineField>
Expand All @@ -89,7 +89,7 @@ export function QueryEditor({ query, onChange, onRunQuery }: Props) {
<InlineField label="Tick interval" labelWidth={16} tooltip="Server tick interval">
<Input onChange={onTickIntervalChange} onBlur={onRunQuery} value={tickInterval || ''} type="number" />
</InlineField>
</div>
<>
);
}
```
Expand Down
18 changes: 15 additions & 3 deletions packages/create-plugin/templates/backend/src/datasource.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DataSourceInstanceSettings, CoreApp } from '@grafana/data';
import { DataSourceWithBackend } from '@grafana/runtime';
import { DataSourceInstanceSettings, CoreApp, ScopedVars } from '@grafana/data';
import { DataSourceWithBackend, getTemplateSrv } from '@grafana/runtime';

import { MyQuery, MyDataSourceOptions, DEFAULT_QUERY } from './types';

Expand All @@ -9,6 +9,18 @@ export class DataSource extends DataSourceWithBackend<MyQuery, MyDataSourceOptio
}

getDefaultQuery(_: CoreApp): Partial<MyQuery> {
return DEFAULT_QUERY
return DEFAULT_QUERY;
}

applyTemplateVariables(query: MyQuery, scopedVars: ScopedVars): Record<string, any> {
return {
...query,
queryText: getTemplateSrv().replace(query.queryText, scopedVars),
};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding scoped variables...currently the ds template for plugin.json doesn't specify any query options. Should we skip passing the scopredVars variable to getTemplateSrv().replace?

}

filterQuery(query: MyQuery): boolean {
// if no query has been provided, prevent the query from being executed
return !!query.queryText;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@ import { InlineField, Input, SecretInput } from '@grafana/ui';
import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
import { MyDataSourceOptions, MySecureJsonData } from '../types';

interface Props extends DataSourcePluginOptionsEditorProps<MyDataSourceOptions> {}
interface Props extends DataSourcePluginOptionsEditorProps<MyDataSourceOptions, MySecureJsonData> {}

export function ConfigEditor(props: Props) {
const { onOptionsChange, options } = props;
const { jsonData, secureJsonFields, secureJsonData } = options;

const onPathChange = (event: ChangeEvent<HTMLInputElement>) => {
const jsonData = {
...options.jsonData,
path: event.target.value,
};
onOptionsChange({ ...options, jsonData });
onOptionsChange({
...options,
jsonData: {
...jsonData,
path: event.target.value,
},
});
};

// Secure field (only sent to the backend)
Expand All @@ -39,29 +43,29 @@ export function ConfigEditor(props: Props) {
});
};

const { jsonData, secureJsonFields } = options;
const secureJsonData = (options.secureJsonData || {}) as MySecureJsonData;

return (
<div className="gf-form-group">
<InlineField label="Path" labelWidth={12}>
<>
<InlineField label="Path" labelWidth={14} interactive tooltip={'Json field returned to frontend'}>
Copy link
Contributor Author

@sunker sunker Mar 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re label width: Opened a PR in Grafana to increase the width of the name field to 14. That way we at least give the plugin authors a chance to align field width across the entire page.

<Input
id="config-editor-path"
onChange={onPathChange}
value={jsonData.path || ''}
placeholder="json field returned to frontend"
value={jsonData.path}
placeholder="Enter the path, e.g. /api/v1"
width={40}
/>
</InlineField>
<InlineField label="API Key" labelWidth={12}>
<InlineField label="API Key" labelWidth={14} interactive tooltip={'Secure json field (backend only)'}>
<SecretInput
isConfigured={(secureJsonFields && secureJsonFields.apiKey) as boolean}
value={secureJsonData.apiKey || ''}
placeholder="secure json field (backend only)"
required
id="config-editor-api-key"
isConfigured={secureJsonFields.apiKey}
value={secureJsonData?.apiKey}
placeholder="Enter your API key"
width={40}
onReset={onResetAPIKey}
onChange={onAPIKeyChange}
/>
</InlineField>
</div>
</>
);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { ChangeEvent } from 'react';
import { InlineField, Input } from '@grafana/ui';
import { InlineField, Input, Stack } from '@grafana/ui';
import { QueryEditorProps } from '@grafana/data';
import { DataSource } from '../datasource';
import { MyDataSourceOptions, MyQuery } from '../types';
Expand All @@ -20,13 +20,26 @@ export function QueryEditor({ query, onChange, onRunQuery }: Props) {
const { queryText, constant } = query;

return (
<div className="gf-form">
<Stack gap={0}>
<InlineField label="Constant">
<Input onChange={onConstantChange} value={constant} width={8} type="number" step="0.1" />
<Input
id="query-editor-constant"
onChange={onConstantChange}
value={constant}
width={8}
type="number"
step="0.1"
/>
</InlineField>
<InlineField label="Query Text" labelWidth={16} tooltip="Not used yet">
<Input onChange={onQueryTextChange} value={queryText || ''} />
<Input
id="query-editor-query-text"
onChange={onQueryTextChange}
value={queryText || ''}
required
placeholder="Enter a query"
/>
</InlineField>
</div>
</Stack>
);
}
12 changes: 11 additions & 1 deletion packages/create-plugin/templates/datasource/src/datasource.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
CoreApp,
DataQueryRequest,
DataQueryResponse,
DataSourceApi,
Expand All @@ -7,13 +8,22 @@ import {
FieldType,
} from '@grafana/data';

import { MyQuery, MyDataSourceOptions } from './types';
import { MyQuery, MyDataSourceOptions, DEFAULT_QUERY } from './types';

export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
constructor(instanceSettings: DataSourceInstanceSettings<MyDataSourceOptions>) {
super(instanceSettings);
}

getDefaultQuery(_: CoreApp): Partial<MyQuery> {
return DEFAULT_QUERY;
}

filterQuery(query: MyQuery): boolean {
// if no query has been provided, prevent the query from being executed
return !!query.queryText;
}

async query(options: DataQueryRequest<MyQuery>): Promise<DataQueryResponse> {
const { range } = options;
const from = range!.from.valueOf();
Expand Down
Loading