Commit 01627b3a by Torkel Ödegaard

feat(ux): dashboard edit mode progress

parent 29e834e7
......@@ -26,7 +26,6 @@ export class DashboardCtrl {
$timeout) {
$scope.editor = { index: 0 };
$scope.panels = config.panels;
var resizeEventTimeout;
......@@ -107,22 +106,12 @@ export class DashboardCtrl {
$rootScope.$broadcast('refresh');
};
$scope.addRow = function(dash, row) {
dash.rows.push(row);
};
$scope.addRowDefault = function() {
$scope.resetRow();
$scope.row.title = 'New row';
$scope.addRow($scope.dashboard, $scope.row);
};
$scope.resetRow = function() {
$scope.row = {
title: '',
$scope.dashboard.rows.push({
title: 'New row',
panels: [],
height: '250px',
editable: true,
};
});
};
$scope.showJsonEditor = function(evt, options) {
......@@ -132,24 +121,6 @@ export class DashboardCtrl {
$scope.appEvent('show-dash-editor', { src: 'public/app/partials/edit_json.html', scope: editScope });
};
$scope.onDrop = function(panelId, row, dropTarget) {
var info = $scope.dashboard.getPanelInfoById(panelId);
if (dropTarget) {
var dropInfo = $scope.dashboard.getPanelInfoById(dropTarget.id);
dropInfo.row.panels[dropInfo.index] = info.panel;
info.row.panels[info.index] = dropTarget;
var dragSpan = info.panel.span;
info.panel.span = dropTarget.span;
dropTarget.span = dragSpan;
} else {
info.row.panels.splice(info.index, 1);
info.panel.span = 12 - $scope.dashboard.rowSpan(row);
row.panels.push(info.panel);
}
$rootScope.$broadcast('render');
};
$scope.registerWindowResizeEvent = function() {
angular.element(window).bind('resize', function() {
$timeout.cancel(resizeEventTimeout);
......@@ -166,7 +137,6 @@ export class DashboardCtrl {
}
init(dashboard) {
this.$scope.resetRow();
this.$scope.registerWindowResizeEvent();
this.$scope.onAppEvent('show-json-editor', this.$scope.showJsonEditor);
this.$scope.onAppEvent('template-variable-value-updated', this.$scope.templateVariableUpdated);
......
......@@ -11,18 +11,15 @@
<div class="dash-row-header pointer" ng-if="ctrl.dashboard.editMode">
<div class="dash-row-header-title" ng-bind="ctrl.row.title | interpolateTemplateVars:this"></div>
<div class="dash-row-header-settings dropdown">
<!-- <a class="pointer dropdown&#45;toggle" data&#45;toggle="dropdown"> -->
<!-- <i class="fa fa&#45;cog"></i> -->
<!-- </a> -->
<a class="pointer dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-plus-circle"></i>
</a>
<ul class="dropdown-menu dropdown-menu-right" role="menu" aria-labelledby="drop1">
<li>
<a ng-click="toggleRow(row)">Collapse row</a>
</li>
<li class="dropdown-submenu">
<a href="javascript:void(0);">Add Panel</a>
<ul class="dropdown-menu">
<li bindonce ng-repeat="(key, value) in panels">
<a ng-click="addPanelDefault(key)" bo-text="value.name"></a>
<li bindonce ng-repeat="(key, value) in ctrl.panelPlugins">
<a ng-click="ctrl.addPanelDefault(key)" bo-text="value.name"></a>
</li>
</ul>
</li>
......@@ -42,20 +39,20 @@
<li><a ng-click="setHeight('700px')">700 px</a></li>
</ul>
</li>
<li class="dropdown-submenu">
<a href="javascript:void(0);">Move</a>
<ul class="dropdown-menu">
<li><a ng-click="moveRow('up')">Up</a></li>
<li><a ng-click="moveRow('down')">Down</a></li>
<li><a ng-click="moveRow('top')">To top</a></li>
<li><a ng-click="moveRow('bottom')">To Bottom</a></li>
</ul>
</li>
<!-- <li class="dropdown&#45;submenu"> -->
<!-- <a href="javascript:void(0);">Move</a> -->
<!-- <ul class="dropdown&#45;menu"> -->
<!-- <li><a ng&#45;click="moveRow('up')">Up</a></li> -->
<!-- <li><a ng&#45;click="moveRow('down')">Down</a></li> -->
<!-- <li><a ng&#45;click="moveRow('top')">To top</a></li> -->
<!-- <li><a ng&#45;click="moveRow('bottom')">To Bottom</a></li> -->
<!-- </ul> -->
<!-- </li> -->
<li>
<a ng-click="editRow()">Row editor</a>
<a ng-click="ctrl.editRow()">Row options</a>
</li>
<li>
<a ng-click="deleteRow()">Delete row</a>
<a ng-click="ctrl.deleteRow()">Delete row</a>
</li>
</ul>
</div>
......@@ -68,12 +65,12 @@
</div>
<div class="panels-wrapper" ng-if="!ctrl.row.collapse">
<div ng-repeat="panel in ctrl.row.panels track by panel.id" class="panel" ui-draggable="!ctrl.dashboard.meta.fullscreen" drag="panel.id" ui-on-drop="onDrop($data, row, panel)" drag-handle-class="drag-handle" panel-width>
<div ng-repeat="panel in ctrl.row.panels track by panel.id" class="panel" ui-draggable="!ctrl.dashboard.meta.fullscreen" drag="panel.id" ui-on-drop="ctrl.onDrop($data, panel)" drag-handle-class="drag-handle" panel-width>
<plugin-component type="panel" class="panel-margin">
</plugin-component>
</div>
<div panel-drop-zone class="panel panel-drop-zone" ui-on-drop="onDrop($data, row)" data-drop="true">
<div panel-drop-zone class="panel panel-drop-zone" ui-on-drop="ctrl.onDrop($data)" data-drop="true">
<div class="panel-container" style="background: transparent">
<div style="text-align: center">
<em>Drop here</em>
......
///<reference path="../../../headers/common.d.ts" />
import _ from 'lodash';
import coreModule from 'app/core/core_module';
import config from 'app/core/config';
import {coreModule, appEvents} from 'app/core/core';
export class DashRowCtrl {
showTitle: boolean;
dashboard: any;
row: any;
panelPlugins;
/** @ngInject */
constructor(private $scope, private $rootScope) {
this.showTitle = true;
this.-
this.panelPlugins = config.panels;
}
}
onDrop(panelId, dropTarget) {
var info = this.dashboard.getPanelInfoById(panelId);
if (dropTarget) {
var dropInfo = this.dashboard.getPanelInfoById(dropTarget.id);
dropInfo.row.panels[dropInfo.index] = info.panel;
info.row.panels[info.index] = dropTarget;
var dragSpan = info.panel.span;
info.panel.span = dropTarget.span;
dropTarget.span = dragSpan;
} else {
info.row.panels.splice(info.index, 1);
info.panel.span = 12 - this.dashboard.rowSpan(this.row);
this.row.panels.push(info.panel);
}
this.$rootScope.$broadcast('render');
}
addPanel(panel) {
this.dashboard.addPanel(panel, this.row);
}
editRow() {
// this.appEvent('show-dash-editor', {
// src: 'public/app/partials/roweditor.html',
// scope: this.$scope.$new()
// });
}
addPanelDefault(type) {
var defaultSpan = 12;
var _as = 12 - this.dashboard.rowSpan(this.row);
var panel = {
title: config.new_panel_title,
error: false,
span: _as < defaultSpan && _as > 0 ? _as : defaultSpan,
editable: true,
type: type,
isNew: true,
};
export function rowDirective() {
this.addPanel(panel);
}
deleteRow() {
if (!this.row.panels.length) {
this.dashboard.rows = _.without(this.dashboard.rows, this.row);
return;
}
appEvents.emit('confirm-modal', {
title: 'Delete',
text: 'Are you sure you want to delete this row?',
icon: 'fa-trash',
yesText: 'Delete',
onConfirm: () => {
this.dashboard.rows = _.without(this.dashboard.rows, this.row);
}
});
}
}
export function rowDirective($rootScope) {
return {
restrict: 'E',
templateUrl: 'public/app/features/dashboard/row/row.html',
......@@ -25,6 +87,22 @@ export function rowDirective() {
scope: {
dashboard: "=",
row: "=",
},
link: function(scope, element) {
scope.$watchGroup(['ctrl.row.collapse', 'ctrl.row.height'], function() {
element.css({minHeight: scope.ctrl.row.collapse ? '5px' : scope.ctrl.row.height});
});
$rootScope.onAppEvent('panel-fullscreen-enter', function(evt, info) {
var hasPanel = _.find(scope.ctrl.row.panels, {id: info.panelId});
if (!hasPanel) {
element.hide();
}
}, scope);
$rootScope.onAppEvent('panel-fullscreen-exit', function() {
element.show();
}, scope);
}
};
}
......@@ -63,7 +141,7 @@ coreModule.directive('panelWidth', function($rootScope) {
updateWidth();
}, scope);
scope.$watch('ctrl.panel.span', updateWidth);
scope.$watch('panel.span', updateWidth);
if (fullscreen) {
element.hide();
......@@ -71,3 +149,23 @@ coreModule.directive('panelWidth', function($rootScope) {
};
});
coreModule.directive('panelDropZone', function($timeout) {
return function(scope, element) {
scope.$on("ANGULAR_DRAG_START", function() {
$timeout(function() {
var dropZoneSpan = 12 - scope.ctrl.dashboard.rowSpan(scope.ctrl.row);
if (dropZoneSpan > 0) {
element.find('.panel-container').css('height', scope.ctrl.row.height);
element[0].style.width = ((dropZoneSpan / 1.2) * 10) + '%';
element.show();
}
});
});
scope.$on("ANGULAR_DRAG_END", function() {
element.hide();
});
};
});
define([
'angular',
'lodash',
'app/core/config'
],
function (angular, _, config) {
'use strict';
var module = angular.module('grafana.controllers');
module.controller('RowCtrl', function($scope, $rootScope, $timeout) {
var _d = {
title: "Row",
height: "150px",
collapse: false,
editable: true,
panels: [],
};
_.defaults($scope.row,_d);
$scope.init = function() {
$scope.editor = {index: 0};
};
$scope.togglePanelMenu = function(posX) {
$scope.showPanelMenu = !$scope.showPanelMenu;
$scope.panelMenuPos = posX;
};
$scope.toggleRow = function(row) {
row.collapse = row.collapse ? false : true;
};
$scope.settingsHover = function(row) {
// Shows/hides the settings button on hover
return row.hoverSettings = ! row.hoverSettings;
};
$scope.addPanel = function(panel) {
$scope.dashboard.addPanel(panel, $scope.row);
};
$scope.deleteRow = function() {
function delete_row() {
$scope.dashboard.rows = _.without($scope.dashboard.rows, $scope.row);
}
if (!$scope.row.panels.length) {
delete_row();
return;
}
$scope.appEvent('confirm-modal', {
title: 'Delete',
text: 'Are you sure you want to delete this row?',
icon: 'fa-trash',
yesText: 'Delete',
onConfirm: function() {
delete_row();
}
});
};
$scope.editRow = function() {
$scope.appEvent('show-dash-editor', {
src: 'public/app/partials/roweditor.html',
scope: $scope.$new()
});
};
$scope.moveRow = function(direction) {
var rowsList = $scope.dashboard.rows;
var rowIndex = _.indexOf(rowsList, $scope.row);
var newIndex = rowIndex;
switch(direction) {
case 'up': {
newIndex = rowIndex - 1;
break;
}
case 'down': {
newIndex = rowIndex + 1;
break;
}
case 'top': {
newIndex = 0;
break;
}
case 'bottom': {
newIndex = rowsList.length - 1;
break;
}
default: {
newIndex = rowIndex;
}
}
if (newIndex >= 0 && newIndex <= (rowsList.length - 1)) {
_.move(rowsList, rowIndex, newIndex);
}
};
$scope.addPanelDefault = function(type) {
var defaultSpan = 12;
var _as = 12 - $scope.dashboard.rowSpan($scope.row);
var panel = {
title: config.new_panel_title,
error: false,
span: _as < defaultSpan && _as > 0 ? _as : defaultSpan,
editable: true,
type: type,
isNew: true,
};
$scope.addPanel(panel);
$timeout(function() {
$scope.dashboardViewState.update({fullscreen: true, edit: true, panelId: panel.id });
});
};
$scope.setHeight = function(height) {
$scope.row.height = height;
$scope.$broadcast('render');
};
$scope.init();
});
module.directive('rowHeight', function() {
return function(scope, element) {
scope.$watchGroup(['row.collapse', 'row.height'], function() {
element.css({ minHeight: scope.row.collapse ? '5px' : scope.row.height });
});
scope.onAppEvent('panel-fullscreen-enter', function(evt, info) {
var hasPanel = _.find(scope.row.panels, {id: info.panelId});
if (!hasPanel) {
element.hide();
}
});
scope.onAppEvent('panel-fullscreen-exit', function() {
element.show();
});
};
});
module.directive('panelDropZone', function() {
return function(scope, element) {
scope.$on("ANGULAR_DRAG_START", function() {
var dropZoneSpan = 12 - scope.dashboard.rowSpan(scope.row);
if (dropZoneSpan > 0) {
element.find('.panel-container').css('height', scope.row.height);
element[0].style.width = ((dropZoneSpan / 1.2) * 10) + '%';
element.show();
}
});
scope.$on("ANGULAR_DRAG_END", function() {
element.hide();
});
};
});
});
// define([
// 'angular',
// 'lodash',
// 'app/core/config'
// ],
// function (angular, _, config) {
// 'use strict';
//
// var module = angular.module('grafana.controllers');
//
// module.controller('RowCtrl', function($scope, $rootScope, $timeout) {
//
// $scope.moveRow = function(direction) {
// var rowsList = $scope.dashboard.rows;
// var rowIndex = _.indexOf(rowsList, $scope.row);
// var newIndex = rowIndex;
// switch(direction) {
// case 'up': {
// newIndex = rowIndex - 1;
// break;
// }
// case 'down': {
// newIndex = rowIndex + 1;
// break;
// }
// case 'top': {
// newIndex = 0;
// break;
// }
// case 'bottom': {
// newIndex = rowsList.length - 1;
// break;
// }
// default: {
// newIndex = rowIndex;
// }
// }
// if (newIndex >= 0 && newIndex <= (rowsList.length - 1)) {
// _.move(rowsList, rowIndex, newIndex);
// }
// };
//
// $scope.setHeight = function(height) {
// $scope.row.height = height;
// $scope.$broadcast('render');
// };
//
// $scope.init();
// });
//
// });
......@@ -149,6 +149,7 @@ function (angular, _, $) {
ctrl.editMode = false;
ctrl.fullscreen = false;
ctrl.dashboard.editMode = this.oldDashboardEditMode;
this.$scope.appEvent('panel-fullscreen-exit', {panelId: ctrl.panel.id});
......@@ -170,8 +171,10 @@ function (angular, _, $) {
ctrl.editMode = this.state.edit && this.dashboard.meta.canEdit;
ctrl.fullscreen = true;
this.oldDashboardEditMode = this.dashboard.editMode;
this.oldTimeRange = ctrl.range;
this.fullscreenPanel = panelScope;
this.dashboard.editMode = false;
$(window).scrollTop(0);
......
......@@ -384,7 +384,6 @@ module.directive('grafanaGraph', function($rootScope, timeSrv) {
if (!annotations || annotations.length === 0) {
return;
}
console.log(annotations);
var types = {};
types['$__alerting'] = {
......
......@@ -80,7 +80,7 @@ $enable-flex: false;
// Typography
// -------------------------
$font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif;
$font-family-sans-serif: "Open Sans", Helvetica, Arial, sans-serif;
$font-family-serif: Georgia, "Times New Roman", Times, serif;
$font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
$font-family-base: $font-family-sans-serif !default;
......
......@@ -211,7 +211,7 @@ div.flot-text {
.dash-row-handle-column {
width: 2rem;
background: $page-bg;
background: $input-label-bg;
display: flex;
flex-direction: column;
}
......@@ -235,7 +235,7 @@ div.flot-text {
flex-direction: row;
text-align: left;
align-items: center;
background: $page-bg;
background: $input-label-bg;
margin-right: $panel-margin;
}
......
......@@ -290,12 +290,12 @@
sendData = angular.fromJson(sendData);
var dropOffset = calculateDropOffset(e);
var position = dropOffset ? {
x: dropOffset.x - sendData.offset.x,
y: dropOffset.y - sendData.offset.y
} : null;
determineEffectAllowed(e);
var uiOnDropFn = $parse(attr.uiOnDrop);
......@@ -305,7 +305,7 @@
element.removeClass(dragEnterClass);
dragging = 0;
}
function isDragChannelAccepted(dragChannel, dropChannel) {
if (dropChannel === '*') {
return true;
......
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