diff --git a/package.json b/package.json
index 2171afee4d7..40badc957ff 100644
--- a/package.json
+++ b/package.json
@@ -73,6 +73,7 @@
"grunt-sync": "^0.4.1",
"karma-sinon": "^1.0.3",
"lodash": "^2.4.1",
+ "mousetrap": "^1.6.0",
"remarkable": "^1.6.2",
"sinon": "1.16.1",
"systemjs-builder": "^0.15.13",
diff --git a/public/app/core/components/search/search.ts b/public/app/core/components/search/search.ts
index a581afe3fd3..65a250d533c 100644
--- a/public/app/core/components/search/search.ts
+++ b/public/app/core/components/search/search.ts
@@ -29,7 +29,7 @@ export class SearchCtrl {
this.isOpen = this.ignoreClose;
}
- openSearch() {
+ openSearch(evt, payload) {
if (this.isOpen) {
this.isOpen = false;
return;
@@ -43,6 +43,10 @@ export class SearchCtrl {
this.currentSearchId = 0;
this.ignoreClose = true;
+ if (payload && payload.starred) {
+ this.query.starred = true;
+ }
+
this.$timeout(() => {
this.ignoreClose = false;
this.giveSearchFocus = this.giveSearchFocus + 1;
diff --git a/public/app/core/core.ts b/public/app/core/core.ts
index 5d30bc6d061..2041f9e60d8 100644
--- a/public/app/core/core.ts
+++ b/public/app/core/core.ts
@@ -44,6 +44,7 @@ import appEvents from './app_events';
import colors from './utils/colors';
import {assignModelProperties} from './utils/model_utils';
import {contextSrv} from './services/context_srv';
+import {KeybindingSrv} from './services/keybindingSrv';
export {
@@ -66,4 +67,5 @@ export {
colors,
assignModelProperties,
contextSrv,
+ KeybindingSrv,
};
diff --git a/public/app/core/services/keybindingSrv.ts b/public/app/core/services/keybindingSrv.ts
new file mode 100644
index 00000000000..55b1cfaadc2
--- /dev/null
+++ b/public/app/core/services/keybindingSrv.ts
@@ -0,0 +1,118 @@
+///
+
+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);
diff --git a/public/app/core/services/util_srv.ts b/public/app/core/services/util_srv.ts
index 8ca7bf8be72..ca386a491b9 100644
--- a/public/app/core/services/util_srv.ts
+++ b/public/app/core/services/util_srv.ts
@@ -8,6 +8,7 @@ import coreModule from 'app/core/core_module';
import appEvents from 'app/core/app_events';
export class UtilSrv {
+ modalScope: any;
/** @ngInject */
constructor(private $rootScope, private $modal) {
@@ -18,9 +19,15 @@ export class UtilSrv {
}
showModal(options) {
+ if (this.modalScope && this.modalScope.dismiss) {
+ this.modalScope.dismiss();
+ }
+
if (options.model) {
- options.scope = this.$rootScope.$new();
+ options.scope = this.modalScope = this.$rootScope.$new();
options.scope.model = options.model;
+ } else {
+ this.modalScope = options.scope;
}
var modal = this.$modal({
diff --git a/public/app/features/dashboard/all.js b/public/app/features/dashboard/all.js
index edcc3c74d8e..88401000fb9 100644
--- a/public/app/features/dashboard/all.js
+++ b/public/app/features/dashboard/all.js
@@ -9,7 +9,6 @@ define([
'./shareModalCtrl',
'./shareSnapshotCtrl',
'./dashboard_srv',
- './keybindings',
'./viewStateSrv',
'./timeSrv',
'./unsavedChangesSrv',
diff --git a/public/app/features/dashboard/dashboard_ctrl.ts b/public/app/features/dashboard/dashboard_ctrl.ts
index 075e3dcaa8f..cf72bb87f61 100644
--- a/public/app/features/dashboard/dashboard_ctrl.ts
+++ b/public/app/features/dashboard/dashboard_ctrl.ts
@@ -13,7 +13,7 @@ export class DashboardCtrl {
constructor(
private $scope,
private $rootScope,
- dashboardKeybindings,
+ keybindingSrv,
timeSrv,
variableSrv,
alertingSrv,
@@ -61,7 +61,7 @@ export class DashboardCtrl {
$scope.dashboardMeta = dashboard.meta;
$scope.dashboardViewState = dashboardViewStateSrv.create($scope);
- dashboardKeybindings.shortcuts($scope);
+ keybindingSrv.setupDashboardBindings($scope, dashboard);
$scope.dashboard.updateSubmenuVisibility();
$scope.setWindowTitleAndTheme();
diff --git a/public/app/features/dashboard/keybindings.js b/public/app/features/dashboard/keybindings.js
deleted file mode 100644
index c8f0e23df17..00000000000
--- a/public/app/features/dashboard/keybindings.js
+++ /dev/null
@@ -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 });
- };
- });
-});
diff --git a/public/app/features/dashboard/partials/settings.html b/public/app/features/dashboard/partials/settings.html
index 679b698502a..ad751c4a1bc 100644
--- a/public/app/features/dashboard/partials/settings.html
+++ b/public/app/features/dashboard/partials/settings.html
@@ -55,12 +55,6 @@
checked="dashboard.editable"
label-class="width-11">
-
-
/vendor/npm'
}