/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* JavaScript for SOGoPreferences */ (function() { 'use strict'; /** * @ngInject */ PreferencesController.$inject = ['$q', '$window', '$state', '$mdConstant', '$mdMedia', '$mdSidenav', '$mdDialog', '$mdToast', 'sgSettings', 'sgFocus', 'Dialog', 'User', 'Account', 'Preferences', 'Authentication']; function PreferencesController($q, $window, $state, $mdConstant, $mdMedia, $mdSidenav, $mdDialog, $mdToast, sgSettings, focus, Dialog, User, Account, Preferences, Authentication) { var vm = this, mailboxes = [], today = new Date().beginOfDay(); this.$onInit = function() { this.preferences = Preferences; this.passwords = { newPassword: null, newPasswordConfirmation: null, oldPassword: null }; this.timeZonesList = $window.timeZonesList; this.timeZonesSearchText = ''; this.sieveVariablesCapability = ($window.sieveCapabilities.indexOf('variables') >= 0); this.addressesSearchText = ''; this.mailLabelKeyRE = new RegExp(/^(?!^_\$)[^(){} %*\"\\\\]*?$/); this.emailSeparatorKeys = [ $mdConstant.KEY_CODE.ENTER, $mdConstant.KEY_CODE.TAB, $mdConstant.KEY_CODE.COMMA, $mdConstant.KEY_CODE.SEMICOLON ]; // Set alternate avatar in User service if (Preferences.defaults.SOGoAlternateAvatar) User.$alternateAvatar = Preferences.defaults.SOGoAlternateAvatar; this.preferences.hasActiveExternalSieveScripts(); this.updateVacationDates(); }; this.go = function(module, form) { if (form.$valid) { // Close sidenav on small devices if (!$mdMedia('gt-md')) $mdSidenav('left').close(); $state.go('preferences.' + module); } }; this.onLanguageChange = function(form) { if (form.$valid) Dialog.confirm(l('Warning'), l('Save preferences and reload page now?'), {ok: l('Yes'), cancel: l('No')}) .then(function() { vm.save(form, { quick: true }).then(function() { $window.location.reload(true); }); }); }; this.onDesktopNotificationsChange = function() { if (this.preferences.defaults.SOGoDesktopNotifications) this.preferences.authorizeNotifications(); }; this.resetContactsCategories = function(form) { this.preferences.defaults.SOGoContactsCategories = $window.defaultContactsCategories; form.$setDirty(); }; this.resetCalendarCategories = function(form) { this.preferences.defaults.SOGoCalendarCategories = _.keys($window.defaultCalendarCategories); this.preferences.defaults.SOGoCalendarCategoriesColorsValues = _.values($window.defaultCalendarCategories); form.$setDirty(); }; this.addCalendarCategory = function(form) { var i = _.indexOf(this.preferences.defaults.SOGoCalendarCategories, l('New category')); if (i < 0) { this.preferences.defaults.SOGoCalendarCategories.push(l('New category')); this.preferences.defaults.SOGoCalendarCategoriesColorsValues.push("#aaa"); form.$setDirty(); i = this.preferences.defaults.SOGoCalendarCategories.length - 1; } focus('calendarCategory_' + i); }; this.resetCalendarCategoryValidity = function(index, form) { form['calendarCategory_' + index].$setValidity('duplicate', true); }; this.removeCalendarCategory = function(index, form) { this.preferences.defaults.SOGoCalendarCategories.splice(index, 1); this.preferences.defaults.SOGoCalendarCategoriesColorsValues.splice(index, 1); form.$setDirty(); }; this.addContactCategory = function(form) { var i = _.indexOf(this.preferences.defaults.SOGoContactsCategories, ""); if (i < 0) { this.preferences.defaults.SOGoContactsCategories.push(""); i = this.preferences.defaults.SOGoContactsCategories.length - 1; } focus('contactCategory_' + i); form.$setDirty(); }; this.removeContactCategory = function(index, form) { this.preferences.defaults.SOGoContactsCategories.splice(index, 1); form.$setDirty(); }; this.addMailAccount = function(ev, form) { var account, index; index = this.preferences.defaults.AuxiliaryMailAccounts.length; account = new Account({ id: index, isNew: true, name: "", identities: [ { fullName: "", email: "" } ], receipts: { receiptAction: "ignore", receiptNonRecipientAction: "ignore", receiptOutsideDomainAction: "ignore", receiptAnyAction: "ignore" } }); $mdDialog.show({ controller: 'AccountDialogController', controllerAs: '$AccountDialogController', templateUrl: 'editAccount?account=new', targetEvent: ev, locals: { defaults: this.preferences.defaults, account: account, accountId: index, mailCustomFromEnabled: $window.mailCustomFromEnabled } }).then(function() { // Automatically expand the new mail account if (!angular.isArray(vm.preferences.settings.Mail.ExpandedFolders)) { vm.preferences.settings.Mail.ExpandedFolders = ['/0']; } vm.preferences.settings.Mail.ExpandedFolders.push('/' + index); vm.preferences.defaults.AuxiliaryMailAccounts.push(account.$omit()); form.$setDirty(); }); }; this.editMailAccount = function(event, index, form) { var data, account; data = _.assign({ id: index }, _.cloneDeep(this.preferences.defaults.AuxiliaryMailAccounts[index])); account = new Account(data); $mdDialog.show({ controller: 'AccountDialogController', controllerAs: '$AccountDialogController', templateUrl: 'editAccount?account=' + index, targetEvent: event, locals: { defaults: this.preferences.defaults, account: account, accountId: index, mailCustomFromEnabled: $window.mailCustomFromEnabled } }).then(function() { vm.preferences.defaults.AuxiliaryMailAccounts[index] = account.$omit(); form.$setDirty(); }).catch(_.noop); // Cancel }; this.removeMailAccount = function(index, form) { this.preferences.defaults.AuxiliaryMailAccounts.splice(index, 1); form.$setDirty(); }; this.resetMailLabelValidity = function(index, form) { form['mailIMAPLabel_' + index].$setValidity('duplicate', true); }; this.addMailLabel = function(form) { // See $omit() in the Preferences services for real key generation var key = '_$$' + guid(); this.preferences.defaults.SOGoMailLabelsColorsKeys.push("label"); this.preferences.defaults.SOGoMailLabelsColorsValues.push(["New label", "#aaa"]); focus('mailLabel_' + (_.size(this.preferences.defaults.SOGoMailLabelsColorsKeys) - 1)); form.$setDirty(); }; this.removeMailLabel = function(index, form) { this.preferences.defaults.SOGoMailLabelsColorsKeys.splice(index, 1); this.preferences.defaults.SOGoMailLabelsColorsValues.splice(index, 1); form.$setDirty(); }; function _loadAllMailboxes() { var account; if (mailboxes.length) { return; } if (sgSettings.activeUser('path').mail) { // Fetch a flatten version of the mailboxes list of the main account (0) // This list will be forwarded to the Sieve filter controller account = new Account({ id: 0 }); account.$getMailboxes().then(function() { var allMailboxes = account.$flattenMailboxes({all: true}), index = -1, length = allMailboxes.length; while (++index < length) { mailboxes.push(allMailboxes[index]); } }); } } this.addMailFilter = function(ev, form) { var filter = { match: 'all', active: 1 }; _loadAllMailboxes(); $mdDialog.show({ templateUrl: 'editFilter?filter=new', controller: 'FiltersDialogController', controllerAs: 'filterEditor', targetEvent: ev, locals: { filter: filter, mailboxes: mailboxes, labels: this.preferences.defaults.SOGoMailLabelsColors, validateForwardAddress: validateForwardAddress } }).then(function() { if (!vm.preferences.defaults.SOGoSieveFilters) vm.preferences.defaults.SOGoSieveFilters = []; vm.preferences.defaults.SOGoSieveFilters.push(filter); form.$setDirty(); }); }; this.editMailFilter = function(ev, index, form) { var filter = angular.copy(this.preferences.defaults.SOGoSieveFilters[index]); _loadAllMailboxes(); $mdDialog.show({ templateUrl: 'editFilter?filter=' + index, controller: 'FiltersDialogController', controllerAs: 'filterEditor', targetEvent: null, locals: { filter: filter, mailboxes: mailboxes, labels: this.preferences.defaults.SOGoMailLabelsColors, validateForwardAddress: validateForwardAddress } }).then(function() { vm.preferences.defaults.SOGoSieveFilters[index] = filter; form.$setDirty(); }, _.noop); // Cancel }; this.removeMailFilter = function(index, form) { this.preferences.defaults.SOGoSieveFilters.splice(index, 1); form.$setDirty(); }; this.onFiltersOrderChanged = function(form) { // Return a callback that will affect the form if (!this._onFiltersOrderChanged) { this._onFiltersOrderChanged = function(type) { form.$setDirty(); }; } return this._onFiltersOrderChanged; }; this.filterEmailAddresses = function ($query) { return _.filter( _.difference($window.defaultEmailAddresses, this.preferences.defaults.Vacation.autoReplyEmailAddresses), function (address) { return address.toLowerCase().indexOf($query.toLowerCase()) >= 0; } ); }; this.addDefaultEmailAddresses = function(form) { var v = []; if (angular.isDefined(this.preferences.defaults.Vacation.autoReplyEmailAddresses)) { v = this.preferences.defaults.Vacation.autoReplyEmailAddresses; } this.preferences.defaults.Vacation.autoReplyEmailAddresses = _.union($window.defaultEmailAddresses, v); form.$setDirty(); }; this.userFilter = function(search, excludedUsers) { if (!search || search.length < sgSettings.minimumSearchLength()) return []; return User.$filter(search, excludedUsers).then(function(users) { // Set users avatars _.forEach(users, function(user) { if (!user.$$image) { if (user.image) user.$$image = user.image; else user.$$image = vm.preferences.avatar(user.c_email, 40, {no_404: true}); } }); return users; }); }; this.manageSieveScript = function(form) { this.preferences.hasActiveExternalSieveScripts(false); form.$setDirty(); }; this.confirmChanges = function($event, form) { var target; if (form.$dirty && form.$valid) { // Stop default action $event.preventDefault(); $event.stopPropagation(); // Find target link target = $event.target; while (target.tagName != 'A') target = target.parentNode; Dialog.confirm(l('Unsaved Changes'), l('Do you want to save your changes made to the configuration?'), { ok: l('Save'), cancel: l('Don\'t Save') }) .then(function() { // Save & follow link vm.save(form, { quick: true }).then(function() { $window.location = target.href; }); }, function() { // Don't save & follow link $window.location = target.href; }); } }; function validateForwardAddress(address) { var defaultAddresses, domains, domain; domains = []; if ($window.forwardConstraints > 0) { // We first extract the list of 'known domains' to SOGo defaultAddresses = $window.defaultEmailAddresses; _.forEach(defaultAddresses, function(adr) { var domain = adr.split("@")[1]; if (domain) { domains.push(domain.toLowerCase()); } }); // We check if we're allowed or not to forward based on the domain defaults domain = address.split("@")[1].toLowerCase(); if (domains.indexOf(domain) < 0 && $window.forwardConstraints == 1) { throw new Error(l("You are not allowed to forward your messages to an external email address.")); } else if (domains.indexOf(domain) >= 0 && $window.forwardConstraints == 2) { throw new Error(l("You are not allowed to forward your messages to an internal email address.")); } else if ($window.forwardConstraints == 2 && $window.forwardConstraintsDomains.length > 0 && $window.forwardConstraintsDomains.indexOf(domain) < 0) { throw new Error(l("You are not allowed to forward your messages to this domain:") + " " + domain); } } return true; } this.save = function(form, options) { var i, sendForm, addresses; sendForm = true; // We do some sanity checks // We check if we're allowed or not to forward based on the domain defaults if (this.preferences.defaults.Forward && this.preferences.defaults.Forward.enabled && this.preferences.defaults.Forward.forwardAddress) { addresses = this.preferences.defaults.Forward.forwardAddress; try { for (i = 0; i < addresses.length; i++) { validateForwardAddress(addresses[i]); } } catch (err) { Dialog.alert(l('Error'), err); sendForm = false; } } // IMAP labels must be unique if (this.preferences.defaults.SOGoMailLabelsColorsKeys.length != this.preferences.defaults.SOGoMailLabelsColorsValues.length || this.preferences.defaults.SOGoMailLabelsColorsKeys.length != _.uniq(this.preferences.defaults.SOGoMailLabelsColorsKeys).length) { Dialog.alert(l('Error'), l("IMAP labels must have unique names.")); _.forEach(this.preferences.defaults.SOGoMailLabelsColorsKeys, function (value, i, keys) { if (form['mailIMAPLabel_' + i].$dirty && (keys.indexOf(value) != i || keys.indexOf(value, i+1) > -1)) { form['mailIMAPLabel_' + i].$setValidity('duplicate', false); sendForm = false; } }); } // Calendar categories must be unique if (this.preferences.defaults.SOGoCalendarCategories.length != _.uniq(this.preferences.defaults.SOGoCalendarCategories).length) { Dialog.alert(l('Error'), l("Calendar categories must have unique names.")); _.forEach(this.preferences.defaults.SOGoCalendarCategories, function (value, i, keys) { if (form['calendarCategory_' + i].$dirty && (keys.indexOf(value) != i || keys.indexOf(value, i+1) > -1)) { form['calendarCategory_' + i].$setValidity('duplicate', false); sendForm = false; } }); } // Contact categories must be unique if (this.preferences.defaults.SOGoContactsCategories.length != _.uniq(this.preferences.defaults.SOGoContactsCategories).length) { Dialog.alert(l('Error'), l("Contact categories must have unique names.")); _.forEach(this.preferences.defaults.SOGoContactsCategories, function (value, i, keys) { if (form['contactCategory_' + i].$dirty && (keys.indexOf(value) != i || keys.indexOf(value, i+1) > -1)) { form['contactCategory_' + i].$setValidity('duplicate', false); sendForm = false; } }); } if (sendForm) return this.preferences.$save().then(function(data) { if (!options || !options.quick) { $mdToast.show( $mdToast.simple() .textContent(l('Preferences saved')) .position('bottom right') .hideDelay(2000)); form.$setPristine(); } }); return $q.reject('Invalid form'); }; this.canChangePassword = function(form) { if (this.passwords.newPasswordConfirmation && this.passwords.newPasswordConfirmation.length && this.passwords.newPassword != this.passwords.newPasswordConfirmation) { form.newPasswordConfirmation.$setValidity('newPasswordMismatch', false); return false; } else { form.newPasswordConfirmation.$setValidity('newPasswordMismatch', true); } if (this.passwords.newPassword && this.passwords.newPassword.length > 0 && this.passwords.newPasswordConfirmation && this.passwords.newPasswordConfirmation.length && this.passwords.newPassword == this.passwords.newPasswordConfirmation && this.passwords.oldPassword && this.passwords.oldPassword.length > 0) return true; return false; }; this.changePassword = function() { Authentication.changePassword(null, null, this.passwords.newPassword, this.passwords.oldPassword).then(function() { var alert = $mdDialog.alert({ title: l('Password'), textContent: l('The password was changed successfully.'), ok: l('OK') }); $mdDialog.show( alert ) .finally(function() { alert = undefined; }); }, function(msg) { var alert = $mdDialog.alert({ title: l('Password'), textContent: msg, ok: l('OK') }); $mdDialog.show( alert ) .finally(function() { alert = undefined; }); }); }; this.timeZonesListFilter = function(filter) { return _.filter(this.timeZonesList, function(value) { return value.toUpperCase().indexOf(filter.toUpperCase()) >= 0; }); }; this.updateVacationDates = function() { var d = this.preferences.defaults; if (d && d.Vacation && d.Vacation.enabled) { this.toggleVacationStartDate(); this.toggleVacationEndDate(); } }; this.toggleVacationStartDate = function() { var v; v = this.preferences.defaults.Vacation; if (v.startDateEnabled) { // Enabling the start date if (!v.startDate) { v.startDate = new Date(); } if (v.endDateEnabled && v.endDate && v.startDate.getTime() > v.endDate.getTime()) { v.startDate = new Date(v.endDate.getTime()); v.startDate.addDays(-1); } } }; this.toggleVacationEndDate = function() { var v; v = this.preferences.defaults.Vacation; if (v.endDateEnabled) { // Enabling the end date if (!v.endDate) { v.endDate = new Date(); } if (v.startDateEnabled && v.startDate && v.endDate.getTime() < v.startDate.getTime()) { v.endDate = new Date(v.startDate.getTime()); v.endDate.addDays(1); } } }; this.validateVacationStartDate = function(date) { var d = vm.preferences.defaults, r = true; if (d && d.Vacation && d.Vacation.enabled) { if (d.Vacation.startDateEnabled) { r = (!d.Vacation.endDateEnabled || !d.Vacation.endDate || date.getTime() <= d.Vacation.endDate.getTime()); } } return r; }; this.validateVacationEndDate = function(date) { var d = vm.preferences.defaults, r = true; if (d && d.Vacation && d.Vacation.enabled) { if (d.Vacation.endDateEnabled) { r = (!d.Vacation.startDateEnabled || !d.Vacation.startDate || date.getTime() >= d.Vacation.startDate.getTime()); } } return r; }; } angular .module('SOGo.PreferencesUI') .controller('PreferencesController', PreferencesController); })();