mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
ux(dashboar): added shortcut for build mode, switched keybinding lib to mousetrap, supports sequences so also added for Go to home dashboard, open search with starred dashbords prefiltered, go to profile, #6442
This commit is contained in:
parent
3c1435253d
commit
40ea014fa8
@ -73,6 +73,7 @@
|
|||||||
"grunt-sync": "^0.4.1",
|
"grunt-sync": "^0.4.1",
|
||||||
"karma-sinon": "^1.0.3",
|
"karma-sinon": "^1.0.3",
|
||||||
"lodash": "^2.4.1",
|
"lodash": "^2.4.1",
|
||||||
|
"mousetrap": "^1.6.0",
|
||||||
"remarkable": "^1.6.2",
|
"remarkable": "^1.6.2",
|
||||||
"sinon": "1.16.1",
|
"sinon": "1.16.1",
|
||||||
"systemjs-builder": "^0.15.13",
|
"systemjs-builder": "^0.15.13",
|
||||||
|
@ -29,7 +29,7 @@ export class SearchCtrl {
|
|||||||
this.isOpen = this.ignoreClose;
|
this.isOpen = this.ignoreClose;
|
||||||
}
|
}
|
||||||
|
|
||||||
openSearch() {
|
openSearch(evt, payload) {
|
||||||
if (this.isOpen) {
|
if (this.isOpen) {
|
||||||
this.isOpen = false;
|
this.isOpen = false;
|
||||||
return;
|
return;
|
||||||
@ -43,6 +43,10 @@ export class SearchCtrl {
|
|||||||
this.currentSearchId = 0;
|
this.currentSearchId = 0;
|
||||||
this.ignoreClose = true;
|
this.ignoreClose = true;
|
||||||
|
|
||||||
|
if (payload && payload.starred) {
|
||||||
|
this.query.starred = true;
|
||||||
|
}
|
||||||
|
|
||||||
this.$timeout(() => {
|
this.$timeout(() => {
|
||||||
this.ignoreClose = false;
|
this.ignoreClose = false;
|
||||||
this.giveSearchFocus = this.giveSearchFocus + 1;
|
this.giveSearchFocus = this.giveSearchFocus + 1;
|
||||||
|
@ -44,6 +44,7 @@ import appEvents from './app_events';
|
|||||||
import colors from './utils/colors';
|
import colors from './utils/colors';
|
||||||
import {assignModelProperties} from './utils/model_utils';
|
import {assignModelProperties} from './utils/model_utils';
|
||||||
import {contextSrv} from './services/context_srv';
|
import {contextSrv} from './services/context_srv';
|
||||||
|
import {KeybindingSrv} from './services/keybindingSrv';
|
||||||
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -66,4 +67,5 @@ export {
|
|||||||
colors,
|
colors,
|
||||||
assignModelProperties,
|
assignModelProperties,
|
||||||
contextSrv,
|
contextSrv,
|
||||||
|
KeybindingSrv,
|
||||||
};
|
};
|
||||||
|
118
public/app/core/services/keybindingSrv.ts
Normal file
118
public/app/core/services/keybindingSrv.ts
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
///<reference path="../../headers/common.d.ts" />
|
||||||
|
|
||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
import coreModule from 'app/core/core_module';
|
||||||
|
import appEvents from 'app/core/app_events';
|
||||||
|
|
||||||
|
import Mousetrap from 'mousetrap';
|
||||||
|
|
||||||
|
export class KeybindingSrv {
|
||||||
|
helpModal: boolean;
|
||||||
|
|
||||||
|
/** @ngInject */
|
||||||
|
constructor(private $rootScope, private $modal, private $location) {
|
||||||
|
// clear out all shortcuts on route change
|
||||||
|
$rootScope.$on('$routeChangeSuccess', () => {
|
||||||
|
Mousetrap.reset();
|
||||||
|
// rebind global shortcuts
|
||||||
|
this.setupGlobal();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setupGlobal();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
setupGlobal() {
|
||||||
|
this.bind("?", this.showHelpModal);
|
||||||
|
this.bind("g h", this.goToHome);
|
||||||
|
this.bind("g p", this.goToProfile);
|
||||||
|
this.bind("s s", this.openSearchStarred);
|
||||||
|
this.bind(['f'], this.openSearch);
|
||||||
|
}
|
||||||
|
|
||||||
|
openSearchStarred() {
|
||||||
|
this.$rootScope.appEvent('show-dash-search', {starred: true});
|
||||||
|
}
|
||||||
|
|
||||||
|
openSearch() {
|
||||||
|
this.$rootScope.appEvent('show-dash-search');
|
||||||
|
}
|
||||||
|
|
||||||
|
goToHome() {
|
||||||
|
this.$location.path("/");
|
||||||
|
}
|
||||||
|
|
||||||
|
goToProfile() {
|
||||||
|
this.$location.path("/profile");
|
||||||
|
}
|
||||||
|
|
||||||
|
showHelpModal() {
|
||||||
|
console.log('showing help modal');
|
||||||
|
appEvents.emit('show-modal', {
|
||||||
|
src: 'public/app/partials/help_modal.html',
|
||||||
|
model: {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bind(keyArg, fn) {
|
||||||
|
Mousetrap.bind(keyArg, evt => {
|
||||||
|
evt.preventDefault();
|
||||||
|
evt.stopPropagation();
|
||||||
|
return this.$rootScope.$apply(fn.bind(this));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setupDashboardBindings(scope, dashboard) {
|
||||||
|
this.bind('b', () => {
|
||||||
|
dashboard.toggleEditMode();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.bind('ctrl+o', () => {
|
||||||
|
dashboard.sharedCrosshair = !dashboard.sharedCrosshair;
|
||||||
|
scope.broadcastRefresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.bind(['ctrl+s', 'command+s'], () => {
|
||||||
|
scope.appEvent('save-dashboard');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.bind('r', () => {
|
||||||
|
scope.broadcastRefresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.bind('ctrl+z', () => {
|
||||||
|
scope.appEvent('zoom-out');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.bind('left', () => {
|
||||||
|
scope.appEvent('shift-time-backward');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.bind('right', () => {
|
||||||
|
scope.appEvent('shift-time-forward');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.bind('ctrl+i', () => {
|
||||||
|
scope.appEvent('quick-snapshot');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.bind('esc', () => {
|
||||||
|
var popups = $('.popover.in');
|
||||||
|
if (popups.length > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// close modals
|
||||||
|
var modalData = $(".modal").data();
|
||||||
|
if (modalData && modalData.$scope && modalData.$scope.dismiss) {
|
||||||
|
modalData.$scope.dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.appEvent('hide-dash-editor');
|
||||||
|
|
||||||
|
scope.exitFullscreen();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
coreModule.service('keybindingSrv', KeybindingSrv);
|
@ -8,6 +8,7 @@ import coreModule from 'app/core/core_module';
|
|||||||
import appEvents from 'app/core/app_events';
|
import appEvents from 'app/core/app_events';
|
||||||
|
|
||||||
export class UtilSrv {
|
export class UtilSrv {
|
||||||
|
modalScope: any;
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
constructor(private $rootScope, private $modal) {
|
constructor(private $rootScope, private $modal) {
|
||||||
@ -18,9 +19,15 @@ export class UtilSrv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showModal(options) {
|
showModal(options) {
|
||||||
|
if (this.modalScope && this.modalScope.dismiss) {
|
||||||
|
this.modalScope.dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
if (options.model) {
|
if (options.model) {
|
||||||
options.scope = this.$rootScope.$new();
|
options.scope = this.modalScope = this.$rootScope.$new();
|
||||||
options.scope.model = options.model;
|
options.scope.model = options.model;
|
||||||
|
} else {
|
||||||
|
this.modalScope = options.scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
var modal = this.$modal({
|
var modal = this.$modal({
|
||||||
|
@ -9,7 +9,6 @@ define([
|
|||||||
'./shareModalCtrl',
|
'./shareModalCtrl',
|
||||||
'./shareSnapshotCtrl',
|
'./shareSnapshotCtrl',
|
||||||
'./dashboard_srv',
|
'./dashboard_srv',
|
||||||
'./keybindings',
|
|
||||||
'./viewStateSrv',
|
'./viewStateSrv',
|
||||||
'./timeSrv',
|
'./timeSrv',
|
||||||
'./unsavedChangesSrv',
|
'./unsavedChangesSrv',
|
||||||
|
@ -13,7 +13,7 @@ export class DashboardCtrl {
|
|||||||
constructor(
|
constructor(
|
||||||
private $scope,
|
private $scope,
|
||||||
private $rootScope,
|
private $rootScope,
|
||||||
dashboardKeybindings,
|
keybindingSrv,
|
||||||
timeSrv,
|
timeSrv,
|
||||||
variableSrv,
|
variableSrv,
|
||||||
alertingSrv,
|
alertingSrv,
|
||||||
@ -61,7 +61,7 @@ export class DashboardCtrl {
|
|||||||
$scope.dashboardMeta = dashboard.meta;
|
$scope.dashboardMeta = dashboard.meta;
|
||||||
$scope.dashboardViewState = dashboardViewStateSrv.create($scope);
|
$scope.dashboardViewState = dashboardViewStateSrv.create($scope);
|
||||||
|
|
||||||
dashboardKeybindings.shortcuts($scope);
|
keybindingSrv.setupDashboardBindings($scope, dashboard);
|
||||||
|
|
||||||
$scope.dashboard.updateSubmenuVisibility();
|
$scope.dashboard.updateSubmenuVisibility();
|
||||||
$scope.setWindowTitleAndTheme();
|
$scope.setWindowTitleAndTheme();
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
define([
|
|
||||||
'angular',
|
|
||||||
'jquery',
|
|
||||||
],
|
|
||||||
function(angular, $) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var module = angular.module('grafana.services');
|
|
||||||
|
|
||||||
module.service('dashboardKeybindings', function($rootScope, keyboardManager, $modal, $q) {
|
|
||||||
|
|
||||||
this.shortcuts = function(scope) {
|
|
||||||
|
|
||||||
var unbindDestroy = scope.$on('$destroy', function() {
|
|
||||||
keyboardManager.unbindAll();
|
|
||||||
unbindDestroy();
|
|
||||||
});
|
|
||||||
|
|
||||||
var helpModalScope = null;
|
|
||||||
keyboardManager.bind('shift+?', function() {
|
|
||||||
if (helpModalScope) { return; }
|
|
||||||
|
|
||||||
helpModalScope = $rootScope.$new();
|
|
||||||
var helpModal = $modal({
|
|
||||||
template: 'public/app/partials/help_modal.html',
|
|
||||||
persist: false,
|
|
||||||
show: false,
|
|
||||||
scope: helpModalScope,
|
|
||||||
keyboard: false
|
|
||||||
});
|
|
||||||
|
|
||||||
var unbindModalDestroy = helpModalScope.$on('$destroy', function() {
|
|
||||||
helpModalScope = null;
|
|
||||||
unbindModalDestroy();
|
|
||||||
});
|
|
||||||
|
|
||||||
$q.when(helpModal).then(function(modalEl) { modalEl.modal('show'); });
|
|
||||||
|
|
||||||
}, { inputDisabled: true });
|
|
||||||
|
|
||||||
keyboardManager.bind('f', function() {
|
|
||||||
scope.appEvent('show-dash-search');
|
|
||||||
}, { inputDisabled: true });
|
|
||||||
|
|
||||||
keyboardManager.bind('ctrl+o', function() {
|
|
||||||
var current = scope.dashboard.sharedCrosshair;
|
|
||||||
scope.dashboard.sharedCrosshair = !current;
|
|
||||||
scope.broadcastRefresh();
|
|
||||||
}, { inputDisabled: true });
|
|
||||||
|
|
||||||
keyboardManager.bind('b', function() {
|
|
||||||
scope.dashboard.toggleEditMode();
|
|
||||||
}, { inputDisabled: true });
|
|
||||||
|
|
||||||
keyboardManager.bind('ctrl+s', function(evt) {
|
|
||||||
scope.appEvent('save-dashboard', evt);
|
|
||||||
}, { inputDisabled: true });
|
|
||||||
|
|
||||||
keyboardManager.bind('r', function() {
|
|
||||||
scope.broadcastRefresh();
|
|
||||||
}, { inputDisabled: true });
|
|
||||||
|
|
||||||
keyboardManager.bind('ctrl+z', function(evt) {
|
|
||||||
scope.appEvent('zoom-out', evt);
|
|
||||||
}, { inputDisabled: true });
|
|
||||||
|
|
||||||
keyboardManager.bind('left', function(evt) {
|
|
||||||
scope.appEvent('shift-time-backward', evt);
|
|
||||||
}, { inputDisabled: true });
|
|
||||||
|
|
||||||
keyboardManager.bind('right', function(evt) {
|
|
||||||
scope.appEvent('shift-time-forward', evt);
|
|
||||||
}, { inputDisabled: true });
|
|
||||||
|
|
||||||
keyboardManager.bind('ctrl+i', function(evt) {
|
|
||||||
scope.appEvent('quick-snapshot', evt);
|
|
||||||
}, { inputDisabled: true });
|
|
||||||
|
|
||||||
keyboardManager.bind('esc', function() {
|
|
||||||
var popups = $('.popover.in');
|
|
||||||
if (popups.length > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// close modals
|
|
||||||
var modalData = $(".modal").data();
|
|
||||||
if (modalData && modalData.$scope && modalData.$scope.dismiss) {
|
|
||||||
modalData.$scope.dismiss();
|
|
||||||
}
|
|
||||||
|
|
||||||
scope.appEvent('hide-dash-editor');
|
|
||||||
|
|
||||||
scope.exitFullscreen();
|
|
||||||
}, { inputDisabled: true });
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
@ -55,12 +55,6 @@
|
|||||||
checked="dashboard.editable"
|
checked="dashboard.editable"
|
||||||
label-class="width-11">
|
label-class="width-11">
|
||||||
</gf-form-switch>
|
</gf-form-switch>
|
||||||
<gf-form-switch class="gf-form"
|
|
||||||
label="Build Mode"
|
|
||||||
tooltip="Enable build mode. Shortcut: CTRL+B"
|
|
||||||
checked="dashboard.editMode"
|
|
||||||
label-class="width-11">
|
|
||||||
</gf-form-switch>
|
|
||||||
<gf-form-switch class="gf-form"
|
<gf-form-switch class="gf-form"
|
||||||
label="Shared Crosshair"
|
label="Shared Crosshair"
|
||||||
tooltip="Shared Crosshair line on all graphs. Shortcut: CTRL+O"
|
tooltip="Shared Crosshair line on all graphs. Shortcut: CTRL+O"
|
||||||
|
5
public/app/headers/common.d.ts
vendored
5
public/app/headers/common.d.ts
vendored
@ -57,3 +57,8 @@ declare module 'virtual-scroll' {
|
|||||||
var config: any;
|
var config: any;
|
||||||
export default config;
|
export default config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module 'mousetrap' {
|
||||||
|
var config: any;
|
||||||
|
export default config;
|
||||||
|
}
|
||||||
|
@ -535,9 +535,9 @@ module.directive('grafanaGraph', function($rootScope, timeSrv) {
|
|||||||
return "%H:%M";
|
return "%H:%M";
|
||||||
}
|
}
|
||||||
|
|
||||||
// new GraphTooltip(elem, dashboard, scope, function() {
|
new GraphTooltip(elem, dashboard, scope, function() {
|
||||||
// return sortedSeries;
|
return sortedSeries;
|
||||||
// });
|
});
|
||||||
|
|
||||||
elem.bind("plotselected", function (event, ranges) {
|
elem.bind("plotselected", function (event, ranges) {
|
||||||
scope.$apply(function() {
|
scope.$apply(function() {
|
||||||
|
@ -153,8 +153,8 @@ export class ThresholdManager {
|
|||||||
this.renderHandle(1, this.height-30);
|
this.renderHandle(1, this.height-30);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this.placeholder.off('mousedown', '.alert-handle');
|
this.placeholder.off('mousedown', '.alert-handle');
|
||||||
// this.placeholder.on('mousedown', '.alert-handle', this.initDragging.bind(this));
|
this.placeholder.on('mousedown', '.alert-handle', this.initDragging.bind(this));
|
||||||
this.needsCleanup = true;
|
this.needsCleanup = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ System.config({
|
|||||||
baseURL: 'public',
|
baseURL: 'public',
|
||||||
paths: {
|
paths: {
|
||||||
'virtual-scroll': 'vendor/npm/virtual-scroll/src/index.js',
|
'virtual-scroll': 'vendor/npm/virtual-scroll/src/index.js',
|
||||||
|
'mousetrap': 'vendor/npm/mousetrap/mousetrap.js',
|
||||||
'remarkable': 'vendor/npm/remarkable/dist/remarkable.js',
|
'remarkable': 'vendor/npm/remarkable/dist/remarkable.js',
|
||||||
'tether': 'vendor/npm/tether/dist/js/tether.js',
|
'tether': 'vendor/npm/tether/dist/js/tether.js',
|
||||||
'eventemitter3': 'vendor/npm/eventemitter3/index.js',
|
'eventemitter3': 'vendor/npm/eventemitter3/index.js',
|
||||||
@ -66,5 +67,9 @@ System.config({
|
|||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
exports: 'EventEmitter'
|
exports: 'EventEmitter'
|
||||||
},
|
},
|
||||||
|
'vendor/npm/mousetrap/mousetrap.js': {
|
||||||
|
format: 'global',
|
||||||
|
exports: 'Mousetrap'
|
||||||
|
},
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -265,7 +265,7 @@ $tooltipBackground: $popover-help-bg;
|
|||||||
$tooltipArrowWidth: 5px;
|
$tooltipArrowWidth: 5px;
|
||||||
$tooltipArrowColor: $tooltipBackground;
|
$tooltipArrowColor: $tooltipBackground;
|
||||||
$tooltipLinkColor: $link-color;
|
$tooltipLinkColor: $link-color;
|
||||||
$graph-tooltip-bg: $dark-4;
|
$graph-tooltip-bg: $dark-1;
|
||||||
|
|
||||||
// images
|
// images
|
||||||
$checkboxImageUrl: '../img/checkbox.png';
|
$checkboxImageUrl: '../img/checkbox.png';
|
||||||
|
@ -244,6 +244,8 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
top: -3px;
|
top: -3px;
|
||||||
padding: 0.2rem;
|
padding: 0.2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: $text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.graph-tooltip-list-item {
|
.graph-tooltip-list-item {
|
||||||
|
@ -33,6 +33,7 @@ module.exports = function(config) {
|
|||||||
'remarkable/dist/*',
|
'remarkable/dist/*',
|
||||||
'remarkable/dist/*',
|
'remarkable/dist/*',
|
||||||
'virtual-scroll/**/*',
|
'virtual-scroll/**/*',
|
||||||
|
'mousetrap/**/*',
|
||||||
],
|
],
|
||||||
dest: '<%= srcDir %>/vendor/npm'
|
dest: '<%= srcDir %>/vendor/npm'
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user