Files
grafana-zabbix/src/datasource/components/QueryEditor/QueryOptionsEditor.tsx
2022-12-29 14:07:02 +01:00

248 lines
7.5 KiB
TypeScript

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' },
];
const trendsOptions: Array<SelectableValue<string>> = [
{ label: 'Default', value: 'default' },
{ label: 'True', value: 'true' },
{ label: 'False', value: 'false' },
];
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="Trends" labelWidth={24}>
<Select
isSearchable={false}
width={16}
value={queryOptions.useTrends}
options={trendsOptions}
onChange={onPropChange('useTrends')}
/>
</InlineField>
<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)};
`,
});