(js) Drag'n'drop of cards in AddressBook module

Required to add the option to move multiple cards to another
addressbook. Fixed the possibility to copy cards to a subscribed
calendar.
This commit is contained in:
Francis Lachapelle
2016-08-05 16:08:04 -04:00
parent e963981460
commit 907024d2c4
7 changed files with 264 additions and 51 deletions
@@ -337,6 +337,16 @@
return loaded;
};
/**
* @function hasSelectedMessage
* @memberof AddressBook.prototype
* @desc Check if a card is selected.
* @returns true if the a card is selected
*/
AddressBook.prototype.hasSelectedCard = function() {
return angular.isDefined(this.selectedCard);
};
/**
* @function isSelectedCard
* @memberof AddressBook.prototype
@@ -345,7 +355,29 @@
* @returns true if the specified card is selected
*/
AddressBook.prototype.isSelectedCard = function(cardId) {
return this.selectedCard == cardId;
return this.hasSelectedCard() && this.selectedCard == cardId;
};
/**
* @function $selectedCard
* @memberof AddressBook.prototype
* @desc Return the currently visible card.
* @returns a Card instance or undefined if no card is displayed
*/
AddressBook.prototype.$selectedCard = function() {
var _this = this;
return _.find(this.$cards, function(card) { return card.id == _this.selectedCard; });
};
/**
* @function $selectedCards
* @memberof AddressBook.prototype
* @desc Return the cards selected by the user.
* @returns Card instances
*/
AddressBook.prototype.$selectedCards = function() {
return _.filter(this.$cards, function(card) { return card.selected; });
};
/**
@@ -553,6 +585,33 @@
return d.promise;
};
/**
* @function $_deleteCards
* @memberof AddressBook.prototype
* @desc Delete multiple cards from AddressBook object.
* @param {string[]} ids - the cards ids
*/
AddressBook.prototype.$_deleteCards = function(ids) {
var _this = this;
// Remove cards from $cards and idsMap
_.forEachRight(this.$cards, function(card, index) {
var selectedIndex = _.findIndex(ids, function(id) {
return card.id == id;
});
if (selectedIndex > -1) {
ids.splice(selectedIndex, 1);
delete _this.idsMap[card.id];
if (_this.isSelectedCard(card.id))
delete _this.selectedCard;
_this.$cards.splice(index, 1);
}
else {
_this.idsMap[card.id] -= ids.length;
}
});
};
/**
* @function $deleteCards
* @memberof AddressBook.prototype
@@ -561,25 +620,10 @@
*/
AddressBook.prototype.$deleteCards = function(cards) {
var _this = this,
ids = _.map(cards, function(card) { return card.id; });
ids = _.map(cards, 'id');
return AddressBook.$$resource.post(this.id, 'batchDelete', {uids: ids}).then(function() {
// Remove cards from $cards and idsMap
_.forEachRight(_this.$cards, function(card, index) {
var selectedIndex = _.findIndex(ids, function(id) {
return card.id == id;
});
if (selectedIndex > -1) {
ids.splice(selectedIndex, 1);
delete _this.idsMap[card.id];
if (_this.isSelectedCard(card.id))
delete _this.selectedCard;
_this.$cards.splice(index, 1);
}
else {
_this.idsMap[card.id] -= ids.length;
}
});
_this.$_deleteCards(ids);
});
};
@@ -590,10 +634,28 @@
* @return a promise of the HTTP operation
*/
AddressBook.prototype.$copyCards = function(cards, folder) {
var uids = _.map(cards, function(card) { return card.id; });
var uids = _.map(cards, 'id');
return AddressBook.$$resource.post(this.id, 'copy', {uids: uids, folder: folder});
};
/**
* @function $moveCards
* @memberof AddressBook.prototype
* @desc Move multiple cards from the current addressbook to a target one
* @param {object[]} cards - instances of Card object
* @param {string} folder - the destination folder id
* @return a promise of the HTTP operation
*/
AddressBook.prototype.$moveCards = function(cards, folder) {
var _this = this, uids;
uids = _.map(cards, 'id');
return AddressBook.$$resource.post(this.id, 'move', {uids: uids, folder: folder})
.then(function() {
return _this.$_deleteCards(uids);
});
};
/**
* @function $save
* @memberof AddressBook.prototype
@@ -6,8 +6,8 @@
/**
* @ngInject
*/
AddressBookController.$inject = ['$scope', '$q', '$window', '$state', '$timeout', '$mdDialog', 'Account', 'Card', 'AddressBook', 'Dialog', 'sgSettings', 'stateAddressbooks', 'stateAddressbook'];
function AddressBookController($scope, $q, $window, $state, $timeout, $mdDialog, Account, Card, AddressBook, Dialog, Settings, stateAddressbooks, stateAddressbook) {
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;
AddressBook.selectedFolder = stateAddressbook;
@@ -20,6 +20,7 @@
vm.unselectCards = unselectCards;
vm.confirmDeleteSelectedCards = confirmDeleteSelectedCards;
vm.copySelectedCards = copySelectedCards;
vm.moveSelectedCards = moveSelectedCards;
vm.selectAll = selectAll;
vm.sort = sort;
vm.sortedBy = sortedBy;
@@ -66,11 +67,58 @@
});
}
function copySelectedCards(folder) {
var selectedCards = _.filter(vm.selectedFolder.$cards, function(card) { return card.selected; });
vm.selectedFolder.$copyCards(selectedCards, folder).then(function() {
// TODO: refresh target addressbook?
/**
* @see AddressBooksController.dragSelectedCards
*/
function _selectedCardsOperation(operation, dstId) {
var srcFolder, allCards, cards, ids, clearCardView, promise, success;
srcFolder = vm.selectedFolder;
clearCardView = false;
allCards = srcFolder.$selectedCards();
cards = _.filter(allCards, function(card) {
return card.$isCard();
});
if (cards.length != allCards.length)
$mdToast.show(
$mdToast.simple()
.content(l("Lists can't be moved or copied."))
.position('top right')
.hideDelay(2000));
if (cards.length) {
if (operation == 'copy') {
promise = srcFolder.$copyCards(cards, dstId);
success = l('%{0} card(s) copied', cards.length);
}
else {
promise = srcFolder.$moveCards(cards, dstId);
success = l('%{0} card(s) moved', cards.length);
// Check if currently displayed card will be moved
ids = _.map(cards, 'id');
clearCardView = (srcFolder.selectedCard && ids.indexOf(srcFolder.selectedCard) >= 0);
}
// Show success toast when action succeeds
promise.then(function() {
if (clearCardView)
$state.go('app.addressbook');
$mdToast.show(
$mdToast.simple()
.content(success)
.position('top right')
.hideDelay(2000));
});
}
}
function copySelectedCards(folder) {
_selectedCardsOperation('copy', folder);
}
function moveSelectedCards(folder) {
_selectedCardsOperation('move', folder);
}
function selectAll() {
@@ -23,6 +23,8 @@
vm.showProperties = showProperties;
vm.share = share;
vm.subscribeToFolder = subscribeToFolder;
vm.isDroppableFolder = isDroppableFolder;
vm.dragSelectedCards = dragSelectedCards;
function select($event, folder) {
if ($state.params.addressbookId != folder.id &&
@@ -214,7 +216,7 @@
addressbook: addressbook
}
});
/**
* @ngInject
*/
@@ -301,6 +303,58 @@
.hideDelay(3000));
});
}
function isDroppableFolder(srcFolder, dstFolder) {
return (dstFolder.id != srcFolder.id) && (dstFolder.isOwned || dstFolder.acls.objectCreator);
}
/**
* @see AddressBookController._selectedCardsOperation
*/
function dragSelectedCards(srcFolder, dstFolder, mode) {
var dstId, cards, ids, clearCardView, promise, success;
dstId = dstFolder.id;
clearCardView = false;
cards = srcFolder.$selectedCards();
if (cards.length === 0)
cards = [srcFolder.$selectedCard()];
if (_.find(cards, function(card) {
return card.$isList();
})) {
$mdToast.show(
$mdToast.simple()
.content(l("Lists can't be moved or copied."))
.position('top right')
.hideDelay(2000));
return;
}
if (mode == 'copy') {
promise = srcFolder.$copyCards(cards, dstId);
success = l('%{0} card(s) copied', cards.length);
}
else {
promise = srcFolder.$moveCards(cards, dstId);
success = l('%{0} card(s) moved', cards.length);
// Check if currently displayed card will be moved
ids = _.map(cards, 'id');
clearCardView = (srcFolder.selectedCard && ids.indexOf(srcFolder.selectedCard) >= 0);
}
// Show success toast when action succeeds
promise.then(function() {
if (clearCardView)
$state.go('app.addressbook');
$mdToast.show(
$mdToast.simple()
.content(success)
.position('top right')
.hideDelay(2000));
});
}
}
angular
@@ -110,7 +110,7 @@
return addressbook.id == $stateParams.addressbookId;
});
if (addressbook) {
addressbook.selectedCard = false;
delete addressbook.selectedCard;
addressbook.$reload();
return addressbook;
}