diff --git a/package.json b/package.json index 40badc957ff..7ed1404990c 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "license": "Apache-2.0", "dependencies": { "eventemitter3": "^1.2.0", + "gaze": "^1.1.2", "grunt-jscs": "~1.5.x", "grunt-sass-lint": "^0.2.0", "grunt-sync": "^0.4.1", diff --git a/public/app/core/services/keybindingSrv.ts b/public/app/core/services/keybindingSrv.ts index 4c6ec6af57c..e5c31f88887 100644 --- a/public/app/core/services/keybindingSrv.ts +++ b/public/app/core/services/keybindingSrv.ts @@ -66,6 +66,7 @@ export class KeybindingSrv { Mousetrap.bind(keyArg, evt => { evt.preventDefault(); evt.stopPropagation(); + evt.returnValue = false; return this.$rootScope.$apply(fn.bind(this)); }); } @@ -80,31 +81,32 @@ export class KeybindingSrv { // dashboard.toggleEditMode(); // }); - this.bind('ctrl+o', () => { + this.bind('mod+o', () => { dashboard.sharedCrosshair = !dashboard.sharedCrosshair; scope.broadcastRefresh(); }); - this.bind('ctrl+h', () => { + this.bind('mod+h', () => { dashboard.hideControls = !dashboard.hideControls; }); - this.bind(['ctrl+s', 'command+s'], () => { + this.bind('mod+s', e => { scope.appEvent('save-dashboard'); }); - this.bind('ctrl+z', () => { + + this.bind('t z', () => { scope.appEvent('zoom-out'); }); - this.bind('left', () => { + this.bind('t left', () => { scope.appEvent('shift-time-backward'); }); - this.bind('right', () => { + this.bind('t right', () => { scope.appEvent('shift-time-forward'); }); - this.bind('ctrl+i', () => { + this.bind('mod+i', () => { scope.appEvent('quick-snapshot'); }); @@ -133,7 +135,7 @@ export class KeybindingSrv { }); // delete panel - this.bind('r', () => { + this.bind('p r', () => { if (dashboard.meta.focusPanelId && dashboard.meta.canEdit) { var panelInfo = dashboard.getPanelInfoById(dashboard.meta.focusPanelId); panelInfo.row.removePanel(panelInfo.panel); @@ -141,8 +143,26 @@ export class KeybindingSrv { } }); - // delete panel - this.bind('s', () => { + // delete row + this.bind('r r', () => { + if (dashboard.meta.focusPanelId && dashboard.meta.canEdit) { + var panelInfo = dashboard.getPanelInfoById(dashboard.meta.focusPanelId); + dashboard.removeRow(panelInfo.row); + dashboard.meta.focusPanelId = 0; + } + }); + + // collapse row + this.bind('r c', () => { + if (dashboard.meta.focusPanelId) { + var panelInfo = dashboard.getPanelInfoById(dashboard.meta.focusPanelId); + panelInfo.row.toggleCollapse(); + dashboard.meta.focusPanelId = 0; + } + }); + + // share panel + this.bind('p s', () => { if (dashboard.meta.focusPanelId) { var shareScope = scope.$new(); var panelInfo = dashboard.getPanelInfoById(dashboard.meta.focusPanelId); diff --git a/public/app/core/services/util_srv.ts b/public/app/core/services/util_srv.ts index d4ca13166d5..d709b17fb04 100644 --- a/public/app/core/services/util_srv.ts +++ b/public/app/core/services/util_srv.ts @@ -23,20 +23,22 @@ export class UtilSrv { this.modalScope.dismiss(); } - if (options.model || !options.scope) { - options.scope = this.modalScope = this.$rootScope.$new(); - options.scope.model = options.model; - } - this.modalScope = options.scope; + if (options.model) { + this.modalScope = this.$rootScope.$new(); + this.modalScope.model = options.model; + } else if (!this.modalScope) { + this.modalScope = this.$rootScope.$new(); + } + var modal = this.$modal({ modalClass: options.modalClass, template: options.src, templateHtml: options.templateHtml, persist: false, show: false, - scope: options.scope, + scope: this.modalScope, keyboard: false, backdrop: options.backdrop }); diff --git a/public/app/features/dashboard/row/add_panel.html b/public/app/features/dashboard/row/add_panel.html index 75e66ecd00d..7f79e697484 100644 --- a/public/app/features/dashboard/row/add_panel.html +++ b/public/app/features/dashboard/row/add_panel.html @@ -1,4 +1,7 @@ -
+
+ + +
@@ -12,7 +15,7 @@ ng-repeat="panel in ctrl.panelHits" ng-class="{active: $index === ctrl.activeIndex}" ng-click="ctrl.addPanel(panel)" - ui-draggable="ctrl.dashboard.editMode" + ui-draggable="true" drag="panel.id" title="{{panel.name}}"> diff --git a/public/app/features/dashboard/row/options.html b/public/app/features/dashboard/row/options.html index 4544faef523..f54c88796e0 100644 --- a/public/app/features/dashboard/row/options.html +++ b/public/app/features/dashboard/row/options.html @@ -1,35 +1,34 @@ -
-
-
+
+ + + + +
+
- Row Title + Title
-
- -
- +
+
+ +
+ +
+ +
- -
-
+
- Height + Height
+
+ Repeat for + +
- -
-
- Repeat Row - -
-
- -
-
- diff --git a/public/app/features/dashboard/row/row.html b/public/app/features/dashboard/row/row.html index 0d6a701a478..67de0675762 100644 --- a/public/app/features/dashboard/row/row.html +++ b/public/app/features/dashboard/row/row.html @@ -1,36 +1,3 @@ - -
-
- - -
+
-
-
-
-
-
-
-
+
+ + +
-
+
+
+
+
+
+
+
+ +
diff --git a/public/app/features/dashboard/row/row_ctrl.ts b/public/app/features/dashboard/row/row_ctrl.ts index c4c550bba13..f82f91e04af 100644 --- a/public/app/features/dashboard/row/row_ctrl.ts +++ b/public/app/features/dashboard/row/row_ctrl.ts @@ -127,6 +127,7 @@ coreModule.directive('dashRow', function($rootScope) { }, link: function(scope, element) { scope.$watchGroup(['ctrl.row.collapse', 'ctrl.row.height'], function() { + element.toggleClass('dash-row--collapse', scope.ctrl.row.collapse); element.find('.panels-wrapper').css({minHeight: scope.ctrl.row.collapse ? '5px' : scope.ctrl.row.height}); }); diff --git a/public/app/features/dashboard/row/row_model.ts b/public/app/features/dashboard/row/row_model.ts index a1079f608e6..8f458e1911d 100644 --- a/public/app/features/dashboard/row/row_model.ts +++ b/public/app/features/dashboard/row/row_model.ts @@ -11,6 +11,7 @@ export class DashboardRow { events: Emitter; span: number; height: number; + collapse: boolean; defaults = { title: 'Dashboard Row', @@ -22,6 +23,7 @@ export class DashboardRow { repeat: null, repeatRowId: null, repeatIteration: null, + collapse: false, }; constructor(private model) { @@ -79,7 +81,6 @@ export class DashboardRow { } removePanel(panel, ask?) { - console.log('remove panel'); if (ask !== false) { appEvents.emit('confirm-modal', { title: 'Remove Panel', @@ -113,5 +114,9 @@ export class DashboardRow { this.showTitle = source.showTitle; this.titleSize = source.titleSize; } + + toggleCollapse() { + this.collapse = !this.collapse; + } } diff --git a/public/sass/_old_responsive.scss b/public/sass/_old_responsive.scss index 852712d2f01..4a69a1bbb9e 100644 --- a/public/sass/_old_responsive.scss +++ b/public/sass/_old_responsive.scss @@ -32,6 +32,10 @@ .page-container { padding: ($spacer * 1) ($spacer * 2); } + + .dash-row-menu-container { + display: none; + } } @include media-breakpoint-down(xs) { diff --git a/public/sass/components/_row.scss b/public/sass/components/_row.scss index aecb8476d41..f7aaa32f9f0 100644 --- a/public/sass/components/_row.scss +++ b/public/sass/components/_row.scss @@ -4,6 +4,14 @@ display: flex; flex-direction: column; position: relative; + + &--collapse { + .dash-row-header { + background: $panel-bg; + border: $panel-border; + margin-bottom: $panel-margin*2; + } + } } .dash-row-header { @@ -46,14 +54,8 @@ position: relative; } -.dash-row-options { - background: $panel-bg; - border: 1px solid $dash-row-border-color; - margin: 0 $panel-margin $panel-margin*2 $panel-margin; - padding: $panel-margin*2; -} - -.dash-row-add-panel { +.dash-row-dropview { + position: relative; background: $panel-bg; border: 1px solid $dash-row-border-color; margin: 0 $panel-margin $panel-margin*2 $panel-margin; @@ -61,6 +63,14 @@ display: flex; } +.dash-row-dropview-close { + position: absolute; + right: -15px; + top: -12px; + width: 20px; + height: 20px; +} + .add-panel-panels-scroll { width: 100%; overflow: auto; @@ -80,7 +90,7 @@ .add-panel-item { background: $input-label-bg; border: $panel-border; - padding: $spacer; + padding: $spacer/3 $spacer; min-width: 9rem; max-width: 9rem; text-align: center; @@ -89,7 +99,7 @@ &.active, &:hover { - box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 5px rgba(82,168,236,10.8) + box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 1px rgba(82,168,236,5.8) } } @@ -109,6 +119,8 @@ $dash-row-menu-animation-speed: 0.20s; .dash-row-menu-container { position: absolute; top: 0px; + width: 138px; + height: 100%; transform: translate(-131px, 0); transition: 0.1s ease-out 0.4s; z-index: 100; @@ -128,8 +140,6 @@ $dash-row-menu-animation-speed: 0.20s; } .dash-row-menu { - border-top: $panel-border; - border-bottom: $panel-border; list-style: none; flex-grow: 1; box-shadow: $search-shadow; diff --git a/public/sass/components/_sidemenu.scss b/public/sass/components/_sidemenu.scss index 6893bf39a85..6f16913a084 100644 --- a/public/sass/components/_sidemenu.scss +++ b/public/sass/components/_sidemenu.scss @@ -179,7 +179,7 @@ top: 38%; right: 6px; font-size: 14px; - color: $text-color-weak; + color: $text-color-faint; } .sidemenu-org-avatar, diff --git a/public/sass/pages/_dashboard.scss b/public/sass/pages/_dashboard.scss index 4e435f3be4a..47c3906397c 100644 --- a/public/sass/pages/_dashboard.scss +++ b/public/sass/pages/_dashboard.scss @@ -35,6 +35,9 @@ .dash-row-menu { display: none; } + .panel-drop-zone { + visibility: hidden; + } } div.flot-text { diff --git a/tasks/options/watch.js b/tasks/options/watch.js index a7da4d325c2..a4c048f648a 100644 --- a/tasks/options/watch.js +++ b/tasks/options/watch.js @@ -1,53 +1,77 @@ module.exports = function(config, grunt) { 'use strict'; - grunt.event.on('watch', function(action, filepath) { - var newPath; + var gaze = require('gaze'); + var path = require('path'); + var firstRun = true; + var done; + var lastTime; - grunt.log.writeln('File Changed: ' + filepath); + grunt.registerTask('watch', function() { - if (/(\.html)|(\.json)$/.test(filepath)) { - newPath = filepath.replace(/^public/, 'public_gen'); - grunt.log.writeln('Copying to ' + newPath); - grunt.file.copy(filepath, newPath); + done = this.async(); + lastTime = new Date().getTime(); + + if (firstRun === false) { + grunt.log.writeln('Watch resuming'); + return; } - if (/(\.js)$/.test(filepath)) { - newPath = filepath.replace(/^public/, 'public_gen'); - grunt.log.writeln('Copying to ' + newPath); - grunt.file.copy(filepath, newPath); + gaze(config.srcDir + '/**/*', function(err, watcher) { - grunt.task.run('jshint'); - grunt.task.run('jscs'); - } + console.log('Gaze watchers setup'); - if (/(\.scss)$/.test(filepath)) { - grunt.task.run('clean:css'); - grunt.task.run('css'); - } + watcher.on('all', function(evtName, filepath) { + filepath = path.relative(process.cwd(), filepath); - if (/(\.ts)$/.test(filepath)) { - newPath = filepath.replace(/^public/, 'public_gen'); - grunt.log.writeln('Copying to ' + newPath); - grunt.file.copy(filepath, newPath); + // ignore multiple changes at once + var now = new Date().getTime(); + if (now - lastTime < 100) { + return; + } + lastTime = now; - // copy ts file also used by source maps - //changes changed file source to that of the changed file - grunt.config('typescript.build.src', filepath); - grunt.config('tslint.source.files.src', filepath); + var newPath; + grunt.log.writeln('File Changed: ', filepath); - grunt.task.run('typescript:build'); - grunt.task.run('tslint'); - } + if (/(\.html)|(\.json)$/.test(filepath)) { + newPath = filepath.replace(/^public/, 'public_gen'); + grunt.log.writeln('Copying to ' + newPath); + grunt.file.copy(filepath, newPath); + } + + if (/(\.js)$/.test(filepath)) { + newPath = filepath.replace(/^public/, 'public_gen'); + grunt.log.writeln('Copying to ' + newPath); + grunt.file.copy(filepath, newPath); + + grunt.task.run('jshint'); + grunt.task.run('jscs'); + } + + if (/(\.scss)$/.test(filepath)) { + grunt.task.run('clean:css'); + grunt.task.run('css'); + } + + if (/(\.ts)$/.test(filepath)) { + newPath = filepath.replace(/^public/, 'public_gen'); + grunt.log.writeln('Copying to ' + newPath); + grunt.file.copy(filepath, newPath); + + // copy ts file also used by source maps + //changes changed file source to that of the changed file + grunt.config('typescript.build.src', filepath); + grunt.config('tslint.source.files.src', filepath); + + grunt.task.run('typescript:build'); + grunt.task.run('tslint'); + } + + done(); + firstRun = false; + grunt.task.run('watch'); + }); + }); }); - - return { - copy_to_gen: { - files: ['<%= srcDir %>/**/*'], - tasks: [], - options: { - spawn: false - } - }, - }; };