mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-07-14 21:04:53 +00:00
(js,css) Improve keyboard shortcuts
- Defined some hotkeys in all modules; - Added generation of cheat sheet.
This commit is contained in:
@@ -212,7 +212,7 @@
|
||||
this.$$cards = [];
|
||||
}
|
||||
this.idsMap = {};
|
||||
this.$cards = []; // TODO Keep the "selected" state of cards
|
||||
this.$cards = [];
|
||||
// Extend instance with all attributes of data except headers
|
||||
angular.forEach(data, function(value, key) {
|
||||
if (key != 'headers' && key != 'cards') {
|
||||
@@ -370,6 +370,16 @@
|
||||
return _.find(this.$cards, function(card) { return card.id == _this.selectedCard; });
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $selectedCardIndex
|
||||
* @memberof AddressBook.prototype
|
||||
* @desc Return the index of the currently visible card.
|
||||
* @returns a number or undefined if no card is selected
|
||||
*/
|
||||
AddressBook.prototype.$selectedCardIndex = function() {
|
||||
return _.indexOf(_.map(this.$cards, 'id'), this.selectedCard);
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $selectedCards
|
||||
* @memberof AddressBook.prototype
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
AddressBookController.$inject = ['$scope', '$q', '$window', '$state', '$timeout', '$mdDialog', '$mdToast', 'Account', 'Card', 'AddressBook', 'Dialog', 'sgSettings', 'stateAddressbooks', 'stateAddressbook'];
|
||||
function AddressBookController($scope, $q, $window, $state, $timeout, $mdDialog, $mdToast, Account, Card, AddressBook, Dialog, Settings, stateAddressbooks, stateAddressbook) {
|
||||
var vm = this;
|
||||
AddressBookController.$inject = ['$scope', '$q', '$window', '$state', '$timeout', '$mdDialog', '$mdToast', 'Account', 'Card', 'AddressBook', 'Dialog', 'sgSettings', 'sgHotkeys', 'stateAddressbooks', 'stateAddressbook'];
|
||||
function AddressBookController($scope, $q, $window, $state, $timeout, $mdDialog, $mdToast, Account, Card, AddressBook, Dialog, Settings, sgHotkeys, stateAddressbooks, stateAddressbook) {
|
||||
var vm = this, hotkeys = [];
|
||||
|
||||
AddressBook.selectedFolder = stateAddressbook;
|
||||
|
||||
@@ -29,12 +29,72 @@
|
||||
vm.newMessageWithSelectedCards = newMessageWithSelectedCards;
|
||||
vm.newMessageWithRecipient = newMessageWithRecipient;
|
||||
vm.mode = { search: false, multiple: 0 };
|
||||
|
||||
|
||||
|
||||
_registerHotkeys(hotkeys);
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
// Deregister hotkeys
|
||||
_.forEach(hotkeys, function(key) {
|
||||
sgHotkeys.deregisterHotkey(key);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function _registerHotkeys(keys) {
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: l('key_create_card'),
|
||||
description: l('Create a new address book card'),
|
||||
callback: angular.bind(vm, newComponent, 'card')
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: l('key_create_list'),
|
||||
description: l('Create a new list'),
|
||||
callback: angular.bind(vm, newComponent, 'list')
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'space',
|
||||
description: l('Toggle item'),
|
||||
callback: toggleCardSelection
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'up',
|
||||
description: l('View next item'),
|
||||
callback: _nextCard
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'down',
|
||||
description: l('View previous item'),
|
||||
callback: _previousCard
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'shift+up',
|
||||
description: l('Add next item to selection'),
|
||||
callback: _addNextCardToSelection
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'shift+down',
|
||||
description: l('Add previous item to selection'),
|
||||
callback: _addPreviousCardToSelection
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'backspace',
|
||||
description: l('Delete selected card or address book'),
|
||||
callback: confirmDeleteSelectedCards
|
||||
}));
|
||||
|
||||
// Register the hotkeys
|
||||
_.forEach(keys, function(key) {
|
||||
sgHotkeys.registerHotkey(key);
|
||||
});
|
||||
}
|
||||
|
||||
function selectCard(card) {
|
||||
$state.go('app.addressbook.card.view', {cardId: card.id});
|
||||
}
|
||||
|
||||
|
||||
function toggleCardSelection($event, card) {
|
||||
if (!card) card = vm.selectedFolder.$selectedCard();
|
||||
card.selected = !card.selected;
|
||||
vm.mode.multiple += card.selected? 1 : -1;
|
||||
$event.preventDefault();
|
||||
@@ -51,20 +111,92 @@
|
||||
});
|
||||
vm.mode.multiple = 0;
|
||||
}
|
||||
|
||||
function confirmDeleteSelectedCards() {
|
||||
Dialog.confirm(l('Warning'),
|
||||
l('Are you sure you want to delete the selected contacts?'),
|
||||
{ ok: l('Delete') })
|
||||
|
||||
/**
|
||||
* User has pressed up arrow key
|
||||
*/
|
||||
function _nextCard($event) {
|
||||
var index = vm.selectedFolder.$selectedCardIndex();
|
||||
|
||||
if (angular.isDefined(index))
|
||||
index--;
|
||||
else
|
||||
// No message is selected, show oldest message
|
||||
index = vm.selectedFolder.$cards.length() - 1;
|
||||
|
||||
if (index > -1)
|
||||
selectCard(vm.selectedFolder.$cards[index]);
|
||||
|
||||
if (vm.selectedFolder.$topIndex > 0)
|
||||
vm.selectedFolder.$topIndex--;
|
||||
|
||||
$event.preventDefault();
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* User has pressed the down arrow key
|
||||
*/
|
||||
function _previousCard($event) {
|
||||
var index = vm.selectedFolder.$selectedCardIndex();
|
||||
|
||||
if (angular.isDefined(index))
|
||||
index++;
|
||||
else
|
||||
// No message is selected, show newest
|
||||
index = 0;
|
||||
|
||||
if (index < vm.selectedFolder.$cards.length)
|
||||
selectCard(vm.selectedFolder.$cards[index]);
|
||||
else
|
||||
index = -1;
|
||||
|
||||
if (vm.selectedFolder.$topIndex < vm.selectedFolder.$cards.length)
|
||||
vm.selectedFolder.$topIndex++;
|
||||
|
||||
$event.preventDefault();
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
function _addNextCardToSelection($event) {
|
||||
var index;
|
||||
|
||||
if (vm.selectedFolder.hasSelectedCard()) {
|
||||
index = _nextCard($event);
|
||||
if (index >= 0)
|
||||
toggleCardSelection($event, vm.selectedFolder.$cards[index]);
|
||||
}
|
||||
}
|
||||
|
||||
function _addPreviousCardToSelection($event) {
|
||||
var index;
|
||||
|
||||
if (vm.selectedFolder.hasSelectedCard()) {
|
||||
index = _previousCard($event);
|
||||
if (index >= 0)
|
||||
toggleCardSelection($event, vm.selectedFolder.$cards[index]);
|
||||
}
|
||||
}
|
||||
|
||||
function confirmDeleteSelectedCards($event) {
|
||||
var selectedCards = vm.selectedFolder.$selectedCards();
|
||||
|
||||
if (_.size(selectedCards) > 0)
|
||||
Dialog.confirm(l('Warning'),
|
||||
l('Are you sure you want to delete the selected contacts?'),
|
||||
{ ok: l('Delete') })
|
||||
.then(function() {
|
||||
// User confirmed the deletion
|
||||
var selectedCards = _.filter(vm.selectedFolder.$cards, function(card) { return card.selected; });
|
||||
vm.selectedFolder.$deleteCards(selectedCards).then(function() {
|
||||
vm.mode.multiple = 0;
|
||||
if (!vm.selectedFolder.selectedCard)
|
||||
$state.go('app.addressbook');
|
||||
});
|
||||
});
|
||||
|
||||
$event.preventDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,6 +346,6 @@
|
||||
}
|
||||
|
||||
angular
|
||||
.module('SOGo.ContactsUI')
|
||||
.controller('AddressBookController', AddressBookController);
|
||||
.module('SOGo.ContactsUI')
|
||||
.controller('AddressBookController', AddressBookController);
|
||||
})();
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
AddressBooksController.$inject = ['$state', '$scope', '$rootScope', '$stateParams', '$timeout', '$window', '$mdDialog', '$mdToast', '$mdMedia', '$mdSidenav', 'FileUploader', 'sgConstant', 'sgFocus', 'Card', 'AddressBook', 'Dialog', 'sgSettings', 'User', 'stateAddressbooks'];
|
||||
function AddressBooksController($state, $scope, $rootScope, $stateParams, $timeout, $window, $mdDialog, $mdToast, $mdMedia, $mdSidenav, FileUploader, sgConstant, focus, Card, AddressBook, Dialog, Settings, User, stateAddressbooks) {
|
||||
var vm = this;
|
||||
AddressBooksController.$inject = ['$state', '$scope', '$rootScope', '$stateParams', '$timeout', '$window', '$mdDialog', '$mdToast', '$mdMedia', '$mdSidenav', 'FileUploader', 'sgConstant', 'sgHotkeys', 'sgFocus', 'Card', 'AddressBook', 'Dialog', 'sgSettings', 'User', 'stateAddressbooks'];
|
||||
function AddressBooksController($state, $scope, $rootScope, $stateParams, $timeout, $window, $mdDialog, $mdToast, $mdMedia, $mdSidenav, FileUploader, sgConstant, sgHotkeys, focus, Card, AddressBook, Dialog, Settings, User, stateAddressbooks) {
|
||||
var vm = this, hotkeys = [];
|
||||
|
||||
vm.activeUser = Settings.activeUser;
|
||||
vm.service = AddressBook;
|
||||
@@ -26,6 +26,33 @@
|
||||
vm.isDroppableFolder = isDroppableFolder;
|
||||
vm.dragSelectedCards = dragSelectedCards;
|
||||
|
||||
|
||||
_registerHotkeys(hotkeys);
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
// Deregister hotkeys
|
||||
_.forEach(hotkeys, function(key) {
|
||||
sgHotkeys.deregisterHotkey(key);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function _registerHotkeys(keys) {
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'backspace',
|
||||
description: l('Delete selected card or address book'),
|
||||
callback: function() {
|
||||
if (AddressBook.selectedFolder && !AddressBook.selectedFolder.hasSelectedCard())
|
||||
confirmDelete();
|
||||
}
|
||||
}));
|
||||
|
||||
// Register the hotkeys
|
||||
_.forEach(keys, function(key) {
|
||||
sgHotkeys.registerHotkey(key);
|
||||
});
|
||||
}
|
||||
|
||||
function select($event, folder) {
|
||||
if ($state.params.addressbookId != folder.id &&
|
||||
vm.editMode != folder.id) {
|
||||
@@ -109,10 +136,12 @@
|
||||
return true;
|
||||
})
|
||||
.catch(function(response) {
|
||||
var message = response.data.message || response.statusText;
|
||||
Dialog.alert(l('An error occured while deleting the addressbook "%{0}".',
|
||||
vm.service.selectedFolder.name),
|
||||
message);
|
||||
if (response) {
|
||||
var message = response.data.message || response.statusText;
|
||||
Dialog.alert(l('An error occured while deleting the addressbook "%{0}".',
|
||||
vm.service.selectedFolder.name),
|
||||
message);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
* Controller to view and edit a card
|
||||
* @ngInject
|
||||
*/
|
||||
CardController.$inject = ['$scope', '$timeout', '$window', '$mdDialog', 'AddressBook', 'Card', 'Dialog', 'sgFocus', '$state', '$stateParams', 'stateCard'];
|
||||
function CardController($scope, $timeout, $window, $mdDialog, AddressBook, Card, Dialog, focus, $state, $stateParams, stateCard) {
|
||||
var vm = this;
|
||||
CardController.$inject = ['$scope', '$timeout', '$window', '$mdDialog', 'AddressBook', 'Card', 'Dialog', 'sgHotkeys', 'sgFocus', '$state', '$stateParams', 'stateCard'];
|
||||
function CardController($scope, $timeout, $window, $mdDialog, AddressBook, Card, Dialog, sgHotkeys, focus, $state, $stateParams, stateCard) {
|
||||
var vm = this, hotkeys = [];
|
||||
|
||||
vm.card = stateCard;
|
||||
|
||||
@@ -37,6 +37,34 @@
|
||||
vm.toggleRawSource = toggleRawSource;
|
||||
vm.showRawSource = false;
|
||||
|
||||
|
||||
_registerHotkeys(hotkeys);
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
// Deregister hotkeys
|
||||
_.forEach(hotkeys, function(key) {
|
||||
sgHotkeys.deregisterHotkey(key);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function _registerHotkeys(keys) {
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'backspace',
|
||||
description: l('Delete'),
|
||||
callback: function($event) {
|
||||
if (vm.currentFolder.$selectedCount() === 0)
|
||||
confirmDelete();
|
||||
$event.preventDefault();
|
||||
}
|
||||
}));
|
||||
|
||||
// Register the hotkeys
|
||||
_.forEach(keys, function(key) {
|
||||
sgHotkeys.registerHotkey(key);
|
||||
});
|
||||
}
|
||||
|
||||
function transformCategory(input) {
|
||||
if (angular.isString(input))
|
||||
return { value: input };
|
||||
@@ -112,7 +140,9 @@
|
||||
$state.go('app.addressbook.card.view', { cardId: vm.card.id });
|
||||
}
|
||||
}
|
||||
function confirmDelete(card) {
|
||||
function confirmDelete() {
|
||||
var card = stateCard;
|
||||
|
||||
Dialog.confirm(l('Warning'),
|
||||
l('Are you sure you want to delete the card of %{0}?', '<b>' + card.$fullname() + '</b>'),
|
||||
{ ok: l('Delete') })
|
||||
|
||||
Reference in New Issue
Block a user