/* -*- Mode: js; indent-tabs-mode: nil; js-indent-level: 2; -*- */ (function() { 'use strict'; /** * @ngInject */ MailboxesController.$inject = ['$scope', '$rootScope', '$state', '$transitions', '$timeout', '$window', '$mdUtil', '$mdMedia', '$mdSidenav', '$mdDialog', '$mdToast', 'sgConstant', 'sgFocus', 'encodeUriFilter', 'Dialog', 'sgSettings', 'sgHotkeys', 'Account', 'Mailbox', 'VirtualMailbox', 'User', 'Preferences', 'stateAccounts', 'Message']; function MailboxesController($scope, $rootScope, $state, $transitions, $timeout, $window, $mdUtil, $mdMedia, $mdSidenav, $mdDialog, $mdToast, sgConstant, focus, encodeUriFilter, Dialog, Settings, sgHotkeys, Account, Mailbox, VirtualMailbox, User, Preferences, stateAccounts, Message) { var vm = this, account, mailbox, hotkeys = []; $scope.closeDialog = function () { $mdDialog.hide(); }; this.$onInit = function () { this.service = Mailbox; this.accounts = stateAccounts; this.message = Message; this.advancedSearchPanelVisible = false; // Advanced search options this.reset(); this.search = { subfolders: 1, match: 'AND', params: [] }; this.highlightWords = []; this.showSubscribedOnly = Preferences.defaults.SOGoMailShowSubscribedFoldersOnly; Account.refreshUnseenCount($window.unseenCountFolders); _registerHotkeys(hotkeys); $scope.$on('$destroy', function() { // Deregister hotkeys _.forEach(hotkeys, function(key) { sgHotkeys.deregisterHotkey(key); }); }); $rootScope.$on('showMailAdvancedSearchPanel', function () { vm.showAdvancedSearch(); }); $rootScope.$on('resetMailAdvancedSearchPanel', function () { vm.reset(); }); $rootScope.$on('showCleanMailboxPanel', function (e, d) { vm.showCleanMailboxPanel(d.folder, d.account); }); }; function _registerHotkeys(keys) { _.forEach(['backspace', 'delete'], function(hotkey) { keys.push(sgHotkeys.createHotkey({ key: hotkey, description: l('Delete selected message or folder'), callback: function() { if (Mailbox.selectedFolderController && Mailbox.selectedFolder && Mailbox.selectedFolder.$isEditable && !Mailbox.selectedFolder.hasSelectedMessage() && Mailbox.selectedFolder.$selectedCount() === 0) Mailbox.selectedFolderController.confirmDelete(Mailbox.selectedFolder); } })); keys.push(sgHotkeys.createHotkey({ key: 'shift+s', description: l('Advanced search'), callback: function () { vm.showAdvancedSearch(); } })); }); // Register the hotkeys _.forEach(keys, function(key) { sgHotkeys.registerHotkey(key); }); } this.hideAdvancedSearch = function(e) { vm.service.$virtualPath = false; vm.service.$virtualMode = false; account = vm.accounts[0]; mailbox = vm.searchPreviousMailbox; vm.search.params = []; vm.highlightWords = []; if (mailbox && mailbox.path) { // Reset mailbox.setHighlightWords([]); mailbox.$filter({ "sort": "date", "asc": false, "match": "OR" }).then(function () { $state.go('mail.account.mailbox', { accountId: account.id, mailboxId: encodeUriFilter(mailbox.path) }); vm.$onInit(); // Reinit search fields }); } e.stopPropagation(); }; this.addHighlightWords = function(sentence) { var words = sentence.split(" "); words.forEach(word => { var cleanedWord = word.trim().toLowerCase(); if (!this.highlightWords.includes(cleanedWord)) { this.highlightWords.push(cleanedWord); } }); }; this.reset = function() { this.highlightWords = []; this.searchForm = { from: '', to: '', contains: '', notContains: '', subject: '', body: '', date: 'anytime', dateStart: new Date(), dateEnd: new Date(), bcc: '', size: '', sizeOperator: '>', sizeUnit: 'mb', attachements: 0, favorite: 0, unseen: 0, tags: { searchText: '', selected: '' }, flags: [], }; } this.addSearchParameters = function() { this.search.params = []; this.highlightWords = []; // From if (this.searchForm.from && this.searchForm.from.length > 0) { this.search.params.push(this.newSearchParam('from', this.searchForm.from)); this.addHighlightWords(this.searchForm.from); } // To if (this.searchForm.to && this.searchForm.to.length > 0) { this.search.params.push(this.newSearchParam('to', this.searchForm.to)); } // Bcc if (this.searchForm.bcc && this.searchForm.bcc.length > 0) { this.search.params.push(this.newSearchParam('bcc', this.searchForm.bcc)); } // Contains if (this.searchForm.contains && this.searchForm.contains.length > 0) { this.search.params.push(this.newSearchParam('contains', this.searchForm.contains)); this.addHighlightWords(this.searchForm.contains); } // Does not contains if (this.searchForm.doesnotcontains && this.searchForm.doesnotcontains.length > 0) { this.search.params.push(this.newSearchParam('not_contains', this.searchForm.doesnotcontains)); } // Subject if (this.searchForm.subject && this.searchForm.subject.length > 0) { this.search.params.push(this.newSearchParam('subject', this.searchForm.subject)); this.addHighlightWords(this.searchForm.subject); } // Body if (this.searchForm.body && this.searchForm.body.length > 0) { this.search.params.push(this.newSearchParam('body', this.searchForm.body)); this.addHighlightWords(this.searchForm.body); } // Date if (this.searchForm.date && this.searchForm.date.length > 0) { var date = null; var dateTo = null; var today = new Date(); var tmp = new Date(today); switch (this.searchForm.date) { case 'anytime': break; case 'last7days': tmp.setDate(tmp.getDate() - 7); date = this.formatDate(tmp); this.search.params.push(this.newSearchParam('date', date, '>=')); break; case 'last30days': tmp.setDate(tmp.getDate() - 30); date = this.formatDate(tmp); this.search.params.push(this.newSearchParam('date', date, '>=')); break; case 'last6month': tmp.setMonth(tmp.getMonth() - 6); date = this.formatDate(tmp); this.search.params.push(this.newSearchParam('date', date, '>=')); break; case 'before': date = this.formatDate(this.searchForm.dateStart); this.search.params.push(this.newSearchParam('date', date, '<')); break; case 'after': date = this.formatDate(this.searchForm.dateStart); this.search.params.push(this.newSearchParam('date', date, '>=')); break; case 'between': date = this.formatDate(this.searchForm.dateStart); dateTo = this.formatDate(this.searchForm.dateEnd); this.search.params.push(this.newSearchDateBetweenParam(date, dateTo)); break; } } // Size if (this.searchForm.size && this.searchForm.size > 0) { this.search.params.push(this.newSearchParam('size', this.searchForm.size.toString(), this.searchForm.sizeOperator)); } // Attachment if (this.searchForm.attachements) { this.search.params.push(this.newSearchParam('attachment', '1', '=')); } // Favorite if (this.searchForm.favorite) { this.search.params.push(this.newSearchParam('favorite', '1', '=')); } // Unseen if (this.searchForm.unseen) { this.search.params.push(this.newSearchParam('unseen', '1', '=')); } // Flags if (this.searchForm.flags && this.searchForm.flags.length > 0) { this.search.params.push(this.newSearchFlagsParam()); } this.toggleAdvancedSearch(); } this.searchFieldChange = function (event) { if (13 == event.keyCode) { this.addSearchParameters(); $mdDialog.hide(); vm.advancedSearchPanelVisible = false; } }; this.toggleAdvancedSearch = function() { if (Mailbox.selectedFolder.$isLoading) { // Stop search vm.virtualMailbox.stopSearch(); } else { // Start search var root, mailboxes = [], _visit = function(folders) { _.forEach(folders, function(o) { if (!o.isNoSelect()) mailboxes.push(o); if (o.children && o.children.length > 0) { _visit(o.children); } }); }; vm.virtualMailbox = new VirtualMailbox(vm.accounts[0]); // Don't set the previous selected mailbox if we're in virtual mode // That allows users to do multiple advanced search but return // correctly to the previously selected mailbox once done. if (!Mailbox.$virtualMode) vm.searchPreviousMailbox = Mailbox.selectedFolder; Mailbox.selectedFolder = vm.virtualMailbox; Mailbox.$virtualMode = true; if (Mailbox.$virtualPath.length) { root = vm.accounts[0].$getMailboxByPath(Mailbox.$virtualPath); root.setHighlightWords(vm.highlightWords); mailboxes.push(root); if (vm.search.subfolders && root.children.length) _visit(root.children); } else { mailboxes = _.filter(vm.accounts[0].$flattenMailboxes({ all: true }), function(mailbox) { return !mailbox.isNoSelect(); }); } mailboxes.forEach((mailbox) => { mailbox }); vm.virtualMailbox.setMailboxes(mailboxes); vm.virtualMailbox.startSearch(vm.search.match, vm.search.params); if ($state.$current.name != 'mail.account.virtualMailbox') $state.go('mail.account.virtualMailbox', { accountId: vm.accounts[0].id }); } }; this.formatDate = function(date) { var year = date.getFullYear(); var month = (date.getMonth() + 1).toString().padStart(2, '0'); var day = date.getDate().toString().padStart(2, '0'); return year + '-' + month + '-' + day; }; this.changeDate = function() { if ('between' == this.searchForm.date) { if (this.searchForm.dateStart > this.searchForm.dateEnd) { this.searchForm.dateEnd = this.searchForm.dateStart; } } }; this.newSearchParam = function (searchParam, pattern, operator = '>') { if (pattern.length && searchParam.length) { var n = 0; if (pattern.startsWith("!")) { n = 1; pattern = pattern.substring(1).trim(); } switch (searchParam) { case 'size': return { searchBy: searchParam, searchInput: pattern, negative: n, operator: operator, sizeUnit: this.searchForm.sizeUnit }; case 'date': return { searchBy: searchParam, searchInput: pattern, negative: n, operator: operator }; default: return { searchBy: searchParam, searchInput: pattern, negative: n }; } } }; this.newSearchDateBetweenParam = function (dateFrom, dateTo) { return { searchBy: 'date_between', searchInput: "*", dateFrom: dateFrom, dateTo: dateTo, negative: 0 }; }; this.newSearchFlagsParam = function () { return { searchBy: 'flags', searchInput: "*", flags: vm.searchForm.flags, negative: 0 }; }; this.toggleAccountState = function (account) { account.$expanded = !account.$expanded; if (!this.debounceSaveState) { this.debounceSaveState = $mdUtil.debounce(function () { account.$flattenMailboxes({ reload: true, saveState: true }); }, 1000); } this.debounceSaveState(); }; this.subscribe = function(account) { $mdDialog.show({ templateUrl: account.id + '/subscribe', controller: SubscriptionsDialogController, controllerAs: 'subscriptions', clickOutsideToClose: true, escapeToClose: true, locals: { srcAccount: account } }).finally(function() { account.$getMailboxes({reload: true}); }); /** * @ngInject */ SubscriptionsDialogController.$inject = ['$scope', '$mdDialog', 'srcAccount']; function SubscriptionsDialogController($scope, $mdDialog, srcAccount) { var vm = this; vm.loading = true; vm.filter = { name: '' }; vm.account = new Account({ id: srcAccount.id, name: srcAccount.name }); vm.close = close; vm.account.$getMailboxes({ reload: true, all: true }).then(function() { vm.loading = false; }); function close() { $mdDialog.hide(); } } }; this.showAdvancedSearch = function() { if (!vm.advancedSearchPanelVisible) { vm.advancedSearchPanelVisible = true; if (Mailbox.selectedFolder.path) Mailbox.$virtualPath = Mailbox.selectedFolder.path; // Close sidenav on small devices if (!$mdMedia(sgConstant['gt-md'])) $mdSidenav('left').close(); $mdDialog.show({ template: document.getElementById('advancedSearch').innerHTML, parent: angular.element(document.body), controller: function () { var dialogCtrl = this; this.$onInit = function () { // Pass main controller this.mainController = vm; this.mailbox = Mailbox; this.message = Message; }; dialogCtrl.closeDialog = function () { $mdDialog.hide(); vm.advancedSearchPanelVisible = false; }; dialogCtrl.search = function () { this.mainController.addSearchParameters(); $mdDialog.hide(); vm.advancedSearchPanelVisible = false; }; }, controllerAs: 'dialogCtrl', clickOutsideToClose: false, escapeToClose: false, }); } }; this.newFolder = function(parentFolder) { Dialog.prompt(l('New Folder...'), l('Enter the new name of your folder')) .then(function(name) { parentFolder.$newMailbox(parentFolder.id, name) .then(function() { // success }, function(data, status) { Dialog.alert(l('An error occured while creating the mailbox "%{0}".', name), l(data.error)); }); }); }; this.showCleanMailboxPanel = function (folder, account) { // Close sidenav on small devices if (!$mdMedia(sgConstant['gt-md'])) $mdSidenav('left').close(); $mdDialog.show({ template: document.getElementById('cleanMailbox').innerHTML, parent: angular.element(document.body), controller: function () { var dialogCtrl = this; this.$onInit = function () { this.mainController = vm; this.folder = folder; this.isMailbox = (folder ? false : true); this.name = folder ? folder.$displayName : account.name; this.loading = false; this.date = null; this.form = { filterDuration: "3m", permanentlyDelete: false, confirmDelete: false, filterDurationDate: null }; var today = new Date(); var maxDate = new Date(today); maxDate.setMonth(today.getMonth() - 3); this.maxDate = maxDate; }; dialogCtrl.closeDialog = function () { $mdDialog.hide(); }; dialogCtrl.isLoading = function () { return this.loading; } dialogCtrl.isWarningDisplayed = function () { return (this.form && this.form.permanentlyDelete); } dialogCtrl.isApplyDisabled = function () { return !(!this.loading && (!this.form.permanentlyDelete || (this.form.permanentlyDelete && this.form.confirmDelete)) && (this.form.filterDuration != 'custom' || (this.form.filterDuration == 'custom' && this.form.filterDurationDate)) ); } dialogCtrl.apply = function () { var folders = []; var i; if (account) { for (i = 0; i < account.$mailboxes.length ; i++) { folders.push(account.$mailboxes[i].id); } this.folder = account.$mailboxes[0]; } var date = ''; var durationMonth = 12; var date = new Date(); switch (this.form.filterDuration) { case '3m': durationMonth = 3; date.setMonth(date.getMonth() - durationMonth); break; case '6m': durationMonth = 6; date.setMonth(date.getMonth() - durationMonth); break; case '9m': durationMonth = 9; date.setMonth(date.getMonth() - durationMonth); break; case '1y': durationMonth = 12; date.setMonth(date.getMonth() - durationMonth); break; case 'custom': date = this.form.filterDurationDate; break; } var year = date.getFullYear(); var month = String(date.getMonth() + 1).padStart(2, '0'); var day = String(date.getDate()).padStart(2, '0'); this.date = `${year}-${month}-${day}`; this.folder.cleanMailbox({ 'applyToSubfolders': (this.form && this.form.applyToSubfolders) ? this.form.applyToSubfolders : false, 'permanentlyDelete': (this.form && this.form.permanentlyDelete) ? this.form.permanentlyDelete : false, 'date': this.date, 'folders': folders }).then(function (data) { dialogCtrl.loading = true; Mailbox.selectedFolder.$filter({ "sort": "date", "asc": false, "match": "OR" }).then(function () { $state.go('mail.account.mailbox', { accountId: vm.accounts[0].id, mailboxId: encodeUriFilter(Mailbox.selectedFolder.path) }); dialogCtrl.loading = false; $mdDialog.hide(); $mdToast.show( $mdToast.simple() .textContent(l('%{0} message(s) deleted', data.nbMessageDeleted)) .position(sgConstant.toastPosition) .hideDelay(2000)); }); }).catch(function () { dialogCtrl.loading = false; $mdDialog.hide(); }); }; }, controllerAs: 'dialogCtrl', clickOutsideToClose: false, escapeToClose: false, }); }; this.delegate = function(account) { $mdDialog.show({ templateUrl: account.id + '/delegation', // UI/Templates/MailerUI/UIxMailUserDelegation.wox controller: MailboxDelegationController, controllerAs: 'delegate', clickOutsideToClose: true, escapeToClose: true, locals: { User: User, account: account } }); /** * @ngInject */ MailboxDelegationController.$inject = ['$scope', '$mdDialog', 'User', 'account']; function MailboxDelegationController($scope, $mdDialog, User, account) { var vm = this; vm.users = account.delegates; vm.account = account; vm.userToAdd = ''; vm.searchText = ''; vm.userFilter = userFilter; vm.closeModal = closeModal; vm.removeUser = removeUser; vm.addUser = addUser; function userFilter($query) { return User.$filter($query, account.delegates); } function closeModal() { $mdDialog.hide(); } function removeUser(user) { account.$removeDelegate(user.uid).catch(function(data, status) { Dialog.alert(l('Warning'), l('An error occured, please try again.')); }); } function addUser(data) { if (data) { account.$addDelegate(data).then(function() { vm.userToAdd = ''; vm.searchText = ''; }, function(error) { Dialog.alert(l('Warning'), error); }); } } } }; // delegate this.isDroppableFolder = function(srcFolder, dstFolder) { return (dstFolder.id != srcFolder.id) && dstFolder.isWritable(); }; this.dragSelectedMessages = function(srcFolder, dstFolder, mode) { var dstId, messages, uids, clearMessageView, promise, success; dstId = '/' + dstFolder.id; messages = srcFolder.selectedMessages(); if (messages.length === 0) messages = [srcFolder.selectedMessage()]; uids = _.map(messages, 'uid'); clearMessageView = (srcFolder.$selectedMessage && uids.indexOf(srcFolder.$selectedMessage) >= 0); if (mode == 'copy') { promise = srcFolder.$copyMessages(messages, dstId); success = l('%{0} message(s) copied', messages.length); } else { promise = srcFolder.$moveMessages(messages, dstId); success = l('%{0} message(s) moved', messages.length); } promise.then(function() { if (clearMessageView) $state.go('mail.account.mailbox'); $mdToast.show( $mdToast.simple() .textContent(success) .position(sgConstant.toastPosition) .hideDelay(2000)); }); }; } angular .module('SOGo.MailerUI') .controller('MailboxesController', MailboxesController); })();