Commit 04ec2224 by Torkel Ödegaard

Big refactoring of the way panels are loaded and how they are built using…

Big refactoring of the way panels are loaded and how they are built using directives, this way feel cleaner and allowed for placing the panel edit box outside the panel-container
parent b67f4dc3
......@@ -6,6 +6,8 @@ function () {
function PanelMeta(options) {
this.description = options.description;
this.fullscreen = options.fullscreen;
this.editIcon = options.editIcon;
this.panelName = options.panelName;
this.menu = [];
this.editorTabs = [];
this.extendedMenu = [];
......
......@@ -18,7 +18,7 @@ function (_, crypto) {
panels : {
'graph': { path: 'panels/graph' },
'singlestat': { path: 'panels/singlestat' },
'text': { path: 'panels/text' }
'text': { path: 'panels/text' },
},
plugins : {},
default_route : '/dashboard/file/default.json',
......
......@@ -143,7 +143,6 @@ function (angular, _, config, $) {
};
$scope.newDashboard = function() {
//$location.path('/dashboard/file/empty.json');
$location.url('dashboard/new');
};
......
define([
'./arrayJoin',
'./dashUpload',
'./grafanaPanel',
'./grafanaSimplePanel',
'./ngBlur',
'./dashEditLink',
......
define([
'angular',
'jquery',
'config',
'./panelMenu',
],
function (angular, $, config) {
'use strict';
angular
.module('grafana.directives')
.directive('grafanaPanel', function($compile, $parse) {
var container = '<div class="panel-container"></div>';
var content = '<div class="panel-content"></div>';
var panelHeader =
'<div class="panel-header">'+
'<span class="alert-error panel-error small pointer"' +
'config-modal="app/partials/inspector.html" ng-if="panelMeta.error">' +
'<span data-placement="top" bs-tooltip="panelMeta.error">' +
'<i class="fa fa-exclamation"></i><span class="panel-error-arrow"></span>' +
'</span>' +
'</span>' +
'<span class="panel-loading" ng-show="panelMeta.loading">' +
'<i class="fa fa-spinner fa-spin"></i>' +
'</span>' +
'<div class="panel-title-container drag-handle" panel-menu></div>' +
'</div>'+
'</div>';
return {
restrict: 'E',
link: function($scope, elem, attr) {
var getter = $parse(attr.type), panelType = getter($scope);
var newScope = $scope.$new();
// compile the module and uncloack. We're done
function loadModule($module) {
$module.appendTo(elem);
elem.wrap(container);
$compile(elem.contents())(newScope);
elem.removeClass("ng-cloak");
var panelCtrlElem = $(elem.children()[0]);
var panelCtrlScope = panelCtrlElem.data().$scope;
panelCtrlScope.$watchGroup(['fullscreen', 'panel.height', 'row.height'], function() {
panelCtrlElem.css({ minHeight: panelCtrlScope.panel.height || panelCtrlScope.row.height });
panelCtrlElem.toggleClass('panel-fullscreen', panelCtrlScope.fullscreen ? true : false);
});
}
newScope.$on('$destroy',function() {
elem.unbind();
elem.remove();
});
elem.addClass('ng-cloak');
var panelPath = config.panels[panelType].path;
$scope.require([
'jquery',
'text!'+panelPath+'/module.html',
panelPath + "/module",
], function ($, moduleTemplate) {
var $module = $(moduleTemplate);
$module.prepend(panelHeader);
$module.first().find('.panel-header').nextAll().wrapAll(content);
loadModule($module);
});
}
};
});
});
<topnav toggle="toggleSideMenu()" icon="fa fa-shield" section="Account" show-menu-btn="!grafana.sidemenu">
<!-- <ul class="nav"> -->
<!-- <li> -->
<!-- <a href="asd">Details</a> -->
<!-- </li> -->
<!-- <li> -->
<!-- <a href="asd">Data Sources</a> -->
<!-- </li> -->
<!-- <li> -->
<!-- <a href="asd">Users</a> -->
<!-- </li> -->
<!-- <li> -->
<!-- <a href="asd">API Keys</a> -->
<!-- </li> -->
<!-- </ul> -->
</topnav>
<div class="gf-box" style="min-height: 500px">
......@@ -22,19 +8,23 @@
<div class="section">
<form name="accountForm">
<div>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 120px">
<strong>Account name</strong>
</li>
<li>
<input type="text" required ng-model="account.name" class="input-xlarge tight-form-input last" >
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 120px">
<strong>Account name</strong>
</li>
<li>
<input type="text" required ng-model="account.name" class="input-xlarge tight-form-input last" >
</li>
</ul>
<div class="clearfix"></div>
</div>
</div>
<br>
<panel-loader type="'test'"></panel-loader>
<br>
<button type="submit" class="pull-right btn btn-success" ng-click="update()">Update</button>
</form>
</div>
......
......@@ -7,6 +7,7 @@ define([
'./opentsdb/datasource',
'./elasticsearch/datasource',
'./dashboard/all',
'./panel/all',
'./profile/profileCtrl',
'./account/accountUsersCtrl',
'./account/datasourcesCtrl',
......
......@@ -9,7 +9,6 @@ define([
'./keybindings',
'./viewStateSrv',
'./playlistSrv',
'./panelSrv',
'./soloPanelCtrl',
'./timeSrv',
'./unsavedChangesSrv',
......
......@@ -118,7 +118,7 @@ function (angular, _, $) {
self.$scope.dashboard.emit_refresh();
}
else {
self.fullscreenPanel.$emit('render');
self.fullscreenPanel.$broadcast('render');
}
delete self.fullscreenPanel;
});
......@@ -139,7 +139,7 @@ function (angular, _, $) {
panelScope.fullscreen = true;
$timeout(function() {
panelScope.$emit('render');
panelScope.$broadcast('render');
});
};
......
define([
'./panelMenu',
'./panelDirective',
'./panelSrv',
], function () {});
define([
'angular',
'jquery',
'config',
],
function (angular, $, config) {
'use strict';
angular
.module('grafana.directives')
.directive('panelLoader', function($compile, $parse) {
return {
restrict: 'E',
link: function(scope, elem, attr) {
var getter = $parse(attr.type), panelType = getter(scope);
var panelPath = config.panels[panelType].path;
scope.require([panelPath + "/module"], function () {
var panelEl = angular.element(document.createElement('grafana-panel-' + panelType));
elem.append(panelEl);
$compile(panelEl)(scope);
});
}
};
}).directive('grafanaPanel', function() {
return {
restrict: 'E',
templateUrl: '/app/features/panel/partials/panel.html',
transclude: true,
link: function(scope, elem) {
var panelContainer = elem.find('.panel-container');
scope.$watchGroup(['fullscreen', 'panel.height', 'row.height'], function() {
panelContainer.css({ minHeight: scope.panel.height || scope.row.height, display: 'block' });
elem.toggleClass('panel-fullscreen', scope.fullscreen ? true : false);
});
}
};
});
});
<div class="panel-container">
<div class="panel-header">
<span class="alert-error panel-error small pointer" config-modal="app/partials/inspector.html" ng-if="panelMeta.error">
<span data-placement="top" bs-tooltip="panelMeta.error">
<i class="fa fa-exclamation"></i><span class="panel-error-arrow"></span>
</span>
</span>
<span class="panel-loading" ng-show="panelMeta.loading">
<i class="fa fa-spinner fa-spin"></i>
</span>
<div class="panel-title-container drag-handle" panel-menu></div>
</div>
<div class="panel-content">
<ng-transclude></ng-transclude>
</div>
</div>
<div class="panel-full-edit" ng-if="editMode">
<div class="gf-box">
<div class="gf-box-header">
<div class="gf-box-title">
<i ng-class="panelMeta.editIcon"></i>
{{panelMeta.panelName}}
</div>
<div ng-model="editor.index" bs-tabs>
<div ng-repeat="tab in panelMeta.editorTabs" data-title="{{tab.title}}">
</div>
</div>
</div>
<div class="gf-box-body">
<div ng-repeat="tab in panelMeta.editorTabs" ng-if="editor.index === $index">
<div ng-include src="tab.src"></div>
</div>
</div>
</div>
</div>
<div ng-controller='GraphCtrl'>
<grafana-panel>
<div class="graph-wrapper" ng-class="{'graph-legend-rightside': panel.legend.rightSide}">
<div class="graph-canvas-wrapper">
......@@ -24,23 +24,6 @@
<div class="clearfix"></div>
<div class="gf-box gf-box-full-edit" ng-if="editMode">
<div class="gf-box-header">
<div class="gf-box-title">
<i class="fa fa-bar-chart"></i>
Graph
</div>
</grafana-panel>
<div ng-model="editor.index" bs-tabs>
<div ng-repeat="tab in panelMeta.editorTabs" data-title="{{tab.title}}">
</div>
</div>
</div>
<div class="gf-box-body">
<div ng-repeat="tab in panelMeta.editorTabs" ng-if="editor.index === $index">
<div ng-include src="tab.src"></div>
</div>
</div>
</div>
</div>
......@@ -16,10 +16,18 @@ function (angular, app, $, _, kbn, moment, TimeSeries, PanelMeta) {
var module = angular.module('grafana.panels.graph');
module.directive('grafanaPanelGraph', function() {
return {
controller: 'GraphCtrl',
templateUrl: '/app/panels/graph/module.html',
};
});
module.controller('GraphCtrl', function($scope, $rootScope, panelSrv, annotationsSrv, timeSrv) {
$scope.panelMeta = new PanelMeta({
description: 'Graph panel',
panelName: 'Graph',
editIcon: "fa fa-bar-chart",
fullscreen: true,
metricsEditor: true
});
......
<div ng-controller='SingleStatCtrl'>
<grafana-panel>
<div class="singlestat-panel" singlestat-panel></div>
<div class="clearfix"></div>
<div class="gf-box gf-box-full-edit" ng-if="editMode">
<div class="gf-box-header">
<div class="gf-box-title">
<i class="fa fa-dashboard"></i>
Singlestat
</div>
<div ng-model="editor.index" bs-tabs>
<div ng-repeat="tab in panelMeta.editorTabs" data-title="{{tab.title}}">
</div>
</div>
</div>
<div class="gf-box-body">
<div ng-repeat="tab in panelMeta.editorTabs" ng-if="editor.index === $index">
<div ng-include src="tab.src"></div>
</div>
</div>
</div>
</div>
</grafana-panel>
......@@ -13,10 +13,18 @@ function (angular, app, _, TimeSeries, kbn, PanelMeta) {
var module = angular.module('grafana.panels.singlestat');
app.useModule(module);
module.directive('grafanaPanelSinglestat', function() {
return {
controller: 'SingleStatCtrl',
templateUrl: '/app/panels/singlestat/module.html',
};
});
module.controller('SingleStatCtrl', function($scope, panelSrv, timeSrv) {
$scope.panelMeta = new PanelMeta({
description: 'Singlestat panel',
panelName: 'Singlestat',
editIcon: "fa fa-dashboard",
fullscreen: true,
metricsEditor: true
});
......@@ -192,7 +200,7 @@ function (angular, app, _, TimeSeries, kbn, PanelMeta) {
data.colorMap = $scope.panel.colors;
$scope.data = data;
$scope.$emit('render');
$scope.$broadcast('render');
};
$scope.getFormatedValue = function(mainValue) {
......
<div ng-controller='text'>
<p ng-bind-html="content" ng-show="content">
</p>
</div>
<grafana-panel>
<p ng-bind-html="content" ng-show="content"></p>
</grafana-panel>
......@@ -8,15 +8,24 @@ define([
function (angular, app, _, require, PanelMeta) {
'use strict';
var converter;
var module = angular.module('grafana.panels.text', []);
app.useModule(module);
var converter;
module.directive('grafanaPanelText', function() {
return {
controller: 'TextPanelCtrl',
templateUrl: '/app/panels/text/module.html',
};
});
module.controller('text', function($scope, templateSrv, $sce, panelSrv) {
module.controller('TextPanelCtrl', function($scope, templateSrv, $sce, panelSrv) {
$scope.panelMeta = new PanelMeta({
description : "A static text panel that can use plain text, markdown, or (sanitized) HTML"
panelName: 'Text',
editIcon: "fa fa-text-width",
fullscreen: true,
});
$scope.panelMeta.addEditorTab('Edit text', 'app/panels/text/editor.html');
......
......@@ -79,12 +79,11 @@
</div>
<!-- Panels, draggable needs to be disabled in fullscreen because Firefox bug -->
<div ng-repeat="(name, panel) in row.panels"
class="panel"
<div ng-repeat="(name, panel) in row.panels" class="panel"
ui-draggable="{{!dashboardViewState.fullscreen}}" drag="panel.id"
ui-on-Drop="onDrop($data, row, panel)"
drag-handle-class="drag-handle" panel-width ng-model="panel">
<grafana-panel type="panel.type" ng-cloak></grafana-panel>
drag-handle-class="drag-handle" panel-width>
<panel-loader type="panel.type" class="panel-margin"></panel-loader>
</div>
<div panel-drop-zone class="panel panel-drop-zone"
......
<div bindonce class="gf-box-header">
<div class="gf-box-title">
<i class="fa fa-text-width"></i>
<span bo-text="panel.type+' settings'"></span>
</div>
<div ng-model="editor.index" bs-tabs style="text-transform:capitalize;">
<div ng-repeat="tab in panelMeta.editorTabs" data-title="{{tab.title}}">
</div>
</div>
<button class="gf-box-header-close-btn" ng-click="dismiss();">
<i class="fa fa-remove"></i>
</button>
</div>
<div class="gf-box-body">
<div ng-repeat="tab in panelMeta.editorTabs" ng-show="editor.index == $index">
<div ng-include src="tab.src"></div>
</div>
</div>
......@@ -58,7 +58,7 @@ function (angular, store) {
$location.path('');
return;
}
$scope.initDashboard(window.grafanaImportDashboard, $scope);
$scope.initDashboard({ meta: {}, model: window.grafanaImportDashboard }, $scope);
});
module.controller('NewDashboardCtrl', function($scope) {
......
......@@ -5,10 +5,6 @@
border: 1px solid @grafanaTargetFuncBackground;
}
.gf-box-full-edit {
margin: 30px 0 0 0;
}
.gf-box-no-margin {
margin: 0;
}
......
......@@ -5,10 +5,13 @@
position: relative;
}
.panel-margin {
margin: 5px;
display: block;
}
.panel-container {
padding: 0px 0px 0px 0px;
background: @grafanaPanelBackground;
margin: 5px;
position: relative;
&:hover {
.panel-actions {
......@@ -91,17 +94,17 @@
top: 60px;
height: 100%;
padding: 0;
background: @grafanaPanelBackground;
overflow-y: auto;
height: 100%;
.panel-content {
padding-bottom: 130px;
}
.dropdown-menu {
margin-bottom: 70px;
}
.panel-container {
margin: 15px;
}
.panel-menu {
top: 0px;
}
......@@ -110,6 +113,11 @@
}
}
.panel-full-edit {
margin-top: 30px;
padding-bottom: 130px;
}
.panel-menu {
z-index: 1000;
position: absolute;
......
define([
'helpers',
'features/dashboard/panelSrv',
'features/panel/panelSrv',
'panels/graph/module'
], function(helpers) {
'use strict';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment