rozetko
2 years ago
34 changed files with 3910 additions and 525 deletions
@ -1,2 +0,0 @@ |
|||||||
export const SOURCE_DIR = 'src'; |
|
||||||
export const DIST_DIR = 'dist'; |
|
@ -1,9 +0,0 @@ |
|||||||
{ |
|
||||||
"compilerOptions": { |
|
||||||
"module": "commonjs", |
|
||||||
"target": "es5", |
|
||||||
"esModuleInterop": true |
|
||||||
}, |
|
||||||
"transpileOnly": true, |
|
||||||
"transpiler": "ts-node/transpilers/swc-experimental" |
|
||||||
} |
|
@ -1,42 +0,0 @@ |
|||||||
import fs from 'fs'; |
|
||||||
import path from 'path'; |
|
||||||
import util from 'util'; |
|
||||||
import glob from 'glob'; |
|
||||||
import { SOURCE_DIR } from './constants'; |
|
||||||
|
|
||||||
const globAsync = util.promisify(glob); |
|
||||||
|
|
||||||
export function getPackageJson() { |
|
||||||
return require(path.resolve(process.cwd(), 'package.json')); |
|
||||||
} |
|
||||||
|
|
||||||
export function getPluginId() { |
|
||||||
const { id } = require(path.resolve(process.cwd(), `${SOURCE_DIR}/plugin.json`)); |
|
||||||
|
|
||||||
return id; |
|
||||||
} |
|
||||||
|
|
||||||
export function hasReadme() { |
|
||||||
return fs.existsSync(path.resolve(process.cwd(), SOURCE_DIR, 'README.md')); |
|
||||||
} |
|
||||||
|
|
||||||
export async function getEntries(): Promise<Record<string, string>> { |
|
||||||
const parent = '..'; |
|
||||||
const pluginsJson = await globAsync('**/src/**/plugin.json'); |
|
||||||
|
|
||||||
const plugins = await Promise.all(pluginsJson.map(pluginJson => { |
|
||||||
const folder = path.dirname(pluginJson); |
|
||||||
return globAsync(`${folder}/module.{ts,tsx,js}`); |
|
||||||
})); |
|
||||||
|
|
||||||
return plugins.reduce((result, modules) => { |
|
||||||
return modules.reduce((result, module) => { |
|
||||||
const pluginPath = path.resolve(path.dirname(module), parent); |
|
||||||
const pluginName = path.basename(pluginPath); |
|
||||||
const entryName = plugins.length > 1 ? `${pluginName}/module` : 'module'; |
|
||||||
|
|
||||||
result[entryName] = path.join(parent, module); |
|
||||||
return result; |
|
||||||
}, result); |
|
||||||
}, {}); |
|
||||||
} |
|
@ -1,3 +1,4 @@ |
|||||||
node_modules |
node_modules |
||||||
dist |
dist |
||||||
.eslintcache |
.eslintcache |
||||||
|
yarn-error.log |
||||||
|
@ -0,0 +1,11 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<testsuites name="jest tests" tests="3" failures="0" errors="0" time="2.424"> |
||||||
|
<testsuite name="RemoveCurrentConfigurationButton" errors="0" failures="0" skipped="0" timestamp="2022-12-19T18:00:28" time="1.512" tests="3"> |
||||||
|
<testcase classname="RemoveCurrentConfigurationButton It renders properly when enabled" name="RemoveCurrentConfigurationButton It renders properly when enabled" time="0.022"> |
||||||
|
</testcase> |
||||||
|
<testcase classname="RemoveCurrentConfigurationButton It renders properly when disabled" name="RemoveCurrentConfigurationButton It renders properly when disabled" time="0.003"> |
||||||
|
</testcase> |
||||||
|
<testcase classname="RemoveCurrentConfigurationButton It calls the onClick handler when clicked" name="RemoveCurrentConfigurationButton It calls the onClick handler when clicked" time="0.164"> |
||||||
|
</testcase> |
||||||
|
</testsuite> |
||||||
|
</testsuites> |
@ -1,2 +0,0 @@ |
|||||||
// Jest setup provided by Grafana scaffolding
|
|
||||||
import './.config/jest-setup'; |
|
@ -1,4 +1,8 @@ |
|||||||
module.exports = { |
// This file is needed because it is used by vscode and other tools that
|
||||||
// Jest configuration provided by Grafana scaffolding
|
// call `jest` directly. However, unless you are doing anything special
|
||||||
...require('./.config/jest.config'), |
// do not edit this file
|
||||||
}; |
|
||||||
|
const standard = require('@grafana/toolkit/src/config/jest.plugin.config'); |
||||||
|
|
||||||
|
// This process will use the same config that `yarn test` is using
|
||||||
|
module.exports = standard.jestConfig(); |
||||||
|
@ -0,0 +1,4 @@ |
|||||||
|
export const getBackendSrv = () => ({ |
||||||
|
get: jest.fn(), |
||||||
|
post: jest.fn(), |
||||||
|
}); |
@ -1,32 +0,0 @@ |
|||||||
import React from 'react'; |
|
||||||
import { AppRootProps, PluginType } from '@grafana/data'; |
|
||||||
import { render, screen } from '@testing-library/react'; |
|
||||||
import { App } from './App'; |
|
||||||
|
|
||||||
describe('Components/App', () => { |
|
||||||
let props: AppRootProps; |
|
||||||
|
|
||||||
beforeEach(() => { |
|
||||||
jest.resetAllMocks(); |
|
||||||
|
|
||||||
props = { |
|
||||||
basename: 'a/sample-app', |
|
||||||
meta: { |
|
||||||
id: 'sample-app', |
|
||||||
name: 'Sample App', |
|
||||||
type: PluginType.app, |
|
||||||
enabled: true, |
|
||||||
jsonData: {}, |
|
||||||
}, |
|
||||||
query: {}, |
|
||||||
path: '', |
|
||||||
onNavChanged: jest.fn(), |
|
||||||
} as unknown as AppRootProps; |
|
||||||
}); |
|
||||||
|
|
||||||
test('renders without an error"', () => { |
|
||||||
render(<App {...props} />); |
|
||||||
|
|
||||||
expect(screen.queryByText(/Hello Grafana!/i)).toBeInTheDocument(); |
|
||||||
}); |
|
||||||
}); |
|
@ -1,8 +0,0 @@ |
|||||||
import * as React from 'react'; |
|
||||||
import { AppRootProps } from '@grafana/data'; |
|
||||||
|
|
||||||
export class App extends React.PureComponent<AppRootProps> { |
|
||||||
render() { |
|
||||||
return <div className="page-container">Hello Grafana!</div>; |
|
||||||
} |
|
||||||
} |
|
@ -1 +1,3 @@ |
|||||||
|
import '../../style/vars.css'; |
||||||
|
import '../../style/global.css'; |
||||||
export * from './PluginConfigPage'; |
export * from './PluginConfigPage'; |
||||||
|
@ -0,0 +1,36 @@ |
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP |
||||||
|
|
||||||
|
exports[`RemoveCurrentConfigurationButton It renders properly when disabled 1`] = ` |
||||||
|
<body> |
||||||
|
<div> |
||||||
|
<button |
||||||
|
class="css-mk7eo3-button" |
||||||
|
disabled="" |
||||||
|
type="button" |
||||||
|
> |
||||||
|
<span |
||||||
|
class="css-1mhnkuh" |
||||||
|
> |
||||||
|
Remove current configuration |
||||||
|
</span> |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
</body> |
||||||
|
`; |
||||||
|
|
||||||
|
exports[`RemoveCurrentConfigurationButton It renders properly when enabled 1`] = ` |
||||||
|
<body> |
||||||
|
<div> |
||||||
|
<button |
||||||
|
class="css-mk7eo3-button" |
||||||
|
type="button" |
||||||
|
> |
||||||
|
<span |
||||||
|
class="css-1mhnkuh" |
||||||
|
> |
||||||
|
Remove current configuration |
||||||
|
</span> |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
</body> |
||||||
|
`; |
@ -1,12 +0,0 @@ |
|||||||
import React from 'react'; |
|
||||||
|
|
||||||
import { render } from '@testing-library/react'; |
|
||||||
|
|
||||||
import StatusMessageBlock from '.'; |
|
||||||
|
|
||||||
describe('StatusMessageBlock', () => { |
|
||||||
test('It renders properly', async () => { |
|
||||||
const component = render(<StatusMessageBlock text="helloooo" />); |
|
||||||
expect(component.baseElement).toMatchSnapshot(); |
|
||||||
}); |
|
||||||
}); |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.8 KiB |
@ -0,0 +1,6 @@ |
|||||||
|
declare module '*.css'; |
||||||
|
|
||||||
|
declare module '*.scss' { |
||||||
|
const content: Record<string, string>; |
||||||
|
export default content; |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
// @ts-ignore
|
||||||
|
export default global.matchMedia = |
||||||
|
global.matchMedia || |
||||||
|
function (query) { |
||||||
|
return { |
||||||
|
matches: false, |
||||||
|
media: query, |
||||||
|
onchange: null, |
||||||
|
addListener: jest.fn(), |
||||||
|
removeListener: jest.fn(), |
||||||
|
addEventListener: jest.fn(), |
||||||
|
removeEventListener: jest.fn(), |
||||||
|
dispatchEvent: jest.fn(), |
||||||
|
}; |
||||||
|
}; |
@ -0,0 +1,8 @@ |
|||||||
|
module.exports = { |
||||||
|
process() { |
||||||
|
return { code: 'module.exports = {};' }; |
||||||
|
}, |
||||||
|
getCacheKey() { |
||||||
|
return 'svgTransform'; |
||||||
|
}, |
||||||
|
}; |
@ -0,0 +1,13 @@ |
|||||||
|
export function mockUseStore() { |
||||||
|
jest.mock('state/useStore', () => ({ |
||||||
|
useStore: () => ({ |
||||||
|
isUserActionAllowed: jest.fn().mockReturnValue(true), |
||||||
|
}), |
||||||
|
})); |
||||||
|
} |
||||||
|
|
||||||
|
export function mockGrafanaLocationSrv() { |
||||||
|
jest.mock('@grafana/runtime', () => ({ |
||||||
|
getLocationSrv: jest.fn(), |
||||||
|
})); |
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
.configure-plugin { |
||||||
|
margin-top: 10px; |
||||||
|
} |
||||||
|
|
||||||
|
@keyframes fadeIn { |
||||||
|
from { |
||||||
|
opacity: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Spinner */ |
||||||
|
|
||||||
|
.spin { |
||||||
|
width: 100%; |
||||||
|
margin-top: 200px; |
||||||
|
margin-bottom: 200px; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
|
||||||
|
.spin-text { |
||||||
|
margin-top: 20px; |
||||||
|
} |
||||||
|
|
||||||
|
/* Tables */ |
||||||
|
|
||||||
|
.disabled-row { |
||||||
|
background: #f0f0f0; |
||||||
|
} |
||||||
|
|
||||||
|
.highlighted-row { |
||||||
|
background: var(--highlighted-row-bg); |
||||||
|
} |
||||||
|
|
||||||
|
/* Navigation */ |
||||||
|
|
||||||
|
.navbarRootFallback { |
||||||
|
margin-top: 24px; |
||||||
|
} |
||||||
|
|
||||||
|
.page-title { |
||||||
|
margin-bottom: 16px; |
||||||
|
} |
@ -0,0 +1,78 @@ |
|||||||
|
:root { |
||||||
|
--maintenance-background: repeating-linear-gradient(45deg, #f6ba52, #f6ba52 20px, #ffd180 20px, #ffd180 40px); |
||||||
|
--gren-5: #6ccf8e; |
||||||
|
--green-6: #73d13d; |
||||||
|
--red-5: #ff4d4f; |
||||||
|
--orange-5: #ffa940; |
||||||
|
--blue-2: #bae7ff; |
||||||
|
--gray-5: #d9d9d9; |
||||||
|
--gray-8: #595959; |
||||||
|
--gray-9: #434343; |
||||||
|
--cyan-1: #e6fffb; |
||||||
|
--purple-9: #22075e; |
||||||
|
--border-radius: 2px; |
||||||
|
--gradient-brandHorizontal: linear-gradient(90deg, #f83 0%, #f53e4c 100%); |
||||||
|
--gradient-brandVertical: linear-gradient(0.01deg, #f53e4c -31.2%, #f83 113.07%); |
||||||
|
--always-gray: #ccccdc; |
||||||
|
--title-marginBottom: 16px; |
||||||
|
} |
||||||
|
|
||||||
|
.theme-light { |
||||||
|
--cards-background: var(--blue-2); |
||||||
|
--highlighted-row-bg: var(--cyan-1); |
||||||
|
--disabled-button-color: #bdbdbd; |
||||||
|
--primary-background: rgb(255, 255, 255); |
||||||
|
--secondary-background: rgb(244, 245, 245); |
||||||
|
--border: 1px solid rgba(36, 41, 46, 0.12); |
||||||
|
--primary-text-color: rgb(36, 41, 46); |
||||||
|
--secondary-text-color: rgba(36, 41, 46, 0.75); |
||||||
|
--disabled-text-color: rgba(36, 41, 46, 0.5); |
||||||
|
--warning-text-color: #8a6c00; |
||||||
|
--success-text-color: rgb(10, 118, 78); |
||||||
|
--error-text-color: rgb(207, 14, 91); |
||||||
|
--primary-text-link: #1f62e0; |
||||||
|
--timeline-icon-background: rgba(70, 76, 84, 0); |
||||||
|
--timeline-icon-background-resolution-note: rgba(50, 116, 217, 0); |
||||||
|
--oncall-icon-stroke-color: #fff; |
||||||
|
--hover-selected: #f4f5f5; |
||||||
|
--background-canvas: #f4f5f5; |
||||||
|
--background-primary: #fff; |
||||||
|
--background-secondary: #f4f5f5; |
||||||
|
--border-medium: 1px solid rgba(36, 41, 46, 0.3); |
||||||
|
--border-strong: 1px solid rgba(36, 41, 46, 0.4); |
||||||
|
--border-weak: 1px solid rgba(36, 41, 46, 0.12); |
||||||
|
--shadows-z1: 0 1px 2px rgba(24, 26, 27, 0.2); |
||||||
|
--shadows-z2: 0 4px 8px rgba(24, 26, 27, 0.2); |
||||||
|
--shadows-z3: 0 13px 20px 1px rgba(24, 26, 27, 0.18); |
||||||
|
} |
||||||
|
|
||||||
|
.theme-dark { |
||||||
|
--cards-background: var(--gray-9); |
||||||
|
--highlighted-row-bg: var(--gray-9); |
||||||
|
--disabled-button-color: hsla(0, 0%, 100%, 0.08); |
||||||
|
--primary-background: rgb(24, 27, 31); |
||||||
|
--secondary-background: rgb(34, 37, 43); |
||||||
|
--border: 1px solid rgba(204, 204, 220, 0.15); |
||||||
|
--primary-text-color: rgb(204, 204, 220); |
||||||
|
--secondary-text-color: rgba(204, 204, 220, 0.65); |
||||||
|
--disabled-text-color: rgba(204, 204, 220, 0.4); |
||||||
|
--warning-text-color: #f8d06b; |
||||||
|
--success-text-color: rgb(108, 207, 142); |
||||||
|
--error-text-color: rgb(255, 82, 134); |
||||||
|
--primary-text-link: #6e9fff; |
||||||
|
--timeline-icon-background: rgba(70, 76, 84, 1); |
||||||
|
--timeline-icon-background-resolution-note: rgba(50, 116, 217, 1); |
||||||
|
--focused-box-shadow: rgb(17 18 23) 0 0 0 2px, rgb(61 113 217) 0 0 0 4px; |
||||||
|
--hover-selected: rgba(204, 204, 220, 0.12); |
||||||
|
--hover-selected-hardcoded: #34363d; |
||||||
|
--oncall-icon-stroke-color: #181b1f; |
||||||
|
--background-canvas: #111217; |
||||||
|
--background-primary: #181b1f; |
||||||
|
--background-secondary: #22252b; |
||||||
|
--border-medium: 1px solid rgba(204, 204, 220, 0.15); |
||||||
|
--border-strong: 1px solid rgba(204, 204, 220, 0.25); |
||||||
|
--border-weak: 1px solid rgba(204, 204, 220, 0.07); |
||||||
|
--shadows-z1: 0 1px 2px rgba(24, 26, 27, 0.75); |
||||||
|
--shadows-z2: 0 4px 8px rgba(24, 26, 27, 0.75); |
||||||
|
--shadows-z3: 0 8px 24px rgb(1, 4, 9); |
||||||
|
} |
@ -0,0 +1,147 @@ |
|||||||
|
const webpack = require('webpack'); |
||||||
|
const path = require('path'); |
||||||
|
|
||||||
|
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, |
||||||
|
}); |
||||||
|
|
||||||
|
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(), |
||||||
|
}), |
||||||
|
], |
||||||
|
|
||||||
|
resolve: { |
||||||
|
...config.resolve, |
||||||
|
symlinks: false, |
||||||
|
modules: [path.resolve(__dirname, './frontend_enterprise/src'), ...config.resolve.modules], |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
return newConfig; |
||||||
|
}; |
Loading…
Reference in new issue