Build plugin with grafana toolkit (#1539)
* Use grafana toolkit template for building plugin * Fix linter and type errors * Update styles building * Fix sass deprecation warning * Remove empty js files produced by webpack building sass * Fix signing script * Replace classnames with cx * Fix data source config page * Use custom webpack config instead of overriding original one * Use gpx_ prefix for plugin executable * Remove unused configs * Roll back react hooks dependencies usage * Move plugin-specific ts config to root config file * Temporary do not use rst2html for function description tooltip * Remove unused code * remove unused dependencies * update react table dependency * Migrate tests to typescript * remove unused dependencies * Remove old webpack configs * Add sign target to makefile * Add magefile * Update CI test job * Update go packages * Update build instructions * Downgrade go version to 1.18 * Fix go version in ci * Fix metric picker * Add comment to webpack config * remove angular mocks * update bra config * Rename datasource-zabbix to datasource (fix mage build) * Add instructions for building backend with mage * Fix webpack targets * Fix ci backend tests * Add initial e2e tests * Fix e2e ci tests * Update docker compose for cypress tests * build grafana docker image * Fix docker stop task * CI: add Grafana compatibility check
This commit is contained in:
232
src/datasource/components/QueryEditor/QueryOptionsEditor.tsx
Normal file
232
src/datasource/components/QueryEditor/QueryOptionsEditor.tsx
Normal file
@@ -0,0 +1,232 @@
|
||||
import { css } from '@emotion/css';
|
||||
import React, { useState, FormEvent } from 'react';
|
||||
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
|
||||
import {
|
||||
HorizontalGroup,
|
||||
Icon,
|
||||
InlineField,
|
||||
InlineFieldRow,
|
||||
InlineSwitch,
|
||||
Input,
|
||||
Select,
|
||||
useStyles2,
|
||||
} from '@grafana/ui';
|
||||
import * as c from '../../constants';
|
||||
import { ZabbixQueryOptions } from '../../types';
|
||||
|
||||
const ackOptions: Array<SelectableValue<number>> = [
|
||||
{ label: 'all triggers', value: 2 },
|
||||
{ label: 'unacknowledged', value: 0 },
|
||||
{ label: 'acknowledged', value: 1 },
|
||||
];
|
||||
|
||||
const sortOptions: Array<SelectableValue<string>> = [
|
||||
{ label: 'Default', value: 'default' },
|
||||
{ label: 'Last change', value: 'lastchange' },
|
||||
{ label: 'Severity', value: 'severity' },
|
||||
];
|
||||
|
||||
interface Props {
|
||||
queryType: string;
|
||||
queryOptions: ZabbixQueryOptions;
|
||||
onChange: (options: ZabbixQueryOptions) => void;
|
||||
}
|
||||
|
||||
export const QueryOptionsEditor = ({ queryType, queryOptions, onChange }: Props) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const onLimitChange = (v: FormEvent<HTMLInputElement>) => {
|
||||
const newValue = Number(v?.currentTarget?.value);
|
||||
if (newValue !== null) {
|
||||
onChange({ ...queryOptions, limit: newValue });
|
||||
}
|
||||
};
|
||||
|
||||
const onPropChange = (prop: string) => {
|
||||
return (option: SelectableValue) => {
|
||||
if (option.value !== null) {
|
||||
onChange({ ...queryOptions, [prop]: option.value });
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const renderClosed = () => {
|
||||
return (
|
||||
<>
|
||||
<HorizontalGroup>
|
||||
{!isOpen && <Icon name="angle-right" />}
|
||||
{isOpen && <Icon name="angle-down" />}
|
||||
<span className={styles.label}>Options</span>
|
||||
<div className={styles.options}>{renderOptions()}</div>
|
||||
</HorizontalGroup>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const renderOptions = () => {
|
||||
const elements: JSX.Element[] = [];
|
||||
for (const key in queryOptions) {
|
||||
if (queryOptions.hasOwnProperty(key)) {
|
||||
const value = queryOptions[key];
|
||||
if (value === true && value !== '' && value !== null && value !== undefined) {
|
||||
elements.push(<span className={styles.optionContainer} key={key}>{`${key} = ${value}`}</span>);
|
||||
}
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
};
|
||||
|
||||
const renderEditor = () => {
|
||||
return (
|
||||
<div className={styles.editorContainer}>
|
||||
{queryType === c.MODE_METRICS && renderMetricOptions()}
|
||||
{queryType === c.MODE_ITEMID && renderMetricOptions()}
|
||||
{queryType === c.MODE_ITSERVICE && renderMetricOptions()}
|
||||
{queryType === c.MODE_TEXT && renderTextMetricsOptions()}
|
||||
{queryType === c.MODE_PROBLEMS && renderProblemsOptions()}
|
||||
{queryType === c.MODE_TRIGGERS && renderTriggersOptions()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const renderMetricOptions = () => {
|
||||
return (
|
||||
<>
|
||||
<InlineField label="Show disabled items" labelWidth={24}>
|
||||
<InlineSwitch
|
||||
value={queryOptions.showDisabledItems}
|
||||
onChange={() => onChange({ ...queryOptions, showDisabledItems: !queryOptions.showDisabledItems })}
|
||||
/>
|
||||
</InlineField>
|
||||
<InlineField label="Use Zabbix value mapping" labelWidth={24}>
|
||||
<InlineSwitch
|
||||
value={queryOptions.useZabbixValueMapping}
|
||||
onChange={() => onChange({ ...queryOptions, useZabbixValueMapping: !queryOptions.useZabbixValueMapping })}
|
||||
/>
|
||||
</InlineField>
|
||||
<InlineField label="Disable data alignment" labelWidth={24}>
|
||||
<InlineSwitch
|
||||
value={queryOptions.disableDataAlignment}
|
||||
onChange={() => onChange({ ...queryOptions, disableDataAlignment: !queryOptions.disableDataAlignment })}
|
||||
/>
|
||||
</InlineField>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const renderTextMetricsOptions = () => {
|
||||
return (
|
||||
<>
|
||||
<InlineField label="Show disabled items" labelWidth={24}>
|
||||
<InlineSwitch
|
||||
value={queryOptions.showDisabledItems}
|
||||
onChange={() => onChange({ ...queryOptions, showDisabledItems: !queryOptions.showDisabledItems })}
|
||||
/>
|
||||
</InlineField>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const renderProblemsOptions = () => {
|
||||
return (
|
||||
<>
|
||||
<InlineField label="Acknowledged" labelWidth={24}>
|
||||
<Select
|
||||
isSearchable={false}
|
||||
width={24}
|
||||
value={queryOptions.acknowledged}
|
||||
options={ackOptions}
|
||||
onChange={onPropChange('acknowledged')}
|
||||
/>
|
||||
</InlineField>
|
||||
<InlineField label="Sort by" labelWidth={24}>
|
||||
<Select
|
||||
isSearchable={false}
|
||||
width={24}
|
||||
value={queryOptions.sortProblems}
|
||||
options={sortOptions}
|
||||
onChange={onPropChange('sortProblems')}
|
||||
/>
|
||||
</InlineField>
|
||||
<InlineField label="Use time range" labelWidth={24}>
|
||||
<InlineSwitch
|
||||
value={queryOptions.useTimeRange}
|
||||
onChange={() => onChange({ ...queryOptions, useTimeRange: !queryOptions.useTimeRange })}
|
||||
/>
|
||||
</InlineField>
|
||||
<InlineField label="Hosts in maintenance" labelWidth={24}>
|
||||
<InlineSwitch
|
||||
value={queryOptions.hostsInMaintenance}
|
||||
onChange={() => onChange({ ...queryOptions, hostsInMaintenance: !queryOptions.hostsInMaintenance })}
|
||||
/>
|
||||
</InlineField>
|
||||
<InlineField label="Host proxy" labelWidth={24}>
|
||||
<InlineSwitch
|
||||
value={queryOptions.hostProxy}
|
||||
onChange={() => onChange({ ...queryOptions, hostProxy: !queryOptions.hostProxy })}
|
||||
/>
|
||||
</InlineField>
|
||||
<InlineField label="Limit" labelWidth={24}>
|
||||
<Input width={12} type="number" defaultValue={queryOptions.limit} onBlur={onLimitChange} />
|
||||
</InlineField>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const renderTriggersOptions = () => {
|
||||
return (
|
||||
<>
|
||||
<InlineField label="Acknowledged" labelWidth={24}>
|
||||
<Select
|
||||
isSearchable={false}
|
||||
width={24}
|
||||
value={queryOptions.acknowledged}
|
||||
options={ackOptions}
|
||||
onChange={onPropChange('acknowledged')}
|
||||
/>
|
||||
</InlineField>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<InlineFieldRow>
|
||||
<div className={styles.container} onClick={() => setIsOpen(!isOpen)}>
|
||||
{renderClosed()}
|
||||
</div>
|
||||
</InlineFieldRow>
|
||||
<InlineFieldRow>{isOpen && renderEditor()}</InlineFieldRow>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => ({
|
||||
container: css({
|
||||
backgroundColor: theme.colors.background.secondary,
|
||||
borderRadius: theme.shape.borderRadius(),
|
||||
marginRight: theme.spacing(0.5),
|
||||
marginBottom: theme.spacing(0.5),
|
||||
padding: `0 ${theme.spacing(1)}`,
|
||||
height: `${theme.v1.spacing.formInputHeight}px`,
|
||||
width: `100%`,
|
||||
}),
|
||||
label: css({
|
||||
color: theme.colors.info.text,
|
||||
fontWeight: theme.typography.fontWeightMedium,
|
||||
cursor: 'pointer',
|
||||
}),
|
||||
options: css({
|
||||
color: theme.colors.text.disabled,
|
||||
fontSize: theme.typography.bodySmall.fontSize,
|
||||
}),
|
||||
optionContainer: css`
|
||||
margin-right: ${theme.spacing(2)};
|
||||
`,
|
||||
editorContainer: css`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: ${theme.spacing(4)};
|
||||
`,
|
||||
});
|
||||
Reference in New Issue
Block a user