Merge pull request #1725 from grafana/gareth/config-page-update
Update config page to follow best practices
This commit is contained in:
@@ -31,6 +31,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/css": "^11.1.3",
|
"@emotion/css": "^11.1.3",
|
||||||
"@grafana/data": "10.1.2",
|
"@grafana/data": "10.1.2",
|
||||||
|
"@grafana/experimental": "^1.7.4",
|
||||||
"@grafana/runtime": "10.1.2",
|
"@grafana/runtime": "10.1.2",
|
||||||
"@grafana/ui": "10.1.2",
|
"@grafana/ui": "10.1.2",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
|
|||||||
@@ -1,11 +1,32 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { getDataSourceSrv, config } from '@grafana/runtime';
|
import { getDataSourceSrv, config } from '@grafana/runtime';
|
||||||
import { DataSourcePluginOptionsEditorProps, DataSourceSettings, SelectableValue } from '@grafana/data';
|
import { DataSourcePluginOptionsEditorProps, DataSourceSettings, GrafanaTheme2, SelectableValue } from '@grafana/data';
|
||||||
import { Button, DataSourceHttpSettings, InlineFormLabel, LegacyForms, Select } from '@grafana/ui';
|
import {
|
||||||
|
Field,
|
||||||
|
Icon,
|
||||||
|
Input,
|
||||||
|
Label,
|
||||||
|
SecretInput,
|
||||||
|
SecureSocksProxySettings,
|
||||||
|
Select,
|
||||||
|
Switch,
|
||||||
|
Tooltip,
|
||||||
|
useStyles2,
|
||||||
|
} from '@grafana/ui';
|
||||||
import { ZabbixAuthType, ZabbixDSOptions, ZabbixSecureJSONData } from '../types';
|
import { ZabbixAuthType, ZabbixDSOptions, ZabbixSecureJSONData } from '../types';
|
||||||
import { gte } from 'semver';
|
import { gte } from 'semver';
|
||||||
|
import {
|
||||||
const { FormField, Switch } = LegacyForms;
|
Auth,
|
||||||
|
ConfigSection,
|
||||||
|
ConfigSubSection,
|
||||||
|
Stack,
|
||||||
|
convertLegacyAuthProps,
|
||||||
|
ConnectionSettings,
|
||||||
|
DataSourceDescription,
|
||||||
|
AdvancedHttpSettings,
|
||||||
|
} from '@grafana/experimental';
|
||||||
|
import { Divider } from './Divider';
|
||||||
|
import { css } from '@emotion/css';
|
||||||
|
|
||||||
const SUPPORTED_SQL_DS = ['mysql', 'postgres', 'influxdb'];
|
const SUPPORTED_SQL_DS = ['mysql', 'postgres', 'influxdb'];
|
||||||
|
|
||||||
@@ -16,6 +37,7 @@ const authOptions: Array<SelectableValue<ZabbixAuthType>> = [
|
|||||||
|
|
||||||
export type Props = DataSourcePluginOptionsEditorProps<ZabbixDSOptions, ZabbixSecureJSONData>;
|
export type Props = DataSourcePluginOptionsEditorProps<ZabbixDSOptions, ZabbixSecureJSONData>;
|
||||||
export const ConfigEditor = (props: Props) => {
|
export const ConfigEditor = (props: Props) => {
|
||||||
|
const styles = useStyles2(getStyles);
|
||||||
const { options, onOptionsChange } = props;
|
const { options, onOptionsChange } = props;
|
||||||
|
|
||||||
const [selectedDBDatasource, setSelectedDBDatasource] = useState(null);
|
const [selectedDBDatasource, setSelectedDBDatasource] = useState(null);
|
||||||
@@ -79,233 +101,300 @@ export const ConfigEditor = (props: Props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DataSourceHttpSettings
|
<DataSourceDescription
|
||||||
defaultUrl={'http://localhost/zabbix/api_jsonrpc.php'}
|
dataSourceName="Zabbix"
|
||||||
dataSourceConfig={options}
|
docsLink="https://grafana.com/docs/grafana/latest/datasources/loki/configure-loki-data-source/"
|
||||||
showAccessOptions={true}
|
hasRequiredFields={true}
|
||||||
onChange={onOptionsChange}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="gf-form-group">
|
<Divider />
|
||||||
<h3 className="page-heading">Zabbix API details</h3>
|
|
||||||
<div className="gf-form">
|
<ConnectionSettings
|
||||||
<InlineFormLabel width={7} tooltip="Token authentication available in Zabbix version 5.4 and higher.">
|
config={options}
|
||||||
Auth type
|
onChange={onOptionsChange}
|
||||||
</InlineFormLabel>
|
urlPlaceholder="http://localhost/zabbix/api_jsonrpc.php"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<Auth
|
||||||
|
{...convertLegacyAuthProps({
|
||||||
|
config: options,
|
||||||
|
onChange: onOptionsChange,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<ConfigSection title="Zabbix Connection">
|
||||||
|
<Field label="Auth type">
|
||||||
<Select
|
<Select
|
||||||
width={30}
|
width={40}
|
||||||
options={authOptions}
|
options={authOptions}
|
||||||
value={options.jsonData.authType}
|
value={options.jsonData.authType}
|
||||||
onChange={jsonDataSelectHandler('authType', options, onOptionsChange)}
|
onChange={jsonDataSelectHandler('authType', options, onOptionsChange)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</Field>
|
||||||
{options.jsonData?.authType === ZabbixAuthType.Token ? (
|
|
||||||
|
{options.jsonData?.authType === ZabbixAuthType.UserLogin && (
|
||||||
<>
|
<>
|
||||||
<div className="gf-form max-width-25">
|
<Field label="Username">
|
||||||
{options.secureJsonFields?.apiToken ? (
|
<Input
|
||||||
<>
|
width={40}
|
||||||
<FormField
|
placeholder="Username"
|
||||||
labelWidth={7}
|
|
||||||
inputWidth={15}
|
|
||||||
label="API token"
|
|
||||||
disabled={true}
|
|
||||||
value=""
|
|
||||||
placeholder="Configured"
|
|
||||||
/>
|
|
||||||
<Button onClick={resetSecureJsonField('apiToken', options, onOptionsChange)}>Reset</Button>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<FormField
|
|
||||||
labelWidth={7}
|
|
||||||
inputWidth={15}
|
|
||||||
label="API token"
|
|
||||||
type="password"
|
|
||||||
value={options.secureJsonData?.apiToken || ''}
|
|
||||||
onChange={secureJsonDataChangeHandler('apiToken', options, onOptionsChange)}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<div className="gf-form max-width-25">
|
|
||||||
<FormField
|
|
||||||
labelWidth={7}
|
|
||||||
inputWidth={15}
|
|
||||||
label="Username"
|
|
||||||
value={options.jsonData.username || ''}
|
value={options.jsonData.username || ''}
|
||||||
onChange={jsonDataChangeHandler('username', options, onOptionsChange)}
|
onChange={jsonDataChangeHandler('username', options, onOptionsChange)}
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</Field>
|
||||||
<div className="gf-form max-width-25">
|
<Field label="Password">
|
||||||
{options.secureJsonFields?.password ? (
|
<SecretInput
|
||||||
<>
|
width={40}
|
||||||
<FormField
|
placeholder="Password"
|
||||||
labelWidth={7}
|
isConfigured={options.secureJsonFields && options.secureJsonFields.password}
|
||||||
inputWidth={15}
|
onReset={() => resetSecureJsonField('password', options, onOptionsChange)}
|
||||||
label="Password"
|
onBlur={secureJsonDataChangeHandler('password', options, onOptionsChange)}
|
||||||
disabled={true}
|
/>
|
||||||
value=""
|
</Field>
|
||||||
placeholder="Configured"
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{options.jsonData?.authType === ZabbixAuthType.Token && (
|
||||||
|
<>
|
||||||
|
<Field label="API Token">
|
||||||
|
<SecretInput
|
||||||
|
width={40}
|
||||||
|
placeholder="API token"
|
||||||
|
isConfigured={options.secureJsonFields && options.secureJsonFields.apiToken}
|
||||||
|
onReset={() => resetSecureJsonField('apiToken', options, onOptionsChange)}
|
||||||
|
onBlur={secureJsonDataChangeHandler('apiToken', options, onOptionsChange)}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</ConfigSection>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<ConfigSection title="Additional settings" isCollapsible>
|
||||||
|
<AdvancedHttpSettings config={options} onChange={onOptionsChange} />
|
||||||
|
|
||||||
|
<div className={styles.space} />
|
||||||
|
|
||||||
|
<ConfigSubSection title="Zabbix API">
|
||||||
|
<Field
|
||||||
|
label={
|
||||||
|
<Label>
|
||||||
|
<Stack gap={0.5}>
|
||||||
|
<span>Cache TTL</span>
|
||||||
|
<Tooltip
|
||||||
|
content={
|
||||||
|
<span>
|
||||||
|
Zabbix data source caches metric names in memory. Specify how often data will be updated.
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Icon name="info-circle" size="sm" />
|
||||||
|
</Tooltip>
|
||||||
|
</Stack>
|
||||||
|
</Label>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
width={40}
|
||||||
|
value={options.jsonData.cacheTTL || ''}
|
||||||
|
placeholder="1h"
|
||||||
|
onChange={jsonDataChangeHandler('cacheTTL', options, onOptionsChange)}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
|
||||||
|
<Field
|
||||||
|
label={
|
||||||
|
<Label>
|
||||||
|
<Stack gap={0.5}>
|
||||||
|
<span>Timeout</span>
|
||||||
|
<Tooltip content={<span>Zabbix API connection timeout in seconds. Default is 30.</span>}>
|
||||||
|
<Icon name="info-circle" size="sm" />
|
||||||
|
</Tooltip>
|
||||||
|
</Stack>
|
||||||
|
</Label>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
width={40}
|
||||||
|
type="number"
|
||||||
|
value={options.jsonData.timeout}
|
||||||
|
placeholder="30"
|
||||||
|
onChange={(event) => {
|
||||||
|
onOptionsChange({
|
||||||
|
...options,
|
||||||
|
jsonData: { ...options.jsonData, timeout: parseInt(event.currentTarget.value, 10) },
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
</ConfigSubSection>
|
||||||
|
|
||||||
|
<ConfigSubSection title="Trends">
|
||||||
|
<Field label="Enable Trends">
|
||||||
|
<Switch
|
||||||
|
value={options.jsonData.trends}
|
||||||
|
onChange={jsonDataSwitchHandler('trends', options, onOptionsChange)}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
|
||||||
|
{options.jsonData.trends && (
|
||||||
|
<>
|
||||||
|
<Field
|
||||||
|
label={
|
||||||
|
<Label>
|
||||||
|
<Stack gap={0.5}>
|
||||||
|
<span>After</span>
|
||||||
|
<Tooltip
|
||||||
|
content={
|
||||||
|
<span>
|
||||||
|
Time after which trends will be used. Best practice is to set this value to your history
|
||||||
|
storage period (7d, 30d, etc).
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Icon name="info-circle" size="sm" />
|
||||||
|
</Tooltip>
|
||||||
|
</Stack>
|
||||||
|
</Label>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
width={40}
|
||||||
|
placeholder="7d"
|
||||||
|
value={options.jsonData.trendsFrom || ''}
|
||||||
|
onChange={jsonDataChangeHandler('trendsFrom', options, onOptionsChange)}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
<Field
|
||||||
|
label={
|
||||||
|
<Label>
|
||||||
|
<Stack gap={0.5}>
|
||||||
|
<span>Range</span>
|
||||||
|
<Tooltip
|
||||||
|
content={
|
||||||
|
<span>
|
||||||
|
Time range width after which trends will be used instead of history. It&aposs better to set
|
||||||
|
this value in range of 4 to 7 days to prevent loading large amount of history data.
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Icon name="info-circle" size="sm" />
|
||||||
|
</Tooltip>
|
||||||
|
</Stack>
|
||||||
|
</Label>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
width={40}
|
||||||
|
placeholder="4d"
|
||||||
|
value={options.jsonData.trendsRange || ''}
|
||||||
|
onChange={jsonDataChangeHandler('trendsRange', options, onOptionsChange)}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</ConfigSubSection>
|
||||||
|
|
||||||
|
<ConfigSubSection title="Direct DB Connection">
|
||||||
|
<Field label="Enable Direct DB Connection">
|
||||||
|
<Switch
|
||||||
|
value={options.jsonData.dbConnectionEnable}
|
||||||
|
onChange={jsonDataSwitchHandler('dbConnectionEnable', options, onOptionsChange)}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
|
||||||
|
{options.jsonData.dbConnectionEnable && (
|
||||||
|
<>
|
||||||
|
<Field label="Data Source">
|
||||||
|
<Select
|
||||||
|
width={40}
|
||||||
|
value={selectedDBDatasource}
|
||||||
|
options={getDirectDBDSOptions()}
|
||||||
|
onChange={directDBDatasourceChanegeHandler(
|
||||||
|
options,
|
||||||
|
onOptionsChange,
|
||||||
|
setSelectedDBDatasource,
|
||||||
|
setCurrentDSType
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
|
||||||
|
{currentDSType === 'influxdb' && (
|
||||||
|
<Field label="Retention Policy">
|
||||||
|
<Input
|
||||||
|
width={40}
|
||||||
|
value={options.jsonData.dbConnectionRetentionPolicy || ''}
|
||||||
|
placeholder="Retention policy name"
|
||||||
|
onChange={jsonDataChangeHandler('dbConnectionRetentionPolicy', options, onOptionsChange)}
|
||||||
|
// tooltip="Specify retention policy name for fetching long-term stored data (optional).
|
||||||
|
// Leave it blank if only default retention policy used."
|
||||||
/>
|
/>
|
||||||
<Button onClick={resetSecureJsonField('password', options, onOptionsChange)}>Reset</Button>
|
</Field>
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<FormField
|
|
||||||
labelWidth={7}
|
|
||||||
inputWidth={15}
|
|
||||||
label="Password"
|
|
||||||
type="password"
|
|
||||||
value={options.secureJsonData?.password || options.jsonData.password || ''}
|
|
||||||
onChange={secureJsonDataChangeHandler('password', options, onOptionsChange)}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</>
|
||||||
</>
|
)}
|
||||||
)}
|
</ConfigSubSection>
|
||||||
<Switch
|
|
||||||
label="Trends"
|
|
||||||
labelClass="width-7"
|
|
||||||
checked={options.jsonData.trends}
|
|
||||||
onChange={jsonDataSwitchHandler('trends', options, onOptionsChange)}
|
|
||||||
/>
|
|
||||||
{options.jsonData.trends && (
|
|
||||||
<>
|
|
||||||
<div className="gf-form">
|
|
||||||
<FormField
|
|
||||||
labelWidth={7}
|
|
||||||
inputWidth={4}
|
|
||||||
label="After"
|
|
||||||
value={options.jsonData.trendsFrom || ''}
|
|
||||||
placeholder="7d"
|
|
||||||
onChange={jsonDataChangeHandler('trendsFrom', options, onOptionsChange)}
|
|
||||||
tooltip="Time after which trends will be used.
|
|
||||||
Best practice is to set this value to your history storage period (7d, 30d, etc)."
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="gf-form">
|
|
||||||
<FormField
|
|
||||||
labelWidth={7}
|
|
||||||
inputWidth={4}
|
|
||||||
label="Range"
|
|
||||||
value={options.jsonData.trendsRange || ''}
|
|
||||||
placeholder="4d"
|
|
||||||
onChange={jsonDataChangeHandler('trendsRange', options, onOptionsChange)}
|
|
||||||
tooltip="Time range width after which trends will be used instead of history.
|
|
||||||
It's better to set this value in range of 4 to 7 days to prevent loading large amount of history data."
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<div className="gf-form">
|
|
||||||
<FormField
|
|
||||||
labelWidth={7}
|
|
||||||
inputWidth={4}
|
|
||||||
label="Cache TTL"
|
|
||||||
value={options.jsonData.cacheTTL || ''}
|
|
||||||
placeholder="1h"
|
|
||||||
onChange={jsonDataChangeHandler('cacheTTL', options, onOptionsChange)}
|
|
||||||
tooltip="Zabbix data source caches metric names in memory. Specify how often data will be updated."
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="gf-form">
|
|
||||||
<FormField
|
|
||||||
labelWidth={7}
|
|
||||||
inputWidth={4}
|
|
||||||
type="number"
|
|
||||||
label="Timeout"
|
|
||||||
value={options.jsonData.timeout}
|
|
||||||
onChange={(event) => {
|
|
||||||
onOptionsChange({
|
|
||||||
...options,
|
|
||||||
jsonData: { ...options.jsonData, timeout: parseInt(event.currentTarget.value, 10) },
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
tooltip="Zabbix API connection timeout in seconds. Default is 30."
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="gf-form-group">
|
<ConfigSubSection title="Other">
|
||||||
<h3 className="page-heading">Direct DB Connection</h3>
|
<Field label="Disable acknowledges for read-only users">
|
||||||
<Switch
|
<Switch
|
||||||
label="Enable"
|
label="Disable acknowledges for read-only users"
|
||||||
labelClass="width-9"
|
value={options.jsonData.disableReadOnlyUsersAck}
|
||||||
checked={options.jsonData.dbConnectionEnable}
|
onChange={jsonDataSwitchHandler('disableReadOnlyUsersAck', options, onOptionsChange)}
|
||||||
onChange={jsonDataSwitchHandler('dbConnectionEnable', options, onOptionsChange)}
|
/>
|
||||||
/>
|
</Field>
|
||||||
{options.jsonData.dbConnectionEnable && (
|
|
||||||
<>
|
<Field
|
||||||
<div className="gf-form">
|
label={
|
||||||
<InlineFormLabel width={9}>Data Source</InlineFormLabel>
|
<Label>
|
||||||
<Select
|
<Stack gap={0.5}>
|
||||||
width={32}
|
<span>Disable data alignment</span>
|
||||||
options={getDirectDBDSOptions()}
|
<Tooltip
|
||||||
value={selectedDBDatasource}
|
content={
|
||||||
onChange={directDBDatasourceChanegeHandler(
|
<span>
|
||||||
options,
|
Data alignment feature aligns points based on item update interval. For instance, if value
|
||||||
onOptionsChange,
|
collected once per minute, then timestamp of the each point will be set to the start of
|
||||||
setSelectedDBDatasource,
|
corresponding minute. This alignment required for proper work of the stacked graphs. If you
|
||||||
setCurrentDSType
|
don't need stacked graphs and want to get exactly the same timestamps as in Zabbix, then
|
||||||
)}
|
you can disable this feature.
|
||||||
/>
|
</span>
|
||||||
</div>
|
}
|
||||||
{currentDSType === 'influxdb' && (
|
>
|
||||||
<div className="gf-form">
|
<Icon name="info-circle" size="sm" />
|
||||||
<FormField
|
</Tooltip>
|
||||||
labelWidth={9}
|
</Stack>
|
||||||
inputWidth={16}
|
</Label>
|
||||||
label="Retention Policy"
|
}
|
||||||
value={options.jsonData.dbConnectionRetentionPolicy || ''}
|
>
|
||||||
placeholder="Retention policy name"
|
<Switch
|
||||||
onChange={jsonDataChangeHandler('dbConnectionRetentionPolicy', options, onOptionsChange)}
|
value={!!options.jsonData.disableDataAlignment}
|
||||||
tooltip="Specify retention policy name for fetching long-term stored data (optional).
|
onChange={jsonDataSwitchHandler('disableDataAlignment', options, onOptionsChange)}
|
||||||
Leave it blank if only default retention policy used."
|
/>
|
||||||
/>
|
</Field>
|
||||||
</div>
|
</ConfigSubSection>
|
||||||
)}
|
|
||||||
</>
|
{config.secureSocksDSProxyEnabled && gte(config.buildInfo.version, '10.0.0-0') && (
|
||||||
|
<SecureSocksProxySettings options={options} onOptionsChange={onOptionsChange} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</ConfigSection>
|
||||||
|
|
||||||
<div className="gf-form-group">
|
|
||||||
<h3 className="page-heading">Other</h3>
|
|
||||||
<Switch
|
|
||||||
label="Disable acknowledges for read-only users"
|
|
||||||
labelClass="width-20"
|
|
||||||
checked={options.jsonData.disableReadOnlyUsersAck}
|
|
||||||
onChange={jsonDataSwitchHandler('disableReadOnlyUsersAck', options, onOptionsChange)}
|
|
||||||
/>
|
|
||||||
<Switch
|
|
||||||
label="Disable data alignment"
|
|
||||||
labelClass="width-20"
|
|
||||||
checked={!!options.jsonData.disableDataAlignment}
|
|
||||||
onChange={jsonDataSwitchHandler('disableDataAlignment', options, onOptionsChange)}
|
|
||||||
tooltip="Data alignment feature aligns points based on item update interval.
|
|
||||||
For instance, if value collected once per minute, then timestamp of the each point will be set to the start of corresponding minute.
|
|
||||||
This alignment required for proper work of the stacked graphs.
|
|
||||||
If you don't need stacked graphs and want to get exactly the same timestamps as in Zabbix, then you can disable this feature."
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{config.featureToggles['secureSocksDSProxyEnabled'] && gte(config.buildInfo.version, '10.0.0-0') && (
|
|
||||||
<div className="gf-form-group">
|
|
||||||
<Switch
|
|
||||||
label="Secure Socks Proxy"
|
|
||||||
labelClass="width-20"
|
|
||||||
checked={options.jsonData.enableSecureSocksProxy}
|
|
||||||
tooltip="Enable proxying the datasource connection through the secure socks proxy to a different network."
|
|
||||||
onChange={jsonDataSwitchHandler('enableSecureSocksProxy', options, onOptionsChange)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getStyles = (theme: GrafanaTheme2) => {
|
||||||
|
return {
|
||||||
|
space: css({
|
||||||
|
width: '100%',
|
||||||
|
height: theme.spacing(2),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const jsonDataChangeHandler =
|
const jsonDataChangeHandler =
|
||||||
(
|
(
|
||||||
key: keyof ZabbixDSOptions,
|
key: keyof ZabbixDSOptions,
|
||||||
|
|||||||
21
src/datasource/components/Divider.tsx
Normal file
21
src/datasource/components/Divider.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { css } from '@emotion/css';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
import { useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
|
// this custom component is necessary because the Grafana UI <Divider /> component is not backwards compatible with Grafana < 10.1.0
|
||||||
|
export const Divider = () => {
|
||||||
|
const styles = useStyles2(getStyles);
|
||||||
|
return <hr className={styles.horizontalDivider} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStyles = (theme: GrafanaTheme2) => {
|
||||||
|
return {
|
||||||
|
horizontalDivider: css({
|
||||||
|
borderTop: `1px solid ${theme.colors.border.weak}`,
|
||||||
|
margin: theme.spacing(2, 0),
|
||||||
|
width: '100%',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
};
|
||||||
19
yarn.lock
19
yarn.lock
@@ -897,6 +897,15 @@
|
|||||||
eslint-plugin-react-hooks "4.6.0"
|
eslint-plugin-react-hooks "4.6.0"
|
||||||
typescript "4.8.4"
|
typescript "4.8.4"
|
||||||
|
|
||||||
|
"@grafana/experimental@^1.7.4":
|
||||||
|
version "1.7.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@grafana/experimental/-/experimental-1.7.4.tgz#5b5efe89abf38b1d3358251148d42b9111de539e"
|
||||||
|
integrity sha512-uYkv9HRx+cqJRktsY43ApG0+kgG4fNR8lv+bkaFvGyCg46dcTeNqokujoPnHp6lt9MEn+0Y3jKEQbvCXjcz2bA==
|
||||||
|
dependencies:
|
||||||
|
"@types/uuid" "^8.3.3"
|
||||||
|
semver "^7.5.4"
|
||||||
|
uuid "^8.3.2"
|
||||||
|
|
||||||
"@grafana/faro-core@^1.1.0":
|
"@grafana/faro-core@^1.1.0":
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/@grafana/faro-core/-/faro-core-1.2.1.tgz#a95fd1376a928917f855068f101d356db067a0f4"
|
resolved "https://registry.yarnpkg.com/@grafana/faro-core/-/faro-core-1.2.1.tgz#a95fd1376a928917f855068f101d356db067a0f4"
|
||||||
@@ -2267,6 +2276,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.3.tgz#3d06b6769518450871fbc40770b7586334bdfd90"
|
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.3.tgz#3d06b6769518450871fbc40770b7586334bdfd90"
|
||||||
integrity sha512-THo502dA5PzG/sfQH+42Lw3fvmYkceefOspdCwpHRul8ik2Jv1K8I5OZz1AT3/rs46kwgMCe9bSBmDLYkkOMGg==
|
integrity sha512-THo502dA5PzG/sfQH+42Lw3fvmYkceefOspdCwpHRul8ik2Jv1K8I5OZz1AT3/rs46kwgMCe9bSBmDLYkkOMGg==
|
||||||
|
|
||||||
|
"@types/uuid@^8.3.3":
|
||||||
|
version "8.3.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc"
|
||||||
|
integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==
|
||||||
|
|
||||||
"@types/yargs-parser@*":
|
"@types/yargs-parser@*":
|
||||||
version "21.0.0"
|
version "21.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b"
|
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b"
|
||||||
@@ -8838,6 +8852,11 @@ uuid@9.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5"
|
||||||
integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==
|
integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==
|
||||||
|
|
||||||
|
uuid@^8.3.2:
|
||||||
|
version "8.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||||
|
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||||
|
|
||||||
v8-compile-cache-lib@^3.0.1:
|
v8-compile-cache-lib@^3.0.1:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
|
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
|
||||||
|
|||||||
Reference in New Issue
Block a user