Files
grafana-zabbix/src/datasource/components/QueryEditor/UserMacrosQueryEditor.tsx
Jocelyn Collado-Kuri ce4a8d3e19 Migrate from DatasourceAPI to DatasourceWithBackend (#2123)
This PR migrates the use of `DatasourceApi` to `DatasourceWithBackend`,
with this a couple additional improvements were made:

1. Migrate to use `interpolateVariablesInQuery` everywhere instead of
the custom `replaceTemplateVariables` we were using
2. Moves util functions out of `datasource.ts` and into the existing
`utils.ts`

<img width="1261" height="406" alt="Screenshot 2025-11-20 at 11 37
56 AM"
src="https://github.com/user-attachments/assets/9e396cf2-eab0-49d1-958c-963a2e896eba"
/>

Now we can see the `query` calls being made to the backend:
<img width="367" height="102" alt="Screenshot 2025-11-20 at 11 38 18 AM"
src="https://github.com/user-attachments/assets/a5a9a337-7f19-4f7c-9d04-9d30c0216fb2"
/>

Tested:
- By running queries from Explore and Dashboards (with and without
variables)
- By interacting with all the different Editors to make sure `ComboBox`
was working as expected


Next:
Once this is merged, we will next be able to slowly move away from using
the `ZabbixConnector` to make backend datasource calls.

Fixes:
[#131](https://github.com/orgs/grafana/projects/457/views/40?pane=issue&itemId=139450234&issue=grafana%7Coss-big-tent-squad%7C131)
2025-12-16 09:58:02 -08:00

131 lines
4.1 KiB
TypeScript

import _ from 'lodash';
import React, { useEffect } from 'react';
import { useAsyncFn } from 'react-use';
import { SelectableValue } from '@grafana/data';
import { InlineField } from '@grafana/ui';
import { QueryEditorRow } from './QueryEditorRow';
import { MetricPicker } from '../../../components';
import { getVariableOptions } from './utils';
import { ZabbixDatasource } from '../../datasource';
import { ZabbixMetricsQuery } from '../../types/query';
import { useInterpolatedQuery } from '../../hooks/useInterpolatedQuery';
export interface Props {
query: ZabbixMetricsQuery;
datasource: ZabbixDatasource;
onChange: (query: ZabbixMetricsQuery) => void;
}
export const UserMacrosQueryEditor = ({ query, datasource, onChange }: Props) => {
const interpolatedQuery = useInterpolatedQuery(datasource, query);
const loadGroupOptions = async () => {
const groups = await datasource.zabbix.getAllGroups();
const options = groups?.map((group) => ({
value: group.name,
label: group.name,
}));
options.unshift(...getVariableOptions());
return options;
};
const [{ loading: groupsLoading, value: groupsOptions }, fetchGroups] = useAsyncFn(async () => {
const options = await loadGroupOptions();
return options;
}, []);
const loadHostOptions = async (group: string) => {
const hosts = await datasource.zabbix.getAllHosts(group);
let options: Array<SelectableValue<string>> = hosts?.map((host) => ({
value: host.name,
label: host.name,
}));
options = _.uniqBy(options, (o) => o.value);
options.unshift({ value: '/.*/' });
options.unshift(...getVariableOptions());
return options;
};
const [{ loading: hostsLoading, value: hostOptions }, fetchHosts] = useAsyncFn(async () => {
const options = await loadHostOptions(interpolatedQuery.group.filter);
return options;
}, [interpolatedQuery.group.filter]);
const loadMacrosOptions = async (group: string, host: string) => {
const macros = await datasource.zabbix.getAllMacros(group, host);
let options: Array<SelectableValue<string>> = macros?.map((m) => ({
value: m.macro,
label: m.macro,
}));
options = _.uniqBy(options, (o) => o.value);
options.unshift({ value: '/.*/' });
options.unshift(...getVariableOptions());
return options;
};
const [{ loading: macrosLoading, value: macrosOptions }, fetchmacros] = useAsyncFn(async () => {
const options = await loadMacrosOptions(interpolatedQuery.group.filter, interpolatedQuery.host.filter);
return options;
}, [interpolatedQuery.group.filter, interpolatedQuery.host.filter]);
// Update suggestions on every metric change
const groupFilter = interpolatedQuery.group?.filter;
const hostFilter = interpolatedQuery.host?.filter;
useEffect(() => {
fetchGroups();
}, []);
useEffect(() => {
fetchHosts();
}, [groupFilter]);
useEffect(() => {
fetchmacros();
}, [groupFilter, hostFilter]);
const onFilterChange = (prop: string) => {
return (value: string) => {
if (value !== null) {
onChange({ ...query, [prop]: { filter: value } });
}
};
};
return (
<>
<QueryEditorRow>
<InlineField label="Group" labelWidth={12}>
<MetricPicker
width={24}
value={query.group.filter}
options={groupsOptions}
isLoading={groupsLoading}
onChange={onFilterChange('group')}
/>
</InlineField>
<InlineField label="Host" labelWidth={12}>
<MetricPicker
width={24}
value={query.host.filter}
options={hostOptions}
isLoading={hostsLoading}
onChange={onFilterChange('host')}
/>
</InlineField>
</QueryEditorRow>
<QueryEditorRow>
<InlineField label="Macros" labelWidth={12}>
<MetricPicker
width={24}
value={query.macro.filter}
options={macrosOptions}
isLoading={macrosLoading}
onChange={onFilterChange('macro')}
/>
</InlineField>
</QueryEditorRow>
</>
);
};