Migrate from grafana-toolkit to grafana plugin tools (#3837)
# What this PR does Migrate from grafana-toolkit to grafana plugin tools ## Which issue(s) this PR fixes https://github.com/grafana/oncall/issues/3651 ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not required) --------- Co-authored-by: Michael Derynck <michael.derynck@grafana.com> Co-authored-by: Dominik <dominik.broj@grafana.com>
This commit is contained in:
parent
d0ee58cb68
commit
828b0a3f4e
34 changed files with 3040 additions and 4073 deletions
28
.drone.yml
28
.drone.yml
|
|
@ -20,8 +20,8 @@ steps:
|
|||
- name: Sign and Package Plugin
|
||||
image: node:18.16.0-buster
|
||||
environment:
|
||||
GRAFANA_API_KEY:
|
||||
from_secret: gcom_plugin_publisher_api_key
|
||||
GRAFANA_ACCESS_POLICY_TOKEN:
|
||||
from_secret: cloud_access_policy_token
|
||||
depends_on:
|
||||
- Build Plugin
|
||||
commands:
|
||||
|
|
@ -30,9 +30,7 @@ steps:
|
|||
- cd grafana-plugin
|
||||
- yarn sign
|
||||
- if [ ! -f dist/MANIFEST.txt ]; then echo "Sign failed, MANIFEST.txt not created, aborting." && exit 1; fi
|
||||
- yarn ci-build:finish
|
||||
- yarn ci-package
|
||||
- cd ci/dist
|
||||
- mv dist grafana-oncall-app
|
||||
- zip -r grafana-oncall-app.zip ./grafana-oncall-app
|
||||
# yamllint disable rule:line-length
|
||||
- if [ -z "$DRONE_TAG" ]; then echo "No tag, skipping archive"; else cp grafana-oncall-app.zip grafana-oncall-app-${DRONE_TAG}.zip; fi
|
||||
|
|
@ -192,8 +190,8 @@ steps:
|
|||
- name: sign and package plugin
|
||||
image: node:18.16.0-buster
|
||||
environment:
|
||||
GRAFANA_API_KEY:
|
||||
from_secret: gcom_plugin_publisher_api_key
|
||||
GRAFANA_ACCESS_POLICY_TOKEN:
|
||||
from_secret: cloud_access_policy_token
|
||||
depends_on:
|
||||
- build plugin
|
||||
commands:
|
||||
|
|
@ -202,9 +200,7 @@ steps:
|
|||
- cd grafana-plugin
|
||||
- yarn sign
|
||||
- if [ ! -f dist/MANIFEST.txt ]; then echo "Sign failed, MANIFEST.txt not created, aborting." && exit 1; fi
|
||||
- yarn ci-build:finish
|
||||
- yarn ci-package
|
||||
- cd ci/dist
|
||||
- mv dist grafana-oncall-app
|
||||
- zip -r grafana-oncall-app.zip ./grafana-oncall-app
|
||||
# yamllint disable rule:line-length
|
||||
- if [ -z "$DRONE_TAG" ]; then echo "No tag, skipping archive"; else cp grafana-oncall-app.zip grafana-oncall-app-${DRONE_TAG}.zip; fi
|
||||
|
|
@ -355,6 +351,7 @@ get:
|
|||
path: infra/data/ci/docker_hub
|
||||
kind: secret
|
||||
name: docker_username
|
||||
|
||||
---
|
||||
get:
|
||||
name: password
|
||||
|
|
@ -377,8 +374,17 @@ get:
|
|||
path: ci/data/repo/grafana/oncall/drone
|
||||
kind: secret
|
||||
name: github_api_token
|
||||
|
||||
---
|
||||
# Secret for signing plugin
|
||||
get:
|
||||
name: cloud_access_policy_token
|
||||
path: ci/data/repo/grafana/oncall/sign_plugin
|
||||
kind: secret
|
||||
name: cloud_access_policy_token
|
||||
|
||||
---
|
||||
kind: signature
|
||||
hmac: f717f3a2708568d8d9ad3e8c738544b96a82455ecd1413feec9f502414807397
|
||||
hmac: 5bf89aaec69ebec6d4489b6ef712f92d10ede5b242b88c8f62930d78ba780f7d
|
||||
|
||||
...
|
||||
|
|
|
|||
|
|
@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Changed
|
||||
|
||||
- Change plugin build to use new packages instead of deprecated grafana-toolkit @maskin25 ([#3837](https://github.com/grafana/oncall/pull/3837))
|
||||
|
||||
## v1.3.106 (2024-02-20)
|
||||
|
||||
### Added
|
||||
|
|
|
|||
25
grafana-plugin/.config/.eslintrc
Normal file
25
grafana-plugin/.config/.eslintrc
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* ⚠️⚠️⚠️ 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/create-a-plugin/extend-a-plugin/extend-configurations#extend-the-eslint-config
|
||||
*/
|
||||
{
|
||||
"extends": ["@grafana/eslint-config"],
|
||||
"root": true,
|
||||
"rules": {
|
||||
"react/prop-types": "off"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"plugins": ["deprecation"],
|
||||
"files": ["src/**/*.{ts,tsx}"],
|
||||
"rules": {
|
||||
"deprecation/deprecation": "warn"
|
||||
},
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
16
grafana-plugin/.config/.prettierrc.js
Normal file
16
grafana-plugin/.config/.prettierrc.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
|
||||
*
|
||||
* In order to extend the configuration follow the steps in .config/README.md
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
endOfLine: 'auto',
|
||||
printWidth: 120,
|
||||
trailingComma: 'es5',
|
||||
semi: true,
|
||||
jsxSingleQuote: false,
|
||||
singleQuote: true,
|
||||
useTabs: false,
|
||||
tabWidth: 2,
|
||||
};
|
||||
25
grafana-plugin/.config/jest-setup.js
Normal file
25
grafana-plugin/.config/jest-setup.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* ⚠️⚠️⚠️ 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/create-a-plugin/extend-a-plugin/extend-configurations#extend-the-jest-config
|
||||
*/
|
||||
|
||||
import '@testing-library/jest-dom';
|
||||
|
||||
// https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom
|
||||
Object.defineProperty(global, 'matchMedia', {
|
||||
writable: true,
|
||||
value: jest.fn().mockImplementation((query) => ({
|
||||
matches: false,
|
||||
media: query,
|
||||
onchange: null,
|
||||
addListener: jest.fn(), // deprecated
|
||||
removeListener: jest.fn(), // deprecated
|
||||
addEventListener: jest.fn(),
|
||||
removeEventListener: jest.fn(),
|
||||
dispatchEvent: jest.fn(),
|
||||
})),
|
||||
});
|
||||
|
||||
HTMLCanvasElement.prototype.getContext = () => {};
|
||||
43
grafana-plugin/.config/jest.config.js
Normal file
43
grafana-plugin/.config/jest.config.js
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* ⚠️⚠️⚠️ 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/create-a-plugin/extend-a-plugin/extend-configurations#extend-the-jest-config
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const { grafanaESModules, nodeModulesToTransform } = require('./jest/utils');
|
||||
|
||||
module.exports = {
|
||||
moduleNameMapper: {
|
||||
'\\.(css|scss|sass)$': 'identity-obj-proxy',
|
||||
'react-inlinesvg': path.resolve(__dirname, 'jest', 'mocks', 'react-inlinesvg.tsx'),
|
||||
},
|
||||
modulePaths: ['<rootDir>/src'],
|
||||
setupFilesAfterEnv: ['<rootDir>/jest-setup.js'],
|
||||
testEnvironment: 'jest-environment-jsdom',
|
||||
testMatch: [
|
||||
'<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}',
|
||||
'<rootDir>/src/**/*.{spec,test,jest}.{js,jsx,ts,tsx}',
|
||||
'<rootDir>/src/**/*.{spec,test,jest}.{js,jsx,ts,tsx}',
|
||||
],
|
||||
transform: {
|
||||
'^.+\\.(t|j)sx?$': [
|
||||
'@swc/jest',
|
||||
{
|
||||
sourceMaps: 'inline',
|
||||
jsc: {
|
||||
parser: {
|
||||
syntax: 'typescript',
|
||||
tsx: true,
|
||||
decorators: false,
|
||||
dynamicImport: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// Jest will throw `Cannot use import statement outside module` if it tries to load an
|
||||
// ES module without it being transformed first. ./config/README.md#esm-errors-with-jest
|
||||
transformIgnorePatterns: [nodeModulesToTransform(grafanaESModules)],
|
||||
};
|
||||
25
grafana-plugin/.config/jest/mocks/react-inlinesvg.tsx
Normal file
25
grafana-plugin/.config/jest/mocks/react-inlinesvg.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Due to the grafana/ui Icon component making fetch requests to
|
||||
// `/public/img/icon/<icon_name>.svg` we need to mock react-inlinesvg to prevent
|
||||
// the failed fetch requests from displaying errors in console.
|
||||
|
||||
import React from 'react';
|
||||
|
||||
type Callback = (...args: any[]) => void;
|
||||
|
||||
export interface StorageItem {
|
||||
content: string;
|
||||
queue: Callback[];
|
||||
status: string;
|
||||
}
|
||||
|
||||
export const cacheStore: { [key: string]: StorageItem } = Object.create(null);
|
||||
|
||||
const SVG_FILE_NAME_REGEX = /(.+)\/(.+)\.svg$/;
|
||||
|
||||
const InlineSVG = ({ src }: { src: string }) => {
|
||||
// testId will be the file name without extension (e.g. `public/img/icons/angle-double-down.svg` -> `angle-double-down`)
|
||||
const testId = src.replace(SVG_FILE_NAME_REGEX, '$2');
|
||||
return <svg xmlns="http://www.w3.org/2000/svg" data-testid={testId} viewBox="0 0 24 24" />;
|
||||
};
|
||||
|
||||
export default InlineSVG;
|
||||
31
grafana-plugin/.config/jest/utils.js
Normal file
31
grafana-plugin/.config/jest/utils.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
|
||||
*
|
||||
* In order to extend the configuration follow the steps in .config/README.md
|
||||
*/
|
||||
|
||||
/*
|
||||
* This utility function is useful in combination with jest `transformIgnorePatterns` config
|
||||
* to transform specific packages (e.g.ES modules) in a projects node_modules folder.
|
||||
*/
|
||||
const nodeModulesToTransform = (moduleNames) => `node_modules\/(?!.*(${moduleNames.join('|')})\/.*)`;
|
||||
|
||||
// Array of known nested grafana package dependencies that only bundle an ESM version
|
||||
const grafanaESModules = [
|
||||
'.pnpm', // Support using pnpm symlinked packages
|
||||
'@grafana/schema',
|
||||
'd3',
|
||||
'd3-color',
|
||||
'd3-force',
|
||||
'd3-interpolate',
|
||||
'd3-scale-chromatic',
|
||||
'ol',
|
||||
'react-colorful',
|
||||
'rxjs',
|
||||
'uuid',
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
nodeModulesToTransform,
|
||||
grafanaESModules,
|
||||
};
|
||||
26
grafana-plugin/.config/tsconfig.json
Normal file
26
grafana-plugin/.config/tsconfig.json
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* ⚠️⚠️⚠️ 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/create-a-plugin/extend-a-plugin/extend-configurations#extend-the-typescript-config
|
||||
*/
|
||||
{
|
||||
"compilerOptions": {
|
||||
"alwaysStrict": true,
|
||||
"declaration": false,
|
||||
"rootDir": "../src",
|
||||
"baseUrl": "../src",
|
||||
"typeRoots": ["../node_modules/@types"],
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"ts-node": {
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"transpileOnly": true
|
||||
},
|
||||
"include": ["../src", "./types"],
|
||||
"extends": "@grafana/tsconfig"
|
||||
}
|
||||
37
grafana-plugin/.config/types/custom.d.ts
vendored
Normal file
37
grafana-plugin/.config/types/custom.d.ts
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// Image declarations
|
||||
declare module '*.gif' {
|
||||
const src: string;
|
||||
export default src;
|
||||
}
|
||||
|
||||
declare module '*.jpg' {
|
||||
const src: string;
|
||||
export default src;
|
||||
}
|
||||
|
||||
declare module '*.jpeg' {
|
||||
const src: string;
|
||||
export default src;
|
||||
}
|
||||
|
||||
declare module '*.png' {
|
||||
const src: string;
|
||||
export default src;
|
||||
}
|
||||
|
||||
declare module '*.webp' {
|
||||
const src: string;
|
||||
export default src;
|
||||
}
|
||||
|
||||
declare module '*.svg' {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
|
||||
// Font declarations
|
||||
declare module '*.woff';
|
||||
declare module '*.woff2';
|
||||
declare module '*.eot';
|
||||
declare module '*.ttf';
|
||||
declare module '*.otf';
|
||||
2
grafana-plugin/.config/webpack/constants.ts
Normal file
2
grafana-plugin/.config/webpack/constants.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export const SOURCE_DIR = 'src';
|
||||
export const DIST_DIR = 'dist';
|
||||
58
grafana-plugin/.config/webpack/utils.ts
Normal file
58
grafana-plugin/.config/webpack/utils.ts
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import fs from 'fs';
|
||||
import process from 'process';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import { glob } from 'glob';
|
||||
import { SOURCE_DIR } from './constants';
|
||||
|
||||
export function isWSL() {
|
||||
if (process.platform !== 'linux') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (os.release().toLowerCase().includes('microsoft')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
return fs.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft');
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function getPackageJson() {
|
||||
return require(path.resolve(process.cwd(), 'package.json'));
|
||||
}
|
||||
|
||||
export function getPluginJson() {
|
||||
return require(path.resolve(process.cwd(), `${SOURCE_DIR}/plugin.json`));
|
||||
}
|
||||
|
||||
export function hasReadme() {
|
||||
return fs.existsSync(path.resolve(process.cwd(), SOURCE_DIR, 'README.md'));
|
||||
}
|
||||
|
||||
// Support bundling nested plugins by finding all plugin.json files in src directory
|
||||
// then checking for a sibling module.[jt]sx? file.
|
||||
export async function getEntries(): Promise<Record<string, string>> {
|
||||
const pluginsJson = await glob('**/src/**/plugin.json', { absolute: true });
|
||||
|
||||
const plugins = await Promise.all(
|
||||
pluginsJson.map((pluginJson) => {
|
||||
const folder = path.dirname(pluginJson);
|
||||
return glob(`${folder}/module.{ts,tsx,js,jsx}`, { absolute: true });
|
||||
})
|
||||
);
|
||||
|
||||
return plugins.reduce((result, modules) => {
|
||||
return modules.reduce((result, module) => {
|
||||
const pluginPath = path.dirname(module);
|
||||
const pluginName = path.relative(process.cwd(), pluginPath).replace(/src\/?/i, '');
|
||||
const entryName = pluginName === '' ? 'module' : `${pluginName}/module`;
|
||||
|
||||
result[entryName] = module;
|
||||
return result;
|
||||
}, result);
|
||||
}, {});
|
||||
}
|
||||
218
grafana-plugin/.config/webpack/webpack.config.ts
Normal file
218
grafana-plugin/.config/webpack/webpack.config.ts
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* ⚠️⚠️⚠️ 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/create-a-plugin/extend-a-plugin/extend-configurations#extend-the-webpack-config
|
||||
*/
|
||||
|
||||
import CopyWebpackPlugin from 'copy-webpack-plugin';
|
||||
import ESLintPlugin from 'eslint-webpack-plugin';
|
||||
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
|
||||
import LiveReloadPlugin from 'webpack-livereload-plugin';
|
||||
import path from 'path';
|
||||
import ReplaceInFileWebpackPlugin from 'replace-in-file-webpack-plugin';
|
||||
import { Configuration } from 'webpack';
|
||||
|
||||
import { getPackageJson, getPluginJson, hasReadme, getEntries, isWSL } from './utils';
|
||||
import { SOURCE_DIR, DIST_DIR } from './constants';
|
||||
|
||||
const pluginJson = getPluginJson();
|
||||
|
||||
const config = async (env): Promise<Configuration> => {
|
||||
const baseConfig: Configuration = {
|
||||
cache: {
|
||||
type: 'filesystem',
|
||||
buildDependencies: {
|
||||
config: [__filename],
|
||||
},
|
||||
},
|
||||
|
||||
context: path.join(process.cwd(), SOURCE_DIR),
|
||||
|
||||
devtool: env.production ? 'source-map' : 'eval-source-map',
|
||||
|
||||
entry: await getEntries(),
|
||||
|
||||
externals: [
|
||||
'lodash',
|
||||
'jquery',
|
||||
'moment',
|
||||
'slate',
|
||||
'emotion',
|
||||
'@emotion/react',
|
||||
'@emotion/css',
|
||||
'prismjs',
|
||||
'slate-plain-serializer',
|
||||
'@grafana/slate-react',
|
||||
'react',
|
||||
'react-dom',
|
||||
'react-redux',
|
||||
'redux',
|
||||
'rxjs',
|
||||
'react-router',
|
||||
'react-router-dom',
|
||||
'd3',
|
||||
'angular',
|
||||
'@grafana/ui',
|
||||
'@grafana/runtime',
|
||||
'@grafana/data',
|
||||
|
||||
// Mark legacy SDK imports as external if their name starts with the "grafana/" prefix
|
||||
({ request }, callback) => {
|
||||
const prefix = 'grafana/';
|
||||
const hasPrefix = (request) => request.indexOf(prefix) === 0;
|
||||
const stripPrefix = (request) => request.substr(prefix.length);
|
||||
|
||||
if (hasPrefix(request)) {
|
||||
return callback(undefined, stripPrefix(request));
|
||||
}
|
||||
|
||||
callback();
|
||||
},
|
||||
],
|
||||
|
||||
mode: env.production ? 'production' : 'development',
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
exclude: /(node_modules)/,
|
||||
test: /\.[tj]sx?$/,
|
||||
use: {
|
||||
loader: 'swc-loader',
|
||||
options: {
|
||||
jsc: {
|
||||
baseUrl: path.resolve(__dirname, 'src'),
|
||||
target: 'es2015',
|
||||
loose: false,
|
||||
parser: {
|
||||
syntax: 'typescript',
|
||||
tsx: true,
|
||||
decorators: false,
|
||||
dynamicImport: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ['style-loader', 'css-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.s[ac]ss$/,
|
||||
use: ['style-loader', 'css-loader', 'sass-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg)$/,
|
||||
type: 'asset/resource',
|
||||
generator: {
|
||||
// Keep publicPath relative for host.com/grafana/ deployments
|
||||
publicPath: `public/plugins/${pluginJson.id}/img/`,
|
||||
outputPath: 'img/',
|
||||
filename: Boolean(env.production) ? '[hash][ext]' : '[file]',
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(woff|woff2|eot|ttf|otf)(\?v=\d+\.\d+\.\d+)?$/,
|
||||
type: 'asset/resource',
|
||||
generator: {
|
||||
// Keep publicPath relative for host.com/grafana/ deployments
|
||||
publicPath: `public/plugins/${pluginJson.id}/fonts/`,
|
||||
outputPath: 'fonts/',
|
||||
filename: Boolean(env.production) ? '[hash][ext]' : '[name][ext]',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
output: {
|
||||
clean: {
|
||||
keep: new RegExp(`(.*?_(amd64|arm(64)?)(.exe)?|go_plugin_build_manifest)`),
|
||||
},
|
||||
filename: '[name].js',
|
||||
library: {
|
||||
type: 'amd',
|
||||
},
|
||||
path: path.resolve(process.cwd(), DIST_DIR),
|
||||
publicPath: `public/plugins/${pluginJson.id}/`,
|
||||
uniqueName: pluginJson.id,
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
// If src/README.md exists use it; otherwise the root README
|
||||
// To `compiler.options.output`
|
||||
{ from: hasReadme() ? 'README.md' : '../README.md', to: '.', force: true },
|
||||
{ from: 'plugin.json', to: '.' },
|
||||
{ from: '../LICENSE', to: '.' },
|
||||
{ from: '../CHANGELOG.md', to: '.', noErrorOnMissing: true, force: true },
|
||||
{ from: '**/*.json', to: '.' }, // TODO<Add an error for checking the basic structure of the repo>
|
||||
{ from: '**/*.svg', to: '.', noErrorOnMissing: true }, // Optional
|
||||
{ from: '**/*.png', to: '.', noErrorOnMissing: true }, // Optional
|
||||
{ from: '**/*.html', to: '.', noErrorOnMissing: true }, // Optional
|
||||
{ from: 'img/**/*', to: '.', noErrorOnMissing: true }, // Optional
|
||||
{ from: 'libs/**/*', to: '.', noErrorOnMissing: true }, // Optional
|
||||
{ from: 'static/**/*', to: '.', noErrorOnMissing: true }, // Optional
|
||||
{ from: '**/query_help.md', to: '.', noErrorOnMissing: true }, // Optional
|
||||
],
|
||||
}),
|
||||
// Replace certain template-variables in the README and plugin.json
|
||||
new ReplaceInFileWebpackPlugin([
|
||||
{
|
||||
dir: DIST_DIR,
|
||||
files: ['plugin.json', 'README.md'],
|
||||
rules: [
|
||||
{
|
||||
search: /\%VERSION\%/g,
|
||||
replace: getPackageJson().version,
|
||||
},
|
||||
{
|
||||
search: /\%TODAY\%/g,
|
||||
replace: new Date().toISOString().substring(0, 10),
|
||||
},
|
||||
{
|
||||
search: /\%PLUGIN_ID\%/g,
|
||||
replace: pluginJson.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
]),
|
||||
...(env.development
|
||||
? [
|
||||
new LiveReloadPlugin(),
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
async: Boolean(env.development),
|
||||
issue: {
|
||||
include: [{ file: '**/*.{ts,tsx}' }],
|
||||
},
|
||||
typescript: { configFile: path.join(process.cwd(), 'tsconfig.json') },
|
||||
}),
|
||||
new ESLintPlugin({
|
||||
extensions: ['.ts', '.tsx'],
|
||||
lintDirtyModulesOnly: Boolean(env.development), // don't lint on start, only lint changed files
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
],
|
||||
|
||||
resolve: {
|
||||
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||
// handle resolving "rootDir" paths
|
||||
modules: [path.resolve(process.cwd(), 'src'), 'node_modules'],
|
||||
unsafeCache: true,
|
||||
},
|
||||
};
|
||||
|
||||
if (isWSL()) {
|
||||
baseConfig.watchOptions = {
|
||||
poll: 3000,
|
||||
ignored: /node_modules/,
|
||||
};
|
||||
}
|
||||
|
||||
return baseConfig;
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
@ -2,7 +2,7 @@ const rulesDirPlugin = require('eslint-plugin-rulesdir');
|
|||
rulesDirPlugin.RULES_DIR = 'tools/eslint-rules';
|
||||
|
||||
module.exports = {
|
||||
extends: ['@grafana/eslint-config'],
|
||||
extends: ['./.config/.eslintrc'],
|
||||
plugins: ['rulesdir', 'import'],
|
||||
settings: {
|
||||
'import/internal-regex':
|
||||
|
|
|
|||
1
grafana-plugin/.nvmrc
Normal file
1
grafana-plugin/.nvmrc
Normal file
|
|
@ -0,0 +1 @@
|
|||
18.16.0
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
module.exports = {
|
||||
...require('@grafana/toolkit/src/config/prettier.plugin.config.json'),
|
||||
// Prettier configuration provided by Grafana scaffolding
|
||||
...require('./.config/.prettierrc.js'),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"presets": [
|
||||
["@babel/preset-env", { "targets": { "node": "current" } }],
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-typescript"
|
||||
],
|
||||
"plugins": [
|
||||
["@babel/plugin-proposal-decorators", { "legacy": true }],
|
||||
["@babel/plugin-transform-destructuring", { "useBuiltIns": true }],
|
||||
"@babel/plugin-transform-runtime",
|
||||
["@babel/plugin-proposal-class-properties", { "loose": false }],
|
||||
"@babel/transform-regenerator",
|
||||
"@babel/plugin-transform-template-literals"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,6 +1,11 @@
|
|||
// force timezone to UTC to allow tests to work regardless of local timezone
|
||||
// generally used by snapshots, but can affect specific tests
|
||||
process.env.TZ = 'UTC';
|
||||
|
||||
const esModules = ['@grafana', 'uplot', 'ol', 'd3', 'react-colorful', 'uuid', 'openapi-fetch'].join('|');
|
||||
|
||||
module.exports = {
|
||||
...require('./.config/jest.config'),
|
||||
testEnvironment: 'jsdom',
|
||||
|
||||
moduleDirectories: ['node_modules', 'src'],
|
||||
|
|
@ -23,4 +28,20 @@ module.exports = {
|
|||
|
||||
testTimeout: 10000,
|
||||
testPathIgnorePatterns: ['/node_modules/', '/e2e-tests/'],
|
||||
transform: {
|
||||
'^.+\\.(t|j)sx?$': [
|
||||
'@swc/jest',
|
||||
{
|
||||
sourceMaps: 'inline',
|
||||
jsc: {
|
||||
parser: {
|
||||
syntax: 'typescript',
|
||||
tsx: true,
|
||||
decorators: true,
|
||||
dynamicImport: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ import '@testing-library/jest-dom';
|
|||
|
||||
import 'plugin/dayjs';
|
||||
|
||||
import { TextEncoder, TextDecoder } from 'util';
|
||||
|
||||
Object.assign(global, { TextDecoder, TextEncoder });
|
||||
|
||||
// https://stackoverflow.com/a/66055672
|
||||
// https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom
|
||||
Object.defineProperty(window, 'matchMedia', {
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
"lint:fix": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx --quiet ./src ./e2e-tests",
|
||||
"stylelint": "stylelint ./src/**/*.{css,scss,module.css,module.scss}",
|
||||
"stylelint:fix": "stylelint --fix ./src/**/*.{css,scss,module.css,module.scss}",
|
||||
"build": "grafana-toolkit plugin:build",
|
||||
"build:dev": "grafana-toolkit plugin:build --skipTest --skipLint",
|
||||
"build": "webpack -c ./webpack.config.ts --env production",
|
||||
"build:dev": "webpack -c ./webpack.config.ts --env development",
|
||||
"labels:link": "yarn --cwd ../../gops-labels/frontend link && yarn link \"@grafana/labels\" && yarn --cwd ../../gops-labels/frontend watch",
|
||||
"labels:unlink": "yarn --cwd ../../gops-labels/frontend unlink",
|
||||
"test": "jest --verbose",
|
||||
|
|
@ -19,12 +19,9 @@
|
|||
"test:e2e:gen": "yarn playwright codegen http://localhost:3000",
|
||||
"e2e-show-report": "yarn playwright show-report",
|
||||
"generate-types": "cd ./src/network/oncall-api/types-generator && yarn generate",
|
||||
"dev": "grafana-toolkit plugin:dev",
|
||||
"watch": "grafana-toolkit plugin:dev --watch",
|
||||
"sign": "grafana-toolkit plugin:sign",
|
||||
"ci-build:finish": "grafana-toolkit plugin:ci-build --finish",
|
||||
"ci-package": "grafana-toolkit plugin:ci-package",
|
||||
"ci-report": "grafana-toolkit plugin:ci-report",
|
||||
"dev": "webpack -c ./.config/webpack/webpack.config.ts --env development",
|
||||
"watch": "webpack -w -c ./.config/webpack/webpack.config.ts --env development",
|
||||
"sign": "npx --yes @grafana/sign-plugin@latest",
|
||||
"start": "yarn watch",
|
||||
"plop": "plop",
|
||||
"setversion": "setversion",
|
||||
|
|
@ -50,6 +47,7 @@
|
|||
"author": "Grafana Labs",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.21.4",
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@babel/plugin-proposal-decorators": "^7.20.0",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
|
||||
|
|
@ -64,17 +62,21 @@
|
|||
"@babel/preset-env": "^7.18.10",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@babel/preset-typescript": "^7.18.6",
|
||||
"@grafana/eslint-config": "^5.1.0",
|
||||
"@grafana/toolkit": "^9.5.2",
|
||||
"@grafana/eslint-config": "^6.0.0",
|
||||
"@grafana/tsconfig": "^1.2.0-rc1",
|
||||
"@jest/globals": "^27.5.1",
|
||||
"@playwright/test": "^1.39.0",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "12",
|
||||
"@swc/core": "^1.3.90",
|
||||
"@swc/helpers": "^0.5.0",
|
||||
"@swc/jest": "^0.2.26",
|
||||
"@testing-library/jest-dom": "6.1.4",
|
||||
"@testing-library/react": "14.0.0",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"@types/dompurify": "^2.3.4",
|
||||
"@types/jest": "27.5.1",
|
||||
"@types/jest": "^29.5.0",
|
||||
"@types/lodash": "^4.14.194",
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/node": "^20.8.7",
|
||||
"@types/query-string": "^6.3.0",
|
||||
"@types/react-copy-to-clipboard": "^5.0.4",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
|
|
@ -82,19 +84,26 @@
|
|||
"@types/react-router-dom": "^5.3.3",
|
||||
"@types/react-test-renderer": "^18.0.5",
|
||||
"@types/react-transition-group": "^4.4.5",
|
||||
"@types/testing-library__jest-dom": "5.14.8",
|
||||
"@types/throttle-debounce": "^5.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.40.1",
|
||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"css-loader": "^6.7.3",
|
||||
"dompurify": "^2.3.12",
|
||||
"dotenv": "^16.0.3",
|
||||
"eslint": "^8.25.0",
|
||||
"eslint-plugin-deprecation": "^2.0.0",
|
||||
"eslint-plugin-jsdoc": "^44.2.4",
|
||||
"eslint-plugin-react": "^7.31.10",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-rulesdir": "^0.2.1",
|
||||
"jest": "27.5.1",
|
||||
"jest-environment-jsdom": "^27.5.1",
|
||||
"eslint-webpack-plugin": "^4.0.1",
|
||||
"fork-ts-checker-webpack-plugin": "^8.0.0",
|
||||
"glob": "^10.2.7",
|
||||
"identity-obj-proxy": "3.0.0",
|
||||
"jest": "^29.5.0",
|
||||
"jest-environment-jsdom": "^29.5.0",
|
||||
"lint-staged": "^10.2.11",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mailslurp-client": "^15.14.1",
|
||||
|
|
@ -102,26 +111,35 @@
|
|||
"openapi-typescript": "^7.0.0-next.4",
|
||||
"plop": "^2.7.4",
|
||||
"postcss-loader": "^7.0.1",
|
||||
"prettier": "^2.8.7",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-test-renderer": "^18.0.2",
|
||||
"replace-in-file-webpack-plugin": "^1.0.6",
|
||||
"sass": "1.63.2",
|
||||
"sass-loader": "13.3.1",
|
||||
"style-loader": "3.3.3",
|
||||
"stylelint-config-prettier": "^9.0.3",
|
||||
"stylelint-prettier": "^2.0.0",
|
||||
"swc-loader": "^0.2.3",
|
||||
"ts-jest": "29.0.3",
|
||||
"ts-loader": "^9.3.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "4.6.4",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"typescript": "4.8.4",
|
||||
"webpack": "^5.86.0",
|
||||
"webpack-bundle-analyzer": "^4.6.1",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-livereload-plugin": "^3.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
"node": "~18.16.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dnd-kit/core": "^6.0.8",
|
||||
"@dnd-kit/modifiers": "^7.0.0",
|
||||
"@dnd-kit/sortable": "^7.0.2",
|
||||
"@dnd-kit/utilities": "^3.2.1",
|
||||
"@emotion/css": "11.10.6",
|
||||
"@grafana/data": "^10.2.3",
|
||||
"@grafana/faro-web-sdk": "^1.0.0-beta4",
|
||||
"@grafana/faro-web-tracing": "^1.0.0-beta4",
|
||||
|
|
@ -133,6 +151,8 @@
|
|||
"@lifeomic/attempt": "^3.0.3",
|
||||
"@opentelemetry/api": "^1.3.0",
|
||||
"array-move": "^4.0.0",
|
||||
"axios": "^1.6.7",
|
||||
"babel-loader": "^9.1.3",
|
||||
"change-case": "^4.1.1",
|
||||
"circular-dependency-plugin": "^5.2.2",
|
||||
"dayjs": "^1.11.5",
|
||||
|
|
@ -142,11 +162,12 @@
|
|||
"mobx-react": "9.1.0",
|
||||
"object-hash": "^3.0.0",
|
||||
"openapi-fetch": "^0.8.1",
|
||||
"prettier": "^2.8.2",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"raw-loader": "^4.0.2",
|
||||
"rc-table": "^7.17.1",
|
||||
"react": "18.2.0",
|
||||
"react-copy-to-clipboard": "^5.0.2",
|
||||
"react-dom": "18.2.0",
|
||||
"react-draggable": "^4.4.5",
|
||||
"react-emoji-render": "^1.2.4",
|
||||
"react-modal": "^3.15.1",
|
||||
|
|
@ -155,9 +176,10 @@
|
|||
"react-sortable-hoc": "^1.11.0",
|
||||
"react-string-replace": "^0.4.4",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"sass-loader": "^13.0.2",
|
||||
"stylelint": "^13.13.1",
|
||||
"stylelint-config-standard": "^22.0.0",
|
||||
"throttle-debounce": "^2.1.0"
|
||||
}
|
||||
"throttle-debounce": "^2.1.0",
|
||||
"tslib": "2.5.3"
|
||||
},
|
||||
"packageManager": "yarn@1.22.21"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ const getStyles = (theme: GrafanaTheme2, color?: string, size?: string) => {
|
|||
color: ${fontColor};
|
||||
font-size: ${theme.typography.bodySmall.fontSize};
|
||||
|
||||
border-radius: ${theme.shape.borderRadius(2)};
|
||||
border-radius: ${theme.shape.radius.default};
|
||||
`,
|
||||
label: css`
|
||||
display: flex;
|
||||
|
|
@ -68,8 +68,8 @@ const getStyles = (theme: GrafanaTheme2, color?: string, size?: string) => {
|
|||
background: ${backgroundColor};
|
||||
|
||||
border: solid 1px ${borderColor};
|
||||
border-top-left-radius: ${theme.shape.borderRadius(2)};
|
||||
border-bottom-left-radius: ${theme.shape.borderRadius(2)};
|
||||
border-top-left-radius: ${theme.shape.radius.default};
|
||||
border-bottom-left-radius: ${theme.shape.radius.default};
|
||||
`,
|
||||
value: css`
|
||||
color: inherit;
|
||||
|
|
@ -78,8 +78,8 @@ const getStyles = (theme: GrafanaTheme2, color?: string, size?: string) => {
|
|||
|
||||
border: solid 1px ${borderColor};
|
||||
border-left: none;
|
||||
border-top-right-radius: ${theme.shape.borderRadius(2)};
|
||||
border-bottom-right-radius: ${theme.shape.borderRadius(2)};
|
||||
border-top-right-radius: ${theme.shape.radius.default};
|
||||
border-bottom-right-radius: ${theme.shape.radius.default};
|
||||
`,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ exports[`Unauthorized renders properly - access control enabled: false 1`] = `
|
|||
<div
|
||||
className="css-8tu8mo-vertical-group"
|
||||
style={
|
||||
Object {
|
||||
{
|
||||
"height": "100%",
|
||||
"width": "100%",
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ exports[`Unauthorized renders properly - access control enabled: false 1`] = `
|
|||
<span
|
||||
className="root text text--undefined text--medium"
|
||||
style={
|
||||
Object {
|
||||
{
|
||||
"maxWidth": undefined,
|
||||
}
|
||||
}
|
||||
|
|
@ -40,7 +40,7 @@ exports[`Unauthorized renders properly - access control enabled: false 1`] = `
|
|||
<span
|
||||
className="root text text--undefined text--medium"
|
||||
style={
|
||||
Object {
|
||||
{
|
||||
"maxWidth": undefined,
|
||||
}
|
||||
}
|
||||
|
|
@ -65,7 +65,7 @@ exports[`Unauthorized renders properly - access control enabled: true 1`] = `
|
|||
<div
|
||||
className="css-8tu8mo-vertical-group"
|
||||
style={
|
||||
Object {
|
||||
{
|
||||
"height": "100%",
|
||||
"width": "100%",
|
||||
}
|
||||
|
|
@ -80,7 +80,7 @@ exports[`Unauthorized renders properly - access control enabled: true 1`] = `
|
|||
<span
|
||||
className="root text text--undefined text--medium"
|
||||
style={
|
||||
Object {
|
||||
{
|
||||
"maxWidth": undefined,
|
||||
}
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ exports[`Unauthorized renders properly - access control enabled: true 1`] = `
|
|||
<span
|
||||
className="root text text--undefined text--medium"
|
||||
style={
|
||||
Object {
|
||||
{
|
||||
"maxWidth": undefined,
|
||||
}
|
||||
}
|
||||
|
|
@ -123,7 +123,7 @@ exports[`Unauthorized renders properly the grammar for different roles - Admin 1
|
|||
<div
|
||||
className="css-8tu8mo-vertical-group"
|
||||
style={
|
||||
Object {
|
||||
{
|
||||
"height": "100%",
|
||||
"width": "100%",
|
||||
}
|
||||
|
|
@ -138,7 +138,7 @@ exports[`Unauthorized renders properly the grammar for different roles - Admin 1
|
|||
<span
|
||||
className="root text text--undefined text--medium"
|
||||
style={
|
||||
Object {
|
||||
{
|
||||
"maxWidth": undefined,
|
||||
}
|
||||
}
|
||||
|
|
@ -156,7 +156,7 @@ exports[`Unauthorized renders properly the grammar for different roles - Admin 1
|
|||
<span
|
||||
className="root text text--undefined text--medium"
|
||||
style={
|
||||
Object {
|
||||
{
|
||||
"maxWidth": undefined,
|
||||
}
|
||||
}
|
||||
|
|
@ -181,7 +181,7 @@ exports[`Unauthorized renders properly the grammar for different roles - Editor
|
|||
<div
|
||||
className="css-8tu8mo-vertical-group"
|
||||
style={
|
||||
Object {
|
||||
{
|
||||
"height": "100%",
|
||||
"width": "100%",
|
||||
}
|
||||
|
|
@ -196,7 +196,7 @@ exports[`Unauthorized renders properly the grammar for different roles - Editor
|
|||
<span
|
||||
className="root text text--undefined text--medium"
|
||||
style={
|
||||
Object {
|
||||
{
|
||||
"maxWidth": undefined,
|
||||
}
|
||||
}
|
||||
|
|
@ -214,7 +214,7 @@ exports[`Unauthorized renders properly the grammar for different roles - Editor
|
|||
<span
|
||||
className="root text text--undefined text--medium"
|
||||
style={
|
||||
Object {
|
||||
{
|
||||
"maxWidth": undefined,
|
||||
}
|
||||
}
|
||||
|
|
@ -239,7 +239,7 @@ exports[`Unauthorized renders properly the grammar for different roles - Viewer
|
|||
<div
|
||||
className="css-8tu8mo-vertical-group"
|
||||
style={
|
||||
Object {
|
||||
{
|
||||
"height": "100%",
|
||||
"width": "100%",
|
||||
}
|
||||
|
|
@ -254,7 +254,7 @@ exports[`Unauthorized renders properly the grammar for different roles - Viewer
|
|||
<span
|
||||
className="root text text--undefined text--medium"
|
||||
style={
|
||||
Object {
|
||||
{
|
||||
"maxWidth": undefined,
|
||||
}
|
||||
}
|
||||
|
|
@ -272,7 +272,7 @@ exports[`Unauthorized renders properly the grammar for different roles - Viewer
|
|||
<span
|
||||
className="root text text--undefined text--medium"
|
||||
style={
|
||||
Object {
|
||||
{
|
||||
"maxWidth": undefined,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ describe('AddRespondersPopup', () => {
|
|||
},
|
||||
grafanaTeamStore: {
|
||||
getSearchResult: jest.fn().mockReturnValue(teams),
|
||||
updateItems: jest.fn(),
|
||||
},
|
||||
userStore: {
|
||||
search: jest.fn().mockReturnValue({ results: [] }),
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ describe('reloadPageWithPluginConfiguredQueryParams', () => {
|
|||
describe('removePluginConfiguredQueryParams', () => {
|
||||
test('it removes all the query params if history.pushState is available, and plugin is enabled', () => {
|
||||
removePluginConfiguredQueryParams(true);
|
||||
expect(window.history.pushState).toBeCalledWith({ path: MOCK_URL }, '', MOCK_URL);
|
||||
expect(window.history.pushState).toHaveBeenCalledWith({ path: MOCK_URL }, '', MOCK_URL);
|
||||
});
|
||||
|
||||
test('it does not remove all the query params if history.pushState is available, and plugin is disabled', () => {
|
||||
|
|
@ -148,7 +148,7 @@ describe('PluginConfigPage', () => {
|
|||
await screen.findByTestId(STATUS_MESSAGE_BLOCK_DATA_ID);
|
||||
|
||||
// assertions
|
||||
expect(window.history.pushState).toBeCalledWith({ path: MOCK_URL }, '', MOCK_URL);
|
||||
expect(window.history.pushState).toHaveBeenCalledWith({ path: MOCK_URL }, '', MOCK_URL);
|
||||
|
||||
expect(PluginState.updatePluginStatus).toHaveBeenCalledTimes(1);
|
||||
expect(PluginState.updatePluginStatus).toHaveBeenCalledWith(metaJsonDataOnCallApiUrl);
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ class _IncidentsPage extends React.Component<IncidentsPageProps, IncidentsPageSt
|
|||
}
|
||||
|
||||
private rootElRef: React.RefObject<HTMLDivElement>;
|
||||
private pollingIntervalId: NodeJS.Timer = undefined;
|
||||
private pollingIntervalId: ReturnType<typeof setInterval> = undefined;
|
||||
|
||||
componentDidMount() {
|
||||
const { store } = this.props;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export class _ChatOpsPage extends React.Component<ChatOpsProps, ChatOpsState> {
|
|||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { query } = this.props;
|
||||
const { query } = this.props; // eslint-disable-line
|
||||
|
||||
this.handleChatopsTabChange(query?.tab || ChatOpsTab.Slack);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -254,20 +254,23 @@ describe('PluginState.installPlugin', () => {
|
|||
onCallAPIResponse: mockedResponse,
|
||||
});
|
||||
|
||||
expect(PluginState.createGrafanaToken).toBeCalledTimes(1);
|
||||
expect(PluginState.createGrafanaToken).toBeCalledWith();
|
||||
expect(PluginState.createGrafanaToken).toHaveBeenCalledTimes(1);
|
||||
expect(PluginState.createGrafanaToken).toHaveBeenCalledWith();
|
||||
|
||||
expect(PluginState.updateGrafanaPluginSettings).toBeCalledTimes(1);
|
||||
expect(PluginState.updateGrafanaPluginSettings).toBeCalledWith({
|
||||
expect(PluginState.updateGrafanaPluginSettings).toHaveBeenCalledTimes(1);
|
||||
expect(PluginState.updateGrafanaPluginSettings).toHaveBeenCalledWith({
|
||||
secureJsonData: {
|
||||
grafanaToken,
|
||||
},
|
||||
});
|
||||
|
||||
expect(makeRequest).toBeCalledTimes(1);
|
||||
expect(makeRequest).toBeCalledWith(`${PluginState.ONCALL_BASE_URL}/${selfHosted ? 'self-hosted/' : ''}install`, {
|
||||
method: 'POST',
|
||||
});
|
||||
expect(makeRequest).toHaveBeenCalledTimes(1);
|
||||
expect(makeRequest).toHaveBeenCalledWith(
|
||||
`${PluginState.ONCALL_BASE_URL}/${selfHosted ? 'self-hosted/' : ''}install`,
|
||||
{
|
||||
method: 'POST',
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ export const getCoords = (elem) => {
|
|||
const body = document.body;
|
||||
const docEl = document.documentElement;
|
||||
|
||||
const scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
|
||||
const scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;
|
||||
const scrollTop = window.scrollY || docEl.scrollTop || body.scrollTop;
|
||||
const scrollLeft = window.scrollX || docEl.scrollLeft || body.scrollLeft;
|
||||
|
||||
const clientTop = docEl.clientTop || body.clientTop || 0;
|
||||
const clientLeft = docEl.clientLeft || body.clientLeft || 0;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { OnCallAppPluginMeta } from 'types';
|
||||
|
||||
//@ts-ignore
|
||||
import plugin from '../../package.json'; // eslint-disable-line
|
||||
|
||||
// Navbar
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { TimeOption, TimeRange, TimeZone, rangeUtil } from '@grafana/data';
|
||||
import { TimeOption, TimeRange, rangeUtil } from '@grafana/data';
|
||||
import { TimeZone } from '@grafana/schema';
|
||||
|
||||
// Valid mapping accepted by @grafana/ui and @grafana/data packages
|
||||
export const quickOptions = [
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
{
|
||||
"extends": "@grafana/toolkit/src/config/tsconfig.plugin.json",
|
||||
"extends": "./.config/tsconfig.json",
|
||||
"include": ["src", "e2e-tests", "playwright.config.ts"],
|
||||
"types": ["node", "@emotion/core"],
|
||||
"compilerOptions": {
|
||||
"rootDirs": ["src"],
|
||||
"baseUrl": "src",
|
||||
"rootDir": "",
|
||||
"typeRoots": ["./node_modules/@types"],
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
|
|
|
|||
|
|
@ -1,158 +0,0 @@
|
|||
const webpack = require('webpack');
|
||||
const path = require('path');
|
||||
const dotenv = require('dotenv');
|
||||
const LiveReloadPlugin = require('webpack-livereload-plugin');
|
||||
|
||||
const CircularDependencyPlugin = require('circular-dependency-plugin');
|
||||
|
||||
const MONACO_DIR = path.resolve(__dirname, './node_modules/monaco-editor');
|
||||
|
||||
Object.defineProperty(RegExp.prototype, 'toJSON', {
|
||||
value: RegExp.prototype.toString,
|
||||
});
|
||||
|
||||
dotenv.config({ path: path.resolve(__dirname, '.env') });
|
||||
|
||||
module.exports.getWebpackConfig = (config, options) => {
|
||||
const cssLoader = config.module.rules.find((rule) => rule.test.toString() === '/\\.css$/');
|
||||
|
||||
cssLoader.exclude.push(/\.module\.css$/, MONACO_DIR);
|
||||
|
||||
const grafanaRules = config.module.rules.filter((a) => a.test.toString() !== /\.s[ac]ss$/.toString());
|
||||
|
||||
const newConfig = {
|
||||
...config,
|
||||
module: {
|
||||
...config.module,
|
||||
rules: [
|
||||
...grafanaRules,
|
||||
|
||||
{
|
||||
test: /\.(ts|tsx)$/,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
cacheDirectory: true,
|
||||
cacheCompression: false,
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
modules: false,
|
||||
},
|
||||
],
|
||||
[
|
||||
'@babel/preset-typescript',
|
||||
{
|
||||
allowNamespaces: true,
|
||||
allowDeclareFields: true,
|
||||
},
|
||||
],
|
||||
['@babel/preset-react'],
|
||||
],
|
||||
plugins: [
|
||||
[
|
||||
'@babel/plugin-transform-typescript',
|
||||
{
|
||||
allowNamespaces: true,
|
||||
allowDeclareFields: true,
|
||||
},
|
||||
],
|
||||
'@babel/plugin-proposal-class-properties',
|
||||
[
|
||||
'@babel/plugin-proposal-object-rest-spread',
|
||||
{
|
||||
loose: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'@babel/plugin-proposal-decorators',
|
||||
{
|
||||
legacy: true,
|
||||
},
|
||||
],
|
||||
'@babel/plugin-transform-react-constant-elements',
|
||||
'@babel/plugin-proposal-nullish-coalescing-operator',
|
||||
'@babel/plugin-proposal-optional-chaining',
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
],
|
||||
},
|
||||
},
|
||||
'ts-loader',
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
test: /\.module\.css$/,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
'style-loader',
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
sourceMap: true,
|
||||
modules: {
|
||||
localIdentName: options.production ? '[name]__[hash:base64]' : '[path][name]__[local]',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
test: /\.module\.scss$/i,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
'style-loader',
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
sourceMap: true,
|
||||
modules: {
|
||||
localIdentName: options.production ? '[name]__[hash:base64]' : '[path][name]__[local]',
|
||||
},
|
||||
},
|
||||
},
|
||||
'postcss-loader',
|
||||
'sass-loader',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
plugins: [
|
||||
...config.plugins,
|
||||
new CircularDependencyPlugin({
|
||||
// exclude detection of files based on a RegExp
|
||||
exclude: /node_modules/,
|
||||
// include specific files based on a RegExp
|
||||
// add errors to webpack instead of warnings
|
||||
failOnError: true,
|
||||
// allow import cycles that include an asyncronous import,
|
||||
// e.g. via import(/* webpackMode: "weak" */ './file.js')
|
||||
allowAsyncCycles: false,
|
||||
// set the current working directory for displaying module paths
|
||||
cwd: process.cwd(),
|
||||
}),
|
||||
|
||||
/**
|
||||
* From docs (https://webpack.js.org/plugins/environment-plugin/):
|
||||
* Default values of null and undefined behave differently.
|
||||
* Use undefined for variables that must be provided during bundling, or null if they are optional.
|
||||
*/
|
||||
new webpack.EnvironmentPlugin({
|
||||
ONCALL_API_URL: null,
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': JSON.stringify(dotenv.config().parsed),
|
||||
}),
|
||||
...(options.production ? [] : [new LiveReloadPlugin({ appendScriptTag: true, useSourceHash: true })]),
|
||||
],
|
||||
};
|
||||
|
||||
return newConfig;
|
||||
};
|
||||
42
grafana-plugin/webpack.config.ts
Normal file
42
grafana-plugin/webpack.config.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import type { Configuration } from 'webpack';
|
||||
import { mergeWithRules, CustomizeRule } from 'webpack-merge';
|
||||
import grafanaConfig from './.config/webpack/webpack.config';
|
||||
|
||||
const config = async (env): Promise<Configuration> => {
|
||||
const baseConfig = await grafanaConfig(env);
|
||||
const customConfig = {
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.[tj]sx?$/,
|
||||
use: {
|
||||
options: {
|
||||
jsc: {
|
||||
parser: {
|
||||
decorators: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
watchOptions: {
|
||||
ignored: ['**/node_modules/', '**/dist'],
|
||||
},
|
||||
};
|
||||
|
||||
return mergeWithRules({
|
||||
module: {
|
||||
rules: {
|
||||
test: CustomizeRule.Match,
|
||||
use: CustomizeRule.Merge,
|
||||
},
|
||||
},
|
||||
watchOptions: {
|
||||
use: CustomizeRule.Merge,
|
||||
},
|
||||
})(baseConfig, customConfig);
|
||||
};
|
||||
|
||||
export default config;
|
||||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue