chore: bump @grafana/create-plugin configuration to 6.7.1 (#2167)

Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com>
This commit is contained in:
ismail simsek
2026-01-08 15:56:29 +01:00
committed by GitHub
parent da27b9a917
commit 1bb5e8a5dd
24 changed files with 3500 additions and 3670 deletions

View File

@@ -45,7 +45,7 @@ export class ModalController extends React.Component<Props, State> {
});
};
renderModal() {
renderModal(): React.ReactNode {
const { component, props } = this.state;
if (!component) {
return null;
@@ -53,7 +53,7 @@ export class ModalController extends React.Component<Props, State> {
this.modalRoot.appendChild(this.modalNode);
const modal = React.createElement(provideTheme(component), props);
return ReactDOM.createPortal(modal, this.modalNode);
return ReactDOM.createPortal(modal, this.modalNode) as React.ReactNode;
}
render() {

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useMemo } from 'react';
import { getDataSourceSrv, config } from '@grafana/runtime';
import { DataSourcePluginOptionsEditorProps, DataSourceSettings, GrafanaTheme2, SelectableValue } from '@grafana/data';
import {
@@ -42,8 +42,19 @@ export const ConfigEditor = (props: Props) => {
const styles = useStyles2(getStyles);
const { options, onOptionsChange } = props;
const [selectedDBDatasource, setSelectedDBDatasource] = useState(null);
const [currentDSType, setCurrentDSType] = useState('');
// Derive selectedDBDatasource and currentDSType from options
const { selectedDBDatasource, currentDSType } = useMemo(() => {
if (!options.jsonData.dbConnectionEnable || !options.jsonData.dbConnectionDatasourceId) {
return { selectedDBDatasource: null, currentDSType: '' };
}
const selectedDs = getDirectDBDatasources().find(
(dsOption) => dsOption.id === options.jsonData.dbConnectionDatasourceId
);
return {
selectedDBDatasource: selectedDs ? { label: selectedDs.name, value: selectedDs.id } : null,
currentDSType: selectedDs?.type || '',
};
}, [options.jsonData.dbConnectionEnable, options.jsonData.dbConnectionDatasourceId]);
// Apply some defaults on initial render
useEffect(() => {
@@ -73,32 +84,22 @@ export const ConfigEditor = (props: Props) => {
secureJsonData: { ...newSecureJsonData },
});
if (options.jsonData.dbConnectionEnable) {
if (!options.jsonData.dbConnectionDatasourceId) {
const dsName = options.jsonData.dbConnectionDatasourceName;
getDataSourceSrv()
.get(dsName)
.then((ds) => {
if (ds) {
const selectedDs = getDirectDBDatasources().find((dsOption) => dsOption.id === ds.id);
setSelectedDBDatasource({ label: selectedDs?.name, value: selectedDs?.id });
setCurrentDSType(selectedDs?.type);
onOptionsChange({
...options,
jsonData: {
...options.jsonData,
dbConnectionDatasourceId: ds.id,
},
});
}
});
} else {
const selectedDs = getDirectDBDatasources().find(
(dsOption) => dsOption.id === options.jsonData.dbConnectionDatasourceId
);
setSelectedDBDatasource({ label: selectedDs?.name, value: selectedDs?.id });
setCurrentDSType(selectedDs?.type);
}
// Handle async lookup when dbConnectionDatasourceId is not set but name is available
if (options.jsonData.dbConnectionEnable && !options.jsonData.dbConnectionDatasourceId) {
const dsName = options.jsonData.dbConnectionDatasourceName;
getDataSourceSrv()
.get(dsName)
.then((ds) => {
if (ds) {
onOptionsChange({
...options,
jsonData: {
...options.jsonData,
dbConnectionDatasourceId: ds.id,
},
});
}
});
}
}, []);
@@ -318,12 +319,7 @@ export const ConfigEditor = (props: Props) => {
width={40}
value={selectedDBDatasource}
options={getDirectDBDSOptions()}
onChange={directDBDatasourceChanegeHandler(
options,
onOptionsChange,
setSelectedDBDatasource,
setCurrentDSType
)}
onChange={directDBDatasourceChanegeHandler(options, onOptionsChange)}
placeholder="Select a DB datasource (MySQL, PostgreSQL, InfluxDB)"
/>
</Field>
@@ -480,16 +476,8 @@ const resetSecureJsonField =
};
const directDBDatasourceChanegeHandler =
(
options: DataSourceSettings<ZabbixDSOptions, ZabbixSecureJSONData>,
onChange: Props['onOptionsChange'],
setSelectedDS: React.Dispatch<any>,
setSelectedDSType: React.Dispatch<any>
) =>
(options: DataSourceSettings<ZabbixDSOptions, ZabbixSecureJSONData>, onChange: Props['onOptionsChange']) =>
(value: SelectableValue<number>) => {
const selectedDs = getDirectDBDatasources().find((dsOption) => dsOption.id === value.value);
setSelectedDS({ label: selectedDs.name, value: selectedDs.id });
setSelectedDSType(selectedDs.type);
onChange({
...options,
jsonData: {

View File

@@ -111,8 +111,11 @@ function getProblemsQueryDefaults(): Partial<ZabbixMetricsQuery> {
};
}
export interface ZabbixQueryEditorProps
extends QueryEditorProps<ZabbixDatasource, ZabbixMetricsQuery, ZabbixDSOptions> {}
export interface ZabbixQueryEditorProps extends QueryEditorProps<
ZabbixDatasource,
ZabbixMetricsQuery,
ZabbixDSOptions
> {}
export const QueryEditor = ({ query, datasource, onChange, onRunQuery, range }: ZabbixQueryEditorProps) => {
const [itemCount, setItemCount] = useState(0);

View File

@@ -14,10 +14,14 @@ export interface Props {
export const QueryFunctionsEditor = ({ query, onChange }: Props) => {
const onFuncParamChange = (func: MetricFunc, index: number, value: string) => {
func.params[index] = value;
const funcIndex = query.functions.findIndex((f) => f === func);
const functions = query.functions;
functions[funcIndex] = func;
const functions = query.functions.map((f) => {
if (f === func) {
const newParams = [...f.params];
newParams[index] = value;
return { ...f, params: newParams };
}
return f;
});
onChange({ ...query, functions });
};

View File

@@ -1,4 +1,4 @@
import { useEffect, useMemo, useState } from 'react';
import { useMemo } from 'react';
import { ScopedVars } from '@grafana/data';
import { ZabbixDatasource } from '../datasource';
import { ZabbixMetricsQuery } from '../types/query';
@@ -10,12 +10,10 @@ export const useInterpolatedQuery = (
query: ZabbixMetricsQuery,
scopedVars?: ScopedVars
): ZabbixMetricsQuery => {
const [interpolatedQuery, setInterpolatedQuery] = useState<ZabbixMetricsQuery>(query);
const resolvedScopedVars = useMemo(() => scopedVars ?? EMPTY_SCOPED_VARS, [scopedVars]);
const resolvedScopedVars = scopedVars ?? EMPTY_SCOPED_VARS;
useEffect(() => {
const replacedQuery = datasource.interpolateVariablesInQueries([query], resolvedScopedVars)[0];
setInterpolatedQuery(replacedQuery);
const interpolatedQuery = useMemo(() => {
return datasource.interpolateVariablesInQueries([query], resolvedScopedVars)[0];
}, [datasource, query, resolvedScopedVars]);
return interpolatedQuery;

View File

@@ -13,7 +13,6 @@ jest.mock(
// Provide a custom query implementation that resolves backend + frontend + db + annotations
// so tests relying on merged results receive expected data.
if (actual && actual.DataSourceWithBackend && actual.DataSourceWithBackend.prototype) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
actual.DataSourceWithBackend.prototype.query = function (request: any) {
const that: any = this;

View File

@@ -29,9 +29,7 @@ export const ProblemsPanel = (props: ProblemsPanelProps) => {
for (const dataFrame of data.series) {
try {
const values = dataFrame.fields[0].values;
if (values.toArray) {
problems.push(...values.toArray());
}
problems.push(...values);
} catch (error) {
console.log(error);
return [];
@@ -125,7 +123,8 @@ export const ProblemsPanel = (props: ProblemsPanelProps) => {
};
const addTagFilter = (tag: ZBXTag, datasource: DataSourceRef) => {
const targets = data.request?.targets!;
const originalTargets = data.request?.targets!;
const targets = _.cloneDeep(originalTargets);
let updated = false;
for (const target of targets) {
if (target.datasource?.uid === datasource?.uid || target.datasource === datasource) {
@@ -148,7 +147,8 @@ export const ProblemsPanel = (props: ProblemsPanelProps) => {
const removeTagFilter = (tag: ZBXTag, datasource: DataSourceRef) => {
const matchTag = (t: ZBXTag) => t.tag === tag.tag && t.value === tag.value;
const targets = data.request?.targets!;
const originalTargets = data.request?.targets!;
const targets = _.cloneDeep(originalTargets);
let updated = false;
for (const target of targets) {
if (target.datasource?.uid === datasource?.uid || target.datasource === datasource) {
@@ -170,8 +170,8 @@ export const ProblemsPanel = (props: ProblemsPanelProps) => {
const getProblemEvents = async (problem: ProblemDTO) => {
const triggerids = [problem.triggerid];
const timeFrom = Math.ceil(dateMath.parse(timeRange.from)!.unix());
const timeTo = Math.ceil(dateMath.parse(timeRange.to)!.unix());
const timeFrom = Math.ceil(dateMath.toDateTime(timeRange.from, {}).unix());
const timeTo = Math.ceil(dateMath.toDateTime(timeRange.to, {}).unix());
const ds: any = await getDataSourceSrv().get(problem.datasource);
return ds.zabbix.getEvents(triggerids, timeFrom, timeTo, [0, 1], PROBLEM_EVENTS_LIMIT);
};

View File

@@ -206,6 +206,7 @@ export class AckModalUnthemed extends PureComponent<Props, State> {
return (
<Modal
isOpen={true}
ariaLabel="Acknowledge problem"
onDismiss={this.dismiss}
className={styles.modal}
title={

View File

@@ -136,6 +136,7 @@ export class ExecScriptModalUnthemed extends PureComponent<Props, State> {
isOpen={true}
onDismiss={this.dismiss}
className={styles.modal}
ariaLabel="Execute script"
title={
<div className={styles.modalHeaderTitle}>
{this.state.loading ? <Spinner size={18} /> : <FAIcon icon="terminal" />}

View File

@@ -53,26 +53,22 @@ export const ProblemDetails = ({
const [show, setShow] = useState(false);
useEffect(() => {
if (showTimeline) {
fetchProblemEvents();
}
fetchProblemAlerts();
const fetchData = async () => {
const problem = original;
if (showTimeline) {
const eventsData = await getProblemEvents(problem);
setEvents(eventsData);
}
const alertsData = await getProblemAlerts(problem);
setAletrs(alertsData);
};
fetchData();
requestAnimationFrame(() => {
setShow(true);
});
}, []);
const fetchProblemEvents = async () => {
const problem = original;
const events = await getProblemEvents(problem);
setEvents(events);
};
const fetchProblemAlerts = async () => {
const problem = original;
const alerts = await getProblemAlerts(problem);
setAletrs(alerts);
};
}, [original, showTimeline, getProblemEvents, getProblemAlerts]);
const handleTagClick = (tag: ZBXTag, datasource: DataSourceRef | string, ctrlKey?: boolean, shiftKey?: boolean) => {
if (onTagClick) {

View File

@@ -1,17 +1,24 @@
import _ from 'lodash';
// eslint-disable-next-line no-restricted-imports
import moment from 'moment';
var units = ['y', 'M', 'w', 'd', 'h', 'm', 's'];
let units = ['y', 'M', 'w', 'd', 'h', 'm', 's'];
export function parse(text, roundUp) {
if (!text) { return undefined; }
if (moment.isMoment(text)) { return text; }
if (_.isDate(text)) { return moment(text); }
if (!text) {
return undefined;
}
if (moment.isMoment(text)) {
return text;
}
if (_.isDate(text)) {
return moment(text);
}
var time;
var mathString = '';
var index;
var parseString;
let time;
let mathString = '';
let index;
let parseString;
if (text.substring(0, 3) === 'now') {
time = moment();
@@ -37,7 +44,7 @@ export function parse(text, roundUp) {
}
export function isValid(text) {
var date = parse(text);
let date = parse(text);
if (!date) {
return false;
}
@@ -50,15 +57,15 @@ export function isValid(text) {
}
export function parseDateMath(mathString, time, roundUp) {
var dateTime = time;
var i = 0;
var len = mathString.length;
let dateTime = time;
let i = 0;
let len = mathString.length;
while (i < len) {
var c = mathString.charAt(i++);
var type;
var num;
var unit;
let c = mathString.charAt(i++);
let type;
let num;
let unit;
if (c === '/') {
type = 0;
@@ -75,10 +82,12 @@ export function parseDateMath(mathString, time, roundUp) {
} else if (mathString.length === 2) {
num = mathString.charAt(i);
} else {
var numFrom = i;
let numFrom = i;
while (!isNaN(mathString.charAt(i))) {
i++;
if (i > 10) { return undefined; }
if (i > 10) {
return undefined;
}
}
num = parseInt(mathString.substring(numFrom, i), 10);
}

View File

@@ -26,24 +26,19 @@ export class PanelCtrl {
this.timing = {};
this.events = {
on: () => {},
emit: () => {}
emit: () => {},
};
}
init() {
}
init() {}
renderingCompleted() {
}
renderingCompleted() {}
refresh() {
}
refresh() {}
publishAppEvent(evtName, evt) {
}
publishAppEvent(evtName, evt) {}
changeView(fullscreen, edit) {
}
changeView(fullscreen, edit) {}
viewPanel() {
this.changeView(true, false);
@@ -57,14 +52,11 @@ export class PanelCtrl {
this.changeView(false, false);
}
initEditMode() {
}
initEditMode() {}
changeTab(newIndex) {
}
changeTab(newIndex) {}
addEditorTab(title, directiveFn, index) {
}
addEditorTab(title, directiveFn, index) {}
getMenu() {
return [];
@@ -78,41 +70,29 @@ export class PanelCtrl {
return false;
}
calculatePanelHeight() {
}
calculatePanelHeight() {}
render(payload) {
}
render(payload) {}
toggleEditorHelp(index) {
}
toggleEditorHelp(index) {}
duplicate() {
}
duplicate() {}
updateColumnSpan(span) {
}
updateColumnSpan(span) {}
removePanel() {
}
removePanel() {}
editPanelJson() {
}
editPanelJson() {}
replacePanel(newPanel, oldPanel) {
}
replacePanel(newPanel, oldPanel) {}
sharePanel() {
}
sharePanel() {}
getInfoMode() {
}
getInfoMode() {}
getInfoContent(options) {
}
getInfoContent(options) {}
openInspector() {
}
openInspector() {}
}
export class MetricsPanelCtrl extends PanelCtrl {