mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'grafana-lib'
This commit is contained in:
commit
66a13b281c
jest.config.jspackage.json
packages
grafana-build
grafana-ui
README.mdpackage.json
src
tsconfig.jsontslint.jsonpublic
app
core
features
alerting
api-keys
dashboard
dashgrid
time_srv.tsutils
datasources
explore
plugins
teams
users
plugins/panel
gauge
graph/specs
graph2
text2
types
viz
sass
scripts/grunt
tsconfig.jsonyarn.lock@ -6,7 +6,9 @@ module.exports = {
|
||||
},
|
||||
"moduleDirectories": ["node_modules", "public"],
|
||||
"roots": [
|
||||
"<rootDir>/public"
|
||||
"<rootDir>/public/app",
|
||||
"<rootDir>/public/test",
|
||||
"<rootDir>/packages"
|
||||
],
|
||||
"testRegex": "(\\.|/)(test)\\.(jsx?|tsx?)$",
|
||||
"moduleFileExtensions": [
|
||||
|
42
package.json
42
package.json
@ -1,4 +1,5 @@
|
||||
{
|
||||
"private": true,
|
||||
"author": {
|
||||
"name": "Torkel Ödegaard",
|
||||
"company": "Grafana Labs"
|
||||
@ -11,19 +12,21 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.1.2",
|
||||
"@rtsao/plugin-proposal-class-properties": "^7.0.1-patch.1",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/preset-typescript": "^7.1.0",
|
||||
"@rtsao/plugin-proposal-class-properties": "^7.0.1-patch.1",
|
||||
"@types/d3": "^4.10.1",
|
||||
"@types/enzyme": "^3.1.13",
|
||||
"@types/jest": "^23.3.2",
|
||||
"@types/jquery": "^1.10.35",
|
||||
"@types/node": "^8.0.31",
|
||||
"@types/react": "^16.7.6",
|
||||
"@types/react-custom-scrollbars": "^4.0.5",
|
||||
"@types/react-dom": "^16.0.9",
|
||||
"@types/react-select": "^2.0.4",
|
||||
"@types/classnames": "^2.2.6",
|
||||
"angular-mocks": "1.6.6",
|
||||
"autoprefixer": "^6.4.0",
|
||||
"axios": "^0.17.1",
|
||||
@ -92,6 +95,7 @@
|
||||
"tslib": "^1.9.3",
|
||||
"tslint": "^5.8.0",
|
||||
"tslint-loader": "^3.5.3",
|
||||
"tslint-react": "^3.6.0",
|
||||
"typescript": "^3.0.3",
|
||||
"uglifyjs-webpack-plugin": "^1.2.7",
|
||||
"webpack": "4.19.1",
|
||||
@ -108,15 +112,25 @@
|
||||
"watch": "webpack --progress --colors --watch --mode development --config scripts/webpack/webpack.dev.js",
|
||||
"build": "grunt build",
|
||||
"test": "grunt test",
|
||||
"lint": "tslint -c tslint.json --project tsconfig.json",
|
||||
"tslint": "tslint -c tslint.json --project tsconfig.json",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"jest": "jest --notify --watch",
|
||||
"api-tests": "jest --notify --watch --config=tests/api/jest.js",
|
||||
"precommit": "lint-staged && grunt precommit"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx}": ["prettier --write", "git add"],
|
||||
"*.scss": ["prettier --write", "git add"],
|
||||
"*pkg/**/*.go": ["gofmt -w -s", "git add"]
|
||||
"*.{ts,tsx}": [
|
||||
"prettier --write",
|
||||
"git add"
|
||||
],
|
||||
"*.scss": [
|
||||
"prettier --write",
|
||||
"git add"
|
||||
],
|
||||
"*pkg/**/*.go": [
|
||||
"gofmt -w -s",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"prettier": {
|
||||
"trailingComma": "es5",
|
||||
@ -126,6 +140,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@babel/polyfill": "^7.0.0",
|
||||
"@torkelo/react-select": "2.1.1",
|
||||
"angular": "1.6.6",
|
||||
"angular-bindonce": "0.3.1",
|
||||
"angular-native-dragdrop": "1.2.2",
|
||||
@ -133,7 +148,7 @@
|
||||
"angular-sanitize": "1.6.6",
|
||||
"baron": "^3.0.3",
|
||||
"brace": "^0.10.0",
|
||||
"classnames": "^2.2.5",
|
||||
"classnames": "^2.2.6",
|
||||
"clipboard": "^1.7.1",
|
||||
"d3": "^4.11.0",
|
||||
"d3-scale-chromatic": "^1.3.0",
|
||||
@ -152,10 +167,9 @@
|
||||
"react-custom-scrollbars": "^4.2.1",
|
||||
"react-dom": "^16.6.3",
|
||||
"react-grid-layout": "0.16.6",
|
||||
"react-popper": "^1.3.0",
|
||||
"react-highlight-words": "0.11.0",
|
||||
"react-popper": "^1.3.0",
|
||||
"react-redux": "^5.0.7",
|
||||
"@torkelo/react-select": "2.1.1",
|
||||
"react-sizeme": "^2.3.6",
|
||||
"react-table": "^6.8.6",
|
||||
"react-transition-group": "^2.2.1",
|
||||
@ -172,11 +186,19 @@
|
||||
"slate-react": "^0.12.4",
|
||||
"tether": "^1.4.0",
|
||||
"tether-drop": "https://github.com/torkelo/drop/tarball/master",
|
||||
"tinycolor2": "^1.4.1",
|
||||
"tslint-react": "^3.6.0"
|
||||
"tinycolor2": "^1.4.1"
|
||||
},
|
||||
"resolutions": {
|
||||
"caniuse-db": "1.0.30000772",
|
||||
"**/@types/react": "16.7.6"
|
||||
},
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"nohoist": [
|
||||
"**/@types/*",
|
||||
"**/@types/*/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
4
packages/grafana-build/README.md
Normal file
4
packages/grafana-build/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Shared build scripts
|
||||
|
||||
Shared build scripts for plugins & internal packages.
|
||||
|
13
packages/grafana-build/package.json
Normal file
13
packages/grafana-build/package.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "@grafana/build",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"tslint": "echo \"Nothing to do\"",
|
||||
"typecheck": "echo \"Nothing to do\""
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
3
packages/grafana-ui/README.md
Normal file
3
packages/grafana-ui/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Grafana (WIP) shared component library
|
||||
|
||||
Used by internal & external plugins.
|
33
packages/grafana-ui/package.json
Normal file
33
packages/grafana-ui/package.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "@grafana/ui",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "src/index.ts",
|
||||
"scripts": {
|
||||
"tslint": "tslint -c tslint.json --project tsconfig.json",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@torkelo/react-select": "2.1.1",
|
||||
"classnames": "^2.2.5",
|
||||
"jquery": "^3.2.1",
|
||||
"lodash": "^4.17.10",
|
||||
"moment": "^2.22.2",
|
||||
"react": "^16.6.3",
|
||||
"react-dom": "^16.6.3",
|
||||
"react-highlight-words": "0.11.0",
|
||||
"react-popper": "^1.3.0",
|
||||
"react-transition-group": "^2.2.1",
|
||||
"react-virtualized": "^9.21.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^23.3.2",
|
||||
"@types/lodash": "^4.14.119",
|
||||
"@types/react": "^16.7.6",
|
||||
"@types/classnames": "^2.2.6",
|
||||
"@types/jquery": "^1.10.35",
|
||||
"typescript": "^3.2.2"
|
||||
}
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
import React from 'react';
|
||||
import DeleteButton from './DeleteButton';
|
||||
import { DeleteButton } from './DeleteButton';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
describe('DeleteButton', () => {
|
||||
let wrapper;
|
||||
let deleted;
|
||||
let wrapper: any;
|
||||
let deleted: any;
|
||||
|
||||
beforeAll(() => {
|
||||
deleted = false;
|
||||
@ -12,7 +12,8 @@ describe('DeleteButton', () => {
|
||||
function deleteItem() {
|
||||
deleted = true;
|
||||
}
|
||||
wrapper = shallow(<DeleteButton onConfirmDelete={() => deleteItem()} />);
|
||||
|
||||
wrapper = shallow(<DeleteButton onConfirm={() => deleteItem()} />);
|
||||
});
|
||||
|
||||
it('should show confirm delete when clicked', () => {
|
@ -1,19 +1,19 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import React, { PureComponent, SyntheticEvent } from 'react';
|
||||
|
||||
export interface DeleteButtonProps {
|
||||
onConfirmDelete();
|
||||
interface Props {
|
||||
onConfirm(): void;
|
||||
}
|
||||
|
||||
export interface DeleteButtonStates {
|
||||
interface State {
|
||||
showConfirm: boolean;
|
||||
}
|
||||
|
||||
export default class DeleteButton extends PureComponent<DeleteButtonProps, DeleteButtonStates> {
|
||||
state: DeleteButtonStates = {
|
||||
export class DeleteButton extends PureComponent<Props, State> {
|
||||
state: State = {
|
||||
showConfirm: false,
|
||||
};
|
||||
|
||||
onClickDelete = event => {
|
||||
onClickDelete = (event: SyntheticEvent) => {
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
@ -23,7 +23,7 @@ export default class DeleteButton extends PureComponent<DeleteButtonProps, Delet
|
||||
});
|
||||
};
|
||||
|
||||
onClickCancel = event => {
|
||||
onClickCancel = (event: SyntheticEvent) => {
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
@ -33,7 +33,7 @@ export default class DeleteButton extends PureComponent<DeleteButtonProps, Delet
|
||||
};
|
||||
|
||||
render() {
|
||||
const onClickConfirm = this.props.onConfirmDelete;
|
||||
const { onConfirm } = this.props;
|
||||
let showConfirm;
|
||||
let showDeleteButton;
|
||||
|
||||
@ -55,7 +55,7 @@ export default class DeleteButton extends PureComponent<DeleteButtonProps, Delet
|
||||
<a className="btn btn-small" onClick={this.onClickCancel}>
|
||||
Cancel
|
||||
</a>
|
||||
<a className="btn btn-danger btn-small" onClick={onClickConfirm}>
|
||||
<a className="btn btn-danger btn-small" onClick={onConfirm}>
|
||||
Confirm Delete
|
||||
</a>
|
||||
</span>
|
1
packages/grafana-ui/src/components/index.scss
Normal file
1
packages/grafana-ui/src/components/index.scss
Normal file
@ -0,0 +1 @@
|
||||
@import 'DeleteButton/DeleteButton';
|
1
packages/grafana-ui/src/components/index.ts
Normal file
1
packages/grafana-ui/src/components/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { DeleteButton } from './DeleteButton/DeleteButton';
|
23
packages/grafana-ui/src/forms/GfFormLabel/GfFormLabel.tsx
Normal file
23
packages/grafana-ui/src/forms/GfFormLabel/GfFormLabel.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import React, { SFC, ReactNode } from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
htmlFor?: string;
|
||||
className?: string;
|
||||
isFocused?: boolean;
|
||||
isInvalid?: boolean;
|
||||
}
|
||||
|
||||
export const GfFormLabel: SFC<Props> = ({ children, isFocused, isInvalid, className, htmlFor, ...rest }) => {
|
||||
const classes = classNames('gf-form-label', className, {
|
||||
'gf-form-label--is-focused': isFocused,
|
||||
'gf-form-label--is-invalid': isInvalid,
|
||||
});
|
||||
|
||||
return (
|
||||
<label className={classes} {...rest} htmlFor={htmlFor}>
|
||||
{children}
|
||||
</label>
|
||||
);
|
||||
};
|
1
packages/grafana-ui/src/forms/index.ts
Normal file
1
packages/grafana-ui/src/forms/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { GfFormLabel } from './GfFormLabel/GfFormLabel';
|
1
packages/grafana-ui/src/index.scss
Normal file
1
packages/grafana-ui/src/index.scss
Normal file
@ -0,0 +1 @@
|
||||
@import 'components/index';
|
5
packages/grafana-ui/src/index.ts
Normal file
5
packages/grafana-ui/src/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export * from './components';
|
||||
export * from './visualizations';
|
||||
export * from './types';
|
||||
export * from './utils';
|
||||
export * from './forms';
|
3
packages/grafana-ui/src/types/index.ts
Normal file
3
packages/grafana-ui/src/types/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './series';
|
||||
export * from './time';
|
||||
export * from './panel';
|
17
packages/grafana-ui/src/types/jquery.d.ts
vendored
Normal file
17
packages/grafana-ui/src/types/jquery.d.ts
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
interface JQueryPlot {
|
||||
(element: HTMLElement | JQuery, data: any, options: any): void;
|
||||
plugins: any[];
|
||||
}
|
||||
|
||||
interface JQueryStatic {
|
||||
plot: JQueryPlot;
|
||||
}
|
||||
|
||||
interface JQuery {
|
||||
place_tt: any;
|
||||
modal: any;
|
||||
tagsinput: any;
|
||||
typeahead: any;
|
||||
accessKey: any;
|
||||
tooltip: any;
|
||||
}
|
31
packages/grafana-ui/src/types/panel.ts
Normal file
31
packages/grafana-ui/src/types/panel.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { TimeSeries, LoadingState } from './series';
|
||||
import { TimeRange } from './time';
|
||||
|
||||
export interface PanelProps<T = any> {
|
||||
timeSeries: TimeSeries[];
|
||||
timeRange: TimeRange;
|
||||
loading: LoadingState;
|
||||
options: T;
|
||||
renderCounter: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface PanelOptionsProps<T = any> {
|
||||
options: T;
|
||||
onChange: (options: T) => void;
|
||||
}
|
||||
|
||||
export interface PanelSize {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface PanelMenuItem {
|
||||
type?: 'submenu' | 'divider';
|
||||
text?: string;
|
||||
iconClassName?: string;
|
||||
onClick?: () => void;
|
||||
shortcut?: string;
|
||||
subMenu?: PanelMenuItem[];
|
||||
}
|
53
packages/grafana-ui/src/types/series.ts
Normal file
53
packages/grafana-ui/src/types/series.ts
Normal file
@ -0,0 +1,53 @@
|
||||
export enum LoadingState {
|
||||
NotStarted = 'NotStarted',
|
||||
Loading = 'Loading',
|
||||
Done = 'Done',
|
||||
Error = 'Error',
|
||||
}
|
||||
|
||||
export type TimeSeriesValue = number | null;
|
||||
|
||||
export type TimeSeriesPoints = TimeSeriesValue[][];
|
||||
|
||||
export interface TimeSeries {
|
||||
target: string;
|
||||
datapoints: TimeSeriesPoints;
|
||||
unit?: string;
|
||||
}
|
||||
|
||||
/** View model projection of a time series */
|
||||
export interface TimeSeriesVM {
|
||||
label: string;
|
||||
color: string;
|
||||
data: TimeSeriesValue[][];
|
||||
stats: TimeSeriesStats;
|
||||
}
|
||||
|
||||
export interface TimeSeriesStats {
|
||||
total: number | null;
|
||||
max: number | null;
|
||||
min: number | null;
|
||||
logmin: number;
|
||||
avg: number | null;
|
||||
current: number | null;
|
||||
first: number | null;
|
||||
delta: number;
|
||||
diff: number | null;
|
||||
range: number | null;
|
||||
timeStep: number;
|
||||
count: number;
|
||||
allIsNull: boolean;
|
||||
allIsZero: boolean;
|
||||
}
|
||||
|
||||
export enum NullValueMode {
|
||||
Null = 'null',
|
||||
Ignore = 'connected',
|
||||
AsZero = 'null as zero',
|
||||
}
|
||||
|
||||
/** View model projection of many time series */
|
||||
export interface TimeSeriesVMs {
|
||||
[index: number]: TimeSeriesVM;
|
||||
length: number;
|
||||
}
|
17
packages/grafana-ui/src/types/time.ts
Normal file
17
packages/grafana-ui/src/types/time.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { Moment } from 'moment';
|
||||
|
||||
export interface RawTimeRange {
|
||||
from: Moment | string;
|
||||
to: Moment | string;
|
||||
}
|
||||
|
||||
export interface TimeRange {
|
||||
from: Moment;
|
||||
to: Moment;
|
||||
raw: RawTimeRange;
|
||||
}
|
||||
|
||||
export interface IntervalValues {
|
||||
interval: string; // 10s,5m
|
||||
intervalMs: number;
|
||||
}
|
1
packages/grafana-ui/src/utils/index.ts
Normal file
1
packages/grafana-ui/src/utils/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './processTimeSeries';
|
174
packages/grafana-ui/src/utils/processTimeSeries.ts
Normal file
174
packages/grafana-ui/src/utils/processTimeSeries.ts
Normal file
@ -0,0 +1,174 @@
|
||||
// Libraries
|
||||
import _ from 'lodash';
|
||||
|
||||
// Types
|
||||
import { TimeSeries, TimeSeriesVMs, NullValueMode, TimeSeriesValue } from '../types';
|
||||
|
||||
interface Options {
|
||||
timeSeries: TimeSeries[];
|
||||
nullValueMode: NullValueMode;
|
||||
colorPalette: string[];
|
||||
}
|
||||
|
||||
export function processTimeSeries({ timeSeries, nullValueMode, colorPalette }: Options): TimeSeriesVMs {
|
||||
const vmSeries = timeSeries.map((item, index) => {
|
||||
const colorIndex = index % colorPalette.length;
|
||||
const label = item.target;
|
||||
const result = [];
|
||||
|
||||
// stat defaults
|
||||
let total = 0;
|
||||
let max: TimeSeriesValue = -Number.MAX_VALUE;
|
||||
let min: TimeSeriesValue = Number.MAX_VALUE;
|
||||
let logmin = Number.MAX_VALUE;
|
||||
let avg: TimeSeriesValue = null;
|
||||
let current: TimeSeriesValue = null;
|
||||
let first: TimeSeriesValue = null;
|
||||
let delta: TimeSeriesValue = 0;
|
||||
let diff: TimeSeriesValue = null;
|
||||
let range: TimeSeriesValue = null;
|
||||
let timeStep = Number.MAX_VALUE;
|
||||
let allIsNull = true;
|
||||
let allIsZero = true;
|
||||
|
||||
const ignoreNulls = nullValueMode === NullValueMode.Ignore;
|
||||
const nullAsZero = nullValueMode === NullValueMode.AsZero;
|
||||
|
||||
let currentTime: TimeSeriesValue = null;
|
||||
let currentValue: TimeSeriesValue = null;
|
||||
let nonNulls = 0;
|
||||
let previousTime: TimeSeriesValue = null;
|
||||
let previousValue = 0;
|
||||
let previousDeltaUp = true;
|
||||
|
||||
for (let i = 0; i < item.datapoints.length; i++) {
|
||||
currentValue = item.datapoints[i][0];
|
||||
currentTime = item.datapoints[i][1];
|
||||
|
||||
if (typeof currentTime !== 'number') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (typeof currentValue !== 'number') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Due to missing values we could have different timeStep all along the series
|
||||
// so we have to find the minimum one (could occur with aggregators such as ZimSum)
|
||||
if (previousTime !== null && currentTime !== null) {
|
||||
const currentStep = currentTime - previousTime;
|
||||
if (currentStep < timeStep) {
|
||||
timeStep = currentStep;
|
||||
}
|
||||
}
|
||||
|
||||
previousTime = currentTime;
|
||||
|
||||
if (currentValue === null) {
|
||||
if (ignoreNulls) {
|
||||
continue;
|
||||
}
|
||||
if (nullAsZero) {
|
||||
currentValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentValue !== null) {
|
||||
if (_.isNumber(currentValue)) {
|
||||
total += currentValue;
|
||||
allIsNull = false;
|
||||
nonNulls++;
|
||||
}
|
||||
|
||||
if (currentValue > max) {
|
||||
max = currentValue;
|
||||
}
|
||||
|
||||
if (currentValue < min) {
|
||||
min = currentValue;
|
||||
}
|
||||
|
||||
if (first === null) {
|
||||
first = currentValue;
|
||||
} else {
|
||||
if (previousValue > currentValue) {
|
||||
// counter reset
|
||||
previousDeltaUp = false;
|
||||
if (i === item.datapoints.length - 1) {
|
||||
// reset on last
|
||||
delta += currentValue;
|
||||
}
|
||||
} else {
|
||||
if (previousDeltaUp) {
|
||||
delta += currentValue - previousValue; // normal increment
|
||||
} else {
|
||||
delta += currentValue; // account for counter reset
|
||||
}
|
||||
previousDeltaUp = true;
|
||||
}
|
||||
}
|
||||
previousValue = currentValue;
|
||||
|
||||
if (currentValue < logmin && currentValue > 0) {
|
||||
logmin = currentValue;
|
||||
}
|
||||
|
||||
if (currentValue !== 0) {
|
||||
allIsZero = false;
|
||||
}
|
||||
}
|
||||
|
||||
result.push([currentTime, currentValue]);
|
||||
}
|
||||
|
||||
if (max === -Number.MAX_VALUE) {
|
||||
max = null;
|
||||
}
|
||||
|
||||
if (min === Number.MAX_VALUE) {
|
||||
min = null;
|
||||
}
|
||||
|
||||
if (result.length && !allIsNull) {
|
||||
avg = total / nonNulls;
|
||||
current = result[result.length - 1][1];
|
||||
if (current === null && result.length > 1) {
|
||||
current = result[result.length - 2][1];
|
||||
}
|
||||
}
|
||||
|
||||
if (max !== null && min !== null) {
|
||||
range = max - min;
|
||||
}
|
||||
|
||||
if (current !== null && first !== null) {
|
||||
diff = current - first;
|
||||
}
|
||||
|
||||
const count = result.length;
|
||||
|
||||
return {
|
||||
data: result,
|
||||
label: label,
|
||||
color: colorPalette[colorIndex],
|
||||
stats: {
|
||||
total,
|
||||
min,
|
||||
max,
|
||||
current,
|
||||
logmin,
|
||||
avg,
|
||||
diff,
|
||||
delta,
|
||||
timeStep,
|
||||
range,
|
||||
count,
|
||||
first,
|
||||
allIsZero,
|
||||
allIsNull,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return vmSeries;
|
||||
}
|
@ -1,11 +1,9 @@
|
||||
// Libraries
|
||||
import $ from 'jquery';
|
||||
import React, { PureComponent } from 'react';
|
||||
import 'vendor/flot/jquery.flot';
|
||||
import 'vendor/flot/jquery.flot.time';
|
||||
|
||||
// Types
|
||||
import { TimeRange, TimeSeriesVMs } from 'app/types';
|
||||
import { TimeRange, TimeSeriesVMs } from '../../types';
|
||||
|
||||
interface GraphProps {
|
||||
timeSeries: TimeSeriesVMs;
|
||||
@ -24,7 +22,7 @@ export class Graph extends PureComponent<GraphProps> {
|
||||
showBars: false,
|
||||
};
|
||||
|
||||
element: HTMLElement;
|
||||
element: HTMLElement | null;
|
||||
|
||||
componentDidUpdate() {
|
||||
this.draw();
|
||||
@ -35,6 +33,10 @@ export class Graph extends PureComponent<GraphProps> {
|
||||
}
|
||||
|
||||
draw() {
|
||||
if (this.element === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { width, timeSeries, timeRange, showLines, showBars, showPoints } = this.props;
|
||||
|
||||
if (!width) {
|
||||
@ -76,7 +78,7 @@ export class Graph extends PureComponent<GraphProps> {
|
||||
max: max,
|
||||
label: 'Datetime',
|
||||
ticks: ticks,
|
||||
timeformat: time_format(ticks, min, max),
|
||||
timeformat: timeFormat(ticks, min, max),
|
||||
},
|
||||
grid: {
|
||||
minBorderMargin: 0,
|
||||
@ -109,7 +111,7 @@ export class Graph extends PureComponent<GraphProps> {
|
||||
}
|
||||
|
||||
// Copied from graph.ts
|
||||
function time_format(ticks, min, max) {
|
||||
function timeFormat(ticks: number, min: number, max: number): string {
|
||||
if (min && max && ticks) {
|
||||
const range = max - min;
|
||||
const secPerTick = range / ticks / 1000;
|
1
packages/grafana-ui/src/visualizations/index.ts
Normal file
1
packages/grafana-ui/src/visualizations/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { Graph } from './Graph/Graph';
|
18
packages/grafana-ui/tsconfig.json
Normal file
18
packages/grafana-ui/tsconfig.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"dist"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"rootDir": ".",
|
||||
"module": "esnext",
|
||||
"outDir": "dist",
|
||||
"declaration": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true
|
||||
}
|
||||
}
|
3
packages/grafana-ui/tslint.json
Normal file
3
packages/grafana-ui/tslint.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "../../tslint.json"
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
import React, { PureComponent, ReactNode, ReactElement } from 'react';
|
||||
import { Label } from './Label';
|
||||
import { uniqueId } from 'lodash';
|
||||
|
||||
interface Props {
|
||||
label?: ReactNode;
|
||||
labelClassName?: string;
|
||||
id?: string;
|
||||
children: ReactElement<any>;
|
||||
}
|
||||
|
||||
export class Element extends PureComponent<Props> {
|
||||
elementId: string = this.props.id || uniqueId('form-element-');
|
||||
|
||||
get elementLabel() {
|
||||
const { label, labelClassName } = this.props;
|
||||
|
||||
if (label) {
|
||||
return (
|
||||
<Label htmlFor={this.elementId} className={labelClassName}>
|
||||
{label}
|
||||
</Label>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
get children() {
|
||||
const { children } = this.props;
|
||||
|
||||
return React.cloneElement(children, { id: this.elementId });
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="our-custom-wrapper-class">
|
||||
{this.elementLabel}
|
||||
{this.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
import React, { PureComponent, ReactNode } from 'react';
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
htmlFor?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export class Label extends PureComponent<Props> {
|
||||
render() {
|
||||
const { children, htmlFor, className } = this.props;
|
||||
|
||||
return (
|
||||
<label className={`custom-label-class ${className || ''}`} htmlFor={htmlFor}>
|
||||
{children}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,3 +1 @@
|
||||
export { Element } from './Element';
|
||||
export { Input } from './Input';
|
||||
export { Label } from './Label';
|
||||
|
@ -69,7 +69,7 @@ function bootstrapTagsinput() {
|
||||
},
|
||||
});
|
||||
|
||||
select.on('itemAdded', event => {
|
||||
select.on('itemAdded', (event: any) => {
|
||||
if (scope.model.indexOf(event.item) === -1) {
|
||||
scope.model.push(event.item);
|
||||
if (scope.onTagsUpdated) {
|
||||
@ -85,7 +85,7 @@ function bootstrapTagsinput() {
|
||||
setColor(event.item, tagElement);
|
||||
});
|
||||
|
||||
select.on('itemRemoved', event => {
|
||||
select.on('itemRemoved', (event: any) => {
|
||||
const idx = scope.model.indexOf(event.item);
|
||||
if (idx !== -1) {
|
||||
scope.model.splice(idx, 1);
|
||||
|
@ -9,7 +9,8 @@ import { parse as parseDate } from 'app/core/utils/datemath';
|
||||
import TimeSeries from 'app/core/time_series2';
|
||||
import TableModel, { mergeTablesIntoModel } from 'app/core/table_model';
|
||||
import { ExploreState, ExploreUrlState, HistoryItem, QueryTransaction } from 'app/types/explore';
|
||||
import { DataQuery, RawTimeRange, IntervalValues, DataSourceApi } from 'app/types/series';
|
||||
import { DataQuery, DataSourceApi } from 'app/types/series';
|
||||
import { RawTimeRange, IntervalValues } from '@grafana/ui';
|
||||
|
||||
export const DEFAULT_RANGE = {
|
||||
from: 'now-6h',
|
||||
|
@ -1,7 +1,7 @@
|
||||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
|
||||
import { RawTimeRange } from 'app/types/series';
|
||||
import { RawTimeRange } from '@grafana/ui';
|
||||
|
||||
import * as dateMath from './datemath';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import Highlighter from 'react-highlight-words';
|
||||
import classNames from 'classnames/bind';
|
||||
import classNames from 'classnames';
|
||||
import { AlertRule } from '../../types';
|
||||
|
||||
export interface Props {
|
||||
@ -23,7 +23,7 @@ class AlertRuleItem extends PureComponent<Props> {
|
||||
render() {
|
||||
const { rule, onTogglePause } = this.props;
|
||||
|
||||
const stateClass = classNames({
|
||||
const iconClassName = classNames({
|
||||
fa: true,
|
||||
'fa-play': rule.state === 'paused',
|
||||
'fa-pause': rule.state !== 'paused',
|
||||
@ -55,7 +55,7 @@ class AlertRuleItem extends PureComponent<Props> {
|
||||
title="Pausing an alert rule prevents it from executing"
|
||||
onClick={onTogglePause}
|
||||
>
|
||||
<i className={stateClass} />
|
||||
<i className={iconClassName} />
|
||||
</button>
|
||||
<a className="btn btn-small btn-inverse alert-list__btn width-2" href={ruleUrl} title="Edit alert rule">
|
||||
<i className="icon-gf icon-gf-settings" />
|
||||
|
@ -13,7 +13,7 @@ import ApiKeysAddedModal from './ApiKeysAddedModal';
|
||||
import config from 'app/core/config';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
|
||||
import DeleteButton from 'app/core/components/DeleteButton/DeleteButton';
|
||||
import { DeleteButton } from '@grafana/ui';
|
||||
|
||||
export interface Props {
|
||||
navModel: NavModel;
|
||||
@ -224,7 +224,7 @@ export class ApiKeysPage extends PureComponent<Props, any> {
|
||||
<td>{key.name}</td>
|
||||
<td>{key.role}</td>
|
||||
<td>
|
||||
<DeleteButton onConfirmDelete={() => this.onDeleteApiKey(key)} />
|
||||
<DeleteButton onConfirm={() => this.onDeleteApiKey(key)} />
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
|
@ -8,7 +8,8 @@ import { getDatasourceSrv, DatasourceSrv } from 'app/features/plugins/datasource
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
|
||||
// Types
|
||||
import { TimeRange, LoadingState, DataQueryOptions, DataQueryResponse, TimeSeries } from 'app/types';
|
||||
import { DataQueryOptions, DataQueryResponse } from 'app/types';
|
||||
import { TimeRange, TimeSeries, LoadingState } from '@grafana/ui';
|
||||
|
||||
interface RenderProps {
|
||||
loading: LoadingState;
|
||||
|
@ -16,7 +16,8 @@ import { PANEL_HEADER_HEIGHT } from 'app/core/constants';
|
||||
// Types
|
||||
import { PanelModel } from '../panel_model';
|
||||
import { DashboardModel } from '../dashboard_model';
|
||||
import { PanelPlugin, TimeRange } from 'app/types';
|
||||
import { PanelPlugin } from 'app/types';
|
||||
import { TimeRange } from '@grafana/ui';
|
||||
|
||||
export interface Props {
|
||||
panel: PanelModel;
|
||||
|
@ -3,7 +3,7 @@ import { DashboardModel } from 'app/features/dashboard/dashboard_model';
|
||||
import { PanelModel } from 'app/features/dashboard/panel_model';
|
||||
import { PanelHeaderMenuItem } from './PanelHeaderMenuItem';
|
||||
import { getPanelMenu } from 'app/features/dashboard/utils/getPanelMenu';
|
||||
import { PanelMenuItem } from 'app/types/panel';
|
||||
import { PanelMenuItem } from '@grafana/ui';
|
||||
|
||||
export interface Props {
|
||||
panel: PanelModel;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { SFC } from 'react';
|
||||
import { PanelMenuItem } from 'app/types/panel';
|
||||
import { PanelMenuItem } from '@grafana/ui';
|
||||
|
||||
interface Props {
|
||||
children: any;
|
||||
|
@ -1,6 +1,10 @@
|
||||
// Libraries
|
||||
import _ from 'lodash';
|
||||
import React, { PureComponent } from 'react';
|
||||
import { PanelPlugin, PanelProps } from 'app/types';
|
||||
|
||||
// Types
|
||||
import { PanelProps } from '@grafana/ui';
|
||||
import { PanelPlugin } from 'app/types';
|
||||
|
||||
interface Props {
|
||||
pluginId: string;
|
||||
|
@ -10,6 +10,7 @@ import { Input } from 'app/core/components/Form';
|
||||
import { EventsWithValidation } from 'app/core/components/Form/Input';
|
||||
import { InputStatus } from 'app/core/components/Form/Input';
|
||||
import DataSourceOption from './DataSourceOption';
|
||||
import { GfFormLabel } from '@grafana/ui';
|
||||
|
||||
// Types
|
||||
import { PanelModel } from '../panel_model';
|
||||
@ -163,7 +164,7 @@ export class QueryOptions extends PureComponent<Props, State> {
|
||||
{this.renderOptions()}
|
||||
|
||||
<div className="gf-form">
|
||||
<span className="gf-form-label">Relative time</span>
|
||||
<GfFormLabel>Relative time</GfFormLabel>
|
||||
<Input
|
||||
type="text"
|
||||
className="width-6"
|
||||
|
@ -6,9 +6,9 @@ import _ from 'lodash';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import coreModule from 'app/core/core_module';
|
||||
import * as dateMath from 'app/core/utils/datemath';
|
||||
// Types
|
||||
|
||||
import { TimeRange } from 'app/types';
|
||||
// Types
|
||||
import { TimeRange } from '@grafana/ui';
|
||||
|
||||
export class TimeSrv {
|
||||
time: any;
|
||||
|
@ -4,7 +4,7 @@ import { store } from 'app/store/store';
|
||||
import { removePanel, duplicatePanel, copyPanel, editPanelJson, sharePanel } from 'app/features/dashboard/utils/panel';
|
||||
import { PanelModel } from 'app/features/dashboard/panel_model';
|
||||
import { DashboardModel } from 'app/features/dashboard/dashboard_model';
|
||||
import { PanelMenuItem } from 'app/types/panel';
|
||||
import { PanelMenuItem } from '@grafana/ui';
|
||||
|
||||
export const getPanelMenu = (dashboard: DashboardModel, panel: PanelModel) => {
|
||||
const onViewPanel = () => {
|
||||
|
@ -4,7 +4,7 @@ import store from 'app/core/store';
|
||||
// Models
|
||||
import { DashboardModel } from 'app/features/dashboard/dashboard_model';
|
||||
import { PanelModel } from 'app/features/dashboard/panel_model';
|
||||
import { TimeRange } from 'app/types/series';
|
||||
import { TimeRange } from '@grafana/ui';
|
||||
|
||||
// Utils
|
||||
import { isString as _isString } from 'lodash';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import classNames from 'classnames/bind';
|
||||
import classNames from 'classnames';
|
||||
import DataSourcesListItem from './DataSourcesListItem';
|
||||
import { DataSource } from 'app/types';
|
||||
import { LayoutMode, LayoutModes } from '../../core/components/LayoutSelector/LayoutSelector';
|
||||
|
@ -11,7 +11,8 @@ import {
|
||||
QueryHintGetter,
|
||||
QueryHint,
|
||||
} from 'app/types/explore';
|
||||
import { TimeRange, DataQuery } from 'app/types/series';
|
||||
import { TimeRange } from '@grafana/ui';
|
||||
import { DataQuery } from 'app/types/series';
|
||||
import store from 'app/core/store';
|
||||
import {
|
||||
DEFAULT_RANGE,
|
||||
|
@ -8,7 +8,7 @@ import 'vendor/flot/jquery.flot.time';
|
||||
import 'vendor/flot/jquery.flot.selection';
|
||||
import 'vendor/flot/jquery.flot.stack';
|
||||
|
||||
import { RawTimeRange } from 'app/types/series';
|
||||
import { RawTimeRange } from '@grafana/ui';
|
||||
import * as dateMath from 'app/core/utils/datemath';
|
||||
import TimeSeries from 'app/core/time_series2';
|
||||
|
||||
|
@ -4,7 +4,7 @@ import Highlighter from 'react-highlight-words';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import * as rangeUtil from 'app/core/utils/rangeutil';
|
||||
import { RawTimeRange } from 'app/types/series';
|
||||
import { RawTimeRange } from '@grafana/ui';
|
||||
import {
|
||||
LogsDedupDescription,
|
||||
LogsDedupStrategy,
|
||||
|
@ -3,7 +3,7 @@ import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoa
|
||||
import { Emitter } from 'app/core/utils/emitter';
|
||||
import { getIntervals } from 'app/core/utils/explore';
|
||||
import { DataQuery } from 'app/types';
|
||||
import { RawTimeRange } from 'app/types/series';
|
||||
import { RawTimeRange } from '@grafana/ui';
|
||||
import { getTimeSrv } from 'app/features/dashboard/time_srv';
|
||||
import 'app/features/plugins/plugin_loader';
|
||||
|
||||
|
@ -7,7 +7,7 @@ import { Emitter } from 'app/core/utils/emitter';
|
||||
import QueryEditor from './QueryEditor';
|
||||
import QueryTransactionStatus from './QueryTransactionStatus';
|
||||
import { DataSource, DataQuery } from 'app/types';
|
||||
import { RawTimeRange } from 'app/types/series';
|
||||
import { RawTimeRange } from '@grafana/ui';
|
||||
|
||||
function getFirstHintFromTransactions(transactions: QueryTransaction[]): QueryHint {
|
||||
const transaction = transactions.find(qt => qt.hints && qt.hints.length > 0);
|
||||
|
@ -3,7 +3,7 @@ import moment from 'moment';
|
||||
|
||||
import * as dateMath from 'app/core/utils/datemath';
|
||||
import * as rangeUtil from 'app/core/utils/rangeutil';
|
||||
import { RawTimeRange, TimeRange } from 'app/types/series';
|
||||
import { RawTimeRange, TimeRange } from '@grafana/ui';
|
||||
|
||||
const DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss';
|
||||
export const DEFAULT_RANGE = {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { SFC } from 'react';
|
||||
import classNames from 'classnames/bind';
|
||||
import classNames from 'classnames';
|
||||
import PluginListItem from './PluginListItem';
|
||||
import { Plugin } from 'app/types';
|
||||
import { LayoutMode, LayoutModes } from '../../core/components/LayoutSelector/LayoutSelector';
|
||||
|
@ -26,6 +26,7 @@ import * as ticks from 'app/core/utils/ticks';
|
||||
import impressionSrv from 'app/core/services/impression_srv';
|
||||
import builtInPlugins from './built_in_plugins';
|
||||
import * as d3 from 'd3';
|
||||
import * as grafanaUI from '@grafana/ui';
|
||||
|
||||
// rxjs
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
@ -71,6 +72,7 @@ function exposeToPlugin(name: string, component: any) {
|
||||
});
|
||||
}
|
||||
|
||||
exposeToPlugin('@grafana/ui', grafanaUI);
|
||||
exposeToPlugin('lodash', _);
|
||||
exposeToPlugin('moment', moment);
|
||||
exposeToPlugin('jquery', jquery);
|
||||
|
@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { hot } from 'react-hot-loader';
|
||||
import PageHeader from 'app/core/components/PageHeader/PageHeader';
|
||||
import DeleteButton from 'app/core/components/DeleteButton/DeleteButton';
|
||||
import { DeleteButton } from '@grafana/ui';
|
||||
import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
|
||||
import PageLoader from 'app/core/components/PageLoader/PageLoader';
|
||||
import { NavModel, Team } from '../../types';
|
||||
@ -58,7 +58,7 @@ export class TeamList extends PureComponent<Props, any> {
|
||||
<a href={teamUrl}>{team.memberCount}</a>
|
||||
</td>
|
||||
<td className="text-right">
|
||||
<DeleteButton onConfirmDelete={() => this.deleteTeam(team)} />
|
||||
<DeleteButton onConfirm={() => this.deleteTeam(team)} />
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
|
@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import SlideDown from 'app/core/components/Animations/SlideDown';
|
||||
import { UserPicker } from 'app/core/components/Select/UserPicker';
|
||||
import DeleteButton from 'app/core/components/DeleteButton/DeleteButton';
|
||||
import { DeleteButton } from '@grafana/ui';
|
||||
import { TagBadge } from 'app/core/components/TagFilter/TagBadge';
|
||||
import { TeamMember, User } from 'app/types';
|
||||
import { loadTeamMembers, addTeamMember, removeTeamMember, setSearchMemberQuery } from './state/actions';
|
||||
@ -76,7 +76,7 @@ export class TeamMembers extends PureComponent<Props, State> {
|
||||
<td>{member.email}</td>
|
||||
{syncEnabled && this.renderLabels(member.labels)}
|
||||
<td className="text-right">
|
||||
<DeleteButton onConfirmDelete={() => this.onRemoveMember(member)} />
|
||||
<DeleteButton onConfirm={() => this.onRemoveMember(member)} />
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
|
@ -124,7 +124,7 @@ exports[`Render should render teams table 1`] = `
|
||||
className="text-right"
|
||||
>
|
||||
<DeleteButton
|
||||
onConfirmDelete={[Function]}
|
||||
onConfirm={[Function]}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -174,7 +174,7 @@ exports[`Render should render teams table 1`] = `
|
||||
className="text-right"
|
||||
>
|
||||
<DeleteButton
|
||||
onConfirmDelete={[Function]}
|
||||
onConfirm={[Function]}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -224,7 +224,7 @@ exports[`Render should render teams table 1`] = `
|
||||
className="text-right"
|
||||
>
|
||||
<DeleteButton
|
||||
onConfirmDelete={[Function]}
|
||||
onConfirm={[Function]}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -274,7 +274,7 @@ exports[`Render should render teams table 1`] = `
|
||||
className="text-right"
|
||||
>
|
||||
<DeleteButton
|
||||
onConfirmDelete={[Function]}
|
||||
onConfirm={[Function]}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -324,7 +324,7 @@ exports[`Render should render teams table 1`] = `
|
||||
className="text-right"
|
||||
>
|
||||
<DeleteButton
|
||||
onConfirmDelete={[Function]}
|
||||
onConfirm={[Function]}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -204,7 +204,7 @@ exports[`Render should render team members 1`] = `
|
||||
className="text-right"
|
||||
>
|
||||
<DeleteButton
|
||||
onConfirmDelete={[Function]}
|
||||
onConfirm={[Function]}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -229,7 +229,7 @@ exports[`Render should render team members 1`] = `
|
||||
className="text-right"
|
||||
>
|
||||
<DeleteButton
|
||||
onConfirmDelete={[Function]}
|
||||
onConfirm={[Function]}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -254,7 +254,7 @@ exports[`Render should render team members 1`] = `
|
||||
className="text-right"
|
||||
>
|
||||
<DeleteButton
|
||||
onConfirmDelete={[Function]}
|
||||
onConfirm={[Function]}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -279,7 +279,7 @@ exports[`Render should render team members 1`] = `
|
||||
className="text-right"
|
||||
>
|
||||
<DeleteButton
|
||||
onConfirmDelete={[Function]}
|
||||
onConfirm={[Function]}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -304,7 +304,7 @@ exports[`Render should render team members 1`] = `
|
||||
className="text-right"
|
||||
>
|
||||
<DeleteButton
|
||||
onConfirmDelete={[Function]}
|
||||
onConfirm={[Function]}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -441,7 +441,7 @@ exports[`Render should render team members when sync enabled 1`] = `
|
||||
className="text-right"
|
||||
>
|
||||
<DeleteButton
|
||||
onConfirmDelete={[Function]}
|
||||
onConfirm={[Function]}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -482,7 +482,7 @@ exports[`Render should render team members when sync enabled 1`] = `
|
||||
className="text-right"
|
||||
>
|
||||
<DeleteButton
|
||||
onConfirmDelete={[Function]}
|
||||
onConfirm={[Function]}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -523,7 +523,7 @@ exports[`Render should render team members when sync enabled 1`] = `
|
||||
className="text-right"
|
||||
>
|
||||
<DeleteButton
|
||||
onConfirmDelete={[Function]}
|
||||
onConfirm={[Function]}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -564,7 +564,7 @@ exports[`Render should render team members when sync enabled 1`] = `
|
||||
className="text-right"
|
||||
>
|
||||
<DeleteButton
|
||||
onConfirmDelete={[Function]}
|
||||
onConfirm={[Function]}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -605,7 +605,7 @@ exports[`Render should render team members when sync enabled 1`] = `
|
||||
className="text-right"
|
||||
>
|
||||
<DeleteButton
|
||||
onConfirmDelete={[Function]}
|
||||
onConfirm={[Function]}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import classNames from 'classnames/bind';
|
||||
import classNames from 'classnames';
|
||||
import { setUsersSearchQuery } from './state/actions';
|
||||
import { getInviteesCount, getUsersSearchQuery } from './state/selectors';
|
||||
|
||||
|
@ -2,7 +2,8 @@ import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import Thresholds from './Thresholds';
|
||||
import { defaultProps, OptionsProps } from './module';
|
||||
import { BasicGaugeColor, PanelOptionsProps } from 'app/types';
|
||||
import { BasicGaugeColor } from 'app/types';
|
||||
import { PanelOptionsProps } from '@grafana/ui';
|
||||
|
||||
const setup = (propOverrides?: object) => {
|
||||
const props: PanelOptionsProps<OptionsProps> = {
|
||||
|
@ -5,15 +5,8 @@ import ValueOptions from './ValueOptions';
|
||||
import GaugeOptions from './GaugeOptions';
|
||||
import Thresholds from './Thresholds';
|
||||
import ValueMappings from './ValueMappings';
|
||||
import {
|
||||
BasicGaugeColor,
|
||||
NullValueMode,
|
||||
PanelOptionsProps,
|
||||
PanelProps,
|
||||
RangeMap,
|
||||
Threshold,
|
||||
ValueMap,
|
||||
} from 'app/types';
|
||||
import { PanelOptionsProps, PanelProps, NullValueMode } from '@grafana/ui';
|
||||
import { BasicGaugeColor, RangeMap, Threshold, ValueMap } from 'app/types';
|
||||
|
||||
export interface OptionsProps {
|
||||
baseColor: string;
|
||||
|
@ -114,6 +114,7 @@ describe('grafanaGraph', () => {
|
||||
{}
|
||||
);
|
||||
|
||||
// @ts-ignore
|
||||
$.plot = ctrl.plot = jest.fn();
|
||||
scope.ctrl = ctrl;
|
||||
|
||||
|
@ -6,7 +6,7 @@ import React, { PureComponent } from 'react';
|
||||
import { Switch } from 'app/core/components/Switch/Switch';
|
||||
|
||||
// Types
|
||||
import { PanelOptionsProps } from 'app/types';
|
||||
import { PanelOptionsProps } from '@grafana/ui';
|
||||
import { Options } from './types';
|
||||
|
||||
export class GraphOptions extends PureComponent<PanelOptionsProps<Options>> {
|
||||
|
@ -1,15 +1,10 @@
|
||||
// Libraries
|
||||
import _ from 'lodash';
|
||||
import React, { PureComponent } from 'react';
|
||||
import colors from 'app/core/utils/colors';
|
||||
|
||||
// Components
|
||||
import Graph from 'app/viz/Graph';
|
||||
|
||||
// Services & Utils
|
||||
import { getTimeSeriesVMs } from 'app/viz/state/timeSeries';
|
||||
|
||||
// Types
|
||||
import { PanelProps, NullValueMode } from 'app/types';
|
||||
// Components & Types
|
||||
import { Graph, PanelProps, NullValueMode, processTimeSeries } from '@grafana/ui';
|
||||
import { Options } from './types';
|
||||
|
||||
interface Props extends PanelProps<Options> {}
|
||||
@ -23,9 +18,10 @@ export class GraphPanel extends PureComponent<Props> {
|
||||
const { timeSeries, timeRange, width, height } = this.props;
|
||||
const { showLines, showBars, showPoints } = this.props.options;
|
||||
|
||||
const vmSeries = getTimeSeriesVMs({
|
||||
const vmSeries = processTimeSeries({
|
||||
timeSeries: timeSeries,
|
||||
nullValueMode: NullValueMode.Ignore,
|
||||
colorPalette: colors,
|
||||
});
|
||||
|
||||
return (
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { PanelProps } from 'app/types';
|
||||
import { PanelProps } from '@grafana/ui';
|
||||
|
||||
export class Text2 extends PureComponent<PanelProps> {
|
||||
constructor(props) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Value } from 'slate';
|
||||
|
||||
import { DataQuery, RawTimeRange } from './series';
|
||||
import { DataQuery } from './series';
|
||||
import { RawTimeRange } from '@grafana/ui';
|
||||
import TableModel from 'app/core/table_model';
|
||||
import { LogsModel } from 'app/core/logs_model';
|
||||
import { DataSourceSelectItem } from 'app/types/datasources';
|
||||
|
@ -8,20 +8,8 @@ import { DashboardAcl, OrgRole, PermissionLevel } from './acl';
|
||||
import { ApiKey, ApiKeysState, NewApiKey } from './apiKeys';
|
||||
import { Invitee, OrgUser, User, UsersState, UserState } from './user';
|
||||
import { DataSource, DataSourceSelectItem, DataSourcesState } from './datasources';
|
||||
import {
|
||||
TimeRange,
|
||||
LoadingState,
|
||||
TimeSeries,
|
||||
TimeSeriesVM,
|
||||
TimeSeriesVMs,
|
||||
TimeSeriesStats,
|
||||
NullValueMode,
|
||||
DataQuery,
|
||||
DataQueryResponse,
|
||||
DataQueryOptions,
|
||||
IntervalValues,
|
||||
} from './series';
|
||||
import { BasicGaugeColor, MappingType, PanelProps, PanelOptionsProps, RangeMap, Threshold, ValueMap } from './panel';
|
||||
import { DataQuery, DataQueryResponse, DataQueryOptions } from './series';
|
||||
import { BasicGaugeColor, MappingType, RangeMap, Threshold, ValueMap } from './panel';
|
||||
import { PluginDashboard, PluginMeta, Plugin, PanelPlugin, PluginsState } from './plugins';
|
||||
import { Organization, OrganizationState } from './organization';
|
||||
import {
|
||||
@ -68,16 +56,7 @@ export {
|
||||
OrgUser,
|
||||
User,
|
||||
UsersState,
|
||||
TimeRange,
|
||||
LoadingState,
|
||||
PanelPlugin,
|
||||
PanelProps,
|
||||
PanelOptionsProps,
|
||||
TimeSeries,
|
||||
TimeSeriesVM,
|
||||
TimeSeriesVMs,
|
||||
NullValueMode,
|
||||
TimeSeriesStats,
|
||||
DataQuery,
|
||||
DataQueryResponse,
|
||||
DataQueryOptions,
|
||||
@ -95,7 +74,6 @@ export {
|
||||
ValidationRule,
|
||||
ValueMap,
|
||||
RangeMap,
|
||||
IntervalValues,
|
||||
MappingType,
|
||||
BasicGaugeColor,
|
||||
};
|
||||
|
17
public/app/types/jquery.d.ts
vendored
Normal file
17
public/app/types/jquery.d.ts
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
interface JQueryPlot {
|
||||
(element: HTMLElement | JQuery, data: any, options: any): void;
|
||||
plugins: any[];
|
||||
}
|
||||
|
||||
interface JQueryStatic {
|
||||
plot: JQueryPlot;
|
||||
}
|
||||
|
||||
interface JQuery {
|
||||
place_tt: any;
|
||||
modal: any;
|
||||
tagsinput: any;
|
||||
typeahead: any;
|
||||
accessKey: any;
|
||||
tooltip: any;
|
||||
}
|
@ -1,34 +1,3 @@
|
||||
import { LoadingState, TimeSeries, TimeRange } from './series';
|
||||
|
||||
export interface PanelProps<T = any> {
|
||||
timeSeries: TimeSeries[];
|
||||
timeRange: TimeRange;
|
||||
loading: LoadingState;
|
||||
options: T;
|
||||
renderCounter: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface PanelOptionsProps<T = any> {
|
||||
options: T;
|
||||
onChange: (options: T) => void;
|
||||
}
|
||||
|
||||
export interface PanelSize {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface PanelMenuItem {
|
||||
type?: 'submenu' | 'divider';
|
||||
text?: string;
|
||||
iconClassName?: string;
|
||||
onClick?: () => void;
|
||||
shortcut?: string;
|
||||
subMenu?: PanelMenuItem[];
|
||||
}
|
||||
|
||||
export interface Threshold {
|
||||
index: number;
|
||||
value: number;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ComponentClass } from 'react';
|
||||
import { PanelProps, PanelOptionsProps } from './panel';
|
||||
import { PanelProps, PanelOptionsProps } from '@grafana/ui';
|
||||
|
||||
export interface PluginExports {
|
||||
Datasource?: any;
|
||||
|
@ -1,75 +1,5 @@
|
||||
import { Moment } from 'moment';
|
||||
import { PluginMeta } from './plugins';
|
||||
|
||||
export enum LoadingState {
|
||||
NotStarted = 'NotStarted',
|
||||
Loading = 'Loading',
|
||||
Done = 'Done',
|
||||
Error = 'Error',
|
||||
}
|
||||
|
||||
export interface RawTimeRange {
|
||||
from: Moment | string;
|
||||
to: Moment | string;
|
||||
}
|
||||
|
||||
export interface TimeRange {
|
||||
from: Moment;
|
||||
to: Moment;
|
||||
raw: RawTimeRange;
|
||||
}
|
||||
|
||||
export interface IntervalValues {
|
||||
interval: string; // 10s,5m
|
||||
intervalMs: number;
|
||||
}
|
||||
|
||||
export type TimeSeriesValue = string | number | null;
|
||||
|
||||
export type TimeSeriesPoints = TimeSeriesValue[][];
|
||||
|
||||
export interface TimeSeries {
|
||||
target: string;
|
||||
datapoints: TimeSeriesPoints;
|
||||
unit?: string;
|
||||
}
|
||||
|
||||
/** View model projection of a time series */
|
||||
export interface TimeSeriesVM {
|
||||
label: string;
|
||||
color: string;
|
||||
data: TimeSeriesValue[][];
|
||||
stats: TimeSeriesStats;
|
||||
}
|
||||
|
||||
export interface TimeSeriesStats {
|
||||
total: number;
|
||||
max: number;
|
||||
min: number;
|
||||
logmin: number;
|
||||
avg: number | null;
|
||||
current: number | null;
|
||||
first: number | null;
|
||||
delta: number;
|
||||
diff: number | null;
|
||||
range: number | null;
|
||||
timeStep: number;
|
||||
count: number;
|
||||
allIsNull: boolean;
|
||||
allIsZero: boolean;
|
||||
}
|
||||
|
||||
export enum NullValueMode {
|
||||
Null = 'null',
|
||||
Ignore = 'connected',
|
||||
AsZero = 'null as zero',
|
||||
}
|
||||
|
||||
/** View model projection of many time series */
|
||||
export interface TimeSeriesVMs {
|
||||
[index: number]: TimeSeriesVM;
|
||||
length: number;
|
||||
}
|
||||
import { TimeSeries, TimeRange, RawTimeRange } from '@grafana/ui';
|
||||
|
||||
export interface DataQueryResponse {
|
||||
data: TimeSeries[];
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import $ from 'jquery';
|
||||
import { BasicGaugeColor, MappingType, RangeMap, Threshold, TimeSeriesVMs, ValueMap } from 'app/types';
|
||||
import { BasicGaugeColor, MappingType, RangeMap, Threshold, ValueMap } from 'app/types';
|
||||
import { TimeSeriesVMs } from '@grafana/ui';
|
||||
import config from '../core/config';
|
||||
import kbn from '../core/utils/kbn';
|
||||
|
||||
|
@ -5,7 +5,7 @@ import _ from 'lodash';
|
||||
import colors from 'app/core/utils/colors';
|
||||
|
||||
// Types
|
||||
import { TimeSeries, TimeSeriesVMs, NullValueMode } from 'app/types';
|
||||
import { TimeSeries, TimeSeriesVMs, NullValueMode } from '@grafana/ui';
|
||||
|
||||
interface Options {
|
||||
timeSeries: TimeSeries[];
|
||||
|
@ -38,6 +38,9 @@
|
||||
@import 'layout/lists';
|
||||
@import 'layout/page';
|
||||
|
||||
// LOAD @grafana/ui components
|
||||
@import '../../packages/grafana-ui/src/index';
|
||||
|
||||
// COMPONENTS
|
||||
@import 'components/scrollbar';
|
||||
@import 'components/cards';
|
||||
@ -98,7 +101,6 @@
|
||||
@import 'components/form_select_box';
|
||||
@import 'components/panel_editor';
|
||||
@import 'components/toolbar';
|
||||
@import 'components/delete_button';
|
||||
@import 'components/add_data_source.scss';
|
||||
@import 'components/page_loader';
|
||||
@import 'components/thresholds';
|
||||
|
@ -10,16 +10,26 @@ module.exports = function (grunt) {
|
||||
|
||||
grunt.registerTask('test', [
|
||||
'sasslint',
|
||||
'exec:tsc',
|
||||
'exec:tslint',
|
||||
'exec:jest',
|
||||
'tslint',
|
||||
'typecheck',
|
||||
"exec:jest",
|
||||
'no-only-tests'
|
||||
]);
|
||||
|
||||
grunt.registerTask('tslint', [
|
||||
'newer:exec:tslintPackages',
|
||||
'newer:exec:tslintRoot',
|
||||
]);
|
||||
|
||||
grunt.registerTask('typecheck', [
|
||||
'newer:exec:typecheckPackages',
|
||||
'newer:exec:typecheckRoot',
|
||||
]);
|
||||
|
||||
grunt.registerTask('precommit', [
|
||||
'sasslint',
|
||||
'newer:exec:tslint',
|
||||
'newer:exec:tsc',
|
||||
'newer:sasslint',
|
||||
'typecheck',
|
||||
'tslint',
|
||||
'no-only-tests'
|
||||
]);
|
||||
|
||||
|
@ -2,12 +2,20 @@ module.exports = function (config, grunt) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
tslint: {
|
||||
command: 'node ./node_modules/tslint/lib/tslintCli.js -c tslint.json --project ./tsconfig.json',
|
||||
tslintPackages: {
|
||||
command: 'yarn workspaces run tslint',
|
||||
src: ['packages/**/*.ts*'],
|
||||
},
|
||||
tslintRoot: {
|
||||
command: 'yarn run tslint',
|
||||
src: ['public/app/**/*.ts*'],
|
||||
},
|
||||
tsc: {
|
||||
command: 'yarn tsc --noEmit',
|
||||
typecheckPackages: {
|
||||
command: 'yarn workspaces run typecheck',
|
||||
src: ['packages/**/*.ts*'],
|
||||
},
|
||||
typecheckRoot: {
|
||||
command: 'yarn run typecheck',
|
||||
src: ['public/app/**/*.ts*'],
|
||||
},
|
||||
jest: 'node ./node_modules/jest-cli/bin/jest.js --maxWorkers 2',
|
||||
|
@ -4,6 +4,7 @@ module.exports = function(config) {
|
||||
options: {
|
||||
configFile: 'public/sass/.sass-lint.yml',
|
||||
},
|
||||
// src: ['public/sass#<{(||)}>#*'],
|
||||
target: [
|
||||
'public/sass/*.scss',
|
||||
'public/sass/components/*.scss',
|
||||
|
@ -1,11 +0,0 @@
|
||||
module.exports = function(config, grunt) {
|
||||
'use strict'
|
||||
// dummy to avoid template compile error
|
||||
return {
|
||||
source: {
|
||||
files: {
|
||||
src: ""
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
@ -26,6 +26,7 @@
|
||||
"noUnusedLocals": true,
|
||||
"baseUrl": "public",
|
||||
"pretty": true,
|
||||
"typeRoots": ["node_modules/@types", "types"],
|
||||
"paths": {
|
||||
"app": ["app"]
|
||||
}
|
||||
|
24
yarn.lock
24
yarn.lock
@ -804,6 +804,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.9.tgz#b5990152604c2ada749b7f88cab3476f21f39d7b"
|
||||
integrity sha512-q6LuBI0t5u04f0Q4/R+cGBqIbZMtJkVvCSF+nTfFBBdQqQvJR/mNHeWjRkszyLl7oyf2rDoKUYMEjTw5AV0hiw==
|
||||
|
||||
"@types/classnames@^2.2.6":
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.6.tgz#dbe8a666156d556ed018e15a4c65f08937c3f628"
|
||||
integrity sha512-XHcYvVdbtAxVstjKxuULYqYaWIzHR15yr1pZj4fnGChuBVJlIAp9StJna0ZJNSgxPh4Nac2FL4JM3M11Tm6fqQ==
|
||||
|
||||
"@types/d3-array@*":
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-1.2.3.tgz#dd141e3ba311485fffbf0792a1b01a7f2ec12dc1"
|
||||
@ -1029,6 +1034,16 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-23.3.4.tgz#cc43ae176a91dcb1504839b0b9d6659386cf0af5"
|
||||
integrity sha512-46jSw0QMerCRkhJZbOwPA0Eb9T1p74HtECsfa0GXdgjkenSGhgvK96w+e2PEPu4GF0/brUK5WQKq/rUQQFyAxA==
|
||||
|
||||
"@types/jquery@^1.10.35":
|
||||
version "1.10.35"
|
||||
resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-1.10.35.tgz#4e5c2b1e5b3bf0b863efb8c5e70081f52e6c9518"
|
||||
integrity sha512-SVtqEcudm7yjkTwoRA1gC6CNMhGDdMx4Pg8BPdiqI7bXXdCn1BPmtxgeWYQOgDxrq53/5YTlhq5ULxBEAlWIBg==
|
||||
|
||||
"@types/lodash@^4.14.119":
|
||||
version "4.14.119"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.119.tgz#be847e5f4bc3e35e46d041c394ead8b603ad8b39"
|
||||
integrity sha512-Z3TNyBL8Vd/M9D9Ms2S3LmFq2sSMzahodD6rCS9V2N44HUMINb75jNkSuwAx7eo2ufqTdfOdtGQpNbieUjPQmw==
|
||||
|
||||
"@types/node@*":
|
||||
version "10.11.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.11.4.tgz#e8bd933c3f78795d580ae41d86590bfc1f4f389d"
|
||||
@ -1083,7 +1098,7 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@16.7.6", "@types/react@^16.1.0", "@types/react@^16.7.6":
|
||||
"@types/react@*", "@types/react@^16.1.0", "@types/react@^16.7.6":
|
||||
version "16.7.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.7.6.tgz#80e4bab0d0731ad3ae51f320c4b08bdca5f03040"
|
||||
integrity sha512-QBUfzftr/8eg/q3ZRgf/GaDP6rTYc7ZNem+g4oZM38C9vXyV8AWRWaTQuW5yCoZTsfHrN7b3DeEiUnqH9SrnpA==
|
||||
@ -3153,7 +3168,7 @@ caniuse-api@^1.5.2:
|
||||
lodash.memoize "^4.1.2"
|
||||
lodash.uniq "^4.5.0"
|
||||
|
||||
caniuse-db@1.0.30000772, caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
|
||||
caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
|
||||
version "1.0.30000772"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000772.tgz#51aae891768286eade4a3d8319ea76d6a01b512b"
|
||||
integrity sha1-UarokXaChureSj2DGep21qAbUSs=
|
||||
@ -14544,6 +14559,11 @@ typescript@^3.0.3:
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.1.tgz#3362ba9dd1e482ebb2355b02dfe8bcd19a2c7c96"
|
||||
integrity sha512-Veu0w4dTc/9wlWNf2jeRInNodKlcdLgemvPsrNpfu5Pq39sgfFjvIIgTsvUHCoLBnMhPoUA+tFxsXjU6VexVRQ==
|
||||
|
||||
typescript@^3.2.2:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.2.2.tgz#fe8101c46aa123f8353523ebdcf5730c2ae493e5"
|
||||
integrity sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==
|
||||
|
||||
ua-parser-js@^0.7.18:
|
||||
version "0.7.19"
|
||||
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.19.tgz#94151be4c0a7fb1d001af7022fdaca4642659e4b"
|
||||
|
Loading…
Reference in New Issue
Block a user