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"
|
# Use space to separate multiple modes, e.g. "console file"
|
||||||
;mode = 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
|
;level = info
|
||||||
|
|
||||||
# optional settings to set different levels for specific loggers. Ex filters = sqlstore:debug
|
# optional settings to set different levels for specific loggers. Ex filters = sqlstore:debug
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ graphite:
|
|||||||
- "8080:80"
|
- "8080:80"
|
||||||
- "2003:2003"
|
- "2003:2003"
|
||||||
volumes:
|
volumes:
|
||||||
- /var/docker/gfdev/graphite:/opt/graphite/storage/whisper
|
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
- /etc/timezone:/etc/timezone:ro
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,15 @@ parent = "http_api"
|
|||||||
"expires": 3600
|
"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**:
|
**Example Response**:
|
||||||
|
|
||||||
HTTP/1.1 200
|
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 {dashboardSelector} from './components/dashboard_selector';
|
||||||
import {queryPartEditorDirective} from './components/query_part/query_part_editor';
|
import {queryPartEditorDirective} from './components/query_part/query_part_editor';
|
||||||
import {WizardFlow} from './components/wizard/wizard';
|
import {WizardFlow} from './components/wizard/wizard';
|
||||||
|
import {formDropdownDirective} from './components/form_dropdown/form_dropdown';
|
||||||
import 'app/core/controllers/all';
|
import 'app/core/controllers/all';
|
||||||
import 'app/core/services/all';
|
import 'app/core/services/all';
|
||||||
import 'app/core/routes/routes';
|
import 'app/core/routes/routes';
|
||||||
@@ -45,6 +46,8 @@ import {assignModelProperties} from './utils/model_utils';
|
|||||||
import {contextSrv} from './services/context_srv';
|
import {contextSrv} from './services/context_srv';
|
||||||
import {KeybindingSrv} from './services/keybindingSrv';
|
import {KeybindingSrv} from './services/keybindingSrv';
|
||||||
import {helpModal} from './components/help/help';
|
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 {NavModelSrv, NavModel} from './nav_model_srv';
|
||||||
import {userPicker} from './components/user_picker';
|
import {userPicker} from './components/user_picker';
|
||||||
import {userGroupPicker} from './components/user_group_picker';
|
import {userGroupPicker} from './components/user_group_picker';
|
||||||
@@ -67,10 +70,13 @@ export {
|
|||||||
queryPartEditorDirective,
|
queryPartEditorDirective,
|
||||||
WizardFlow,
|
WizardFlow,
|
||||||
colors,
|
colors,
|
||||||
|
formDropdownDirective,
|
||||||
assignModelProperties,
|
assignModelProperties,
|
||||||
contextSrv,
|
contextSrv,
|
||||||
KeybindingSrv,
|
KeybindingSrv,
|
||||||
helpModal,
|
helpModal,
|
||||||
|
collapseBox,
|
||||||
|
JsonExplorer,
|
||||||
NavModelSrv,
|
NavModelSrv,
|
||||||
NavModel,
|
NavModel,
|
||||||
userPicker,
|
userPicker,
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ function ($, angular, coreModule) {
|
|||||||
options.html = editViewMap[options.editview].html;
|
options.html = editViewMap[options.editview].html;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastEditView === options.editview) {
|
if (lastEditView && lastEditView === options.editview) {
|
||||||
hideEditorPane(false);
|
hideEditorPane(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
define([
|
define([
|
||||||
'angular',
|
'angular',
|
||||||
|
'require',
|
||||||
'../core_module',
|
'../core_module',
|
||||||
'app/core/utils/kbn',
|
'app/core/utils/kbn',
|
||||||
],
|
],
|
||||||
function (angular, coreModule, kbn) {
|
function (angular, require, coreModule, kbn) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
coreModule.default.directive('tip', function($compile) {
|
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) {
|
coreModule.default.directive('compile', function($compile) {
|
||||||
return {
|
return {
|
||||||
restrict: 'A',
|
restrict: 'A',
|
||||||
@@ -77,10 +101,10 @@ function (angular, coreModule, kbn) {
|
|||||||
text + tip + '</label>';
|
text + tip + '</label>';
|
||||||
|
|
||||||
var template =
|
var template =
|
||||||
'<input class="cr1" id="' + scope.$id + model + '" type="checkbox" ' +
|
'<input class="cr1" id="' + scope.$id + model + '" type="checkbox" ' +
|
||||||
' ng-model="' + model + '"' + ngchange +
|
' ng-model="' + model + '"' + ngchange +
|
||||||
' ng-checked="' + model + '"></input>' +
|
' ng-checked="' + model + '"></input>' +
|
||||||
' <label for="' + scope.$id + model + '" class="cr1"></label>';
|
' <label for="' + scope.$id + model + '" class="cr1"></label>';
|
||||||
|
|
||||||
template = template + label;
|
template = template + label;
|
||||||
elem.addClass('gf-form-checkbox');
|
elem.addClass('gf-form-checkbox');
|
||||||
@@ -105,7 +129,7 @@ function (angular, coreModule, kbn) {
|
|||||||
var li = '<li' + (item.submenu && item.submenu.length ? ' class="dropdown-submenu"' : '') + '>' +
|
var li = '<li' + (item.submenu && item.submenu.length ? ' class="dropdown-submenu"' : '') + '>' +
|
||||||
'<a tabindex="-1" ng-href="' + (item.href || '') + '"' + (item.click ? ' ng-click="' + item.click + '"' : '') +
|
'<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.target ? ' target="' + item.target + '"' : '') + (item.method ? ' data-method="' + item.method + '"' : '') +
|
||||||
'>' + (item.text || '') + '</a>';
|
'>' + (item.text || '') + '</a>';
|
||||||
|
|
||||||
if (item.submenu && item.submenu.length) {
|
if (item.submenu && item.submenu.length) {
|
||||||
li += buildTemplate(item.submenu).join('\n');
|
li += buildTemplate(item.submenu).join('\n');
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $
|
|||||||
baseUrl: ds.meta.baseUrl,
|
baseUrl: ds.meta.baseUrl,
|
||||||
name: 'query-ctrl-' + ds.meta.id,
|
name: 'query-ctrl-' + ds.meta.id,
|
||||||
bindings: {target: "=", panelCtrl: "=", datasource: "="},
|
bindings: {target: "=", panelCtrl: "=", datasource: "="},
|
||||||
attrs: {"target": "target", "panel-ctrl": "ctrl", datasource: "datasource"},
|
attrs: {"target": "target", "panel-ctrl": "ctrl.panelCtrl", datasource: "datasource"},
|
||||||
Component: dsModule.QueryCtrl
|
Component: dsModule.QueryCtrl
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -127,7 +127,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $
|
|||||||
baseUrl: ds.meta.baseUrl,
|
baseUrl: ds.meta.baseUrl,
|
||||||
name: 'query-options-ctrl-' + ds.meta.id,
|
name: 'query-options-ctrl-' + ds.meta.id,
|
||||||
bindings: {panelCtrl: "="},
|
bindings: {panelCtrl: "="},
|
||||||
attrs: {"panel-ctrl": "ctrl"},
|
attrs: {"panel-ctrl": "ctrl.panelCtrl"},
|
||||||
Component: dsModule.QueryOptionsCtrl
|
Component: dsModule.QueryOptionsCtrl
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import angular from 'angular';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
import coreModule from 'app/core/core_module';
|
import coreModule from 'app/core/core_module';
|
||||||
|
import appEvents from 'app/core/app_events';
|
||||||
|
|
||||||
export class BackendSrv {
|
export class BackendSrv {
|
||||||
inFlightRequests = {};
|
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) {
|
if (err.status === this.HTTP_REQUEST_CANCELLED) {
|
||||||
throw {err, cancelled: true};
|
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) {
|
if (_.isString(err.data) && err.status === 500) {
|
||||||
err.data = {
|
err.data = {
|
||||||
error: err.statusText,
|
error: err.statusText,
|
||||||
@@ -179,7 +183,9 @@ export class BackendSrv {
|
|||||||
err.data.message = err.data.error;
|
err.data.message = err.data.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
appEvents.emit('ds-request-error', err);
|
||||||
throw err;
|
throw err;
|
||||||
|
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
// clean up
|
// clean up
|
||||||
if (options.requestId) {
|
if (options.requestId) {
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export class DashboardExporter {
|
|||||||
templateizeDatasourceUsage(variable);
|
templateizeDatasourceUsage(variable);
|
||||||
variable.options = [];
|
variable.options = [];
|
||||||
variable.current = {};
|
variable.current = {};
|
||||||
variable.refresh = 1;
|
variable.refresh = variable.refresh > 0 ? variable.refresh : 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export class HistoryListCtrl {
|
|||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
constructor(private $scope,
|
constructor(private $scope,
|
||||||
|
private $route,
|
||||||
private $rootScope,
|
private $rootScope,
|
||||||
private $location,
|
private $location,
|
||||||
private $window,
|
private $window,
|
||||||
@@ -179,6 +180,7 @@ export class HistoryListCtrl {
|
|||||||
this.loading = true;
|
this.loading = true;
|
||||||
return this.historySrv.restoreDashboard(this.dashboard, version).then(response => {
|
return this.historySrv.restoreDashboard(this.dashboard, version).then(response => {
|
||||||
this.$location.path('dashboard/db/' + response.slug);
|
this.$location.path('dashboard/db/' + response.slug);
|
||||||
|
this.$route.reload();
|
||||||
this.$rootScope.appEvent('alert-success', ['Dashboard restored', 'Restored from version ' + version]);
|
this.$rootScope.appEvent('alert-success', ['Dashboard restored', 'Restored from version ' + version]);
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.mode = 'list';
|
this.mode = 'list';
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
<input type="text" data-share-panel-url class="gf-form-input" ng-model="shareUrl"></input>
|
<input type="text" data-share-panel-url class="gf-form-input" ng-model="shareUrl"></input>
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -143,7 +143,7 @@
|
|||||||
{{snapshotUrl}}
|
{{snapshotUrl}}
|
||||||
</a>
|
</a>
|
||||||
<br>
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,10 +2,9 @@ define(['angular',
|
|||||||
'lodash',
|
'lodash',
|
||||||
'jquery',
|
'jquery',
|
||||||
'moment',
|
'moment',
|
||||||
'require',
|
|
||||||
'app/core/config',
|
'app/core/config',
|
||||||
],
|
],
|
||||||
function (angular, _, $, moment, require, config) {
|
function (angular, _, $, moment, config) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var module = angular.module('grafana.controllers');
|
var module = angular.module('grafana.controllers');
|
||||||
@@ -89,20 +88,10 @@ function (angular, _, $, moment, require, config) {
|
|||||||
$scope.imageUrl += '&tz=UTC' + encodeURIComponent(moment().format("Z"));
|
$scope.imageUrl += '&tz=UTC' + encodeURIComponent(moment().format("Z"));
|
||||||
};
|
};
|
||||||
|
|
||||||
});
|
$scope.getShareUrl = function() {
|
||||||
|
return $scope.shareUrl;
|
||||||
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();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -96,6 +96,10 @@ function (angular, _) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.getSnapshotUrl = function() {
|
||||||
|
return $scope.snapshotUrl;
|
||||||
|
};
|
||||||
|
|
||||||
$scope.scrubDashboard = function(dash) {
|
$scope.scrubDashboard = function(dash) {
|
||||||
// change title
|
// change title
|
||||||
dash.title = $scope.snapshot.name;
|
dash.title = $scope.snapshot.name;
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ define([
|
|||||||
'./query_ctrl',
|
'./query_ctrl',
|
||||||
'./panel_editor_tab',
|
'./panel_editor_tab',
|
||||||
'./query_editor_row',
|
'./query_editor_row',
|
||||||
'./metrics_ds_selector',
|
'./query_troubleshooter',
|
||||||
], function () {});
|
], 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" />
|
///<reference path="../../headers/common.d.ts" />
|
||||||
|
|
||||||
|
import angular from 'angular';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
@@ -10,6 +11,7 @@ import * as rangeUtil from 'app/core/utils/rangeutil';
|
|||||||
import * as dateMath from 'app/core/utils/datemath';
|
import * as dateMath from 'app/core/utils/datemath';
|
||||||
|
|
||||||
import {Subject} from 'vendor/npm/rxjs/Subject';
|
import {Subject} from 'vendor/npm/rxjs/Subject';
|
||||||
|
import {metricsTabDirective} from './metrics_tab';
|
||||||
|
|
||||||
class MetricsPanelCtrl extends PanelCtrl {
|
class MetricsPanelCtrl extends PanelCtrl {
|
||||||
scope: any;
|
scope: any;
|
||||||
@@ -32,6 +34,7 @@ class MetricsPanelCtrl extends PanelCtrl {
|
|||||||
dataStream: any;
|
dataStream: any;
|
||||||
dataSubscription: any;
|
dataSubscription: any;
|
||||||
dataList: any;
|
dataList: any;
|
||||||
|
nextRefId: string;
|
||||||
|
|
||||||
constructor($scope, $injector) {
|
constructor($scope, $injector) {
|
||||||
super($scope, $injector);
|
super($scope, $injector);
|
||||||
@@ -61,7 +64,7 @@ class MetricsPanelCtrl extends PanelCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onInitMetricsPanelEditMode() {
|
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');
|
this.addEditorTab('Time range', 'public/app/features/panel/partials/panelTime.html');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +259,7 @@ class MetricsPanelCtrl extends PanelCtrl {
|
|||||||
result = {data: []};
|
result = {data: []};
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.events.emit('data-received', result.data);
|
this.events.emit('data-received', result.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDataStream(stream) {
|
handleDataStream(stream) {
|
||||||
@@ -306,6 +309,25 @@ class MetricsPanelCtrl extends PanelCtrl {
|
|||||||
this.datasource = null;
|
this.datasource = null;
|
||||||
this.refresh();
|
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};
|
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() {
|
refresh() {
|
||||||
this.events.emit('refresh', null);
|
this.events.emit('refresh', null);
|
||||||
}
|
}
|
||||||
|
|
||||||
publishAppEvent(evtName, evt) {
|
publishAppEvent(evtName, evt) {
|
||||||
|
|||||||
@@ -16,10 +16,15 @@ function panelEditorTab(dynamicDirectiveSrv) {
|
|||||||
directive: scope => {
|
directive: scope => {
|
||||||
var pluginId = scope.ctrl.pluginId;
|
var pluginId = scope.ctrl.pluginId;
|
||||||
var tabIndex = scope.index;
|
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({
|
return Promise.resolve({
|
||||||
name: `panel-editor-tab-${pluginId}${tabIndex}`,
|
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;
|
this.panel = this.panelCtrl.panel;
|
||||||
|
|
||||||
if (!this.target.refId) {
|
if (!this.target.refId) {
|
||||||
this.target.refId = this.getNextQueryLetter();
|
this.target.refId = this.panelCtrl.dashboard.getNextQueryLetter(this.panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.toggleCollapse(true);
|
this.toggleCollapse(true);
|
||||||
@@ -40,16 +40,6 @@ export class QueryRowCtrl {
|
|||||||
this.panelCtrl.refresh();
|
this.panelCtrl.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
getNextQueryLetter() {
|
|
||||||
var letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
||||||
|
|
||||||
return _.find(letters, refId => {
|
|
||||||
return _.every(this.panel.targets, function(other) {
|
|
||||||
return other.refId !== refId;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleCollapse(init) {
|
toggleCollapse(init) {
|
||||||
if (!this.canCollapse) {
|
if (!this.canCollapse) {
|
||||||
return;
|
return;
|
||||||
@@ -87,19 +77,16 @@ export class QueryRowCtrl {
|
|||||||
delete this.panelCtrl.__collapsedQueryCache[this.target.refId];
|
delete this.panelCtrl.__collapsedQueryCache[this.target.refId];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.panel.targets = _.without(this.panel.targets, this.target);
|
this.panelCtrl.removeQuery(this.target);
|
||||||
this.panelCtrl.refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
duplicateQuery() {
|
duplicateQuery() {
|
||||||
var clone = angular.copy(this.target);
|
var clone = angular.copy(this.target);
|
||||||
clone.refId = this.getNextQueryLetter();
|
this.panelCtrl.addQuery(clone);
|
||||||
this.panel.targets.push(clone);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
moveQuery(direction) {
|
moveQuery(direction) {
|
||||||
var index = _.indexOf(this.panel.targets, this.target);
|
this.panelCtrl.moveQuery(this.target, direction);
|
||||||
_.move(this.panel.targets, index, index + 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;
|
var d3: any;
|
||||||
export default d3;
|
export default d3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
GitHub
|
GitHub
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-large btn-grafana-com" href="login/grafana_com" target="_self" ng-if="oauth.grafana_com">
|
<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>
|
<span>Grafana.com</span>
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-large btn-generic-oauth" href="login/generic_oauth" target="_self" ng-if="oauth.generic_oauth">
|
<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;
|
var bucketAggs = $scope.target.bucketAggs;
|
||||||
|
|
||||||
$scope.orderByOptions = [];
|
$scope.orderByOptions = [];
|
||||||
$scope.bucketAggTypes = queryDef.bucketAggTypes;
|
|
||||||
$scope.orderOptions = queryDef.orderOptions;
|
$scope.getBucketAggTypes = function() {
|
||||||
$scope.sizeOptions = queryDef.sizeOptions;
|
return queryDef.bucketAggTypes;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.getOrderOptions = function() {
|
||||||
|
return queryDef.orderOptions;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.getSizeOptions = function() {
|
||||||
|
return queryDef.sizeOptions;
|
||||||
|
};
|
||||||
|
|
||||||
$rootScope.onAppEvent('elastic-query-updated', function() {
|
$rootScope.onAppEvent('elastic-query-updated', function() {
|
||||||
$scope.validateModel();
|
$scope.validateModel();
|
||||||
$scope.updateOrderByOptions();
|
|
||||||
}, $scope);
|
}, $scope);
|
||||||
|
|
||||||
$scope.init = function() {
|
$scope.init = function() {
|
||||||
@@ -166,11 +174,10 @@ function (angular, _, queryDef) {
|
|||||||
|
|
||||||
$scope.toggleOptions = function() {
|
$scope.toggleOptions = function() {
|
||||||
$scope.showOptions = !$scope.showOptions;
|
$scope.showOptions = !$scope.showOptions;
|
||||||
$scope.updateOrderByOptions();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.updateOrderByOptions = function() {
|
$scope.getOrderByOptions = function() {
|
||||||
$scope.orderByOptions = queryDef.getOrderByOptions($scope.target);
|
return queryDef.getOrderByOptions($scope.target);
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.getFieldsInternal = function() {
|
$scope.getFieldsInternal = function() {
|
||||||
|
|||||||
@@ -5,8 +5,22 @@
|
|||||||
<span ng-hide="isFirst">Then by</span>
|
<span ng-hide="isFirst">Then by</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<metric-segment-model property="agg.type" options="bucketAggTypes" on-change="onTypeChanged()" custom="false" css-class="width-10"></metric-segment-model>
|
<gf-form-dropdown model="agg.type"
|
||||||
<metric-segment-model ng-if="agg.field" property="agg.field" get-options="getFieldsInternal()" on-change="onChange()" css-class="width-12"></metric-segment-model>
|
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>
|
||||||
|
|
||||||
<div class="gf-form gf-form--grow">
|
<div class="gf-form gf-form--grow">
|
||||||
@@ -33,7 +47,13 @@
|
|||||||
<div ng-if="agg.type === 'date_histogram'">
|
<div ng-if="agg.type === 'date_histogram'">
|
||||||
<div class="gf-form offset-width-7">
|
<div class="gf-form offset-width-7">
|
||||||
<label class="gf-form-label width-10">Interval</label>
|
<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>
|
||||||
|
|
||||||
<div class="gf-form offset-width-7">
|
<div class="gf-form offset-width-7">
|
||||||
@@ -66,11 +86,23 @@
|
|||||||
<div ng-if="agg.type === 'terms'">
|
<div ng-if="agg.type === 'terms'">
|
||||||
<div class="gf-form offset-width-7">
|
<div class="gf-form offset-width-7">
|
||||||
<label class="gf-form-label width-10">Order</label>
|
<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>
|
||||||
<div class="gf-form offset-width-7">
|
<div class="gf-form offset-width-7">
|
||||||
<label class="gf-form-label width-10">Size</label>
|
<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>
|
||||||
<div class="gf-form offset-width-7">
|
<div class="gf-form offset-width-7">
|
||||||
<label class="gf-form-label width-10">Min Doc Count</label>
|
<label class="gf-form-label width-10">Min Doc Count</label>
|
||||||
@@ -78,7 +110,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="gf-form offset-width-7">
|
<div class="gf-form offset-width-7">
|
||||||
<label class="gf-form-label width-10">Order By</label>
|
<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>
|
||||||
<div class="gf-form offset-width-7">
|
<div class="gf-form offset-width-7">
|
||||||
<label class="gf-form-label width-10">
|
<label class="gf-form-label width-10">
|
||||||
|
|||||||
@@ -31,11 +31,11 @@ export class ElasticQueryCtrl extends QueryCtrl {
|
|||||||
|
|
||||||
queryUpdated() {
|
queryUpdated() {
|
||||||
var newJson = angular.toJson(this.datasource.queryBuilder.build(this.target), true);
|
var newJson = angular.toJson(this.datasource.queryBuilder.build(this.target), true);
|
||||||
if (newJson !== this.rawQueryOld) {
|
if (this.rawQueryOld && newJson !== this.rawQueryOld) {
|
||||||
this.rawQueryOld = newJson;
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.rawQueryOld = newJson;
|
||||||
this.$rootScope.appEvent('elastic-query-updated');
|
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-inline">
|
||||||
<div class="gf-form max-width-15">
|
<div class="gf-form max-width-15">
|
||||||
<span class="gf-form-label width-8">
|
<span class="gf-form-label width-8">
|
||||||
|
|||||||
@@ -210,10 +210,12 @@ export default class InfluxDatasource {
|
|||||||
var currentUrl = self.urls.shift();
|
var currentUrl = self.urls.shift();
|
||||||
self.urls.push(currentUrl);
|
self.urls.push(currentUrl);
|
||||||
|
|
||||||
var params: any = {
|
var params: any = {};
|
||||||
u: self.username,
|
|
||||||
p: self.password,
|
if (self.username) {
|
||||||
};
|
params.username = self.username;
|
||||||
|
params.password = self.password;
|
||||||
|
}
|
||||||
|
|
||||||
if (self.database) {
|
if (self.database) {
|
||||||
params.db = self.database;
|
params.db = self.database;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ System.config({
|
|||||||
"jquery.flot.fillbelow": "vendor/flot/jquery.flot.fillbelow",
|
"jquery.flot.fillbelow": "vendor/flot/jquery.flot.fillbelow",
|
||||||
"jquery.flot.gauge": "vendor/flot/jquery.flot.gauge",
|
"jquery.flot.gauge": "vendor/flot/jquery.flot.gauge",
|
||||||
"d3": "vendor/d3/d3.js",
|
"d3": "vendor/d3/d3.js",
|
||||||
"jquery.flot.dashes": "vendor/flot/jquery.flot.dashes"
|
"jquery.flot.dashes": "vendor/flot/jquery.flot.dashes",
|
||||||
},
|
},
|
||||||
|
|
||||||
packages: {
|
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"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
<!-- Generator: Adobe Illustrator 20.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"
|
<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"
|
||||||
height="365px" viewBox="0 0 351 365" style="enable-background:new 0 0 351 365;" xml:space="preserve">
|
width="351px" height="365px" viewBox="0 0 351 365" style="enable-background:new 0 0 351 365;" xml:space="preserve">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.st0{fill:url(#SVGID_1_);}
|
.st0{fill:url(#SVGID_1_);}
|
||||||
</style>
|
</style>
|
||||||
<g id="Layer_1">
|
<g id="Layer_1_1_">
|
||||||
</g>
|
</g>
|
||||||
<g id="Layer_2">
|
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="175.5" y1="445.4948" x2="175.5" y2="114.0346">
|
||||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="170.963" y1="439.9414" x2="170.963" y2="106.0154">
|
<stop offset="0" style="stop-color:#FFF100"/>
|
||||||
<stop offset="0" style="stop-color:#FFF200"/>
|
<stop offset="1" style="stop-color:#F05A28"/>
|
||||||
<stop offset="1" style="stop-color:#F15A29"/>
|
</linearGradient>
|
||||||
</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
|
||||||
<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-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-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-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-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-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-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
|
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
|
||||||
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
|
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
|
||||||
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
|
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
|
||||||
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
|
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.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
|
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.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
|
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
|
||||||
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
|
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
|
||||||
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-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
|
||||||
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.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
|
||||||
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
|
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
|
||||||
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
|
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
|
||||||
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
|
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
|
||||||
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
|
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
|
||||||
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
|
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.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
|
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
|
||||||
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
|
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
|
||||||
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
|
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
|
||||||
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
|
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
|
||||||
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
|
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
|
||||||
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-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
|
||||||
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
|
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
|
||||||
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
|
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
|
||||||
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
|
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
|
||||||
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
|
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-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-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-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
|
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
|
||||||
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
|
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
|
||||||
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
|
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
|
||||||
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
|
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
|
||||||
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.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
|
||||||
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
|
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
|
||||||
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
|
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
|
||||||
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
|
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
|
||||||
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
|
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
|
||||||
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
|
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
|
||||||
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
|
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.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.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.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.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.4-0.3,0.9-0.6,1.3-1C229.9,243.8,230.1,241.4,228.8,239.8L228.8,239.8z"/>
|
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"/>
|
||||||
</g>
|
</svg>
|
||||||
</svg>
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
@@ -76,6 +76,8 @@
|
|||||||
@import "components/jsontree";
|
@import "components/jsontree";
|
||||||
@import "components/edit_sidemenu.scss";
|
@import "components/edit_sidemenu.scss";
|
||||||
@import "components/row.scss";
|
@import "components/row.scss";
|
||||||
|
@import "components/json_explorer.scss";
|
||||||
|
@import "components/collapse_box.scss";
|
||||||
|
|
||||||
// PAGES
|
// PAGES
|
||||||
@import "pages/login";
|
@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-color: $gray-1;
|
||||||
$footer-link-hover: $gray-4;
|
$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
|
// 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-color: $gray-3;
|
||||||
$footer-link-hover: $dark-5;
|
$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
|
// 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;
|
padding: $input-padding-y $input-padding-x;
|
||||||
margin-right: $gf-form-margin;
|
margin-right: $gf-form-margin;
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
|
margin-right: $gf-form-margin;
|
||||||
line-height: $input-line-height;
|
line-height: $input-line-height;
|
||||||
color: $input-color;
|
color: $input-color;
|
||||||
background-color: $input-bg;
|
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";
|
||||||
@import "variables.dark";
|
@import "variables.dark";
|
||||||
@import "grafana";
|
@import "grafana";
|
||||||
|
|
||||||
|
|||||||
@@ -119,6 +119,7 @@
|
|||||||
|
|
||||||
img {
|
img {
|
||||||
width: 19px;
|
width: 19px;
|
||||||
|
vertical-align: sub;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
"jquery.flot.fillbelow": "vendor/flot/jquery.flot.fillbelow",
|
"jquery.flot.fillbelow": "vendor/flot/jquery.flot.fillbelow",
|
||||||
"jquery.flot.gauge": "vendor/flot/jquery.flot.gauge",
|
"jquery.flot.gauge": "vendor/flot/jquery.flot.gauge",
|
||||||
"d3": "vendor/d3/d3.js",
|
"d3": "vendor/d3/d3.js",
|
||||||
"jquery.flot.dashes": "vendor/flot/jquery.flot.dashes"
|
"jquery.flot.dashes": "vendor/flot/jquery.flot.dashes",
|
||||||
},
|
},
|
||||||
|
|
||||||
packages: {
|
packages: {
|
||||||
|
|||||||
@@ -1663,9 +1663,9 @@ glob@7.0.5:
|
|||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
path-is-absolute "^1.0.0"
|
path-is-absolute "^1.0.0"
|
||||||
|
|
||||||
glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@~7.0.0:
|
glob@^7.0.0, glob@^7.1.1, glob@~7.1.1:
|
||||||
version "7.0.6"
|
version "7.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a"
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
|
||||||
dependencies:
|
dependencies:
|
||||||
fs.realpath "^1.0.0"
|
fs.realpath "^1.0.0"
|
||||||
inflight "^1.0.4"
|
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"
|
once "^1.3.0"
|
||||||
path-is-absolute "^1.0.0"
|
path-is-absolute "^1.0.0"
|
||||||
|
|
||||||
glob@^7.1.1, glob@~7.1.1:
|
glob@^7.0.3, glob@^7.0.5, glob@~7.0.0:
|
||||||
version "7.1.1"
|
version "7.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a"
|
||||||
dependencies:
|
dependencies:
|
||||||
fs.realpath "^1.0.0"
|
fs.realpath "^1.0.0"
|
||||||
inflight "^1.0.4"
|
inflight "^1.0.4"
|
||||||
@@ -3807,11 +3807,11 @@ resolve-pkg@^0.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
resolve-from "^2.0.0"
|
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"
|
version "1.1.7"
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
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"
|
version "1.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5"
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user