(js) Add batch operations in advanced search
parent
cf3a9b89b6
commit
13e826b6f2
1
NEWS
1
NEWS
|
@ -7,6 +7,7 @@ New features
|
|||
Enhancements
|
||||
- [eas] use the preferred email identity in EAS if valid (#3698)
|
||||
- [eas] handle inline attachments during EAS content generation
|
||||
- [web] all batch operations can now be performed on selected messages in advanced search mode
|
||||
|
||||
Bug fixes
|
||||
- [web] fixed crash when an attachment filename has no extension
|
||||
|
|
|
@ -65,11 +65,11 @@
|
|||
<!-- sort mode (default) -->
|
||||
<div class="md-toolbar-tools" ng-hide="mailbox.mode.search">
|
||||
<md-button class="sg-icon-button" label:aria-label="Search"
|
||||
ng-click="mailbox.mode.search = true">
|
||||
ng-click="mailbox.searchMode()">
|
||||
<md-icon>search</md-icon>
|
||||
</md-button>
|
||||
<a href="javascript:void(0)" class="sg-folder-name"
|
||||
ng-click="mailbox.mode.search = true">{{mailbox.selectedFolder.name}}</a>
|
||||
ng-click="mailbox.searchMode()">{{mailbox.selectedFolder.name}}</a>
|
||||
<md-menu>
|
||||
<md-button class="sg-icon-button" label:aria-label="Sort"
|
||||
ng-click="$mdOpenMenu()">
|
||||
|
@ -128,7 +128,7 @@
|
|||
<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>
|
||||
|
|
|
@ -221,6 +221,16 @@
|
|||
return Mailbox.$absolutePath(this.$account.id, this.path);
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $selectedMessages
|
||||
* @memberof Mailbox.prototype
|
||||
* @desc Return the messages selected by the user.
|
||||
* @returns Message instances
|
||||
*/
|
||||
Mailbox.prototype.$selectedMessages = function() {
|
||||
return _.filter(this.$messages, function(message) { return message.selected; });
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $selectedCount
|
||||
* @memberof Mailbox.prototype
|
||||
|
@ -228,13 +238,7 @@
|
|||
* @returns the number of selected messages
|
||||
*/
|
||||
Mailbox.prototype.$selectedCount = function() {
|
||||
var count;
|
||||
|
||||
count = 0;
|
||||
if (this.$messages) {
|
||||
count = (_.filter(this.$messages, function(message) { return message.selected; })).length;
|
||||
}
|
||||
return count;
|
||||
return this.$selectedMessages().length;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -542,12 +546,14 @@
|
|||
* @desc Add or remove a flag on a message set
|
||||
* @returns a promise of the HTTP operation
|
||||
*/
|
||||
Mailbox.prototype.$flagMessages = function(uids, flags, operation) {
|
||||
var data = {msgUIDs: uids,
|
||||
Mailbox.prototype.$flagMessages = function(messages, flags, operation) {
|
||||
var data = {msgUIDs: _.map(messages, 'uid'),
|
||||
flags: flags,
|
||||
operation: operation};
|
||||
|
||||
return Mailbox.$$resource.post(this.id, 'addOrRemoveLabel', data);
|
||||
return Mailbox.$$resource.post(this.id, 'addOrRemoveLabel', data).then(function() {
|
||||
return messages;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -656,9 +662,9 @@
|
|||
* @return a promise of the HTTP operation
|
||||
*/
|
||||
Mailbox.prototype.$markOrUnMarkMessagesAsJunk = function(messages) {
|
||||
var _this = this, uids;
|
||||
var method = (this.type == 'junk' ? 'markMessagesAsNotJunk' : 'markMessagesAsJunk');
|
||||
uids = _.map(messages, 'uid');
|
||||
var _this = this,
|
||||
uids = _.map(messages, 'uid'),
|
||||
method = (this.type == 'junk' ? 'markMessagesAsNotJunk' : 'markMessagesAsJunk');
|
||||
|
||||
return Mailbox.$$resource.post(this.id, method, {uids: uids});
|
||||
};
|
||||
|
@ -669,8 +675,9 @@
|
|||
* @desc Copy multiple messages from the current mailbox to a target one
|
||||
* @return a promise of the HTTP operation
|
||||
*/
|
||||
Mailbox.prototype.$copyMessages = function(uids, folder) {
|
||||
var _this = this;
|
||||
Mailbox.prototype.$copyMessages = function(messages, folder) {
|
||||
var _this = this,
|
||||
uids = _.map(messages, 'uid');
|
||||
|
||||
return Mailbox.$$resource.post(this.id, 'copyMessages', {uids: uids, folder: folder})
|
||||
.then(function(data) {
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
MailboxController.$inject = ['$window', '$timeout', '$state', '$mdDialog', 'stateAccounts', 'stateAccount', 'stateMailbox', 'encodeUriFilter', 'Dialog', 'Account', 'Mailbox'];
|
||||
function MailboxController($window, $timeout, $state, $mdDialog, stateAccounts, stateAccount, stateMailbox, encodeUriFilter, Dialog, Account, Mailbox) {
|
||||
MailboxController.$inject = ['$window', '$timeout', '$q', '$state', '$mdDialog', 'stateAccounts', 'stateAccount', 'stateMailbox', 'encodeUriFilter', 'sgFocus', 'Dialog', 'Account', 'Mailbox'];
|
||||
function MailboxController($window, $timeout, $q, $state, $mdDialog, stateAccounts, stateAccount, stateMailbox, encodeUriFilter, focus, Dialog, Account, Mailbox) {
|
||||
var vm = this, messageDialog = null;
|
||||
|
||||
// Expose controller
|
||||
|
@ -21,7 +21,12 @@
|
|||
vm.selectedFolder = stateMailbox;
|
||||
vm.selectMessage = selectMessage;
|
||||
vm.toggleMessageSelection = toggleMessageSelection;
|
||||
vm.unselectMessages = unselectMessages;
|
||||
vm.sort = sort;
|
||||
vm.sortedBy = sortedBy;
|
||||
vm.searchMode = searchMode;
|
||||
vm.cancelSearch = cancelSearch;
|
||||
vm.newMessage = newMessage;
|
||||
vm.mode = { search: false, multiple: 0 };
|
||||
vm.confirmDeleteSelectedMessages = confirmDeleteSelectedMessages;
|
||||
vm.markOrUnMarkMessagesAsJunk = markOrUnMarkMessagesAsJunk;
|
||||
vm.copySelectedMessages = copySelectedMessages;
|
||||
|
@ -29,160 +34,7 @@
|
|||
vm.markSelectedMessagesAsFlagged = markSelectedMessagesAsFlagged;
|
||||
vm.markSelectedMessagesAsUnread = markSelectedMessagesAsUnread;
|
||||
vm.selectAll = selectAll;
|
||||
vm.sort = sort;
|
||||
vm.sortedBy = sortedBy;
|
||||
vm.cancelSearch = cancelSearch;
|
||||
vm.newMessage = newMessage;
|
||||
vm.mode = { search: false, multiple: 0 };
|
||||
|
||||
function selectMessage(message) {
|
||||
if (Mailbox.$virtualMode)
|
||||
$state.go('mail.account.virtualMailbox.message', {accountId: stateAccount.id, mailboxId: encodeUriFilter(message.$mailbox.path), messageId: message.uid});
|
||||
else
|
||||
$state.go('mail.account.mailbox.message', {messageId: message.uid});
|
||||
}
|
||||
|
||||
function toggleMessageSelection($event, message) {
|
||||
message.selected = !message.selected;
|
||||
vm.mode.multiple += message.selected? 1 : -1;
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
}
|
||||
|
||||
function unselectMessages() {
|
||||
_.forEach(vm.selectedFolder.$messages, function(message) {
|
||||
message.selected = false;
|
||||
});
|
||||
vm.mode.multiple = 0;
|
||||
}
|
||||
|
||||
function confirmDeleteSelectedMessages() {
|
||||
Dialog.confirm(l('Warning'),
|
||||
l('Are you sure you want to delete the selected messages?'),
|
||||
{ ok: l('Delete') })
|
||||
.then(function() {
|
||||
var deleteSelectedMessage = false;
|
||||
var selectedMessages = _.filter(vm.selectedFolder.$messages, function(message) {
|
||||
if (message.selected &&
|
||||
message.uid == vm.selectedFolder.selectedMessage)
|
||||
deleteSelectedMessage = true;
|
||||
return message.selected;
|
||||
});
|
||||
vm.selectedFolder.$deleteMessages(selectedMessages).then(function(index) {
|
||||
unselectMessage(deleteSelectedMessage, index);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function markOrUnMarkMessagesAsJunk() {
|
||||
var moveSelectedMessage = false;
|
||||
var selectedMessages = _.filter(vm.selectedFolder.$messages, function(message) {
|
||||
if (message.selected &&
|
||||
message.uid == vm.selectedFolder.selectedMessage)
|
||||
moveSelectedMessage = true;
|
||||
return message.selected;
|
||||
});
|
||||
|
||||
vm.selectedFolder.$markOrUnMarkMessagesAsJunk(selectedMessages).then(function() {
|
||||
var folder = '/' + vm.account.id + '/folderINBOX';
|
||||
|
||||
if (vm.selectedFolder.type != 'junk') {
|
||||
folder = '/' + vm.account.$getMailboxByType('junk').id;
|
||||
}
|
||||
|
||||
vm.selectedFolder.$moveMessages(selectedMessages, folder).then(function(index) {
|
||||
unselectMessage(moveSelectedMessage, index);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function unselectMessage(message, index) {
|
||||
// Unselect current message and cleverly load the next message
|
||||
var nextMessage, previousMessage, nextIndex = index;
|
||||
vm.mode.multiple = vm.selectedFolder.$selectedCount();
|
||||
if (message) {
|
||||
if (Mailbox.$virtualMode) {
|
||||
$state.go('mail.account.virtualMailbox');
|
||||
}
|
||||
else {
|
||||
// Select either the next or previous message
|
||||
if (index > 0) {
|
||||
nextIndex -= 1;
|
||||
nextMessage = vm.selectedFolder.$messages[nextIndex];
|
||||
}
|
||||
if (index < vm.selectedFolder.$messages.length)
|
||||
previousMessage = vm.selectedFolder.$messages[index];
|
||||
if (nextMessage) {
|
||||
if (nextMessage.isread && previousMessage && !previousMessage.isread) {
|
||||
nextIndex = index;
|
||||
nextMessage = previousMessage;
|
||||
}
|
||||
}
|
||||
else if (previousMessage) {
|
||||
nextIndex = index;
|
||||
nextMessage = previousMessage;
|
||||
}
|
||||
if (nextMessage) {
|
||||
$state.go('mail.account.mailbox.message', { messageId: nextMessage.uid });
|
||||
vm.selectedFolder.$topIndex = nextIndex;
|
||||
}
|
||||
else {
|
||||
$state.go('mail.account.mailbox');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function copySelectedMessages(folder) {
|
||||
var selectedMessages = _.filter(vm.selectedFolder.$messages, function(message) { return message.selected; });
|
||||
var selectedUIDs = _.map(selectedMessages, 'uid');
|
||||
vm.selectedFolder.$copyMessages(selectedUIDs, '/' + folder);
|
||||
}
|
||||
|
||||
function moveSelectedMessages(folder) {
|
||||
var moveSelectedMessage = false;
|
||||
var selectedMessages = _.filter(vm.selectedFolder.$messages, function(message) {
|
||||
if (message.selected &&
|
||||
message.uid == vm.selectedFolder.selectedMessage)
|
||||
moveSelectedMessage = true;
|
||||
return message.selected;
|
||||
});
|
||||
vm.selectedFolder.$moveMessages(selectedMessages, '/' + folder).then(function(index) {
|
||||
unselectMessage(moveSelectedMessage, index);
|
||||
});
|
||||
}
|
||||
|
||||
function selectAll() {
|
||||
var i = 0, length = vm.selectedFolder.$messages.length;
|
||||
for (; i < length; i++)
|
||||
vm.selectedFolder.$messages[i].selected = true;
|
||||
vm.mode.multiple = length;
|
||||
}
|
||||
|
||||
function markSelectedMessagesAsFlagged() {
|
||||
var selectedMessages = _.filter(vm.selectedFolder.$messages, function(message) { return message.selected; });
|
||||
var selectedUIDs = _.map(selectedMessages, 'uid');
|
||||
|
||||
vm.selectedFolder.$flagMessages(selectedUIDs, '\\Flagged', 'add').then(function(d) {
|
||||
// Success
|
||||
_.forEach(selectedMessages, function(message) {
|
||||
message.isflagged = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function markSelectedMessagesAsUnread() {
|
||||
var selectedMessages = _.filter(vm.selectedFolder.$messages, function(message) { return message.selected; });
|
||||
var selectedUIDs = _.map(selectedMessages, 'uid');
|
||||
|
||||
vm.selectedFolder.$flagMessages(selectedUIDs, 'seen', 'remove').then(function(d) {
|
||||
// Success
|
||||
_.forEach(selectedMessages, function(message) {
|
||||
message.isread = false;
|
||||
vm.selectedFolder.unseenCount++;
|
||||
});
|
||||
});
|
||||
}
|
||||
vm.unselectMessages = unselectMessages;
|
||||
|
||||
function sort(field) {
|
||||
vm.selectedFolder.$filter({ sort: field });
|
||||
|
@ -192,6 +44,11 @@
|
|||
return Mailbox.$query.sort == field;
|
||||
}
|
||||
|
||||
function searchMode() {
|
||||
vm.mode.search = true;
|
||||
focus('search');
|
||||
}
|
||||
|
||||
function cancelSearch() {
|
||||
vm.mode.search = false;
|
||||
vm.selectedFolder.$filter().then(function() {
|
||||
|
@ -228,6 +85,183 @@
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
function selectMessage(message) {
|
||||
if (Mailbox.$virtualMode)
|
||||
$state.go('mail.account.virtualMailbox.message', {mailboxId: encodeUriFilter(message.$mailbox.path), messageId: message.uid});
|
||||
else
|
||||
$state.go('mail.account.mailbox.message', {messageId: message.uid});
|
||||
}
|
||||
|
||||
function toggleMessageSelection($event, message) {
|
||||
message.selected = !message.selected;
|
||||
vm.mode.multiple += message.selected? 1 : -1;
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch operations
|
||||
*/
|
||||
|
||||
function _currentMailboxes() {
|
||||
if (Mailbox.$virtualMode)
|
||||
return vm.selectedFolder.$mailboxes;
|
||||
else
|
||||
return [vm.selectedFolder];
|
||||
}
|
||||
|
||||
function _unselectMessage(message, index) {
|
||||
// Unselect current message and cleverly load the next message.
|
||||
// This function must not be called in virtual mode.
|
||||
var nextMessage, previousMessage, nextIndex = index;
|
||||
vm.mode.multiple = vm.selectedFolder.$selectedCount();
|
||||
if (message) {
|
||||
// Select either the next or previous message
|
||||
if (index > 0) {
|
||||
nextIndex -= 1;
|
||||
nextMessage = vm.selectedFolder.$messages[nextIndex];
|
||||
}
|
||||
if (index < vm.selectedFolder.$messages.length)
|
||||
previousMessage = vm.selectedFolder.$messages[index];
|
||||
if (nextMessage) {
|
||||
if (nextMessage.isread && previousMessage && !previousMessage.isread) {
|
||||
nextIndex = index;
|
||||
nextMessage = previousMessage;
|
||||
}
|
||||
}
|
||||
else if (previousMessage) {
|
||||
nextIndex = index;
|
||||
nextMessage = previousMessage;
|
||||
}
|
||||
if (nextMessage) {
|
||||
vm.selectedFolder.$topIndex = nextIndex;
|
||||
$state.go('mail.account.mailbox.message', { messageId: nextMessage.uid });
|
||||
}
|
||||
else {
|
||||
$state.go('mail.account.mailbox');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$timeout(function() {
|
||||
console.warn('go to mailbox');
|
||||
$state.go('mail.account.mailbox');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function confirmDeleteSelectedMessages() {
|
||||
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();
|
||||
var selectedMessages = vm.selectedFolder.$selectedMessages();
|
||||
if (_.size(selectedMessages) > 0)
|
||||
vm.selectedFolder.$deleteMessages(selectedMessages).then(function(index) {
|
||||
if (Mailbox.$virtualMode) {
|
||||
// When performing an advanced search, we refresh the view if the selected message
|
||||
// was deleted, but only once all promises have completed.
|
||||
if (deleteSelectedMessage)
|
||||
$state.go('mail.account.virtualMailbox');
|
||||
}
|
||||
else {
|
||||
// In normal mode, we immediately unselect the selected message.
|
||||
_unselectMessage(deleteSelectedMessage, index);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function markOrUnMarkMessagesAsJunk() {
|
||||
var moveSelectedMessage = vm.selectedFolder.hasSelectedMessage();
|
||||
var selectedMessages = vm.selectedFolder.$selectedMessages();
|
||||
if (_.size(selectedMessages) > 0)
|
||||
vm.selectedFolder.$markOrUnMarkMessagesAsJunk(selectedMessages).then(function() {
|
||||
var dstFolder = '/' + vm.account.id + '/folderINBOX';
|
||||
if (vm.selectedFolder.type != 'junk') {
|
||||
dstFolder = '/' + vm.account.$getMailboxByType('junk').id;
|
||||
}
|
||||
vm.selectedFolder.$moveMessages(selectedMessages, dstFolder).then(function(index) {
|
||||
if (Mailbox.$virtualMode) {
|
||||
// When performing an advanced search, we refresh the view if the selected message
|
||||
// was deleted, but only once all promises have completed.
|
||||
if (moveSelectedMessage)
|
||||
$state.go('mail.account.virtualMailbox');
|
||||
}
|
||||
else {
|
||||
// In normal mode, we immediately unselect the selected message.
|
||||
_unselectMessage(moveSelectedMessage, index);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function copySelectedMessages(dstFolder) {
|
||||
var selectedMessages = vm.selectedFolder.$selectedMessages();
|
||||
if (_.size(selectedMessages) > 0)
|
||||
vm.selectedFolder.$copyMessages(selectedMessages, '/' + dstFolder);
|
||||
}
|
||||
|
||||
function moveSelectedMessages(dstFolder) {
|
||||
var moveSelectedMessage = vm.selectedFolder.hasSelectedMessage();
|
||||
var selectedMessages = vm.selectedFolder.$selectedMessages();
|
||||
if (_.size(selectedMessages) > 0)
|
||||
vm.selectedFolder.$moveMessages(selectedMessages, '/' + dstFolder).then(function(index) {
|
||||
if (Mailbox.$virtualMode) {
|
||||
// When performing an advanced search, we refresh the view if the selected message
|
||||
// was moved, but only once all promises have completed.
|
||||
if (moveSelectedMessage)
|
||||
$state.go('mail.account.virtualMailbox');
|
||||
}
|
||||
else {
|
||||
// In normal mode, we immediately unselect the selected message.
|
||||
_unselectMessage(moveSelectedMessage, index);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function selectAll() {
|
||||
var count = 0;
|
||||
_.forEach(_currentMailboxes(), function(folder) {
|
||||
var i = 0, length = folder.$messages.length;
|
||||
for (; i < length; i++)
|
||||
folder.$messages[i].selected = true;
|
||||
count += length;
|
||||
});
|
||||
vm.mode.multiple = count;
|
||||
}
|
||||
|
||||
function unselectMessages() {
|
||||
_.forEach(_currentMailboxes(), function(folder) {
|
||||
_.forEach(folder.$messages, function(message) {
|
||||
message.selected = false;
|
||||
});
|
||||
});
|
||||
vm.mode.multiple = 0;
|
||||
}
|
||||
|
||||
function markSelectedMessagesAsFlagged() {
|
||||
var selectedMessages = vm.selectedFolder.$selectedMessages();
|
||||
if (_.size(selectedMessages) > 0)
|
||||
vm.selectedFolder.$flagMessages(selectedMessages, '\\Flagged', 'add').then(function(messages) {
|
||||
_.forEach(messages, function(message) {
|
||||
message.isflagged = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function markSelectedMessagesAsUnread() {
|
||||
var selectedMessages = vm.selectedFolder.$selectedMessages();
|
||||
if (_.size(selectedMessages) > 0)
|
||||
vm.selectedFolder.$flagMessages(selectedMessages, 'seen', 'remove').then(function(messages) {
|
||||
_.forEach(messages, function(message) {
|
||||
message.isread = false;
|
||||
message.$mailbox.unseenCount++;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular
|
||||
|
|
|
@ -521,10 +521,19 @@
|
|||
* @returns a promise of the HTTP operation
|
||||
*/
|
||||
Message.prototype.$reload = function(options) {
|
||||
var futureMessageData;
|
||||
var _this = this, futureMessageData;
|
||||
|
||||
if (options && options.useCache && this.$futureMessageData)
|
||||
if (options && options.useCache && this.$futureMessageData) {
|
||||
if (!this.isread) {
|
||||
Message.$$resource.fetch(this.$absolutePath(), 'markMessageRead').then(function() {
|
||||
Message.$timeout(function() {
|
||||
_this.isread = true;
|
||||
_this.$mailbox.unseenCount--;
|
||||
});
|
||||
});
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
futureMessageData = Message.$$resource.fetch(this.$absolutePath(options), 'view');
|
||||
|
||||
|
|
Loading…
Reference in New Issue