Merge branch 'master' into dashboard_folders
This commit is contained in:
+1
-1
@@ -298,7 +298,7 @@
|
||||
# Use space to separate multiple modes, e.g. "console file"
|
||||
;mode = console file
|
||||
|
||||
# Either "trace", "debug", "info", "warn", "error", "critical", default is "info"
|
||||
# Either "debug", "info", "warn", "error", "critical", default is "info"
|
||||
;level = info
|
||||
|
||||
# optional settings to set different levels for specific loggers. Ex filters = sqlstore:debug
|
||||
|
||||
@@ -4,7 +4,6 @@ graphite:
|
||||
- "8080:80"
|
||||
- "2003:2003"
|
||||
volumes:
|
||||
- /var/docker/gfdev/graphite:/opt/graphite/storage/whisper
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
|
||||
|
||||
@@ -52,6 +52,15 @@ parent = "http_api"
|
||||
"expires": 3600
|
||||
}
|
||||
|
||||
JSON Body schema:
|
||||
|
||||
- **dashboard** – Required. The complete dashboard model.
|
||||
- **name** – Optional. snapshot name
|
||||
- **expires** - Optional. When the snapshot should expire in seconds. 3600 is 1 hour, 86400 is 1 day. Default is never to expire.
|
||||
- **external** - Optional. Save the snapshot on an external server rather than locally. Default is `false`.
|
||||
- **key** - Optional. Define the unique key. Required if **external** is `true`.
|
||||
- **deleteKey** - Optional. Unique key used to delete the snapshot. It is different from the **key** so that only the creator can delete the snapshot. Required if **external** is `true`.
|
||||
|
||||
**Example Response**:
|
||||
|
||||
HTTP/1.1 200
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
///<reference path="../../headers/common.d.ts" />
|
||||
|
||||
import coreModule from 'app/core/core_module';
|
||||
|
||||
const template = `
|
||||
<div class="collapse-box">
|
||||
<div class="collapse-box__header">
|
||||
<a class="collapse-box__header-title pointer" ng-click="ctrl.toggle()">
|
||||
<span class="fa fa-fw fa-caret-right" ng-hide="ctrl.isOpen"></span>
|
||||
<span class="fa fa-fw fa-caret-down" ng-hide="!ctrl.isOpen"></span>
|
||||
{{ctrl.title}}
|
||||
</a>
|
||||
<div class="collapse-box__header-actions" ng-transclude="actions" ng-if="ctrl.isOpen"></div>
|
||||
</div>
|
||||
<div class="collapse-box__body" ng-transclude="body" ng-if="ctrl.isOpen">
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
export class CollapseBoxCtrl {
|
||||
isOpen: boolean;
|
||||
stateChanged: () => void;
|
||||
|
||||
/** @ngInject **/
|
||||
constructor(private $timeout) {
|
||||
this.isOpen = false;
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.isOpen = !this.isOpen;
|
||||
this.$timeout(() => {
|
||||
this.stateChanged();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function collapseBox() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: template,
|
||||
controller: CollapseBoxCtrl,
|
||||
bindToController: true,
|
||||
controllerAs: 'ctrl',
|
||||
scope: {
|
||||
"title": "@",
|
||||
"isOpen": "=?",
|
||||
"stateChanged": "&"
|
||||
},
|
||||
transclude: {
|
||||
'actions': '?collapseBoxActions',
|
||||
'body': 'collapseBoxBody',
|
||||
},
|
||||
link: function(scope, elem, attrs) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
coreModule.directive('collapseBox', collapseBox);
|
||||
@@ -0,0 +1,248 @@
|
||||
///<reference path="../../../headers/common.d.ts" />
|
||||
|
||||
import config from 'app/core/config';
|
||||
import _ from 'lodash';
|
||||
import $ from 'jquery';
|
||||
import coreModule from '../../core_module';
|
||||
|
||||
function typeaheadMatcher(item) {
|
||||
var str = this.query;
|
||||
if (str[0] === '/') { str = str.substring(1); }
|
||||
if (str[str.length - 1] === '/') { str = str.substring(0, str.length-1); }
|
||||
return item.toLowerCase().match(str.toLowerCase());
|
||||
}
|
||||
|
||||
export class FormDropdownCtrl {
|
||||
inputElement: any;
|
||||
linkElement: any;
|
||||
model: any;
|
||||
display: any;
|
||||
text: any;
|
||||
options: any;
|
||||
cssClass: any;
|
||||
cssClasses: any;
|
||||
allowCustom: any;
|
||||
labelMode: boolean;
|
||||
linkMode: boolean;
|
||||
cancelBlur: any;
|
||||
onChange: any;
|
||||
getOptions: any;
|
||||
optionCache: any;
|
||||
lookupText: boolean;
|
||||
|
||||
constructor(private $scope, $element, private $sce, private templateSrv, private $q) {
|
||||
this.inputElement = $element.find('input').first();
|
||||
this.linkElement = $element.find('a').first();
|
||||
this.linkMode = true;
|
||||
this.cancelBlur = null;
|
||||
|
||||
// listen to model changes
|
||||
$scope.$watch("ctrl.model", this.modelChanged.bind(this));
|
||||
|
||||
if (this.labelMode) {
|
||||
this.cssClasses = 'gf-form-label ' + this.cssClass;
|
||||
} else {
|
||||
this.cssClasses = 'gf-form-input gf-form-input--dropdown ' + this.cssClass;
|
||||
}
|
||||
|
||||
this.inputElement.attr('data-provide', 'typeahead');
|
||||
this.inputElement.typeahead({
|
||||
source: this.typeaheadSource.bind(this),
|
||||
minLength: 0,
|
||||
items: 10000,
|
||||
updater: this.typeaheadUpdater.bind(this),
|
||||
matcher: typeaheadMatcher,
|
||||
});
|
||||
|
||||
// modify typeahead lookup
|
||||
// this = typeahead
|
||||
var typeahead = this.inputElement.data('typeahead');
|
||||
typeahead.lookup = function () {
|
||||
this.query = this.$element.val() || '';
|
||||
var items = this.source(this.query, $.proxy(this.process, this));
|
||||
return items ? this.process(items) : items;
|
||||
};
|
||||
|
||||
this.linkElement.keydown(evt => {
|
||||
// trigger typeahead on down arrow or enter key
|
||||
if (evt.keyCode === 40 || evt.keyCode === 13) {
|
||||
this.linkElement.click();
|
||||
}
|
||||
});
|
||||
|
||||
this.inputElement.keydown(evt => {
|
||||
if (evt.keyCode === 13) {
|
||||
this.inputElement.blur();
|
||||
}
|
||||
});
|
||||
|
||||
this.inputElement.blur(this.inputBlur.bind(this));
|
||||
}
|
||||
|
||||
getOptionsInternal(query) {
|
||||
var result = this.getOptions({$query: query});
|
||||
if (this.isPromiseLike(result)) {
|
||||
return result;
|
||||
}
|
||||
return this.$q.when(result);
|
||||
}
|
||||
|
||||
isPromiseLike(obj) {
|
||||
return obj && (typeof obj.then === 'function');
|
||||
}
|
||||
|
||||
modelChanged() {
|
||||
if (_.isObject(this.model)) {
|
||||
this.updateDisplay(this.model.text);
|
||||
} else {
|
||||
// if we have text use it
|
||||
if (this.lookupText) {
|
||||
this.getOptionsInternal("").then(options => {
|
||||
var item = _.find(options, {value: this.model});
|
||||
this.updateDisplay(item ? item.text : this.model);
|
||||
});
|
||||
} else {
|
||||
this.updateDisplay(this.model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typeaheadSource(query, callback) {
|
||||
this.getOptionsInternal(query).then(options => {
|
||||
this.optionCache = options;
|
||||
|
||||
// extract texts
|
||||
let optionTexts = _.map(options, 'text');
|
||||
|
||||
// add custom values
|
||||
if (this.allowCustom) {
|
||||
if (_.indexOf(optionTexts, this.text) === -1) {
|
||||
options.unshift(this.text);
|
||||
}
|
||||
}
|
||||
|
||||
callback(optionTexts);
|
||||
});
|
||||
}
|
||||
|
||||
typeaheadUpdater(text) {
|
||||
if (text === this.text) {
|
||||
clearTimeout(this.cancelBlur);
|
||||
this.inputElement.focus();
|
||||
return text;
|
||||
}
|
||||
|
||||
this.inputElement.val(text);
|
||||
this.switchToLink(true);
|
||||
return text;
|
||||
}
|
||||
|
||||
switchToLink(fromClick) {
|
||||
if (this.linkMode && !fromClick) { return; }
|
||||
|
||||
clearTimeout(this.cancelBlur);
|
||||
this.cancelBlur = null;
|
||||
this.linkMode = true;
|
||||
this.inputElement.hide();
|
||||
this.linkElement.show();
|
||||
this.updateValue(this.inputElement.val());
|
||||
}
|
||||
|
||||
inputBlur() {
|
||||
// happens long before the click event on the typeahead options
|
||||
// need to have long delay because the blur
|
||||
this.cancelBlur = setTimeout(this.switchToLink.bind(this), 200);
|
||||
}
|
||||
|
||||
updateValue(text) {
|
||||
if (text === '' || this.text === text) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$scope.$apply(() => {
|
||||
var option = _.find(this.optionCache, {text: text});
|
||||
|
||||
if (option) {
|
||||
if (_.isObject(this.model)) {
|
||||
this.model = option;
|
||||
} else {
|
||||
this.model = option.value;
|
||||
}
|
||||
this.text = option.text;
|
||||
} else if (this.allowCustom) {
|
||||
if (_.isObject(this.model)) {
|
||||
this.model.text = this.model.value = text;
|
||||
} else {
|
||||
this.model = text;
|
||||
}
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
// needs to call this after digest so
|
||||
// property is synced with outerscope
|
||||
this.$scope.$$postDigest(() => {
|
||||
this.$scope.$apply(() => {
|
||||
this.onChange({$option: option});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
updateDisplay(text) {
|
||||
this.text = text;
|
||||
this.display = this.$sce.trustAsHtml(this.templateSrv.highlightVariablesAsHtml(text));
|
||||
}
|
||||
|
||||
open() {
|
||||
this.inputElement.show();
|
||||
|
||||
this.inputElement.css('width', (Math.max(this.linkElement.width(), 80) + 16) + 'px');
|
||||
this.inputElement.focus();
|
||||
|
||||
this.linkElement.hide();
|
||||
this.linkMode = false;
|
||||
|
||||
var typeahead = this.inputElement.data('typeahead');
|
||||
if (typeahead) {
|
||||
this.inputElement.val('');
|
||||
typeahead.lookup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const template = `
|
||||
<input type="text"
|
||||
data-provide="typeahead"
|
||||
class="gf-form-input"
|
||||
spellcheck="false"
|
||||
style="display:none">
|
||||
</input>
|
||||
<a ng-class="ctrl.cssClasses"
|
||||
tabindex="1"
|
||||
ng-click="ctrl.open()"
|
||||
give-focus="ctrl.focus"
|
||||
ng-bind-html="ctrl.display">
|
||||
</a>
|
||||
`;
|
||||
|
||||
export function formDropdownDirective() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: template,
|
||||
controller: FormDropdownCtrl,
|
||||
bindToController: true,
|
||||
controllerAs: 'ctrl',
|
||||
scope: {
|
||||
model: "=",
|
||||
getOptions: "&",
|
||||
onChange: "&",
|
||||
cssClass: "@",
|
||||
allowCustom: "@",
|
||||
labelMode: "@",
|
||||
lookupText: "@",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
coreModule.directive('gfFormDropdown', formDropdownDirective);
|
||||
@@ -0,0 +1,113 @@
|
||||
// Based on work https://github.com/mohsen1/json-formatter-js
|
||||
// Licence MIT, Copyright (c) 2015 Mohsen Azimi
|
||||
|
||||
/*
|
||||
* Escapes `"` charachters from string
|
||||
*/
|
||||
function escapeString(str: string): string {
|
||||
return str.replace('"', '\"');
|
||||
}
|
||||
|
||||
/*
|
||||
* Determines if a value is an object
|
||||
*/
|
||||
export function isObject(value: any): boolean {
|
||||
var type = typeof value;
|
||||
return !!value && (type === 'object');
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets constructor name of an object.
|
||||
* From http://stackoverflow.com/a/332429
|
||||
*
|
||||
*/
|
||||
export function getObjectName(object: Object): string {
|
||||
if (object === undefined) {
|
||||
return '';
|
||||
}
|
||||
if (object === null) {
|
||||
return 'Object';
|
||||
}
|
||||
if (typeof object === 'object' && !object.constructor) {
|
||||
return 'Object';
|
||||
}
|
||||
|
||||
const funcNameRegex = /function ([^(]*)/;
|
||||
const results = (funcNameRegex).exec((object).constructor.toString());
|
||||
if (results && results.length > 1) {
|
||||
return results[1];
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets type of an object. Returns "null" for null objects
|
||||
*/
|
||||
export function getType(object: Object): string {
|
||||
if (object === null) { return 'null'; }
|
||||
return typeof object;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates inline preview for a JavaScript object based on a value
|
||||
*/
|
||||
export function getValuePreview (object: Object, value: string): string {
|
||||
var type = getType(object);
|
||||
|
||||
if (type === 'null' || type === 'undefined') { return type; }
|
||||
|
||||
if (type === 'string') {
|
||||
value = '"' + escapeString(value) + '"';
|
||||
}
|
||||
if (type === 'function'){
|
||||
|
||||
// Remove content of the function
|
||||
return object.toString()
|
||||
.replace(/[\r\n]/g, '')
|
||||
.replace(/\{.*\}/, '') + '{…}';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates inline preview for a JavaScript object
|
||||
*/
|
||||
export function getPreview(object: string): string {
|
||||
let value = '';
|
||||
if (isObject(object)) {
|
||||
value = getObjectName(object);
|
||||
if (Array.isArray(object)) {
|
||||
value += '[' + object.length + ']';
|
||||
}
|
||||
} else {
|
||||
value = getValuePreview(object, object);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates a prefixed CSS class name
|
||||
*/
|
||||
export function cssClass(className: string): string {
|
||||
return `json-formatter-${className}`;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new DOM element wiht given type and class
|
||||
* TODO: move me to helpers
|
||||
*/
|
||||
export function createElement(type: string, className?: string, content?: Element|string): Element {
|
||||
const el = document.createElement(type);
|
||||
if (className) {
|
||||
el.classList.add(cssClass(className));
|
||||
}
|
||||
if (content !== undefined) {
|
||||
if (content instanceof Node) {
|
||||
el.appendChild(content);
|
||||
} else {
|
||||
el.appendChild(document.createTextNode(String(content)));
|
||||
}
|
||||
}
|
||||
return el;
|
||||
}
|
||||
@@ -0,0 +1,431 @@
|
||||
// Based on work https://github.com/mohsen1/json-formatter-js
|
||||
// Licence MIT, Copyright (c) 2015 Mohsen Azimi
|
||||
|
||||
import {
|
||||
isObject,
|
||||
getObjectName,
|
||||
getType,
|
||||
getValuePreview,
|
||||
getPreview,
|
||||
cssClass,
|
||||
createElement
|
||||
} from './helpers';
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
const DATE_STRING_REGEX = /(^\d{1,4}[\.|\\/|-]\d{1,2}[\.|\\/|-]\d{1,4})(\s*(?:0?[1-9]:[0-5]|1(?=[012])\d:[0-5])\d\s*[ap]m)?$/;
|
||||
const PARTIAL_DATE_REGEX = /\d{2}:\d{2}:\d{2} GMT-\d{4}/;
|
||||
const JSON_DATE_REGEX = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/;
|
||||
|
||||
// When toggleing, don't animated removal or addition of more than a few items
|
||||
const MAX_ANIMATED_TOGGLE_ITEMS = 10;
|
||||
|
||||
const requestAnimationFrame = window.requestAnimationFrame || function(cb: ()=>void) { cb(); return 0; };
|
||||
|
||||
export interface JsonExplorerConfig {
|
||||
animateOpen?: boolean;
|
||||
animateClose?: boolean;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
const _defaultConfig: JsonExplorerConfig = {
|
||||
animateOpen: true,
|
||||
animateClose: true,
|
||||
theme: null
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class JsonExplorer
|
||||
*
|
||||
* JsonExplorer allows you to render JSON objects in HTML with a
|
||||
* **collapsible** navigation.
|
||||
*/
|
||||
export class JsonExplorer {
|
||||
|
||||
// Hold the open state after the toggler is used
|
||||
private _isOpen: boolean = null;
|
||||
|
||||
// A reference to the element that we render to
|
||||
private element: Element;
|
||||
|
||||
private skipChildren = false;
|
||||
|
||||
/**
|
||||
* @param {object} json The JSON object you want to render. It has to be an
|
||||
* object or array. Do NOT pass raw JSON string.
|
||||
*
|
||||
* @param {number} [open=1] his number indicates up to how many levels the
|
||||
* rendered tree should expand. Set it to `0` to make the whole tree collapsed
|
||||
* or set it to `Infinity` to expand the tree deeply
|
||||
*
|
||||
* @param {object} [config=defaultConfig] -
|
||||
* defaultConfig = {
|
||||
* hoverPreviewEnabled: false,
|
||||
* hoverPreviewArrayCount: 100,
|
||||
* hoverPreviewFieldCount: 5
|
||||
* }
|
||||
*
|
||||
* Available configurations:
|
||||
* #####Hover Preview
|
||||
* * `hoverPreviewEnabled`: enable preview on hover
|
||||
* * `hoverPreviewArrayCount`: number of array items to show in preview Any
|
||||
* array larger than this number will be shown as `Array[XXX]` where `XXX`
|
||||
* is length of the array.
|
||||
* * `hoverPreviewFieldCount`: number of object properties to show for object
|
||||
* preview. Any object with more properties that thin number will be
|
||||
* truncated.
|
||||
*
|
||||
* @param {string} [key=undefined] The key that this object in it's parent
|
||||
* context
|
||||
*/
|
||||
constructor(public json: any, private open = 1, private config: JsonExplorerConfig = _defaultConfig, private key?: string) {
|
||||
}
|
||||
|
||||
/*
|
||||
* is formatter open?
|
||||
*/
|
||||
private get isOpen(): boolean {
|
||||
if (this._isOpen !== null) {
|
||||
return this._isOpen;
|
||||
} else {
|
||||
return this.open > 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* set open state (from toggler)
|
||||
*/
|
||||
private set isOpen(value: boolean) {
|
||||
this._isOpen = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* is this a date string?
|
||||
*/
|
||||
private get isDate(): boolean {
|
||||
return (this.type === 'string') &&
|
||||
(DATE_STRING_REGEX.test(this.json) ||
|
||||
JSON_DATE_REGEX.test(this.json) ||
|
||||
PARTIAL_DATE_REGEX.test(this.json));
|
||||
}
|
||||
|
||||
/*
|
||||
* is this a URL string?
|
||||
*/
|
||||
private get isUrl(): boolean {
|
||||
return this.type === 'string' && (this.json.indexOf('http') === 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* is this an array?
|
||||
*/
|
||||
private get isArray(): boolean {
|
||||
return Array.isArray(this.json);
|
||||
}
|
||||
|
||||
/*
|
||||
* is this an object?
|
||||
* Note: In this context arrays are object as well
|
||||
*/
|
||||
private get isObject(): boolean {
|
||||
return isObject(this.json);
|
||||
}
|
||||
|
||||
/*
|
||||
* is this an empty object with no properties?
|
||||
*/
|
||||
private get isEmptyObject(): boolean {
|
||||
return !this.keys.length && !this.isArray;
|
||||
}
|
||||
|
||||
/*
|
||||
* is this an empty object or array?
|
||||
*/
|
||||
private get isEmpty(): boolean {
|
||||
return this.isEmptyObject || (this.keys && !this.keys.length && this.isArray);
|
||||
}
|
||||
|
||||
/*
|
||||
* did we recieve a key argument?
|
||||
* This means that the formatter was called as a sub formatter of a parent formatter
|
||||
*/
|
||||
private get hasKey(): boolean {
|
||||
return typeof this.key !== 'undefined';
|
||||
}
|
||||
|
||||
/*
|
||||
* if this is an object, get constructor function name
|
||||
*/
|
||||
private get constructorName(): string {
|
||||
return getObjectName(this.json);
|
||||
}
|
||||
|
||||
/*
|
||||
* get type of this value
|
||||
* Possible values: all JavaScript primitive types plus "array" and "null"
|
||||
*/
|
||||
private get type(): string {
|
||||
return getType(this.json);
|
||||
}
|
||||
|
||||
/*
|
||||
* get object keys
|
||||
* If there is an empty key we pad it wit quotes to make it visible
|
||||
*/
|
||||
private get keys(): string[] {
|
||||
if (this.isObject) {
|
||||
return Object.keys(this.json).map((key)=> key ? key : '""');
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles `isOpen` state
|
||||
*
|
||||
*/
|
||||
toggleOpen() {
|
||||
this.isOpen = !this.isOpen;
|
||||
|
||||
if (this.element) {
|
||||
if (this.isOpen) {
|
||||
this.appendChildren(this.config.animateOpen);
|
||||
} else{
|
||||
this.removeChildren(this.config.animateClose);
|
||||
}
|
||||
this.element.classList.toggle(cssClass('open'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open all children up to a certain depth.
|
||||
* Allows actions such as expand all/collapse all
|
||||
*
|
||||
*/
|
||||
openAtDepth(depth = 1) {
|
||||
if (depth < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.open = depth;
|
||||
this.isOpen = (depth !== 0);
|
||||
|
||||
if (this.element) {
|
||||
this.removeChildren(false);
|
||||
|
||||
if (depth === 0) {
|
||||
this.element.classList.remove(cssClass('open'));
|
||||
} else {
|
||||
this.appendChildren(this.config.animateOpen);
|
||||
this.element.classList.add(cssClass('open'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isNumberArray() {
|
||||
return (this.json.length > 0 && this.json.length < 4) &&
|
||||
(_.isNumber(this.json[0]) || _.isNumber(this.json[1]));
|
||||
}
|
||||
|
||||
renderArray() {
|
||||
const arrayWrapperSpan = createElement('span');
|
||||
arrayWrapperSpan.appendChild(createElement('span', 'bracket', '['));
|
||||
|
||||
// some pretty handling of number arrays
|
||||
if (this.isNumberArray()) {
|
||||
this.json.forEach((val, index) => {
|
||||
if (index > 0) {
|
||||
arrayWrapperSpan.appendChild(createElement('span', 'array-comma', ','));
|
||||
}
|
||||
arrayWrapperSpan.appendChild(createElement('span', 'number', val));
|
||||
});
|
||||
this.skipChildren = true;
|
||||
} else {
|
||||
arrayWrapperSpan.appendChild(createElement('span', 'number', (this.json.length)));
|
||||
}
|
||||
|
||||
arrayWrapperSpan.appendChild(createElement('span', 'bracket', ']'));
|
||||
return arrayWrapperSpan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders an HTML element and installs event listeners
|
||||
*
|
||||
* @returns {HTMLDivElement}
|
||||
*/
|
||||
render(skipRoot = false): HTMLDivElement {
|
||||
// construct the root element and assign it to this.element
|
||||
this.element = createElement('div', 'row');
|
||||
|
||||
// construct the toggler link
|
||||
const togglerLink = createElement('a', 'toggler-link');
|
||||
const togglerIcon = createElement('span', 'toggler');
|
||||
|
||||
// if this is an object we need a wrapper span (toggler)
|
||||
if (this.isObject) {
|
||||
togglerLink.appendChild(togglerIcon);
|
||||
}
|
||||
|
||||
// if this is child of a parent formatter we need to append the key
|
||||
if (this.hasKey) {
|
||||
togglerLink.appendChild(createElement('span', 'key', `${this.key}:`));
|
||||
}
|
||||
|
||||
// Value for objects and arrays
|
||||
if (this.isObject) {
|
||||
// construct the value holder element
|
||||
const value = createElement('span', 'value');
|
||||
|
||||
// we need a wrapper span for objects
|
||||
const objectWrapperSpan = createElement('span');
|
||||
|
||||
// get constructor name and append it to wrapper span
|
||||
var constructorName = createElement('span', 'constructor-name', this.constructorName);
|
||||
objectWrapperSpan.appendChild(constructorName);
|
||||
|
||||
// if it's an array append the array specific elements like brackets and length
|
||||
if (this.isArray) {
|
||||
const arrayWrapperSpan = this.renderArray();
|
||||
objectWrapperSpan.appendChild(arrayWrapperSpan);
|
||||
}
|
||||
|
||||
// append object wrapper span to toggler link
|
||||
value.appendChild(objectWrapperSpan);
|
||||
togglerLink.appendChild(value);
|
||||
// Primitive values
|
||||
} else {
|
||||
|
||||
// make a value holder element
|
||||
const value = this.isUrl ? createElement('a') : createElement('span');
|
||||
|
||||
// add type and other type related CSS classes
|
||||
value.classList.add(cssClass(this.type));
|
||||
if (this.isDate) {
|
||||
value.classList.add(cssClass('date'));
|
||||
}
|
||||
if (this.isUrl) {
|
||||
value.classList.add(cssClass('url'));
|
||||
value.setAttribute('href', this.json);
|
||||
}
|
||||
|
||||
// Append value content to value element
|
||||
const valuePreview = getValuePreview(this.json, this.json);
|
||||
value.appendChild(document.createTextNode(valuePreview));
|
||||
|
||||
// append the value element to toggler link
|
||||
togglerLink.appendChild(value);
|
||||
}
|
||||
|
||||
// construct a children element
|
||||
const children = createElement('div', 'children');
|
||||
|
||||
// set CSS classes for children
|
||||
if (this.isObject) {
|
||||
children.classList.add(cssClass('object'));
|
||||
}
|
||||
if (this.isArray) {
|
||||
children.classList.add(cssClass('array'));
|
||||
}
|
||||
if (this.isEmpty) {
|
||||
children.classList.add(cssClass('empty'));
|
||||
}
|
||||
|
||||
// set CSS classes for root element
|
||||
if (this.config && this.config.theme) {
|
||||
this.element.classList.add(cssClass(this.config.theme));
|
||||
}
|
||||
if (this.isOpen) {
|
||||
this.element.classList.add(cssClass('open'));
|
||||
}
|
||||
|
||||
// append toggler and children elements to root element
|
||||
if (!skipRoot) {
|
||||
this.element.appendChild(togglerLink);
|
||||
}
|
||||
|
||||
if (!this.skipChildren) {
|
||||
this.element.appendChild(children);
|
||||
} else {
|
||||
// remove togglerIcon
|
||||
togglerLink.removeChild(togglerIcon);
|
||||
}
|
||||
|
||||
// if formatter is set to be open call appendChildren
|
||||
if (this.isObject && this.isOpen) {
|
||||
this.appendChildren();
|
||||
}
|
||||
|
||||
// add event listener for toggling
|
||||
if (this.isObject) {
|
||||
togglerLink.addEventListener('click', this.toggleOpen.bind(this));
|
||||
}
|
||||
|
||||
return this.element as HTMLDivElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends all the children to children element
|
||||
* Animated option is used when user triggers this via a click
|
||||
*/
|
||||
appendChildren(animated = false) {
|
||||
const children = this.element.querySelector(`div.${cssClass('children')}`);
|
||||
|
||||
if (!children || this.isEmpty) { return; }
|
||||
|
||||
if (animated) {
|
||||
let index = 0;
|
||||
const addAChild = ()=> {
|
||||
const key = this.keys[index];
|
||||
const formatter = new JsonExplorer(this.json[key], this.open - 1, this.config, key);
|
||||
children.appendChild(formatter.render());
|
||||
|
||||
index += 1;
|
||||
|
||||
if (index < this.keys.length) {
|
||||
if (index > MAX_ANIMATED_TOGGLE_ITEMS) {
|
||||
addAChild();
|
||||
} else {
|
||||
requestAnimationFrame(addAChild);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
requestAnimationFrame(addAChild);
|
||||
|
||||
} else {
|
||||
this.keys.forEach(key => {
|
||||
const formatter = new JsonExplorer(this.json[key], this.open - 1, this.config, key);
|
||||
children.appendChild(formatter.render());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all the children from children element
|
||||
* Animated option is used when user triggers this via a click
|
||||
*/
|
||||
removeChildren(animated = false) {
|
||||
const childrenElement = this.element.querySelector(`div.${cssClass('children')}`) as HTMLDivElement;
|
||||
|
||||
if (animated) {
|
||||
let childrenRemoved = 0;
|
||||
const removeAChild = ()=> {
|
||||
if (childrenElement && childrenElement.children.length) {
|
||||
childrenElement.removeChild(childrenElement.children[0]);
|
||||
childrenRemoved += 1;
|
||||
if (childrenRemoved > MAX_ANIMATED_TOGGLE_ITEMS) {
|
||||
removeAChild();
|
||||
} else {
|
||||
requestAnimationFrame(removeAChild);
|
||||
}
|
||||
}
|
||||
};
|
||||
requestAnimationFrame(removeAChild);
|
||||
} else {
|
||||
if (childrenElement) {
|
||||
childrenElement.innerHTML = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,7 @@ import {switchDirective} from './components/switch';
|
||||
import {dashboardSelector} from './components/dashboard_selector';
|
||||
import {queryPartEditorDirective} from './components/query_part/query_part_editor';
|
||||
import {WizardFlow} from './components/wizard/wizard';
|
||||
import {formDropdownDirective} from './components/form_dropdown/form_dropdown';
|
||||
import 'app/core/controllers/all';
|
||||
import 'app/core/services/all';
|
||||
import 'app/core/routes/routes';
|
||||
@@ -45,6 +46,8 @@ import {assignModelProperties} from './utils/model_utils';
|
||||
import {contextSrv} from './services/context_srv';
|
||||
import {KeybindingSrv} from './services/keybindingSrv';
|
||||
import {helpModal} from './components/help/help';
|
||||
import {collapseBox} from './components/collapse_box';
|
||||
import {JsonExplorer} from './components/json_explorer/json_explorer';
|
||||
import {NavModelSrv, NavModel} from './nav_model_srv';
|
||||
import {userPicker} from './components/user_picker';
|
||||
import {userGroupPicker} from './components/user_group_picker';
|
||||
@@ -67,10 +70,13 @@ export {
|
||||
queryPartEditorDirective,
|
||||
WizardFlow,
|
||||
colors,
|
||||
formDropdownDirective,
|
||||
assignModelProperties,
|
||||
contextSrv,
|
||||
KeybindingSrv,
|
||||
helpModal,
|
||||
collapseBox,
|
||||
JsonExplorer,
|
||||
NavModelSrv,
|
||||
NavModel,
|
||||
userPicker,
|
||||
|
||||
@@ -35,7 +35,7 @@ function ($, angular, coreModule) {
|
||||
options.html = editViewMap[options.editview].html;
|
||||
}
|
||||
|
||||
if (lastEditView === options.editview) {
|
||||
if (lastEditView && lastEditView === options.editview) {
|
||||
hideEditorPane(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
define([
|
||||
'angular',
|
||||
'require',
|
||||
'../core_module',
|
||||
'app/core/utils/kbn',
|
||||
],
|
||||
function (angular, coreModule, kbn) {
|
||||
function (angular, require, coreModule, kbn) {
|
||||
'use strict';
|
||||
|
||||
coreModule.default.directive('tip', function($compile) {
|
||||
@@ -18,6 +19,29 @@ function (angular, coreModule, kbn) {
|
||||
};
|
||||
});
|
||||
|
||||
coreModule.default.directive('clipboardButton', function() {
|
||||
return {
|
||||
scope: {
|
||||
getText: '&clipboardButton'
|
||||
},
|
||||
link: function(scope, elem) {
|
||||
require(['vendor/clipboard/dist/clipboard'], function(Clipboard) {
|
||||
scope.clipboard = new Clipboard(elem[0], {
|
||||
text: function() {
|
||||
return scope.getText();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
if (scope.clipboard) {
|
||||
scope.clipboard.destroy();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
coreModule.default.directive('compile', function($compile) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
@@ -77,10 +101,10 @@ function (angular, coreModule, kbn) {
|
||||
text + tip + '</label>';
|
||||
|
||||
var template =
|
||||
'<input class="cr1" id="' + scope.$id + model + '" type="checkbox" ' +
|
||||
' ng-model="' + model + '"' + ngchange +
|
||||
' ng-checked="' + model + '"></input>' +
|
||||
' <label for="' + scope.$id + model + '" class="cr1"></label>';
|
||||
'<input class="cr1" id="' + scope.$id + model + '" type="checkbox" ' +
|
||||
' ng-model="' + model + '"' + ngchange +
|
||||
' ng-checked="' + model + '"></input>' +
|
||||
' <label for="' + scope.$id + model + '" class="cr1"></label>';
|
||||
|
||||
template = template + label;
|
||||
elem.addClass('gf-form-checkbox');
|
||||
@@ -105,7 +129,7 @@ function (angular, coreModule, kbn) {
|
||||
var li = '<li' + (item.submenu && item.submenu.length ? ' class="dropdown-submenu"' : '') + '>' +
|
||||
'<a tabindex="-1" ng-href="' + (item.href || '') + '"' + (item.click ? ' ng-click="' + item.click + '"' : '') +
|
||||
(item.target ? ' target="' + item.target + '"' : '') + (item.method ? ' data-method="' + item.method + '"' : '') +
|
||||
'>' + (item.text || '') + '</a>';
|
||||
'>' + (item.text || '') + '</a>';
|
||||
|
||||
if (item.submenu && item.submenu.length) {
|
||||
li += buildTemplate(item.submenu).join('\n');
|
||||
|
||||
@@ -109,7 +109,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $
|
||||
baseUrl: ds.meta.baseUrl,
|
||||
name: 'query-ctrl-' + ds.meta.id,
|
||||
bindings: {target: "=", panelCtrl: "=", datasource: "="},
|
||||
attrs: {"target": "target", "panel-ctrl": "ctrl", datasource: "datasource"},
|
||||
attrs: {"target": "target", "panel-ctrl": "ctrl.panelCtrl", datasource: "datasource"},
|
||||
Component: dsModule.QueryCtrl
|
||||
};
|
||||
});
|
||||
@@ -127,7 +127,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $
|
||||
baseUrl: ds.meta.baseUrl,
|
||||
name: 'query-options-ctrl-' + ds.meta.id,
|
||||
bindings: {panelCtrl: "="},
|
||||
attrs: {"panel-ctrl": "ctrl"},
|
||||
attrs: {"panel-ctrl": "ctrl.panelCtrl"},
|
||||
Component: dsModule.QueryOptionsCtrl
|
||||
};
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
import config from 'app/core/config';
|
||||
import coreModule from 'app/core/core_module';
|
||||
import appEvents from 'app/core/app_events';
|
||||
|
||||
export class BackendSrv {
|
||||
inFlightRequests = {};
|
||||
@@ -150,7 +151,10 @@ export class BackendSrv {
|
||||
}
|
||||
}
|
||||
|
||||
return this.$http(options).catch(err => {
|
||||
return this.$http(options).then(response => {
|
||||
appEvents.emit('ds-request-response', response);
|
||||
return response;
|
||||
}).catch(err => {
|
||||
if (err.status === this.HTTP_REQUEST_CANCELLED) {
|
||||
throw {err, cancelled: true};
|
||||
}
|
||||
@@ -166,7 +170,7 @@ export class BackendSrv {
|
||||
});
|
||||
}
|
||||
|
||||
//populate error obj on Internal Error
|
||||
// populate error obj on Internal Error
|
||||
if (_.isString(err.data) && err.status === 500) {
|
||||
err.data = {
|
||||
error: err.statusText,
|
||||
@@ -179,7 +183,9 @@ export class BackendSrv {
|
||||
err.data.message = err.data.error;
|
||||
}
|
||||
|
||||
appEvents.emit('ds-request-error', err);
|
||||
throw err;
|
||||
|
||||
}).finally(() => {
|
||||
// clean up
|
||||
if (options.requestId) {
|
||||
|
||||
@@ -103,7 +103,7 @@ export class DashboardExporter {
|
||||
templateizeDatasourceUsage(variable);
|
||||
variable.options = [];
|
||||
variable.current = {};
|
||||
variable.refresh = 1;
|
||||
variable.refresh = variable.refresh > 0 ? variable.refresh : 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ export class HistoryListCtrl {
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private $scope,
|
||||
private $route,
|
||||
private $rootScope,
|
||||
private $location,
|
||||
private $window,
|
||||
@@ -179,6 +180,7 @@ export class HistoryListCtrl {
|
||||
this.loading = true;
|
||||
return this.historySrv.restoreDashboard(this.dashboard, version).then(response => {
|
||||
this.$location.path('dashboard/db/' + response.slug);
|
||||
this.$route.reload();
|
||||
this.$rootScope.appEvent('alert-success', ['Dashboard restored', 'Restored from version ' + version]);
|
||||
}).catch(() => {
|
||||
this.mode = 'list';
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
<input type="text" data-share-panel-url class="gf-form-input" ng-model="shareUrl"></input>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<button class="btn btn-inverse" data-clipboard-text="{{shareUrl}}" clipboard-button><i class="fa fa-clipboard"></i> Copy</button>
|
||||
<button class="btn btn-inverse" clipboard-button="getShareUrl()"><i class="fa fa-clipboard"></i> Copy</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -143,7 +143,7 @@
|
||||
{{snapshotUrl}}
|
||||
</a>
|
||||
<br>
|
||||
<button class="btn btn-inverse" data-clipboard-text="{{snapshotUrl}}" clipboard-button><i class="fa fa-clipboard"></i> Copy Link</button>
|
||||
<button class="btn btn-inverse" clipboard-button="getSnapshotUrl()"><i class="fa fa-clipboard"></i> Copy Link</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,10 +2,9 @@ define(['angular',
|
||||
'lodash',
|
||||
'jquery',
|
||||
'moment',
|
||||
'require',
|
||||
'app/core/config',
|
||||
],
|
||||
function (angular, _, $, moment, require, config) {
|
||||
function (angular, _, $, moment, config) {
|
||||
'use strict';
|
||||
|
||||
var module = angular.module('grafana.controllers');
|
||||
@@ -89,20 +88,10 @@ function (angular, _, $, moment, require, config) {
|
||||
$scope.imageUrl += '&tz=UTC' + encodeURIComponent(moment().format("Z"));
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
module.directive('clipboardButton',function() {
|
||||
return function(scope, elem) {
|
||||
require(['vendor/clipboard/dist/clipboard'], function(Clipboard) {
|
||||
scope.clipboard = new Clipboard(elem[0]);
|
||||
});
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
if (scope.clipboard) {
|
||||
scope.clipboard.destroy();
|
||||
}
|
||||
});
|
||||
$scope.getShareUrl = function() {
|
||||
return $scope.shareUrl;
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -96,6 +96,10 @@ function (angular, _) {
|
||||
});
|
||||
};
|
||||
|
||||
$scope.getSnapshotUrl = function() {
|
||||
return $scope.snapshotUrl;
|
||||
};
|
||||
|
||||
$scope.scrubDashboard = function(dash) {
|
||||
// change title
|
||||
dash.title = $scope.snapshot.name;
|
||||
|
||||
@@ -5,5 +5,5 @@ define([
|
||||
'./query_ctrl',
|
||||
'./panel_editor_tab',
|
||||
'./query_editor_row',
|
||||
'./metrics_ds_selector',
|
||||
'./query_troubleshooter',
|
||||
], function () {});
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
///<reference path="../../headers/common.d.ts" />
|
||||
|
||||
import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
|
||||
var module = angular.module('grafana.directives');
|
||||
|
||||
var template = `
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label">
|
||||
<i class="icon-gf icon-gf-datasources"></i>
|
||||
</label>
|
||||
<label class="gf-form-label">
|
||||
Data Source
|
||||
</label>
|
||||
|
||||
<metric-segment segment="ctrl.dsSegment"
|
||||
get-options="ctrl.getOptions(true)"
|
||||
on-change="ctrl.datasourceChanged()"></metric-segment>
|
||||
</div>
|
||||
|
||||
<div class="gf-form gf-form--offset-1">
|
||||
<button class="btn btn-secondary gf-form-btn" ng-click="ctrl.addDataQuery()" ng-hide="ctrl.current.meta.mixed">
|
||||
<i class="fa fa-plus"></i>
|
||||
Add query
|
||||
</button>
|
||||
|
||||
<div class="dropdown" ng-if="ctrl.current.meta.mixed">
|
||||
<metric-segment segment="ctrl.mixedDsSegment"
|
||||
get-options="ctrl.getOptions(false)"
|
||||
on-change="ctrl.mixedDatasourceChanged()"></metric-segment>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
||||
export class MetricsDsSelectorCtrl {
|
||||
dsSegment: any;
|
||||
mixedDsSegment: any;
|
||||
dsName: string;
|
||||
panelCtrl: any;
|
||||
datasources: any[];
|
||||
current: any;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private uiSegmentSrv, datasourceSrv) {
|
||||
this.datasources = datasourceSrv.getMetricSources();
|
||||
|
||||
var dsValue = this.panelCtrl.panel.datasource || null;
|
||||
|
||||
for (let ds of this.datasources) {
|
||||
if (ds.value === dsValue) {
|
||||
this.current = ds;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.current) {
|
||||
this.current = {name: dsValue + ' not found', value: null};
|
||||
}
|
||||
|
||||
this.dsSegment = uiSegmentSrv.newSegment({value: this.current.name, selectMode: true});
|
||||
this.mixedDsSegment = uiSegmentSrv.newSegment({value: 'Add query', selectMode: true});
|
||||
}
|
||||
|
||||
getOptions(includeBuiltin) {
|
||||
return Promise.resolve(this.datasources.filter(value => {
|
||||
return includeBuiltin || !value.meta.builtIn;
|
||||
}).map(value => {
|
||||
return this.uiSegmentSrv.newSegment(value.name);
|
||||
}));
|
||||
}
|
||||
|
||||
datasourceChanged() {
|
||||
var ds = _.find(this.datasources, {name: this.dsSegment.value});
|
||||
if (ds) {
|
||||
this.current = ds;
|
||||
this.panelCtrl.setDatasource(ds);
|
||||
}
|
||||
}
|
||||
|
||||
mixedDatasourceChanged() {
|
||||
var target: any = {isNew: true};
|
||||
var ds = _.find(this.datasources, {name: this.mixedDsSegment.value});
|
||||
if (ds) {
|
||||
target.datasource = ds.name;
|
||||
this.panelCtrl.panel.targets.push(target);
|
||||
this.mixedDsSegment.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
addDataQuery() {
|
||||
var target: any = {isNew: true};
|
||||
this.panelCtrl.panel.targets.push(target);
|
||||
}
|
||||
}
|
||||
|
||||
module.directive('metricsDsSelector', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: template,
|
||||
controller: MetricsDsSelectorCtrl,
|
||||
bindToController: true,
|
||||
controllerAs: 'ctrl',
|
||||
transclude: true,
|
||||
scope: {
|
||||
panelCtrl: "="
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
///<reference path="../../headers/common.d.ts" />
|
||||
|
||||
import angular from 'angular';
|
||||
import config from 'app/core/config';
|
||||
import $ from 'jquery';
|
||||
import _ from 'lodash';
|
||||
@@ -10,6 +11,7 @@ import * as rangeUtil from 'app/core/utils/rangeutil';
|
||||
import * as dateMath from 'app/core/utils/datemath';
|
||||
|
||||
import {Subject} from 'vendor/npm/rxjs/Subject';
|
||||
import {metricsTabDirective} from './metrics_tab';
|
||||
|
||||
class MetricsPanelCtrl extends PanelCtrl {
|
||||
scope: any;
|
||||
@@ -32,6 +34,7 @@ class MetricsPanelCtrl extends PanelCtrl {
|
||||
dataStream: any;
|
||||
dataSubscription: any;
|
||||
dataList: any;
|
||||
nextRefId: string;
|
||||
|
||||
constructor($scope, $injector) {
|
||||
super($scope, $injector);
|
||||
@@ -61,7 +64,7 @@ class MetricsPanelCtrl extends PanelCtrl {
|
||||
}
|
||||
|
||||
private onInitMetricsPanelEditMode() {
|
||||
this.addEditorTab('Metrics', 'public/app/partials/metrics.html');
|
||||
this.addEditorTab('Metrics', metricsTabDirective);
|
||||
this.addEditorTab('Time range', 'public/app/features/panel/partials/panelTime.html');
|
||||
}
|
||||
|
||||
@@ -256,7 +259,7 @@ class MetricsPanelCtrl extends PanelCtrl {
|
||||
result = {data: []};
|
||||
}
|
||||
|
||||
return this.events.emit('data-received', result.data);
|
||||
this.events.emit('data-received', result.data);
|
||||
}
|
||||
|
||||
handleDataStream(stream) {
|
||||
@@ -306,6 +309,25 @@ class MetricsPanelCtrl extends PanelCtrl {
|
||||
this.datasource = null;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
addQuery(target) {
|
||||
target.refId = this.dashboard.getNextQueryLetter(this.panel);
|
||||
|
||||
this.panel.targets.push(target);
|
||||
this.nextRefId = this.dashboard.getNextQueryLetter(this.panel);
|
||||
}
|
||||
|
||||
removeQuery(target) {
|
||||
var index = _.indexOf(this.panel.targets, target);
|
||||
this.panel.targets.splice(index, 1);
|
||||
this.nextRefId = this.dashboard.getNextQueryLetter(this.panel);
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
moveQuery(target, direction) {
|
||||
var index = _.indexOf(this.panel.targets, target);
|
||||
_.move(this.panel.targets, index, index + direction);
|
||||
}
|
||||
}
|
||||
|
||||
export {MetricsPanelCtrl};
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
///<reference path="../../headers/common.d.ts" />
|
||||
|
||||
import _ from 'lodash';
|
||||
//import {coreModule} from 'app/core/core';
|
||||
import {DashboardModel} from '../dashboard/model';
|
||||
|
||||
export class MetricsTabCtrl {
|
||||
dsName: string;
|
||||
panel: any;
|
||||
panelCtrl: any;
|
||||
datasources: any[];
|
||||
current: any;
|
||||
nextRefId: string;
|
||||
dashboard: DashboardModel;
|
||||
panelDsValue: any;
|
||||
addQueryDropdown: any;
|
||||
|
||||
/** @ngInject */
|
||||
constructor($scope, private uiSegmentSrv, private datasourceSrv) {
|
||||
this.panelCtrl = $scope.ctrl;
|
||||
$scope.ctrl = this;
|
||||
|
||||
this.panel = this.panelCtrl.panel;
|
||||
this.dashboard = this.panelCtrl.dashboard;
|
||||
this.datasources = datasourceSrv.getMetricSources();
|
||||
this.panelDsValue = this.panelCtrl.panel.datasource || null;
|
||||
|
||||
for (let ds of this.datasources) {
|
||||
if (ds.value === this.panelDsValue) {
|
||||
this.current = ds;
|
||||
}
|
||||
}
|
||||
|
||||
this.addQueryDropdown = {text: 'Add Query', value: null, fake: true};
|
||||
|
||||
// update next ref id
|
||||
this.panelCtrl.nextRefId = this.dashboard.getNextQueryLetter(this.panel);
|
||||
}
|
||||
|
||||
getOptions(includeBuiltin) {
|
||||
return Promise.resolve(this.datasources.filter(value => {
|
||||
return includeBuiltin || !value.meta.builtIn;
|
||||
}).map(ds => {
|
||||
return {value: ds.value, text: ds.name, datasource: ds};
|
||||
}));
|
||||
}
|
||||
|
||||
datasourceChanged(option) {
|
||||
if (!option) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.current = option.datasource;
|
||||
this.panelCtrl.setDatasource(option.datasource);
|
||||
}
|
||||
|
||||
addMixedQuery(option) {
|
||||
if (!option) {
|
||||
return;
|
||||
}
|
||||
|
||||
var target: any = {isNew: true};
|
||||
this.panelCtrl.addQuery({isNew: true, datasource: option.datasource.name});
|
||||
this.addQueryDropdown = {text: 'Add Query', value: null, fake: true};
|
||||
}
|
||||
|
||||
addQuery() {
|
||||
this.panelCtrl.addQuery({isNew: true});
|
||||
}
|
||||
}
|
||||
|
||||
/** @ngInject **/
|
||||
export function metricsTabDirective() {
|
||||
'use strict';
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: true,
|
||||
templateUrl: 'public/app/features/panel/partials/metrics_tab.html',
|
||||
controller: MetricsTabCtrl,
|
||||
};
|
||||
}
|
||||
|
||||
//coreModule.directive('metricsTab', metricsTabDirective);
|
||||
@@ -75,7 +75,7 @@ export class PanelCtrl {
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.events.emit('refresh', null);
|
||||
this.events.emit('refresh', null);
|
||||
}
|
||||
|
||||
publishAppEvent(evtName, evt) {
|
||||
|
||||
@@ -16,10 +16,15 @@ function panelEditorTab(dynamicDirectiveSrv) {
|
||||
directive: scope => {
|
||||
var pluginId = scope.ctrl.pluginId;
|
||||
var tabIndex = scope.index;
|
||||
// create a wrapper for directiveFn
|
||||
// required for metrics tab directive
|
||||
// that is the same for many panels but
|
||||
// given different names in this function
|
||||
var fn = () => scope.editorTab.directiveFn();
|
||||
|
||||
return Promise.resolve({
|
||||
name: `panel-editor-tab-${pluginId}${tabIndex}`,
|
||||
fn: scope.editorTab.directiveFn,
|
||||
fn: fn,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<div class="query-editor-rows gf-form-group">
|
||||
<div ng-repeat="target in ctrl.panel.targets" ng-class="{'gf-form-disabled': target.hide}">
|
||||
<rebuild-on-change property="ctrl.panel.datasource || target.datasource" show-null="true">
|
||||
<plugin-component type="query-ctrl">
|
||||
</plugin-component>
|
||||
</rebuild-on-change>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-query">
|
||||
<div class="gf-form gf-form-query-letter-cell">
|
||||
<label class="gf-form-label">
|
||||
<span class="gf-form-query-letter-cell-carret">
|
||||
<i class="fa fa-caret-down"></i>
|
||||
</span>
|
||||
<span class="gf-form-query-letter-cell-letter">{{ctrl.panelCtrl.nextRefId}}</span>
|
||||
</label>
|
||||
<button class="btn btn-secondary gf-form-btn" ng-click="ctrl.addQuery()" ng-hide="ctrl.current.meta.mixed">
|
||||
Add Query
|
||||
</button>
|
||||
|
||||
<div class="dropdown" ng-if="ctrl.current.meta.mixed">
|
||||
<gf-form-dropdown model="ctrl.addQueryDropdown"
|
||||
get-options="ctrl.getOptions(false)"
|
||||
on-change="ctrl.addMixedQuery($option)">
|
||||
</gf-form-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <query-troubleshooter panel-ctrl="ctrl.panelCtrl"></query-troubleshooter> -->
|
||||
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label">Panel Data Source</label>
|
||||
<gf-form-dropdown model="ctrl.panelDsValue"
|
||||
lookup-text="true"
|
||||
get-options="ctrl.getOptions(true)"
|
||||
on-change="ctrl.datasourceChanged($option)">
|
||||
</gf-form-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<rebuild-on-change property="ctrl.panel.datasource" show-null="true">
|
||||
<plugin-component type="query-options-ctrl">
|
||||
</plugin-component>
|
||||
</rebuild-on-change>
|
||||
</div>
|
||||
@@ -21,7 +21,7 @@ export class QueryRowCtrl {
|
||||
this.panel = this.panelCtrl.panel;
|
||||
|
||||
if (!this.target.refId) {
|
||||
this.target.refId = this.getNextQueryLetter();
|
||||
this.target.refId = this.panelCtrl.dashboard.getNextQueryLetter(this.panel);
|
||||
}
|
||||
|
||||
this.toggleCollapse(true);
|
||||
@@ -40,16 +40,6 @@ export class QueryRowCtrl {
|
||||
this.panelCtrl.refresh();
|
||||
}
|
||||
|
||||
getNextQueryLetter() {
|
||||
var letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
|
||||
return _.find(letters, refId => {
|
||||
return _.every(this.panel.targets, function(other) {
|
||||
return other.refId !== refId;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
toggleCollapse(init) {
|
||||
if (!this.canCollapse) {
|
||||
return;
|
||||
@@ -87,19 +77,16 @@ export class QueryRowCtrl {
|
||||
delete this.panelCtrl.__collapsedQueryCache[this.target.refId];
|
||||
}
|
||||
|
||||
this.panel.targets = _.without(this.panel.targets, this.target);
|
||||
this.panelCtrl.refresh();
|
||||
this.panelCtrl.removeQuery(this.target);
|
||||
}
|
||||
|
||||
duplicateQuery() {
|
||||
var clone = angular.copy(this.target);
|
||||
clone.refId = this.getNextQueryLetter();
|
||||
this.panel.targets.push(clone);
|
||||
this.panelCtrl.addQuery(clone);
|
||||
}
|
||||
|
||||
moveQuery(direction) {
|
||||
var index = _.indexOf(this.panel.targets, this.target);
|
||||
_.move(this.panel.targets, index, index + direction);
|
||||
this.panelCtrl.moveQuery(this.target, direction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
///<reference path="../../headers/common.d.ts" />
|
||||
|
||||
import _ from 'lodash';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import {coreModule, JsonExplorer} from 'app/core/core';
|
||||
|
||||
const template = `
|
||||
<collapse-box title="Query Troubleshooter" is-open="ctrl.isOpen" state-changed="ctrl.stateChanged()"
|
||||
ng-class="{'collapse-box--error': ctrl.hasError}">
|
||||
<collapse-box-actions>
|
||||
<a class="pointer" ng-click="ctrl.toggleExpand()" ng-hide="ctrl.allNodesExpanded">
|
||||
<i class="fa fa-plus-square-o"></i> Expand All
|
||||
</a>
|
||||
<a class="pointer" ng-click="ctrl.toggleExpand()" ng-show="ctrl.allNodesExpanded">
|
||||
<i class="fa fa-minus-square-o"></i> Collapse All
|
||||
</a>
|
||||
<a class="pointer" clipboard-button="ctrl.getClipboardText()"><i class="fa fa-clipboard"></i> Copy to Clipboard</a>
|
||||
</collapse-box-actions>
|
||||
<collapse-box-body>
|
||||
<i class="fa fa-spinner fa-spin" ng-show="ctrl.isLoading"></i>
|
||||
<div class="query-troubleshooter-json"></div>
|
||||
</collapse-box-body>
|
||||
</collapse-box>
|
||||
`;
|
||||
|
||||
export class QueryTroubleshooterCtrl {
|
||||
isOpen: any;
|
||||
isLoading: boolean;
|
||||
showResponse: boolean;
|
||||
panelCtrl: any;
|
||||
renderJsonExplorer: (data) => void;
|
||||
onRequestErrorEventListener: any;
|
||||
onRequestResponseEventListener: any;
|
||||
hasError: boolean;
|
||||
allNodesExpanded: boolean;
|
||||
jsonExplorer: JsonExplorer;
|
||||
|
||||
/** @ngInject **/
|
||||
constructor($scope, private $timeout) {
|
||||
this.onRequestErrorEventListener = this.onRequestError.bind(this);
|
||||
this.onRequestResponseEventListener = this.onRequestResponse.bind(this);
|
||||
|
||||
appEvents.on('ds-request-response', this.onRequestResponseEventListener);
|
||||
appEvents.on('ds-request-error', this.onRequestErrorEventListener);
|
||||
$scope.$on('$destroy', this.removeEventsListeners.bind(this));
|
||||
}
|
||||
|
||||
removeEventsListeners() {
|
||||
appEvents.off('ds-request-response', this.onRequestResponseEventListener);
|
||||
appEvents.off('ds-request-error', this.onRequestErrorEventListener);
|
||||
}
|
||||
|
||||
onRequestError(err) {
|
||||
this.isOpen = true;
|
||||
this.hasError = true;
|
||||
this.onRequestResponse(err);
|
||||
}
|
||||
|
||||
stateChanged() {
|
||||
if (this.isOpen) {
|
||||
this.panelCtrl.refresh();
|
||||
this.isLoading = true;
|
||||
}
|
||||
}
|
||||
|
||||
getClipboardText() {
|
||||
if (this.jsonExplorer) {
|
||||
return JSON.stringify(this.jsonExplorer.json, null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
onRequestResponse(data) {
|
||||
// ignore if closed
|
||||
if (!this.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
data = _.cloneDeep(data);
|
||||
|
||||
if (data.headers) {
|
||||
delete data.headers;
|
||||
}
|
||||
|
||||
if (data.config) {
|
||||
data.request = data.config;
|
||||
delete data.config;
|
||||
delete data.request.transformRequest;
|
||||
delete data.request.transformResponse;
|
||||
delete data.request.paramSerializer;
|
||||
delete data.request.jsonpCallbackParam;
|
||||
delete data.request.headers;
|
||||
delete data.request.requestId;
|
||||
delete data.request.inspect;
|
||||
delete data.request.retry;
|
||||
delete data.request.timeout;
|
||||
}
|
||||
|
||||
if (data.data) {
|
||||
data.response = data.data;
|
||||
|
||||
if (data.status === 200) {
|
||||
// if we are in error state, assume we automatically opened
|
||||
// and auto close it again
|
||||
if (this.hasError) {
|
||||
this.hasError = false;
|
||||
this.isOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
delete data.data;
|
||||
delete data.status;
|
||||
delete data.statusText;
|
||||
delete data.$$config;
|
||||
}
|
||||
|
||||
this.$timeout(_.partial(this.renderJsonExplorer, data));
|
||||
}
|
||||
|
||||
toggleExpand(depth) {
|
||||
if (this.jsonExplorer) {
|
||||
this.allNodesExpanded = !this.allNodesExpanded;
|
||||
this.jsonExplorer.openAtDepth(this.allNodesExpanded ? 20 : 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function queryTroubleshooter() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: template,
|
||||
controller: QueryTroubleshooterCtrl,
|
||||
bindToController: true,
|
||||
controllerAs: 'ctrl',
|
||||
scope: {
|
||||
panelCtrl: "="
|
||||
},
|
||||
link: function(scope, elem, attrs, ctrl) {
|
||||
|
||||
ctrl.renderJsonExplorer = function(data) {
|
||||
var jsonElem = elem.find('.query-troubleshooter-json');
|
||||
|
||||
ctrl.jsonExplorer = new JsonExplorer(data, 3, {
|
||||
animateOpen: true,
|
||||
});
|
||||
|
||||
const html = ctrl.jsonExplorer.render(true);
|
||||
jsonElem.html(html);
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
coreModule.directive('queryTroubleshooter', queryTroubleshooter);
|
||||
Vendored
-1
@@ -72,4 +72,3 @@ declare module 'd3' {
|
||||
var d3: any;
|
||||
export default d3;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
GitHub
|
||||
</a>
|
||||
<a class="btn btn-large btn-grafana-com" href="login/grafana_com" target="_self" ng-if="oauth.grafana_com">
|
||||
<img src="public/img/grafana_icon.svg"></img>
|
||||
<img src="public/img/grafana_com_auth_icon.svg"></img>
|
||||
<span>Grafana.com</span>
|
||||
</a>
|
||||
<a class="btn btn-large btn-generic-oauth" href="login/generic_oauth" target="_self" ng-if="oauth.generic_oauth">
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
|
||||
<div class="query-editor-rows gf-form-group">
|
||||
<div ng-repeat="target in ctrl.panel.targets" ng-class="{'gf-form-disabled': target.hide}">
|
||||
<rebuild-on-change property="ctrl.panel.datasource || target.datasource" show-null="true">
|
||||
<plugin-component type="query-ctrl">
|
||||
</plugin-component>
|
||||
</rebuild-on-change>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<metrics-ds-selector panel-ctrl="ctrl"></metrics-ds-selector>
|
||||
|
||||
<div class="gf-form-group">
|
||||
<rebuild-on-change property="ctrl.panel.datasource" show-null="true">
|
||||
<plugin-component type="query-options-ctrl">
|
||||
</plugin-component>
|
||||
</rebuild-on-change>
|
||||
</div>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
@@ -26,13 +26,21 @@ function (angular, _, queryDef) {
|
||||
var bucketAggs = $scope.target.bucketAggs;
|
||||
|
||||
$scope.orderByOptions = [];
|
||||
$scope.bucketAggTypes = queryDef.bucketAggTypes;
|
||||
$scope.orderOptions = queryDef.orderOptions;
|
||||
$scope.sizeOptions = queryDef.sizeOptions;
|
||||
|
||||
$scope.getBucketAggTypes = function() {
|
||||
return queryDef.bucketAggTypes;
|
||||
};
|
||||
|
||||
$scope.getOrderOptions = function() {
|
||||
return queryDef.orderOptions;
|
||||
};
|
||||
|
||||
$scope.getSizeOptions = function() {
|
||||
return queryDef.sizeOptions;
|
||||
};
|
||||
|
||||
$rootScope.onAppEvent('elastic-query-updated', function() {
|
||||
$scope.validateModel();
|
||||
$scope.updateOrderByOptions();
|
||||
}, $scope);
|
||||
|
||||
$scope.init = function() {
|
||||
@@ -166,11 +174,10 @@ function (angular, _, queryDef) {
|
||||
|
||||
$scope.toggleOptions = function() {
|
||||
$scope.showOptions = !$scope.showOptions;
|
||||
$scope.updateOrderByOptions();
|
||||
};
|
||||
|
||||
$scope.updateOrderByOptions = function() {
|
||||
$scope.orderByOptions = queryDef.getOrderByOptions($scope.target);
|
||||
$scope.getOrderByOptions = function() {
|
||||
return queryDef.getOrderByOptions($scope.target);
|
||||
};
|
||||
|
||||
$scope.getFieldsInternal = function() {
|
||||
|
||||
@@ -5,8 +5,22 @@
|
||||
<span ng-hide="isFirst">Then by</span>
|
||||
</label>
|
||||
|
||||
<metric-segment-model property="agg.type" options="bucketAggTypes" on-change="onTypeChanged()" custom="false" css-class="width-10"></metric-segment-model>
|
||||
<metric-segment-model ng-if="agg.field" property="agg.field" get-options="getFieldsInternal()" on-change="onChange()" css-class="width-12"></metric-segment-model>
|
||||
<gf-form-dropdown model="agg.type"
|
||||
lookup-text="true"
|
||||
get-options="getBucketAggTypes()"
|
||||
on-change="onTypeChanged()"
|
||||
allow-custom="false"
|
||||
label-mode="true"
|
||||
css-class="width-10">
|
||||
</gf-form-dropdown>
|
||||
<gf-form-dropdown ng-if="agg.field"
|
||||
model="agg.field"
|
||||
get-options="getFieldsInternal()"
|
||||
on-change="onChange()"
|
||||
allow-custom="false"
|
||||
label-mode="true"
|
||||
css-class="width-12">
|
||||
</gf-form-dropdown>
|
||||
</div>
|
||||
|
||||
<div class="gf-form gf-form--grow">
|
||||
@@ -33,7 +47,13 @@
|
||||
<div ng-if="agg.type === 'date_histogram'">
|
||||
<div class="gf-form offset-width-7">
|
||||
<label class="gf-form-label width-10">Interval</label>
|
||||
<metric-segment-model property="agg.settings.interval" get-options="getIntervalOptions()" on-change="onChangeInternal()" css-class="width-12" custom="true"></metric-segment-model>
|
||||
<gf-form-dropdown model="agg.settings.interval"
|
||||
get-options="getIntervalOptions()"
|
||||
on-change="onChangeInternal()"
|
||||
allow-custom="true"
|
||||
label-mode="true"
|
||||
css-class="width-12">
|
||||
</gf-form-dropdown>
|
||||
</div>
|
||||
|
||||
<div class="gf-form offset-width-7">
|
||||
@@ -66,11 +86,23 @@
|
||||
<div ng-if="agg.type === 'terms'">
|
||||
<div class="gf-form offset-width-7">
|
||||
<label class="gf-form-label width-10">Order</label>
|
||||
<metric-segment-model property="agg.settings.order" options="orderOptions" on-change="onChangeInternal()" css-class="width-12"></metric-segment-model>
|
||||
<gf-form-dropdown model="agg.settings.order"
|
||||
lookup-text="true"
|
||||
get-options="getOrderOptions()"
|
||||
on-change="onChangeInternal()"
|
||||
label-mode="true"
|
||||
css-class="width-12">
|
||||
</gf-form-dropdown>
|
||||
</div>
|
||||
<div class="gf-form offset-width-7">
|
||||
<label class="gf-form-label width-10">Size</label>
|
||||
<metric-segment-model property="agg.settings.size" options="sizeOptions" on-change="onChangeInternal()" css-class="width-12"></metric-segment-model>
|
||||
<gf-form-dropdown model="agg.settings.size"
|
||||
lookup-text="true"
|
||||
get-options="getSizeOptions()"
|
||||
on-change="onChangeInternal()"
|
||||
label-mode="true"
|
||||
css-class="width-12">
|
||||
</gf-form-dropdown>
|
||||
</div>
|
||||
<div class="gf-form offset-width-7">
|
||||
<label class="gf-form-label width-10">Min Doc Count</label>
|
||||
@@ -78,7 +110,13 @@
|
||||
</div>
|
||||
<div class="gf-form offset-width-7">
|
||||
<label class="gf-form-label width-10">Order By</label>
|
||||
<metric-segment-model property="agg.settings.orderBy" options="orderByOptions" on-change="onChangeInternal()" css-class="width-12"></metric-segment-model>
|
||||
<gf-form-dropdown model="agg.settings.orderBy"
|
||||
lookup-text="true"
|
||||
get-options="getOrderByOptions()"
|
||||
on-change="onChangeInternal()"
|
||||
label-mode="true"
|
||||
css-class="width-12">
|
||||
</gf-form-dropdown>
|
||||
</div>
|
||||
<div class="gf-form offset-width-7">
|
||||
<label class="gf-form-label width-10">
|
||||
|
||||
@@ -31,11 +31,11 @@ export class ElasticQueryCtrl extends QueryCtrl {
|
||||
|
||||
queryUpdated() {
|
||||
var newJson = angular.toJson(this.datasource.queryBuilder.build(this.target), true);
|
||||
if (newJson !== this.rawQueryOld) {
|
||||
this.rawQueryOld = newJson;
|
||||
if (this.rawQueryOld && newJson !== this.rawQueryOld) {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
this.rawQueryOld = newJson;
|
||||
this.$rootScope.appEvent('elastic-query-updated');
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<section class="grafana-metric-options gf-form-group">
|
||||
<section class="gf-form-group">
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form max-width-15">
|
||||
<span class="gf-form-label width-8">
|
||||
|
||||
@@ -210,10 +210,12 @@ export default class InfluxDatasource {
|
||||
var currentUrl = self.urls.shift();
|
||||
self.urls.push(currentUrl);
|
||||
|
||||
var params: any = {
|
||||
u: self.username,
|
||||
p: self.password,
|
||||
};
|
||||
var params: any = {};
|
||||
|
||||
if (self.username) {
|
||||
params.username = self.username;
|
||||
params.password = self.password;
|
||||
}
|
||||
|
||||
if (self.database) {
|
||||
params.db = self.database;
|
||||
|
||||
@@ -32,7 +32,7 @@ System.config({
|
||||
"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"
|
||||
"jquery.flot.dashes": "vendor/flot/jquery.flot.dashes",
|
||||
},
|
||||
|
||||
packages: {
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="351px" height="365px" viewBox="0 0 351 365" style="enable-background:new 0 0 351 365;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:url(#SVGID_1_);}
|
||||
</style>
|
||||
<g id="Layer_1_1_">
|
||||
</g>
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="175.5" y1="445.4948" x2="175.5" y2="114.0346">
|
||||
<stop offset="0" style="stop-color:#FFF100"/>
|
||||
<stop offset="1" style="stop-color:#F05A28"/>
|
||||
</linearGradient>
|
||||
<path class="st0" d="M342,161.2c-0.6-6.1-1.6-13.1-3.6-20.9c-2-7.7-5-16.2-9.4-25c-4.4-8.8-10.1-17.9-17.5-26.8
|
||||
c-2.9-3.5-6.1-6.9-9.5-10.2c5.1-20.3-6.2-37.9-6.2-37.9c-19.5-1.2-31.9,6.1-36.5,9.4c-0.8-0.3-1.5-0.7-2.3-1
|
||||
c-3.3-1.3-6.7-2.6-10.3-3.7c-3.5-1.1-7.1-2.1-10.8-3c-3.7-0.9-7.4-1.6-11.2-2.2c-0.7-0.1-1.3-0.2-2-0.3
|
||||
c-8.5-27.2-32.9-38.6-32.9-38.6c-27.3,17.3-32.4,41.5-32.4,41.5s-0.1,0.5-0.3,1.4c-1.5,0.4-3,0.9-4.5,1.3c-2.1,0.6-4.2,1.4-6.2,2.2
|
||||
c-2.1,0.8-4.1,1.6-6.2,2.5c-4.1,1.8-8.2,3.8-12.2,6c-3.9,2.2-7.7,4.6-11.4,7.1c-0.5-0.2-1-0.4-1-0.4c-37.8-14.4-71.3,2.9-71.3,2.9
|
||||
c-3.1,40.2,15.1,65.5,18.7,70.1c-0.9,2.5-1.7,5-2.5,7.5c-2.8,9.1-4.9,18.4-6.2,28.1c-0.2,1.4-0.4,2.8-0.5,4.2
|
||||
C18.8,192.7,8.5,228,8.5,228c29.1,33.5,63.1,35.6,63.1,35.6c0,0,0.1-0.1,0.1-0.1c4.3,7.7,9.3,15,14.9,21.9c2.4,2.9,4.8,5.6,7.4,8.3
|
||||
c-10.6,30.4,1.5,55.6,1.5,55.6c32.4,1.2,53.7-14.2,58.2-17.7c3.2,1.1,6.5,2.1,9.8,2.9c10,2.6,20.2,4.1,30.4,4.5
|
||||
c2.5,0.1,5.1,0.2,7.6,0.1l1.2,0l0.8,0l1.6,0l1.6-0.1l0,0.1c15.3,21.8,42.1,24.9,42.1,24.9c19.1-20.1,20.2-40.1,20.2-44.4l0,0
|
||||
c0,0,0-0.1,0-0.3c0-0.4,0-0.6,0-0.6l0,0c0-0.3,0-0.6,0-0.9c4-2.8,7.8-5.8,11.4-9.1c7.6-6.9,14.3-14.8,19.9-23.3
|
||||
c0.5-0.8,1-1.6,1.5-2.4c21.6,1.2,36.9-13.4,36.9-13.4c-3.6-22.5-16.4-33.5-19.1-35.6l0,0c0,0-0.1-0.1-0.3-0.2
|
||||
c-0.2-0.1-0.2-0.2-0.2-0.2c0,0,0,0,0,0c-0.1-0.1-0.3-0.2-0.5-0.3c0.1-1.4,0.2-2.7,0.3-4.1c0.2-2.4,0.2-4.9,0.2-7.3l0-1.8l0-0.9
|
||||
l0-0.5c0-0.6,0-0.4,0-0.6l-0.1-1.5l-0.1-2c0-0.7-0.1-1.3-0.2-1.9c-0.1-0.6-0.1-1.3-0.2-1.9l-0.2-1.9l-0.3-1.9
|
||||
c-0.4-2.5-0.8-4.9-1.4-7.4c-2.3-9.7-6.1-18.9-11-27.2c-5-8.3-11.2-15.6-18.3-21.8c-7-6.2-14.9-11.2-23.1-14.9
|
||||
c-8.3-3.7-16.9-6.1-25.5-7.2c-4.3-0.6-8.6-0.8-12.9-0.7l-1.6,0l-0.4,0c-0.1,0-0.6,0-0.5,0l-0.7,0l-1.6,0.1c-0.6,0-1.2,0.1-1.7,0.1
|
||||
c-2.2,0.2-4.4,0.5-6.5,0.9c-8.6,1.6-16.7,4.7-23.8,9c-7.1,4.3-13.3,9.6-18.3,15.6c-5,6-8.9,12.7-11.6,19.6c-2.7,6.9-4.2,14.1-4.6,21
|
||||
c-0.1,1.7-0.1,3.5-0.1,5.2c0,0.4,0,0.9,0,1.3l0.1,1.4c0.1,0.8,0.1,1.7,0.2,2.5c0.3,3.5,1,6.9,1.9,10.1c1.9,6.5,4.9,12.4,8.6,17.4
|
||||
c3.7,5,8.2,9.1,12.9,12.4c4.7,3.2,9.8,5.5,14.8,7c5,1.5,10,2.1,14.7,2.1c0.6,0,1.2,0,1.7,0c0.3,0,0.6,0,0.9,0c0.3,0,0.6,0,0.9-0.1
|
||||
c0.5,0,1-0.1,1.5-0.1c0.1,0,0.3,0,0.4-0.1l0.5-0.1c0.3,0,0.6-0.1,0.9-0.1c0.6-0.1,1.1-0.2,1.7-0.3c0.6-0.1,1.1-0.2,1.6-0.4
|
||||
c1.1-0.2,2.1-0.6,3.1-0.9c2-0.7,4-1.5,5.7-2.4c1.8-0.9,3.4-2,5-3c0.4-0.3,0.9-0.6,1.3-1c1.6-1.3,1.9-3.7,0.6-5.3
|
||||
c-1.1-1.4-3.1-1.8-4.7-0.9c-0.4,0.2-0.8,0.4-1.2,0.6c-1.4,0.7-2.8,1.3-4.3,1.8c-1.5,0.5-3.1,0.9-4.7,1.2c-0.8,0.1-1.6,0.2-2.5,0.3
|
||||
c-0.4,0-0.8,0.1-1.3,0.1c-0.4,0-0.9,0-1.2,0c-0.4,0-0.8,0-1.2,0c-0.5,0-1,0-1.5-0.1c0,0-0.3,0-0.1,0l-0.2,0l-0.3,0
|
||||
c-0.2,0-0.5,0-0.7-0.1c-0.5-0.1-0.9-0.1-1.4-0.2c-3.7-0.5-7.4-1.6-10.9-3.2c-3.6-1.6-7-3.8-10.1-6.6c-3.1-2.8-5.8-6.1-7.9-9.9
|
||||
c-2.1-3.8-3.6-8-4.3-12.4c-0.3-2.2-0.5-4.5-0.4-6.7c0-0.6,0.1-1.2,0.1-1.8c0,0.2,0-0.1,0-0.1l0-0.2l0-0.5c0-0.3,0.1-0.6,0.1-0.9
|
||||
c0.1-1.2,0.3-2.4,0.5-3.6c1.7-9.6,6.5-19,13.9-26.1c1.9-1.8,3.9-3.4,6-4.9c2.1-1.5,4.4-2.8,6.8-3.9c2.4-1.1,4.8-2,7.4-2.7
|
||||
c2.5-0.7,5.1-1.1,7.8-1.4c1.3-0.1,2.6-0.2,4-0.2c0.4,0,0.6,0,0.9,0l1.1,0l0.7,0c0.3,0,0,0,0.1,0l0.3,0l1.1,0.1
|
||||
c2.9,0.2,5.7,0.6,8.5,1.3c5.6,1.2,11.1,3.3,16.2,6.1c10.2,5.7,18.9,14.5,24.2,25.1c2.7,5.3,4.6,11,5.5,16.9c0.2,1.5,0.4,3,0.5,4.5
|
||||
l0.1,1.1l0.1,1.1c0,0.4,0,0.8,0,1.1c0,0.4,0,0.8,0,1.1l0,1l0,1.1c0,0.7-0.1,1.9-0.1,2.6c-0.1,1.6-0.3,3.3-0.5,4.9
|
||||
c-0.2,1.6-0.5,3.2-0.8,4.8c-0.3,1.6-0.7,3.2-1.1,4.7c-0.8,3.1-1.8,6.2-3,9.3c-2.4,6-5.6,11.8-9.4,17.1
|
||||
c-7.7,10.6-18.2,19.2-30.2,24.7c-6,2.7-12.3,4.7-18.8,5.7c-3.2,0.6-6.5,0.9-9.8,1l-0.6,0l-0.5,0l-1.1,0l-1.6,0l-0.8,0
|
||||
c0.4,0-0.1,0-0.1,0l-0.3,0c-1.8,0-3.5-0.1-5.3-0.3c-7-0.5-13.9-1.8-20.7-3.7c-6.7-1.9-13.2-4.6-19.4-7.8
|
||||
c-12.3-6.6-23.4-15.6-32-26.5c-4.3-5.4-8.1-11.3-11.2-17.4c-3.1-6.1-5.6-12.6-7.4-19.1c-1.8-6.6-2.9-13.3-3.4-20.1l-0.1-1.3l0-0.3
|
||||
l0-0.3l0-0.6l0-1.1l0-0.3l0-0.4l0-0.8l0-1.6l0-0.3c0,0,0,0.1,0-0.1l0-0.6c0-0.8,0-1.7,0-2.5c0.1-3.3,0.4-6.8,0.8-10.2
|
||||
c0.4-3.4,1-6.9,1.7-10.3c0.7-3.4,1.5-6.8,2.5-10.2c1.9-6.7,4.3-13.2,7.1-19.3c5.7-12.2,13.1-23.1,22-31.8c2.2-2.2,4.5-4.2,6.9-6.2
|
||||
c2.4-1.9,4.9-3.7,7.5-5.4c2.5-1.7,5.2-3.2,7.9-4.6c1.3-0.7,2.7-1.4,4.1-2c0.7-0.3,1.4-0.6,2.1-0.9c0.7-0.3,1.4-0.6,2.1-0.9
|
||||
c2.8-1.2,5.7-2.2,8.7-3.1c0.7-0.2,1.5-0.4,2.2-0.7c0.7-0.2,1.5-0.4,2.2-0.6c1.5-0.4,3-0.8,4.5-1.1c0.7-0.2,1.5-0.3,2.3-0.5
|
||||
c0.8-0.2,1.5-0.3,2.3-0.5c0.8-0.1,1.5-0.3,2.3-0.4l1.1-0.2l1.2-0.2c0.8-0.1,1.5-0.2,2.3-0.3c0.9-0.1,1.7-0.2,2.6-0.3
|
||||
c0.7-0.1,1.9-0.2,2.6-0.3c0.5-0.1,1.1-0.1,1.6-0.2l1.1-0.1l0.5-0.1l0.6,0c0.9-0.1,1.7-0.1,2.6-0.2l1.3-0.1c0,0,0.5,0,0.1,0l0.3,0
|
||||
l0.6,0c0.7,0,1.5-0.1,2.2-0.1c2.9-0.1,5.9-0.1,8.8,0c5.8,0.2,11.5,0.9,17,1.9c11.1,2.1,21.5,5.6,31,10.3
|
||||
c9.5,4.6,17.9,10.3,25.3,16.5c0.5,0.4,0.9,0.8,1.4,1.2c0.4,0.4,0.9,0.8,1.3,1.2c0.9,0.8,1.7,1.6,2.6,2.4c0.9,0.8,1.7,1.6,2.5,2.4
|
||||
c0.8,0.8,1.6,1.6,2.4,2.5c3.1,3.3,6,6.6,8.6,10c5.2,6.7,9.4,13.5,12.7,19.9c0.2,0.4,0.4,0.8,0.6,1.2c0.2,0.4,0.4,0.8,0.6,1.2
|
||||
c0.4,0.8,0.8,1.6,1.1,2.4c0.4,0.8,0.7,1.5,1.1,2.3c0.3,0.8,0.7,1.5,1,2.3c1.2,3,2.4,5.9,3.3,8.6c1.5,4.4,2.6,8.3,3.5,11.7
|
||||
c0.3,1.4,1.6,2.3,3,2.1c1.5-0.1,2.6-1.3,2.6-2.8C342.6,170.4,342.5,166.1,342,161.2z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
+57
-58
@@ -1,58 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="351px"
|
||||
height="365px" viewBox="0 0 351 365" style="enable-background:new 0 0 351 365;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:url(#SVGID_1_);}
|
||||
</style>
|
||||
<g id="Layer_1">
|
||||
</g>
|
||||
<g id="Layer_2">
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="170.963" y1="439.9414" x2="170.963" y2="106.0154">
|
||||
<stop offset="0" style="stop-color:#FFF200"/>
|
||||
<stop offset="1" style="stop-color:#F15A29"/>
|
||||
</linearGradient>
|
||||
<path class="st0" d="M228.8,239.8c-1.1-1.4-3.1-1.8-4.7-0.9c-0.4,0.2-0.8,0.4-1.2,0.6c-1.4,0.7-2.8,1.3-4.3,1.8
|
||||
c-1.5,0.5-3.1,0.9-4.7,1.2c-0.8,0.1-1.6,0.2-2.5,0.3c-0.4,0-0.8,0.1-1.3,0.1c-0.4,0-0.9,0-1.2,0c-0.4,0-0.8,0-1.2,0
|
||||
c-0.5,0-1,0-1.5-0.1c0,0-0.3,0-0.1,0l-0.2,0l-0.3,0c-0.2,0-0.5,0-0.7-0.1c-0.5-0.1-0.9-0.1-1.4-0.2c-3.7-0.5-7.4-1.6-10.9-3.2
|
||||
c-3.6-1.6-7-3.8-10.1-6.6c-3.1-2.8-5.8-6.1-7.9-9.9c-2.1-3.8-3.6-8-4.3-12.4c-0.3-2.2-0.5-4.5-0.4-6.7c0-0.6,0.1-1.2,0.1-1.8
|
||||
c0,0.2,0-0.1,0-0.1l0-0.2l0-0.5c0-0.3,0.1-0.6,0.1-0.9c0.1-1.2,0.3-2.4,0.5-3.6c1.7-9.6,6.5-19,13.9-26.1c1.9-1.8,3.9-3.4,6-4.9
|
||||
c2.1-1.5,4.4-2.8,6.8-3.9c2.4-1.1,4.8-2,7.4-2.7c2.5-0.7,5.1-1.1,7.8-1.4c1.3-0.1,2.6-0.2,4-0.2c0.4,0,0.6,0,0.9,0l1.1,0l0.7,0
|
||||
c0.3,0,0,0,0.1,0l0.3,0l1.1,0.1c2.9,0.2,5.7,0.6,8.5,1.3c5.6,1.2,11.1,3.3,16.2,6.1c10.2,5.7,18.9,14.5,24.2,25.1
|
||||
c2.7,5.3,4.6,11,5.5,16.9c0.2,1.5,0.4,3,0.5,4.5l0.1,1.1l0.1,1.1c0,0.4,0,0.8,0,1.1c0,0.4,0,0.8,0,1.1l0,1l0,1.1
|
||||
c0,0.7-0.1,1.9-0.1,2.6c-0.1,1.6-0.3,3.3-0.5,4.9c-0.2,1.6-0.5,3.2-0.8,4.8c-0.3,1.6-0.7,3.2-1.1,4.7c-0.8,3.1-1.8,6.2-3,9.3
|
||||
c-2.4,6-5.6,11.8-9.4,17.1c-7.7,10.6-18.2,19.2-30.1,24.7c-6,2.7-12.3,4.7-18.8,5.7c-3.2,0.6-6.5,0.9-9.8,1l-0.6,0l-0.5,0l-1.1,0
|
||||
l-1.6,0l-0.8,0c0.4,0-0.1,0-0.1,0l-0.3,0c-1.8,0-3.5-0.1-5.3-0.3c-7-0.5-13.9-1.8-20.7-3.7c-6.7-1.9-13.2-4.6-19.4-7.8
|
||||
c-12.3-6.6-23.3-15.6-32-26.5c-4.3-5.4-8.1-11.3-11.2-17.4c-3.1-6.1-5.6-12.6-7.4-19.1c-1.8-6.6-2.9-13.3-3.4-20.1l-0.1-1.3l0-0.3
|
||||
l0-0.3l0-0.6l0-1.1l0-0.3l0-0.4l0-0.8l0-1.6l0-0.3c0,0,0,0.1,0-0.1l0-0.6c0-0.8,0-1.7,0-2.5c0.1-3.3,0.4-6.8,0.8-10.2
|
||||
c0.4-3.4,1-6.9,1.7-10.3c0.7-3.4,1.5-6.8,2.5-10.2c1.9-6.7,4.3-13.2,7.1-19.3c5.7-12.2,13.1-23.1,22-31.8c2.2-2.2,4.5-4.2,6.9-6.2
|
||||
c2.4-1.9,4.9-3.7,7.5-5.4c2.5-1.7,5.2-3.2,7.9-4.6c1.3-0.7,2.7-1.4,4.1-2c0.7-0.3,1.4-0.6,2.1-0.9c0.7-0.3,1.4-0.6,2.1-0.9
|
||||
c2.8-1.2,5.7-2.2,8.7-3.1c0.7-0.2,1.5-0.4,2.2-0.7c0.7-0.2,1.5-0.4,2.2-0.6c1.5-0.4,3-0.8,4.5-1.1c0.7-0.2,1.5-0.3,2.3-0.5
|
||||
c0.8-0.2,1.5-0.3,2.3-0.5c0.8-0.1,1.5-0.3,2.3-0.4l1.1-0.2l1.1-0.2c0.8-0.1,1.5-0.2,2.3-0.3c0.9-0.1,1.7-0.2,2.6-0.3
|
||||
c0.7-0.1,1.9-0.2,2.6-0.3c0.5-0.1,1.1-0.1,1.6-0.2l1.1-0.1l0.5-0.1l0.6,0c0.9-0.1,1.7-0.1,2.6-0.2l1.3-0.1c0,0,0.5,0,0.1,0l0.3,0
|
||||
l0.6,0c0.7,0,1.5-0.1,2.2-0.1c2.9-0.1,5.9-0.1,8.8,0c5.8,0.2,11.5,0.9,17,1.9c11.1,2.1,21.5,5.6,30.9,10.3
|
||||
c9.5,4.6,17.9,10.3,25.3,16.5c0.5,0.4,0.9,0.8,1.4,1.2c0.4,0.4,0.9,0.8,1.3,1.2c0.9,0.8,1.7,1.6,2.6,2.4c0.9,0.8,1.7,1.6,2.5,2.4
|
||||
c0.8,0.8,1.6,1.6,2.4,2.5c3.1,3.3,6,6.6,8.6,10c5.2,6.7,9.4,13.5,12.7,19.9c0.2,0.4,0.4,0.8,0.6,1.2c0.2,0.4,0.4,0.8,0.6,1.2
|
||||
c0.4,0.8,0.8,1.6,1.1,2.3c0.4,0.8,0.7,1.5,1.1,2.3c0.3,0.8,0.7,1.5,1,2.3c1.2,3,2.4,5.8,3.3,8.6c1.5,4.4,2.6,8.3,3.5,11.7
|
||||
c0.3,1.4,1.6,2.3,3,2.1l0,0c1.5-0.1,2.6-1.3,2.6-2.8c0.1-3.7,0-8-0.4-12.9c-0.6-6.1-1.6-13.1-3.6-20.9c-2-7.7-5-16.2-9.4-25
|
||||
c-4.4-8.8-10.1-17.9-17.5-26.8c-2.9-3.5-6.1-6.9-9.5-10.2c5.1-20.3-6.2-37.9-6.2-37.9c-19.5-1.2-31.9,6.1-36.5,9.4
|
||||
c-0.8-0.3-1.5-0.7-2.3-1c-3.3-1.3-6.7-2.6-10.2-3.7c-3.5-1.1-7.1-2.1-10.8-3c-3.7-0.9-7.4-1.6-11.2-2.2c-0.7-0.1-1.3-0.2-2-0.3
|
||||
C209.6,12.4,185.2,1,185.2,1c-27.3,17.3-32.4,41.5-32.4,41.5c0.2,0.4,0.5,0.8,0.7,1.1c-1.8,0.5-3.7,1.1-5.5,1.6
|
||||
c-2.1,0.6-4.2,1.4-6.2,2.2c-2.1,0.8-4.1,1.6-6.2,2.5c-4.1,1.8-8.2,3.8-12.2,6c-4,2.2-7.9,4.7-11.7,7.4c-0.1,0.1-0.2,0.2-0.4,0.3
|
||||
c-0.2-0.6-0.3-0.9-0.3-0.9c-37.7-14.4-71.3,2.9-71.3,2.9c-3.1,40.2,15.1,65.4,18.7,70c-0.9,2.5-1.7,5-2.5,7.5
|
||||
c-2.8,9.1-4.9,18.4-6.2,28.1c-0.2,1.4-0.4,2.8-0.5,4.2C14.3,192.6,4,227.9,4,227.9c29.1,33.5,63,35.5,63,35.5c0,0,0.1-0.1,0.1-0.1
|
||||
c4.3,7.7,9.3,15,14.9,21.9c2.4,2.9,4.8,5.6,7.4,8.3c-10.6,30.3,1.5,55.6,1.5,55.6c32.4,1.2,53.7-14.2,58.2-17.7
|
||||
c3.2,1.1,6.5,2.1,9.8,2.9c10,2.6,20.2,4.1,30.3,4.5c2.5,0.1,5.1,0.2,7.6,0.1l1.2,0l0.8,0l1.6,0l1.6-0.1c0,0,0,0.1,0,0.1
|
||||
c15.3,21.8,42.1,24.9,42.1,24.9c21.6-22.7,20.2-45.3,20.2-45.3c-0.2-0.2-0.4-0.3-0.6-0.5c4.2-2.9,8.2-6.1,12-9.5
|
||||
c7.6-6.9,14.3-14.8,19.9-23.3c0.5-0.8,1-1.6,1.5-2.4c21.6,1.2,36.9-13.4,36.9-13.4c-4-25.2-19.6-36-19.6-36c-0.2,0-0.3,0.1-0.5,0.1
|
||||
c0.2-1.5,0.3-3,0.4-4.5c0.2-2.4,0.2-4.9,0.2-7.3l0-1.8l0-0.9l0-0.5c0-0.6,0-0.4,0-0.6l-0.1-1.5l-0.1-2c0-0.7-0.1-1.3-0.2-1.9
|
||||
c-0.1-0.6-0.1-1.3-0.2-1.9l-0.2-1.9l-0.3-1.9c-0.4-2.5-0.8-4.9-1.4-7.4c-2.3-9.7-6.1-18.9-11-27.2c-5-8.3-11.2-15.6-18.2-21.8
|
||||
c-7-6.2-14.9-11.2-23.1-14.9c-8.2-3.7-16.9-6.1-25.5-7.2c-4.3-0.6-8.6-0.8-12.9-0.7l-1.6,0l-0.4,0c-0.1,0-0.6,0-0.5,0l-0.7,0
|
||||
l-1.6,0.1c-0.6,0-1.2,0.1-1.7,0.1c-2.2,0.2-4.4,0.5-6.5,0.9c-8.6,1.6-16.6,4.7-23.8,9c-7.1,4.3-13.3,9.6-18.3,15.6
|
||||
c-5,6-8.9,12.7-11.6,19.6c-2.7,6.9-4.2,14.1-4.6,21c-0.1,1.7-0.1,3.5-0.1,5.2c0,0.4,0,0.9,0,1.3l0.1,1.4c0.1,0.8,0.1,1.7,0.2,2.5
|
||||
c0.3,3.5,1,6.9,1.9,10.1c1.9,6.5,4.9,12.4,8.6,17.4c3.7,5,8.2,9.1,12.9,12.4c4.7,3.2,9.8,5.5,14.8,7c5,1.5,10,2.1,14.7,2.1
|
||||
c0.6,0,1.2,0,1.7,0c0.3,0,0.6,0,0.9,0c0.3,0,0.6,0,0.9-0.1c0.5,0,1-0.1,1.5-0.1c0.1,0,0.3,0,0.4-0.1l0.5-0.1c0.3,0,0.6-0.1,0.9-0.1
|
||||
c0.6-0.1,1.1-0.2,1.7-0.3c0.6-0.1,1.1-0.2,1.6-0.4c1.1-0.2,2.1-0.6,3.1-0.9c2-0.7,3.9-1.5,5.7-2.4c1.8-0.9,3.4-2,5-3
|
||||
c0.4-0.3,0.9-0.6,1.3-1C229.9,243.8,230.1,241.4,228.8,239.8L228.8,239.8z"/>
|
||||
</g>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="351px" height="365px" viewBox="0 0 351 365" style="enable-background:new 0 0 351 365;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:url(#SVGID_1_);}
|
||||
</style>
|
||||
<g id="Layer_1_1_">
|
||||
</g>
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="175.5" y1="445.4948" x2="175.5" y2="114.0346">
|
||||
<stop offset="0" style="stop-color:#FFF100"/>
|
||||
<stop offset="1" style="stop-color:#F05A28"/>
|
||||
</linearGradient>
|
||||
<path class="st0" d="M342,161.2c-0.6-6.1-1.6-13.1-3.6-20.9c-2-7.7-5-16.2-9.4-25c-4.4-8.8-10.1-17.9-17.5-26.8
|
||||
c-2.9-3.5-6.1-6.9-9.5-10.2c5.1-20.3-6.2-37.9-6.2-37.9c-19.5-1.2-31.9,6.1-36.5,9.4c-0.8-0.3-1.5-0.7-2.3-1
|
||||
c-3.3-1.3-6.7-2.6-10.3-3.7c-3.5-1.1-7.1-2.1-10.8-3c-3.7-0.9-7.4-1.6-11.2-2.2c-0.7-0.1-1.3-0.2-2-0.3
|
||||
c-8.5-27.2-32.9-38.6-32.9-38.6c-27.3,17.3-32.4,41.5-32.4,41.5s-0.1,0.5-0.3,1.4c-1.5,0.4-3,0.9-4.5,1.3c-2.1,0.6-4.2,1.4-6.2,2.2
|
||||
c-2.1,0.8-4.1,1.6-6.2,2.5c-4.1,1.8-8.2,3.8-12.2,6c-3.9,2.2-7.7,4.6-11.4,7.1c-0.5-0.2-1-0.4-1-0.4c-37.8-14.4-71.3,2.9-71.3,2.9
|
||||
c-3.1,40.2,15.1,65.5,18.7,70.1c-0.9,2.5-1.7,5-2.5,7.5c-2.8,9.1-4.9,18.4-6.2,28.1c-0.2,1.4-0.4,2.8-0.5,4.2
|
||||
C18.8,192.7,8.5,228,8.5,228c29.1,33.5,63.1,35.6,63.1,35.6c0,0,0.1-0.1,0.1-0.1c4.3,7.7,9.3,15,14.9,21.9c2.4,2.9,4.8,5.6,7.4,8.3
|
||||
c-10.6,30.4,1.5,55.6,1.5,55.6c32.4,1.2,53.7-14.2,58.2-17.7c3.2,1.1,6.5,2.1,9.8,2.9c10,2.6,20.2,4.1,30.4,4.5
|
||||
c2.5,0.1,5.1,0.2,7.6,0.1l1.2,0l0.8,0l1.6,0l1.6-0.1l0,0.1c15.3,21.8,42.1,24.9,42.1,24.9c19.1-20.1,20.2-40.1,20.2-44.4l0,0
|
||||
c0,0,0-0.1,0-0.3c0-0.4,0-0.6,0-0.6l0,0c0-0.3,0-0.6,0-0.9c4-2.8,7.8-5.8,11.4-9.1c7.6-6.9,14.3-14.8,19.9-23.3
|
||||
c0.5-0.8,1-1.6,1.5-2.4c21.6,1.2,36.9-13.4,36.9-13.4c-3.6-22.5-16.4-33.5-19.1-35.6l0,0c0,0-0.1-0.1-0.3-0.2
|
||||
c-0.2-0.1-0.2-0.2-0.2-0.2c0,0,0,0,0,0c-0.1-0.1-0.3-0.2-0.5-0.3c0.1-1.4,0.2-2.7,0.3-4.1c0.2-2.4,0.2-4.9,0.2-7.3l0-1.8l0-0.9
|
||||
l0-0.5c0-0.6,0-0.4,0-0.6l-0.1-1.5l-0.1-2c0-0.7-0.1-1.3-0.2-1.9c-0.1-0.6-0.1-1.3-0.2-1.9l-0.2-1.9l-0.3-1.9
|
||||
c-0.4-2.5-0.8-4.9-1.4-7.4c-2.3-9.7-6.1-18.9-11-27.2c-5-8.3-11.2-15.6-18.3-21.8c-7-6.2-14.9-11.2-23.1-14.9
|
||||
c-8.3-3.7-16.9-6.1-25.5-7.2c-4.3-0.6-8.6-0.8-12.9-0.7l-1.6,0l-0.4,0c-0.1,0-0.6,0-0.5,0l-0.7,0l-1.6,0.1c-0.6,0-1.2,0.1-1.7,0.1
|
||||
c-2.2,0.2-4.4,0.5-6.5,0.9c-8.6,1.6-16.7,4.7-23.8,9c-7.1,4.3-13.3,9.6-18.3,15.6c-5,6-8.9,12.7-11.6,19.6c-2.7,6.9-4.2,14.1-4.6,21
|
||||
c-0.1,1.7-0.1,3.5-0.1,5.2c0,0.4,0,0.9,0,1.3l0.1,1.4c0.1,0.8,0.1,1.7,0.2,2.5c0.3,3.5,1,6.9,1.9,10.1c1.9,6.5,4.9,12.4,8.6,17.4
|
||||
c3.7,5,8.2,9.1,12.9,12.4c4.7,3.2,9.8,5.5,14.8,7c5,1.5,10,2.1,14.7,2.1c0.6,0,1.2,0,1.7,0c0.3,0,0.6,0,0.9,0c0.3,0,0.6,0,0.9-0.1
|
||||
c0.5,0,1-0.1,1.5-0.1c0.1,0,0.3,0,0.4-0.1l0.5-0.1c0.3,0,0.6-0.1,0.9-0.1c0.6-0.1,1.1-0.2,1.7-0.3c0.6-0.1,1.1-0.2,1.6-0.4
|
||||
c1.1-0.2,2.1-0.6,3.1-0.9c2-0.7,4-1.5,5.7-2.4c1.8-0.9,3.4-2,5-3c0.4-0.3,0.9-0.6,1.3-1c1.6-1.3,1.9-3.7,0.6-5.3
|
||||
c-1.1-1.4-3.1-1.8-4.7-0.9c-0.4,0.2-0.8,0.4-1.2,0.6c-1.4,0.7-2.8,1.3-4.3,1.8c-1.5,0.5-3.1,0.9-4.7,1.2c-0.8,0.1-1.6,0.2-2.5,0.3
|
||||
c-0.4,0-0.8,0.1-1.3,0.1c-0.4,0-0.9,0-1.2,0c-0.4,0-0.8,0-1.2,0c-0.5,0-1,0-1.5-0.1c0,0-0.3,0-0.1,0l-0.2,0l-0.3,0
|
||||
c-0.2,0-0.5,0-0.7-0.1c-0.5-0.1-0.9-0.1-1.4-0.2c-3.7-0.5-7.4-1.6-10.9-3.2c-3.6-1.6-7-3.8-10.1-6.6c-3.1-2.8-5.8-6.1-7.9-9.9
|
||||
c-2.1-3.8-3.6-8-4.3-12.4c-0.3-2.2-0.5-4.5-0.4-6.7c0-0.6,0.1-1.2,0.1-1.8c0,0.2,0-0.1,0-0.1l0-0.2l0-0.5c0-0.3,0.1-0.6,0.1-0.9
|
||||
c0.1-1.2,0.3-2.4,0.5-3.6c1.7-9.6,6.5-19,13.9-26.1c1.9-1.8,3.9-3.4,6-4.9c2.1-1.5,4.4-2.8,6.8-3.9c2.4-1.1,4.8-2,7.4-2.7
|
||||
c2.5-0.7,5.1-1.1,7.8-1.4c1.3-0.1,2.6-0.2,4-0.2c0.4,0,0.6,0,0.9,0l1.1,0l0.7,0c0.3,0,0,0,0.1,0l0.3,0l1.1,0.1
|
||||
c2.9,0.2,5.7,0.6,8.5,1.3c5.6,1.2,11.1,3.3,16.2,6.1c10.2,5.7,18.9,14.5,24.2,25.1c2.7,5.3,4.6,11,5.5,16.9c0.2,1.5,0.4,3,0.5,4.5
|
||||
l0.1,1.1l0.1,1.1c0,0.4,0,0.8,0,1.1c0,0.4,0,0.8,0,1.1l0,1l0,1.1c0,0.7-0.1,1.9-0.1,2.6c-0.1,1.6-0.3,3.3-0.5,4.9
|
||||
c-0.2,1.6-0.5,3.2-0.8,4.8c-0.3,1.6-0.7,3.2-1.1,4.7c-0.8,3.1-1.8,6.2-3,9.3c-2.4,6-5.6,11.8-9.4,17.1
|
||||
c-7.7,10.6-18.2,19.2-30.2,24.7c-6,2.7-12.3,4.7-18.8,5.7c-3.2,0.6-6.5,0.9-9.8,1l-0.6,0l-0.5,0l-1.1,0l-1.6,0l-0.8,0
|
||||
c0.4,0-0.1,0-0.1,0l-0.3,0c-1.8,0-3.5-0.1-5.3-0.3c-7-0.5-13.9-1.8-20.7-3.7c-6.7-1.9-13.2-4.6-19.4-7.8
|
||||
c-12.3-6.6-23.4-15.6-32-26.5c-4.3-5.4-8.1-11.3-11.2-17.4c-3.1-6.1-5.6-12.6-7.4-19.1c-1.8-6.6-2.9-13.3-3.4-20.1l-0.1-1.3l0-0.3
|
||||
l0-0.3l0-0.6l0-1.1l0-0.3l0-0.4l0-0.8l0-1.6l0-0.3c0,0,0,0.1,0-0.1l0-0.6c0-0.8,0-1.7,0-2.5c0.1-3.3,0.4-6.8,0.8-10.2
|
||||
c0.4-3.4,1-6.9,1.7-10.3c0.7-3.4,1.5-6.8,2.5-10.2c1.9-6.7,4.3-13.2,7.1-19.3c5.7-12.2,13.1-23.1,22-31.8c2.2-2.2,4.5-4.2,6.9-6.2
|
||||
c2.4-1.9,4.9-3.7,7.5-5.4c2.5-1.7,5.2-3.2,7.9-4.6c1.3-0.7,2.7-1.4,4.1-2c0.7-0.3,1.4-0.6,2.1-0.9c0.7-0.3,1.4-0.6,2.1-0.9
|
||||
c2.8-1.2,5.7-2.2,8.7-3.1c0.7-0.2,1.5-0.4,2.2-0.7c0.7-0.2,1.5-0.4,2.2-0.6c1.5-0.4,3-0.8,4.5-1.1c0.7-0.2,1.5-0.3,2.3-0.5
|
||||
c0.8-0.2,1.5-0.3,2.3-0.5c0.8-0.1,1.5-0.3,2.3-0.4l1.1-0.2l1.2-0.2c0.8-0.1,1.5-0.2,2.3-0.3c0.9-0.1,1.7-0.2,2.6-0.3
|
||||
c0.7-0.1,1.9-0.2,2.6-0.3c0.5-0.1,1.1-0.1,1.6-0.2l1.1-0.1l0.5-0.1l0.6,0c0.9-0.1,1.7-0.1,2.6-0.2l1.3-0.1c0,0,0.5,0,0.1,0l0.3,0
|
||||
l0.6,0c0.7,0,1.5-0.1,2.2-0.1c2.9-0.1,5.9-0.1,8.8,0c5.8,0.2,11.5,0.9,17,1.9c11.1,2.1,21.5,5.6,31,10.3
|
||||
c9.5,4.6,17.9,10.3,25.3,16.5c0.5,0.4,0.9,0.8,1.4,1.2c0.4,0.4,0.9,0.8,1.3,1.2c0.9,0.8,1.7,1.6,2.6,2.4c0.9,0.8,1.7,1.6,2.5,2.4
|
||||
c0.8,0.8,1.6,1.6,2.4,2.5c3.1,3.3,6,6.6,8.6,10c5.2,6.7,9.4,13.5,12.7,19.9c0.2,0.4,0.4,0.8,0.6,1.2c0.2,0.4,0.4,0.8,0.6,1.2
|
||||
c0.4,0.8,0.8,1.6,1.1,2.4c0.4,0.8,0.7,1.5,1.1,2.3c0.3,0.8,0.7,1.5,1,2.3c1.2,3,2.4,5.9,3.3,8.6c1.5,4.4,2.6,8.3,3.5,11.7
|
||||
c0.3,1.4,1.6,2.3,3,2.1c1.5-0.1,2.6-1.3,2.6-2.8C342.6,170.4,342.5,166.1,342,161.2z"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
@@ -76,6 +76,8 @@
|
||||
@import "components/jsontree";
|
||||
@import "components/edit_sidemenu.scss";
|
||||
@import "components/row.scss";
|
||||
@import "components/json_explorer.scss";
|
||||
@import "components/collapse_box.scss";
|
||||
|
||||
// PAGES
|
||||
@import "pages/login";
|
||||
|
||||
@@ -280,6 +280,24 @@ $card-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, .1), 1px 1px 0 0 rgba(0, 0, 0, .3)
|
||||
$footer-link-color: $gray-1;
|
||||
$footer-link-hover: $gray-4;
|
||||
|
||||
// collapse box
|
||||
$collapse-box-body-border: $dark-5;
|
||||
$collapse-box-body-error-border: $red;
|
||||
|
||||
// json-explorer
|
||||
$json-explorer-default-color: $text-color;
|
||||
$json-explorer-string-color: #23d662;
|
||||
$json-explorer-number-color: $variable;
|
||||
$json-explorer-boolean-color: $variable;
|
||||
$json-explorer-null-color: #EEC97D;
|
||||
$json-explorer-undefined-color: rgb(239, 143, 190);
|
||||
$json-explorer-function-color: #FD48CB;
|
||||
$json-explorer-rotate-time: 100ms;
|
||||
$json-explorer-toggler-opacity: 0.6;
|
||||
$json-explorer-toggler-color: #45376F;
|
||||
$json-explorer-bracket-color: #9494FF;
|
||||
$json-explorer-key-color: #23A0DB;
|
||||
$json-explorer-url-color: #027BFF;
|
||||
|
||||
// Changelog and diff
|
||||
// -------------------------
|
||||
|
||||
@@ -304,6 +304,24 @@ $card-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, .1), 1px 1px 0 0 rgba(0, 0, 0, .1)
|
||||
$footer-link-color: $gray-3;
|
||||
$footer-link-hover: $dark-5;
|
||||
|
||||
// collapse box
|
||||
$collapse-box-body-border: $gray-4;
|
||||
$collapse-box-body-error-border: $red;
|
||||
|
||||
// json explorer
|
||||
$json-explorer-default-color: black;
|
||||
$json-explorer-string-color: green;
|
||||
$json-explorer-number-color: blue;
|
||||
$json-explorer-boolean-color: red;
|
||||
$json-explorer-null-color: #855A00;
|
||||
$json-explorer-undefined-color: rgb(202, 11, 105);
|
||||
$json-explorer-function-color: #FF20ED;
|
||||
$json-explorer-rotate-time: 100ms;
|
||||
$json-explorer-toggler-opacity: 0.6;
|
||||
$json-explorer-toggler-color: #45376F;
|
||||
$json-explorer-bracket-color: blue;
|
||||
$json-explorer-key-color: #00008B;
|
||||
$json-explorer-url-color: blue;
|
||||
|
||||
// Changelog and diff
|
||||
// -------------------------
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
.collapse-box {
|
||||
margin-bottom: $spacer;
|
||||
|
||||
&--error {
|
||||
.collapse-box__header {
|
||||
border-color: $collapse-box-body-error-border;
|
||||
}
|
||||
.collapse-box__body {
|
||||
border-color: $collapse-box-body-error-border;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.collapse-box__header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: $input-padding-y $input-padding-x;
|
||||
margin-right: $gf-form-margin;
|
||||
background-color: $input-label-bg;
|
||||
font-size: $font-size-sm;
|
||||
margin-right: $gf-form-margin;
|
||||
border: $input-btn-border-width solid $collapse-box-body-border;
|
||||
@include border-radius($label-border-radius-sm);
|
||||
}
|
||||
|
||||
.collapse-box__header-title {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.collapse-box__body {
|
||||
padding: $input-padding-y*2 $input-padding-x;
|
||||
display: block;
|
||||
margin-right: $gf-form-margin;
|
||||
border: $input-btn-border-width solid $collapse-box-body-border;
|
||||
border-top: none;
|
||||
@include border-radius($label-border-radius-sm);
|
||||
}
|
||||
|
||||
.collapse-box__header-actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
a {
|
||||
margin-left: $spacer;
|
||||
}
|
||||
}
|
||||
@@ -103,6 +103,7 @@ $gf-form-margin: 0.25rem;
|
||||
padding: $input-padding-y $input-padding-x;
|
||||
margin-right: $gf-form-margin;
|
||||
font-size: $font-size-base;
|
||||
margin-right: $gf-form-margin;
|
||||
line-height: $input-line-height;
|
||||
color: $input-color;
|
||||
background-color: $input-bg;
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
|
||||
.json-formatter-row {
|
||||
font-family: monospace;
|
||||
|
||||
&, a, a:hover {
|
||||
color: $json-explorer-default-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.json-formatter-row {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.json-formatter-children {
|
||||
&.json-formatter-empty {
|
||||
opacity: 0.5;
|
||||
margin-left: 1rem;
|
||||
|
||||
&::after { display: none; }
|
||||
&.json-formatter-object::after { content: "No properties"; }
|
||||
&.json-formatter-array::after { content: "[]"; }
|
||||
}
|
||||
}
|
||||
|
||||
.json-formatter-string {
|
||||
color: $json-explorer-string-color;
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.json-formatter-number { color: $json-explorer-number-color; }
|
||||
.json-formatter-boolean { color: $json-explorer-boolean-color; }
|
||||
.json-formatter-null { color: $json-explorer-null-color; }
|
||||
.json-formatter-undefined { color: $json-explorer-undefined-color; }
|
||||
.json-formatter-function { color: $json-explorer-function-color; }
|
||||
.json-formatter-date { background-color: fade($json-explorer-default-color, 5%); }
|
||||
.json-formatter-url {
|
||||
text-decoration: underline;
|
||||
color: $json-explorer-url-color;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.json-formatter-bracket { color: $json-explorer-bracket-color; }
|
||||
.json-formatter-key {
|
||||
color: $json-explorer-key-color;
|
||||
cursor: pointer;
|
||||
padding-right: 0.2rem;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.json-formatter-constructor-name {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.json-formatter-array-comma { margin-right: 4px; }
|
||||
|
||||
.json-formatter-toggler {
|
||||
line-height: 1.2rem;
|
||||
font-size: 0.7rem;
|
||||
vertical-align: middle;
|
||||
opacity: $json-explorer-toggler-opacity;
|
||||
cursor: pointer;
|
||||
padding-right: 0.2rem;
|
||||
|
||||
&::after {
|
||||
display: inline-block;
|
||||
transition: transform $json-explorer-rotate-time ease-in;
|
||||
content: "►";
|
||||
}
|
||||
}
|
||||
|
||||
// Inline preview on hover (optional)
|
||||
> a > .json-formatter-preview-text {
|
||||
opacity: 0;
|
||||
transition: opacity .15s ease-in;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
&:hover > a > .json-formatter-preview-text {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
// Open state
|
||||
&.json-formatter-open {
|
||||
> .json-formatter-toggler-link .json-formatter-toggler::after{
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
> .json-formatter-children::after {
|
||||
display: inline-block;
|
||||
}
|
||||
> a > .json-formatter-preview-text {
|
||||
display: none;
|
||||
}
|
||||
&.json-formatter-empty::after {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
@import "variables";
|
||||
@import "variables.dark";
|
||||
@import "grafana";
|
||||
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
|
||||
img {
|
||||
width: 19px;
|
||||
vertical-align: sub;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
"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"
|
||||
"jquery.flot.dashes": "vendor/flot/jquery.flot.dashes",
|
||||
},
|
||||
|
||||
packages: {
|
||||
|
||||
@@ -1663,9 +1663,9 @@ glob@7.0.5:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@~7.0.0:
|
||||
version "7.0.6"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a"
|
||||
glob@^7.0.0, glob@^7.1.1, glob@~7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
@@ -1674,9 +1674,9 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@~7.0.0:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^7.1.1, glob@~7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
|
||||
glob@^7.0.3, glob@^7.0.5, glob@~7.0.0:
|
||||
version "7.0.6"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a"
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
@@ -3807,11 +3807,11 @@ resolve-pkg@^0.1.0:
|
||||
dependencies:
|
||||
resolve-from "^2.0.0"
|
||||
|
||||
resolve@1.1.x, resolve@^1.1.6, resolve@~1.1.0:
|
||||
resolve@1.1.x, resolve@~1.1.0:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
||||
|
||||
resolve@^1.3.2:
|
||||
resolve@^1.1.6, resolve@^1.3.2:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5"
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user