Merge branch 'master' into develop
This commit is contained in:
commit
b44daaabf2
69 files changed
+1284
-654
No files matched your search
@@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
test -z "$(gofmt -s -l . | grep -v vendor/src/ | tee /dev/stderr)"
|
||||
if [ $? -gt 0 ]; then
|
||||
echo "Some files aren't formatted, please run 'go fmt ./pkg/...' to format your source code before committing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
grunt test
|
||||
+4
-3
@@ -12,15 +12,16 @@
|
||||
## New Features
|
||||
* **Data Source Proxy**: Add support for whitelisting specified cookies that will be passed through to the data source when proxying data source requests [#5457](https://github.com/grafana/grafana/issues/5457), thanks [@robingustafsson](https://github.com/robingustafsson)
|
||||
|
||||
* **Postgres**: modify group by time macro so it can be used in select clause [#9527](https://github.com/grafana/grafana/pull/9527), thanks [@svenklemm](https://github.com/svenklemm)
|
||||
|
||||
## Fixes
|
||||
* **Sensu**: Send alert message to sensu output [#9551](https://github.com/grafana/grafana/issues/9551), thx [@cjchand](https://github.com/cjchand)
|
||||
|
||||
# 4.6.0-beta3 (unreleased)
|
||||
# 4.6.0-beta3 (2017-10-23)
|
||||
|
||||
## Fixes
|
||||
* **Prometheus**: Fix for browser crash for short time ranges. [#9575](https://github.com/grafana/grafana/issues/9575)
|
||||
* **Heatmap**: Fix for y-axis not showing. [#9576](https://github.com/grafana/grafana/issues/9576)
|
||||
* **Save to file**: Fix for save to file in export modal. [#9586](https://github.com/grafana/grafana/issues/9586)
|
||||
* **Postgres**: modify group by time macro so it can be used in select clause [#9527](https://github.com/grafana/grafana/pull/9527), thanks [@svenklemm](https://github.com/svenklemm)
|
||||
|
||||
# 4.6.0-beta2 (2017-10-17)
|
||||
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
machine:
|
||||
node:
|
||||
version: 6.9.2
|
||||
version: 6.11.4
|
||||
python:
|
||||
version: 2.7.3
|
||||
services:
|
||||
@@ -30,10 +30,10 @@ dependencies:
|
||||
- sudo apt-get update; sudo apt-get install rpm; sudo apt-get install expect
|
||||
- ./scripts/build/build_container.sh
|
||||
|
||||
|
||||
test:
|
||||
override:
|
||||
- bash scripts/circle-test.sh
|
||||
- bash scripts/circle-test-frontend.sh
|
||||
- bash scripts/circle-test-backend.sh
|
||||
|
||||
deployment:
|
||||
gh_branch:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
+++
|
||||
title = "Data Sources"
|
||||
type = "docs"
|
||||
aliases = ["/datasources/overview/"]
|
||||
[menu.docs]
|
||||
name = "Data Sources"
|
||||
identifier = "datasources"
|
||||
|
||||
@@ -68,6 +68,7 @@ This makes exploring and filtering Prometheus data much easier.
|
||||
* **Opsgenie**: Use their latest API instead of old version [#9399](https://github.com/grafana/grafana/pull/9399), thx [@cglrkn](https://github.com/cglrkn)
|
||||
* **Table**: Add support for displaying the timestamp with milliseconds [#9429](https://github.com/grafana/grafana/pull/9429), thx [@s1061123](https://github.com/s1061123)
|
||||
* **Hipchat**: Add metrics, message and image to hipchat notifications [#9110](https://github.com/grafana/grafana/issues/9110), thx [@eloo](https://github.com/eloo)
|
||||
* **Postgres**: modify group by time macro so it can be used in select clause [#9527](https://github.com/grafana/grafana/pull/9527), thanks [@svenklemm](https://github.com/svenklemm)
|
||||
|
||||
### Tech
|
||||
* **Go**: Grafana is now built using golang 1.9
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ module.exports = {
|
||||
"transform": {
|
||||
"^.+\\.tsx?$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
|
||||
},
|
||||
"moduleDirectories": ["<rootDir>node_modules", "<rootDir>/public"],
|
||||
"moduleDirectories": ["<rootDir>/node_modules", "<rootDir>/public"],
|
||||
"roots": [
|
||||
"<rootDir>/public"
|
||||
],
|
||||
|
||||
+12
-9
@@ -95,14 +95,15 @@
|
||||
"zone.js": "^0.7.2"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "./node_modules/.bin/webpack --progress --colors --config scripts/webpack/webpack.dev.js",
|
||||
"watch": "./node_modules/.bin/webpack --progress --colors --watch --config scripts/webpack/webpack.dev.js",
|
||||
"build": "./node_modules/.bin/grunt build",
|
||||
"test": "./node_modules/.bin/grunt test",
|
||||
"test-ci": "./node_modules/.bin/grunt test --coverage=true",
|
||||
"lint": "./node_modules/.bin/tslint -c tslint.json --project tsconfig.json --type-check",
|
||||
"karma": "./node_modules/grunt-cli/bin/grunt karma:dev",
|
||||
"jest": "./node_modules/jest-cli/bin/jest --notify --watch"
|
||||
"dev": "node ./node_modules/.bin/webpack --progress --colors --config scripts/webpack/webpack.dev.js",
|
||||
"watch": "node ./node_modules/.bin/webpack --progress --colors --watch --config scripts/webpack/webpack.dev.js",
|
||||
"build": "node ./node_modules/.bin/grunt build",
|
||||
"test": "node ./node_modules/.bin/grunt test",
|
||||
"test:coverage": "node ./node_modules/.bin/grunt test --coverage=true",
|
||||
"lint": "node ./node_modules/.bin/tslint -c tslint.json --project tsconfig.json --type-check",
|
||||
"karma": "node ./node_modules/grunt-cli/bin/grunt karma:dev",
|
||||
"jest": "node ./node_modules/jest-cli/bin/jest.js --notify --watch",
|
||||
"precommit": "node ./node_modules/grunt-cli/bin/grunt precommit"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
@@ -133,6 +134,8 @@
|
||||
"rxjs": "^5.4.3",
|
||||
"tether": "^1.4.0",
|
||||
"tether-drop": "https://github.com/torkelo/drop",
|
||||
"tinycolor2": "^1.4.1"
|
||||
"tinycolor2": "^1.4.1",
|
||||
"d3": "^4.11.0",
|
||||
"d3-scale-chromatic": "^1.1.1"
|
||||
}
|
||||
}
|
||||
@@ -188,9 +188,8 @@ func (hs *HttpServer) metricsEndpoint(ctx *macaron.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{
|
||||
DisableCompression: true,
|
||||
}).ServeHTTP(ctx.Resp, ctx.Req.Request)
|
||||
promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{}).
|
||||
ServeHTTP(ctx.Resp, ctx.Req.Request)
|
||||
}
|
||||
|
||||
func (hs *HttpServer) healthHandler(ctx *macaron.Context) {
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@ import (
|
||||
|
||||
"github.com/go-stack/stack"
|
||||
"github.com/inconshreveable/log15"
|
||||
"github.com/inconshreveable/log15/term"
|
||||
isatty "github.com/mattn/go-isatty"
|
||||
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
@@ -157,7 +157,7 @@ func getFilters(filterStrArray []string) map[string]log15.Lvl {
|
||||
func getLogFormat(format string) log15.Format {
|
||||
switch format {
|
||||
case "console":
|
||||
if term.IsTty(os.Stdout.Fd()) {
|
||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||
return log15.TerminalFormat()
|
||||
}
|
||||
return log15.LogfmtFormat()
|
||||
|
||||
@@ -21,6 +21,10 @@ func Gziper() macaron.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasPrefix(requestPath, "/metrics") {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Invoke(macaronGziper)
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ func getPluginLogoUrl(pluginType, path, baseUrl string) string {
|
||||
}
|
||||
|
||||
func (fp *FrontendPluginBase) setPathsBasedOnApp(app *AppPlugin) {
|
||||
appSubPath := strings.Replace(fp.PluginDir, app.PluginDir, "", 1)
|
||||
appSubPath := strings.Replace(strings.Replace(fp.PluginDir, app.PluginDir, "", 1), "\\", "/", 1)
|
||||
fp.IncludedInAppId = app.Id
|
||||
fp.BaseUrl = app.BaseUrl
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestFrontendPlugin(t *testing.T) {
|
||||
|
||||
Convey("When setting paths based on App on Windows", t, func() {
|
||||
setting.StaticRootPath = "c:\\grafana\\public"
|
||||
|
||||
fp := &FrontendPluginBase{
|
||||
PluginBase: PluginBase{
|
||||
PluginDir: "c:\\grafana\\public\\app\\plugins\\app\\testdata\\datasource",
|
||||
BaseUrl: "fpbase",
|
||||
},
|
||||
}
|
||||
app := &AppPlugin{
|
||||
FrontendPluginBase: FrontendPluginBase{
|
||||
PluginBase: PluginBase{
|
||||
PluginDir: "c:\\grafana\\public\\app\\plugins\\app\\testdata",
|
||||
Id: "testdata",
|
||||
BaseUrl: "public/app/plugins/app/testdata",
|
||||
},
|
||||
},
|
||||
}
|
||||
fp.setPathsBasedOnApp(app)
|
||||
|
||||
So(fp.Module, ShouldEqual, "app/plugins/app/testdata/datasource/module")
|
||||
})
|
||||
}
|
||||
+4
-1
@@ -27,7 +27,7 @@ _.move = function (array, fromIndex, toIndex) {
|
||||
return array;
|
||||
};
|
||||
|
||||
import {coreModule} from './core/core';
|
||||
import {coreModule, registerAngularDirectives} from './core/core';
|
||||
|
||||
export class GrafanaApp {
|
||||
registerFunctions: any;
|
||||
@@ -109,6 +109,9 @@ export class GrafanaApp {
|
||||
// makes it possible to add dynamic stuff
|
||||
this.useModule(coreModule);
|
||||
|
||||
// register react angular wrappers
|
||||
registerAngularDirectives();
|
||||
|
||||
var preBootRequires = [System.import('app/features/all')];
|
||||
|
||||
Promise.all(preBootRequires).then(() => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { react2AngularDirective } from 'app/core/utils/react2angular';
|
||||
import { PasswordStrength } from './ui/PasswordStrength';
|
||||
import { PasswordStrength } from './components/PasswordStrength';
|
||||
|
||||
export function registerAngularDirectives() {
|
||||
|
||||
|
||||
File renamed without changes.
@@ -6,7 +6,7 @@ export interface IProps {
|
||||
onColorSelect: (c: string) => void;
|
||||
}
|
||||
|
||||
export class GfColorPalette extends React.Component<IProps, any> {
|
||||
export class ColorPalette extends React.Component<IProps, any> {
|
||||
paletteColors: string[];
|
||||
|
||||
constructor(props) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import $ from 'jquery';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import { GfColorPalette } from './ColorPalette';
|
||||
import { GfSpectrumPicker } from './SpectrumPicker';
|
||||
import { ColorPalette } from './ColorPalette';
|
||||
import { SpectrumPicker } from './SpectrumPicker';
|
||||
|
||||
const DEFAULT_COLOR = '#000000';
|
||||
|
||||
@@ -82,12 +82,12 @@ export class ColorPickerPopover extends React.Component<IProps, any> {
|
||||
render() {
|
||||
const paletteTab = (
|
||||
<div id="palette">
|
||||
<GfColorPalette color={this.state.color} onColorSelect={this.sampleColorSelected.bind(this)} />
|
||||
<ColorPalette color={this.state.color} onColorSelect={this.sampleColorSelected.bind(this)} />
|
||||
</div>
|
||||
);
|
||||
const spectrumTab = (
|
||||
<div id="spectrum">
|
||||
<GfSpectrumPicker color={this.state.color} onColorSelect={this.spectrumColorSelected.bind(this)} options={{}} />
|
||||
<SpectrumPicker color={this.state.color} onColorSelect={this.spectrumColorSelected.bind(this)} options={{}} />
|
||||
</div>
|
||||
);
|
||||
const currentTab = this.state.tab === 'palette' ? paletteTab : spectrumTab;
|
||||
|
||||
@@ -9,7 +9,7 @@ export interface IProps {
|
||||
onColorSelect: (c: string) => void;
|
||||
}
|
||||
|
||||
export class GfSpectrumPicker extends React.Component<IProps, any> {
|
||||
export class SpectrumPicker extends React.Component<IProps, any> {
|
||||
elem: any;
|
||||
isMoving: boolean;
|
||||
|
||||
|
||||
@@ -53,10 +53,9 @@ import {orgSwitcher} from './components/org_switcher';
|
||||
import {profiler} from './profiler';
|
||||
import {registerAngularDirectives} from './angular_wrappers';
|
||||
|
||||
registerAngularDirectives();
|
||||
|
||||
export {
|
||||
profiler,
|
||||
registerAngularDirectives,
|
||||
arrayJoin,
|
||||
coreModule,
|
||||
grafanaAppDirective,
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { ColorPalette } from '../components/colorpicker/ColorPalette';
|
||||
|
||||
describe('CollorPalette', () => {
|
||||
it('renders correctly', () => {
|
||||
const tree = renderer.create(<ColorPalette color="#EAB839" onColorSelect={jest.fn()} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import {shallow} from 'enzyme';
|
||||
|
||||
import {PasswordStrength} from '../ui/PasswordStrength';
|
||||
import {PasswordStrength} from '../components/PasswordStrength';
|
||||
|
||||
describe('PasswordStrength', () => {
|
||||
|
||||
|
||||
@@ -0,0 +1,628 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CollorPalette renders correctly 1`] = `
|
||||
<div
|
||||
className="graph-legend-popover"
|
||||
>
|
||||
<p
|
||||
className="m-b-0"
|
||||
>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#890f02",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#58140c",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#99440a",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#c15c17",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#967302",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#cca300",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#3f6833",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#2f575e",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#64b0c8",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#052b51",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#0a50a1",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#584477",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#3f2b5b",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#511749",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#e24d42",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#bf1b00",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#ef843c",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#f4d598",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#e5ac0e",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#9ac48a",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#508642",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#6ed0e0",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#65c5db",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#0a437c",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#447ebc",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#614d93",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#d683ce",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#6d1f62",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#ea6460",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#e0752d",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#f9934e",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#fceaca",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle-o"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#eab839",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#b7dbab",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#629e51",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#70dbed",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#82b5d8",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#1f78c1",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#aea2e0",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#705da0",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#e5a8e2",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#962d82",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#f29191",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#fce2de",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#f9ba8f",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#f9e2d2",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#f2c96d",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#e0f9d7",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#7eb26d",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#cffaff",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#badff4",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#5195ce",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#dedaf7",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#806eb7",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#f9d9f9",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#ba43a9",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
</p>
|
||||
</div>
|
||||
`;
|
||||
@@ -1,5 +1,3 @@
|
||||
///<reference path="../headers/common.d.ts" />
|
||||
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import _ from 'lodash';
|
||||
|
||||
@@ -23,6 +21,7 @@ export default class TimeSeries {
|
||||
id: string;
|
||||
label: string;
|
||||
alias: string;
|
||||
aliasEscaped: string;
|
||||
color: string;
|
||||
valueFormater: any;
|
||||
stats: any;
|
||||
@@ -52,6 +51,7 @@ export default class TimeSeries {
|
||||
this.label = opts.alias;
|
||||
this.id = opts.alias;
|
||||
this.alias = opts.alias;
|
||||
this.aliasEscaped = _.escape(opts.alias);
|
||||
this.color = opts.color;
|
||||
this.valueFormater = kbn.valueFormats.none;
|
||||
this.stats = {};
|
||||
|
||||
@@ -3,6 +3,7 @@ import './editor_ctrl';
|
||||
import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
import coreModule from 'app/core/core_module';
|
||||
import {makeRegions, dedupAnnotations} from './events_processing';
|
||||
|
||||
export class AnnotationsSrv {
|
||||
globalAnnotationsPromise: any;
|
||||
@@ -161,83 +162,4 @@ export class AnnotationsSrv {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function converts annotation events into set
|
||||
* of single events and regions (event consist of two)
|
||||
* @param annotations
|
||||
* @param options
|
||||
*/
|
||||
function makeRegions(annotations, options) {
|
||||
let [regionEvents, singleEvents] = _.partition(annotations, 'regionId');
|
||||
let regions = getRegions(regionEvents, options.range);
|
||||
annotations = _.concat(regions, singleEvents);
|
||||
return annotations;
|
||||
}
|
||||
|
||||
function getRegions(events, range) {
|
||||
let region_events = _.filter(events, event => {
|
||||
return event.regionId;
|
||||
});
|
||||
let regions = _.groupBy(region_events, 'regionId');
|
||||
regions = _.compact(
|
||||
_.map(regions, region_events => {
|
||||
let region_obj = _.head(region_events);
|
||||
if (region_events && region_events.length > 1) {
|
||||
region_obj.timeEnd = region_events[1].time;
|
||||
region_obj.isRegion = true;
|
||||
return region_obj;
|
||||
} else {
|
||||
if (region_events && region_events.length) {
|
||||
// Don't change proper region object
|
||||
if (!region_obj.time || !region_obj.timeEnd) {
|
||||
// This is cut region
|
||||
if (isStartOfRegion(region_obj)) {
|
||||
region_obj.timeEnd = range.to.valueOf() - 1;
|
||||
} else {
|
||||
// Start time = null
|
||||
region_obj.timeEnd = region_obj.time;
|
||||
region_obj.time = range.from.valueOf() + 1;
|
||||
}
|
||||
region_obj.isRegion = true;
|
||||
}
|
||||
|
||||
return region_obj;
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
return regions;
|
||||
}
|
||||
|
||||
function isStartOfRegion(event): boolean {
|
||||
return event.id && event.id === event.regionId;
|
||||
}
|
||||
|
||||
function dedupAnnotations(annotations) {
|
||||
let dedup = [];
|
||||
|
||||
// Split events by annotationId property existance
|
||||
let events = _.partition(annotations, 'id');
|
||||
|
||||
let eventsById = _.groupBy(events[0], 'id');
|
||||
dedup = _.map(eventsById, eventGroup => {
|
||||
if (eventGroup.length > 1 && !_.every(eventGroup, isPanelAlert)) {
|
||||
// Get first non-panel alert
|
||||
return _.find(eventGroup, event => {
|
||||
return event.eventType !== 'panel-alert';
|
||||
});
|
||||
} else {
|
||||
return _.head(eventGroup);
|
||||
}
|
||||
});
|
||||
|
||||
dedup = _.concat(dedup, events[1]);
|
||||
return dedup;
|
||||
}
|
||||
|
||||
function isPanelAlert(event) {
|
||||
return event.eventType === 'panel-alert';
|
||||
}
|
||||
|
||||
coreModule.service('annotationsSrv', AnnotationsSrv);
|
||||
@@ -0,0 +1,80 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
/**
|
||||
* This function converts annotation events into set
|
||||
* of single events and regions (event consist of two)
|
||||
* @param annotations
|
||||
* @param options
|
||||
*/
|
||||
export function makeRegions(annotations, options) {
|
||||
let [regionEvents, singleEvents] = _.partition(annotations, 'regionId');
|
||||
let regions = getRegions(regionEvents, options.range);
|
||||
annotations = _.concat(regions, singleEvents);
|
||||
return annotations;
|
||||
}
|
||||
|
||||
function getRegions(events, range) {
|
||||
let region_events = _.filter(events, event => {
|
||||
return event.regionId;
|
||||
});
|
||||
let regions = _.groupBy(region_events, 'regionId');
|
||||
regions = _.compact(
|
||||
_.map(regions, region_events => {
|
||||
let region_obj = _.head(region_events);
|
||||
if (region_events && region_events.length > 1) {
|
||||
region_obj.timeEnd = region_events[1].time;
|
||||
region_obj.isRegion = true;
|
||||
return region_obj;
|
||||
} else {
|
||||
if (region_events && region_events.length) {
|
||||
// Don't change proper region object
|
||||
if (!region_obj.time || !region_obj.timeEnd) {
|
||||
// This is cut region
|
||||
if (isStartOfRegion(region_obj)) {
|
||||
region_obj.timeEnd = range.to.valueOf() - 1;
|
||||
} else {
|
||||
// Start time = null
|
||||
region_obj.timeEnd = region_obj.time;
|
||||
region_obj.time = range.from.valueOf() + 1;
|
||||
}
|
||||
region_obj.isRegion = true;
|
||||
}
|
||||
|
||||
return region_obj;
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
return regions;
|
||||
}
|
||||
|
||||
function isStartOfRegion(event): boolean {
|
||||
return event.id && event.id === event.regionId;
|
||||
}
|
||||
|
||||
export function dedupAnnotations(annotations) {
|
||||
let dedup = [];
|
||||
|
||||
// Split events by annotationId property existance
|
||||
let events = _.partition(annotations, 'id');
|
||||
|
||||
let eventsById = _.groupBy(events[0], 'id');
|
||||
dedup = _.map(eventsById, eventGroup => {
|
||||
if (eventGroup.length > 1 && !_.every(eventGroup, isPanelAlert)) {
|
||||
// Get first non-panel alert
|
||||
return _.find(eventGroup, event => {
|
||||
return event.eventType !== 'panel-alert';
|
||||
});
|
||||
} else {
|
||||
return _.head(eventGroup);
|
||||
}
|
||||
});
|
||||
|
||||
dedup = _.concat(dedup, events[1]);
|
||||
return dedup;
|
||||
}
|
||||
|
||||
function isPanelAlert(event) {
|
||||
return event.eventType === 'panel-alert';
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import {makeRegions, dedupAnnotations} from '../events_processing';
|
||||
|
||||
describe('Annotations', () => {
|
||||
|
||||
describe('Annotations regions', () => {
|
||||
let testAnnotations: any[];
|
||||
|
||||
beforeEach(() => {
|
||||
testAnnotations = [
|
||||
{id: 1, time: 1},
|
||||
{id: 2, time: 2},
|
||||
{id: 3, time: 3, regionId: 3},
|
||||
{id: 4, time: 5, regionId: 3},
|
||||
{id: 5, time: 4, regionId: 5},
|
||||
{id: 6, time: 8, regionId: 5}
|
||||
];
|
||||
});
|
||||
|
||||
it('should convert single region events to regions', () => {
|
||||
const range = {from: 0, to: 10};
|
||||
const expectedAnnotations = [
|
||||
{id: 3, regionId: 3, isRegion: true, time: 3, timeEnd: 5},
|
||||
{id: 5, regionId: 5, isRegion: true, time: 4, timeEnd: 8},
|
||||
{id: 1, time: 1},
|
||||
{id: 2, time: 2}
|
||||
];
|
||||
|
||||
let regions = makeRegions(testAnnotations, {range: range});
|
||||
expect(regions).toEqual(expectedAnnotations);
|
||||
});
|
||||
|
||||
it('should cut regions to current time range', () => {
|
||||
const range = {from: 0, to: 8};
|
||||
testAnnotations = [
|
||||
{id: 5, time: 4, regionId: 5}
|
||||
];
|
||||
const expectedAnnotations = [
|
||||
{id: 5, regionId: 5, isRegion: true, time: 4, timeEnd: 7}
|
||||
];
|
||||
|
||||
let regions = makeRegions(testAnnotations, {range: range});
|
||||
expect(regions).toEqual(expectedAnnotations);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Annotations deduplication', () => {
|
||||
it('should remove duplicated annotations', () => {
|
||||
const testAnnotations = [
|
||||
{id: 1, time: 1},
|
||||
{id: 2, time: 2},
|
||||
{id: 2, time: 2},
|
||||
{id: 5, time: 5},
|
||||
{id: 5, time: 5}
|
||||
];
|
||||
const expectedAnnotations = [
|
||||
{id: 1, time: 1},
|
||||
{id: 2, time: 2},
|
||||
{id: 5, time: 5}
|
||||
];
|
||||
|
||||
let deduplicated = dedupAnnotations(testAnnotations);
|
||||
expect(deduplicated).toEqual(expectedAnnotations);
|
||||
});
|
||||
|
||||
it('should leave non "panel-alert" event if present', () => {
|
||||
const testAnnotations = [
|
||||
{id: 1, time: 1},
|
||||
{id: 2, time: 2},
|
||||
{id: 2, time: 2, eventType: 'panel-alert'},
|
||||
{id: 5, time: 5},
|
||||
{id: 5, time: 5}
|
||||
];
|
||||
const expectedAnnotations = [
|
||||
{id: 1, time: 1},
|
||||
{id: 2, time: 2},
|
||||
{id: 5, time: 5}
|
||||
];
|
||||
|
||||
let deduplicated = dedupAnnotations(testAnnotations);
|
||||
expect(deduplicated).toEqual(expectedAnnotations);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -7,6 +7,7 @@ import {coreModule, JsonExplorer} from 'app/core/core';
|
||||
const template = `
|
||||
<div class="query-troubleshooter" ng-if="ctrl.isOpen">
|
||||
<div class="query-troubleshooter__header">
|
||||
<a class="pointer" ng-click="ctrl.toggleMocking()">Mock Response</a>
|
||||
<a class="pointer" ng-click="ctrl.toggleExpand()" ng-hide="ctrl.allNodesExpanded">
|
||||
<i class="fa fa-plus-square-o"></i> Expand All
|
||||
</a>
|
||||
@@ -15,10 +16,15 @@ const template = `
|
||||
</a>
|
||||
<a class="pointer" clipboard-button="ctrl.getClipboardText()"><i class="fa fa-clipboard"></i> Copy to Clipboard</a>
|
||||
</div>
|
||||
<div class="query-troubleshooter__body">
|
||||
<div class="query-troubleshooter__body" ng-hide="ctrl.isMocking">
|
||||
<i class="fa fa-spinner fa-spin" ng-show="ctrl.isLoading"></i>
|
||||
<div class="query-troubleshooter-json"></div>
|
||||
</div>
|
||||
<div class="query-troubleshooter__body" ng-show="ctrl.isMocking">
|
||||
<div class="gf-form p-l-1 gf-form--v-stretch">
|
||||
<textarea class="gf-form-input" style="width: 95%" rows="10" ng-model="ctrl.mockedResponse" placeholder="JSON"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -32,6 +38,8 @@ export class QueryTroubleshooterCtrl {
|
||||
onRequestResponseEventListener: any;
|
||||
hasError: boolean;
|
||||
allNodesExpanded: boolean;
|
||||
isMocking: boolean;
|
||||
mockedResponse: string;
|
||||
jsonExplorer: JsonExplorer;
|
||||
|
||||
/** @ngInject **/
|
||||
@@ -51,6 +59,10 @@ export class QueryTroubleshooterCtrl {
|
||||
appEvents.off('ds-request-error', this.onRequestErrorEventListener);
|
||||
}
|
||||
|
||||
toggleMocking() {
|
||||
this.isMocking = !this.isMocking;
|
||||
}
|
||||
|
||||
onRequestError(err) {
|
||||
// ignore if closed
|
||||
if (!this.isOpen) {
|
||||
@@ -76,12 +88,29 @@ export class QueryTroubleshooterCtrl {
|
||||
return '';
|
||||
}
|
||||
|
||||
handleMocking(data) {
|
||||
var mockedData;
|
||||
try {
|
||||
mockedData = JSON.parse(this.mockedResponse);
|
||||
} catch (err) {
|
||||
appEvents.emit('alert-error', ['Failed to parse mocked response']);
|
||||
return;
|
||||
}
|
||||
|
||||
data.data = mockedData;
|
||||
}
|
||||
|
||||
onRequestResponse(data) {
|
||||
// ignore if closed
|
||||
if (!this.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isMocking) {
|
||||
this.handleMocking(data);
|
||||
return;
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
data = _.cloneDeep(data);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import * as flatten from 'app/core/utils/flatten';
|
||||
import * as ticks from 'app/core/utils/ticks';
|
||||
import {impressions} from 'app/features/dashboard/impression_store';
|
||||
import builtInPlugins from './built_in_plugins';
|
||||
import d3 from 'vendor/d3/d3';
|
||||
import * as d3 from 'd3';
|
||||
|
||||
// rxjs
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
|
||||
+10
-12
@@ -1,5 +1,3 @@
|
||||
import {describe, it, expect} from 'test/lib/common';
|
||||
|
||||
import {containsVariable, assignModelProperties} from '../variable';
|
||||
|
||||
describe('containsVariable', function() {
|
||||
@@ -8,37 +6,37 @@ describe('containsVariable', function() {
|
||||
|
||||
it('should find it with $var syntax', function() {
|
||||
var contains = containsVariable('this.$test.filters', 'test');
|
||||
expect(contains).to.be(true);
|
||||
expect(contains).toBe(true);
|
||||
});
|
||||
|
||||
it('should not find it if only part matches with $var syntax', function() {
|
||||
var contains = containsVariable('this.$serverDomain.filters', 'server');
|
||||
expect(contains).to.be(false);
|
||||
expect(contains).toBe(false);
|
||||
});
|
||||
|
||||
it('should find it if it ends with variable and passing multiple test strings', function() {
|
||||
var contains = containsVariable('show field keys from $pgmetric', 'test string2', 'pgmetric');
|
||||
expect(contains).to.be(true);
|
||||
expect(contains).toBe(true);
|
||||
});
|
||||
|
||||
it('should find it with [[var]] syntax', function() {
|
||||
var contains = containsVariable('this.[[test]].filters', 'test');
|
||||
expect(contains).to.be(true);
|
||||
expect(contains).toBe(true);
|
||||
});
|
||||
|
||||
it('should find it when part of segment', function() {
|
||||
var contains = containsVariable('metrics.$env.$group-*', 'group');
|
||||
expect(contains).to.be(true);
|
||||
expect(contains).toBe(true);
|
||||
});
|
||||
|
||||
it('should find it its the only thing', function() {
|
||||
var contains = containsVariable('$env', 'env');
|
||||
expect(contains).to.be(true);
|
||||
expect(contains).toBe(true);
|
||||
});
|
||||
|
||||
it('should be able to pass in multiple test strings', function() {
|
||||
var contains = containsVariable('asd','asd2.$env', 'env');
|
||||
expect(contains).to.be(true);
|
||||
expect(contains).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -50,14 +48,14 @@ describe('assignModelProperties', function() {
|
||||
it('only set properties defined in defaults', function() {
|
||||
var target: any = {test: 'asd'};
|
||||
assignModelProperties(target, {propA: 1, propB: 2}, {propB: 0});
|
||||
expect(target.propB).to.be(2);
|
||||
expect(target.test).to.be('asd');
|
||||
expect(target.propB).toBe(2);
|
||||
expect(target.test).toBe('asd');
|
||||
});
|
||||
|
||||
it('use default value if not found on source', function() {
|
||||
var target: any = {test: 'asd'};
|
||||
assignModelProperties(target, {propA: 1, propB: 2}, {propC: 10});
|
||||
expect(target.propC).to.be(10);
|
||||
expect(target.propC).toBe(10);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,8 +1,6 @@
|
||||
///<reference path="../../../headers/common.d.ts" />
|
||||
|
||||
import _ from 'lodash';
|
||||
import TimeSeries from 'app/core/time_series2';
|
||||
import {colors} from 'app/core/core';
|
||||
import colors from 'app/core/utils/colors';
|
||||
|
||||
export class DataProcessor {
|
||||
|
||||
|
||||
@@ -381,7 +381,7 @@ function graphDirective($rootScope, timeSrv, popoverSrv, contextSrv) {
|
||||
var haveSortOrder = sortOrder !== null || sortOrder !== undefined;
|
||||
|
||||
if (panel.stack && haveSortBy && haveSortOrder) {
|
||||
var desc = desc = panel.legend.sortDesc === true ? 1 : -1;
|
||||
var desc = desc = panel.legend.sortDesc === true ? -1 : 1;
|
||||
series.sort((x, y) => {
|
||||
if (x.stats[sortBy] > y.stats[sortBy]) {
|
||||
return 1 * desc;
|
||||
|
||||
@@ -127,7 +127,7 @@ function ($, core) {
|
||||
value: value,
|
||||
hoverIndex: hoverIndex,
|
||||
color: series.color,
|
||||
label: series.label,
|
||||
label: series.aliasEscaped,
|
||||
time: pointTime,
|
||||
distance: hoverDistance,
|
||||
index: i
|
||||
@@ -264,7 +264,7 @@ function ($, core) {
|
||||
else if (item) {
|
||||
series = seriesList[item.seriesIndex];
|
||||
group = '<div class="graph-tooltip-list-item"><div class="graph-tooltip-series-name">';
|
||||
group += '<i class="fa fa-minus" style="color:' + item.series.color +';"></i> ' + series.label + ':</div>';
|
||||
group += '<i class="fa fa-minus" style="color:' + item.series.color +';"></i> ' + series.aliasEscaped + ':</div>';
|
||||
|
||||
if (panel.stack && panel.tooltip.value_type === 'individual') {
|
||||
value = item.datapoint[1] - item.datapoint[2];
|
||||
|
||||
@@ -169,7 +169,7 @@ function (angular, _, $) {
|
||||
html += '<i class="fa fa-minus pointer" style="color:' + series.color + '"></i>';
|
||||
html += '</div>';
|
||||
|
||||
html += '<a class="graph-legend-alias pointer" title="' + _.escape(series.label) + '">' + _.escape(series.label) + '</a>';
|
||||
html += '<a class="graph-legend-alias pointer" title="' + series.aliasEscaped + '">' + series.aliasEscaped + '</a>';
|
||||
|
||||
if (panel.legend.values) {
|
||||
var avg = series.formatValue(series.stats.avg);
|
||||
|
||||
+7
-11
@@ -1,7 +1,3 @@
|
||||
///<reference path="../../../../headers/common.d.ts" />
|
||||
|
||||
import {describe, beforeEach, it, expect} from '../../../../../test/lib/common';
|
||||
|
||||
import {DataProcessor} from '../data_processor';
|
||||
|
||||
describe('Graph DataProcessor', function() {
|
||||
@@ -29,7 +25,7 @@ describe('Graph DataProcessor', function() {
|
||||
});
|
||||
|
||||
it('Should automatically set xaxis mode to field', () => {
|
||||
expect(panel.xaxis.mode).to.be('field');
|
||||
expect(panel.xaxis.mode).toBe('field');
|
||||
});
|
||||
|
||||
});
|
||||
@@ -48,16 +44,16 @@ describe('Graph DataProcessor', function() {
|
||||
|
||||
it('Should return all field names', () => {
|
||||
var fields = processor.getDataFieldNames(dataList, false);
|
||||
expect(fields).to.contain('hostname');
|
||||
expect(fields).to.contain('valueField');
|
||||
expect(fields).to.contain('nested.prop1');
|
||||
expect(fields).to.contain('nested.value2');
|
||||
expect(fields).toContain('hostname');
|
||||
expect(fields).toContain('valueField');
|
||||
expect(fields).toContain('nested.prop1');
|
||||
expect(fields).toContain('nested.value2');
|
||||
});
|
||||
|
||||
it('Should return all number fields', () => {
|
||||
var fields = processor.getDataFieldNames(dataList, true);
|
||||
expect(fields).to.contain('valueField');
|
||||
expect(fields).to.contain('nested.value2');
|
||||
expect(fields).toContain('valueField');
|
||||
expect(fields).toContain('nested.value2');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -75,7 +75,7 @@ describe('grafanaGraph', function() {
|
||||
alias: 'series1'
|
||||
}));
|
||||
ctx.data.push(new TimeSeries({
|
||||
datapoints: [[1,10],[2,20]],
|
||||
datapoints: [[10,1],[20,2]],
|
||||
alias: 'series2'
|
||||
}));
|
||||
|
||||
@@ -112,52 +112,67 @@ describe('grafanaGraph', function() {
|
||||
});
|
||||
});
|
||||
|
||||
graphScenario('sort series as legend', (ctx) => {
|
||||
describe("with sort as legend undefined", () => {
|
||||
ctx.setup((ctrl) => {
|
||||
ctrl.panel.legend.sort = undefined;
|
||||
});
|
||||
|
||||
it("should not modify order of time series", () => {
|
||||
expect(ctx.plotData[0].alias).to.be('series1');
|
||||
expect(ctx.plotData[1].alias).to.be('series2');
|
||||
});
|
||||
graphScenario('sorting stacked series as legend. disabled', (ctx) => {
|
||||
ctx.setup((ctrl) => {
|
||||
ctrl.panel.legend.sort = undefined;
|
||||
ctrl.panel.stack = false;
|
||||
});
|
||||
|
||||
describe("with sort as legend set to min. descending order", () => {
|
||||
ctx.setup((ctrl) => {
|
||||
ctrl.panel.legend.sort = 'min';
|
||||
ctrl.panel.legend.sortDesc = true;
|
||||
});
|
||||
it("should not modify order of time series", () => {
|
||||
expect(ctx.plotData[0].alias).to.be('series1');
|
||||
expect(ctx.plotData[1].alias).to.be('series2');
|
||||
});
|
||||
});
|
||||
|
||||
it("highest value should be first", () => {
|
||||
expect(ctx.plotData[1].alias).to.be('series2');
|
||||
expect(ctx.plotData[0].alias).to.be('series1');
|
||||
});
|
||||
graphScenario("sorting stacked series as legend. min descending order", (ctx) => {
|
||||
ctx.setup(ctrl => {
|
||||
ctrl.panel.legend.sort = 'min';
|
||||
ctrl.panel.legend.sortDesc = true;
|
||||
ctrl.panel.stack = true;
|
||||
});
|
||||
|
||||
describe("with sort as legend set to min. ascending order", () => {
|
||||
ctx.setup((ctrl) => {
|
||||
ctrl.panel.legend.sort = 'min';
|
||||
ctrl.panel.legend.sortDesc = true;
|
||||
});
|
||||
it("highest value should be first", () => {
|
||||
expect(ctx.plotData[0].alias).to.be('series2');
|
||||
expect(ctx.plotData[1].alias).to.be('series1');
|
||||
});
|
||||
});
|
||||
|
||||
it("lowest value should be first", () => {
|
||||
expect(ctx.plotData[0].alias).to.be('series1');
|
||||
expect(ctx.plotData[1].alias).to.be('series2');
|
||||
});
|
||||
graphScenario("sorting stacked series as legend. min ascending order", (ctx) => {
|
||||
ctx.setup((ctrl, data) => {
|
||||
ctrl.panel.legend.sort = 'min';
|
||||
ctrl.panel.legend.sortDesc = false;
|
||||
ctrl.panel.stack = true;
|
||||
});
|
||||
|
||||
describe("with sort as legend set to current. ascending order", () => {
|
||||
ctx.setup((ctrl) => {
|
||||
ctrl.panel.legend.sort = 'current';
|
||||
ctrl.panel.legend.sortDesc = false;
|
||||
});
|
||||
it("lowest value should be first", () => {
|
||||
expect(ctx.plotData[0].alias).to.be('series1');
|
||||
expect(ctx.plotData[1].alias).to.be('series2');
|
||||
});
|
||||
});
|
||||
|
||||
it("highest last value should be first", () => {
|
||||
expect(ctx.plotData[1].alias).to.be('series2');
|
||||
expect(ctx.plotData[0].alias).to.be('series1');
|
||||
});
|
||||
graphScenario("sorting stacked series as legend. stacking disabled", (ctx) => {
|
||||
ctx.setup((ctrl) => {
|
||||
ctrl.panel.legend.sort = 'min';
|
||||
ctrl.panel.legend.sortDesc = true;
|
||||
ctrl.panel.stack = false;
|
||||
});
|
||||
|
||||
it("highest value should be first", () => {
|
||||
expect(ctx.plotData[0].alias).to.be('series1');
|
||||
expect(ctx.plotData[1].alias).to.be('series2');
|
||||
});
|
||||
});
|
||||
|
||||
graphScenario("sorting stacked series as legend. current descending order", (ctx) => {
|
||||
ctx.setup((ctrl) => {
|
||||
ctrl.panel.legend.sort = 'current';
|
||||
ctrl.panel.legend.sortDesc = true;
|
||||
ctrl.panel.stack = true;
|
||||
});
|
||||
|
||||
it("highest last value should be first", () => {
|
||||
expect(ctx.plotData[0].alias).to.be('series2');
|
||||
expect(ctx.plotData[1].alias).to.be('series1');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -300,7 +315,7 @@ describe('grafanaGraph', function() {
|
||||
});
|
||||
|
||||
it('should set barWidth', function() {
|
||||
expect(ctx.plotOptions.series.bars.barWidth).to.be(10/1.5);
|
||||
expect(ctx.plotOptions.series.bars.barWidth).to.be(1/1.5);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -383,146 +398,4 @@ describe('grafanaGraph', function() {
|
||||
});
|
||||
|
||||
}, 10);
|
||||
|
||||
// graphScenario('when using flexible Y-Min and Y-Max settings', function(ctx) {
|
||||
// describe('and Y-Min is <100 and Y-Max is >200 and values within range', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = '<100';
|
||||
// ctrl.panel.yaxes[0].max = '>200';
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[120,10],[160,20]],
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min to 100 and max to 200', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(100);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(200);
|
||||
// });
|
||||
// });
|
||||
// describe('and Y-Min is <100 and Y-Max is >200 and values outside range', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = '<100';
|
||||
// ctrl.panel.yaxes[0].max = '>200';
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[99,10],[201,20]],
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min to auto and max to auto', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(null);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(null);
|
||||
// });
|
||||
// });
|
||||
// describe('and Y-Min is =10.5 and Y-Max is =10.5', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = '=10.5';
|
||||
// ctrl.panel.yaxes[0].max = '=10.5';
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[100,10],[120,20], [110,30]],
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min to last value + 10.5 and max to last value + 10.5', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(99.5);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(120.5);
|
||||
// });
|
||||
// });
|
||||
// describe('and Y-Min is ~10.5 and Y-Max is ~10.5', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = '~10.5';
|
||||
// ctrl.panel.yaxes[0].max = '~10.5';
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[102,10],[104,20], [110,30]], //Also checks precision
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min to average value + 10.5 and max to average value + 10.5', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(94.8);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(115.8);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// graphScenario('when using regular Y-Min and Y-Max settings', function(ctx) {
|
||||
// describe('and Y-Min is 100 and Y-Max is 200', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = '100';
|
||||
// ctrl.panel.yaxes[0].max = '200';
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[120,10],[160,20]],
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min to 100 and max to 200', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(100);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(200);
|
||||
// });
|
||||
// });
|
||||
// describe('and Y-Min is 0 and Y-Max is 0', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = '0';
|
||||
// ctrl.panel.yaxes[0].max = '0';
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[120,10],[160,20]],
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min to 0 and max to 0', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(0);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(0);
|
||||
// });
|
||||
// });
|
||||
// describe('and negative values used', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = '-10';
|
||||
// ctrl.panel.yaxes[0].max = '-13.14';
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[120,10],[160,20]],
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min and max to negative', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(-10);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(-13.14);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// graphScenario('when using Y-Min and Y-Max settings stored as number', function(ctx) {
|
||||
// describe('and Y-Min is 0 and Y-Max is 100', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = 0;
|
||||
// ctrl.panel.yaxes[0].max = 100;
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[120,10],[160,20]],
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min to 0 and max to 100', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(0);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(100);
|
||||
// });
|
||||
// });
|
||||
// describe('and Y-Min is -100 and Y-Max is -10.5', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = -100;
|
||||
// ctrl.panel.yaxes[0].max = -10.5;
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[120,10],[160,20]],
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min to -100 and max to -10.5', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(-100);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(-10.5);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
});
|
||||
+4
-8
@@ -1,7 +1,3 @@
|
||||
///<reference path="../../../../headers/common.d.ts" />
|
||||
|
||||
import { describe, beforeEach, it, expect } from '../../../../../test/lib/common';
|
||||
|
||||
import { convertValuesToHistogram, getSeriesValues } from '../histogram';
|
||||
|
||||
describe('Graph Histogam Converter', function () {
|
||||
@@ -21,7 +17,7 @@ describe('Graph Histogam Converter', function () {
|
||||
];
|
||||
|
||||
let histogram = convertValuesToHistogram(values, bucketSize);
|
||||
expect(histogram).to.eql(expected);
|
||||
expect(histogram).toMatchObject(expected);
|
||||
});
|
||||
|
||||
it('Should not add empty buckets', () => {
|
||||
@@ -31,7 +27,7 @@ describe('Graph Histogam Converter', function () {
|
||||
];
|
||||
|
||||
let histogram = convertValuesToHistogram(values, bucketSize);
|
||||
expect(histogram).to.eql(expected);
|
||||
expect(histogram).toMatchObject(expected);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -50,7 +46,7 @@ describe('Graph Histogam Converter', function () {
|
||||
let expected = [1, 2, 10, 11, 17, 20, 29];
|
||||
|
||||
let values = getSeriesValues(data);
|
||||
expect(values).to.eql(expected);
|
||||
expect(values).toMatchObject(expected);
|
||||
});
|
||||
|
||||
it('Should skip null values', () => {
|
||||
@@ -59,7 +55,7 @@ describe('Graph Histogam Converter', function () {
|
||||
let expected = [1, 2, 10, 11, 17, 20, 29];
|
||||
|
||||
let values = getSeriesValues(data);
|
||||
expect(values).to.eql(expected);
|
||||
expect(values).toMatchObject(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,9 +1,10 @@
|
||||
import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
import $ from 'jquery';
|
||||
import d3 from 'vendor/d3/d3';
|
||||
import * as d3 from 'd3';
|
||||
import {contextSrv} from 'app/core/core';
|
||||
import {tickStep} from 'app/core/utils/ticks';
|
||||
import {getColorScale, getOpacityScale} from './color_scale';
|
||||
|
||||
let module = angular.module('grafana.directives');
|
||||
|
||||
@@ -30,7 +31,7 @@ module.directive('colorLegend', function() {
|
||||
|
||||
if (panel.color.mode === 'spectrum') {
|
||||
let colorScheme = _.find(ctrl.colorSchemes, {value: panel.color.colorScheme});
|
||||
let colorScale = getColorScale(colorScheme, legendWidth);
|
||||
let colorScale = getColorScale(colorScheme, contextSrv.user.lightTheme, legendWidth);
|
||||
drawSimpleColorLegend(elem, colorScale);
|
||||
} else if (panel.color.mode === 'opacity') {
|
||||
let colorOptions = panel.color;
|
||||
@@ -93,7 +94,7 @@ function drawColorLegend(elem, colorScheme, rangeFrom, rangeTo, maxValue, minVal
|
||||
let widthFactor = legendWidth / (rangeTo - rangeFrom);
|
||||
let valuesRange = d3.range(rangeFrom, rangeTo, rangeStep);
|
||||
|
||||
let colorScale = getColorScale(colorScheme, maxValue, minValue);
|
||||
let colorScale = getColorScale(colorScheme, contextSrv.user.lightTheme, maxValue, minValue);
|
||||
legend.selectAll(".heatmap-color-legend-rect")
|
||||
.data(valuesRange)
|
||||
.enter().append("rect")
|
||||
@@ -115,7 +116,10 @@ function drawOpacityLegend(elem, options, rangeFrom, rangeTo, maxValue, minValue
|
||||
let legendWidth = Math.floor(legendElem.outerWidth()) - 30;
|
||||
let legendHeight = legendElem.attr("height");
|
||||
|
||||
let rangeStep = 10;
|
||||
let rangeStep = 1;
|
||||
if (rangeTo - rangeFrom > legendWidth) {
|
||||
rangeStep = Math.floor((rangeTo - rangeFrom) / legendWidth);
|
||||
}
|
||||
let widthFactor = legendWidth / (rangeTo - rangeFrom);
|
||||
let valuesRange = d3.range(rangeFrom, rangeTo, rangeStep);
|
||||
|
||||
@@ -228,31 +232,6 @@ function clearLegend(elem) {
|
||||
legendElem.empty();
|
||||
}
|
||||
|
||||
function getColorScale(colorScheme, maxValue, minValue = 0) {
|
||||
let colorInterpolator = d3[colorScheme.value];
|
||||
let colorScaleInverted = colorScheme.invert === 'always' ||
|
||||
(colorScheme.invert === 'dark' && !contextSrv.user.lightTheme);
|
||||
|
||||
let start = colorScaleInverted ? maxValue : minValue;
|
||||
let end = colorScaleInverted ? minValue : maxValue;
|
||||
|
||||
return d3.scaleSequential(colorInterpolator).domain([start, end]);
|
||||
}
|
||||
|
||||
function getOpacityScale(options, maxValue, minValue = 0) {
|
||||
let legendOpacityScale;
|
||||
if (options.colorScale === 'linear') {
|
||||
legendOpacityScale = d3.scaleLinear()
|
||||
.domain([minValue, maxValue])
|
||||
.range([0, 1]);
|
||||
} else if (options.colorScale === 'sqrt') {
|
||||
legendOpacityScale = d3.scalePow().exponent(options.exponent)
|
||||
.domain([minValue, maxValue])
|
||||
.range([0, 1]);
|
||||
}
|
||||
return legendOpacityScale;
|
||||
}
|
||||
|
||||
function getSvgElemX(elem) {
|
||||
let svgElem = elem.get(0);
|
||||
if (svgElem && svgElem.x && svgElem.x.baseVal) {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import * as d3 from 'd3';
|
||||
import * as d3ScaleChromatic from 'd3-scale-chromatic';
|
||||
|
||||
export function getColorScale(colorScheme: any, lightTheme: boolean, maxValue: number, minValue = 0): (d: any) => any {
|
||||
let colorInterpolator = d3ScaleChromatic[colorScheme.value];
|
||||
let colorScaleInverted = colorScheme.invert === 'always' ||
|
||||
(colorScheme.invert === 'dark' && !lightTheme);
|
||||
|
||||
let start = colorScaleInverted ? maxValue : minValue;
|
||||
let end = colorScaleInverted ? minValue : maxValue;
|
||||
|
||||
return d3.scaleSequential(colorInterpolator).domain([start, end]);
|
||||
}
|
||||
|
||||
export function getOpacityScale(options, maxValue, minValue = 0) {
|
||||
let legendOpacityScale;
|
||||
if (options.colorScale === 'linear') {
|
||||
legendOpacityScale = d3.scaleLinear()
|
||||
.domain([minValue, maxValue])
|
||||
.range([0, 1]);
|
||||
} else if (options.colorScale === 'sqrt') {
|
||||
legendOpacityScale = d3.scalePow().exponent(options.exponent)
|
||||
.domain([minValue, maxValue])
|
||||
.range([0, 1]);
|
||||
}
|
||||
return legendOpacityScale;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import d3 from 'vendor/d3/d3';
|
||||
import * as d3 from 'd3';
|
||||
import $ from 'jquery';
|
||||
import _ from 'lodash';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import _ from 'lodash';
|
||||
import $ from 'jquery';
|
||||
import moment from 'moment';
|
||||
import * as d3 from 'd3';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import {appEvents, contextSrv} from 'app/core/core';
|
||||
import {tickStep, getScaledDecimals, getFlotTickSize} from 'app/core/utils/ticks';
|
||||
import d3 from 'vendor/d3/d3';
|
||||
import {HeatmapTooltip} from './heatmap_tooltip';
|
||||
import {mergeZeroBuckets} from './heatmap_data_converter';
|
||||
import {getColorScale, getOpacityScale} from './color_scale';
|
||||
|
||||
let MIN_CARD_SIZE = 1,
|
||||
CARD_PADDING = 1,
|
||||
@@ -386,8 +387,9 @@ export default function link(scope, elem, attrs, ctrl) {
|
||||
let maxValue = panel.color.max || maxValueAuto;
|
||||
let minValue = panel.color.min || 0;
|
||||
|
||||
colorScale = getColorScale(maxValue, minValue);
|
||||
setOpacityScale(maxValue);
|
||||
let colorScheme = _.find(ctrl.colorSchemes, {value: panel.color.colorScheme});
|
||||
colorScale = getColorScale(colorScheme, contextSrv.user.lightTheme, maxValue, minValue);
|
||||
opacityScale = getOpacityScale(panel.color, maxValue);
|
||||
setCardSize();
|
||||
|
||||
let cards = heatmap.selectAll(".heatmap-card").data(cardsData);
|
||||
@@ -422,8 +424,8 @@ export default function link(scope, elem, attrs, ctrl) {
|
||||
let strokeColor = d3.color(color).brighter(4);
|
||||
let current_card = d3.select(event.target);
|
||||
tooltip.originalFillColor = color;
|
||||
current_card.style("fill", highlightColor)
|
||||
.style("stroke", strokeColor)
|
||||
current_card.style("fill", highlightColor.toString())
|
||||
.style("stroke", strokeColor.toString())
|
||||
.style("stroke-width", 1);
|
||||
}
|
||||
|
||||
@@ -433,30 +435,6 @@ export default function link(scope, elem, attrs, ctrl) {
|
||||
.style("stroke-width", 0);
|
||||
}
|
||||
|
||||
function getColorScale(maxValue, minValue = 0) {
|
||||
let colorScheme = _.find(ctrl.colorSchemes, {value: panel.color.colorScheme});
|
||||
let colorInterpolator = d3[colorScheme.value];
|
||||
let colorScaleInverted = colorScheme.invert === 'always' ||
|
||||
(colorScheme.invert === 'dark' && !contextSrv.user.lightTheme);
|
||||
|
||||
let start = colorScaleInverted ? maxValue : minValue;
|
||||
let end = colorScaleInverted ? minValue : maxValue;
|
||||
|
||||
return d3.scaleSequential(colorInterpolator).domain([start, end]);
|
||||
}
|
||||
|
||||
function setOpacityScale(maxValue) {
|
||||
if (panel.color.colorScale === 'linear') {
|
||||
opacityScale = d3.scaleLinear()
|
||||
.domain([0, maxValue])
|
||||
.range([0, 1]);
|
||||
} else if (panel.color.colorScale === 'sqrt') {
|
||||
opacityScale = d3.scalePow().exponent(panel.color.exponent)
|
||||
.domain([0, maxValue])
|
||||
.range([0, 1]);
|
||||
}
|
||||
}
|
||||
|
||||
function setCardSize() {
|
||||
let xGridSize = Math.floor(xScale(data.xBucketSize) - xScale(0));
|
||||
let yGridSize = Math.floor(yScale(yScale.invert(0) - data.yBucketSize));
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
System.config({
|
||||
defaultJSExtenions: true,
|
||||
baseURL: 'public',
|
||||
paths: {
|
||||
'virtual-scroll': 'vendor/npm/virtual-scroll/src/index.js',
|
||||
'mousetrap': 'vendor/npm/mousetrap/mousetrap.js',
|
||||
'remarkable': 'vendor/npm/remarkable/dist/remarkable.js',
|
||||
'tether': 'vendor/npm/tether/dist/js/tether.js',
|
||||
'eventemitter3': 'vendor/npm/eventemitter3/index.js',
|
||||
'tether-drop': 'vendor/npm/tether-drop/dist/js/drop.js',
|
||||
'moment': 'vendor/moment.js',
|
||||
"jquery": "vendor/jquery/dist/jquery.js",
|
||||
'lodash-src': 'vendor/lodash/dist/lodash.js',
|
||||
"lodash": 'app/core/lodash_extended.js',
|
||||
"angular": "vendor/angular/angular.js",
|
||||
"bootstrap": "vendor/bootstrap/bootstrap.js",
|
||||
'angular-route': 'vendor/angular-route/angular-route.js',
|
||||
'angular-sanitize': 'vendor/angular-sanitize/angular-sanitize.js',
|
||||
"angular-ui": "vendor/angular-ui/ui-bootstrap-tpls.js",
|
||||
"angular-strap": "vendor/angular-other/angular-strap.js",
|
||||
"angular-dragdrop": "vendor/angular-native-dragdrop/draganddrop.js",
|
||||
"angular-bindonce": "vendor/angular-bindonce/bindonce.js",
|
||||
"spectrum": "vendor/spectrum.js",
|
||||
"bootstrap-tagsinput": "vendor/tagsinput/bootstrap-tagsinput.js",
|
||||
"jquery.flot": "vendor/flot/jquery.flot",
|
||||
"jquery.flot.pie": "vendor/flot/jquery.flot.pie",
|
||||
"jquery.flot.selection": "vendor/flot/jquery.flot.selection",
|
||||
"jquery.flot.stack": "vendor/flot/jquery.flot.stack",
|
||||
"jquery.flot.stackpercent": "vendor/flot/jquery.flot.stackpercent",
|
||||
"jquery.flot.time": "vendor/flot/jquery.flot.time",
|
||||
"jquery.flot.crosshair": "vendor/flot/jquery.flot.crosshair",
|
||||
"jquery.flot.fillbelow": "vendor/flot/jquery.flot.fillbelow",
|
||||
"jquery.flot.gauge": "vendor/flot/jquery.flot.gauge",
|
||||
"d3": "vendor/d3/d3.js",
|
||||
"jquery.flot.dashes": "vendor/flot/jquery.flot.dashes",
|
||||
"twemoji": "vendor/npm/twemoji/2/twemoji.amd.js",
|
||||
"ace": "vendor/npm/ace-builds/src-noconflict/ace",
|
||||
},
|
||||
|
||||
packages: {
|
||||
app: {
|
||||
defaultExtension: 'js',
|
||||
},
|
||||
vendor: {
|
||||
defaultExtension: 'js',
|
||||
},
|
||||
plugins: {
|
||||
defaultExtension: 'js',
|
||||
},
|
||||
test: {
|
||||
defaultExtension: 'js',
|
||||
},
|
||||
},
|
||||
|
||||
map: {
|
||||
text: 'vendor/plugin-text/text.js',
|
||||
css: 'app/core/utils/css_loader.js'
|
||||
},
|
||||
|
||||
meta: {
|
||||
'vendor/npm/virtual-scroll/src/indx.js': {
|
||||
format: 'cjs',
|
||||
exports: 'VirtualScroll',
|
||||
},
|
||||
'vendor/angular/angular.js': {
|
||||
format: 'global',
|
||||
deps: ['jquery'],
|
||||
exports: 'angular',
|
||||
},
|
||||
'vendor/npm/eventemitter3/index.js': {
|
||||
format: 'cjs',
|
||||
exports: 'EventEmitter'
|
||||
},
|
||||
'vendor/npm/mousetrap/mousetrap.js': {
|
||||
format: 'global',
|
||||
exports: 'Mousetrap'
|
||||
},
|
||||
'vendor/npm/ace-builds/src-noconflict/ace.js': {
|
||||
format: 'global',
|
||||
exports: 'ace'
|
||||
}
|
||||
}
|
||||
});
|
||||
Vendored
-27
@@ -1,27 +0,0 @@
|
||||
Copyright 2010-2016 Mike Bostock
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the author nor the names of contributors may be used to
|
||||
endorse or promote products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
Vendored
-57
@@ -1,57 +0,0 @@
|
||||
# D3: Data-Driven Documents
|
||||
|
||||
<a href="https://d3js.org"><img src="https://d3js.org/logo.svg" align="left" hspace="10" vspace="6"></a>
|
||||
|
||||
**D3** (or **D3.js**) is a JavaScript library for visualizing data using web standards. D3 helps you bring data to life using SVG, Canvas and HTML. D3 combines powerful visualization and interaction techniques with a data-driven approach to DOM manipulation, giving you the full capabilities of modern browsers and the freedom to design the right visual interface for your data.
|
||||
|
||||
## Resources
|
||||
|
||||
* [API Reference](https://github.com/d3/d3/blob/master/API.md)
|
||||
* [Release Notes](https://github.com/d3/d3/releases)
|
||||
* [Gallery](https://github.com/d3/d3/wiki/Gallery)
|
||||
* [Examples](http://bl.ocks.org/mbostock)
|
||||
* [Wiki](https://github.com/d3/d3/wiki)
|
||||
|
||||
## Installing
|
||||
|
||||
If you use npm, `npm install d3`. Otherwise, download the [latest release](https://github.com/d3/d3/releases/latest). The released bundle supports anonymous AMD, CommonJS, and vanilla environments. You can load directly from [d3js.org](https://d3js.org), [CDNJS](https://cdnjs.com/libraries/d3), or [unpkg](https://unpkg.com/d3/). For example:
|
||||
|
||||
```html
|
||||
<script src="https://d3js.org/d3.v4.js"></script>
|
||||
```
|
||||
|
||||
For the minified version:
|
||||
|
||||
```html
|
||||
<script src="https://d3js.org/d3.v4.min.js"></script>
|
||||
```
|
||||
|
||||
You can also use the standalone D3 microlibraries. For example, [d3-selection](https://github.com/d3/d3-selection):
|
||||
|
||||
```html
|
||||
<script src="https://d3js.org/d3-selection.v1.js"></script>
|
||||
```
|
||||
|
||||
D3 is written using [ES2015 modules](http://www.2ality.com/2014/09/es6-modules-final.html). Create a [custom bundle using Rollup](http://bl.ocks.org/mbostock/bb09af4c39c79cffcde4), Webpack, or your preferred bundler. To import D3 into an ES2015 application, either import specific symbols from specific D3 modules:
|
||||
|
||||
```js
|
||||
import {scaleLinear} from "d3-scale";
|
||||
```
|
||||
|
||||
Or import everything into a namespace (here, `d3`):
|
||||
|
||||
```js
|
||||
import * as d3 from "d3";
|
||||
```
|
||||
|
||||
In Node:
|
||||
|
||||
```js
|
||||
var d3 = require("d3");
|
||||
```
|
||||
|
||||
You can also require individual modules and combine them into a `d3` object using [Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign):
|
||||
|
||||
```js
|
||||
var d3 = Object.assign({}, require("d3-format"), require("d3-geo"), require("d3-geo-projection"));
|
||||
```
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
// https://d3js.org/d3-scale-chromatic/ Version 1.1.1. Copyright 2017 Mike Bostock.
|
||||
!function(f,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("./d3.v4.min.js")):"function"==typeof define&&define.amd?define(["exports","./d3.v4.min.js"],e):e(f.d3=f.d3||{},f.d3)}(this,function(f,e){"use strict";var d=function(f){for(var e=f.length/6|0,d=new Array(e),c=0;c<e;)d[c]="#"+f.slice(6*c,6*++c);return d},c=d("7fc97fbeaed4fdc086ffff99386cb0f0027fbf5b17666666"),a=d("1b9e77d95f027570b3e7298a66a61ee6ab02a6761d666666"),b=d("a6cee31f78b4b2df8a33a02cfb9a99e31a1cfdbf6fff7f00cab2d66a3d9affff99b15928"),r=d("fbb4aeb3cde3ccebc5decbe4fed9a6ffffcce5d8bdfddaecf2f2f2"),n=d("b3e2cdfdcdaccbd5e8f4cae4e6f5c9fff2aef1e2cccccccc"),t=d("e41a1c377eb84daf4a984ea3ff7f00ffff33a65628f781bf999999"),o=d("66c2a5fc8d628da0cbe78ac3a6d854ffd92fe5c494b3b3b3"),p=d("8dd3c7ffffb3bebadafb807280b1d3fdb462b3de69fccde5d9d9d9bc80bdccebc5ffed6f"),m=function(f){return e.interpolateRgbBasis(f[f.length-1])},s=new Array(3).concat("d8b365f5f5f55ab4ac","a6611adfc27d80cdc1018571","a6611adfc27df5f5f580cdc1018571","8c510ad8b365f6e8c3c7eae55ab4ac01665e","8c510ad8b365f6e8c3f5f5f5c7eae55ab4ac01665e","8c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e","8c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e","5430058c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e003c30","5430058c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e003c30").map(d),l=m(s),i=new Array(3).concat("af8dc3f7f7f77fbf7b","7b3294c2a5cfa6dba0008837","7b3294c2a5cff7f7f7a6dba0008837","762a83af8dc3e7d4e8d9f0d37fbf7b1b7837","762a83af8dc3e7d4e8f7f7f7d9f0d37fbf7b1b7837","762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b7837","762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b7837","40004b762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b783700441b","40004b762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b783700441b").map(d),u=m(i),h=new Array(3).concat("e9a3c9f7f7f7a1d76a","d01c8bf1b6dab8e1864dac26","d01c8bf1b6daf7f7f7b8e1864dac26","c51b7de9a3c9fde0efe6f5d0a1d76a4d9221","c51b7de9a3c9fde0eff7f7f7e6f5d0a1d76a4d9221","c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221","c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221","8e0152c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221276419","8e0152c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221276419").map(d),y=m(h),A=new Array(3).concat("998ec3f7f7f7f1a340","5e3c99b2abd2fdb863e66101","5e3c99b2abd2f7f7f7fdb863e66101","542788998ec3d8daebfee0b6f1a340b35806","542788998ec3d8daebf7f7f7fee0b6f1a340b35806","5427888073acb2abd2d8daebfee0b6fdb863e08214b35806","5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b35806","2d004b5427888073acb2abd2d8daebfee0b6fdb863e08214b358067f3b08","2d004b5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b358067f3b08").map(d),w=m(A),B=new Array(3).concat("ef8a62f7f7f767a9cf","ca0020f4a58292c5de0571b0","ca0020f4a582f7f7f792c5de0571b0","b2182bef8a62fddbc7d1e5f067a9cf2166ac","b2182bef8a62fddbc7f7f7f7d1e5f067a9cf2166ac","b2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac","b2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac","67001fb2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac053061","67001fb2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac053061").map(d),G=m(B),P=new Array(3).concat("ef8a62ffffff999999","ca0020f4a582bababa404040","ca0020f4a582ffffffbababa404040","b2182bef8a62fddbc7e0e0e09999994d4d4d","b2182bef8a62fddbc7ffffffe0e0e09999994d4d4d","b2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d","b2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d","67001fb2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d1a1a1a","67001fb2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d1a1a1a").map(d),R=m(P),Y=new Array(3).concat("fc8d59ffffbf91bfdb","d7191cfdae61abd9e92c7bb6","d7191cfdae61ffffbfabd9e92c7bb6","d73027fc8d59fee090e0f3f891bfdb4575b4","d73027fc8d59fee090ffffbfe0f3f891bfdb4575b4","d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4","d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4","a50026d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4313695","a50026d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4313695").map(d),O=m(Y),g=new Array(3).concat("fc8d59ffffbf91cf60","d7191cfdae61a6d96a1a9641","d7191cfdae61ffffbfa6d96a1a9641","d73027fc8d59fee08bd9ef8b91cf601a9850","d73027fc8d59fee08bffffbfd9ef8b91cf601a9850","d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850","d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850","a50026d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850006837","a50026d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850006837").map(d),S=m(g),v=new Array(3).concat("fc8d59ffffbf99d594","d7191cfdae61abdda42b83ba","d7191cfdae61ffffbfabdda42b83ba","d53e4ffc8d59fee08be6f59899d5943288bd","d53e4ffc8d59fee08bffffbfe6f59899d5943288bd","d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd","d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd","9e0142d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd5e4fa2","9e0142d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd5e4fa2").map(d),x=m(v),j=new Array(3).concat("e5f5f999d8c92ca25f","edf8fbb2e2e266c2a4238b45","edf8fbb2e2e266c2a42ca25f006d2c","edf8fbccecLine truncated
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
// Import main D3.js module and combine it with another
|
||||
var d3 = Object.assign({}, require('./d3.v4.min.js'), require('./d3-scale-chromatic.min.js'));
|
||||
module.exports = d3;
|
||||
Vendored
-8
@@ -1,8 +0,0 @@
|
||||
// https://d3js.org Version 4.5.0. Copyright 2017 Mike Bostock.
|
||||
(function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(t.d3=t.d3||{})})(this,function(t){"use strict";function n(t){return function(n,e){return Ns(t(n),e)}}function e(t,n,e){var r=Math.abs(n-t)/Math.max(0,e),i=Math.pow(10,Math.floor(Math.log(r)/Math.LN10)),o=r/i;return o>=Ys?i*=10:o>=Bs?i*=5:o>=js&&(i*=2),n<t?-i:i}function r(t){return t.length}function i(t,n,e){var r=t(e);return"translate("+(isFinite(r)?r:n(e))+",0)"}function o(t,n,e){var r=t(e);return"translate(0,"+(isFinite(r)?r:n(e))+")"}function u(t){var n=t.bandwidth()/2;return t.round()&&(n=Math.round(n)),function(e){return t(e)+n}}function a(){return!this.__axis}function c(t,n){function e(e){var p,d=null==c?n.ticks?n.ticks.apply(n,r):n.domain():c,v=null==s?n.tickFormat?n.tickFormat.apply(n,r):ff:s,_=Math.max(f,0)+h,y=t===lf||t===pf?i:o,g=n.range(),m=g[0]+.5,x=g[g.length-1]+.5,b=(n.bandwidth?u:ff)(n.copy()),w=e.selection?e.selection():e,M=w.selectAll(".domain").data([null]),T=w.selectAll(".tick").data(d,n).order(),N=T.exit(),k=T.enter().append("g").attr("class","tick"),S=T.select("line"),E=T.select("text"),A=t===lf||t===df?-1:1,C=t===df||t===hf?(p="x","y"):(p="y","x");M=M.merge(M.enter().insert("path",".tick").attr("class","domain").attr("stroke","#000")),T=T.merge(k),S=S.merge(k.append("line").attr("stroke","#000").attr(p+"2",A*f).attr(C+"1",.5).attr(C+"2",.5)),E=E.merge(k.append("text").attr("fill","#000").attr(p,A*_).attr(C,.5).attr("dy",t===lf?"0em":t===pf?"0.71em":"0.32em")),e!==w&&(M=M.transition(e),T=T.transition(e),S=S.transition(e),E=E.transition(e),N=N.transition(e).attr("opacity",vf).attr("transform",function(t){return y(b,this.parentNode.__axis||b,t)}),k.attr("opacity",vf).attr("transform",function(t){return y(this.parentNode.__axis||b,b,t)})),N.remove(),M.attr("d",t===df||t==hf?"M"+A*l+","+m+"H0.5V"+x+"H"+A*l:"M"+m+","+A*l+"V0.5H"+x+"V"+A*l),T.attr("opacity",1).attr("transform",function(t){return y(b,b,t)}),S.attr(p+"2",A*f),E.attr(p,A*_).text(v),w.filter(a).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",t===hf?"start":t===df?"end":"middle"),w.each(function(){this.__axis=b})}var r=[],c=null,s=null,f=6,l=6,h=3;return e.scale=function(t){return arguments.length?(n=t,e):n},e.ticks=function(){return r=sf.call(arguments),e},e.tickArguments=function(t){return arguments.length?(r=null==t?[]:sf.call(t),e):r.slice()},e.tickValues=function(t){return arguments.length?(c=null==t?null:sf.call(t),e):c&&c.slice()},e.tickFormat=function(t){return arguments.length?(s=t,e):s},e.tickSize=function(t){return arguments.length?(f=l=+t,e):f},e.tickSizeInner=function(t){return arguments.length?(f=+t,e):f},e.tickSizeOuter=function(t){return arguments.length?(l=+t,e):l},e.tickPadding=function(t){return arguments.length?(h=+t,e):h},e}function s(t){return c(lf,t)}function f(t){return c(hf,t)}function l(t){return c(pf,t)}function h(t){return c(df,t)}function p(){for(var t,n=0,e=arguments.length,r={};n<e;++n){if(!(t=arguments[n]+"")||t in r)throw new Error("illegal type: "+t);r[t]=[]}return new d(r)}function d(t){this._=t}function v(t,n){return t.trim().split(/^|\s+/).map(function(t){var e="",r=t.indexOf(".");if(r>=0&&(e=t.slice(r+1),t=t.slice(0,r)),t&&!n.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:e}})}function _(t,n){for(var e,r=0,i=t.length;r<i;++r)if((e=t[r]).name===n)return e.value}function y(t,n,e){for(var r=0,i=t.length;r<i;++r)if(t[r].name===n){t[r]=_f,t=t.slice(0,r).concat(t.slice(r+1));break}return null!=e&&t.push({name:n,value:e}),t}function g(t){return function(){var n=this.ownerDocument,e=this.namespaceURI;return e===yf&&n.documentElement.namespaceURI===yf?n.createElement(t):n.createElementNS(e,t)}}function m(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function x(){return new b}function b(){this._="@"+(++bf).toString(36)}function w(t,n,e){return t=M(t,n,e),function(n){var e=n.relatedTarget;e&&(e===this||8&e.compareDocumentPosition(this))||t.call(this,n)}}function M(n,e,r){return function(i){var o=t.event;t.event=i;try{n.call(this,this.__data__,e,r)}finally{t.event=o}}}function T(t){return t.trim().split(/^|\s+/).map(function(t){var n="",e=t.indexOf(".");return e>=0&&(n=t.slice(e+1),t=t.slice(0,e)),{type:t,name:n}})}function N(t){return function(){var n=this.__on;if(n){for(var e,r=0,i=-1,o=n.length;r<o;++r)e=n[r],t.type&&e.type!==t.type||e.name!==t.name?n[++i]=e:this.removeEventListener(e.type,e.listener,e.capture);++i?n.length=i:delete this.__on}}}function k(t,n,e){var r=kf.hasOwnProperty(t.type)?w:M;return function(i,o,u){var a,c=this.__on,s=r(n,o,u);if(c)for(var f=0,l=c.length;f<l;++f)if((a=c[f]).type===t.type&&a.name===t.name)return this.removeEventListener(a.type,a.listener,a.capture),this.addEventListener(a.type,a.listener=s,a.capture=e),void(a.value=n);this.addEventListener(t.type,s,e),a={type:t.type,name:t.name,value:n,listener:s,capture:e},c?c.push(a):tLine truncated
|
||||
t.format=Pv.format,t.formatPrefix=Pv.formatPrefix,Pv}function pr(){this.reset()}function dr(t,n,e){var r=t.s=n+e,i=r-n,o=r-i;t.t=n-o+(e-i)}function vr(t){return t>1?0:t<-1?m_:Math.acos(t)}function _r(t){return t>1?x_:t<-1?-x_:Math.asin(t)}function yr(t){return(t=R_(t/2))*t}function gr(){}function mr(t,n){t&&O_.hasOwnProperty(t.type)&&O_[t.type](t,n)}function xr(t,n,e){var r,i=-1,o=t.length-e;for(n.lineStart();++i<o;)r=t[i],n.point(r[0],r[1],r[2]);n.lineEnd()}function br(t,n){var e=-1,r=t.length;for(n.polygonStart();++e<r;)xr(t[e],n,1);n.polygonEnd()}function wr(){B_.point=Tr}function Mr(){Nr(Fv,Iv)}function Tr(t,n){B_.point=Nr,Fv=t,Iv=n,t*=T_,n*=T_,Yv=t,Bv=E_(n=n/2+b_),jv=R_(n)}function Nr(t,n){t*=T_,n*=T_,n=n/2+b_;var e=t-Yv,r=e>=0?1:-1,i=r*e,o=E_(n),u=R_(n),a=jv*u,c=Bv*o+a*E_(i),s=a*r*R_(i);I_.add(S_(s,c)),Yv=t,Bv=o,jv=u}function kr(t){return[S_(t[1],t[0]),_r(t[2])]}function Sr(t){var n=t[0],e=t[1],r=E_(e);return[r*E_(n),r*R_(n),R_(e)]}function Er(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function Ar(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1]-t[1]*n[0]]}function Cr(t,n){t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]}function zr(t,n){return[t[0]*n,t[1]*n,t[2]*n]}function Pr(t){var n=L_(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=n,t[1]/=n,t[2]/=n}function Rr(t,n){Qv.push(Kv=[Hv=t,Vv=t]),n<Xv&&(Xv=n),n>Wv&&(Wv=n)}function qr(t,n){var e=Sr([t*T_,n*T_]);if(Jv){var r=Ar(Jv,e),i=[r[1],-r[0],0],o=Ar(i,r);Pr(o),o=kr(o);var u,a=t-$v,c=a>0?1:-1,s=o[0]*M_*c,f=N_(a)>180;f^(c*$v<s&&s<c*t)?(u=o[1]*M_,u>Wv&&(Wv=u)):(s=(s+360)%360-180,f^(c*$v<s&&s<c*t)?(u=-o[1]*M_,u<Xv&&(Xv=u)):(n<Xv&&(Xv=n),n>Wv&&(Wv=n))),f?t<$v?Ir(Hv,t)>Ir(Hv,Vv)&&(Vv=t):Ir(t,Vv)>Ir(Hv,Vv)&&(Hv=t):Vv>=Hv?(t<Hv&&(Hv=t),t>Vv&&(Vv=t)):t>$v?Ir(Hv,t)>Ir(Hv,Vv)&&(Vv=t):Ir(t,Vv)>Ir(Hv,Vv)&&(Hv=t)}else Rr(t,n);Jv=e,$v=t}function Lr(){X_.point=qr}function Ur(){Kv[0]=Hv,Kv[1]=Vv,X_.point=Rr,Jv=null}function Dr(t,n){if(Jv){var e=t-$v;H_.add(N_(e)>180?e+(e>0?360:-360):e)}else Zv=t,Gv=n;B_.point(t,n),qr(t,n)}function Or(){B_.lineStart()}function Fr(){Dr(Zv,Gv),B_.lineEnd(),N_(H_)>y_&&(Hv=-(Vv=180)),Kv[0]=Hv,Kv[1]=Vv,Jv=null}function Ir(t,n){return(n-=t)<0?n+360:n}function Yr(t,n){return t[0]-n[0]}function Br(t,n){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}function jr(t,n){t*=T_,n*=T_;var e=E_(n);Hr(e*E_(t),e*R_(t),R_(n))}function Hr(t,n,e){++t_,e_+=(t-e_)/t_,r_+=(n-r_)/t_,i_+=(e-i_)/t_}function Xr(){W_.point=Vr}function Vr(t,n){t*=T_,n*=T_;var e=E_(n);p_=e*E_(t),d_=e*R_(t),v_=R_(n),W_.point=Wr,Hr(p_,d_,v_)}function Wr(t,n){t*=T_,n*=T_;var e=E_(n),r=e*E_(t),i=e*R_(t),o=R_(n),u=S_(L_((u=d_*o-v_*i)*u+(u=v_*r-p_*o)*u+(u=p_*i-d_*r)*u),p_*r+d_*i+v_*o);n_+=u,o_+=u*(p_+(p_=r)),u_+=u*(d_+(d_=i)),a_+=u*(v_+(v_=o)),Hr(p_,d_,v_)}function $r(){W_.point=jr}function Zr(){W_.point=Jr}function Gr(){Qr(l_,h_),W_.point=jr}function Jr(t,n){l_=t,h_=n,t*=T_,n*=T_,W_.point=Qr;var e=E_(n);p_=e*E_(t),d_=e*R_(t),v_=R_(n),Hr(p_,d_,v_)}function Qr(t,n){t*=T_,n*=T_;var e=E_(n),r=e*E_(t),i=e*R_(t),o=R_(n),u=d_*o-v_*i,a=v_*r-p_*o,c=p_*i-d_*r,s=L_(u*u+a*a+c*c),f=p_*r+d_*i+v_*o,l=s&&-vr(f)/s,h=S_(s,f);c_+=l*u,s_+=l*a,f_+=l*c,n_+=h,o_+=h*(p_+(p_=r)),u_+=h*(d_+(d_=i)),a_+=h*(v_+(v_=o)),Hr(p_,d_,v_)}function Kr(t,n){return[t>m_?t-w_:t<-m_?t+w_:t,n]}function ti(t,n,e){return(t%=w_)?n||e?G_(ei(t),ri(n,e)):ei(t):n||e?ri(n,e):Kr}function ni(t){return function(n,e){return n+=t,[n>m_?n-w_:n<-m_?n+w_:n,e]}}function ei(t){var n=ni(t);return n.invert=ni(-t),n}function ri(t,n){function e(t,n){var e=E_(n),a=E_(t)*e,c=R_(t)*e,s=R_(n),f=s*r+a*i;return[S_(c*o-f*u,a*r-s*i),_r(f*o+c*u)]}var r=E_(t),i=R_(t),o=E_(n),u=R_(n);return e.invert=function(t,n){var e=E_(n),a=E_(t)*e,c=R_(t)*e,s=R_(n),f=s*o-c*u;return[S_(c*o+s*u,a*r+f*i),_r(f*r-a*i)]},e}function ii(t,n,e,r,i,o){if(e){var u=E_(n),a=R_(n),c=r*e;null==i?(i=n+r*w_,o=n-c/2):(i=oi(u,i),o=oi(u,o),(r>0?i<o:i>o)&&(i+=r*w_));for(var s,f=i;r>0?f>o:f<o;f-=c)s=kr([u,-a*E_(f),-a*R_(f)]),t.point(s[0],s[1])}}function oi(t,n){n=Sr(n),n[0]-=t,Pr(n);var e=vr(-n[1]);return((-n[2]<0?-e:e)+w_-y_)%w_}function ui(t,n,e,r){this.x=t,this.z=n,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function ai(t){if(n=t.length){for(var n,e,r=0,i=t[0];++r<n;)i.n=e=t[r],e.p=i,i=e;i.n=e=t[0],e.p=i}}function ci(t,n,e,r){function i(i,o){return t<=i&&i<=e&&n<=o&&o<=r}function o(i,o,a,s){var f=0,l=0;if(null==i||(f=u(i,a))!==(l=u(o,a))||c(i,o)<0^a>0){do s.point(0===f||3===f?t:e,f>1?r:n);while((f=(f+a+4)%4)!==l)}else s.point(o[0],o[1])}function u(r,i){return N_(r[0]-t)<y_?i>0?0:3:N_(r[0]-e)<y_?i>0?2:1:N_(r[1]-n)<y_?i>0?1:0:i>0?3:2}function a(t,n){return c(t.x,n.x)}function c(t,n){var e=u(t,1),r=u(n,1);return e!==r?e-r:0===e?n[1]-t[1]:1===e?t[0]-n[0]:2===e?t[1]-n[1]:n[0]-t[0]}return function(u){function c(t,n){i(t,n)&&k.point(t,n)}function s(){for(var n=0,e=0,i=_.length;e<i;++e)for(var o,u,a=_[e],c=1,s=a.length,f=a[0],l=f[0],h=f[1];c<s;++c)o=l,u=h,f=a[c],l=f[0],h=f[1],u<=r?h>r&&(l-o)*(r-u)>(h-u)*(t-o)&&++n:h<=r&&(l-o)*(r-u)<(h-u)*(t-o)&&--n;return n}function f(){k=S,v=[],_=[],N=!0}function l(){var t=Line truncated
|
||||
}function a(t,n,e){var r=O.exec(n.slice(e));return r?(t.m=F[r[0].toLowerCase()],e+r[0].length):-1}function c(t,n,e){var r=U.exec(n.slice(e));return r?(t.m=D[r[0].toLowerCase()],e+r[0].length):-1}function s(t,n,e){return r(t,w,n,e)}function f(t,n,e){return r(t,M,n,e)}function l(t,n,e){return r(t,T,n,e)}function h(t){return S[t.getDay()]}function p(t){return k[t.getDay()]}function d(t){return A[t.getMonth()]}function v(t){return E[t.getMonth()]}function _(t){return N[+(t.getHours()>=12)]}function y(t){return S[t.getUTCDay()]}function g(t){return k[t.getUTCDay()]}function m(t){return A[t.getUTCMonth()]}function x(t){return E[t.getUTCMonth()]}function b(t){return N[+(t.getUTCHours()>=12)]}var w=t.dateTime,M=t.date,T=t.time,N=t.periods,k=t.days,S=t.shortDays,E=t.months,A=t.shortMonths,C=Gu(N),z=Ju(N),P=Gu(k),R=Ju(k),q=Gu(S),L=Ju(S),U=Gu(E),D=Ju(E),O=Gu(A),F=Ju(A),I={a:h,A:p,b:d,B:v,c:null,d:ha,e:ha,H:pa,I:da,j:va,L:_a,m:ya,M:ga,p:_,S:ma,U:xa,w:ba,W:wa,x:null,X:null,y:Ma,Y:Ta,Z:Na,"%":Ia},Y={a:y,A:g,b:m,B:x,c:null,d:ka,e:ka,H:Sa,I:Ea,j:Aa,L:Ca,m:za,M:Pa,p:b,S:Ra,U:qa,w:La,W:Ua,x:null,X:null,y:Da,Y:Oa,Z:Fa,"%":Ia},B={a:o,A:u,b:a,B:c,c:s,d:oa,e:oa,H:aa,I:aa,j:ua,L:fa,m:ia,M:ca,p:i,S:sa,U:Ku,w:Qu,W:ta,x:f,X:l,y:ea,Y:na,Z:ra,"%":la};return I.x=n(M,I),I.X=n(T,I),I.c=n(w,I),Y.x=n(M,Y),Y.X=n(T,Y),Y.c=n(w,Y),{format:function(t){var e=n(t+="",I);return e.toString=function(){return t},e},parse:function(t){var n=e(t+="",Hu);return n.toString=function(){return t},n},utcFormat:function(t){var e=n(t+="",Y);return e.toString=function(){return t},e},utcParse:function(t){var n=e(t,Xu);return n.toString=function(){return t},n}}}function $u(t,n,e){var r=t<0?"-":"",i=(r?-t:t)+"",o=i.length;return r+(o<e?new Array(e-o+1).join(n)+i:i)}function Zu(t){return t.replace(Lx,"\\$&")}function Gu(t){return new RegExp("^(?:"+t.map(Zu).join("|")+")","i")}function Ju(t){for(var n={},e=-1,r=t.length;++e<r;)n[t[e].toLowerCase()]=e;return n}function Qu(t,n,e){var r=Rx.exec(n.slice(e,e+1));return r?(t.w=+r[0],e+r[0].length):-1}function Ku(t,n,e){var r=Rx.exec(n.slice(e));return r?(t.U=+r[0],e+r[0].length):-1}function ta(t,n,e){var r=Rx.exec(n.slice(e));return r?(t.W=+r[0],e+r[0].length):-1}function na(t,n,e){var r=Rx.exec(n.slice(e,e+4));return r?(t.y=+r[0],e+r[0].length):-1}function ea(t,n,e){var r=Rx.exec(n.slice(e,e+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),e+r[0].length):-1}function ra(t,n,e){var r=/^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(n.slice(e,e+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),e+r[0].length):-1}function ia(t,n,e){var r=Rx.exec(n.slice(e,e+2));return r?(t.m=r[0]-1,e+r[0].length):-1}function oa(t,n,e){var r=Rx.exec(n.slice(e,e+2));return r?(t.d=+r[0],e+r[0].length):-1}function ua(t,n,e){var r=Rx.exec(n.slice(e,e+3));return r?(t.m=0,t.d=+r[0],e+r[0].length):-1}function aa(t,n,e){var r=Rx.exec(n.slice(e,e+2));return r?(t.H=+r[0],e+r[0].length):-1}function ca(t,n,e){var r=Rx.exec(n.slice(e,e+2));return r?(t.M=+r[0],e+r[0].length):-1}function sa(t,n,e){var r=Rx.exec(n.slice(e,e+2));return r?(t.S=+r[0],e+r[0].length):-1}function fa(t,n,e){var r=Rx.exec(n.slice(e,e+3));return r?(t.L=+r[0],e+r[0].length):-1}function la(t,n,e){var r=qx.exec(n.slice(e,e+1));return r?e+r[0].length:-1}function ha(t,n){return $u(t.getDate(),n,2)}function pa(t,n){return $u(t.getHours(),n,2)}function da(t,n){return $u(t.getHours()%12||12,n,2)}function va(t,n){return $u(1+Ym.count(ox(t),t),n,3)}function _a(t,n){return $u(t.getMilliseconds(),n,3)}function ya(t,n){return $u(t.getMonth()+1,n,2)}function ga(t,n){return $u(t.getMinutes(),n,2)}function ma(t,n){return $u(t.getSeconds(),n,2)}function xa(t,n){return $u(jm.count(ox(t),t),n,2)}function ba(t){return t.getDay()}function wa(t,n){return $u(Hm.count(ox(t),t),n,2)}function Ma(t,n){return $u(t.getFullYear()%100,n,2)}function Ta(t,n){return $u(t.getFullYear()%1e4,n,4)}function Na(t){var n=t.getTimezoneOffset();return(n>0?"-":(n*=-1,"+"))+$u(n/60|0,"0",2)+$u(n%60,"0",2)}function ka(t,n){return $u(t.getUTCDate(),n,2)}function Sa(t,n){return $u(t.getUTCHours(),n,2)}function Ea(t,n){return $u(t.getUTCHours()%12||12,n,2)}function Aa(t,n){return $u(1+lx.count(Ax(t),t),n,3)}function Ca(t,n){return $u(t.getUTCMilliseconds(),n,3)}function za(t,n){return $u(t.getUTCMonth()+1,n,2)}function Pa(t,n){return $u(t.getUTCMinutes(),n,2)}function Ra(t,n){return $u(t.getUTCSeconds(),n,2)}function qa(t,n){return $u(px.count(Ax(t),t),n,2)}function La(t){return t.getUTCDay()}function Ua(t,n){return $u(dx.count(Ax(t),t),n,2)}function Da(t,n){return $u(t.getUTCFullYear()%100,n,2)}function Oa(t,n){return $u(t.getUTCFullYear()%1e4,n,4)}function Fa(){return"+0000"}function Ia(){return"%"}function Ya(n){return Cx=Wu(n),t.timeFormat=Cx.format,t.timeParse=Cx.parse,t.utcFormat=Cx.utcFormat,t.utcParse=Cx.utcParse,Cx}function Ba(t){return t.toISOString()}function ja(t){var n=new Date(t);return isNaN(n)?null:n}function Ha(t){return new Date(t)}function Xa(t){return t instanceof Date?+t:+new Date(+t)}function Va(t,n,r,i,o,u,a,c,s){function f(e){retLine truncated
|
||||
n):d},n.on=function(){var t=_.on.apply(_,arguments);return t===_?n:t},n},bl=function(t,n,e){t.prototype=n.prototype=e,e.constructor=t},wl=.7,Ml=1/wl,Tl="\\s*([+-]?\\d+)\\s*",Nl="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",kl="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",Sl=/^#([0-9a-f]{3})$/,El=/^#([0-9a-f]{6})$/,Al=new RegExp("^rgb\\("+[Tl,Tl,Tl]+"\\)$"),Cl=new RegExp("^rgb\\("+[kl,kl,kl]+"\\)$"),zl=new RegExp("^rgba\\("+[Tl,Tl,Tl,Nl]+"\\)$"),Pl=new RegExp("^rgba\\("+[kl,kl,kl,Nl]+"\\)$"),Rl=new RegExp("^hsl\\("+[Nl,kl,kl]+"\\)$"),ql=new RegExp("^hsla\\("+[Nl,kl,kl,Nl]+"\\)$"),Ll={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};bl(wt,Mt,{displayable:function(){return this.rgb().displayable()},toString:function(){return this.rgb()+""}}),bl(Et,St,bt(wt,{brighter:function(t){return t=null==t?Ml:Math.pow(Ml,t),new Et(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?wl:Math.pow(wl,t),new Et(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return 0<=this.r&&this.r<=255&&0<=this.g&&this.g<=255&&0<=this.b&&this.b<=255&&0<=this.opacity&&this.opacity<=1},toString:function(){var t=this.opacity;return t=isNaN(t)?1:Math.max(0,Math.min(1,t)),(1===t?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}})),bl(Pt,zt,bt(wt,{brighter:function(t){return t=null==t?Ml:Math.pow(Ml,t),new Pt(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?wl:Math.pow(wl,t),new Pt(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),n=isNaN(t)||isNaN(this.s)?0:this.s,e=this.l,r=e+(e<.5?e:1-e)*n,i=2*e-r;return new Et(Rt(t>=240?t-240:t+120,i,r),Rt(t,i,r),Rt(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1}}));var Ul=Math.PI/180,Dl=180/Math.PI,Ol=18,Fl=.95047,Il=1,Yl=1.08883,Bl=4/29,jl=6/29,Hl=3*jl*jl,Xl=jl*jl*jl;bl(Ut,Lt,bt(wt,{brighter:function(t){return new Ut(this.l+Ol*(null==t?1:t),this.a,this.b,this.opacity)},darker:function(t){return new Ut(this.l-Ol*(null==t?1:t),this.a,this.b,this.opacity)},rgb:function(){var t=(this.l+16)/116,n=isNaN(this.a)?t:t+this.a/500,e=isNLine truncated
|
||||
return arguments.length?(s=+t,o):s},velocityDecay:function(t){return arguments.length?(f=1-t,o):1-f},force:function(t,n){return arguments.length>1?(null==n?l.remove(t):l.set(t,i(n)),o):l.get(t)},find:function(n,e,r){var i,o,u,a,c,s=0,f=t.length;for(null==r?r=1/0:r*=r,s=0;s<f;++s)a=t[s],i=n-a.x,o=e-a.y,u=i*i+o*o,u<r&&(c=a,r=u);return c},on:function(t,n){return arguments.length>1?(d.on(t,n),o):d.on(t)}}},xv=function(){function t(t){var n,a=i.length,c=nr(i,cr,sr).visitAfter(e);for(u=t,n=0;n<a;++n)o=i[n],c.visit(r)}function n(){if(i){var t,n,e=i.length;for(a=new Array(e),t=0;t<e;++t)n=i[t],a[n.index]=+c(n,t,i)}}function e(t){var n,e,r,i,o,u=0;if(t.length){for(r=i=o=0;o<4;++o)(n=t[o])&&(e=n.value)&&(u+=e,r+=e*n.x,i+=e*n.y);t.x=r/u,t.y=i/u}else{n=t,n.x=n.data.x,n.y=n.data.y;do u+=a[n.data.index];while(n=n.next)}t.value=u}function r(t,n,e,r){if(!t.value)return!0;var i=t.x-o.x,c=t.y-o.y,h=r-n,p=i*i+c*c;if(h*h/l<p)return p<f&&(0===i&&(i=Kd(),p+=i*i),0===c&&(c=Kd(),p+=c*c),p<s&&(p=Math.sqrt(s*p)),o.vx+=i*t.value*u/p,o.vy+=c*t.value*u/p),!0;if(!(t.length||p>=f)){(t.data!==o||t.next)&&(0===i&&(i=Kd(),p+=i*i),0===c&&(c=Kd(),p+=c*c),p<s&&(p=Math.sqrt(s*p)));do t.data!==o&&(h=a[t.data.index]*u/p,o.vx+=i*h,o.vy+=c*h);while(t=t.next)}}var i,o,u,a,c=Qd(-30),s=1,f=1/0,l=.81;return t.initialize=function(t){i=t,n()},t.strength=function(e){return arguments.length?(c="function"==typeof e?e:Qd(+e),n(),t):c},t.distanceMin=function(n){return arguments.length?(s=n*n,t):Math.sqrt(s)},t.distanceMax=function(n){return arguments.length?(f=n*n,t):Math.sqrt(f)},t.theta=function(n){return arguments.length?(l=n*n,t):Math.sqrt(l)},t},bv=function(t){function n(t){for(var n,e=0,u=r.length;e<u;++e)n=r[e],n.vx+=(o[e]-n.x)*i[e]*t}function e(){if(r){var n,e=r.length;for(i=new Array(e),o=new Array(e),n=0;n<e;++n)i[n]=isNaN(o[n]=+t(r[n],n,r))?0:+u(r[n],n,r)}}var r,i,o,u=Qd(.1);return"function"!=typeof t&&(t=Qd(null==t?0:+t)),n.initialize=function(t){r=t,e()},n.strength=function(t){return arguments.length?(u="function"==typeof t?t:Qd(+t),e(),n):u},n.x=function(r){return arguments.length?(t="function"==typeof r?r:Qd(+r),e(),n):t},n},wv=function(t){function n(t){for(var n,e=0,u=r.length;e<u;++e)n=r[e],n.vy+=(o[e]-n.y)*i[e]*t}function e(){if(r){var n,e=r.length;for(i=new Array(e),o=new Array(e),n=0;n<e;++n)i[n]=isNaN(o[n]=+t(r[n],n,r))?0:+u(r[n],n,r)}}var r,i,o,u=Qd(.1);return"function"!=typeof t&&(t=Qd(null==t?0:+t)),n.initialize=function(t){r=t,e()},n.strength=function(t){return arguments.length?(u="function"==typeof t?t:Qd(+t),e(),n):u},n.y=function(r){return arguments.length?(t="function"==typeof r?r:Qd(+r),e(),n):t},n},Mv=function(t,n){if((e=(t=n?t.toExponential(n-1):t.toExponential()).indexOf("e"))<0)return null;var e,r=t.slice(0,e);return[r.length>1?r[0]+r.slice(2):r,+t.slice(e+1)]},Tv=function(t){return t=Mv(Math.abs(t)),t?t[1]:NaN},Nv=function(t,n){return function(e,r){for(var i=e.length,o=[],u=0,a=t[0],c=0;i>0&&a>0&&(c+a+1>r&&(a=Math.max(1,r-c)),o.push(e.substring(i-=a,i+a)),!((c+=a+1)>r));)a=t[u=(u+1)%t.length];return o.reverse().join(n)}},kv=function(t,n){t=t.toPrecision(n);t:for(var e,r=t.length,i=1,o=-1;i<r;++i)switch(t[i]){case".":o=e=i;break;case"0":0===o&&(o=i),e=i;break;case"e":break t;default:o>0&&(o=0)}return o>0?t.slice(0,o)+t.slice(e+1):t},Sv=function(t,n){var e=Mv(t,n);if(!e)return t+"";var r=e[0],i=e[1],o=i-(dv=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,u=r.length;return o===u?r:o>u?r+new Array(o-u+1).join("0"):o>0?r.slice(0,o)+"."+r.slice(o):"0."+new Array(1-o).join("0")+Mv(t,Math.max(0,n+o-1))[0]},Ev=function(t,n){var e=Mv(t,n);if(!e)return t+"";var r=e[0],i=e[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")},Av={"":kv,"%":function(t,n){return(100*t).toFixed(n)},b:function(t){return Math.round(t).toString(2)},c:function(t){return t+""},d:function(t){return Math.round(t).toString(10)},e:function(t,n){return t.toExponential(n)},f:function(t,n){return t.toFixed(n)},g:function(t,n){return t.toPrecision(n)},o:function(t){return Math.round(t).toString(8)},p:function(t,n){return Ev(100*t,n)},r:Ev,s:Sv,X:function(t){return Math.round(t).toString(16).toUpperCase()},x:function(t){return Math.round(t).toString(16)}},Cv=/^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i,zv=function(t){return new fr(t)};fr.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(null==this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(null==this.precision?"":"."+Math.max(0,0|this.precision))+this.type};var Pv,Rv=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"],qv=function(t){function n(t){function n(t){var n,i,c,g=d,m=v;if("c"===p)m=_(t)+m,t="";else{t=+t;var x=(t<0||1/t<0)&&(t*=-1,!0);if(t=_(t,h),x)for(n=-1,i=t.length,x=!1;++n<i;)if(c=t.charCodeAt(n),48<c&&c<58||"x"===p&&96<c&&c<103||"X"===p&&64<c&&c<71){x=!0;break}if(g=(x?"("===a?a:"-":"-"===a||"("===a?"":a)+g,m=m+("s"===p?Rv[8+dv/3]:Line truncated
|
||||
return function(){for(var n=0,e=0;e<t;++e)n+=Math.random();return n}},um=function(t){var n=om(t);return function(){return n()/t}},am=function(t){return function(){return-Math.log(1-Math.random())/t}},cm=function(t,n){function e(t){var n,e=s.status;if(!e&&hu(s)||e>=200&&e<300||304===e){if(o)try{n=o.call(r,s)}catch(t){return void a.call("error",r,t)}else n=s;a.call("load",r,n)}else a.call("error",r,t)}var r,i,o,u,a=p("beforesend","progress","load","error"),c=Ie(),s=new XMLHttpRequest,f=null,l=null,h=0;if("undefined"==typeof XDomainRequest||"withCredentials"in s||!/^(http(s)?:)?\/\//.test(t)||(s=new XDomainRequest),"onload"in s?s.onload=s.onerror=s.ontimeout=e:s.onreadystatechange=function(t){s.readyState>3&&e(t)},s.onprogress=function(t){a.call("progress",r,t)},r={header:function(t,n){return t=(t+"").toLowerCase(),arguments.length<2?c.get(t):(null==n?c.remove(t):c.set(t,n+""),r)},mimeType:function(t){return arguments.length?(i=null==t?null:t+"",r):i},responseType:function(t){return arguments.length?(u=t,r):u},timeout:function(t){return arguments.length?(h=+t,r):h},user:function(t){return arguments.length<1?f:(f=null==t?null:t+"",r)},password:function(t){return arguments.length<1?l:(l=null==t?null:t+"",r)},response:function(t){return o=t,r},get:function(t,n){return r.send("GET",t,n)},post:function(t,n){return r.send("POST",t,n)},send:function(n,e,o){return s.open(n,t,!0,f,l),null==i||c.has("accept")||c.set("accept",i+",*/*"),s.setRequestHeader&&c.each(function(t,n){s.setRequestHeader(n,t)}),null!=i&&s.overrideMimeType&&s.overrideMimeType(i),null!=u&&(s.responseType=u),h>0&&(s.timeout=h),null==o&&"function"==typeof e&&(o=e,e=null),null!=o&&1===o.length&&(o=lu(o)),null!=o&&r.on("error",o).on("load",function(t){o(null,t)}),a.call("beforesend",r,s),s.send(null==e?null:e),r},abort:function(){return s.abort(),r},on:function(){var t=a.on.apply(a,arguments);return t===a?r:t}},null!=n){if("function"!=typeof n)throw new Error("invalid callback: "+n);return r.get(n)}return r},sm=function(t,n){return function(e,r){var i=cm(e).mimeType(t).response(n);if(null!=r){if("function"!=typeof r)throw new Error("invalid callback: "+r);return i.get(r)}return i}},fm=sm("text/html",function(t){return document.createRange().createContextualFragment(t.responseText)}),lm=sm("application/json",function(t){return JSON.parse(t.responseText)}),hm=sm("text/plain",function(t){return t.responseText}),pm=sm("application/xml",function(t){var n=t.responseXML;if(!n)throw new Error("parse error");return n}),dm=function(t,n){return function(e,r,i){arguments.length<3&&(i=r,r=null);var o=cm(e).mimeType(t);return o.row=function(t){return arguments.length?o.response(pu(n,r=t)):r},o.row(r),i?o.get(i):o}},vm=dm("text/csv",Bd),_m=dm("text/tab-separated-values",Wd),ym=Array.prototype,gm=ym.map,mm=ym.slice,xm={name:"implicit"},bm=function(t){return function(){return t}},wm=function(t){return+t},Mm=[0,1],Tm=function(n,r,i){var o,u=n[0],a=n[n.length-1],c=e(u,a,null==r?10:r);switch(i=zv(null==i?",f":i),i.type){case"s":var s=Math.max(Math.abs(u),Math.abs(a));return null!=i.precision||isNaN(o=Uv(c,s))||(i.precision=o),t.formatPrefix(i,s);case"":case"e":case"g":case"p":case"r":null!=i.precision||isNaN(o=Dv(c,Math.max(Math.abs(u),Math.abs(a))))||(i.precision=o-("e"===i.type));break;case"f":case"%":null!=i.precision||isNaN(o=Lv(c))||(i.precision=o-2*("%"===i.type))}return t.format(i)},Nm=function(t,n){t=t.slice();var e,r=0,i=t.length-1,o=t[r],u=t[i];return u<o&&(e=r,r=i,i=e,e=o,o=u,u=e),t[r]=n.floor(o),t[i]=n.ceil(u),t},km=new Date,Sm=new Date,Em=Yu(function(){},function(t,n){t.setTime(+t+n)},function(t,n){return n-t});Em.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?Yu(function(n){n.setTime(Math.floor(n/t)*t)},function(n,e){n.setTime(+n+e*t)},function(n,e){return(e-n)/t}):Em:null};var Am=Em.range,Cm=1e3,zm=6e4,Pm=36e5,Rm=864e5,qm=6048e5,Lm=Yu(function(t){t.setTime(Math.floor(t/Cm)*Cm)},function(t,n){t.setTime(+t+n*Cm)},function(t,n){return(n-t)/Cm},function(t){return t.getUTCSeconds()}),Um=Lm.range,Dm=Yu(function(t){t.setTime(Math.floor(t/zm)*zm)},function(t,n){t.setTime(+t+n*zm)},function(t,n){return(n-t)/zm},function(t){return t.getMinutes()}),Om=Dm.range,Fm=Yu(function(t){var n=t.getTimezoneOffset()*zm%Pm;n<0&&(n+=Pm),t.setTime(Math.floor((+t-n)/Pm)*Pm+n)},function(t,n){t.setTime(+t+n*Pm)},function(t,n){return(n-t)/Pm},function(t){return t.getHours()}),Im=Fm.range,Ym=Yu(function(t){t.setHours(0,0,0,0)},function(t,n){t.setDate(t.getDate()+n)},function(t,n){return(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*zm)/Rm},function(t){return t.getDate()-1}),Bm=Ym.range,jm=Bu(0),Hm=Bu(1),Xm=Bu(2),Vm=Bu(3),Wm=Bu(4),$m=Bu(5),Zm=Bu(6),Gm=jm.range,Jm=Hm.range,Qm=Xm.range,Km=Vm.range,tx=Wm.range,nx=$m.range,ex=Zm.range,rx=Yu(function(t){t.setDate(1),t.setHours(0,0,0,0)},function(t,n){t.setMonth(t.getMonth()+n)},function(t,n){return n.getMonth()-t.getMonth()+12*(n.getFullYear()-t.getFullYear())},function(t){return t.getMonth()}),ix=rx.range,ox=Yu(function(t)Line truncated
|
||||
},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:gc(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Kb=function t(n){function e(t){return n?new bc(t,n):new yc(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);wc.prototype={areaStart:jb,areaEnd:jb,lineStart:function(){this._point=0},lineEnd:function(){this._point&&this._context.closePath()},point:function(t,n){t=+t,n=+n,this._point?this._context.lineTo(t,n):(this._point=1,this._context.moveTo(t,n))}};var tw=function(t){return new wc(t)};Sc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:kc(this,this._t0,Nc(this,this._t0))}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){var e=NaN;if(t=+t,n=+n,t!==this._x1||n!==this._y1){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3,kc(this,Nc(this,e=Tc(this,t,n)),e);break;default:kc(this,this._t0,e=Tc(this,t,n))}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n,this._t0=e}}},(Ec.prototype=Object.create(Sc.prototype)).point=function(t,n){Sc.prototype.point.call(this,n,t)},Ac.prototype={moveTo:function(t,n){this._context.moveTo(n,t)},closePath:function(){this._context.closePath()},lineTo:function(t,n){this._context.lineTo(n,t)},bezierCurveTo:function(t,n,e,r,i,o){this._context.bezierCurveTo(n,t,r,e,o,i)}},Pc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=[],this._y=[]},lineEnd:function(){var t=this._x,n=this._y,e=t.length;if(e)if(this._line?this._context.lineTo(t[0],n[0]):this._context.moveTo(t[0],n[0]),2===e)this._context.lineTo(t[1],n[1]);else for(var r=Rc(t),i=Rc(n),o=0,u=1;u<e;++o,++u)this._context.bezierCurveTo(r[0][o],i[0][o],r[1][o],i[1][o],t[u],n[u]);(this._line||0!==this._line&&1===e)&&this._context.closePath(),this._line=1-this._line,this._x=this._y=null},point:function(t,n){this._x.push(+t),this._y.push(+n)}};var nw=function(t){return new Pc(t)};qc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=this._y=NaN,this._point=0},lineEnd:function(){0<this._t&&this._t<1&&2===this._point&&this._context.lineTo(this._x,this._y),(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line>=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,n),this._context.lineTo(t,n);else{var e=this._x*(1-this._t)+t*this._t;this._context.lineTo(e,this._y),this._context.lineTo(e,n)}}this._x=t,this._y=n}};var ew=function(t){return new qc(t,.5)},rw=Array.prototype.slice,iw=function(t,n){if((r=t.length)>1)for(var e,r,i=1,o=t[n[0]],u=o.length;i<r;++i){e=o,o=t[n[i]];for(var a=0;a<u;++a)o[a][1]+=o[a][0]=isNaN(e[a][1])?e[a][0]:e[a][1]}},ow=function(t){for(var n=t.length,e=new Array(n);--n>=0;)e[n]=n;return e},uw=function(){function t(t){var o,u,a=n.apply(this,arguments),c=t.length,s=a.length,f=new Array(s);for(o=0;o<s;++o){for(var l,h=a[o],p=f[o]=new Array(c),d=0;d<c;++d)p[d]=l=[0,+i(t[d],h,d,t)],l.data=t[d];p.key=h}for(o=0,u=e(f);o<s;++o)f[u[o]].index=o;return r(f,u),f}var n=cb([]),e=ow,r=iw,i=Dc;return t.keys=function(e){return arguments.length?(n="function"==typeof e?e:cb(rw.call(e)),t):n},t.value=function(n){return arguments.length?(i="function"==typeof n?n:cb(+n),t):i},t.order=function(n){return arguments.length?(e=null==n?ow:"function"==typeof n?n:cb(rw.call(n)),t):e},t.offset=function(n){return arguments.length?(r=null==n?iw:n,t):r},t},aw=function(t,n){if((r=t.length)>0){for(var e,r,i,o=0,u=t[0].length;o<u;++o){for(i=e=0;e<r;++e)i+=t[e][o][1]||0;if(i)for(e=0;e<r;++e)t[e][o][1]/=i}iw(t,n)}},cw=function(t,n){if((e=t.length)>0){for(var e,r=0,i=t[n[0]],o=i.length;r<o;++r){for(var u=0,a=0;u<e;++u)a+=t[u][r][1]||0;i[r][1]+=i[r][0]=-a/2}iw(t,n)}},sw=function(t,n){if((i=t.length)>0&&(r=(e=t[n[0]]).length)>0){for(var e,r,i,o=0,u=1;u<r;++u){for(var a=0,c=0,s=0;a<i;++a){for(var f=t[n[a]],l=f[u][1]||0,h=f[u-1][1]||0,p=(l-Line truncated
|
||||
@@ -12,37 +12,23 @@ function exit_if_fail {
|
||||
|
||||
cd /home/ubuntu/.go_workspace/src/github.com/grafana/grafana
|
||||
|
||||
rm -rf node_modules
|
||||
npm install -g yarn --quiet
|
||||
yarn install --pure-lockfile --no-progress
|
||||
|
||||
exit_if_fail npm run test-ci
|
||||
exit_if_fail npm run build
|
||||
|
||||
# publish code coverage
|
||||
echo "Publishing javascript code coverage"
|
||||
bash <(curl -s https://codecov.io/bash) -cF javascript
|
||||
rm -rf coverage
|
||||
# npm install -g codecov
|
||||
# codecov
|
||||
# cat ./coverage/lcov.info | node ./node_modules/coveralls/bin/coveralls.js
|
||||
|
||||
echo "running go fmt"
|
||||
exit_if_fail test -z "$(gofmt -s -l ./pkg | tee /dev/stderr)"
|
||||
|
||||
echo "running go vet"
|
||||
exit_if_fail test -z "$(go vet ./pkg/... | tee /dev/stderr)"
|
||||
|
||||
echo "building binaries"
|
||||
exit_if_fail go run build.go build
|
||||
cd ~/dev/go/src/github.com/grafana/grafana
|
||||
echo "building backend with install to cache pkgs"
|
||||
exit_if_fail time go install ./pkg/cmd/grafana-server
|
||||
|
||||
echo "running go test"
|
||||
|
||||
set -e
|
||||
echo "" > coverage.txt
|
||||
|
||||
for d in $(go list ./pkg/...); do
|
||||
exit_if_fail go test -race -coverprofile=profile.out -covermode=atomic $d
|
||||
time for d in $(go list ./pkg/...); do
|
||||
exit_if_fail go test -coverprofile=profile.out -covermode=atomic $d
|
||||
if [ -f profile.out ]; then
|
||||
cat profile.out >> coverage.txt
|
||||
rm profile.out
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
function exit_if_fail {
|
||||
command=$@
|
||||
echo "Executing '$command'"
|
||||
eval $command
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
echo "'$command' returned $rc."
|
||||
exit $rc
|
||||
fi
|
||||
}
|
||||
|
||||
cd /home/ubuntu/.go_workspace/src/github.com/grafana/grafana
|
||||
|
||||
rm -rf node_modules
|
||||
npm install -g yarn --quiet
|
||||
yarn install --pure-lockfile --no-progress
|
||||
|
||||
exit_if_fail npm run test:coverage
|
||||
exit_if_fail npm run build
|
||||
|
||||
# publish code coverage
|
||||
echo "Publishing javascript code coverage"
|
||||
bash <(curl -s https://codecov.io/bash) -cF javascript
|
||||
rm -rf coverage
|
||||
@@ -7,7 +7,7 @@ module.exports = function(grunt) {
|
||||
'clean:release',
|
||||
'clean:build',
|
||||
'phantomjs',
|
||||
'webpack:prod',
|
||||
'exec:webpack',
|
||||
]);
|
||||
|
||||
};
|
||||
@@ -19,6 +19,12 @@ module.exports = function(grunt) {
|
||||
'no-only-tests'
|
||||
]);
|
||||
|
||||
grunt.registerTask('precommit', [
|
||||
'sasslint',
|
||||
'exec:tslint',
|
||||
'no-only-tests'
|
||||
]);
|
||||
|
||||
grunt.registerTask('no-only-tests', function() {
|
||||
var files = grunt.file.expand('public/**/*_specs\.ts', 'public/**/*_specs\.js');
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
module.exports = function(config, grunt) {
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
var coverage = '';
|
||||
if (config.coverage) {
|
||||
coverage = '--coverage';
|
||||
coverage = '--coverage --maxWorkers 2';
|
||||
}
|
||||
|
||||
return {
|
||||
tslint : "node ./node_modules/tslint/lib/tslint-cli.js -c tslint.json --project ./tsconfig.json",
|
||||
jest : "node ./node_modules/jest-cli/bin/jest.js " + coverage,
|
||||
tslint: 'node ./node_modules/tslint/lib/tslint-cli.js -c tslint.json --project ./tsconfig.json',
|
||||
jest: 'node ./node_modules/jest-cli/bin/jest.js ' + coverage,
|
||||
webpack: 'node ./node_modules/webpack/bin/webpack.js --config scripts/webpack/webpack.prod.js',
|
||||
};
|
||||
};
|
||||
@@ -5,7 +5,7 @@ module.exports = function() {
|
||||
'use strict';
|
||||
return {
|
||||
options: {
|
||||
stats: !process.env.NODE_ENV || process.env.NODE_ENV === 'development'
|
||||
stats: false,
|
||||
},
|
||||
dev: dev,
|
||||
prod: prod
|
||||
|
||||
@@ -27,7 +27,10 @@ module.exports = merge(common, {
|
||||
},
|
||||
|
||||
devServer: {
|
||||
stats: 'errors-only',
|
||||
noInfo: true,
|
||||
stats: {
|
||||
chunks: false,
|
||||
},
|
||||
},
|
||||
|
||||
plugins: [
|
||||
|
||||
+28
-11
@@ -1,11 +1,28 @@
|
||||
Contributors to log15:
|
||||
|
||||
- Aaron L
|
||||
- Alan Shreve
|
||||
- Chris Hines
|
||||
- Ciaran Downey
|
||||
- Dmitry Chestnykh
|
||||
- Evan Shaw
|
||||
- Péter Szilágyi
|
||||
- Trevor Gattis
|
||||
- Vincent Vanackere
|
||||
Aaron L <aaron@bettercoder.net>
|
||||
Alan Shreve <alan@inconshreveable.com>
|
||||
Andy Walker <walkeraj@gmail.com>
|
||||
Andy Watson <andrewmoorewatson@gmail.com>
|
||||
Carl Veazey <Carl_Veazey@cable.comcast.com>
|
||||
Chris Hines <github@cs-guy.com>
|
||||
Christoph Hack <christoph@tux21b.org>
|
||||
Ciaran Downey <me@ciarand.me>
|
||||
Dmitry Chestnykh <dmitry@codingrobots.com>
|
||||
Evan Shaw <edsrzf@gmail.com>
|
||||
Gonzalo Serrano <boikot@gmail.com>
|
||||
Jeremy <jrbudnack@starkandwayne.com>
|
||||
Jonathan Rudenberg <jonathan@titanous.com>
|
||||
Kang Seong-Min <kang.seongmin@gmail.com>
|
||||
Kevin Burke <kev@inburke.com>
|
||||
Marc Abramowitz <marc@marc-abramowitz.com>
|
||||
Nathan Baulch <nathan.baulch@gmail.com>
|
||||
NotZippy <notzippy@gmail.com>
|
||||
Péter Szilágyi <peterke@gmail.com>
|
||||
Robert Egorov <robert.egorov@gmail.com>
|
||||
Robert Starbuck <robstarbuck@gmail.com>
|
||||
Robert Zaremba <robert.zaremba@scale-it.pl>
|
||||
Sean Chittenden <sean@chittenden.org>
|
||||
Spencer Nelson <s@spenczar.com>
|
||||
Tomasz Grodzki <tg@users.noreply.github.com>
|
||||
Trevor Gattis <github@trevorgattis.com>
|
||||
Vincent Vanackere <vincent.vanackere@gmail.com>
|
||||
Will McGovern <will@brkt.com>
|
||||
+7
@@ -73,5 +73,12 @@ srvlog := log.New(log.Ctx{"module": "app/server"})
|
||||
srvlog.Warn("abnormal conn rate", log.Ctx{"rate": curRate, "low": lowRate, "high": highRate})
|
||||
```
|
||||
|
||||
### Regenerating the CONTRIBUTORS file
|
||||
|
||||
```
|
||||
go get -u github.com/kevinburke/write_mailmap
|
||||
write_mailmap > CONTRIBUTORS
|
||||
```
|
||||
|
||||
## License
|
||||
Apache
|
||||
+1
-1
@@ -23,7 +23,7 @@ To get started, you'll want to import the library:
|
||||
Now you're ready to start logging:
|
||||
|
||||
func main() {
|
||||
log.Info("Program starting", "args", os.Args())
|
||||
log.Info("Program starting", "args", os.Args)
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-2
@@ -18,6 +18,7 @@ const (
|
||||
termMsgJust = 40
|
||||
)
|
||||
|
||||
// Format is the interface implemented by StreamHandler formatters.
|
||||
type Format interface {
|
||||
Format(r *Record) []byte
|
||||
}
|
||||
@@ -147,7 +148,7 @@ func JsonFormatEx(pretty, lineSeparated bool) Format {
|
||||
if !ok {
|
||||
props[errorKey] = fmt.Sprintf("%+v is not a string key", r.Ctx[i])
|
||||
}
|
||||
props[k] = formatJsonValue(r.Ctx[i+1])
|
||||
props[k] = formatJSONValue(r.Ctx[i+1])
|
||||
}
|
||||
|
||||
b, err := jsonMarshal(props)
|
||||
@@ -192,7 +193,7 @@ func formatShared(value interface{}) (result interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func formatJsonValue(value interface{}) interface{} {
|
||||
func formatJSONValue(value interface{}) interface{} {
|
||||
value = formatShared(value)
|
||||
switch value.(type) {
|
||||
case int, int8, int16, int32, int64, float32, float64, uint, uint8, uint16, uint32, uint64, string:
|
||||
|
||||
+11
-14
@@ -11,8 +11,8 @@ import (
|
||||
"github.com/go-stack/stack"
|
||||
)
|
||||
|
||||
// A Logger prints its log records by writing to a Handler.
|
||||
// The Handler interface defines where and how log records are written.
|
||||
// Handler interface defines where and how log records are written.
|
||||
// A logger prints its log records by writing to a Handler.
|
||||
// Handlers are composable, providing you great flexibility in combining
|
||||
// them to achieve the logging structure that suits your applications.
|
||||
type Handler interface {
|
||||
@@ -188,7 +188,7 @@ func LvlFilterHandler(maxLvl Lvl, h Handler) Handler {
|
||||
}, h)
|
||||
}
|
||||
|
||||
// A MultiHandler dispatches any write to each of its handlers.
|
||||
// MultiHandler dispatches any write to each of its handlers.
|
||||
// This is useful for writing different types of log information
|
||||
// to different locations. For example, to log to a file and
|
||||
// standard error:
|
||||
@@ -207,7 +207,7 @@ func MultiHandler(hs ...Handler) Handler {
|
||||
})
|
||||
}
|
||||
|
||||
// A FailoverHandler writes all log records to the first handler
|
||||
// FailoverHandler writes all log records to the first handler
|
||||
// specified, but will failover and write to the second handler if
|
||||
// the first handler has failed, and so on for all handlers specified.
|
||||
// For example you might want to log to a network socket, but failover
|
||||
@@ -229,11 +229,9 @@ func FailoverHandler(hs ...Handler) Handler {
|
||||
err = h.Log(r)
|
||||
if err == nil {
|
||||
return nil
|
||||
} else {
|
||||
r.Ctx = append(r.Ctx, fmt.Sprintf("failover_err_%d", i), err)
|
||||
}
|
||||
r.Ctx = append(r.Ctx, fmt.Sprintf("failover_err_%d", i), err)
|
||||
}
|
||||
|
||||
return err
|
||||
})
|
||||
}
|
||||
@@ -315,13 +313,12 @@ func evaluateLazy(lz Lazy) (interface{}, error) {
|
||||
results := value.Call([]reflect.Value{})
|
||||
if len(results) == 1 {
|
||||
return results[0].Interface(), nil
|
||||
} else {
|
||||
values := make([]interface{}, len(results))
|
||||
for i, v := range results {
|
||||
values[i] = v.Interface()
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
values := make([]interface{}, len(results))
|
||||
for i, v := range results {
|
||||
values[i] = v.Interface()
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// DiscardHandler reports success for all writes but does nothing.
|
||||
@@ -333,7 +330,7 @@ func DiscardHandler() Handler {
|
||||
})
|
||||
}
|
||||
|
||||
// The Must object provides the following Handler creation functions
|
||||
// Must object provides the following Handler creation functions
|
||||
// which instead of returning an error parameter only return a Handler
|
||||
// and panic on failure: FileHandler, NetHandler, SyslogHandler, SyslogNetHandler
|
||||
var Must muster
|
||||
|
||||
+4
-1
@@ -12,8 +12,10 @@ const lvlKey = "lvl"
|
||||
const msgKey = "msg"
|
||||
const errorKey = "LOG15_ERROR"
|
||||
|
||||
// Lvl is a type for predefined log levels.
|
||||
type Lvl int
|
||||
|
||||
// List of predefined log Levels
|
||||
const (
|
||||
LvlCrit Lvl = iota
|
||||
LvlError
|
||||
@@ -40,7 +42,7 @@ func (l Lvl) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the appropriate Lvl from a string name.
|
||||
// LvlFromString returns the appropriate Lvl from a string name.
|
||||
// Useful for parsing command line args and configuration files.
|
||||
func LvlFromString(lvlString string) (Lvl, error) {
|
||||
switch lvlString {
|
||||
@@ -69,6 +71,7 @@ type Record struct {
|
||||
KeyNames RecordKeyNames
|
||||
}
|
||||
|
||||
// RecordKeyNames are the predefined names of the log props used by the Logger interface.
|
||||
type RecordKeyNames struct {
|
||||
Time string
|
||||
Msg string
|
||||
|
||||
+4
-3
@@ -3,10 +3,11 @@ package log15
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/inconshreveable/log15/term"
|
||||
"github.com/mattn/go-colorable"
|
||||
isatty "github.com/mattn/go-isatty"
|
||||
)
|
||||
|
||||
// Predefined handlers
|
||||
var (
|
||||
root *logger
|
||||
StdoutHandler = StreamHandler(os.Stdout, LogfmtFormat())
|
||||
@@ -14,11 +15,11 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
if term.IsTty(os.Stdout.Fd()) {
|
||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||
StdoutHandler = StreamHandler(colorable.NewColorableStdout(), TerminalFormat())
|
||||
}
|
||||
|
||||
if term.IsTty(os.Stderr.Fd()) {
|
||||
if isatty.IsTerminal(os.Stderr.Fd()) {
|
||||
StderrHandler = StreamHandler(colorable.NewColorableStderr(), TerminalFormat())
|
||||
}
|
||||
|
||||
|
||||
+15
-2
@@ -1,5 +1,10 @@
|
||||
# go-isatty
|
||||
|
||||
[](http://godoc.org/github.com/mattn/go-isatty)
|
||||
[](https://travis-ci.org/mattn/go-isatty)
|
||||
[](https://coveralls.io/github/mattn/go-isatty?branch=master)
|
||||
[](https://goreportcard.com/report/mattn/go-isatty)
|
||||
|
||||
isatty for golang
|
||||
|
||||
## Usage
|
||||
@@ -16,6 +21,8 @@ import (
|
||||
func main() {
|
||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||
fmt.Println("Is Terminal")
|
||||
} else if isatty.IsCygwinTerminal(os.Stdout.Fd()) {
|
||||
fmt.Println("Is Cygwin/MSYS2 Terminal")
|
||||
} else {
|
||||
fmt.Println("Is Not Terminal")
|
||||
}
|
||||
@@ -28,10 +35,16 @@ func main() {
|
||||
$ go get github.com/mattn/go-isatty
|
||||
```
|
||||
|
||||
# License
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
# Author
|
||||
## Author
|
||||
|
||||
Yasuhiro Matsumoto (a.k.a mattn)
|
||||
|
||||
## Thanks
|
||||
|
||||
* k-takata: base idea for IsCygwinTerminal
|
||||
|
||||
https://github.com/k-takata/go-iscygpty
|
||||
+6
@@ -7,3 +7,9 @@ package isatty
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
|
||||
// terminal. This is also always false on this environment.
|
||||
func IsCygwinTerminal(fd uintptr) bool {
|
||||
return false
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// +build darwin freebsd openbsd netbsd
|
||||
// +build darwin freebsd openbsd netbsd dragonfly
|
||||
// +build !appengine
|
||||
|
||||
package isatty
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// +build linux
|
||||
// +build !appengine
|
||||
// +build !appengine,!ppc64,!ppc64le
|
||||
|
||||
package isatty
|
||||
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// +build linux
|
||||
// +build ppc64 ppc64le
|
||||
|
||||
package isatty
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
syscall "golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const ioctlReadTermios = syscall.TCGETS
|
||||
|
||||
// IsTerminal return true if the file descriptor is terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
var termios syscall.Termios
|
||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
||||
return err == 0
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// +build !windows
|
||||
// +build !appengine
|
||||
|
||||
package isatty
|
||||
|
||||
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
|
||||
// terminal. This is also always false on this environment.
|
||||
func IsCygwinTerminal(fd uintptr) bool {
|
||||
return false
|
||||
}
|
||||
+77
-2
@@ -4,12 +4,30 @@
|
||||
package isatty
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
var procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
||||
const (
|
||||
fileNameInfo uintptr = 2
|
||||
fileTypePipe = 3
|
||||
)
|
||||
|
||||
var (
|
||||
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
||||
procGetFileInformationByHandleEx = kernel32.NewProc("GetFileInformationByHandleEx")
|
||||
procGetFileType = kernel32.NewProc("GetFileType")
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Check if GetFileInformationByHandleEx is available.
|
||||
if procGetFileInformationByHandleEx.Find() != nil {
|
||||
procGetFileInformationByHandleEx = nil
|
||||
}
|
||||
}
|
||||
|
||||
// IsTerminal return true if the file descriptor is terminal.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
@@ -17,3 +35,60 @@ func IsTerminal(fd uintptr) bool {
|
||||
r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0)
|
||||
return r != 0 && e == 0
|
||||
}
|
||||
|
||||
// Check pipe name is used for cygwin/msys2 pty.
|
||||
// Cygwin/MSYS2 PTY has a name like:
|
||||
// \{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master
|
||||
func isCygwinPipeName(name string) bool {
|
||||
token := strings.Split(name, "-")
|
||||
if len(token) < 5 {
|
||||
return false
|
||||
}
|
||||
|
||||
if token[0] != `\msys` && token[0] != `\cygwin` {
|
||||
return false
|
||||
}
|
||||
|
||||
if token[1] == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(token[2], "pty") {
|
||||
return false
|
||||
}
|
||||
|
||||
if token[3] != `from` && token[3] != `to` {
|
||||
return false
|
||||
}
|
||||
|
||||
if token[4] != "master" {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
|
||||
// terminal.
|
||||
func IsCygwinTerminal(fd uintptr) bool {
|
||||
if procGetFileInformationByHandleEx == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Cygwin/msys's pty is a pipe.
|
||||
ft, _, e := syscall.Syscall(procGetFileType.Addr(), 1, fd, 0, 0)
|
||||
if ft != fileTypePipe || e != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
var buf [2 + syscall.MAX_PATH]uint16
|
||||
r, _, e := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(),
|
||||
4, fd, fileNameInfo, uintptr(unsafe.Pointer(&buf)),
|
||||
uintptr(len(buf)*2), 0, 0)
|
||||
if r == 0 || e != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
l := *(*uint32)(unsafe.Pointer(&buf))
|
||||
return isCygwinPipeName(string(utf16.Decode(buf[2 : 2+l/2])))
|
||||
}
|
||||
Vendored
+10
-6
@@ -443,10 +443,10 @@
|
||||
"revisionTime": "2016-12-15T22:53:35Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "mrmfY0cVu7jvgoIuTRaR8yVVh/M=",
|
||||
"checksumSHA1": "W7WyVSrJNaQNQt2R9O4DxrK58cs=",
|
||||
"path": "github.com/inconshreveable/log15",
|
||||
"revision": "39bacc234bf1afd0b68573e95b45871f67ba2cd4",
|
||||
"revisionTime": "2017-02-16T22:56:31Z"
|
||||
"revision": "0decfc6c20d9ca0ad143b0e89dcaa20f810b4fb3",
|
||||
"revisionTime": "2016-11-12T20:41:34Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "oVIIInZXKkcRozJfuH2vWJsAS7s=",
|
||||
@@ -468,25 +468,29 @@
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "jaCQF1par6Jl8g+V2Cgp0n/0wSc=",
|
||||
"origin": "github.com/grafana/grafana/vendor/github.com/lib/pq/hstore",
|
||||
"path": "github.com/lib/pq/hstore",
|
||||
"revision": "23da1db4f16d9658a86ae9b717c245fc078f10f1",
|
||||
"revisionTime": "2017-09-18T17:50:43Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "mJHrY33tDs2MRhHt+XunkRF/5ek=",
|
||||
"origin": "github.com/grafana/grafana/vendor/github.com/lib/pq/listen_example",
|
||||
"path": "github.com/lib/pq/listen_example",
|
||||
"revision": "23da1db4f16d9658a86ae9b717c245fc078f10f1",
|
||||
"revisionTime": "2017-09-18T17:50:43Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "AU3fA8Sm33Vj9PBoRPSeYfxLRuE=",
|
||||
"origin": "github.com/grafana/grafana/vendor/github.com/lib/pq/oid",
|
||||
"path": "github.com/lib/pq/oid",
|
||||
"revision": "23da1db4f16d9658a86ae9b717c245fc078f10f1",
|
||||
"revisionTime": "2017-09-18T17:50:43Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "y/A5iuvwjytQE2CqVuphQRXR2nI=",
|
||||
"origin": "github.com/grafana/grafana/vendor/github.com/mattn/go-isatty",
|
||||
"path": "github.com/mattn/go-isatty",
|
||||
"revision": "a5cdd64afdee435007ee3e9f6ed4684af949d568",
|
||||
"revisionTime": "2017-09-25T05:49:04Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "bKMZjd2wPw13VwoE7mBeSv5djFA=",
|
||||
"path": "github.com/matttproud/golang_protobuf_extensions/pbutil",
|
||||
|
||||
Reference in new issue
Block a user