Merge branch 'master' into plugin-editors

Conflicts:
	public/app/features/panel/panel.ts
	public/app/features/panel/panel_directive.js
	public/app/plugins/datasource/grafana/module.ts
This commit is contained in:
Torkel Ödegaard 2016-02-01 21:37:36 +01:00
commit 30a8a434a1
83 changed files with 257 additions and 414 deletions

View File

@ -36,7 +36,6 @@ func newMacaron() *macaron.Macaron {
}
mapStatic(m, setting.StaticRootPath, "", "public")
mapStatic(m, setting.StaticRootPath, "app", "app")
mapStatic(m, setting.StaticRootPath, "css", "css")
mapStatic(m, setting.StaticRootPath, "img", "img")
mapStatic(m, setting.StaticRootPath, "fonts", "fonts")

View File

@ -46,8 +46,8 @@ var (
// ConsoleWriter implements LoggerInterface and writes messages to terminal.
type ConsoleWriter struct {
lg *log.Logger
Level int `json:"level"`
Formatting bool `json:"formatting"`
Level LogLevel `json:"level"`
Formatting bool `json:"formatting"`
}
// create ConsoleWriter returning as LoggerInterface.
@ -63,7 +63,7 @@ func (cw *ConsoleWriter) Init(config string) error {
return json.Unmarshal([]byte(config), cw)
}
func (cw *ConsoleWriter) WriteMsg(msg string, skip, level int) error {
func (cw *ConsoleWriter) WriteMsg(msg string, skip int, level LogLevel) error {
if cw.Level > level {
return nil
}
@ -82,11 +82,11 @@ func (_ *ConsoleWriter) Flush() {
func (_ *ConsoleWriter) Destroy() {
}
func printConsole(level int, msg string) {
func printConsole(level LogLevel, msg string) {
consoleWriter.WriteMsg(msg, 0, level)
}
func printfConsole(level int, format string, v ...interface{}) {
func printfConsole(level LogLevel, format string, v ...interface{}) {
consoleWriter.WriteMsg(fmt.Sprintf(format, v...), 0, level)
}

View File

@ -41,7 +41,7 @@ type FileLogWriter struct {
startLock sync.Mutex // Only one log can write to the file
Level int `json:"level"`
Level LogLevel `json:"level"`
}
// an *os.File writer with locker.
@ -132,7 +132,7 @@ func (w *FileLogWriter) docheck(size int) {
}
// write logger message into file.
func (w *FileLogWriter) WriteMsg(msg string, skip, level int) error {
func (w *FileLogWriter) WriteMsg(msg string, skip int, level LogLevel) error {
if level < w.Level {
return nil
}

View File

@ -99,7 +99,7 @@ func Close() {
type LogLevel int
const (
TRACE = iota
TRACE LogLevel = iota
DEBUG
INFO
WARN
@ -111,7 +111,7 @@ const (
// LoggerInterface represents behaviors of a logger provider.
type LoggerInterface interface {
Init(config string) error
WriteMsg(msg string, skip, level int) error
WriteMsg(msg string, skip int, level LogLevel) error
Destroy()
Flush()
}
@ -132,8 +132,9 @@ func Register(name string, log loggerType) {
}
type logMsg struct {
skip, level int
msg string
skip int
level LogLevel
msg string
}
// Logger is default logger in beego application.
@ -141,7 +142,7 @@ type logMsg struct {
type Logger struct {
adapter string
lock sync.Mutex
level int
level LogLevel
msg chan *logMsg
outputs map[string]LoggerInterface
quit chan bool
@ -188,10 +189,7 @@ func (l *Logger) DelLogger(adapter string) error {
return nil
}
func (l *Logger) writerMsg(skip, level int, msg string) error {
if l.level > level {
return nil
}
func (l *Logger) writerMsg(skip int, level LogLevel, msg string) error {
lm := &logMsg{
skip: skip,
level: level,
@ -266,36 +264,57 @@ func (l *Logger) Close() {
}
func (l *Logger) Trace(format string, v ...interface{}) {
if l.level > TRACE {
return
}
msg := fmt.Sprintf("[T] "+format, v...)
l.writerMsg(0, TRACE, msg)
}
func (l *Logger) Debug(format string, v ...interface{}) {
if l.level > DEBUG {
return
}
msg := fmt.Sprintf("[D] "+format, v...)
l.writerMsg(0, DEBUG, msg)
}
func (l *Logger) Info(format string, v ...interface{}) {
if l.level > INFO {
return
}
msg := fmt.Sprintf("[I] "+format, v...)
l.writerMsg(0, INFO, msg)
}
func (l *Logger) Warn(format string, v ...interface{}) {
if l.level > WARN {
return
}
msg := fmt.Sprintf("[W] "+format, v...)
l.writerMsg(0, WARN, msg)
}
func (l *Logger) Error(skip int, format string, v ...interface{}) {
if l.level > ERROR {
return
}
msg := fmt.Sprintf("[E] "+format, v...)
l.writerMsg(skip, ERROR, msg)
}
func (l *Logger) Critical(skip int, format string, v ...interface{}) {
if l.level > CRITICAL {
return
}
msg := fmt.Sprintf("[C] "+format, v...)
l.writerMsg(skip, CRITICAL, msg)
}
func (l *Logger) Fatal(skip int, format string, v ...interface{}) {
if l.level > FATAL {
return
}
msg := fmt.Sprintf("[F] "+format, v...)
l.writerMsg(skip, FATAL, msg)
l.Close()

View File

@ -39,7 +39,7 @@ func (sw *SyslogWriter) Init(config string) error {
return nil
}
func (sw *SyslogWriter) WriteMsg(msg string, skip, level int) error {
func (sw *SyslogWriter) WriteMsg(msg string, skip int, level LogLevel) error {
var err error
switch level {

View File

@ -14,7 +14,7 @@ export class NavbarCtrl {
export function navbarDirective() {
return {
restrict: 'E',
templateUrl: 'app/core/components/navbar/navbar.html',
templateUrl: 'public/app/core/components/navbar/navbar.html',
controller: NavbarCtrl,
bindToController: true,
controllerAs: 'ctrl',

View File

@ -137,7 +137,7 @@ export class SearchCtrl {
export function searchDirective() {
return {
restrict: 'E',
templateUrl: 'app/core/components/search/search.html',
templateUrl: 'public/app/core/components/search/search.html',
controller: SearchCtrl,
bindToController: true,
controllerAs: 'ctrl',

View File

@ -148,7 +148,7 @@ export class SideMenuCtrl {
export function sideMenuDirective() {
return {
restrict: 'E',
templateUrl: 'app/core/components/sidemenu/sidemenu.html',
templateUrl: 'public/app/core/components/sidemenu/sidemenu.html',
controller: SideMenuCtrl,
bindToController: true,
controllerAs: 'ctrl',

View File

@ -6,9 +6,9 @@ function ($, coreModule) {
'use strict';
var editViewMap = {
'settings': { src: 'app/features/dashboard/partials/settings.html', title: "Settings" },
'annotations': { src: 'app/features/annotations/partials/editor.html', title: "Annotations" },
'templating': { src: 'app/features/templating/partials/editor.html', title: "Templating" }
'settings': { src: 'public/app/features/dashboard/partials/settings.html', title: "Settings" },
'annotations': { src: 'public/app/features/annotations/partials/editor.html', title: "Annotations" },
'templating': { src: 'public/app/features/templating/partials/editor.html', title: "Templating" }
};
coreModule.default.directive('dashEditorLink', function($timeout) {

View File

@ -227,7 +227,7 @@ function (angular, _, coreModule) {
coreModule.default.directive('valueSelectDropdown', function($compile, $window, $timeout, $rootScope) {
return {
scope: { variable: "=", onUpdated: "&", getValuesForTag: "&" },
templateUrl: 'app/partials/valueSelectDropdown.html',
templateUrl: 'public/app/partials/valueSelectDropdown.html',
controller: 'ValueSelectDropdownCtrl',
controllerAs: 'vm',
bindToController: true,

View File

@ -14,146 +14,146 @@ define([
$routeProvider
.when('/', {
templateUrl: 'app/partials/dashboard.html',
templateUrl: 'public/app/partials/dashboard.html',
controller : 'LoadDashboardCtrl',
reloadOnSearch: false,
})
.when('/dashboard/:type/:slug', {
templateUrl: 'app/partials/dashboard.html',
templateUrl: 'public/app/partials/dashboard.html',
controller : 'LoadDashboardCtrl',
reloadOnSearch: false,
})
.when('/dashboard-solo/:type/:slug', {
templateUrl: 'app/features/panel/partials/soloPanel.html',
templateUrl: 'public/app/features/panel/partials/soloPanel.html',
controller : 'SoloPanelCtrl',
})
.when('/dashboard-import/:file', {
templateUrl: 'app/partials/dashboard.html',
templateUrl: 'public/app/partials/dashboard.html',
controller : 'DashFromImportCtrl',
reloadOnSearch: false,
})
.when('/dashboard/new', {
templateUrl: 'app/partials/dashboard.html',
templateUrl: 'public/app/partials/dashboard.html',
controller : 'NewDashboardCtrl',
reloadOnSearch: false,
})
.when('/import/dashboard', {
templateUrl: 'app/features/dashboard/partials/import.html',
templateUrl: 'public/app/features/dashboard/partials/import.html',
controller : 'DashboardImportCtrl',
})
.when('/datasources', {
templateUrl: 'app/features/datasources/partials/list.html',
templateUrl: 'public/app/features/datasources/partials/list.html',
controller : 'DataSourcesCtrl',
resolve: loadOrgBundle,
})
.when('/datasources/edit/:id', {
templateUrl: 'app/features/datasources/partials/edit.html',
templateUrl: 'public/app/features/datasources/partials/edit.html',
controller : 'DataSourceEditCtrl',
resolve: loadOrgBundle,
})
.when('/datasources/new', {
templateUrl: 'app/features/datasources/partials/edit.html',
templateUrl: 'public/app/features/datasources/partials/edit.html',
controller : 'DataSourceEditCtrl',
resolve: loadOrgBundle,
})
.when('/org', {
templateUrl: 'app/features/org/partials/orgDetails.html',
templateUrl: 'public/app/features/org/partials/orgDetails.html',
controller : 'OrgDetailsCtrl',
resolve: loadOrgBundle,
})
.when('/org/new', {
templateUrl: 'app/features/org/partials/newOrg.html',
templateUrl: 'public/app/features/org/partials/newOrg.html',
controller : 'NewOrgCtrl',
resolve: loadOrgBundle,
})
.when('/org/users', {
templateUrl: 'app/features/org/partials/orgUsers.html',
templateUrl: 'public/app/features/org/partials/orgUsers.html',
controller : 'OrgUsersCtrl',
resolve: loadOrgBundle,
})
.when('/org/apikeys', {
templateUrl: 'app/features/org/partials/orgApiKeys.html',
templateUrl: 'public/app/features/org/partials/orgApiKeys.html',
controller : 'OrgApiKeysCtrl',
resolve: loadOrgBundle,
})
.when('/profile', {
templateUrl: 'app/features/profile/partials/profile.html',
templateUrl: 'public/app/features/profile/partials/profile.html',
controller : 'ProfileCtrl',
})
.when('/profile/password', {
templateUrl: 'app/features/profile/partials/password.html',
templateUrl: 'public/app/features/profile/partials/password.html',
controller : 'ChangePasswordCtrl',
})
.when('/profile/select-org', {
templateUrl: 'app/features/profile/partials/select_org.html',
templateUrl: 'public/app/features/profile/partials/select_org.html',
controller : 'SelectOrgCtrl',
})
.when('/admin/settings', {
templateUrl: 'app/features/admin/partials/settings.html',
templateUrl: 'public/app/features/admin/partials/settings.html',
controller : 'AdminSettingsCtrl',
})
.when('/admin/users', {
templateUrl: 'app/features/admin/partials/users.html',
templateUrl: 'public/app/features/admin/partials/users.html',
controller : 'AdminListUsersCtrl',
})
.when('/admin/users/create', {
templateUrl: 'app/features/admin/partials/new_user.html',
templateUrl: 'public/app/features/admin/partials/new_user.html',
controller : 'AdminEditUserCtrl',
})
.when('/admin/users/edit/:id', {
templateUrl: 'app/features/admin/partials/edit_user.html',
templateUrl: 'public/app/features/admin/partials/edit_user.html',
controller : 'AdminEditUserCtrl',
})
.when('/admin/orgs', {
templateUrl: 'app/features/admin/partials/orgs.html',
templateUrl: 'public/app/features/admin/partials/orgs.html',
controller : 'AdminListOrgsCtrl',
})
.when('/admin/orgs/edit/:id', {
templateUrl: 'app/features/admin/partials/edit_org.html',
templateUrl: 'public/app/features/admin/partials/edit_org.html',
controller : 'AdminEditOrgCtrl',
})
.when('/admin/stats', {
templateUrl: 'app/features/admin/partials/stats.html',
templateUrl: 'public/app/features/admin/partials/stats.html',
controller : 'AdminStatsCtrl',
controllerAs: 'ctrl',
})
.when('/login', {
templateUrl: 'app/partials/login.html',
templateUrl: 'public/app/partials/login.html',
controller : 'LoginCtrl',
})
.when('/invite/:code', {
templateUrl: 'app/partials/signup_invited.html',
templateUrl: 'public/app/partials/signup_invited.html',
controller : 'InvitedCtrl',
})
.when('/signup', {
templateUrl: 'app/partials/signup_step2.html',
templateUrl: 'public/app/partials/signup_step2.html',
controller : 'SignUpCtrl',
})
.when('/user/password/send-reset-email', {
templateUrl: 'app/partials/reset_password.html',
templateUrl: 'public/app/partials/reset_password.html',
controller : 'ResetPasswordCtrl',
})
.when('/user/password/reset', {
templateUrl: 'app/partials/reset_password.html',
templateUrl: 'public/app/partials/reset_password.html',
controller : 'ResetPasswordCtrl',
})
.when('/apps', {
templateUrl: 'app/features/apps/partials/list.html',
templateUrl: 'public/app/features/apps/partials/list.html',
controller: 'AppListCtrl',
controllerAs: 'ctrl',
resolve: loadAppsBundle,
})
.when('/apps/edit/:appId', {
templateUrl: 'app/features/apps/partials/edit.html',
templateUrl: 'public/app/features/apps/partials/edit.html',
controller: 'AppEditCtrl',
controllerAs: 'ctrl',
resolve: loadAppsBundle,
})
.when('/global-alerts', {
templateUrl: 'app/features/dashboard/partials/globalAlerts.html',
templateUrl: 'public/app/features/dashboard/partials/globalAlerts.html',
})
.otherwise({
templateUrl: 'app/partials/error.html',
templateUrl: 'public/app/partials/error.html',
controller: 'ErrorCtrl'
});
});

View File

@ -72,7 +72,7 @@ function (angular, _, coreModule) {
scope.noText = payload.noText || "Cancel";
var confirmModal = $modal({
template: './app/partials/confirm_modal.html',
template: 'public/app/partials/confirm_modal.html',
persist: false,
modalClass: 'modal-no-header confirm-modal',
show: false,

View File

@ -31,7 +31,7 @@ function (angular, _, $) {
};
$scope.datasourceChanged = function() {
datasourceSrv.get($scope.currentAnnotation.datasource).then(function(ds) {
return datasourceSrv.get($scope.currentAnnotation.datasource).then(function(ds) {
$scope.currentDatasource = ds;
$scope.currentAnnotation.datasource = ds.name;
});

View File

@ -33,9 +33,9 @@
<i class="fa fa-remove"></i>
</button>
</div>
<div class="gf-box-body">
<div class="editor-row row" ng-if="mode === 'list'">
<div class="span6">
<div ng-if="annotations.length === 0">

View File

@ -9,7 +9,7 @@ function annotationsQueryEditor(dynamicDirectiveSrv) {
annotation: "=",
datasource: "="
},
watchPath: "datasource.type",
watchPath: "annotation.datasource",
directive: scope => {
return System.import(scope.datasource.meta.module).then(function(dsModule) {
return {

View File

@ -102,7 +102,7 @@ function (angular, $, config, moment) {
var editScope = $rootScope.$new();
editScope.object = options.object;
editScope.updateHandler = options.updateHandler;
$scope.appEvent('show-dash-editor', { src: 'app/partials/edit_json.html', scope: editScope });
$scope.appEvent('show-dash-editor', { src: 'public/app/partials/edit_json.html', scope: editScope });
};
$scope.onDrop = function(panelId, row, dropTarget) {

View File

@ -27,13 +27,17 @@
<li ng-show="dashboardMeta.canShare" class="dropdown">
<a class="pointer" ng-click="hideTooltip($event)" bs-tooltip="'Share dashboard'" data-placement="bottom" data-toggle="dropdown"><i class="fa fa-share-square-o"></i></a>
<ul class="dropdown-menu">
<li ng-if="dashboardMeta.canEdit"><a class="pointer" ng-click="shareDashboard(0)">
<i class="fa fa-link"></i>
Link to Dashboard</a></li>
<li ng-if="dashboardMeta.canEdit"><a class="pointer" ng-click="shareDashboard(1)">
<i class="gf-icon gf-icon-snap-multi"></i>
Snapshot sharing</a></li>
</ul>
<li ng-if="dashboardMeta.canEdit">
<a class="pointer" ng-click="shareDashboard(0)">
<i class="fa fa-link"></i> Link to Dashboard
</a>
</li>
<li ng-if="dashboardMeta.canEdit">
<a class="pointer" ng-click="shareDashboard(1)">
<i class="icon-gf icon-gf-snapshot"></i>Snapshot sharing
</a>
</li>
</ul>
</li>
<li ng-show="dashboardMeta.canSave">
<a ng-click="saveDashboard()" bs-tooltip="'Save dashboard'" data-placement="bottom"><i class="fa fa-save"></i></a>

View File

@ -47,7 +47,7 @@ export class DashNavCtrl {
modalScope.tabIndex = tabIndex;
$scope.appEvent('show-modal', {
src: './app/features/dashboard/partials/shareModal.html',
src: 'public/app/features/dashboard/partials/shareModal.html',
scope: modalScope
});
};
@ -152,7 +152,7 @@ export class DashNavCtrl {
newScope.clone.hideControls = false;
$scope.appEvent('show-modal', {
src: './app/features/dashboard/partials/saveDashboardAs.html',
src: 'public/app/features/dashboard/partials/saveDashboardAs.html',
scope: newScope,
});
};
@ -192,7 +192,7 @@ export class DashNavCtrl {
export function dashNavDirective() {
return {
restrict: 'E',
templateUrl: 'app/features/dashboard/dashnav/dashnav.html',
templateUrl: 'public/app/features/dashboard/dashnav/dashnav.html',
controller: DashNavCtrl,
transclude: true,
};

View File

@ -21,7 +21,7 @@ function(angular, $) {
helpModalScope = $rootScope.$new();
var helpModal = $modal({
template: './app/partials/help_modal.html',
template: 'public/app/partials/help_modal.html',
persist: false,
show: false,
scope: helpModalScope,

View File

@ -59,7 +59,7 @@
</section>
</div>
<div ng-include="'app/features/dashboard/partials/graphiteImport.html'"></div>
<div ng-include="'public/app/features/dashboard/partials/graphiteImport.html'"></div>
</div>
</div>

View File

@ -34,7 +34,7 @@ export class SubmenuCtrl {
export function submenuDirective() {
return {
restrict: 'E',
templateUrl: 'app/features/dashboard/submenu/submenu.html',
templateUrl: 'public/app/features/dashboard/submenu/submenu.html',
controller: SubmenuCtrl,
bindToController: true,
controllerAs: 'ctrl',

View File

@ -101,7 +101,7 @@ export class TimePickerCtrl {
this.refresh.options.unshift({text: 'off'});
this.$rootScope.appEvent('show-dash-editor', {
src: 'app/features/dashboard/timepicker/dropdown.html',
src: 'public/app/features/dashboard/timepicker/dropdown.html',
scope: this.$scope,
cssClass: 'gf-timepicker-dropdown',
});
@ -146,7 +146,7 @@ export class TimePickerCtrl {
export function settingsDirective() {
return {
restrict: 'E',
templateUrl: 'app/features/dashboard/timepicker/settings.html',
templateUrl: 'public/app/features/dashboard/timepicker/settings.html',
controller: TimePickerCtrl,
bindToController: true,
controllerAs: 'ctrl',
@ -159,7 +159,7 @@ export function settingsDirective() {
export function timePickerDirective() {
return {
restrict: 'E',
templateUrl: 'app/features/dashboard/timepicker/timepicker.html',
templateUrl: 'public/app/features/dashboard/timepicker/timepicker.html',
controller: TimePickerCtrl,
bindToController: true,
controllerAs: 'ctrl',

View File

@ -139,7 +139,7 @@ function(angular, _) {
};
$rootScope.appEvent('show-modal', {
src: './app/partials/unsaved-changes.html',
src: 'public/app/partials/unsaved-changes.html',
modalClass: 'modal-no-header confirm-modal',
scope: modalScope,
});

View File

@ -21,7 +21,7 @@ function (angular, _) {
return {
restrict: 'E',
controller: 'DashLinkEditorCtrl',
templateUrl: 'app/features/dashlinks/editor.html',
templateUrl: 'public/app/features/dashlinks/editor.html',
link: function() {
}
};

View File

@ -10,7 +10,7 @@ function (angular, _, config) {
var datasourceTypes = [];
module.directive('datasourceHttpSettings', function() {
return {templateUrl: 'app/features/datasources/partials/http_settings.html'};
return {templateUrl: 'public/app/features/datasources/partials/http_settings.html'};
});
module.controller('DataSourceEditCtrl', function($scope, $q, backendSrv, $routeParams, $location, datasourceSrv) {

View File

@ -32,7 +32,7 @@ function (angular) {
modalScope.key = result.key;
$scope.appEvent('show-modal', {
src: './app/features/org/partials/apikeyModal.html',
src: 'public/app/features/org/partials/apikeyModal.html',
scope: modalScope
});

View File

@ -54,7 +54,7 @@ function (angular) {
};
$scope.appEvent('show-modal', {
src: './app/features/org/partials/invite.html',
src: 'public/app/features/org/partials/invite.html',
modalClass: 'modal-no-header invite-modal',
scope: modalScope
});

View File

@ -1,8 +1,6 @@
define([
'./panel_menu',
'./panel_directive',
'./panel_srv',
'./panel_helper',
'./solo_panel_ctrl',
'./panel_loader',
'./query_editor',

View File

@ -49,7 +49,7 @@ class MetricsPanelCtrl extends PanelCtrl {
initEditMode() {
this.addEditorTab('Metrics', 'public/app/partials/metrics.html');
this.addEditorTab('Time range', 'app/features/panel/partials/panelTime.html');
this.addEditorTab('Time range', 'public/app/features/panel/partials/panelTime.html');
this.datasources = this.datasourceSrv.getMetricSources();
}

View File

@ -172,7 +172,7 @@ export class PanelCtrl {
shareScope.dashboard = this.dashboard;
this.publishAppEvent('show-modal', {
src: './app/features/dashboard/partials/shareModal.html',
src: 'public/app/features/dashboard/partials/shareModal.html',
scope: shareScope
});
}

View File

@ -6,6 +6,7 @@ import $ from 'jquery';
import {PanelCtrl} from './panel_ctrl';
export class DefaultPanelCtrl extends PanelCtrl {
/** @ngInject */
constructor($scope, $injector) {
super($scope, $injector);
}

View File

@ -8,7 +8,7 @@ import {UnknownPanel} from '../../plugins/panel/unknown/module';
var directiveModule = angular.module('grafana.directives');
/** @ngInject */
function panelLoader($compile, dynamicDirectiveSrv, $http, $q, $injector) {
function panelLoader($compile, dynamicDirectiveSrv, $http, $q, $injector, $templateCache) {
return {
restrict: 'E',
scope: {
@ -22,6 +22,10 @@ function panelLoader($compile, dynamicDirectiveSrv, $http, $q, $injector) {
if (directive.template) {
return $q.when(directive.template);
}
var cached = $templateCache.get(directive.templateUrl);
if (cached) {
return $q.when(cached);
}
return $http.get(directive.templateUrl).then(res => {
return res.data;
});

View File

@ -12,7 +12,7 @@ function (angular, $, _) {
var linkTemplate =
'<span class="panel-title drag-handle pointer">' +
'<span class="panel-title-text drag-handle">{{ctrl.panel.title | interpolateTemplateVars:this}}</span>' +
'<span class="panel-links-btn"><i class="fa fa-link"></i></span>' +
'<span class="panel-links-btn"><i class="fa fa-external-link"></i></span>' +
'<span class="panel-time-info" ng-show="ctrl.timeInfo"><i class="fa fa-clock-o"></i> {{ctrl.timeInfo}}</span>' +
'</span>';
@ -28,6 +28,7 @@ function (angular, $, _) {
}
return template;
}
function createMenuTemplate(ctrl) {
var template = '<div class="panel-menu small">';
@ -124,8 +125,8 @@ function (angular, $, _) {
}
var menuTemplate;
if ($(e.target).hasClass('fa-link')) {
menuTemplate = createExternalLinkMenu($scope);
if ($(e.target).hasClass('fa-external-link')) {
menuTemplate = createExternalLinkMenu(ctrl);
} else {
menuTemplate = createMenuTemplate(ctrl);
}

View File

@ -1,162 +0,0 @@
define([
'angular',
'lodash',
'app/core/config',
],
function (angular, _, config) {
'use strict';
var module = angular.module('grafana.services');
module.service('panelSrv', function($rootScope, $timeout, datasourceSrv, $q) {
this.init = function($scope) {
if (!$scope.panel.span) { $scope.panel.span = 12; }
$scope.inspector = {};
$scope.editPanel = function() {
$scope.toggleFullscreen(true);
};
$scope.sharePanel = function() {
$scope.appEvent('show-modal', {
src: './app/features/dashboard/partials/shareModal.html',
scope: $scope.$new()
});
};
$scope.editPanelJson = function() {
$scope.appEvent('show-json-editor', { object: $scope.panel, updateHandler: $scope.replacePanel });
};
$scope.duplicatePanel = function() {
$scope.dashboard.duplicatePanel($scope.panel, $scope.row);
};
$scope.updateColumnSpan = function(span) {
$scope.updatePanelSpan($scope.panel, span);
$timeout(function() {
$scope.$broadcast('render');
});
};
$scope.addDataQuery = function(datasource) {
$scope.dashboard.addDataQueryTo($scope.panel, datasource);
};
$scope.removeDataQuery = function (query) {
$scope.dashboard.removeDataQuery($scope.panel, query);
$scope.get_data();
};
$scope.duplicateDataQuery = function(query) {
$scope.dashboard.duplicateDataQuery($scope.panel, query);
};
$scope.moveDataQuery = function(fromIndex, toIndex) {
$scope.dashboard.moveDataQuery($scope.panel, fromIndex, toIndex);
};
$scope.setDatasource = function(datasource) {
// switching to mixed
if (datasource.meta.mixed) {
_.each($scope.panel.targets, function(target) {
target.datasource = $scope.panel.datasource;
if (target.datasource === null) {
target.datasource = config.defaultDatasource;
}
});
}
// switching from mixed
else if ($scope.datasource && $scope.datasource.meta.mixed) {
_.each($scope.panel.targets, function(target) {
delete target.datasource;
});
}
$scope.panel.datasource = datasource.value;
$scope.datasource = null;
$scope.get_data();
};
$scope.toggleEditorHelp = function(index) {
if ($scope.editorHelpIndex === index) {
$scope.editorHelpIndex = null;
return;
}
$scope.editorHelpIndex = index;
};
$scope.isNewPanel = function() {
return $scope.panel.title === config.new_panel_title;
};
$scope.toggleFullscreen = function(edit) {
$scope.dashboardViewState.update({ fullscreen: true, edit: edit, panelId: $scope.panel.id });
};
$scope.otherPanelInFullscreenMode = function() {
return $scope.dashboardViewState.fullscreen && !$scope.fullscreen;
};
$scope.getCurrentDatasource = function() {
if ($scope.datasource) {
return $q.when($scope.datasource);
}
return datasourceSrv.get($scope.panel.datasource);
};
$scope.panelRenderingComplete = function() {
$rootScope.performance.panelsRendered++;
};
$scope.get_data = function() {
if ($scope.otherPanelInFullscreenMode()) { return; }
if ($scope.panel.snapshotData) {
if ($scope.loadSnapshot) {
$scope.loadSnapshot($scope.panel.snapshotData);
}
return;
}
delete $scope.panelMeta.error;
$scope.panelMeta.loading = true;
$scope.getCurrentDatasource().then(function(datasource) {
$scope.datasource = datasource;
return $scope.refreshData($scope.datasource) || $q.when({});
}).then(function() {
$scope.panelMeta.loading = false;
}, function(err) {
console.log('Panel data error:', err);
$scope.panelMeta.loading = false;
$scope.panelMeta.error = err.message || "Timeseries data request error";
$scope.inspector.error = err;
});
};
if ($scope.refreshData) {
$scope.$on("refresh", $scope.get_data);
}
// Post init phase
$scope.fullscreen = false;
$scope.editor = { index: 1 };
$scope.dashboardViewState.registerPanel($scope);
$scope.datasources = datasourceSrv.getMetricSources();
if (!$scope.skipDataOnInit) {
$timeout(function() {
$scope.get_data();
}, 30);
}
};
});
});

View File

@ -87,7 +87,7 @@ function metricsQueryEditor(dynamicDirectiveSrv, datasourceSrv) {
directive: scope => {
let datasource = scope.target.datasource || scope.ctrl.panel.datasource;
return datasourceSrv.get(datasource).then(ds => {
scope.ctrl.datasource = ds;
scope.datasource = ds;
if (!scope.target.refId) {
scope.target.refId = 'A';

View File

@ -15,7 +15,7 @@ function (angular, _) {
},
restrict: 'E',
controller: 'PanelLinksEditorCtrl',
templateUrl: 'app/features/panellinks/module.html',
templateUrl: 'public/app/features/panellinks/module.html',
link: function() {
}
};

View File

@ -11,17 +11,17 @@ function (angular) {
module.config(function($routeProvider) {
$routeProvider
.when('/playlists', {
templateUrl: 'app/features/playlist/partials/playlists.html',
templateUrl: 'public/app/features/playlist/partials/playlists.html',
controllerAs: 'ctrl',
controller : 'PlaylistsCtrl'
})
.when('/playlists/create', {
templateUrl: 'app/features/playlist/partials/playlist.html',
templateUrl: 'public/app/features/playlist/partials/playlist.html',
controllerAs: 'ctrl',
controller : 'PlaylistEditCtrl'
})
.when('/playlists/edit/:id', {
templateUrl: 'app/features/playlist/partials/playlist.html',
templateUrl: 'public/app/features/playlist/partials/playlist.html',
controllerAs: 'ctrl',
controller : 'PlaylistEditCtrl'
})

View File

@ -70,7 +70,7 @@ export class PlaylistSearchCtrl {
export function playlistSearchDirective() {
return {
restrict: 'E',
templateUrl: 'app/features/playlist/partials/playlist_search.html',
templateUrl: 'public/app/features/playlist/partials/playlist_search.html',
controller: PlaylistSearchCtrl,
bindToController: true,
controllerAs: 'ctrl',

View File

@ -107,8 +107,3 @@
</div>
</div>
<div ng-include="'app/partials/console.html'" ng-if="consoleEnabled">
</div>
</div>

View File

@ -3,7 +3,8 @@
<div class="login-box">
<div class="login-box-logo">
<img src="img/logo_transparent_200x75.png">
<img class="logo-icon" src="img/grafana_icon.svg"></img><br>
<i class="icon-gf icon-gf-grafana_wordmark"></i>
</div>
<div class="login-inner-box">

View File

@ -7,15 +7,15 @@ function (CloudWatchDatasource) {
'use strict';
function metricsQueryEditor() {
return {controller: 'CloudWatchQueryCtrl', templateUrl: 'app/plugins/datasource/cloudwatch/partials/query.editor.html'};
return {controller: 'CloudWatchQueryCtrl', templateUrl: 'public/app/plugins/datasource/cloudwatch/partials/query.editor.html'};
}
function annotationsQueryEditor() {
return {templateUrl: 'app/plugins/datasource/cloudwatch/partials/annotations.editor.html'};
return {templateUrl: 'public/app/plugins/datasource/cloudwatch/partials/annotations.editor.html'};
}
function configView() {
return {templateUrl: 'app/plugins/datasource/cloudwatch/partials/edit_view.html'};
return {templateUrl: 'public/app/plugins/datasource/cloudwatch/partials/edit_view.html'};
}
return {

View File

@ -6,14 +6,14 @@
<i class="fa fa-bars"></i>
</a>
<ul class="dropdown-menu pull-right" role="menu">
<li role="menuitem"><a tabindex="1" ng-click="duplicateDataQuery(target)">Duplicate</a></li>
<li role="menuitem"><a tabindex="1" ng-click="moveDataQuery($index, $index-1)">Move up</a></li>
<li role="menuitem"><a tabindex="1" ng-click="moveDataQuery($index, $index+1)">Move down</a></li>
<li role="menuitem"><a tabindex="1" ng-click="ctrl.duplicateDataQuery(target)">Duplicate</a></li>
<li role="menuitem"><a tabindex="1" ng-click="ctrl.moveDataQuery($index, $index-1)">Move up</a></li>
<li role="menuitem"><a tabindex="1" ng-click="ctrl.moveDataQuery($index, $index+1)">Move down</a></li>
</ul>
</div>
</li>
<li class="tight-form-item last">
<a class="pointer" tabindex="1" ng-click="removeDataQuery(target)">
<a class="pointer" tabindex="1" ng-click="ctrl.removeDataQuery(target)">
<i class="fa fa-remove"></i>
</a>
</li>
@ -25,7 +25,7 @@
</li>
<li>
<a class="tight-form-item"
ng-click="target.hide = !target.hide; get_data();"
ng-click="target.hide = !target.hide; ctrl.refresh();"
role="menuitem">
<i class="fa fa-eye"></i>
</a>
@ -35,4 +35,4 @@
<div class="clearfix"></div>
</div>
<cloudwatch-query-parameter target="target" datasource="datasource" on-change="refreshMetricData()"></cloudwatch-query-parameter>
<cloudwatch-query-parameter target="target" datasource="ctrl.datasource" on-change="refreshMetricData()"></cloudwatch-query-parameter>

View File

@ -16,7 +16,7 @@ function (angular, _) {
$scope.refreshMetricData = function() {
if (!_.isEqual($scope.oldTarget, $scope.target)) {
$scope.oldTarget = angular.copy($scope.target);
$scope.get_data();
$scope.ctrl.refresh();
}
};

View File

@ -10,7 +10,7 @@ function (angular, _, queryDef) {
module.directive('elasticBucketAgg', function() {
return {
templateUrl: 'app/plugins/datasource/elasticsearch/partials/bucket_agg.html',
templateUrl: 'public/app/plugins/datasource/elasticsearch/partials/bucket_agg.html',
controller: 'ElasticBucketAggCtrl',
restrict: 'E',
scope: {

View File

@ -5,6 +5,7 @@ import _ from 'lodash';
export class EditViewCtrl {
/** @ngInject */
constructor($scope) {
$scope.indexPatternTypes = [
{name: 'No pattern', value: undefined},
@ -29,7 +30,7 @@ export class EditViewCtrl {
function editViewDirective() {
return {
templateUrl: 'app/plugins/datasource/elasticsearch/partials/edit_view.html',
templateUrl: 'public/app/plugins/datasource/elasticsearch/partials/edit_view.html',
controller: EditViewCtrl,
};
};

View File

@ -10,7 +10,7 @@ function (angular, _, queryDef) {
module.directive('elasticMetricAgg', function() {
return {
templateUrl: 'app/plugins/datasource/elasticsearch/partials/metric_agg.html',
templateUrl: 'public/app/plugins/datasource/elasticsearch/partials/metric_agg.html',
controller: 'ElasticMetricAggCtrl',
restrict: 'E',
scope: {

View File

@ -8,15 +8,15 @@ function (ElasticDatasource, editView) {
'use strict';
function metricsQueryEditor() {
return {controller: 'ElasticQueryCtrl', templateUrl: 'app/plugins/datasource/elasticsearch/partials/query.editor.html'};
return {controller: 'ElasticQueryCtrl', templateUrl: 'public/app/plugins/datasource/elasticsearch/partials/query.editor.html'};
}
function metricsQueryOptions() {
return {templateUrl: 'app/plugins/datasource/elasticsearch/partials/query.options.html'};
return {templateUrl: 'public/app/plugins/datasource/elasticsearch/partials/query.options.html'};
}
function annotationsQueryEditor() {
return {templateUrl: 'app/plugins/datasource/elasticsearch/partials/annotations.editor.html'};
return {templateUrl: 'public/app/plugins/datasource/elasticsearch/partials/annotations.editor.html'};
}
return {

View File

@ -14,15 +14,15 @@
<i class="fa fa-bars"></i>
</a>
<ul class="dropdown-menu pull-right" role="menu">
<li role="menuitem"><a tabindex="1" ng-click="duplicateDataQuery(target)">Duplicate</a></li>
<li role="menuitem"><a tabindex="1" ng-click="moveDataQuery($index, $index-1)">Move up</a></li>
<li role="menuitem"><a tabindex="1" ng-click="moveDataQuery($index, $index+1)">Move down</a></li>
<li role="menuitem"><a tabindex="1" ng-click="panelCtrl.duplicateDataQuery(target)">Duplicate</a></li>
<li role="menuitem"><a tabindex="1" ng-click="panelCtrl.moveDataQuery($index, $index-1)">Move up</a></li>
<li role="menuitem"><a tabindex="1" ng-click="panelCtrl.moveDataQuery($index, $index+1)">Move down</a></li>
</ul>
</div>
</li>
<li class="tight-form-item last">
<a class="pointer" tabindex="1" ng-click="removeDataQuery(target)">
<a class="pointer" tabindex="1" ng-click="panelCtrl.removeDataQuery(target)">
<i class="fa fa-remove"></i>
</a>
</li>
@ -33,7 +33,7 @@
{{target.refId}}
</li>
<li>
<a class="tight-form-item" ng-click="target.hide = !target.hide; get_data();" role="menuitem">
<a class="tight-form-item" ng-click="target.hide = !target.hide; panelCtrl.refresh();" role="menuitem">
<i class="fa fa-eye"></i>
</a>
</li>
@ -44,13 +44,13 @@
Query
</li>
<li>
<input type="text" class="tight-form-input" style="width: 345px;" ng-model="target.query" spellcheck='false' placeholder="Lucene query" ng-blur="get_data()">
<input type="text" class="tight-form-input" style="width: 345px;" ng-model="target.query" spellcheck='false' placeholder="Lucene query" ng-blur="panelCtrl.refresh()">
</li>
<li class="tight-form-item query-keyword">
Alias
</li>
<li>
<input type="text" class="tight-form-input" style="width: 200px;" ng-model="target.alias" spellcheck='false' placeholder="alias patterns (empty = auto)" ng-blur="get_data()">
<input type="text" class="tight-form-input" style="width: 200px;" ng-model="target.alias" spellcheck='false' placeholder="alias patterns (empty = auto)" ng-blur="panelCtrl.refresh()">
</li>
</ul>
<div class="clearfix"></div>

View File

@ -8,7 +8,7 @@
Group by time interval
</li>
<li>
<input type="text" class="input-medium tight-form-input" ng-model="panel.interval" ng-blur="get_data();"
<input type="text" class="input-medium tight-form-input" ng-model="ctrl.panel.interval" ng-blur="ctrl.refresh();"
spellcheck='false' placeholder="example: >10s">
</li>
<li class="tight-form-item">
@ -23,7 +23,7 @@
<i class="fa fa-info-circle"></i>
</li>
<li class="tight-form-item">
<a ng-click="toggleEditorHelp(1);" bs-tooltip="'click to show helpful info'" data-placement="bottom">
<a ng-click="ctrl.toggleEditorHelp(1);" bs-tooltip="'click to show helpful info'" data-placement="bottom">
alias patterns
</a>
</li>
@ -34,7 +34,7 @@
<div class="editor-row">
<div class="pull-left" style="margin-top: 30px;">
<div class="grafana-info-box span6" ng-if="editorHelpIndex === 1">
<div class="grafana-info-box span6" ng-if="ctrl.editorHelpIndex === 1">
<h5>Alias patterns</h5>
<ul ng-non-bindable>
<li>{{term fieldname}} = replaced with value of term group by</li>

View File

@ -6,8 +6,9 @@ function (angular) {
var module = angular.module('grafana.controllers');
module.controller('ElasticQueryCtrl', function($scope, $timeout, uiSegmentSrv) {
module.controller('ElasticQueryCtrl', function($scope, $rootScope, $timeout, uiSegmentSrv) {
$scope.esVersion = $scope.datasource.esVersion;
$scope.panelCtrl = $scope.ctrl;
$scope.init = function() {
var target = $scope.target;
@ -27,10 +28,10 @@ function (angular) {
var newJson = angular.toJson($scope.datasource.queryBuilder.build($scope.target), true);
if (newJson !== $scope.oldQueryRaw) {
$scope.rawQueryOld = newJson;
$scope.get_data();
$scope.panelCtrl.refresh();
}
$scope.appEvent('elastic-query-updated');
$rootScope.appEvent('elastic-query-updated');
};
$scope.handleQueryError = function(err) {

View File

@ -4,7 +4,7 @@ import angular from 'angular';
import {GrafanaDatasource} from './datasource';
class GrafanaMetricsQueryEditor {
static templateUrl = 'app/plugins/datasource/grafana/partials/query.editor.html';
static templateUrl = 'public/app/plugins/datasource/grafana/partials/query.editor.html';
}
export {

View File

@ -7,20 +7,20 @@ function (GraphiteDatasource) {
function metricsQueryEditor() {
return {
controller: 'GraphiteQueryCtrl',
templateUrl: 'app/plugins/datasource/graphite/partials/query.editor.html'
templateUrl: 'public/app/plugins/datasource/graphite/partials/query.editor.html'
};
}
function metricsQueryOptions() {
return {templateUrl: 'app/plugins/datasource/graphite/partials/query.options.html'};
return {templateUrl: 'public/app/plugins/datasource/graphite/partials/query.options.html'};
}
function annotationsQueryEditor() {
return {templateUrl: 'app/plugins/datasource/graphite/partials/annotations.editor.html'};
return {templateUrl: 'public/app/plugins/datasource/graphite/partials/annotations.editor.html'};
}
function configView() {
return {templateUrl: 'app/plugins/datasource/graphite/partials/config.html'};
return {templateUrl: 'public/app/plugins/datasource/graphite/partials/config.html'};
}
return {

View File

@ -12,6 +12,7 @@ function (angular, _, config, gfunc, Parser) {
module.controller('GraphiteQueryCtrl', function($scope, uiSegmentSrv, templateSrv) {
var panelCtrl = $scope.panelCtrl = $scope.ctrl;
var datasource = $scope.datasource;
$scope.init = function() {
if ($scope.target) {
@ -126,7 +127,7 @@ function (angular, _, config, gfunc, Parser) {
}
var path = getSegmentPathUpTo(fromIndex + 1);
return panelCtrl.datasource.metricFindQuery(path)
return datasource.metricFindQuery(path)
.then(function(segments) {
if (segments.length === 0) {
if (path !== '') {
@ -160,7 +161,7 @@ function (angular, _, config, gfunc, Parser) {
$scope.getAltSegments = function (index) {
var query = index === 0 ? '*' : getSegmentPathUpTo(index) + '.*';
return panelCtrl.datasource.metricFindQuery(query).then(function(segments) {
return datasource.metricFindQuery(query).then(function(segments) {
var altSegments = _.map(segments, function(segment) {
return uiSegmentSrv.newSegment({ value: segment.text, expandable: segment.expandable });
});

View File

@ -19,14 +19,13 @@ describe('GraphiteQueryCtrl', function() {
ctx.scope = $rootScope.$new();
ctx.scope.ctrl = {panel: ctx.panel};
ctx.panelCtrl = ctx.scope.ctrl;
ctx.scope.datasource = ctx.datasource;
ctx.scope.datasource.metricFindQuery = sinon.stub().returns(ctx.$q.when([]));
ctx.controller = $controller('GraphiteQueryCtrl', {$scope: ctx.scope});
}));
beforeEach(function() {
ctx.scope.target = {target: 'aliasByNode(scaleToSeconds(test.prod.*,1),2)'};
ctx.panelCtrl.datasource = ctx.datasource;
ctx.panelCtrl.datasource.metricFindQuery = sinon.stub().returns(ctx.$q.when([]));
});
describe('init', function() {
@ -36,7 +35,7 @@ describe('GraphiteQueryCtrl', function() {
});
it('should validate metric key exists', function() {
expect(ctx.panelCtrl.datasource.metricFindQuery.getCall(0).args[0]).to.be('test.prod.*');
expect(ctx.scope.datasource.metricFindQuery.getCall(0).args[0]).to.be('test.prod.*');
});
it('should delete last segment if no metrics are found', function() {
@ -51,7 +50,7 @@ describe('GraphiteQueryCtrl', function() {
describe('when adding function', function() {
beforeEach(function() {
ctx.scope.target.target = 'test.prod.*.count';
ctx.panelCtrl.datasource.metricFindQuery.returns(ctx.$q.when([{expandable: false}]));
ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([{expandable: false}]));
ctx.scope.init();
ctx.scope.$digest();
@ -75,7 +74,7 @@ describe('GraphiteQueryCtrl', function() {
describe('when adding function before any metric segment', function() {
beforeEach(function() {
ctx.scope.target.target = '';
ctx.panelCtrl.datasource.metricFindQuery.returns(ctx.$q.when([{expandable: true}]));
ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([{expandable: true}]));
ctx.scope.init();
ctx.scope.$digest();
ctx.scope.addFunction(gfunc.getFuncDef('asPercent'));
@ -89,7 +88,7 @@ describe('GraphiteQueryCtrl', function() {
describe('when initalizing target without metric expression and only function', function() {
beforeEach(function() {
ctx.scope.target.target = 'asPercent(#A, #B)';
ctx.panelCtrl.datasource.metricFindQuery.returns(ctx.$q.when([]));
ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([]));
ctx.scope.init();
ctx.scope.$digest();
});
@ -107,7 +106,7 @@ describe('GraphiteQueryCtrl', function() {
describe('when initializing a target with single param func using variable', function() {
beforeEach(function() {
ctx.scope.target.target = 'movingAverage(prod.count, $var)';
ctx.panelCtrl.datasource.metricFindQuery.returns(ctx.$q.when([]));
ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([]));
ctx.scope.init();
ctx.scope.$digest();
});
@ -125,7 +124,7 @@ describe('GraphiteQueryCtrl', function() {
describe('when initalizing target without metric expression and function with series-ref', function() {
beforeEach(function() {
ctx.scope.target.target = 'asPercent(metric.node.count, #A)';
ctx.panelCtrl.datasource.metricFindQuery.returns(ctx.$q.when([]));
ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([]));
ctx.scope.init();
ctx.scope.$digest();
ctx.scope.$parent = { get_data: sinon.spy() };
@ -143,7 +142,7 @@ describe('GraphiteQueryCtrl', function() {
describe('when getting altSegments and metricFindQuery retuns empty array', function() {
beforeEach(function() {
ctx.scope.target.target = 'test.count';
ctx.panelCtrl.datasource.metricFindQuery.returns(ctx.$q.when([]));
ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([]));
ctx.scope.init();
ctx.scope.getAltSegments(1).then(function(results) {
ctx.altSegments = results;
@ -159,7 +158,7 @@ describe('GraphiteQueryCtrl', function() {
describe('targetChanged', function() {
beforeEach(function() {
ctx.panelCtrl.datasource.metricFindQuery.returns(ctx.$q.when([{expandable: false}]));
ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([{expandable: false}]));
ctx.scope.init();
ctx.scope.$digest();

View File

@ -218,5 +218,4 @@ function (angular, _, dateMath, InfluxSeries, InfluxQuery) {
}
return InfluxDatasource;
});

View File

@ -5,19 +5,19 @@ function (InfluxDatasource) {
'use strict';
function influxMetricsQueryEditor() {
return {controller: 'InfluxQueryCtrl', templateUrl: 'app/plugins/datasource/influxdb/partials/query.editor.html'};
return {controller: 'InfluxQueryCtrl', templateUrl: 'public/app/plugins/datasource/influxdb/partials/query.editor.html'};
}
function influxMetricsQueryOptions() {
return {templateUrl: 'app/plugins/datasource/influxdb/partials/query.options.html'};
return {templateUrl: 'public/app/plugins/datasource/influxdb/partials/query.options.html'};
}
function influxAnnotationsQueryEditor() {
return {templateUrl: 'app/plugins/datasource/influxdb/partials/annotations.editor.html'};
return {templateUrl: 'public/app/plugins/datasource/influxdb/partials/annotations.editor.html'};
}
function influxConfigView() {
return {templateUrl: 'app/plugins/datasource/influxdb/partials/config.html'};
return {templateUrl: 'public/app/plugins/datasource/influxdb/partials/config.html'};
}
return {

View File

@ -16,15 +16,15 @@
</a>
<ul class="dropdown-menu pull-right" role="menu">
<li role="menuitem"><a tabindex="1" ng-click="toggleQueryMode()">Switch editor mode</a></li>
<li role="menuitem"><a tabindex="1" ng-click="duplicateDataQuery(target)">Duplicate</a></li>
<li role="menuitem"><a tabindex="1" ng-click="moveDataQuery($index, $index-1)">Move up</a></li>
<li role="menuitem"><a tabindex="1" ng-click="moveDataQuery($index, $index+1)">Move down</a></li>
<li role="menuitem"><a tabindex="1" ng-click="panelCtrl.duplicateDataQuery(target)">Duplicate</a></li>
<li role="menuitem"><a tabindex="1" ng-click="panelCtrl.moveDataQuery($index, $index-1)">Move up</a></li>
<li role="menuitem"><a tabindex="1" ng-click="panelCtrl.moveDataQuery($index, $index+1)">Move down</a></li>
</ul>
</div>
</li>
<li class="tight-form-item last">
<a class="pointer" tabindex="1" ng-click="removeDataQuery(target)">
<a class="pointer" tabindex="1" ng-click="panelCtrl.removeDataQuery(target)">
<i class="fa fa-remove"></i>
</a>
</li>

View File

@ -16,6 +16,7 @@ function (angular, _, InfluxQueryBuilder, InfluxQuery, queryPart) {
module.controller('InfluxQueryCtrl', function($scope, templateSrv, $q, uiSegmentSrv) {
var panelCtrl = $scope.ctrl;
var datasource = $scope.datasource;
$scope.panelCtrl = panelCtrl;
$scope.init = function() {
@ -23,7 +24,7 @@ function (angular, _, InfluxQueryBuilder, InfluxQuery, queryPart) {
$scope.target = $scope.target;
$scope.queryModel = new InfluxQuery($scope.target);
$scope.queryBuilder = new InfluxQueryBuilder($scope.target, panelCtrl.datasource.database);
$scope.queryBuilder = new InfluxQueryBuilder($scope.target, datasource.database);
$scope.groupBySegment = uiSegmentSrv.newPlusButton();
$scope.resultFormats = [
{text: 'Time series', value: 'time_series'},
@ -77,7 +78,7 @@ function (angular, _, InfluxQueryBuilder, InfluxQuery, queryPart) {
$scope.getGroupByOptions = function() {
var query = $scope.queryBuilder.buildExploreQuery('TAG_KEYS');
return panelCtrl.datasource.metricFindQuery(query)
return datasource.metricFindQuery(query)
.then(function(tags) {
var options = [];
if (!$scope.queryModel.hasFill()) {
@ -137,7 +138,7 @@ function (angular, _, InfluxQueryBuilder, InfluxQuery, queryPart) {
$scope.getPolicySegments = function() {
var policiesQuery = $scope.queryBuilder.buildExploreQuery('RETENTION POLICIES');
return panelCtrl.datasource.metricFindQuery(policiesQuery)
return datasource.metricFindQuery(policiesQuery)
.then($scope.transformToSegments(false))
.then(null, $scope.handleQueryError);
};
@ -153,19 +154,19 @@ function (angular, _, InfluxQueryBuilder, InfluxQuery, queryPart) {
$scope.getMeasurements = function () {
var query = $scope.queryBuilder.buildExploreQuery('MEASUREMENTS');
return panelCtrl.datasource.metricFindQuery(query)
return datasource.metricFindQuery(query)
.then($scope.transformToSegments(true), $scope.handleQueryError);
};
$scope.getPartOptions = function(part) {
if (part.def.type === 'field') {
var fieldsQuery = $scope.queryBuilder.buildExploreQuery('FIELDS');
return panelCtrl.datasource.metricFindQuery(fieldsQuery)
return datasource.metricFindQuery(fieldsQuery)
.then($scope.transformToSegments(true), $scope.handleQueryError);
}
if (part.def.type === 'tag') {
var tagsQuery = $scope.queryBuilder.buildExploreQuery('TAG_KEYS');
return panelCtrl.datasource.metricFindQuery(tagsQuery)
return datasource.metricFindQuery(tagsQuery)
.then($scope.transformToSegments(true), $scope.handleQueryError);
}
};
@ -213,7 +214,7 @@ function (angular, _, InfluxQueryBuilder, InfluxQuery, queryPart) {
addTemplateVars = true;
}
return panelCtrl.datasource.metricFindQuery(query)
return datasource.metricFindQuery(query)
.then($scope.transformToSegments(addTemplateVars))
.then(function(results) {
if (segment.type === 'key') {
@ -226,7 +227,7 @@ function (angular, _, InfluxQueryBuilder, InfluxQuery, queryPart) {
$scope.getFieldSegments = function() {
var fieldsQuery = $scope.queryBuilder.buildExploreQuery('FIELDS');
return panelCtrl.datasource.metricFindQuery(fieldsQuery)
return datasource.metricFindQuery(fieldsQuery)
.then($scope.transformToSegments(false))
.then(null, $scope.handleQueryError);
};

View File

@ -14,7 +14,7 @@ function (angular, _, $) {
' class="input-mini tight-form-func-param"></input>';
return {
restrict: 'E',
templateUrl: 'app/plugins/datasource/influxdb/partials/query_part.html',
templateUrl: 'public/app/plugins/datasource/influxdb/partials/query_part.html',
scope: {
part: "=",
removeAction: "&",

View File

@ -15,6 +15,8 @@ describe('InfluxDBQueryCtrl', function() {
ctx.$q = $q;
ctx.scope = $rootScope.$new();
ctx.scope.ctrl = {panel: ctx.panel};
ctx.scope.datasource = ctx.datasource;
ctx.scope.datasource.metricFindQuery = sinon.stub().returns(ctx.$q.when([]));
ctx.panelCtrl = ctx.scope.ctrl;
ctx.controller = $controller('InfluxQueryCtrl', {$scope: ctx.scope});
}));
@ -22,8 +24,6 @@ describe('InfluxDBQueryCtrl', function() {
beforeEach(function() {
ctx.scope.target = {};
ctx.panelCtrl.refresh = sinon.spy();
ctx.panelCtrl.datasource = ctx.datasource;
ctx.panelCtrl.datasource.metricFindQuery = sinon.stub().returns(ctx.$q.when([]));
});
describe('init', function() {

View File

@ -13,6 +13,8 @@ function (angular, _, dateMath) {
this.type = 'opentsdb';
this.url = instanceSettings.url;
this.name = instanceSettings.name;
this.withCredentials = instanceSettings.withCredentials;
this.basicAuth = instanceSettings.basicAuth;
this.supportMetrics = true;
// Called once per panel (graph)
@ -71,6 +73,14 @@ function (angular, _, dateMath) {
url: this.url + '/api/query',
data: reqBody
};
if (this.basicAuth || this.withCredentials) {
options.withCredentials = true;
}
if (this.basicAuth) {
options.headers = {
"Authorization": this.basicAuth
};
}
// In case the backend is 3rd-party hosted and does not suport OPTIONS, urlencoded requests
// go as POST rather than OPTIONS+POST

View File

@ -7,12 +7,12 @@ function (OpenTsDatasource) {
function metricsQueryEditor() {
return {
controller: 'OpenTSDBQueryCtrl',
templateUrl: 'app/plugins/datasource/opentsdb/partials/query.editor.html',
templateUrl: 'public/app/plugins/datasource/opentsdb/partials/query.editor.html',
};
}
function configView() {
return {templateUrl: 'app/plugins/datasource/opentsdb/partials/config.html'};
return {templateUrl: 'public/app/plugins/datasource/opentsdb/partials/config.html'};
}
return {

View File

@ -9,15 +9,14 @@
<i class="fa fa-bars"></i>
</a>
<ul class="dropdown-menu pull-right" role="menu">
<li role="menuitem"><a tabindex="1" ng-click="toggleQueryMode()">Switch editor mode</a></li>
<li role="menuitem"><a tabindex="1" ng-click="duplicateDataQuery(target)">Duplicate</a></li>
<li role="menuitem"><a tabindex="1" ng-click="moveDataQuery($index, $index-1)">Move up</a></li>
<li role="menuitem"><a tabindex="1" ng-click="moveDataQuery($index, $index+1)">Move down</a></li>
<li role="menuitem"><a tabindex="1" ng-click="panelCtrl.duplicateDataQuery(target)">Duplicate</a></li>
<li role="menuitem"><a tabindex="1" ng-click="panelCtrl.moveDataQuery($index, $index-1)">Move up</a></li>
<li role="menuitem"><a tabindex="1" ng-click="panelCtrl.moveDataQuery($index, $index+1)">Move down</a></li>
</ul>
</div>
</li>
<li class="tight-form-item last">
<a class="pointer" tabindex="1" ng-click="removeDataQuery(target)">
<a class="pointer" tabindex="1" ng-click="panelCtrl.removeDataQuery(target)">
<i class="fa fa-remove"></i>
</a>
</li>
@ -29,7 +28,7 @@
</li>
<li>
<a class="tight-form-item"
ng-click="target.hide = !target.hide; get_data();"
ng-click="target.hide = !target.hide; panelCtrl.refresh();"
role="menuitem">
<i class="fa fa-eye"></i>
</a>

View File

@ -9,6 +9,7 @@ function (angular, _, kbn) {
var module = angular.module('grafana.controllers');
module.controller('OpenTSDBQueryCtrl', function($scope) {
$scope.panelCtrl = $scope.ctrl;
$scope.init = function() {
$scope.target.errors = validateTarget($scope.target);

View File

@ -5,11 +5,11 @@ function (PromDatasource) {
'use strict';
function metricsQueryEditor() {
return {controller: 'PrometheusQueryCtrl', templateUrl: 'app/plugins/datasource/prometheus/partials/query.editor.html'};
return {controller: 'PrometheusQueryCtrl', templateUrl: 'public/app/plugins/datasource/prometheus/partials/query.editor.html'};
}
function configView() {
return {templateUrl: 'app/plugins/datasource/prometheus/partials/config.html'};
return {templateUrl: 'public/app/plugins/datasource/prometheus/partials/config.html'};
}
return {

View File

@ -9,15 +9,14 @@
<i class="fa fa-bars"></i>
</a>
<ul class="dropdown-menu pull-right" role="menu">
<li role="menuitem"><a tabindex="1" ng-click="toggleQueryMode()">Switch editor mode</a></li>
<li role="menuitem"><a tabindex="1" ng-click="duplicateDataQuery(target)">Duplicate</a></li>
<li role="menuitem"><a tabindex="1" ng-click="moveDataQuery($index, $index-1)">Move up</a></li>
<li role="menuitem"><a tabindex="1" ng-click="moveDataQuery($index, $index+1)">Move down</a></li>
<li role="menuitem"><a tabindex="1" ng-click="panelCtrl.duplicateDataQuery(target)">Duplicate</a></li>
<li role="menuitem"><a tabindex="1" ng-click="panelCtrl.moveDataQuery($index, $index-1)">Move up</a></li>
<li role="menuitem"><a tabindex="1" ng-click="panelCtrl.moveDataQuery($index, $index+1)">Move down</a></li>
</ul>
</div>
</li>
<li class="tight-form-item last">
<a class="pointer" tabindex="1" ng-click="removeDataQuery(target)">
<a class="pointer" tabindex="1" ng-click="panelCtr.removeDataQuery(target)">
<i class="fa fa-remove"></i>
</a>
</li>
@ -29,7 +28,7 @@
</li>
<li>
<a class="tight-form-item"
ng-click="target.hide = !target.hide; get_data();"
ng-click="target.hide = !target.hide; panelCtrl.refresh();"
role="menuitem">
<i class="fa fa-eye"></i>
</a>

View File

@ -8,6 +8,8 @@ function (angular, _) {
var module = angular.module('grafana.controllers');
module.controller('PrometheusQueryCtrl', function($scope, templateSrv) {
$scope.panelCtrl = $scope.ctrl;
$scope.panel = $scope.panelCtrl.panel;
$scope.init = function() {
var target = $scope.target;
@ -29,7 +31,7 @@ function (angular, _) {
$scope.refreshMetricData = function() {
if (!_.isEqual($scope.oldTarget, $scope.target)) {
$scope.oldTarget = angular.copy($scope.target);
$scope.get_data();
$scope.paneCtrl.refresh();
}
};

View File

@ -31,7 +31,7 @@ class DashListCtrl extends PanelCtrl {
this.modes = ['starred', 'search'];
this.icon = "fa fa-star";
this.addEditorTab('Options', () => {
return {templateUrl: 'app/plugins/panel/dashlist/editor.html'};
return {templateUrl: 'public/app/plugins/panel/dashlist/editor.html'};
});
}

View File

@ -46,7 +46,7 @@ function (angular, _, $) {
popoverScope.series = seriesInfo;
popoverSrv.show({
element: el,
templateUrl: 'app/plugins/panel/graph/legend.popover.html',
templateUrl: 'public/app/plugins/panel/graph/legend.popover.html',
scope: popoverScope
});
}

View File

@ -60,7 +60,7 @@ define([
popoverSrv.show({
element: $element.find(".dropdown"),
placement: 'top',
templateUrl: 'app/partials/colorpicker.html',
templateUrl: 'public/app/partials/colorpicker.html',
scope: popoverScope
});
};

View File

@ -7,7 +7,7 @@ import {SingleStatCtrl} from './controller';
import {PanelDirective} from '../../../features/panel/panel';
class SingleStatPanel extends PanelDirective {
templateUrl = 'app/plugins/panel/singlestat/module.html';
templateUrl = 'public/app/plugins/panel/singlestat/module.html';
controller = SingleStatCtrl;
/** @ngInject */

View File

@ -2,9 +2,6 @@
import {describe, beforeEach, it, sinon, expect, angularMocks} from '../../../../../test/lib/common';
import 'app/features/panel/panel_srv';
import 'app/features/panel/panel_helper';
import angular from 'angular';
import helpers from '../../../../../test/specs/helpers';
import {SingleStatCtrl} from '../controller';

View File

@ -136,7 +136,7 @@ export function tablePanelEditor($q, uiSegmentSrv) {
return {
restrict: 'E',
scope: true,
templateUrl: 'app/plugins/panel/table/editor.html',
templateUrl: 'public/app/plugins/panel/table/editor.html',
controller: TablePanelEditorCtrl,
};
}

View File

@ -10,7 +10,7 @@ import {TablePanelCtrl} from './controller';
import {TableRenderer} from './renderer';
class TablePanel extends PanelDirective {
templateUrl = 'app/plugins/panel/table/module.html';
templateUrl = 'public/app/plugins/panel/table/module.html';
controller = TablePanelCtrl;
link(scope, elem, attrs, ctrl) {

View File

@ -78,7 +78,7 @@ export class TextPanelCtrl extends PanelCtrl {
}
class TextPanel extends PanelDirective {
templateUrl = `app/plugins/panel/text/module.html`;
templateUrl = `public/app/plugins/panel/text/module.html`;
controller = TextPanelCtrl;
}

View File

@ -1,5 +1,5 @@
<div class="text-center" style="padding-top: 2rem">
Unknown panel type: <strong>{{ctrl.panel.type}}</strong>
</div
</div>

View File

@ -37,7 +37,7 @@ Example:
```javascript
function metricsQueryEditor() {
return {controller: 'ElasticQueryCtrl', templateUrl: 'app/plugins/datasource/elasticsearch/partials/query.editor.html'};
return {controller: 'ElasticQueryCtrl', templateUrl: 'public/app/plugins/datasource/elasticsearch/partials/query.editor.html'};
}
```

View File

@ -12,10 +12,10 @@
{
"collapse": false,
"editable": true,
"height": "100px",
"height": "90px",
"panels": [
{
"content": "<div class=\"text-center dashboard-header\">\nHome Dashboard\n</div>",
"content": "<div class=\"text-center dashboard-header\">\n <span>Home Dashboard</span>\n</div>",
"editable": true,
"id": 1,
"mode": "html",
@ -23,7 +23,8 @@
"style": {},
"title": "",
"transparent": true,
"type": "text"
"type": "text",
"links": []
}
],
"title": "New row"

View File

@ -391,12 +391,15 @@
}
.dashboard-header {
margin-top: 1rem;
font-family: "grafana-icons";
font-size: 22px;
padding-bottom: 1rem;
border: none;
border-bottom: 2px solid transparent;
border-image: linear-gradient(to right, rgba(255,213,0,1) 0%, rgba(255,68,0,1) 99%, rgba(255,68,0,1) 100%);
border-image-slice: 1;
text-align: center;
span {
display: inline-block;
border: none;
border-image: linear-gradient(to right, rgba(255,213,0,1) 0%, rgba(255,68,0,1) 99%, rgba(255,68,0,1) 100%);
border-image-slice: 1;
border-bottom: 2px solid transparent;
padding: 1.2rem 3rem 0.8rem 3rem;
}
}

View File

@ -9,15 +9,23 @@
.login-box {
width: 700px;
margin: 100px auto 0 auto;
margin: 70px auto 0 auto;
}
.login-box-logo {
text-align: center;
padding-bottom: 50px;
img {
width: 125px;
}
.icon-gf-grafana_wordmark {
color: @linkColor;
position: relative;
top: -90px;
font-size: 3rem;
text-shadow: 3px 3px 5px black;
}
}
.login-inner-box {
background: @grafanaPanelBackground;
}

View File

@ -7,7 +7,7 @@
}
.gf-timepicker-dropdown {
margin: -5px -10px;
margin: -5px -10px 10px 5px;
padding: 10px 20px;
float: right;
background-color: @grafanaPanelBackground;

View File

@ -1,40 +0,0 @@
define([
'./helpers',
'app/features/panel/panel_srv',
], function() {
'use strict';
describe('PanelSrv', function() {
var _panelSrv;
var _panelScope;
var _datasourceSrvStub;
beforeEach(module('grafana.services'));
beforeEach(module(function($provide) {
_datasourceSrvStub = {
getMetricSources: sinon.spy(),
};
$provide.value('datasourceSrv', _datasourceSrvStub);
}));
beforeEach(inject(function(panelSrv, $rootScope) {
_panelSrv = panelSrv;
_panelScope = $rootScope.$new();
_panelScope.panel = {
targets: [],
};
_panelScope.dashboardViewState = {
registerPanel: sinon.spy(),
};
}));
describe('init', function() {
beforeEach(function() {
_panelSrv.init(_panelScope);
});
});
});
});

View File

@ -5,6 +5,7 @@ module.exports = function(config) {
src: ['app/**/*.html'],
dest: '<%= genDir %>/app/core/partials.js',
options: {
prefix: 'public/',
bootstrap: function(module, script) {
return "define('app/core/partials', ['app/core/core_module'], function(coreModule) { \n" +
"coreModule.default.run(['$templateCache', function($templateCache) { \n" +