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:
@@ -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() {
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 });
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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={
|
||||
|
||||
@@ -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" />}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user