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

@@ -1,3 +1,4 @@
{
"version": "5.26.4"
"version": "6.7.1",
"features": {}
}

View File

@@ -1,30 +0,0 @@
/*
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
*
* In order to extend the configuration follow the steps in
* https://grafana.com/developers/plugin-tools/how-to-guides/extend-configurations#extend-the-eslint-config
*/
{
"extends": ["@grafana/eslint-config"],
"root": true,
"rules": {
"react/prop-types": "off"
},
"overrides": [
{
"files": ["src/**/*.{ts,tsx}"],
"rules": {
"@typescript-eslint/no-deprecated": "warn"
},
"parserOptions": {
"project": "./tsconfig.json"
}
},
{
"files": ["./tests/**/*"],
"rules": {
"react-hooks/rules-of-hooks": "off"
}
}
]
}

View File

@@ -0,0 +1,43 @@
import type { Configuration, ExternalItemFunctionData } from 'webpack';
type ExternalsType = Configuration['externals'];
export const externals: ExternalsType = [
// Required for dynamic publicPath resolution
{ 'amd-module': 'module' },
'lodash',
'jquery',
'moment',
'slate',
'emotion',
'@emotion/react',
'@emotion/css',
'prismjs',
'slate-plain-serializer',
'@grafana/slate-react',
'react',
'react-dom',
'react-redux',
'redux',
'rxjs',
'i18next',
'react-router',
'd3',
'angular',
/^@grafana\/ui/i,
/^@grafana\/runtime/i,
/^@grafana\/data/i,
// Mark legacy SDK imports as external if their name starts with the "grafana/" prefix
({ request }: ExternalItemFunctionData, callback: (error?: Error, result?: string) => void) => {
const prefix = 'grafana/';
const hasPrefix = (request: string) => request.indexOf(prefix) === 0;
const stripPrefix = (request: string) => request.slice(prefix.length);
if (request && hasPrefix(request)) {
return callback(undefined, stripPrefix(request));
}
callback();
},
];

View File

@@ -7,7 +7,7 @@ services:
context: .
args:
grafana_image: ${GRAFANA_IMAGE:-grafana-enterprise}
grafana_version: ${GRAFANA_VERSION:-12.1.1}
grafana_version: ${GRAFANA_VERSION:-12.2.0}
development: ${DEVELOPMENT:-false}
anonymous_auth_enabled: ${ANONYMOUS_AUTH_ENABLED:-true}
ports:

31
.config/eslint.config.mjs Normal file
View File

@@ -0,0 +1,31 @@
import { defineConfig } from 'eslint/config';
import grafanaConfig from '@grafana/eslint-config/flat.js';
export default defineConfig([
...grafanaConfig,
{
rules: {
'react/prop-types': 'off',
},
},
{
files: ['src/**/*.{ts,tsx}'],
languageOptions: {
parserOptions: {
project: './tsconfig.json',
},
},
rules: {
'@typescript-eslint/no-deprecated': 'warn',
},
},
{
files: ['./tests/**/*'],
rules: {
'react-hooks/rules-of-hooks': 'off',
},
},
]);

1
.config/types/setupTests.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
import '@testing-library/jest-dom';

View File

