(js,css) Improve keyboard shortcuts
- Defined some hotkeys in all modules; - Added generation of cheat sheet.pull/222/head
parent
13dd21bebb
commit
57a735753f
1
NEWS
1
NEWS
|
@ -3,6 +3,7 @@
|
|||
|
||||
New features
|
||||
- [web] added IMAP folder subscriptions management (#255)
|
||||
- [web] keyboard shortcuts
|
||||
- [eas] initial support for server-side mailbox search operations
|
||||
|
||||
Enhancements
|
||||
|
|
|
@ -119,4 +119,52 @@
|
|||
"Wrong username or password." = "Wrong username or password.";
|
||||
|
||||
/* Error message display bellow search field when the search string has less than the required number of characters */
|
||||
"Enter at least %{minimumSearchLength} characters" = "Enter at least %{minimumSearchLength} characters";
|
||||
"Enter at least %{minimumSearchLength} characters" = "Enter at least %{minimumSearchLength} characters";
|
||||
|
||||
/* Question mark shows list of hotkeys */
|
||||
"Show or hide this help" = "Show or hide this help";
|
||||
|
||||
/* Space key */
|
||||
"key_space" = "space";
|
||||
|
||||
/* Up arrow key */
|
||||
"key_up" = "↑";
|
||||
|
||||
/* Down arrow key */
|
||||
"key_down" = "↓";
|
||||
|
||||
/* Left arrow key */
|
||||
"key_left" = "←";
|
||||
|
||||
/* Right arrow key */
|
||||
"key_right" = "→";
|
||||
|
||||
/* Shift and up arrow combo keys */
|
||||
"key_shift+up" = "shift + ↑";
|
||||
|
||||
/* Shift and down arrow combo keys */
|
||||
"key_shift+down" = "shift + ↓";
|
||||
|
||||
/* Backspace key */
|
||||
"key_backspace" = "backspace";
|
||||
|
||||
/* Hotkey to start a search */
|
||||
"hotkey_search" = "s";
|
||||
|
||||
/* Hotkey description to select next list item */
|
||||
"View next item" = "View next item";
|
||||
|
||||
/* Hotkey description to select previous list item */
|
||||
"View previous item" = "View previous item";
|
||||
|
||||
/* Hotkey description to add next list item to selection */
|
||||
"Add next item to selection" = "Add next item to selection";
|
||||
|
||||
/* Hotkey description to add previous list item to selection */
|
||||
"Add previous item to selection" = "Add previous item to selection";
|
||||
|
||||
/* Hotkey description to move backward in current view */
|
||||
"Move backward" = "Move backward";
|
||||
|
||||
/* Hotkey description to move forward in current view */
|
||||
"Move forward" = "Move forward";
|
|
@ -253,3 +253,9 @@
|
|||
|
||||
/* Aria label for avatar button to select and unselect a card */
|
||||
"Toggle item" = "Toggle item";
|
||||
|
||||
/* Hotkey to create a new card */
|
||||
"key_create_card" = "c";
|
||||
|
||||
/* Hotkey to create a new list */
|
||||
"key_create_list" = "l";
|
|
@ -365,4 +365,7 @@
|
|||
"Search scope" = "Search scope";
|
||||
|
||||
/* Subscriptions Dialog */
|
||||
"Manage Subscriptions" = "Manage Subscriptions";
|
||||
"Manage Subscriptions" = "Manage Subscriptions";
|
||||
|
||||
/* Hotkey to write a new message */
|
||||
"hotkey_compose" = "w";
|
|
@ -579,4 +579,25 @@ vtodo_class2 = "(Confidential task)";
|
|||
"Toggle item" = "Toggle item";
|
||||
|
||||
/* Aria label for scope of search on events or tasks */
|
||||
"Search scope" = "Search scope";
|
||||
"Search scope" = "Search scope";
|
||||
|
||||
/* Hotkey to create an event */
|
||||
"hotkey_create_event" = "e";
|
||||
|
||||
/* Hotkey to create a task */
|
||||
"hotkey_create_task" = "t";
|
||||
|
||||
/* Hotkey to go to today */
|
||||
"hotkey_today" = "n";
|
||||
|
||||
/* Hotkey to switch to day view */
|
||||
"hotkey_dayview" = "d";
|
||||
|
||||
/* Hotkey to switch to week view */
|
||||
"hotkey_weekview" = "w";
|
||||
|
||||
/* Hotkey to switch to month view */
|
||||
"hotkey_monthview" = "m";
|
||||
|
||||
/* Hotkey to switch to multicolumn day view */
|
||||
"hotkey_multicolumndayview" = "c";
|
|
@ -34,16 +34,16 @@
|
|||
<a class="md-icon-button md-button"
|
||||
label:aria-label="Day"
|
||||
ng-disabled="true"
|
||||
ng-click="calendar.changeView('day')"><md-icon>view_day</md-icon></a>
|
||||
ng-click="calendar.changeView($event, 'day')"><md-icon>view_day</md-icon></a>
|
||||
<a class="md-icon-button md-button"
|
||||
label:aria-label="Week"
|
||||
ng-click="calendar.changeView('week')"><md-icon>view_week</md-icon></a>
|
||||
ng-click="calendar.changeView($event, 'week')"><md-icon>view_week</md-icon></a>
|
||||
<a class="md-icon-button md-button"
|
||||
label:aria-label="Month"
|
||||
ng-click="calendar.changeView('month')"><md-icon>view_module</md-icon></a>
|
||||
ng-click="calendar.changeView($event, 'month')"><md-icon>view_module</md-icon></a>
|
||||
<a class="md-icon-button md-button"
|
||||
label:aria-label="Multicolumn Day View"
|
||||
ng-click="calendar.changeView('multicolumnday')"><md-icon>view_array</md-icon></a>
|
||||
ng-click="calendar.changeView($event, 'multicolumnday')"><md-icon>view_array</md-icon></a>
|
||||
</md-card-actions>
|
||||
|
||||
<var:component
|
||||
|
|
|
@ -348,7 +348,7 @@
|
|||
<!-- sort/filter mode (default) -->
|
||||
<div class="md-toolbar-tools" layout="row" ng-hide="list.mode.search">
|
||||
<md-button class="sg-icon-button" label:aria-label="Search"
|
||||
ng-click="list.mode.search = true">
|
||||
ng-click="list.searchMode()">
|
||||
<md-icon>search</md-icon>
|
||||
</md-button>
|
||||
<div class="md-flex"><!-- spacer --></div>
|
||||
|
@ -530,7 +530,8 @@
|
|||
<md-icon>arrow_back</md-icon>
|
||||
</md-button>
|
||||
<md-input-container class="md-flex" md-no-float="md-no-float">
|
||||
<input name="folderSearch" type="search" var:minlength="minimumSearchLength" label:placeholder="Search"/>
|
||||
<input name="folderSearch" type="search" var:minlength="minimumSearchLength" label:placeholder="Search"
|
||||
sg-focus-on="search"/>
|
||||
<div ng-messages="searchForm.folderSearch.$error" ng-show="searchForm.folderSearch.$dirty">
|
||||
<div ng-message="minlength"><var:string value="minimumSearchLengthLabel"/></div>
|
||||
</div>
|
||||
|
|
|
@ -33,17 +33,17 @@
|
|||
</md-button>
|
||||
<a class="md-icon-button md-button"
|
||||
label:aria-label="Day"
|
||||
ng-click="calendar.changeView('day')"><md-icon>view_day</md-icon></a>
|
||||
ng-click="calendar.changeView($event, 'day')"><md-icon>view_day</md-icon></a>
|
||||
<a class="md-icon-button md-button"
|
||||
label:aria-label="Week"
|
||||
ng-click="calendar.changeView('week')"><md-icon>view_week</md-icon></a>
|
||||
ng-click="calendar.changeView($event, 'week')"><md-icon>view_week</md-icon></a>
|
||||
<a class="md-icon-button md-button"
|
||||
label:aria-label="Month"
|
||||
ng-disabled="true"
|
||||
ng-click="calendar.changeView('month')"><md-icon>view_module</md-icon></a>
|
||||
ng-click="calendar.changeView($event, 'month')"><md-icon>view_module</md-icon></a>
|
||||
<a class="md-icon-button md-button"
|
||||
label:aria-label="Multicolumn Day View"
|
||||
ng-click="calendar.changeView('multicolumnday')"><md-icon>view_array</md-icon></a>
|
||||
ng-click="calendar.changeView($event, 'multicolumnday')"><md-icon>view_array</md-icon></a>
|
||||
</md-card-actions>
|
||||
|
||||
<md-toolbar class="monthView">
|
||||
|
|
|
@ -33,17 +33,17 @@
|
|||
</md-button>
|
||||
<a class="md-icon-button md-button"
|
||||
label:aria-label="Day"
|
||||
ng-click="calendar.changeView('day')"><md-icon>view_day</md-icon></a>
|
||||
ng-click="calendar.changeView($event, 'day')"><md-icon>view_day</md-icon></a>
|
||||
<a class="md-icon-button md-button"
|
||||
label:aria-label="Week"
|
||||
ng-disabled="true"
|
||||
ng-click="calendar.changeView('week')"><md-icon>view_week</md-icon></a>
|
||||
ng-click="calendar.changeView($event, 'week')"><md-icon>view_week</md-icon></a>
|
||||
<a class="md-icon-button md-button"
|
||||
label:aria-label="Month"
|
||||
ng-click="calendar.changeView('month')"><md-icon>view_module</md-icon></a>
|
||||
ng-click="calendar.changeView($event, 'month')"><md-icon>view_module</md-icon></a>
|
||||
<a class="md-icon-button md-button"
|
||||
label:aria-label="Multicolumn Day View"
|
||||
ng-click="calendar.changeView('multicolumnday')"><md-icon>view_array</md-icon></a>
|
||||
ng-click="calendar.changeView($event, 'multicolumnday')"><md-icon>view_array</md-icon></a>
|
||||
</md-card-actions>
|
||||
<var:component
|
||||
className="UIxCalDayTable"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
(function() {
|
||||
/* jshint validthis: true */
|
||||
'use strict';
|
||||
|
||||
|
||||
/**
|
||||
* $sgHotkeys - A service to associate keyboard shortcuts to actions.
|
||||
* @memberof SOGo.Common
|
||||
|
@ -18,7 +18,6 @@
|
|||
// Source : http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes
|
||||
// http://unixpapa.com/js/key.html
|
||||
// Date: Oct 02, 2015.
|
||||
//var KEY_CODES = this.KEY_CODES = {
|
||||
var KEY_CODES = {
|
||||
8: 'backspace',
|
||||
9: 'tab',
|
||||
|
@ -70,6 +69,10 @@
|
|||
122: 'f11',
|
||||
123: 'f12'
|
||||
};
|
||||
// Char-code values for characters that require a key combinations
|
||||
var CHAR_CODES = {
|
||||
63: '?'
|
||||
};
|
||||
|
||||
this.$get = getService;
|
||||
|
||||
|
@ -87,11 +90,16 @@
|
|||
var HotKey = function(params) {
|
||||
this.id = params.id || guid();
|
||||
this.key = params.key;
|
||||
this.description = params.description || null;
|
||||
this.context = params.context || null;
|
||||
this.callback = params.callback;
|
||||
this.preventInClass = params.preventInClass;
|
||||
this.args = params.args;
|
||||
this.onKeyUp = false;
|
||||
|
||||
if (this.key.length > 1)
|
||||
// Automatically translate common hotkeys
|
||||
this.lkey = l('key_' + this.key);
|
||||
};
|
||||
|
||||
HotKey.prototype.clone = function() {
|
||||
|
@ -114,10 +122,11 @@
|
|||
/**
|
||||
* Keybindings are ignored by default when coming from a form input field.
|
||||
*/
|
||||
this._preventIn = ['INPUT', 'SELECT', 'MD-SELECT', 'TEXTAREA'];
|
||||
|
||||
this._preventIn = ['INPUT', 'BUTTON', 'SELECT', 'TEXTAREA'];
|
||||
|
||||
this._onKeydown = this._onKeydown.bind(this);
|
||||
this._onKeyup = this._onKeyup.bind(this);
|
||||
this._onKeypress = this._onKeypress.bind(this);
|
||||
|
||||
this.initialize();
|
||||
};
|
||||
|
@ -126,8 +135,17 @@
|
|||
* Binds Keydown, Keyup with the window object
|
||||
*/
|
||||
Hotkeys.prototype.initialize = function() {
|
||||
this.registerHotkey(
|
||||
this.createHotkey({
|
||||
key: '?',
|
||||
description: l('Show or hide this help'),
|
||||
callback: this._toggleCheatSheet.bind(this)
|
||||
})
|
||||
);
|
||||
|
||||
$window.addEventListener('keydown', this._onKeydown, true);
|
||||
$window.addEventListener('keyup', this._onKeyup, true);
|
||||
$window.addEventListener('keypress', this._onKeypress, true);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -176,6 +194,20 @@
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Keypress Event Handler
|
||||
* @private
|
||||
*/
|
||||
Hotkeys.prototype._onKeypress = function(event) {
|
||||
var charCode, keyString;
|
||||
|
||||
charCode = event.keyCode || event.which;
|
||||
keyString = CHAR_CODES[charCode];
|
||||
if (keyString && this._hotkeys[keyString]) {
|
||||
this._invokeHotkeyHandlers(event, keyString, this._hotkeys[keyString]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cross-browser method which can extract a key string from an event.
|
||||
* Key strings are of the form
|
||||
|
@ -360,12 +392,62 @@
|
|||
return Boolean(~key.indexOf(eventHotkey));
|
||||
};
|
||||
|
||||
/**
|
||||
* Build and display (or hide) the hotkeys cheat sheet
|
||||
*
|
||||
* If a hotkey is registered multiple times, only the description of the first registered
|
||||
* hotkey is displayed.
|
||||
*/
|
||||
Hotkeys.prototype._toggleCheatSheet = function() {
|
||||
var _this = this;
|
||||
|
||||
if (this._cheatSheet) {
|
||||
Hotkeys.$modal.hide();
|
||||
this._cheatSheet = null;
|
||||
}
|
||||
else {
|
||||
this._cheatSheet = Hotkeys.$modal
|
||||
.show({
|
||||
clickOutsideToClose: true,
|
||||
escapeToClose: true,
|
||||
template: [
|
||||
'<md-dialog>',
|
||||
' <md-dialog-content>',
|
||||
' <md-list>',
|
||||
' <md-list-item ng-repeat="(hotkey, keys) in hotkeys">',
|
||||
' <div class="sg-hotkey-container">',
|
||||
' <sg-hotkey>{{keys[0].lkey || hotkey}}</sg-hotkey>',
|
||||
' </div>',
|
||||
' {{keys[0].description}}',
|
||||
' </md-list-item>',
|
||||
' </md-list>',
|
||||
' </md-dialog-content>',
|
||||
'</md-dialog>'
|
||||
].join(''),
|
||||
controller: CheatSheetController,
|
||||
locals: {
|
||||
hotkeys: _this._hotkeys
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
CheatSheetController.$inject = ['$scope', 'hotkeys'];
|
||||
function CheatSheetController($scope, hotkeys) {
|
||||
$scope.hotkeys = hotkeys;
|
||||
$scope.closeDialog = function() {
|
||||
Hotkeys.$modal.hide();
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
return Hotkeys;
|
||||
}
|
||||
}
|
||||
|
||||
sgHotkeys.$inject = ['$sgHotkeys'];
|
||||
function sgHotkeys($sgHotkeys) {
|
||||
sgHotkeys.$inject = ['$mdDialog', '$sgHotkeys'];
|
||||
function sgHotkeys($mdDialog, $sgHotkeys) {
|
||||
angular.extend($sgHotkeys, { $modal: $mdDialog });
|
||||
|
||||
return new $sgHotkeys();
|
||||
}
|
||||
|
||||
|
|
|
@ -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') })
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
// Expose controller for eventual popup windows
|
||||
$window.$mailboxController = vm;
|
||||
|
||||
stateMailbox.selectFolder();
|
||||
|
||||
vm.service = Mailbox;
|
||||
vm.accounts = stateAccounts;
|
||||
vm.account = stateAccount;
|
||||
|
@ -38,6 +36,11 @@
|
|||
vm.selectAll = selectAll;
|
||||
vm.unselectMessages = unselectMessages;
|
||||
|
||||
|
||||
stateMailbox.selectFolder();
|
||||
|
||||
_registerHotkeys(hotkeys);
|
||||
|
||||
// Expunge mailbox when leaving the Mail module
|
||||
angular.element($window).on('beforeunload', _compactBeforeUnload);
|
||||
$scope.$on('$destroy', function() {
|
||||
|
@ -57,45 +60,55 @@
|
|||
$window.document.title = title;
|
||||
});
|
||||
|
||||
_registerHotkeys(hotkeys);
|
||||
|
||||
|
||||
function _registerHotkeys(keys) {
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'c',
|
||||
key: l('hotkey_search'),
|
||||
description: l('Search'),
|
||||
callback: searchMode
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: l('hotkey_compose'),
|
||||
description: l('Write a new message'),
|
||||
callback: newMessage
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'space',
|
||||
description: l('Toggle item'),
|
||||
callback: toggleMessageSelection
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'up',
|
||||
description: l('View next item'),
|
||||
callback: _nextMessage,
|
||||
preventInClass: ['sg-mail-part']
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'down',
|
||||
description: l('View previous item'),
|
||||
callback: _previousMessage,
|
||||
preventInClass: ['sg-mail-part']
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'shift+up',
|
||||
description: l('Add next item to selection'),
|
||||
callback: _addNextMessageToSelection,
|
||||
preventInClass: ['sg-mail-part']
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'shift+down',
|
||||
description: l('Add previous item to selection'),
|
||||
callback: _addPreviousMessageToSelection,
|
||||
preventInClass: ['sg-mail-part']
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'backspace',
|
||||
description: l('Delete selected message or folder'),
|
||||
callback: confirmDeleteSelectedMessages
|
||||
}));
|
||||
|
||||
// Register the hotkeys
|
||||
_.forEach(hotkeys, function(key) {
|
||||
_.forEach(keys, function(key) {
|
||||
sgHotkeys.registerHotkey(key);
|
||||
});
|
||||
}
|
||||
|
@ -169,6 +182,9 @@
|
|||
if (index > -1)
|
||||
selectMessage(vm.selectedFolder.$messages[index]);
|
||||
|
||||
if (vm.selectedFolder.$topIndex > 0)
|
||||
vm.selectedFolder.$topIndex--;
|
||||
|
||||
$event.preventDefault();
|
||||
|
||||
return index;
|
||||
|
@ -191,6 +207,9 @@
|
|||
else
|
||||
index = -1;
|
||||
|
||||
if (vm.selectedFolder.$topIndex < vm.selectedFolder.getLength())
|
||||
vm.selectedFolder.$topIndex++;
|
||||
|
||||
$event.preventDefault();
|
||||
|
||||
return index;
|
||||
|
@ -284,10 +303,10 @@
|
|||
function confirmDeleteSelectedMessages($event) {
|
||||
var selectedMessages = vm.selectedFolder.$selectedMessages();
|
||||
|
||||
if (_.size(selectedMessages) > 0)
|
||||
Dialog.confirm(l('Warning'),
|
||||
l('Are you sure you want to delete the selected messages?'),
|
||||
{ ok: l('Delete') })
|
||||
if (messageDialog === null && _.size(selectedMessages) > 0)
|
||||
messageDialog = Dialog.confirm(l('Warning'),
|
||||
l('Are you sure you want to delete the selected messages?'),
|
||||
{ ok: l('Delete') })
|
||||
.then(function() {
|
||||
var deleteSelectedMessage = vm.selectedFolder.hasSelectedMessage();
|
||||
vm.selectedFolder.$deleteMessages(selectedMessages).then(function(index) {
|
||||
|
@ -302,6 +321,9 @@
|
|||
_unselectMessage(deleteSelectedMessage, index);
|
||||
}
|
||||
});
|
||||
})
|
||||
.finally(function() {
|
||||
messageDialog = null;
|
||||
});
|
||||
|
||||
$event.preventDefault();
|
||||
|
|
|
@ -6,11 +6,12 @@
|
|||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
MailboxesController.$inject = ['$state', '$timeout', '$window', '$mdDialog', '$mdToast', '$mdMedia', '$mdSidenav', 'sgConstant', 'sgFocus', 'encodeUriFilter', 'Dialog', 'sgSettings', 'Account', 'Mailbox', 'VirtualMailbox', 'User', 'Preferences', 'stateAccounts'];
|
||||
function MailboxesController($state, $timeout, $window, $mdDialog, $mdToast, $mdMedia, $mdSidenav, sgConstant, focus, encodeUriFilter, Dialog, Settings, Account, Mailbox, VirtualMailbox, User, Preferences, stateAccounts) {
|
||||
MailboxesController.$inject = ['$scope', '$state', '$timeout', '$window', '$mdDialog', '$mdToast', '$mdMedia', '$mdSidenav', 'sgConstant', 'sgFocus', 'encodeUriFilter', 'Dialog', 'sgSettings', 'sgHotkeys', 'Account', 'Mailbox', 'VirtualMailbox', 'User', 'Preferences', 'stateAccounts'];
|
||||
function MailboxesController($scope, $state, $timeout, $window, $mdDialog, $mdToast, $mdMedia, $mdSidenav, sgConstant, focus, encodeUriFilter, Dialog, Settings, sgHotkeys, Account, Mailbox, VirtualMailbox, User, Preferences, stateAccounts) {
|
||||
var vm = this,
|
||||
account,
|
||||
mailbox;
|
||||
mailbox,
|
||||
hotkeys = [];
|
||||
|
||||
vm.service = Mailbox;
|
||||
vm.accounts = stateAccounts;
|
||||
|
@ -55,12 +56,39 @@
|
|||
params: []
|
||||
};
|
||||
|
||||
|
||||
Preferences.ready().then(function() {
|
||||
vm.showSubscribedOnly = Preferences.defaults.SOGoMailShowSubscribedFoldersOnly;
|
||||
});
|
||||
|
||||
vm.refreshUnseenCount();
|
||||
|
||||
_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 message or folder'),
|
||||
callback: function() {
|
||||
if (Mailbox.selectedFolder && !Mailbox.selectedFolder.hasSelectedMessage())
|
||||
confirmDelete(Mailbox.selectedFolder);
|
||||
}
|
||||
}));
|
||||
|
||||
// Register the hotkeys
|
||||
_.forEach(keys, function(key) {
|
||||
sgHotkeys.registerHotkey(key);
|
||||
});
|
||||
}
|
||||
|
||||
function showAdvancedSearch(path) {
|
||||
vm.showingAdvancedSearch = true;
|
||||
vm.search.mailbox = path;
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
vm.convertToEvent = convertToEvent;
|
||||
vm.convertToTask = convertToTask;
|
||||
|
||||
_registerHotkeys(hotkeys);
|
||||
|
||||
// One-way refresh of the parent window when modifying the message from a popup window.
|
||||
if ($window.opener) {
|
||||
// Update the message flags. The message must be displayed in the parent window.
|
||||
|
@ -100,8 +102,6 @@
|
|||
});
|
||||
});
|
||||
|
||||
_registerHotkeys(hotkeys);
|
||||
|
||||
|
||||
function _registerHotkeys(keys) {
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
|
@ -114,7 +114,7 @@
|
|||
}));
|
||||
|
||||
// Register the hotkeys
|
||||
_.forEach(hotkeys, function(key) {
|
||||
_.forEach(keys, function(key) {
|
||||
sgHotkeys.registerHotkey(key);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
CalendarController.$inject = ['$scope', '$rootScope', '$state', '$stateParams', 'Calendar', 'Component', 'Preferences', 'stateEventsBlocks'];
|
||||
function CalendarController($scope, $rootScope, $state, $stateParams, Calendar, Component, Preferences, stateEventsBlocks) {
|
||||
var vm = this, deregisterCalendarsList;
|
||||
CalendarController.$inject = ['$scope', '$rootScope', '$state', '$stateParams', 'sgHotkeys', 'Calendar', 'Component', 'Preferences', 'stateEventsBlocks'];
|
||||
function CalendarController($scope, $rootScope, $state, $stateParams, sgHotkeys, Calendar, Component, Preferences, stateEventsBlocks) {
|
||||
var vm = this, deregisterCalendarsList, hotkeys = [];
|
||||
|
||||
// Make the toolbar state of all-day events persistent
|
||||
if (angular.isUndefined(CalendarController.expandedAllDays))
|
||||
|
@ -21,6 +21,9 @@
|
|||
vm.changeDate = changeDate;
|
||||
vm.changeView = changeView;
|
||||
|
||||
|
||||
_registerHotkeys(hotkeys);
|
||||
|
||||
Preferences.ready().then(function() {
|
||||
_formatDate(vm.selectedDate);
|
||||
});
|
||||
|
@ -28,8 +31,84 @@
|
|||
// Refresh current view when the list of calendars is modified
|
||||
deregisterCalendarsList = $rootScope.$on('calendars:list', updateView);
|
||||
|
||||
// Destroy event listener when the controller is being deactivated
|
||||
$scope.$on('$destroy', deregisterCalendarsList);
|
||||
$scope.$on('$destroy', function() {
|
||||
// Destroy event listener when the controller is being deactivated
|
||||
deregisterCalendarsList();
|
||||
// Deregister hotkeys
|
||||
_.forEach(hotkeys, function(key) {
|
||||
sgHotkeys.deregisterHotkey(key);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function _registerHotkeys(keys) {
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: l('hotkey_today'),
|
||||
description: l('Today'),
|
||||
callback: changeDate,
|
||||
args: new Date()
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: l('hotkey_dayview'),
|
||||
description: l('Day'),
|
||||
callback: changeView,
|
||||
args: 'day'
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: l('hotkey_weekview'),
|
||||
description: l('Week'),
|
||||
callback: changeView,
|
||||
args: 'week'
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: l('hotkey_monthview'),
|
||||
description: l('Month'),
|
||||
callback: changeView,
|
||||
args: 'month'
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: l('hotkey_multicolumndayview'),
|
||||
description: l('Multicolumn Day View'),
|
||||
callback: changeView,
|
||||
args: 'multicolumnday'
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'left',
|
||||
description: l('Move backward'),
|
||||
callback: _goToPeriod,
|
||||
args: -1
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: 'right',
|
||||
description: l('Move forward'),
|
||||
callback: _goToPeriod,
|
||||
args: +1
|
||||
}));
|
||||
|
||||
// Register the hotkeys
|
||||
_.forEach(keys, function(key) {
|
||||
sgHotkeys.registerHotkey(key);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function _goToPeriod($event, direction) {
|
||||
var date;
|
||||
|
||||
if ($stateParams.view == 'week') {
|
||||
date = vm.selectedDate.beginOfWeek(Preferences.defaults.SOGoFirstDayOfWeek).addDays(7 * direction);
|
||||
}
|
||||
else if ($stateParams.view == 'month') {
|
||||
date = vm.selectedDate;
|
||||
date.setDate(1);
|
||||
date.setMonth(date.getMonth() + direction);
|
||||
}
|
||||
else {
|
||||
date = vm.selectedDate.addDays(direction);
|
||||
}
|
||||
|
||||
changeDate($event, date);
|
||||
}
|
||||
|
||||
function _formatDate(date) {
|
||||
if ($stateParams.view == 'month') {
|
||||
|
@ -75,7 +154,7 @@
|
|||
}
|
||||
|
||||
// Change calendar's view
|
||||
function changeView(view) {
|
||||
function changeView($event, view) {
|
||||
$state.go('calendars.view', { view: view });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
CalendarListController.$inject = ['$rootScope', '$timeout', '$state', '$mdDialog', 'Dialog', 'Preferences', 'Calendar', 'Component'];
|
||||
function CalendarListController($rootScope, $timeout, $state, $mdDialog, Dialog, Preferences, Calendar, Component) {
|
||||
var vm = this;
|
||||
CalendarListController.$inject = ['$rootScope', '$scope', '$timeout', '$state', '$mdDialog', 'sgHotkeys', 'sgFocus', 'Dialog', 'Preferences', 'Calendar', 'Component'];
|
||||
function CalendarListController($rootScope, $scope, $timeout, $state, $mdDialog, sgHotkeys, focus, Dialog, Preferences, Calendar, Component) {
|
||||
var vm = this, hotkeys = [];
|
||||
|
||||
vm.component = Component;
|
||||
vm.componentType = 'events';
|
||||
|
@ -16,6 +16,7 @@
|
|||
vm.selectComponentType = selectComponentType;
|
||||
vm.unselectComponents = unselectComponents;
|
||||
vm.selectAll = selectAll;
|
||||
vm.searchMode = searchMode;
|
||||
vm.toggleComponentSelection = toggleComponentSelection;
|
||||
vm.confirmDeleteSelectedComponents = confirmDeleteSelectedComponents;
|
||||
vm.openEvent = openEvent;
|
||||
|
@ -30,6 +31,9 @@
|
|||
vm.cancelSearch = cancelSearch;
|
||||
vm.mode = { search: false, multiple: 0 };
|
||||
|
||||
|
||||
_registerHotkeys(hotkeys);
|
||||
|
||||
// Select list based on user's settings
|
||||
Preferences.ready().then(function() {
|
||||
var type = 'events';
|
||||
|
@ -48,6 +52,39 @@
|
|||
// Update the component being dragged
|
||||
$rootScope.$on('calendar:dragend', updateComponentFromGhost);
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
// Deregister hotkeys
|
||||
_.forEach(hotkeys, function(key) {
|
||||
sgHotkeys.deregisterHotkey(key);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function _registerHotkeys(keys) {
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: l('hotkey_search'),
|
||||
description: l('Search'),
|
||||
callback: searchMode
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: l('hotkey_create_event'),
|
||||
description: l('Create a new event'),
|
||||
callback: newComponent,
|
||||
args: 'appointment'
|
||||
}));
|
||||
keys.push(sgHotkeys.createHotkey({
|
||||
key: l('hotkey_create_task'),
|
||||
description: l('Create a new task'),
|
||||
callback: newComponent,
|
||||
args: 'task'
|
||||
}));
|
||||
|
||||
// Register the hotkeys
|
||||
_.forEach(keys, function(key) {
|
||||
sgHotkeys.registerHotkey(key);
|
||||
});
|
||||
}
|
||||
|
||||
// Switch between components tabs
|
||||
function selectComponentType(type, options) {
|
||||
if (options && options.reload || vm.componentType != type) {
|
||||
|
@ -80,6 +117,11 @@
|
|||
$event.stopPropagation();
|
||||
}
|
||||
|
||||
function searchMode() {
|
||||
vm.mode.search = true;
|
||||
focus('search');
|
||||
}
|
||||
|
||||
function confirmDeleteSelectedComponents() {
|
||||
Dialog.confirm(l('Warning'),
|
||||
l('Are you sure you want to delete the selected components?'),
|
||||
|
@ -317,7 +359,7 @@
|
|||
Component.$filter(vm.componentType, { value: '' });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
angular
|
||||
.module('SOGo.SchedulerUI')
|
||||
.controller('CalendarListController', CalendarListController);
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/// hotkeys.scss -*- Mode: scss; indent-tabs-mode: nil; basic-offset: 2 -*-
|
||||
|
||||
.sg-hotkey-container {
|
||||
display: inline;
|
||||
margin-right: 1em;
|
||||
text-align: right;
|
||||
max-width: 7em;
|
||||
min-width: 3em;
|
||||
}
|
||||
|
||||
sg-hotkey {
|
||||
background-color: #333;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #333;
|
||||
box-shadow: inset 0 1px 0 #666, 0 1px 0 #bbb;
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
padding: 5px 9px;
|
||||
text-align: center;
|
||||
}
|
|
@ -65,6 +65,7 @@
|
|||
// Inverse components
|
||||
@import 'components/draggable-droppable/draggable';
|
||||
@import 'components/draggable-droppable/droppable';
|
||||
@import 'components/hotkeys/hotkeys';
|
||||
@import 'components/ripple/ripple';
|
||||
@import 'components/timepicker/timepicker';
|
||||
@import 'components/pseudo-input/pseudo-input';
|
||||
|
|
Loading…
Reference in New Issue