mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
ux: popover forms
This commit is contained in:
26
pkg/services/sqlstore/migrations/annotation_category_mig.go
Normal file
26
pkg/services/sqlstore/migrations/annotation_category_mig.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func addAnnotationCategoryMig(mg *Migrator) {
|
||||||
|
category := Table{
|
||||||
|
Name: "annotation_category",
|
||||||
|
Columns: []*Column{
|
||||||
|
{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
|
||||||
|
{Name: "org_id", Type: DB_BigInt, Nullable: false},
|
||||||
|
{Name: "user_id", Type: DB_BigInt, Nullable: true},
|
||||||
|
{Name: "name", Type: DB_Text, Nullable: false},
|
||||||
|
},
|
||||||
|
Indices: []*Index{
|
||||||
|
{Cols: []string{"org_id", "name"}, Type: IndexType},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// create table
|
||||||
|
mg.AddMigration("create annotation_category table", NewAddTableMigration(category))
|
||||||
|
|
||||||
|
// create indices
|
||||||
|
mg.AddMigration("add index org_id & name", NewAddIndexMigration(category, category.Indices[0]))
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ func AddMigrations(mg *Migrator) {
|
|||||||
addAnnotationMig(mg)
|
addAnnotationMig(mg)
|
||||||
addStatsMigrations(mg)
|
addStatsMigrations(mg)
|
||||||
addTestDataMigrations(mg)
|
addTestDataMigrations(mg)
|
||||||
|
// addAnnotationCategoryMig(mg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func addMigrationLogMigrations(mg *Migrator) {
|
func addMigrationLogMigrations(mg *Migrator) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
define([
|
define([
|
||||||
'./panellinks/module',
|
'./panellinks/module',
|
||||||
'./dashlinks/module',
|
'./dashlinks/module',
|
||||||
'./annotations/annotations_srv',
|
'./annotations/all',
|
||||||
'./templating/all',
|
'./templating/all',
|
||||||
'./dashboard/all',
|
'./dashboard/all',
|
||||||
'./playlist/all',
|
'./playlist/all',
|
||||||
|
|||||||
8
public/app/features/annotations/all.ts
Normal file
8
public/app/features/annotations/all.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
import {AnnotationsSrv} from './annotations_srv';
|
||||||
|
import {eventEditor} from './event_editor';
|
||||||
|
|
||||||
|
export {
|
||||||
|
AnnotationsSrv,
|
||||||
|
eventEditor
|
||||||
|
};
|
||||||
@@ -60,7 +60,7 @@ export class AnnotationsSrv {
|
|||||||
var panel = options.panel;
|
var panel = options.panel;
|
||||||
var dashboard = options.dashboard;
|
var dashboard = options.dashboard;
|
||||||
|
|
||||||
if (panel && panel.alert) {
|
if (panel) {
|
||||||
return this.backendSrv.get('/api/annotations', {
|
return this.backendSrv.get('/api/annotations', {
|
||||||
from: options.range.from.valueOf(),
|
from: options.range.from.valueOf(),
|
||||||
to: options.range.to.valueOf(),
|
to: options.range.to.valueOf(),
|
||||||
@@ -133,10 +133,8 @@ export class AnnotationsSrv {
|
|||||||
return this.globalAnnotationsPromise;
|
return this.globalAnnotationsPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
postAnnotation(annotations) {
|
postAnnotation(annotation) {
|
||||||
return Promise.all(_.map(annotations, annotation => {
|
return this.backendSrv.post('/api/annotations', annotation);
|
||||||
return this.backendSrv.post('/api/annotations', annotation);
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
translateQueryResult(annotation, results) {
|
translateQueryResult(annotation, results) {
|
||||||
|
|||||||
60
public/app/features/annotations/event_editor.ts
Normal file
60
public/app/features/annotations/event_editor.ts
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
///<reference path="../../headers/common.d.ts" />
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
import moment from 'moment';
|
||||||
|
import coreModule from 'app/core/core_module';
|
||||||
|
import {MetricsPanelCtrl} from 'app/plugins/sdk';
|
||||||
|
|
||||||
|
export class AnnotationItem {
|
||||||
|
dashboardId: number;
|
||||||
|
panelId: number;
|
||||||
|
time: Date;
|
||||||
|
timeEnd: Date;
|
||||||
|
isRegion: boolean;
|
||||||
|
title: string;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class EventEditorCtrl {
|
||||||
|
panelCtrl: MetricsPanelCtrl;
|
||||||
|
timeFormat = 'YYYY-MM-DD HH:mm:ss';
|
||||||
|
annotation: AnnotationItem;
|
||||||
|
timeRange: {from: number, to: number};
|
||||||
|
form: any;
|
||||||
|
|
||||||
|
/** @ngInject **/
|
||||||
|
constructor() {
|
||||||
|
this.annotation = new AnnotationItem();
|
||||||
|
this.annotation.panelId = this.panelCtrl.panel.id;
|
||||||
|
this.annotation.dashboardId = this.panelCtrl.dashboard.id;
|
||||||
|
this.annotation.text = "hello";
|
||||||
|
|
||||||
|
this.annotation.time = moment(this.timeRange.from);
|
||||||
|
if (this.timeRange.to) {
|
||||||
|
this.annotation.timeEnd = moment(this.timeRange.to);
|
||||||
|
this.annotation.isRegion = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
if (!this.form.$valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function eventEditor() {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
controller: EventEditorCtrl,
|
||||||
|
bindToController: true,
|
||||||
|
controllerAs: 'ctrl',
|
||||||
|
templateUrl: 'public/app/features/annotations/partials/event_editor.html',
|
||||||
|
scope: {
|
||||||
|
"panelCtrl": "=",
|
||||||
|
"timeRange": "="
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
coreModule.directive('eventEditor', eventEditor);
|
||||||
39
public/app/features/annotations/partials/event_editor.html
Normal file
39
public/app/features/annotations/partials/event_editor.html
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
<h5 class="section-heading text-center">Add annotation</h5>
|
||||||
|
|
||||||
|
<form name="ctrl.form" class="text-center">
|
||||||
|
<div class="gf-form-group" style="display: inline-block">
|
||||||
|
<div class="gf-form">
|
||||||
|
<span class="gf-form-label width-7">Title</span>
|
||||||
|
<input type="text" ng-model="ctrl.annotation.title" class="gf-form-input max-width-20" required>
|
||||||
|
</div>
|
||||||
|
<!-- single event -->
|
||||||
|
<div ng-if="!ctrl.annotation.isRegion">
|
||||||
|
<div class="gf-form-inline">
|
||||||
|
<div class="gf-form">
|
||||||
|
<span class="gf-form-label width-7">Time</span>
|
||||||
|
<input type="text" ng-model="ctrl.annotation.time" class="gf-form-input max-width-20" input-datetime required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- region event -->
|
||||||
|
<div ng-if="ctrl.annotation.isRegion">
|
||||||
|
<div class="gf-form">
|
||||||
|
<span class="gf-form-label width-7">Start</span>
|
||||||
|
<input type="text" ng-model="ctrl.annotation.time" class="gf-form-input max-width-20" input-datetime required>
|
||||||
|
</div>
|
||||||
|
<div class="gf-form">
|
||||||
|
<span class="gf-form-label width-7">End</span>
|
||||||
|
<input type="text" ng-model="ctrl.annotation.timeEnd" class="gf-form-input max-width-20" input-datetime required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="gf-form gf-form--v-stretch">
|
||||||
|
<span class="gf-form-label width-7">Description</span>
|
||||||
|
<textarea class="gf-form-input width-20" rows="3" ng-model="ctrl.annotation.text" placeholder="Event description"></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form-button-row">
|
||||||
|
<button type="submit" class="btn gf-form-btn btn-success" ng-click="ctrl.save()">Save</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
@@ -4,12 +4,8 @@ import angular from 'angular';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
export class AddAnnotationModalCtrl {
|
export class AddAnnotationModalCtrl {
|
||||||
annotationTimeFormat = 'YYYY-MM-DD HH:mm:ss';
|
timeFormat = 'YYYY-MM-DD HH:mm:ss';
|
||||||
annotationTimeFrom: any;
|
annotation: any;
|
||||||
annotationTimeTo: any = null;
|
|
||||||
annotationTitle: string;
|
|
||||||
annotationTextFrom: string;
|
|
||||||
annotationTextTo: string;
|
|
||||||
graphCtrl: any;
|
graphCtrl: any;
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
@@ -17,41 +13,31 @@ export class AddAnnotationModalCtrl {
|
|||||||
this.graphCtrl = $scope.ctrl;
|
this.graphCtrl = $scope.ctrl;
|
||||||
$scope.ctrl = this;
|
$scope.ctrl = this;
|
||||||
|
|
||||||
this.annotationTimeFrom = moment($scope.annotationTimeRange.from).format(this.annotationTimeFormat);
|
let dashboardId = this.graphCtrl.dashboard.id;
|
||||||
|
let panelId = this.graphCtrl.panel.id;
|
||||||
|
this.annotation = {
|
||||||
|
dashboardId: dashboardId,
|
||||||
|
panelId: panelId,
|
||||||
|
time: null,
|
||||||
|
timeTo: null,
|
||||||
|
title: "",
|
||||||
|
text: ""
|
||||||
|
};
|
||||||
|
|
||||||
|
this.annotation.time = moment($scope.annotationTimeRange.from).format(this.timeFormat);0
|
||||||
if ($scope.annotationTimeRange.to) {
|
if ($scope.annotationTimeRange.to) {
|
||||||
this.annotationTimeTo = moment($scope.annotationTimeRange.to).format(this.annotationTimeFormat);
|
this.annotation.timeTo = moment($scope.annotationTimeRange.to).format(this.timeFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addAnnotation() {
|
addAnnotation() {
|
||||||
let dashboardId = this.graphCtrl.dashboard.id;
|
this.annotation.time = moment(this.annotation.time, this.timeFormat).valueOf();
|
||||||
let panelId = this.graphCtrl.panel.id;
|
if (this.annotation.timeTo) {
|
||||||
let timeFrom = moment(this.annotationTimeFrom, this.annotationTimeFormat).valueOf();
|
this.annotation.timeTo = moment(this.annotation.timeTo, this.timeFormat).valueOf();
|
||||||
|
|
||||||
let annotationFrom = {
|
|
||||||
dashboardId: dashboardId,
|
|
||||||
panelId: panelId,
|
|
||||||
time: timeFrom,
|
|
||||||
title: this.annotationTitle,
|
|
||||||
text: this.annotationTextFrom
|
|
||||||
};
|
|
||||||
let annotations = [annotationFrom];
|
|
||||||
|
|
||||||
if (this.annotationTimeTo) {
|
|
||||||
let timeTo = moment(this.annotationTimeTo, this.annotationTimeFormat).valueOf();
|
|
||||||
let annotationTo = {
|
|
||||||
dashboardId: dashboardId,
|
|
||||||
panelId: panelId,
|
|
||||||
time: timeTo,
|
|
||||||
title: this.annotationTitle,
|
|
||||||
text: this.annotationTextTo
|
|
||||||
};
|
|
||||||
annotations.push(annotationTo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.graphCtrl.pushAnnotations(annotations)
|
this.graphCtrl.pushAnnotation(this.annotation)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
console.log(response);
|
|
||||||
this.close();
|
this.close();
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|||||||
@@ -22,5 +22,4 @@ define([
|
|||||||
'./ad_hoc_filters',
|
'./ad_hoc_filters',
|
||||||
'./row/row_ctrl',
|
'./row/row_ctrl',
|
||||||
'./repeat_option/repeat_option',
|
'./repeat_option/repeat_option',
|
||||||
'./event_editor',
|
|
||||||
], function () {});
|
], function () {});
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
///<reference path="../../headers/common.d.ts" />
|
|
||||||
|
|
||||||
import _ from 'lodash';
|
|
||||||
import coreModule from 'app/core/core_module';
|
|
||||||
|
|
||||||
export class EventEditorCtrl {
|
|
||||||
/** @ngInject */
|
|
||||||
constructor() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function eventEditor() {
|
|
||||||
return {
|
|
||||||
restrict: 'E',
|
|
||||||
controller: EventEditorCtrl,
|
|
||||||
bindToController: true,
|
|
||||||
controllerAs: 'ctrl',
|
|
||||||
templateUrl: 'public/app/features/dashboard/partials/event_editor.html',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
coreModule.directive('eventEditor', eventEditor);
|
|
||||||
@@ -28,38 +28,25 @@
|
|||||||
|
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<span class="gf-form-label width-8">Title</span>
|
<span class="gf-form-label width-8">Title</span>
|
||||||
<input type="text" ng-model="ctrl.annotationTitle" class="gf-form-input max-width-20">
|
<input type="text" ng-model="ctrl.annotation.title" class="gf-form-input max-width-20">
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<span class="gf-form-label width-8" ng-if="!ctrl.annotationTimeTo">Time</span>
|
<span class="gf-form-label width-8" ng-if="!ctrl.annotation.timeTo">Time</span>
|
||||||
<span class="gf-form-label width-8" ng-if="ctrl.annotationTimeTo">Time Start</span>
|
<span class="gf-form-label width-8" ng-if="ctrl.annotation.timeTo">Time Start</span>
|
||||||
<input type="text" ng-model="ctrl.annotationTimeFrom" class="gf-form-input max-width-20">
|
<input type="text" ng-model="ctrl.annotation.time" class="gf-form-input max-width-20">
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form" ng-if="ctrl.annotationTimeTo">
|
<div class="gf-form" ng-if="ctrl.annotation.timeTo">
|
||||||
<span class="gf-form-label width-8">Time Stop</span>
|
<span class="gf-form-label width-8">Time Stop</span>
|
||||||
<input type="text" ng-model="ctrl.annotationTimeTo" class="gf-form-input max-width-20">
|
<input type="text" ng-model="ctrl.annotation.timeTo" class="gf-form-input max-width-20">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h6 ng-if="!ctrl.annotationTimeTo">Description</h6>
|
<h6>Description</h6>
|
||||||
<h6 ng-if="ctrl.annotationTimeTo">Description Start</h6>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form-group share-modal-options">
|
<div class="gf-form-group share-modal-options">
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<textarea rows="3" class="gf-form-input width-27" ng-model="ctrl.annotationTextFrom"></textarea>
|
<textarea rows="3" class="gf-form-input width-27" ng-model="ctrl.annotation.text"></textarea>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div ng-if="ctrl.annotationTimeTo">
|
|
||||||
<div>
|
|
||||||
<h6>Description Stop</h6>
|
|
||||||
</div>
|
|
||||||
<div class="gf-form-group share-modal-options">
|
|
||||||
<div class="gf-form">
|
|
||||||
<textarea rows="3" class="gf-form-input width-27" ng-model="ctrl.annotationTextTo"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
|
|
||||||
<h5 class="section-heading text-center">Create event</h5>
|
|
||||||
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="gf-form-group" style="display: inline-block">
|
|
||||||
<div class="gf-form">
|
|
||||||
<span class="gf-form-label width-7">Title</span>
|
|
||||||
<input type="text" ng-model="ctrl.event.title" class="gf-form-input max-width-20">
|
|
||||||
</div>
|
|
||||||
<div class="gf-form">
|
|
||||||
<span class="gf-form-label width-7">Time</span>
|
|
||||||
<input type="text" ng-model="ctrl.event.time" class="gf-form-input max-width-20">
|
|
||||||
</div>
|
|
||||||
<div class="gf-form" ng-if="ctrl.event.isRegion">
|
|
||||||
<span class="gf-form-label width-7">To</span>
|
|
||||||
<input type="text" ng-model="ctrl.event.endTime" class="gf-form-input max-width-20">
|
|
||||||
</div>
|
|
||||||
<div class="gf-form gf-form--v-stretch">
|
|
||||||
<span class="gf-form-label width-7">Description</span>
|
|
||||||
<textarea class="gf-form-input width-20" rows="3" ng-model="ctrl.event.description" placeholder="Event description"></textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gf-form-button-row">
|
|
||||||
<button class="btn gf-form-btn btn-success" ng-click="ctrl.addAnnotation()">Save</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -79,29 +79,13 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
|
|||||||
}
|
}
|
||||||
}, scope);
|
}, scope);
|
||||||
|
|
||||||
appEvents.on('graph-click', (event) => {
|
|
||||||
// Add event only for selected panel
|
|
||||||
let thisPanelEvent = event.panel.id === ctrl.panel.id;
|
|
||||||
|
|
||||||
// Select time for new annotation
|
|
||||||
let createAnnotation = event.pos.ctrlKey || event.pos.metaKey;
|
|
||||||
if (createAnnotation && thisPanelEvent) {
|
|
||||||
let timeRange = {
|
|
||||||
from: event.pos.x,
|
|
||||||
to: null
|
|
||||||
};
|
|
||||||
|
|
||||||
showAddAnnotationView(timeRange);
|
|
||||||
}
|
|
||||||
}, scope);
|
|
||||||
|
|
||||||
function showAddAnnotationView(timeRange) {
|
function showAddAnnotationView(timeRange) {
|
||||||
popoverSrv.show({
|
popoverSrv.show({
|
||||||
element: elem[0],
|
element: elem[0],
|
||||||
classNames: 'drop-popover drop-popover--form',
|
classNames: 'drop-popover drop-popover--form',
|
||||||
position: 'bottom center',
|
position: 'bottom center',
|
||||||
openOn: 'click',
|
openOn: 'click',
|
||||||
template: '<event-editor panelCtrl="ctrl" timeRange="timeRange"></event-editor>',
|
template: '<event-editor panel-ctrl="panelCtrl" time-range="timeRange"></event-editor>',
|
||||||
model: {
|
model: {
|
||||||
timeRange: timeRange,
|
timeRange: timeRange,
|
||||||
panelCtrl: ctrl,
|
panelCtrl: ctrl,
|
||||||
@@ -670,10 +654,7 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
|
|||||||
|
|
||||||
elem.bind("plotselected", function (event, ranges) {
|
elem.bind("plotselected", function (event, ranges) {
|
||||||
if (ranges.ctrlKey || ranges.metaKey) {
|
if (ranges.ctrlKey || ranges.metaKey) {
|
||||||
// Create new annotation from time range
|
showAddAnnotationView(ranges.xaxis);
|
||||||
let timeRange = ranges.xaxis;
|
|
||||||
showAddAnnotationView(timeRange);
|
|
||||||
//plot.clearSelection();
|
|
||||||
} else {
|
} else {
|
||||||
scope.$apply(function() {
|
scope.$apply(function() {
|
||||||
timeSrv.setTime({
|
timeSrv.setTime({
|
||||||
@@ -684,6 +665,15 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
elem.bind("plotclick", function (event, pos, item) {
|
||||||
|
// Skip if range selected (added in "plotselected" event handler)
|
||||||
|
let isRangeSelection = pos.x !== pos.x1;
|
||||||
|
let createAnnotation = !isRangeSelection && (pos.ctrlKey || pos.metaKey);
|
||||||
|
if (createAnnotation) {
|
||||||
|
showAddAnnotationView({from: pos.x, to: null});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
scope.$on('$destroy', function() {
|
scope.$on('$destroy', function() {
|
||||||
tooltip.destroy();
|
tooltip.destroy();
|
||||||
elem.off();
|
elem.off();
|
||||||
|
|||||||
@@ -306,21 +306,6 @@ class GraphCtrl extends MetricsPanelCtrl {
|
|||||||
alert('selection region while holding down CTRL or CMD');
|
alert('selection region while holding down CTRL or CMD');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get annotation info from dialog and push it to backend
|
|
||||||
pushAnnotations(annotations) {
|
|
||||||
return this.annotationsSrv.postAnnotation(annotations);
|
|
||||||
}
|
|
||||||
|
|
||||||
showAddAnnotationModal(timeRange) {
|
|
||||||
let addAnnotationScope = this.$scope.$new();
|
|
||||||
addAnnotationScope.annotationTimeRange = timeRange;
|
|
||||||
|
|
||||||
this.publishAppEvent('show-modal', {
|
|
||||||
src: 'public/app/features/dashboard/partials/addAnnotationModal.html',
|
|
||||||
scope: addAnnotationScope
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
legendValuesOptionChanged() {
|
legendValuesOptionChanged() {
|
||||||
var legend = this.panel.legend;
|
var legend = this.panel.legend;
|
||||||
legend.values = legend.min || legend.max || legend.avg || legend.current || legend.total;
|
legend.values = legend.min || legend.max || legend.avg || legend.current || legend.total;
|
||||||
|
|||||||
Reference in New Issue
Block a user