@@ -19,6 +19,7 @@ import VirtualModulesPlugin from 'webpack-virtual-modules';
import { BuildModeWebpackPlugin } from './BuildModeWebpackPlugin.ts';
import { DIST_DIR, SOURCE_DIR } from './constants.ts';
import { getCPConfigVersion, getEntries, getPackageJson, getPluginJson, hasReadme, isWSL } from './utils.ts';
import { externals } from '../bundler/externals.ts';
const pluginJson = getPluginJson();
const cpVersion = getCPConfigVersion();
@@ -55,45 +56,7 @@ const config = async (env: Env): Promise<Configuration> => {
entry: await getEntries(),
externals: [
// Required for dynamic publicPath resolution
{ 'amd-module': 'module' },
'lodash',
'jquery',
'moment',
'slate',
'emotion',
'@emotion/react',
'@emotion/css',
'prismjs',
'slate-plain-serializer',
'@grafana/slate-react',
'react',
'react-dom',
'react-redux',
'redux',
'rxjs',
'i18next',
'react-router',
'd3',
'angular',
/^@grafana\/ui/i,
/^@grafana\/runtime/i,
/^@grafana\/data/i,
// Mark legacy SDK imports as external if their name starts with the "grafana/" prefix
({ request }, callback) => {
const prefix = 'grafana/';
const hasPrefix = (request: string) => request.indexOf(prefix) === 0;
const stripPrefix = (request: string) => request.substr(prefix.length);
if (request && hasPrefix(request)) {
return callback(undefined, stripPrefix(request));
}
callback();
},
],
externals,
// Support WebAssembly according to latest spec - makes WebAssembly module async
experiments: {
@@ -224,7 +187,8 @@ const config = async (env: Env): Promise<Configuration> => {
new ReplaceInFileWebpackPlugin([
{
dir: DIST_DIR,
files: ['plugin.json', 'README.md'],
test: [/(^|\/)plugin\.json$/, /(^|\/)README\.md$/],
rules: [
{
search: /\%VERSION\%/g,

View File

@@ -1,9 +0,0 @@
{
"extends": "./.config/.eslintrc",
"plugins": ["prettier"],
"ignorePatterns": ["/src/test-setup/**/*"],
"rules": {
"react-hooks/exhaustive-deps": "off",
"prettier/prettier": "error"
}
}

View File

@@ -1,4 +1,4 @@
module.exports = {
// Prettier configuration provided by Grafana scaffolding
...require("./.config/.prettierrc.js")
...require('./.config/.prettierrc.js'),
};

60
eslint.config.mjs Normal file
View File

@@ -0,0 +1,60 @@
import { defineConfig } from 'eslint/config';
import baseConfig from './.config/eslint.config.mjs';
import prettier from 'eslint-plugin-prettier';
export default defineConfig([
{
ignores: [
'**/*.sublime-workspace',
'**/*.sublime-project',
'**/.idea/',
'**/.vscode',
'**/*.bat',
'**/.DS_Store',
'docs/site/',
'dist/test/',
'dist/test-setup/',
'**/vendor',
'src/vendor',
'src/vendor/npm',
'**/node_modules',
'**/coverage/',
'tmp',
'**/artifacts/',
'**/work/',
'**/test-results/',
'**/playwright-report/',
'**/blob-report/',
'playwright/.cache/',
'playwright/.auth/',
'**/npm-debug.log',
'**/yarn-error.log',
'**/dist/',
'**/ci/',
'**/alexanderzobnin-zabbix-app.zip',
'**/.eslintcache',
'public/css/*.min.css',
'**/provisioning/',
'devenv/nginx/nginx.crt',
'devenv/nginx/nginx.key',
'**/.pnp.*',
'.yarn/*',
'!.yarn/patches',
'!.yarn/plugins',
'!.yarn/releases',
'!.yarn/sdks',
'!.yarn/versions',
],
},
...baseConfig,
{
plugins: {
prettier: prettier,
},
rules: {
'react-hooks/exhaustive-deps': 'off',
'prettier/prettier': 'error',
},
},
]);

View File

@@ -16,7 +16,7 @@
"build": "webpack -c ./webpack.config.ts --env production",
"dev": "webpack -w -c ./webpack.config.ts --env development",
"e2e": "playwright test",
"lint": "eslint --cache --ignore-path ./.gitignore --ext .js,.jsx,.ts,.tsx .",
"lint": "eslint --cache .",
"lint:fix": "yarn run lint --fix && prettier --write --list-different .",
"server": "docker compose up --build",
"server:down": "docker compose --file ./devenv/default/docker-compose.yml down",
@@ -28,89 +28,84 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@emotion/css": "11.10.6",
"@grafana/data": "^12.1.0",
"@grafana/i18n": "^12.1.0",
"@grafana/plugin-ui": "^0.10.10",
"@grafana/runtime": "^12.1.0",
"@grafana/schema": "^12.1.0",
"@grafana/ui": "^12.1.0",
"@emotion/css": "11.13.5",
"@grafana/data": "12.3.1",
"@grafana/i18n": "12.3.1",
"@grafana/plugin-ui": "0.12.1",
"@grafana/runtime": "12.3.1",
"@grafana/schema": "12.3.1",
"@grafana/ui": "12.3.1",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-router-dom": "^6.22.0",
"react-use": "17.6.0",
"rxjs": "7.8.2",
"tslib": "2.5.3"
"tslib": "2.8.1"
},
"devDependencies": {
"@babel/core": "^7.28.4",
"@changesets/cli": "^2.29.7",
"@grafana/e2e-selectors": "12.1.0",
"@grafana/eslint-config": "^8.0.0",
"@grafana/plugin-e2e": "^2.2.3",
"@grafana/tsconfig": "^2.0.0",
"@playwright/test": "^1.55.0",
"@stylistic/eslint-plugin-ts": "^2.9.0",
"@swc/core": "^1.3.90",
"@swc/helpers": "^0.5.0",
"@swc/jest": "^0.2.26",
"@tanstack/react-table": "^8.21.3",
"@testing-library/jest-dom": "6.1.4",
"@testing-library/react": "14.0.0",
"@types/glob": "^8.0.0",
"@babel/core": "7.28.5",
"@changesets/cli": "2.29.8",
"@grafana/e2e-selectors": "12.3.1",
"@grafana/eslint-config": "9.0.0",
"@grafana/plugin-e2e": "3.1.1",
"@grafana/tsconfig": "2.0.1",
"@playwright/test": "1.57.0",
"@stylistic/eslint-plugin-ts": "4.4.1",
"@swc/core": "1.15.8",
"@swc/helpers": "0.5.18",
"@swc/jest": "0.2.39",
"@tanstack/react-table": "8.21.3",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "6.9.1",
"@testing-library/react": "16.3.1",
"@types/grafana": "github:CorpGlory/types-grafana",
"@types/jest": "^29.5.0",
"@types/lodash": "^4.14.194",
"@types/node": "^20.19.16",
"@types/react": "18.3.24",
"@types/react-router-dom": "^5.2.0",
"@types/testing-library__jest-dom": "5.14.8",
"@typescript-eslint/eslint-plugin": "^8.3.0",
"@typescript-eslint/parser": "^8.3.0",
"autoprefixer": "10.4.7",
"clean-webpack-plugin": "^0.1.19",
"copy-webpack-plugin": "^11.0.0",
"cspell": "6.31.3",
"css-loader": "^6.7.3",
"eslint": "8.57.1",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-deprecation": "^2.0.0",
"eslint-plugin-jsdoc": "^46.8.2",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-webpack-plugin": "^4.0.1",
"fork-ts-checker-webpack-plugin": "^8.0.0",
"@types/jest": "30.0.0",
"@types/lodash": "4.17.21",
"@types/node": "25.0.3",
"@types/react": "18.3.27",
"@types/react-dom": "18.3.1",
"@typescript-eslint/eslint-plugin": "8.52.0",
"@typescript-eslint/parser": "8.52.0",
"autoprefixer": "10.4.23",
"copy-webpack-plugin": "13.0.1",
"cspell": "9.4.0",
"css-loader": "7.1.2",
"eslint": "9.39.2",
"eslint-config-prettier": "10.1.8",
"eslint-plugin-jsdoc": "61.5.0",
"eslint-plugin-prettier": "5.5.4",
"eslint-plugin-react": "7.37.5",
"eslint-plugin-react-hooks": "7.0.1",
"eslint-webpack-plugin": "5.0.2",
"fork-ts-checker-webpack-plugin": "9.1.0",
"glob": "13.0.0",
"identity-obj-proxy": "3.0.0",
"imports-loader": "^5.0.0",
"jest": "^29.5.0",
"jest-environment-jsdom": "^29.5.0",
"imports-loader": "5.0.0",
"jest": "30.2.0",
"jest-environment-jsdom": "30.2.0",
"lodash": "4.17.21",
"mini-css-extract-plugin": "2.6.1",
"moment": "2.29.4",
"postcss": "8.4.31",
"postcss-loader": "7.0.1",
"postcss-reporter": "7.0.5",
"postcss-scss": "4.0.4",
"prettier": "^3.0.3",
"prop-types": "15.7.2",
"react-use": "17.4.0",
"replace-in-file-webpack-plugin": "^1.0.6",
"sass": "1.63.2",
"sass-loader": "13.3.3",
"semver": "^7.7.2",
"style-loader": "3.3.4",
"swc-loader": "^0.2.3",
"terser-webpack-plugin": "^5.3.14",
"ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0",
"typescript": "5.5.4",
"webpack": "^5.94.0",
"webpack-cli": "^5.1.4",
"webpack-livereload-plugin": "^3.0.2",
"webpack-remove-empty-scripts": "^1.0.1",
"webpack-subresource-integrity": "^5.1.0",
"webpack-virtual-modules": "^0.6.2"
"mini-css-extract-plugin": "2.9.4",
"moment": "2.30.1",
"postcss": "8.5.6",
"postcss-loader": "8.2.0",
"postcss-reporter": "7.1.0",
"postcss-scss": "4.0.9",
"prettier": "3.7.4",
"replace-in-file-webpack-plugin": "1.0.6",
"sass": "1.97.2",
"sass-loader": "16.0.6",
"semver": "7.7.3",
"style-loader": "4.0.0",
"swc-loader": "0.2.6",
"terser-webpack-plugin": "5.3.16",
"ts-node": "10.9.2",
"tsconfig-paths": "4.2.0",
"typescript": "5.9.3",
"webpack": "5.104.1",
"webpack-cli": "6.0.1",
"webpack-livereload-plugin": "3.0.2",
"webpack-remove-empty-scripts": "1.1.1",
"webpack-subresource-integrity": "5.1.0",
"webpack-virtual-modules": "0.6.2"
},
"resolutions": {
"glob": "^13.0.0",

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,16 +84,13 @@ export const ConfigEditor = (props: Props) => {
secureJsonData: { ...newSecureJsonData },
});
if (options.jsonData.dbConnectionEnable) {
if (!options.jsonData.dbConnectionDatasourceId) {
// 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) {
const selectedDs = getDirectDBDatasources().find((dsOption) => dsOption.id === ds.id);
setSelectedDBDatasource({ label: selectedDs?.name, value: selectedDs?.id });
setCurrentDSType(selectedDs?.type);
onOptionsChange({
...options,
jsonData: {
@@ -92,13 +100,6 @@ export const ConfigEditor = (props: Props) => {
});
}
});
} else {
const selectedDs = getDirectDBDatasources().find(
(dsOption) => dsOption.id === options.jsonData.dbConnectionDatasourceId
);
setSelectedDBDatasource({ label: selectedDs?.name, value: selectedDs?.id });
setCurrentDSType(selectedDs?.type);
}
}
}, []);
@@ -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(() => {
const fetchData = async () => {
const problem = original;
if (showTimeline) {
fetchProblemEvents();
const eventsData = await getProblemEvents(problem);
setEvents(eventsData);
}
fetchProblemAlerts();
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 {

6537
yarn.lock

File diff suppressed because it is too large Load Diff