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:
@@ -1,3 +1,4 @@
|
||||
{
|
||||
"version": "5.26.4"
|
||||
"version": "6.7.1",
|
||||
"features": {}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
43
.config/bundler/externals.ts
Normal file
43
.config/bundler/externals.ts
Normal 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();
|
||||
},
|
||||
];
|
||||
@@ -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
31
.config/eslint.config.mjs
Normal 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
1
.config/types/setupTests.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import '@testing-library/jest-dom';
|
||||
@@ -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,
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"extends": "./.config/.eslintrc",
|
||||
"plugins": ["prettier"],
|
||||
"ignorePatterns": ["/src/test-setup/**/*"],
|
||||
"rules": {
|
||||
"react-hooks/exhaustive-deps": "off",
|
||||
"prettier/prettier": "error"
|
||||
}
|
||||
}
|
||||
@@ -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
60
eslint.config.mjs
Normal 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',
|
||||
},
|
||||
},
|
||||
]);
|
||||
145
package.json
145
package.json
@@ -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",
|
||||
|
||||
@@ -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,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: {
|
||||
|
||||
@@ -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(() => {
|
||||
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) {
|
||||
|
||||
@@ -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