mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Panels: Progress on new singlestat / BigValue (#19374)
* POC: friday hack * exploring new singlestat styles * minor changes * Testing bizcharts * style tweaks * Updated * minor progress * updated * Updated layout handling * Updated editor * added editor options * adding mode * progress on new display mode * tweaks * Added classic style * Added final mode * Minor tweak * tweaks * minor tweak * Singlestat: Adjust colors for light theme * fixed build issues with bizcharts * fixed typescript issue * updated snapshot * Added demo dashboard
This commit is contained in:
parent
45e0ebcc57
commit
81dd57524d
647
devenv/dev-dashboards/panel-stat/panel-stat-tests.json
Normal file
647
devenv/dev-dashboards/panel-stat/panel-stat-tests.json
Normal file
@ -0,0 +1,647 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"datasource": null,
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 20,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"interval": "10m",
|
||||
"options": {
|
||||
"colorMode": 0,
|
||||
"displayMode": 2,
|
||||
"fieldOptions": {
|
||||
"calcs": ["mean"],
|
||||
"defaults": {
|
||||
"mappings": [],
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"thresholds": [
|
||||
{
|
||||
"color": "blue",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "green",
|
||||
"value": 10
|
||||
},
|
||||
{
|
||||
"color": "purple",
|
||||
"value": 20
|
||||
},
|
||||
{
|
||||
"color": "orange",
|
||||
"value": 40
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
],
|
||||
"unit": "percent"
|
||||
},
|
||||
"override": {},
|
||||
"values": false
|
||||
},
|
||||
"orientation": "auto",
|
||||
"sparkline": {
|
||||
"show": true
|
||||
}
|
||||
},
|
||||
"pluginVersion": "6.5.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "B",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "C",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "D",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "E",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "F",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "G",
|
||||
"scenarioId": "random_walk"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Panel Title",
|
||||
"type": "singlestat2"
|
||||
},
|
||||
{
|
||||
"datasource": null,
|
||||
"gridPos": {
|
||||
"h": 20,
|
||||
"w": 4,
|
||||
"x": 20,
|
||||
"y": 0
|
||||
},
|
||||
"id": 8,
|
||||
"interval": "10m",
|
||||
"options": {
|
||||
"colorMode": 0,
|
||||
"displayMode": 2,
|
||||
"fieldOptions": {
|
||||
"calcs": ["mean"],
|
||||
"defaults": {
|
||||
"mappings": [],
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"thresholds": [
|
||||
{
|
||||
"color": "blue",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "green",
|
||||
"value": 10
|
||||
},
|
||||
{
|
||||
"color": "purple",
|
||||
"value": 20
|
||||
},
|
||||
{
|
||||
"color": "orange",
|
||||
"value": 40
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
],
|
||||
"unit": "percent"
|
||||
},
|
||||
"override": {},
|
||||
"values": false
|
||||
},
|
||||
"orientation": "auto",
|
||||
"sparkline": {
|
||||
"show": true
|
||||
}
|
||||
},
|
||||
"pluginVersion": "6.5.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "B",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "C",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "D",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "E",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "F",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "G",
|
||||
"scenarioId": "random_walk"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Panel Title",
|
||||
"type": "singlestat2"
|
||||
},
|
||||
{
|
||||
"datasource": null,
|
||||
"gridPos": {
|
||||
"h": 3,
|
||||
"w": 20,
|
||||
"x": 0,
|
||||
"y": 7
|
||||
},
|
||||
"id": 6,
|
||||
"interval": "10m",
|
||||
"options": {
|
||||
"colorMode": 0,
|
||||
"displayMode": 2,
|
||||
"fieldOptions": {
|
||||
"calcs": ["mean"],
|
||||
"defaults": {
|
||||
"mappings": [],
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"thresholds": [
|
||||
{
|
||||
"color": "blue",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "green",
|
||||
"value": 10
|
||||
},
|
||||
{
|
||||
"color": "purple",
|
||||
"value": 20
|
||||
},
|
||||
{
|
||||
"color": "orange",
|
||||
"value": 40
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
],
|
||||
"unit": "percent"
|
||||
},
|
||||
"override": {},
|
||||
"values": false
|
||||
},
|
||||
"orientation": "auto",
|
||||
"sparkline": {
|
||||
"show": true
|
||||
}
|
||||
},
|
||||
"pluginVersion": "6.5.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "B",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "C",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "D",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "E",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "F",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "G",
|
||||
"scenarioId": "random_walk"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Panel Title",
|
||||
"type": "singlestat2"
|
||||
},
|
||||
{
|
||||
"datasource": null,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 20,
|
||||
"x": 0,
|
||||
"y": 10
|
||||
},
|
||||
"id": 3,
|
||||
"interval": "10m",
|
||||
"options": {
|
||||
"colorMode": 0,
|
||||
"displayMode": 3,
|
||||
"fieldOptions": {
|
||||
"calcs": ["mean"],
|
||||
"defaults": {
|
||||
"mappings": [],
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"thresholds": [
|
||||
{
|
||||
"color": "blue",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "green",
|
||||
"value": 10
|
||||
},
|
||||
{
|
||||
"color": "purple",
|
||||
"value": 20
|
||||
},
|
||||
{
|
||||
"color": "orange",
|
||||
"value": 40
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
],
|
||||
"unit": "percent"
|
||||
},
|
||||
"override": {},
|
||||
"values": false
|
||||
},
|
||||
"orientation": "auto",
|
||||
"sparkline": {
|
||||
"show": true
|
||||
}
|
||||
},
|
||||
"pluginVersion": "6.5.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "B",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "C",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "D",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "E",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "F",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "G",
|
||||
"scenarioId": "random_walk"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Panel Title",
|
||||
"type": "singlestat2"
|
||||
},
|
||||
{
|
||||
"datasource": null,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 20,
|
||||
"x": 0,
|
||||
"y": 16
|
||||
},
|
||||
"id": 4,
|
||||
"interval": "10m",
|
||||
"options": {
|
||||
"colorMode": 0,
|
||||
"displayMode": 0,
|
||||
"fieldOptions": {
|
||||
"calcs": ["mean"],
|
||||
"defaults": {
|
||||
"mappings": [],
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"thresholds": [
|
||||
{
|
||||
"color": "blue",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "green",
|
||||
"value": 10
|
||||
},
|
||||
{
|
||||
"color": "purple",
|
||||
"value": 20
|
||||
},
|
||||
{
|
||||
"color": "orange",
|
||||
"value": 40
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
],
|
||||
"unit": "percent"
|
||||
},
|
||||
"override": {},
|
||||
"values": false
|
||||
},
|
||||
"orientation": "auto",
|
||||
"sparkline": {
|
||||
"show": true
|
||||
}
|
||||
},
|
||||
"pluginVersion": "6.5.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "B",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "C",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "D",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "E",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "F",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "G",
|
||||
"scenarioId": "random_walk"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Panel Title",
|
||||
"type": "singlestat2"
|
||||
},
|
||||
{
|
||||
"datasource": null,
|
||||
"gridPos": {
|
||||
"h": 21,
|
||||
"w": 4,
|
||||
"x": 20,
|
||||
"y": 20
|
||||
},
|
||||
"id": 9,
|
||||
"interval": "10m",
|
||||
"options": {
|
||||
"colorMode": 0,
|
||||
"displayMode": 0,
|
||||
"fieldOptions": {
|
||||
"calcs": ["mean"],
|
||||
"defaults": {
|
||||
"mappings": [],
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"thresholds": [
|
||||
{
|
||||
"color": "blue",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "green",
|
||||
"value": 10
|
||||
},
|
||||
{
|
||||
"color": "purple",
|
||||
"value": 20
|
||||
},
|
||||
{
|
||||
"color": "orange",
|
||||
"value": 40
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
],
|
||||
"unit": "percent"
|
||||
},
|
||||
"override": {},
|
||||
"values": false
|
||||
},
|
||||
"orientation": "auto",
|
||||
"sparkline": {
|
||||
"show": true
|
||||
}
|
||||
},
|
||||
"pluginVersion": "6.5.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "B",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "C",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "D",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "E",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "F",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "G",
|
||||
"scenarioId": "random_walk"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Panel Title",
|
||||
"type": "singlestat2"
|
||||
},
|
||||
{
|
||||
"datasource": null,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 20,
|
||||
"x": 0,
|
||||
"y": 22
|
||||
},
|
||||
"id": 5,
|
||||
"interval": "10m",
|
||||
"options": {
|
||||
"colorMode": 0,
|
||||
"displayMode": 1,
|
||||
"fieldOptions": {
|
||||
"calcs": ["mean"],
|
||||
"defaults": {
|
||||
"mappings": [],
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"thresholds": [
|
||||
{
|
||||
"color": "blue",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "green",
|
||||
"value": 10
|
||||
},
|
||||
{
|
||||
"color": "purple",
|
||||
"value": 20
|
||||
},
|
||||
{
|
||||
"color": "orange",
|
||||
"value": 40
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
],
|
||||
"unit": "percent"
|
||||
},
|
||||
"override": {},
|
||||
"values": false
|
||||
},
|
||||
"orientation": "auto",
|
||||
"sparkline": {
|
||||
"show": true
|
||||
}
|
||||
},
|
||||
"pluginVersion": "6.5.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "B",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "C",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "D",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "E",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "F",
|
||||
"scenarioId": "random_walk"
|
||||
},
|
||||
{
|
||||
"refId": "G",
|
||||
"scenarioId": "random_walk"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Panel Title",
|
||||
"type": "singlestat2"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 20,
|
||||
"style": "dark",
|
||||
"tags": ["gdev", "panel-tests"],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
|
||||
},
|
||||
"timezone": "",
|
||||
"title": "Panel Tests - Stat",
|
||||
"uid": "jWWHNJpWz",
|
||||
"version": 6
|
||||
}
|
@ -29,6 +29,7 @@
|
||||
"@grafana/slate-react": "0.22.9-grafana",
|
||||
"@torkelo/react-select": "2.1.1",
|
||||
"@types/react-color": "2.17.0",
|
||||
"bizcharts": "^3.5.5",
|
||||
"@types/slate": "0.47.1",
|
||||
"@types/slate-react": "0.22.5",
|
||||
"classnames": "2.2.6",
|
||||
|
@ -57,6 +57,7 @@ const buildCjsPackage = ({ env }) => {
|
||||
],
|
||||
'node_modules/immutable/dist/immutable.js': ['Record', 'Set', 'Map', 'List', 'OrderedSet', 'is', 'Stack'],
|
||||
'../../node_modules/esrever/esrever.js': ['reverse'],
|
||||
'../../node_modules/bizcharts/es6/index.js': ['Chart', 'Geom', 'View', 'Tooltip', 'Legend'],
|
||||
},
|
||||
}),
|
||||
resolve(),
|
||||
|
@ -1,14 +1,13 @@
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { number, text } from '@storybook/addon-knobs';
|
||||
import { BigValue } from './BigValue';
|
||||
import { text } from '@storybook/addon-knobs';
|
||||
import { BigValue, SingleStatDisplayMode } from './BigValue';
|
||||
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||
import { renderComponentWithTheme } from '../../utils/storybook/withTheme';
|
||||
|
||||
const getKnobs = () => {
|
||||
return {
|
||||
value: text('value', 'Hello'),
|
||||
valueFontSize: number('valueFontSize', 120),
|
||||
prefix: text('prefix', ''),
|
||||
value: text('value', '$5022'),
|
||||
title: text('title', 'Total Earnings'),
|
||||
};
|
||||
};
|
||||
|
||||
@ -16,22 +15,37 @@ const BigValueStories = storiesOf('UI/BigValue', module);
|
||||
|
||||
BigValueStories.addDecorator(withCenteredStory);
|
||||
|
||||
BigValueStories.add('Singlestat viz', () => {
|
||||
const { value, prefix, valueFontSize } = getKnobs();
|
||||
interface StoryOptions {
|
||||
mode: SingleStatDisplayMode;
|
||||
width?: number;
|
||||
height?: number;
|
||||
noSparkline?: boolean;
|
||||
}
|
||||
|
||||
return renderComponentWithTheme(BigValue, {
|
||||
width: 300,
|
||||
height: 250,
|
||||
value: {
|
||||
text: value,
|
||||
numeric: NaN,
|
||||
fontSize: valueFontSize + '%',
|
||||
},
|
||||
prefix: prefix
|
||||
? {
|
||||
text: prefix,
|
||||
numeric: NaN,
|
||||
}
|
||||
: null,
|
||||
function addStoryForMode(options: StoryOptions) {
|
||||
BigValueStories.add(`Mode: ${SingleStatDisplayMode[options.mode]}`, () => {
|
||||
const { value, title } = getKnobs();
|
||||
|
||||
return renderComponentWithTheme(BigValue, {
|
||||
width: options.width || 400,
|
||||
height: options.height || 300,
|
||||
displayMode: options.mode,
|
||||
value: {
|
||||
text: value,
|
||||
numeric: 5022,
|
||||
color: 'red',
|
||||
title,
|
||||
},
|
||||
sparkline: {
|
||||
minX: 0,
|
||||
maxX: 5,
|
||||
data: [[0, 10], [1, 20], [2, 15], [3, 25], [4, 5], [5, 10]],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
addStoryForMode({ mode: SingleStatDisplayMode.Classic });
|
||||
addStoryForMode({ mode: SingleStatDisplayMode.Classic2 });
|
||||
addStoryForMode({ mode: SingleStatDisplayMode.Vibrant });
|
||||
addStoryForMode({ mode: SingleStatDisplayMode.Vibrant2 });
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { BigValue, Props } from './BigValue';
|
||||
import { BigValue, Props, SingleStatDisplayMode } from './BigValue';
|
||||
import { getTheme } from '../../themes/index';
|
||||
|
||||
jest.mock('jquery', () => ({
|
||||
@ -11,6 +11,7 @@ const setup = (propOverrides?: object) => {
|
||||
const props: Props = {
|
||||
height: 300,
|
||||
width: 300,
|
||||
displayMode: SingleStatDisplayMode.Classic,
|
||||
value: {
|
||||
text: '25',
|
||||
numeric: 25,
|
||||
@ -29,7 +30,7 @@ const setup = (propOverrides?: object) => {
|
||||
};
|
||||
};
|
||||
|
||||
describe('Render BarGauge with basic options', () => {
|
||||
describe('Render SingleStat with basic options', () => {
|
||||
it('should render', () => {
|
||||
const { wrapper } = setup();
|
||||
expect(wrapper).toBeDefined();
|
||||
|
@ -1,168 +1,413 @@
|
||||
// Library
|
||||
import React, { PureComponent, ReactNode, CSSProperties } from 'react';
|
||||
import $ from 'jquery';
|
||||
import { css, cx } from 'emotion';
|
||||
import React, { PureComponent, CSSProperties } from 'react';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import { Chart, Geom } from 'bizcharts';
|
||||
import { DisplayValue } from '@grafana/data';
|
||||
|
||||
// Utils
|
||||
import { getColorFromHexRgbOrName } from '../../utils';
|
||||
|
||||
// Types
|
||||
import { Themeable } from '../../types';
|
||||
import { stylesFactory } from '../../themes/stylesFactory';
|
||||
import { Themeable, GrafanaTheme } from '../../types';
|
||||
|
||||
export interface BigValueSparkline {
|
||||
data: any[][]; // [[number,number]]
|
||||
data: any[][];
|
||||
minX: number;
|
||||
maxX: number;
|
||||
full: boolean; // full height
|
||||
fillColor: string;
|
||||
lineColor: string;
|
||||
}
|
||||
|
||||
export enum SingleStatDisplayMode {
|
||||
Classic,
|
||||
Classic2,
|
||||
Vibrant,
|
||||
Vibrant2,
|
||||
}
|
||||
|
||||
export interface Props extends Themeable {
|
||||
height: number;
|
||||
width: number;
|
||||
value: DisplayValue;
|
||||
prefix?: DisplayValue;
|
||||
suffix?: DisplayValue;
|
||||
sparkline?: BigValueSparkline;
|
||||
backgroundColor?: string;
|
||||
onClick?: React.MouseEventHandler<HTMLElement>;
|
||||
className?: string;
|
||||
displayMode: SingleStatDisplayMode;
|
||||
}
|
||||
|
||||
const getStyles = stylesFactory(() => {
|
||||
return {
|
||||
wrapper: css`
|
||||
position: 'relative';
|
||||
display: 'table';
|
||||
`,
|
||||
title: css`
|
||||
line-height: 1;
|
||||
text-align: 'center';
|
||||
z-index: 1;
|
||||
display: 'block';
|
||||
width: '100%';
|
||||
position: 'absolute';
|
||||
`,
|
||||
value: css`
|
||||
line-height: 1;
|
||||
text-align: 'center';
|
||||
z-index: 1;
|
||||
display: 'table-cell';
|
||||
vertical-align: 'middle';
|
||||
position: 'relative';
|
||||
font-size: '3em';
|
||||
font-weight: 500;
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
/*
|
||||
* This visualization is still in POC state, needed more tests & better structure
|
||||
*/
|
||||
export class BigValue extends PureComponent<Props> {
|
||||
canvasElement: any;
|
||||
|
||||
componentDidMount() {
|
||||
this.draw();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.draw();
|
||||
}
|
||||
|
||||
draw() {
|
||||
const { sparkline, theme } = this.props;
|
||||
|
||||
if (sparkline && this.canvasElement) {
|
||||
const { data, minX, maxX, fillColor, lineColor } = sparkline;
|
||||
|
||||
const options = {
|
||||
legend: { show: false },
|
||||
series: {
|
||||
lines: {
|
||||
show: true,
|
||||
fill: 1,
|
||||
zero: false,
|
||||
lineWidth: 1,
|
||||
fillColor: getColorFromHexRgbOrName(fillColor, theme.type),
|
||||
},
|
||||
},
|
||||
yaxes: { show: false },
|
||||
xaxis: {
|
||||
show: false,
|
||||
min: minX,
|
||||
max: maxX,
|
||||
},
|
||||
grid: { hoverable: false, show: false },
|
||||
};
|
||||
|
||||
const plotSeries = {
|
||||
data,
|
||||
color: getColorFromHexRgbOrName(lineColor, theme.type),
|
||||
};
|
||||
|
||||
try {
|
||||
$.plot(this.canvasElement, [plotSeries], options);
|
||||
} catch (err) {
|
||||
console.log('sparkline rendering error', err, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderText = (value?: DisplayValue, padding?: string): ReactNode => {
|
||||
if (!value || !value.text) {
|
||||
return null;
|
||||
}
|
||||
const css: CSSProperties = {};
|
||||
if (padding) {
|
||||
css.padding = padding;
|
||||
}
|
||||
if (value.color) {
|
||||
css.color = value.color;
|
||||
}
|
||||
if (value.fontSize) {
|
||||
css.fontSize = value.fontSize;
|
||||
}
|
||||
|
||||
return <span style={css}>{value.text}</span>;
|
||||
};
|
||||
|
||||
renderSparkline(sparkline: BigValueSparkline) {
|
||||
const { height, width } = this.props;
|
||||
|
||||
const plotCss: CSSProperties = {};
|
||||
plotCss.position = 'absolute';
|
||||
plotCss.bottom = '0px';
|
||||
plotCss.left = '0px';
|
||||
plotCss.width = width + 'px';
|
||||
|
||||
if (sparkline.full) {
|
||||
const dynamicHeightMargin = height <= 100 ? 5 : Math.round(height / 100) * 15 + 5;
|
||||
plotCss.height = height - dynamicHeightMargin + 'px';
|
||||
} else {
|
||||
plotCss.height = Math.floor(height * 0.25) + 'px';
|
||||
}
|
||||
return <div style={plotCss} ref={element => (this.canvasElement = element)} />;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { height, width, value, prefix, suffix, sparkline, backgroundColor, onClick, className } = this.props;
|
||||
const styles = getStyles();
|
||||
const { value, onClick, className, sparkline } = this.props;
|
||||
|
||||
const layout = calculateLayout(this.props);
|
||||
const panelStyles = getPanelStyles(layout);
|
||||
const valueAndTitleContainerStyles = getValueAndTitleContainerStyles(layout);
|
||||
const valueStyles = getValueStyles(layout);
|
||||
const titleStyles = getTitleStyles(layout);
|
||||
|
||||
return (
|
||||
<div className={cx(styles.wrapper, className)} style={{ width, height, backgroundColor }} onClick={onClick}>
|
||||
{value.title && <div className={styles.title}>{value.title}</div>}
|
||||
|
||||
<span className={styles.value}>
|
||||
{this.renderText(prefix, '0px 2px 0px 0px')}
|
||||
{this.renderText(value)}
|
||||
{this.renderText(suffix)}
|
||||
</span>
|
||||
|
||||
{sparkline && this.renderSparkline(sparkline)}
|
||||
<div className={className} style={panelStyles} onClick={onClick}>
|
||||
<div style={valueAndTitleContainerStyles}>
|
||||
{value.title && <div style={titleStyles}>{value.title}</div>}
|
||||
<div style={valueStyles}>{value.text}</div>
|
||||
</div>
|
||||
{renderGraph(layout, sparkline)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const MIN_VALUE_FONT_SIZE = 20;
|
||||
const MAX_VALUE_FONT_SIZE = 50;
|
||||
const MIN_TITLE_FONT_SIZE = 14;
|
||||
const TITLE_VALUE_RATIO = 0.45;
|
||||
const VALUE_HEIGHT_RATIO = 0.25;
|
||||
const VALUE_HEIGHT_RATIO_WIDE = 0.3;
|
||||
const LINE_HEIGHT = 1.2;
|
||||
const PANEL_PADDING = 16;
|
||||
const CHART_TOP_MARGIN = 8;
|
||||
|
||||
interface LayoutResult {
|
||||
titleFontSize: number;
|
||||
valueFontSize: number;
|
||||
chartHeight: number;
|
||||
chartWidth: number;
|
||||
type: LayoutType;
|
||||
width: number;
|
||||
height: number;
|
||||
displayMode: SingleStatDisplayMode;
|
||||
theme: GrafanaTheme;
|
||||
valueColor: string;
|
||||
}
|
||||
|
||||
enum LayoutType {
|
||||
Stacked,
|
||||
StackedNoChart,
|
||||
Wide,
|
||||
WideNoChart,
|
||||
}
|
||||
|
||||
export function calculateLayout(props: Props): LayoutResult {
|
||||
const { width, height, sparkline, displayMode, theme, value } = props;
|
||||
const useWideLayout = width / height > 2.8;
|
||||
const valueColor = getColorFromHexRgbOrName(value.color || 'green', theme.type);
|
||||
|
||||
// handle wide layouts
|
||||
if (useWideLayout) {
|
||||
const valueFontSize = Math.min(
|
||||
Math.max(height * VALUE_HEIGHT_RATIO_WIDE, MIN_VALUE_FONT_SIZE),
|
||||
MAX_VALUE_FONT_SIZE
|
||||
);
|
||||
const titleFontSize = Math.max(valueFontSize * TITLE_VALUE_RATIO, MIN_TITLE_FONT_SIZE);
|
||||
|
||||
const chartHeight = height - PANEL_PADDING * 2;
|
||||
const chartWidth = width / 2;
|
||||
let type = !!sparkline ? LayoutType.Wide : LayoutType.WideNoChart;
|
||||
|
||||
if (height < 80 || !sparkline) {
|
||||
type = LayoutType.WideNoChart;
|
||||
}
|
||||
|
||||
return {
|
||||
valueFontSize,
|
||||
titleFontSize,
|
||||
chartHeight,
|
||||
chartWidth,
|
||||
type,
|
||||
width,
|
||||
height,
|
||||
displayMode,
|
||||
theme,
|
||||
valueColor,
|
||||
};
|
||||
}
|
||||
|
||||
// handle stacked layouts
|
||||
const valueFontSize = Math.min(Math.max(height * VALUE_HEIGHT_RATIO, MIN_VALUE_FONT_SIZE), MAX_VALUE_FONT_SIZE);
|
||||
const titleFontSize = Math.max(valueFontSize * TITLE_VALUE_RATIO, MIN_TITLE_FONT_SIZE);
|
||||
const valueHeight = valueFontSize * LINE_HEIGHT;
|
||||
const titleHeight = titleFontSize * LINE_HEIGHT;
|
||||
|
||||
let chartHeight = height - valueHeight - titleHeight - PANEL_PADDING * 2 - CHART_TOP_MARGIN;
|
||||
let chartWidth = width - PANEL_PADDING * 2;
|
||||
let type = LayoutType.Stacked;
|
||||
|
||||
if (height < 100 || !sparkline) {
|
||||
type = LayoutType.StackedNoChart;
|
||||
}
|
||||
|
||||
switch (displayMode) {
|
||||
case SingleStatDisplayMode.Vibrant2:
|
||||
case SingleStatDisplayMode.Classic:
|
||||
case SingleStatDisplayMode.Classic2:
|
||||
chartWidth = width;
|
||||
chartHeight += PANEL_PADDING;
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
valueFontSize,
|
||||
titleFontSize,
|
||||
chartHeight,
|
||||
chartWidth,
|
||||
type,
|
||||
width,
|
||||
height,
|
||||
displayMode,
|
||||
theme,
|
||||
valueColor,
|
||||
};
|
||||
}
|
||||
|
||||
export function getTitleStyles(layout: LayoutResult) {
|
||||
const styles: CSSProperties = {
|
||||
fontSize: `${layout.titleFontSize}px`,
|
||||
textShadow: '#333 1px 1px 5px',
|
||||
color: '#EEE',
|
||||
};
|
||||
|
||||
if (layout.theme.isLight) {
|
||||
styles.color = 'white';
|
||||
}
|
||||
|
||||
return styles;
|
||||
}
|
||||
|
||||
export function getValueStyles(layout: LayoutResult) {
|
||||
const styles: CSSProperties = {
|
||||
fontSize: `${layout.valueFontSize}px`,
|
||||
color: '#EEE',
|
||||
textShadow: '#333 1px 1px 5px',
|
||||
lineHeight: LINE_HEIGHT,
|
||||
};
|
||||
|
||||
switch (layout.displayMode) {
|
||||
case SingleStatDisplayMode.Classic:
|
||||
case SingleStatDisplayMode.Classic2:
|
||||
styles.color = layout.valueColor;
|
||||
}
|
||||
|
||||
return styles;
|
||||
}
|
||||
|
||||
export function getValueAndTitleContainerStyles(layout: LayoutResult): CSSProperties {
|
||||
switch (layout.type) {
|
||||
case LayoutType.Wide:
|
||||
return {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flexGrow: 1,
|
||||
};
|
||||
case LayoutType.WideNoChart:
|
||||
return {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
flexGrow: 1,
|
||||
};
|
||||
case LayoutType.StackedNoChart:
|
||||
return {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flexGrow: 1,
|
||||
};
|
||||
case LayoutType.Stacked:
|
||||
default:
|
||||
return {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function getPanelStyles(layout: LayoutResult) {
|
||||
const panelStyles: CSSProperties = {
|
||||
width: `${layout.width}px`,
|
||||
height: `${layout.height}px`,
|
||||
padding: `${PANEL_PADDING}px`,
|
||||
borderRadius: '3px',
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
};
|
||||
|
||||
const themeFactor = layout.theme.isDark ? 1 : -0.7;
|
||||
|
||||
switch (layout.displayMode) {
|
||||
case SingleStatDisplayMode.Vibrant:
|
||||
case SingleStatDisplayMode.Vibrant2:
|
||||
const bgColor2 = tinycolor(layout.valueColor)
|
||||
.darken(15 * themeFactor)
|
||||
.spin(8)
|
||||
.toRgbString();
|
||||
const bgColor3 = tinycolor(layout.valueColor)
|
||||
.darken(5 * themeFactor)
|
||||
.spin(-8)
|
||||
.toRgbString();
|
||||
panelStyles.background = `linear-gradient(120deg, ${bgColor2}, ${bgColor3})`;
|
||||
break;
|
||||
case SingleStatDisplayMode.Classic:
|
||||
case SingleStatDisplayMode.Classic2:
|
||||
panelStyles.background = `${layout.theme.colors.dark4}`;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (layout.type) {
|
||||
case LayoutType.Stacked:
|
||||
panelStyles.flexDirection = 'column';
|
||||
break;
|
||||
case LayoutType.StackedNoChart:
|
||||
panelStyles.alignItems = 'center';
|
||||
break;
|
||||
case LayoutType.Wide:
|
||||
panelStyles.flexDirection = 'row';
|
||||
panelStyles.alignItems = 'center';
|
||||
panelStyles.justifyContent = 'space-between';
|
||||
break;
|
||||
case LayoutType.WideNoChart:
|
||||
panelStyles.alignItems = 'center';
|
||||
break;
|
||||
}
|
||||
|
||||
return panelStyles;
|
||||
}
|
||||
|
||||
function renderGraph(layout: LayoutResult, sparkline?: BigValueSparkline) {
|
||||
if (!sparkline) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = sparkline.data.map(values => {
|
||||
return { time: values[0], value: values[1], name: 'A' };
|
||||
});
|
||||
|
||||
const scales = {
|
||||
time: {
|
||||
type: 'time',
|
||||
},
|
||||
};
|
||||
|
||||
const chartStyles: CSSProperties = {
|
||||
marginTop: `${CHART_TOP_MARGIN}`,
|
||||
};
|
||||
|
||||
// default to line graph
|
||||
let geomRender = renderLineGeom;
|
||||
|
||||
switch (layout.type) {
|
||||
case LayoutType.Wide:
|
||||
chartStyles.width = `${layout.chartWidth}px`;
|
||||
chartStyles.height = `${layout.chartHeight}px`;
|
||||
break;
|
||||
case LayoutType.Stacked:
|
||||
chartStyles.position = 'relative';
|
||||
chartStyles.top = '8px';
|
||||
break;
|
||||
case LayoutType.WideNoChart:
|
||||
case LayoutType.StackedNoChart:
|
||||
return null;
|
||||
}
|
||||
|
||||
if (layout.chartWidth === layout.width) {
|
||||
chartStyles.position = 'absolute';
|
||||
chartStyles.bottom = 0;
|
||||
chartStyles.right = 0;
|
||||
chartStyles.left = 0;
|
||||
chartStyles.right = 0;
|
||||
chartStyles.top = 'unset';
|
||||
}
|
||||
|
||||
switch (layout.displayMode) {
|
||||
case SingleStatDisplayMode.Vibrant2:
|
||||
geomRender = renderVibrant2Geom;
|
||||
break;
|
||||
case SingleStatDisplayMode.Classic:
|
||||
geomRender = renderClassicAreaGeom;
|
||||
break;
|
||||
case SingleStatDisplayMode.Classic2:
|
||||
geomRender = renderAreaGeom;
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<Chart
|
||||
height={layout.chartHeight}
|
||||
width={layout.chartWidth}
|
||||
data={data}
|
||||
animate={false}
|
||||
padding={[4, 0, 0, 0]}
|
||||
scale={scales}
|
||||
style={chartStyles}
|
||||
>
|
||||
{geomRender(layout)}
|
||||
</Chart>
|
||||
);
|
||||
}
|
||||
|
||||
function renderLineGeom(layout: LayoutResult) {
|
||||
const lineStyle: any = {
|
||||
stroke: '#CCC',
|
||||
lineWidth: 2,
|
||||
shadowBlur: 15,
|
||||
shadowColor: '#444',
|
||||
shadowOffsetY: 7,
|
||||
};
|
||||
|
||||
return <Geom type="line" position="time*value" size={2} color="white" style={lineStyle} shape="smooth" />;
|
||||
}
|
||||
|
||||
function renderVibrant2Geom(layout: LayoutResult) {
|
||||
const lineStyle: any = {
|
||||
stroke: '#CCC',
|
||||
lineWidth: 2,
|
||||
shadowBlur: 15,
|
||||
shadowColor: '#444',
|
||||
shadowOffsetY: -5,
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Geom type="area" position="time*value" size={0} color="rgba(255,255,255,0.4)" style={lineStyle} shape="smooth" />
|
||||
<Geom type="line" position="time*value" size={1} color="white" style={lineStyle} shape="smooth" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function renderClassicAreaGeom(layout: LayoutResult) {
|
||||
const lineStyle: any = {
|
||||
opacity: 1,
|
||||
fillOpacity: 1,
|
||||
};
|
||||
|
||||
const fillColor = tinycolor(layout.valueColor)
|
||||
.setAlpha(0.2)
|
||||
.toRgbString();
|
||||
|
||||
lineStyle.stroke = layout.valueColor;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Geom type="area" position="time*value" size={0} color={fillColor} style={lineStyle} shape="smooth" />
|
||||
<Geom type="line" position="time*value" size={1} color={layout.valueColor} style={lineStyle} shape="smooth" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function renderAreaGeom(layout: LayoutResult) {
|
||||
const lineStyle: any = {
|
||||
opacity: 1,
|
||||
fillOpacity: 1,
|
||||
};
|
||||
|
||||
const color1 = tinycolor(layout.valueColor)
|
||||
.darken(0)
|
||||
.spin(20)
|
||||
.toRgbString();
|
||||
const color2 = tinycolor(layout.valueColor)
|
||||
.lighten(0)
|
||||
.spin(-20)
|
||||
.toRgbString();
|
||||
|
||||
const fillColor = `l (0) 0:${color1} 1:${color2}`;
|
||||
|
||||
return <Geom type="area" position="time*value" size={0} color={fillColor} style={lineStyle} shape="smooth" />;
|
||||
}
|
||||
|
@ -164,6 +164,8 @@ exports[`Render should render with base threshold 1`] = `
|
||||
"md": "32px",
|
||||
"sm": "24px",
|
||||
},
|
||||
"isDark": true,
|
||||
"isLight": false,
|
||||
"name": "Grafana Dark",
|
||||
"panelHeaderHeight": 28,
|
||||
"panelPadding": 8,
|
||||
@ -331,6 +333,8 @@ exports[`Render should render with base threshold 1`] = `
|
||||
"md": "32px",
|
||||
"sm": "24px",
|
||||
},
|
||||
"isDark": true,
|
||||
"isLight": false,
|
||||
"name": "Grafana Dark",
|
||||
"panelHeaderHeight": 28,
|
||||
"panelPadding": 8,
|
||||
|
@ -46,7 +46,7 @@ export { Table } from './Table/Table';
|
||||
export { TableInputCSV } from './Table/TableInputCSV';
|
||||
|
||||
// Visualizations
|
||||
export { BigValue } from './BigValue/BigValue';
|
||||
export { BigValue, SingleStatDisplayMode } from './BigValue/BigValue';
|
||||
export { Gauge } from './Gauge/Gauge';
|
||||
export { Graph } from './Graph/Graph';
|
||||
export { GraphLegend } from './Graph/GraphLegend';
|
||||
|
@ -42,6 +42,8 @@ const basicColors = {
|
||||
const darkTheme: GrafanaTheme = {
|
||||
...defaultTheme,
|
||||
type: GrafanaThemeType.Dark,
|
||||
isDark: true,
|
||||
isLight: false,
|
||||
name: 'Grafana Dark',
|
||||
colors: {
|
||||
...basicColors,
|
||||
|
@ -42,6 +42,8 @@ const basicColors = {
|
||||
const lightTheme: GrafanaTheme = {
|
||||
...defaultTheme,
|
||||
type: GrafanaThemeType.Light,
|
||||
isDark: false,
|
||||
isLight: true,
|
||||
name: 'Grafana Light',
|
||||
colors: {
|
||||
...basicColors,
|
||||
|
@ -92,6 +92,8 @@ export interface GrafanaThemeCommons {
|
||||
|
||||
export interface GrafanaTheme extends GrafanaThemeCommons {
|
||||
type: GrafanaThemeType;
|
||||
isDark: boolean;
|
||||
isLight: boolean;
|
||||
background: {
|
||||
dropdown: string;
|
||||
scrollbar: string;
|
||||
|
@ -142,6 +142,7 @@ export class PanelQueryRunner {
|
||||
|
||||
request.interval = norm.interval;
|
||||
request.intervalMs = norm.intervalMs;
|
||||
console.log('to', request.range.to.valueOf());
|
||||
|
||||
this.pipeToSubject(runRequest(ds, request));
|
||||
} catch (err) {
|
||||
|
@ -1,63 +0,0 @@
|
||||
// Libraries
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
// Components
|
||||
import { Switch, PanelOptionsGroup } from '@grafana/ui';
|
||||
|
||||
// Types
|
||||
import { SingleStatOptions } from './types';
|
||||
|
||||
const labelWidth = 6;
|
||||
|
||||
export interface Props {
|
||||
options: SingleStatOptions;
|
||||
onChange: (options: SingleStatOptions) => void;
|
||||
}
|
||||
|
||||
export class ColoringEditor extends PureComponent<Props> {
|
||||
onToggleColorBackground = () =>
|
||||
this.props.onChange({ ...this.props.options, colorBackground: !this.props.options.colorBackground });
|
||||
|
||||
onToggleColorValue = () => this.props.onChange({ ...this.props.options, colorValue: !this.props.options.colorValue });
|
||||
|
||||
onToggleColorPrefix = () =>
|
||||
this.props.onChange({ ...this.props.options, colorPrefix: !this.props.options.colorPrefix });
|
||||
|
||||
onToggleColorPostfix = () =>
|
||||
this.props.onChange({ ...this.props.options, colorPostfix: !this.props.options.colorPostfix });
|
||||
|
||||
render() {
|
||||
const { colorBackground, colorValue, colorPrefix, colorPostfix } = this.props.options;
|
||||
|
||||
return (
|
||||
<PanelOptionsGroup title="Coloring">
|
||||
<Switch
|
||||
label="Background"
|
||||
labelClass={`width-${labelWidth}`}
|
||||
checked={colorBackground!}
|
||||
onChange={this.onToggleColorBackground}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label="Value"
|
||||
labelClass={`width-${labelWidth}`}
|
||||
checked={colorValue!}
|
||||
onChange={this.onToggleColorValue}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label="Prefix"
|
||||
labelClass={`width-${labelWidth}`}
|
||||
checked={colorPrefix!}
|
||||
onChange={this.onToggleColorPrefix}
|
||||
/>
|
||||
<Switch
|
||||
label="Postfix"
|
||||
labelClass={`width-${labelWidth}`}
|
||||
checked={colorPostfix!}
|
||||
onChange={this.onToggleColorPostfix}
|
||||
/>
|
||||
</PanelOptionsGroup>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
// Libraries
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
// Components
|
||||
import { FormLabel, Select, PanelOptionsGroup } from '@grafana/ui';
|
||||
|
||||
// Types
|
||||
import { SingleStatOptions } from './types';
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
|
||||
const labelWidth = 6;
|
||||
|
||||
export interface Props {
|
||||
options: SingleStatOptions;
|
||||
onChange: (options: SingleStatOptions) => void;
|
||||
}
|
||||
|
||||
const percents = ['20%', '30%', '50%', '70%', '80%', '100%', '110%', '120%', '150%', '170%', '200%'];
|
||||
const fontSizeOptions = percents.map(v => {
|
||||
return { value: v, label: v };
|
||||
});
|
||||
|
||||
export class FontSizeEditor extends PureComponent<Props> {
|
||||
setPrefixFontSize = (v: SelectableValue<string>) =>
|
||||
this.props.onChange({ ...this.props.options, prefixFontSize: v.value });
|
||||
|
||||
setValueFontSize = (v: SelectableValue<string>) =>
|
||||
this.props.onChange({ ...this.props.options, valueFontSize: v.value });
|
||||
|
||||
setPostfixFontSize = (v: SelectableValue<string>) =>
|
||||
this.props.onChange({ ...this.props.options, postfixFontSize: v.value });
|
||||
|
||||
render() {
|
||||
const { prefixFontSize, valueFontSize, postfixFontSize } = this.props.options;
|
||||
|
||||
return (
|
||||
<PanelOptionsGroup title="Font Size">
|
||||
<div className="gf-form">
|
||||
<FormLabel width={labelWidth}>Prefix</FormLabel>
|
||||
<Select
|
||||
width={12}
|
||||
options={fontSizeOptions}
|
||||
onChange={this.setPrefixFontSize}
|
||||
value={fontSizeOptions.find(option => option.value === prefixFontSize)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="gf-form">
|
||||
<FormLabel width={labelWidth}>Value</FormLabel>
|
||||
<Select
|
||||
width={12}
|
||||
options={fontSizeOptions}
|
||||
onChange={this.setValueFontSize}
|
||||
value={fontSizeOptions.find(option => option.value === valueFontSize)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="gf-form">
|
||||
<FormLabel width={labelWidth}>Postfix</FormLabel>
|
||||
<Select
|
||||
width={12}
|
||||
options={fontSizeOptions}
|
||||
onChange={this.setPostfixFontSize}
|
||||
value={fontSizeOptions.find(option => option.value === postfixFontSize)}
|
||||
/>
|
||||
</div>
|
||||
</PanelOptionsGroup>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
// Libraries
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
import {
|
||||
PanelEditorProps,
|
||||
ThresholdsEditor,
|
||||
@ -10,12 +11,13 @@ import {
|
||||
FieldPropertiesEditor,
|
||||
PanelOptionsGroup,
|
||||
DataLinksEditor,
|
||||
FormLabel,
|
||||
Select,
|
||||
} from '@grafana/ui';
|
||||
|
||||
import { Threshold, ValueMapping, FieldConfig, DataLink } from '@grafana/data';
|
||||
|
||||
import { SingleStatOptions, SparklineOptions } from './types';
|
||||
import { ColoringEditor } from './ColoringEditor';
|
||||
import { FontSizeEditor } from './FontSizeEditor';
|
||||
import { SingleStatOptions, SparklineOptions, displayModes, colorModes } from './types';
|
||||
import { SparklineEditor } from './SparklineEditor';
|
||||
import {
|
||||
getDataLinksVariableSuggestions,
|
||||
@ -51,6 +53,9 @@ export class SingleStatEditor extends PureComponent<PanelEditorProps<SingleStatO
|
||||
sparkline,
|
||||
});
|
||||
|
||||
onDisplayModeChange = ({ value }: any) => this.props.onOptionsChange({ ...this.props.options, displayMode: value });
|
||||
onColorModeChange = ({ value }: any) => this.props.onOptionsChange({ ...this.props.options, colorMode: value });
|
||||
|
||||
onDefaultsChange = (field: FieldConfig) => {
|
||||
this.onDisplayOptionsChanged({
|
||||
...this.props.options.fieldOptions,
|
||||
@ -77,17 +82,34 @@ export class SingleStatEditor extends PureComponent<PanelEditorProps<SingleStatO
|
||||
<>
|
||||
<PanelOptionsGrid>
|
||||
<PanelOptionsGroup title="Display">
|
||||
<FieldDisplayEditor onChange={this.onDisplayOptionsChanged} value={fieldOptions} />
|
||||
<FieldDisplayEditor onChange={this.onDisplayOptionsChanged} value={fieldOptions} labelWidth={8} />
|
||||
<div className="form-field">
|
||||
<FormLabel width={8}>Display mode</FormLabel>
|
||||
<Select
|
||||
width={12}
|
||||
options={displayModes}
|
||||
defaultValue={displayModes[0]}
|
||||
onChange={this.onDisplayModeChange}
|
||||
value={displayModes.find(item => item.value === options.displayMode)}
|
||||
/>
|
||||
</div>
|
||||
<div className="form-field">
|
||||
<FormLabel width={8}>Color by</FormLabel>
|
||||
<Select
|
||||
width={12}
|
||||
options={colorModes}
|
||||
defaultValue={colorModes[0]}
|
||||
onChange={this.onColorModeChange}
|
||||
value={colorModes.find(item => item.value === options.colorMode)}
|
||||
/>
|
||||
</div>
|
||||
<SparklineEditor options={options.sparkline} onChange={this.onSparklineChanged} />
|
||||
</PanelOptionsGroup>
|
||||
|
||||
<PanelOptionsGroup title="Field (default)">
|
||||
<FieldPropertiesEditor showMinMax={true} onChange={this.onDefaultsChange} value={defaults} />
|
||||
</PanelOptionsGroup>
|
||||
|
||||
<FontSizeEditor options={options} onChange={this.props.onOptionsChange} />
|
||||
<ColoringEditor options={options} onChange={this.props.onOptionsChange} />
|
||||
<SparklineEditor options={options.sparkline} onChange={this.onSparklineChanged} />
|
||||
|
||||
<ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={defaults.thresholds} />
|
||||
</PanelOptionsGrid>
|
||||
|
||||
|
@ -19,10 +19,10 @@ import { getFieldLinksSupplier } from 'app/features/panel/panellinks/linkSupplie
|
||||
|
||||
export class SingleStatPanel extends PureComponent<PanelProps<SingleStatOptions>> {
|
||||
renderValue = (value: FieldDisplay, width: number, height: number): JSX.Element => {
|
||||
let sparkline: BigValueSparkline;
|
||||
if (value.sparkline) {
|
||||
const { timeRange, options } = this.props;
|
||||
const { timeRange, options } = this.props;
|
||||
let sparkline: BigValueSparkline | undefined;
|
||||
|
||||
if (value.sparkline) {
|
||||
sparkline = {
|
||||
...options.sparkline,
|
||||
data: value.sparkline,
|
||||
@ -38,6 +38,7 @@ export class SingleStatPanel extends PureComponent<PanelProps<SingleStatOptions>
|
||||
<BigValue
|
||||
value={value.display}
|
||||
sparkline={sparkline}
|
||||
displayMode={options.displayMode}
|
||||
width={width}
|
||||
height={height}
|
||||
theme={config.theme}
|
||||
@ -52,6 +53,7 @@ export class SingleStatPanel extends PureComponent<PanelProps<SingleStatOptions>
|
||||
|
||||
getValues = (): FieldDisplay[] => {
|
||||
const { data, options, replaceVariables } = this.props;
|
||||
|
||||
return getFieldDisplayValues({
|
||||
...options,
|
||||
replaceVariables,
|
||||
|
@ -2,14 +2,12 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
// Components
|
||||
import { Switch, PanelOptionsGroup } from '@grafana/ui';
|
||||
import { Switch } from '@grafana/ui';
|
||||
|
||||
// Types
|
||||
import { SparklineOptions } from './types';
|
||||
|
||||
const labelWidth = 6;
|
||||
|
||||
export interface Props {
|
||||
interface Props {
|
||||
options: SparklineOptions;
|
||||
onChange: (options: SparklineOptions) => void;
|
||||
}
|
||||
@ -17,17 +15,9 @@ export interface Props {
|
||||
export class SparklineEditor extends PureComponent<Props> {
|
||||
onToggleShow = () => this.props.onChange({ ...this.props.options, show: !this.props.options.show });
|
||||
|
||||
onToggleFull = () => this.props.onChange({ ...this.props.options, full: !this.props.options.full });
|
||||
|
||||
render() {
|
||||
const { show, full } = this.props.options;
|
||||
const { show } = this.props.options;
|
||||
|
||||
return (
|
||||
<PanelOptionsGroup title="Sparkline">
|
||||
<Switch label="Show" labelClass={`width-${labelWidth}`} checked={show} onChange={this.onToggleShow} />
|
||||
|
||||
<Switch label="Full Height" labelClass={`width-${labelWidth}`} checked={full} onChange={this.onToggleFull} />
|
||||
</PanelOptionsGroup>
|
||||
);
|
||||
return <Switch label="Graph" labelClass="width-8" checked={show} onChange={this.onToggleShow} />;
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +1,35 @@
|
||||
import { VizOrientation, SingleStatBaseOptions, FieldDisplayOptions } from '@grafana/ui';
|
||||
import { VizOrientation, SingleStatBaseOptions, FieldDisplayOptions, SingleStatDisplayMode } from '@grafana/ui';
|
||||
import { ReducerID } from '@grafana/data';
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
|
||||
export interface SparklineOptions {
|
||||
show: boolean;
|
||||
full: boolean; // full height
|
||||
fillColor: string;
|
||||
lineColor: string;
|
||||
}
|
||||
|
||||
// Structure copied from angular
|
||||
export interface SingleStatOptions extends SingleStatBaseOptions {
|
||||
prefixFontSize?: string;
|
||||
valueFontSize?: string;
|
||||
postfixFontSize?: string;
|
||||
colorBackground: boolean;
|
||||
colorValue: boolean;
|
||||
colorPrefix: boolean;
|
||||
colorPostfix: boolean;
|
||||
sparkline: SparklineOptions;
|
||||
colorMode: ColorMode;
|
||||
displayMode: SingleStatDisplayMode;
|
||||
}
|
||||
|
||||
export const displayModes: Array<SelectableValue<SingleStatDisplayMode>> = [
|
||||
{ value: SingleStatDisplayMode.Classic, label: 'Classic' },
|
||||
{ value: SingleStatDisplayMode.Classic2, label: 'Classic 2' },
|
||||
{ value: SingleStatDisplayMode.Vibrant, label: 'Vibrant' },
|
||||
{ value: SingleStatDisplayMode.Vibrant2, label: 'Vibrant 2' },
|
||||
];
|
||||
|
||||
export enum ColorMode {
|
||||
Thresholds,
|
||||
Series,
|
||||
}
|
||||
|
||||
export const colorModes: Array<SelectableValue<ColorMode>> = [
|
||||
{ value: ColorMode.Thresholds, label: 'Thresholds' },
|
||||
{ value: ColorMode.Series, label: 'Series' },
|
||||
];
|
||||
|
||||
export const standardFieldDisplayOptions: FieldDisplayOptions = {
|
||||
values: false,
|
||||
calcs: [ReducerID.mean],
|
||||
@ -38,14 +48,9 @@ export const standardFieldDisplayOptions: FieldDisplayOptions = {
|
||||
export const defaults: SingleStatOptions = {
|
||||
sparkline: {
|
||||
show: true,
|
||||
full: false,
|
||||
lineColor: 'rgb(31, 120, 193)',
|
||||
fillColor: 'rgba(31, 118, 189, 0.18)',
|
||||
},
|
||||
colorMode: ColorMode.Thresholds,
|
||||
displayMode: SingleStatDisplayMode.Vibrant,
|
||||
fieldOptions: standardFieldDisplayOptions,
|
||||
orientation: VizOrientation.Auto,
|
||||
colorBackground: false,
|
||||
colorValue: false,
|
||||
colorPrefix: false,
|
||||
colorPostfix: false,
|
||||
};
|
||||
|
@ -386,3 +386,7 @@ a.external-link {
|
||||
th {
|
||||
font-weight: $font-weight-semi-bold;
|
||||
}
|
||||
|
||||
canvas {
|
||||
display: block;
|
||||
}
|
||||
|
@ -40,7 +40,8 @@ const localStorageMock = (() => {
|
||||
})();
|
||||
|
||||
global.localStorage = localStorageMock;
|
||||
// Object.defineProperty(window, 'localStorage', { value: localStorageMock });
|
||||
|
||||
HTMLCanvasElement.prototype.getContext = jest.fn() as any;
|
||||
|
||||
const throwUnhandledRejections = () => {
|
||||
process.on('unhandledRejection', err => {
|
||||
|
240
yarn.lock
240
yarn.lock
@ -2,6 +2,84 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@antv/adjust@~0.1.0":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@antv/adjust/-/adjust-0.1.1.tgz#e263ab0e1a1941a648842fc086cf65a7e3b75e98"
|
||||
integrity sha512-9FaMOyBlM4AgoRL0b5o0VhEKAYkexBNUrxV8XmpHU/9NBPJONBOB/NZUlQDqxtLItrt91tCfbAuMQmF529UX2Q==
|
||||
dependencies:
|
||||
"@antv/util" "~1.3.1"
|
||||
|
||||
"@antv/attr@~0.1.2":
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@antv/attr/-/attr-0.1.2.tgz#2eeb122fcaaf851a2d8749abc7c60519d3f77e37"
|
||||
integrity sha512-QXjP+T2I+pJQcwZx1oCA4tipG43vgeCeKcGGKahlcxb71OBAzjJZm1QbF4frKXcnOqRkxVXtCr70X9TRair3Ew==
|
||||
dependencies:
|
||||
"@antv/util" "~1.3.1"
|
||||
|
||||
"@antv/component@~0.3.2":
|
||||
version "0.3.5"
|
||||
resolved "https://registry.yarnpkg.com/@antv/component/-/component-0.3.5.tgz#03f12db9206ae4e2d61c52443b7ff8bf0093e6f4"
|
||||
integrity sha512-ucXFy5bDWAyEM/sRUOQJQHz3eiTP5J1t9np/y+KdmdvbqBr/B1Y6+X7lE1NzqwEuwKWfHUkVECYgqNQrhAZJWw==
|
||||
dependencies:
|
||||
"@antv/attr" "~0.1.2"
|
||||
"@antv/g" "~3.3.5"
|
||||
"@antv/util" "~1.3.1"
|
||||
wolfy87-eventemitter "~5.1.0"
|
||||
|
||||
"@antv/coord@~0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@antv/coord/-/coord-0.1.0.tgz#48a80ae36d07552f96657e7f8095227c63f0c0a9"
|
||||
integrity sha512-W1R8h3Jfb3AfMBVfCreFPMVetgEYuwHBIGn0+d3EgYXe2ckOF8XWjkpGF1fZhOMHREMr+Gt27NGiQh8yBdLUgg==
|
||||
dependencies:
|
||||
"@antv/util" "~1.3.1"
|
||||
|
||||
"@antv/g2@3.5.8-beta.1":
|
||||
version "3.5.8-beta.1"
|
||||
resolved "https://registry.yarnpkg.com/@antv/g2/-/g2-3.5.8-beta.1.tgz#71ba5b065ce513be916ceca258d2a02e1ea8e441"
|
||||
integrity sha512-Lpq9rPDZI2mJzlaeY3qZ6R/Asb1wz6xopRmekOn3TXl8kzgQjp2m0U35gO7M2/Z+HxYOafzVjHkxCLuicsEuQw==
|
||||
dependencies:
|
||||
"@antv/adjust" "~0.1.0"
|
||||
"@antv/attr" "~0.1.2"
|
||||
"@antv/component" "~0.3.2"
|
||||
"@antv/coord" "~0.1.0"
|
||||
"@antv/g" "~3.3.6"
|
||||
"@antv/scale" "~0.1.1"
|
||||
"@antv/util" "~1.3.1"
|
||||
venn.js "~0.2.20"
|
||||
wolfy87-eventemitter "~5.1.0"
|
||||
|
||||
"@antv/g@~3.3.5", "@antv/g@~3.3.6":
|
||||
version "3.3.6"
|
||||
resolved "https://registry.yarnpkg.com/@antv/g/-/g-3.3.6.tgz#11fed9ddc9ed4e5a2aa244b7c8abb982a003f201"
|
||||
integrity sha512-2GtyTz++s0BbN6s0ZL2/nrqGYCkd52pVoNH92YkrTdTOvpO6Z4DNoo6jGVgZdPX6Nzwli6yduC8MinVAhE8X6g==
|
||||
dependencies:
|
||||
"@antv/gl-matrix" "~2.7.1"
|
||||
"@antv/util" "~1.3.1"
|
||||
d3-ease "~1.0.3"
|
||||
d3-interpolate "~1.1.5"
|
||||
d3-timer "~1.0.6"
|
||||
wolfy87-eventemitter "~5.1.0"
|
||||
|
||||
"@antv/gl-matrix@^2.7.1", "@antv/gl-matrix@~2.7.1":
|
||||
version "2.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@antv/gl-matrix/-/gl-matrix-2.7.1.tgz#acb8e37f7ab3df01345aba4372d7942be42eba14"
|
||||
integrity sha512-oOWcVNlpELIKi9x+Mm1Vwbz8pXfkbJKykoCIOJ/dNK79hSIANbpXJ5d3Rra9/wZqK6MC961B7sybFhPlLraT3Q==
|
||||
|
||||
"@antv/scale@~0.1.1":
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@antv/scale/-/scale-0.1.3.tgz#4876e6140cb7dcda190e7fe2e780882dcac6b09d"
|
||||
integrity sha512-oknlOg4OUqIh8LygrfQttx+OAnNJm2fQ81si4g8aby1WJJwj/TU1gCr+J3loIpKBtBK4VpP/OzTTqg1Ym67SOQ==
|
||||
dependencies:
|
||||
"@antv/util" "~1.3.1"
|
||||
fecha "~2.3.3"
|
||||
|
||||
"@antv/util@~1.3.1":
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@antv/util/-/util-1.3.1.tgz#30a34b201ff9126ec0d58c72c8166a9c3e644ccd"
|
||||
integrity sha512-cbUta0hIJrKEaW3eKoGarz3Ita+9qUPF2YzTj8A6wds/nNiy20G26ztIWHU+5ThLc13B1n5Ik52LbaCaeg9enA==
|
||||
dependencies:
|
||||
"@antv/gl-matrix" "^2.7.1"
|
||||
|
||||
"@babel/code-frame@7.0.0", "@babel/code-frame@^7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8"
|
||||
@ -4812,6 +4890,18 @@ binary-extensions@^1.0.0:
|
||||
version "1.13.1"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
|
||||
|
||||
bizcharts@^3.5.5:
|
||||
version "3.5.5"
|
||||
resolved "https://registry.yarnpkg.com/bizcharts/-/bizcharts-3.5.5.tgz#108fb79c6dd203456361effbe3558b08ed82bf0e"
|
||||
integrity sha512-2qTwWAylfPGdGX81u26a5t4IKUVHGbTK/lga873Wf+1/9mhG0TN6kLKmTpsPN9WKJmdDjFnZugFyNtB1bUWcKA==
|
||||
dependencies:
|
||||
"@antv/g2" "3.5.8-beta.1"
|
||||
invariant "^2.2.2"
|
||||
lodash.debounce "^4.0.8"
|
||||
prop-types "^15.6.0"
|
||||
resize-observer-polyfill "^1.5.1"
|
||||
warning "^3.0.0"
|
||||
|
||||
bl@^1.0.0:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c"
|
||||
@ -5879,6 +5969,11 @@ content-type@~1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
||||
|
||||
contour_plot@^0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/contour_plot/-/contour_plot-0.0.1.tgz#475870f032b8e338412aa5fc507880f0bf495c77"
|
||||
integrity sha1-R1hw8DK44zhBKqX8UHiA8L9JXHc=
|
||||
|
||||
conventional-changelog-angular@^5.0.3:
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.3.tgz#299fdd43df5a1f095283ac16aeedfb0a682ecab0"
|
||||
@ -6571,7 +6666,7 @@ d3-dsv@1.0.8:
|
||||
iconv-lite "0.4"
|
||||
rw "1"
|
||||
|
||||
d3-ease@1:
|
||||
d3-ease@1, d3-ease@~1.0.3:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-1.0.5.tgz#8ce59276d81241b1b72042d6af2d40e76d936ffb"
|
||||
|
||||
@ -6637,7 +6732,7 @@ d3-interpolate@1:
|
||||
dependencies:
|
||||
d3-color "1"
|
||||
|
||||
d3-interpolate@1.1.6:
|
||||
d3-interpolate@1.1.6, d3-interpolate@~1.1.5:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.1.6.tgz#2cf395ae2381804df08aa1bf766b7f97b5f68fb6"
|
||||
dependencies:
|
||||
@ -6726,7 +6821,7 @@ d3-scale@2:
|
||||
d3-time "1"
|
||||
d3-time-format "2"
|
||||
|
||||
d3-selection@1, d3-selection@^1.1.0:
|
||||
d3-selection@1, d3-selection@^1.0.2, d3-selection@^1.1.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.4.0.tgz#ab9ac1e664cf967ebf1b479cc07e28ce9908c474"
|
||||
|
||||
@ -6766,7 +6861,7 @@ d3-time@1.0.8:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.0.8.tgz#dbd2d6007bf416fe67a76d17947b784bffea1e84"
|
||||
|
||||
d3-timer@1:
|
||||
d3-timer@1, d3-timer@~1.0.6:
|
||||
version "1.0.9"
|
||||
resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.9.tgz#f7bb8c0d597d792ff7131e1c24a36dd471a471ba"
|
||||
|
||||
@ -6774,7 +6869,7 @@ d3-timer@1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.7.tgz#df9650ca587f6c96607ff4e60cc38229e8dd8531"
|
||||
|
||||
d3-transition@1:
|
||||
d3-transition@1, d3-transition@^1.0.1:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-1.2.0.tgz#f538c0e21b2aa1f05f3e965f8567e81284b3b2b8"
|
||||
dependencies:
|
||||
@ -7006,7 +7101,7 @@ deep-diff@^0.3.5:
|
||||
version "0.3.8"
|
||||
resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.8.tgz#c01de63efb0eec9798801d40c7e0dae25b582c84"
|
||||
|
||||
deep-equal@^1.0.1:
|
||||
deep-equal@^1.0.1, deep-equal@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
|
||||
|
||||
@ -7071,6 +7166,11 @@ define-property@^2.0.2:
|
||||
is-descriptor "^1.0.2"
|
||||
isobject "^3.0.1"
|
||||
|
||||
defined@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
|
||||
integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=
|
||||
|
||||
del@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5"
|
||||
@ -8145,6 +8245,11 @@ fd-slicer@~1.0.1:
|
||||
dependencies:
|
||||
pend "~1.2.0"
|
||||
|
||||
fecha@~2.3.3:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fecha/-/fecha-2.3.3.tgz#948e74157df1a32fd1b12c3a3c3cdcb6ec9d96cd"
|
||||
integrity sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==
|
||||
|
||||
figgy-pudding@^3.4.1, figgy-pudding@^3.5.1:
|
||||
version "3.5.1"
|
||||
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
|
||||
@ -8328,6 +8433,17 @@ flush-write-stream@^1.0.0:
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^2.3.6"
|
||||
|
||||
fmin@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/fmin/-/fmin-0.0.2.tgz#59bbb40d43ffdc1c94cd00a568c41f95f1973017"
|
||||
integrity sha1-Wbu0DUP/3ByUzQClaMQflfGXMBc=
|
||||
dependencies:
|
||||
contour_plot "^0.0.1"
|
||||
json2module "^0.0.3"
|
||||
rollup "^0.25.8"
|
||||
tape "^4.5.1"
|
||||
uglify-js "^2.6.2"
|
||||
|
||||
fn-name@~2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-2.0.1.tgz#5214d7537a4d06a4a301c0cc262feb84188002e7"
|
||||
@ -8348,6 +8464,13 @@ follow-redirects@^1.0.0:
|
||||
dependencies:
|
||||
debug "^3.2.6"
|
||||
|
||||
for-each@~0.3.3:
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
|
||||
integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==
|
||||
dependencies:
|
||||
is-callable "^1.1.3"
|
||||
|
||||
for-in@^0.1.3:
|
||||
version "0.1.8"
|
||||
resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1"
|
||||
@ -8533,7 +8656,7 @@ fstream@^1.0.0, fstream@^1.0.2:
|
||||
mkdirp ">=0.5 0"
|
||||
rimraf "2"
|
||||
|
||||
function-bind@^1.0.2, function-bind@^1.1.1:
|
||||
function-bind@^1.0.2, function-bind@^1.1.1, function-bind@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
|
||||
@ -8801,7 +8924,7 @@ glob@7.1.3, glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^7.1.3, glob@^7.1.4:
|
||||
glob@^7.1.3, glob@^7.1.4, glob@~7.1.4:
|
||||
version "7.1.4"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255"
|
||||
integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==
|
||||
@ -9221,7 +9344,7 @@ has-values@^1.0.0:
|
||||
is-number "^3.0.0"
|
||||
kind-of "^4.0.0"
|
||||
|
||||
has@^1.0.0, has@^1.0.1, has@^1.0.3:
|
||||
has@^1.0.0, has@^1.0.1, has@^1.0.3, has@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||
dependencies:
|
||||
@ -9702,7 +9825,7 @@ inflight@^1.0.4, inflight@~1.0.6:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
|
||||
inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
@ -10908,6 +11031,13 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
||||
|
||||
json2module@^0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/json2module/-/json2module-0.0.3.tgz#00fb5f4a9b7adfc3f0647c29cb17bcd1979be9b2"
|
||||
integrity sha1-APtfSpt638PwZHwpyxe80Zeb6bI=
|
||||
dependencies:
|
||||
rw "^1.3.2"
|
||||
|
||||
json3@^3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
|
||||
@ -12056,7 +12186,7 @@ minimist@1.1.x:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8"
|
||||
|
||||
minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
|
||||
minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
|
||||
|
||||
@ -12893,7 +13023,7 @@ object-hash@^1.1.8:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df"
|
||||
|
||||
object-inspect@^1.6.0:
|
||||
object-inspect@^1.6.0, object-inspect@~1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b"
|
||||
|
||||
@ -15908,6 +16038,13 @@ resolve@1.x, resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2, resolve@^1.8.1:
|
||||
dependencies:
|
||||
path-parse "^1.0.6"
|
||||
|
||||
resolve@~1.11.1:
|
||||
version "1.11.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e"
|
||||
integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==
|
||||
dependencies:
|
||||
path-parse "^1.0.6"
|
||||
|
||||
restore-cursor@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
|
||||
@ -15931,6 +16068,13 @@ restructured@0.0.11:
|
||||
power-assert "^1.2.0"
|
||||
unist-util-map "^1.0.2"
|
||||
|
||||
resumer@~0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759"
|
||||
integrity sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=
|
||||
dependencies:
|
||||
through "~2.3.4"
|
||||
|
||||
ret@~0.1.10:
|
||||
version "0.1.15"
|
||||
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
|
||||
@ -16056,6 +16200,15 @@ rollup@1.6.0:
|
||||
"@types/node" "^11.9.5"
|
||||
acorn "^6.1.1"
|
||||
|
||||
rollup@^0.25.8:
|
||||
version "0.25.8"
|
||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.25.8.tgz#bf6ce83b87510d163446eeaa577ed6a6fc5835e0"
|
||||
integrity sha1-v2zoO4dRDRY0Ru6qV37WpvxYNeA=
|
||||
dependencies:
|
||||
chalk "^1.1.1"
|
||||
minimist "^1.2.0"
|
||||
source-map-support "^0.3.2"
|
||||
|
||||
rst-selector-parser@^2.2.3:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz#81b230ea2fcc6066c89e3472de794285d9b03d91"
|
||||
@ -16101,7 +16254,7 @@ run-queue@^1.0.0, run-queue@^1.0.3:
|
||||
dependencies:
|
||||
aproba "^1.1.1"
|
||||
|
||||
rw@1:
|
||||
rw@1, rw@^1.3.2:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
|
||||
|
||||
@ -16732,6 +16885,13 @@ source-map-resolve@^0.5.0:
|
||||
source-map-url "^0.4.0"
|
||||
urix "^0.1.0"
|
||||
|
||||
source-map-support@^0.3.2:
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.3.3.tgz#34900977d5ba3f07c7757ee72e73bb1a9b53754f"
|
||||
integrity sha1-NJAJd9W6PwfHdX7nLnO7GptTdU8=
|
||||
dependencies:
|
||||
source-map "0.1.32"
|
||||
|
||||
source-map-support@^0.5.6, source-map-support@~0.5.10:
|
||||
version "0.5.12"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599"
|
||||
@ -16743,6 +16903,13 @@ source-map-url@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
|
||||
|
||||
source-map@0.1.32:
|
||||
version "0.1.32"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.32.tgz#c8b6c167797ba4740a8ea33252162ff08591b266"
|
||||
integrity sha1-yLbBZ3l7pHQKjqMyUhYv8IWRsmY=
|
||||
dependencies:
|
||||
amdefine ">=0.0.4"
|
||||
|
||||
source-map@0.4.x, source-map@^0.4.2, source-map@~0.4.1:
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
|
||||
@ -17061,7 +17228,7 @@ string.prototype.padstart@^3.0.0:
|
||||
es-abstract "^1.4.3"
|
||||
function-bind "^1.0.2"
|
||||
|
||||
string.prototype.trim@^1.1.2:
|
||||
string.prototype.trim@^1.1.2, string.prototype.trim@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea"
|
||||
dependencies:
|
||||
@ -17322,6 +17489,25 @@ tapable@^1.0.0, tapable@^1.1.0:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
|
||||
|
||||
tape@^4.5.1:
|
||||
version "4.11.0"
|
||||
resolved "https://registry.yarnpkg.com/tape/-/tape-4.11.0.tgz#63d41accd95e45a23a874473051c57fdbc58edc1"
|
||||
integrity sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA==
|
||||
dependencies:
|
||||
deep-equal "~1.0.1"
|
||||
defined "~1.0.0"
|
||||
for-each "~0.3.3"
|
||||
function-bind "~1.1.1"
|
||||
glob "~7.1.4"
|
||||
has "~1.0.3"
|
||||
inherits "~2.0.4"
|
||||
minimist "~1.2.0"
|
||||
object-inspect "~1.6.0"
|
||||
resolve "~1.11.1"
|
||||
resumer "~0.0.0"
|
||||
string.prototype.trim "~1.1.2"
|
||||
through "~2.3.8"
|
||||
|
||||
tar-fs@^1.13.0:
|
||||
version "1.16.3"
|
||||
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509"
|
||||
@ -17503,7 +17689,7 @@ through2@^3.0.0:
|
||||
dependencies:
|
||||
readable-stream "2 || 3"
|
||||
|
||||
through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@~2.3.6:
|
||||
through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@~2.3.4, through@~2.3.6, through@~2.3.8:
|
||||
version "2.3.8"
|
||||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
|
||||
@ -17891,6 +18077,16 @@ uglify-js@3.4.x:
|
||||
commander "~2.19.0"
|
||||
source-map "~0.6.1"
|
||||
|
||||
uglify-js@^2.6.2:
|
||||
version "2.8.29"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
|
||||
integrity sha1-KcVzMUgFe7Th913zW3qcty5qWd0=
|
||||
dependencies:
|
||||
source-map "~0.5.1"
|
||||
yargs "~3.10.0"
|
||||
optionalDependencies:
|
||||
uglify-to-browserify "~1.0.0"
|
||||
|
||||
uglify-js@^3.1.4:
|
||||
version "3.5.11"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.5.11.tgz#833442c0aa29b3a7d34344c7c63adaa3f3504f6a"
|
||||
@ -18231,6 +18427,15 @@ vendors@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.2.tgz#7fcb5eef9f5623b156bcea89ec37d63676f21801"
|
||||
|
||||
venn.js@~0.2.20:
|
||||
version "0.2.20"
|
||||
resolved "https://registry.yarnpkg.com/venn.js/-/venn.js-0.2.20.tgz#3f0e50cc75cba1f58692a8a32f67bd7aaf1aa6fa"
|
||||
integrity sha512-bb5SYq/wamY9fvcuErb9a0FJkgIFHJjkLZWonQ+DoKKuDX3WPH2B4ouI1ce4K2iejBklQy6r1ly8nOGIyOCO6w==
|
||||
dependencies:
|
||||
d3-selection "^1.0.2"
|
||||
d3-transition "^1.0.1"
|
||||
fmin "0.0.2"
|
||||
|
||||
verror@1.10.0:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
|
||||
@ -18648,6 +18853,11 @@ windows-release@^3.1.0:
|
||||
dependencies:
|
||||
execa "^1.0.0"
|
||||
|
||||
wolfy87-eventemitter@~5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/wolfy87-eventemitter/-/wolfy87-eventemitter-5.1.0.tgz#35c1ac0dd1ac0c15e35d981508fc22084a13a011"
|
||||
integrity sha1-NcGsDdGsDBXjXZgVCPwiCEoToBE=
|
||||
|
||||
wordwrap@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
|
||||
|
Loading…
Reference in New Issue
Block a user