From 984677796c12e3c17a1e6a87aaa670eb3c920456 Mon Sep 17 00:00:00 2001 From: InverseBot Date: Sun, 16 Oct 2016 01:57:59 -0400 Subject: [PATCH] (js/css) Update generated files --- UI/WebServerResources/js/Contacts.js | 2 +- UI/WebServerResources/js/Contacts.js.map | 2 +- UI/WebServerResources/js/Preferences.js | 2 +- UI/WebServerResources/js/Preferences.js.map | 2 +- UI/WebServerResources/js/vendor/ng-sortable.min.js | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/UI/WebServerResources/js/Contacts.js b/UI/WebServerResources/js/Contacts.js index e61e30301..02e01a56f 100644 --- a/UI/WebServerResources/js/Contacts.js +++ b/UI/WebServerResources/js/Contacts.js @@ -1,2 +1,2 @@ -!function(){"use strict";function a(a,h){a.state("app",{url:"/addressbooks",abstract:!0,views:{addressbooks:{templateUrl:"UIxContactFoldersView",controller:"AddressBooksController",controllerAs:"app"}},resolve:{stateAddressbooks:b}}).state("app.addressbook",{url:"/:addressbookId",views:{addressbook:{templateUrl:"addressbook",controller:"AddressBookController",controllerAs:"addressbook"}},resolve:{stateAddressbook:c}}).state("app.addressbook.new",{url:"/{contactType:(?:card|list)}/new",views:{card:{templateUrl:"UIxContactEditorTemplate",controller:"CardController",controllerAs:"editor"}},resolve:{stateCard:d}}).state("app.addressbook.card",{url:"/:cardId",abstract:!0,views:{card:{template:""}},resolve:{stateCard:e},onEnter:f,onExit:g}).state("app.addressbook.card.view",{url:"/view",views:{"card@app.addressbook":{templateUrl:"UIxContactViewTemplate",controller:"CardController",controllerAs:"editor"}}}).state("app.addressbook.card.editor",{url:"/edit",views:{"card@app.addressbook":{templateUrl:"UIxContactEditorTemplate",controller:"CardController",controllerAs:"editor"}}}),h.otherwise("/addressbooks/personal")}function b(a){return a.$findAll(window.contactFolders)}function c(a,b,c,d){var e=_.find(d.$findAll(),function(a){return a.id==c.addressbookId});return e?(delete e.selectedCard,e.$reload(),e):a.reject("Addressbook "+c.addressbookId+" not found")}function d(a,b,c){var d="v"+a.contactType,e=new c({pid:a.addressbookId,c_component:d});return b.selectedCard=!0,e}function e(a,b,c){var d;return(d=_.find(c.$cards,function(a){return a.id==b.cardId}))?d.$reload():void a.go("app.addressbook")}function f(a,b){b.selectedCard=a.cardId}function g(a){delete c.selectedCard}function h(a,b,c){a.$on("$stateChangeError",function(a,d,e,f,g,h){b.error(h),c.go("app.addressbook",{addressbookId:"personal"})}),a.$on("$routeChangeError",function(a,c,d,e){b.error(a,c,d,e)})}angular.module("SOGo.ContactsUI",["ngCookies","ui.router","angularFileUpload","ck","SOGo.Common","SOGo.PreferencesUI","SOGo.MailerUI"]).config(a).run(h),a.$inject=["$stateProvider","$urlRouterProvider"],b.$inject=["AddressBook"],c.$inject=["$q","$state","$stateParams","AddressBook"],d.$inject=["$stateParams","stateAddressbook","Card"],e.$inject=["$state","$stateParams","stateAddressbook"],f.$inject=["$stateParams","stateAddressbook"],g.$inject=["stateAddressbook"],h.$inject=["$rootScope","$log","$state"]}(),function(){"use strict";function a(a,b,c,d,e,f,g,h,i,j,k,m,n,o,p,q){function r(a){a.push(o.createHotkey({key:l("hotkey_search"),description:l("Search"),callback:H})),a.push(o.createHotkey({key:l("key_create_card"),description:l("Create a new address book card"),callback:angular.bind(M,u,"card")})),a.push(o.createHotkey({key:l("key_create_list"),description:l("Create a new list"),callback:angular.bind(M,u,"list")})),a.push(o.createHotkey({key:"space",description:l("Toggle item"),callback:t})),a.push(o.createHotkey({key:"up",description:l("View next item"),callback:w})),a.push(o.createHotkey({key:"down",description:l("View previous item"),callback:x})),a.push(o.createHotkey({key:"shift+up",description:l("Add next item to selection"),callback:y})),a.push(o.createHotkey({key:"shift+down",description:l("Add previous item to selection"),callback:z})),a.push(o.createHotkey({key:"backspace",description:l("Delete selected card or address book"),callback:A})),_.forEach(a,function(a){o.registerHotkey(a)})}function s(a){d.go("app.addressbook.card.view",{cardId:a.id})}function t(a,b){b||(b=M.selectedFolder.$selectedCard()),b.selected=!b.selected,M.mode.multiple+=b.selected?1:-1,a.preventDefault(),a.stopPropagation()}function u(a){d.go("app.addressbook.new",{contactType:a})}function v(){_.forEach(M.selectedFolder.$cards,function(a){a.selected=!1}),M.mode.multiple=0}function w(a){var b=M.selectedFolder.$selectedCardIndex();return angular.isDefined(b)?(b--,M.selectedFolder.$topIndex>0&&M.selectedFolder.$topIndex--):(b=M.selectedFolder.$cards.length()-1,M.selectedFolder.$topIndex=M.selectedFolder.getLength()),b>-1&&s(M.selectedFolder.$cards[b]),a.preventDefault(),b}function x(a){var b=M.selectedFolder.$selectedCardIndex();return angular.isDefined(b)?(b++,M.selectedFolder.$topIndex=0&&t(a,M.selectedFolder.$cards[b]))}function z(a){var b;M.selectedFolder.hasSelectedCard()&&(b=x(a),b>=0&&t(a,M.selectedFolder.$cards[b]))}function A(a){var b=M.selectedFolder.$selectedCards();_.size(b)>0&&m.confirm(l("Warning"),l("Are you sure you want to delete the selected contacts?"),{ok:l("Delete")}).then(function(){M.selectedFolder.$deleteCards(b).then(function(){M.mode.multiple=0,M.selectedFolder.selectedCard||d.go("app.addressbook")})}),a.preventDefault()}function B(a,b){var c,e,f,h,i,j,k;c=M.selectedFolder,i=!1,e=c.$selectedCards(),f=_.filter(e,function(a){return a.$isCard()}),f.length!=e.length&&g.show(g.simple().content(l("Lists can't be moved or copied.")).position("top right").hideDelay(2e3)),f.length&&("copy"==a?(j=c.$copyCards(f,b),k=l("%{0} card(s) copied",f.length)):(j=c.$moveCards(f,b),k=l("%{0} card(s) moved",f.length),h=_.map(f,"id"),i=c.selectedCard&&h.indexOf(c.selectedCard)>=0),j.then(function(){i&&d.go("app.addressbook"),g.show(g.simple().content(k).position("top right").hideDelay(2e3))}))}function C(a){B("copy",a)}function D(a){B("move",a)}function E(){_.forEach(M.selectedFolder.$cards,function(a){a.selected=!0}),M.mode.multiple=M.selectedFolder.$cards.length}function F(a){M.selectedFolder.$filter("",{sort:a})}function G(a){return j.$query.sort==a}function H(){M.mode.search=!0,k("search")}function I(){M.mode.search=!1,M.selectedFolder.$filter("")}function J(a,b){h.$findAll().then(function(c){var d=_.find(c,function(a){if(0===a.id)return a});d.$getMailboxes().then(function(c){d.$newMessage().then(function(c){angular.extend(c.editable,{to:b}),f.show({parent:angular.element(document.body),targetEvent:a,clickOutsideToClose:!1,escapeToClose:!1,templateUrl:"../Mail/UIxMailEditor",controller:"MessageEditorController",controllerAs:"editor",locals:{stateAccount:d,stateMessage:c}})})})})}function K(a,b,c){var d=[c+" <"+b+">"];M.newMessage(a,d),a.stopPropagation(),a.preventDefault()}function L(a){var c=_.filter(M.selectedFolder.$cards,function(a){return a.selected}),d=[],e=[];_.forEach(c,function(a){a.$isList({expandable:!0})?angular.isDefined(a.refs)&&a.refs.length?_.forEach(a.refs,function(a){a.email.length&&e.push(a.$shortFormat())}):d.push(a.$reload().then(function(a){_.forEach(a.refs,function(a){a.email.length&&e.push(a.$shortFormat())})})):a.c_mail.length&&e.push(a.$shortFormat())}),b.all(d).then(function(){e=_.uniq(e),e.length&&M.newMessage(a,e)})}var M=this,N=[];j.selectedFolder=q,M.service=j,M.selectedFolder=q,M.selectCard=s,M.toggleCardSelection=t,M.newComponent=u,M.unselectCards=v,M.confirmDeleteSelectedCards=A,M.copySelectedCards=C,M.moveSelectedCards=D,M.selectAll=E,M.sort=F,M.sortedBy=G,M.searchMode=H,M.cancelSearch=I,M.newMessage=J,M.newMessageWithSelectedCards=L,M.newMessageWithRecipient=K,M.mode={search:!1,multiple:0},r(N),a.$on("$destroy",function(){_.forEach(N,function(a){o.deregisterHotkey(a)})})}a.$inject=["$scope","$q","$window","$state","$timeout","$mdDialog","$mdToast","Account","Card","AddressBook","sgFocus","Dialog","sgSettings","sgHotkeys","stateAddressbooks","stateAddressbook"],angular.module("SOGo.ContactsUI").controller("AddressBookController",a)}(),function(){"use strict";function a(a,b,c,d,e,f,g,h,i,j,k,m,n,o,p,q,r,s,t,u){function v(a){a.push(n.createHotkey({key:"backspace",description:l("Delete selected card or address book"),callback:function(){q.selectedFolder&&!q.selectedFolder.hasSelectedCard()&&B()}})),_.forEach(a,function(a){n.registerHotkey(a)})}function w(b,c){a.params.addressbookId!=c.id&&J.editMode!=c.id?(J.editMode=!1,q.$query.value="",i(m["gt-md"])||j("left").close(),a.go("app.addressbook",{addressbookId:c.id})):(b.preventDefault(),b.stopPropagation())}function x(){r.prompt(l("New addressbook"),l("Name of new addressbook")).then(function(a){var b=new q({name:a,isEditable:!0,isRemote:!1,owner:UserLogin});q.$add(b)})}function y(a){a.isRemote||(J.editMode=a.id,J.originalAddressbook=angular.extend({},a.$omit()),o("addressBookName_"+a.id))}function z(a){a.name=J.originalAddressbook.name,J.editMode=!1}function A(a){var b=a.name;b&&b.length>0&&b!=J.originalAddressbook.name&&a.$rename(b).then(function(a){J.editMode=!1},function(a,b){r.alert(l("Warning"),a)})}function B(){J.service.selectedFolder.isSubscription?J.service.selectedFolder.$delete().then(function(){J.service.selectedFolder=null,a.go("app.addressbook",{addressbookId:"personal"})},function(a,b){r.alert(l('An error occured while deleting the addressbook "%{0}".',J.service.selectedFolder.name),l(a.error))}):r.confirm(l("Warning"),l('Are you sure you want to delete the addressbook "%{0}"?',J.service.selectedFolder.name),{ok:l("Delete")}).then(function(){return J.service.selectedFolder.$delete()}).then(function(){return J.service.selectedFolder=null,a.go("app.addressbook",{addressbookId:"personal"}),!0}).catch(function(a){if(a){var b=a.data.message||a.statusText;r.alert(l('An error occured while deleting the addressbook "%{0}".',J.service.selectedFolder.name),b)}})}function C(a,b){function c(a,b,c){function d(a){var b=0===a.type.indexOf("text")||/\.(ldif|vcf|vcard)$/.test(a.name);return b||h.show({template:["",'
',' error_outline'," "+l("Select a vCard or LDIF file.")+"","
","
"].join(""),position:"top right",hideDelay:3e3}),b}var e=this;e.uploader=new k({url:ApplicationBaseURL+[c.id,"import"].join("/"),autoUpload:!0,queueLimit:1,filters:[{name:d,fn:d}],onSuccessItem:function(a,c,d,e){var f;b.hide(),0===c.imported?f=l("No card was imported."):(f=l("A total of %{0} cards were imported in the addressbook.",c.imported),q.selectedFolder.$reload()),h.show(h.simple().content(f).position("top right").hideDelay(3e3))},onErrorItem:function(a,b,c,d){h.show({template:["",'
',' error_outline'," "+l("An error occured while importing contacts.")+"","
","
"].join(""),position:"top right",hideDelay:3e3})}}),e.close=function(){b.hide()}}g.show({parent:angular.element(document.body),targetEvent:a,clickOutsideToClose:!0,escapeToClose:!0,templateUrl:"UIxContactsImportDialog",controller:c,controllerAs:"$CardsImportDialogController",locals:{folder:b}}),c.$inject=["scope","$mdDialog","folder"]}function D(a){function b(a,b){function c(){a.hide()}this.addressbook=b,this.close=c}g.show({parent:angular.element(document.body),clickOutsideToClose:!0,escapeToClose:!0,templateUrl:a.id+"/links",controller:b,controllerAs:"links",locals:{addressbook:a}}),b.$inject=["$mdDialog","addressbook"]}function E(a){function b(a,b,c){function d(){f.addressbook.$save().then(function(){c.init(f.addressbook.$omit()),b.hide()})}function e(){b.cancel()}var f=this;f.addressbook=new q(c.$omit()),f.saveProperties=d,f.close=e}g.show({templateUrl:a.id+"/properties",controller:b,controllerAs:"properties",clickOutsideToClose:!0,escapeToClose:!0,locals:{srcAddressBook:a}}).catch(function(){}),b.$inject=["$scope","$mdDialog","srcAddressBook"]}function F(a){a.$acl.$users().then(function(){g.show({templateUrl:a.id+"/UIxAclEditor",controller:"AclController",controllerAs:"acl",clickOutsideToClose:!0,escapeToClose:!0,locals:{usersWithACL:a.$acl.users,User:t,folder:a}})})}function G(a){console.debug("subscribeToFolder "+a.owner+a.name),q.$subscribe(a.owner,a.name).then(function(a){h.show(h.simple().content(l("Successfully subscribed to address book")).position("top right").hideDelay(3e3))})}function H(a,b){return b.id!=a.id&&(b.isOwned||b.acls.objectCreator)}function I(b,c,d){var e,f,g,i,j,k,m;e=c.id,j=!1,f=b.$selectedCards(),0===f.length&&(f=[b.$selectedCard()]),g=_.filter(f,function(a){return a.$isCard()}),g.length!=f.length&&h.show(h.simple().content(l("Lists can't be moved or copied.")).position("top right").hideDelay(2e3)),g.length&&("copy"==d?(k=b.$copyCards(g,e),m=l("%{0} card(s) copied",g.length)):(k=b.$moveCards(g,e),m=l("%{0} card(s) moved",g.length),i=_.map(g,"id"),j=b.selectedCard&&i.indexOf(b.selectedCard)>=0),k.then(function(){j&&a.go("app.addressbook"),h.show(h.simple().content(m).position("top right").hideDelay(2e3))}))}var J=this,K=[];J.activeUser=s.activeUser,J.service=q,J.select=w,J.newAddressbook=x,J.edit=y,J.revertEditing=z,J.save=A,J.confirmDelete=B,J.importCards=C,J.showLinks=D,J.showProperties=E,J.share=F,J.subscribeToFolder=G,J.isDroppableFolder=H,J.dragSelectedCards=I,v(K),b.$on("$destroy",function(){_.forEach(K,function(a){n.deregisterHotkey(a)})})}a.$inject=["$state","$scope","$rootScope","$stateParams","$timeout","$window","$mdDialog","$mdToast","$mdMedia","$mdSidenav","FileUploader","sgConstant","sgHotkeys","sgFocus","Card","AddressBook","Dialog","sgSettings","User","stateAddressbooks"],angular.module("SOGo.ContactsUI").controller("AddressBooksController",a)}(),function(){"use strict";function a(a,b,c,d,e,f,g,h,i,j,k,m){function n(a){a.push(h.createHotkey({key:"backspace",description:l("Delete"),callback:function(a){0===D.currentFolder.$selectedCount()&&B(),a.preventDefault()}})),_.forEach(a,function(a){h.registerHotkey(a)})}function o(a){return angular.isString(a)?{value:a}:a}function p(){var a=D.card.$addOrgUnit("");i("orgUnit_"+a)}function q(){D.card.birthday=new Date}function r(){D.card.$addScreenName("")}function s(){var a=D.card.$addEmail("");i("email_"+a)}function t(){var a=D.card.$addPhone("");i("phone_"+a)}function u(){var a=D.card.$addUrl("","");i("url_"+a)}function v(){var a=D.card.$addAddress("","","","","","","","");i("address_"+a)}function w(a,b){return e.selectedFolder.$filter(a,{dry:!0,excludeLists:!0},b),e.selectedFolder.$$cards}function x(a){a.$valid&&D.card.$save().then(function(a){var b=_.indexOf(_.map(e.selectedFolder.$cards,"id"),D.card.id);b<0?e.selectedFolder.$reload():e.selectedFolder.$cards[b]=angular.copy(D.card),j.go("app.addressbook.card.view",{cardId:D.card.id})})}function y(){j.go("app.addressbook").then(function(){D.card=null,delete e.selectedFolder.selectedCard})}function z(){D.card.$reset()}function A(){D.card.$reset(),D.card.isNew?(D.card=null,delete e.selectedFolder.selectedCard,j.go("app.addressbook",{addressbookId:e.selectedFolder.id})):j.go("app.addressbook.card.view",{cardId:D.card.id})}function B(){var a=m;g.confirm(l("Warning"),l("Are you sure you want to delete the card of %{0}?",""+a.$fullname()+""),{ok:l("Delete")}).then(function(){e.selectedFolder.$deleteCards([a]).then(function(){y()},function(b,c){g.alert(l("Warning"),l('An error occured while deleting the card "%{0}".',a.$fullname()))})})}function C(a){D.showRawSource||D.rawSource?D.showRawSource=!D.showRawSource:f.$$resource.post(D.currentFolder.id+"/"+D.card.id,"raw").then(function(a){D.rawSource=a,D.showRawSource=!0})}var D=this,E=[];D.card=m,D.currentFolder=e.selectedFolder,D.allEmailTypes=f.$EMAIL_TYPES,D.allTelTypes=f.$TEL_TYPES,D.allUrlTypes=f.$URL_TYPES,D.allAddressTypes=f.$ADDRESS_TYPES,D.categories={},D.userFilterResults=[],D.transformCategory=o,D.addOrgUnit=p,D.addBirthday=q,D.addScreenName=r,D.addEmail=s,D.addPhone=t,D.addUrl=u,D.addAddress=v,D.userFilter=w,D.save=x,D.close=y,D.reset=z,D.cancel=A,D.confirmDelete=B,D.toggleRawSource=C,D.showRawSource=!1,n(E),a.$on("$destroy",function(){_.forEach(E,function(a){h.deregisterHotkey(a)})})}a.$inject=["$scope","$timeout","$window","$mdDialog","AddressBook","Card","Dialog","sgHotkeys","sgFocus","$state","$stateParams","stateCard"],angular.module("SOGo.ContactsUI").controller("CardController",a)}(),function(){"use strict";function a(){return{restrict:"A",scope:{data:"=sgAddress"},controller:["$scope",function(a){a.addressLines=function(a){var b=[],c=[];return a.street&&b.push(a.street),a.street2&&b.push(a.street2),a.locality&&c.push(a.locality),a.region&&c.push(a.region),c.length>0&&b.push(c.join(", ")),a.country&&b.push(a.country),a.postalcode&&b.push(a.postalcode),b.join("
")}}],template:'
'}}angular.module("SOGo.Common").directive("sgAddress",a)}(); +!function(){"use strict";function a(a,h){a.state("app",{url:"/addressbooks",abstract:!0,views:{addressbooks:{templateUrl:"UIxContactFoldersView",controller:"AddressBooksController",controllerAs:"app"}},resolve:{stateAddressbooks:b}}).state("app.addressbook",{url:"/:addressbookId",views:{addressbook:{templateUrl:"addressbook",controller:"AddressBookController",controllerAs:"addressbook"}},resolve:{stateAddressbook:c}}).state("app.addressbook.new",{url:"/{contactType:(?:card|list)}/new",views:{card:{templateUrl:"UIxContactEditorTemplate",controller:"CardController",controllerAs:"editor"}},resolve:{stateCard:d}}).state("app.addressbook.card",{url:"/:cardId",abstract:!0,views:{card:{template:""}},resolve:{stateCard:e},onEnter:f,onExit:g}).state("app.addressbook.card.view",{url:"/view",views:{"card@app.addressbook":{templateUrl:"UIxContactViewTemplate",controller:"CardController",controllerAs:"editor"}}}).state("app.addressbook.card.editor",{url:"/edit",views:{"card@app.addressbook":{templateUrl:"UIxContactEditorTemplate",controller:"CardController",controllerAs:"editor"}}}),h.otherwise("/addressbooks/personal")}function b(a){return a.$findAll(window.contactFolders)}function c(a,b,c,d){var e=_.find(d.$findAll(),function(a){return a.id==c.addressbookId});return e?(delete e.selectedCard,e.$reload(),e):a.reject("Addressbook "+c.addressbookId+" not found")}function d(a,b,c){var d="v"+a.contactType,e=new c({pid:a.addressbookId,c_component:d});return b.selectedCard=!0,e}function e(a,b,c){var d;return(d=_.find(c.$cards,function(a){return a.id==b.cardId}))?d.$reload():void a.go("app.addressbook")}function f(a,b){b.selectedCard=a.cardId}function g(a){delete c.selectedCard}function h(a,b,c){a.$on("$stateChangeError",function(a,d,e,f,g,h){b.error(h),c.go("app.addressbook",{addressbookId:"personal"})}),a.$on("$routeChangeError",function(a,c,d,e){b.error(a,c,d,e)})}angular.module("SOGo.ContactsUI",["ngCookies","ui.router","angularFileUpload","ck","SOGo.Common","SOGo.PreferencesUI","SOGo.MailerUI"]).config(a).run(h),a.$inject=["$stateProvider","$urlRouterProvider"],b.$inject=["AddressBook"],c.$inject=["$q","$state","$stateParams","AddressBook"],d.$inject=["$stateParams","stateAddressbook","Card"],e.$inject=["$state","$stateParams","stateAddressbook"],f.$inject=["$stateParams","stateAddressbook"],g.$inject=["stateAddressbook"],h.$inject=["$rootScope","$log","$state"]}(),function(){"use strict";function a(a,b,c,d,e,f,g,h,i,j,k,m,n,o,p,q){function r(a){a.push(o.createHotkey({key:l("hotkey_search"),description:l("Search"),callback:H})),a.push(o.createHotkey({key:l("key_create_card"),description:l("Create a new address book card"),callback:angular.bind(M,u,"card")})),a.push(o.createHotkey({key:l("key_create_list"),description:l("Create a new list"),callback:angular.bind(M,u,"list")})),a.push(o.createHotkey({key:"space",description:l("Toggle item"),callback:t})),a.push(o.createHotkey({key:"up",description:l("View next item"),callback:w})),a.push(o.createHotkey({key:"down",description:l("View previous item"),callback:x})),a.push(o.createHotkey({key:"shift+up",description:l("Add next item to selection"),callback:y})),a.push(o.createHotkey({key:"shift+down",description:l("Add previous item to selection"),callback:z})),a.push(o.createHotkey({key:"backspace",description:l("Delete selected card or address book"),callback:A})),_.forEach(a,function(a){o.registerHotkey(a)})}function s(a){d.go("app.addressbook.card.view",{cardId:a.id})}function t(a,b){b||(b=M.selectedFolder.$selectedCard()),b.selected=!b.selected,M.mode.multiple+=b.selected?1:-1,a.preventDefault(),a.stopPropagation()}function u(a){d.go("app.addressbook.new",{contactType:a})}function v(){_.forEach(M.selectedFolder.$cards,function(a){a.selected=!1}),M.mode.multiple=0}function w(a){var b=M.selectedFolder.$selectedCardIndex();return angular.isDefined(b)?(b--,M.selectedFolder.$topIndex>0&&M.selectedFolder.$topIndex--):(b=M.selectedFolder.$cards.length()-1,M.selectedFolder.$topIndex=M.selectedFolder.getLength()),b>-1&&s(M.selectedFolder.$cards[b]),a.preventDefault(),b}function x(a){var b=M.selectedFolder.$selectedCardIndex();return angular.isDefined(b)?(b++,M.selectedFolder.$topIndex=0&&t(a,M.selectedFolder.$cards[b]))}function z(a){var b;M.selectedFolder.hasSelectedCard()&&(b=x(a),b>=0&&t(a,M.selectedFolder.$cards[b]))}function A(a){var b=M.selectedFolder.$selectedCards();_.size(b)>0&&m.confirm(l("Warning"),l("Are you sure you want to delete the selected contacts?"),{ok:l("Delete")}).then(function(){M.selectedFolder.$deleteCards(b).then(function(){M.mode.multiple=0,M.selectedFolder.selectedCard||d.go("app.addressbook")})}),a.preventDefault()}function B(a,b){var c,e,f,h,i,j,k;c=M.selectedFolder,i=!1,e=c.$selectedCards(),f=_.filter(e,function(a){return a.$isCard()}),f.length!=e.length&&g.show(g.simple().content(l("Lists can't be moved or copied.")).position("top right").hideDelay(2e3)),f.length&&("copy"==a?(j=c.$copyCards(f,b),k=l("%{0} card(s) copied",f.length)):(j=c.$moveCards(f,b),k=l("%{0} card(s) moved",f.length),h=_.map(f,"id"),i=c.selectedCard&&h.indexOf(c.selectedCard)>=0),j.then(function(){i&&d.go("app.addressbook"),g.show(g.simple().content(k).position("top right").hideDelay(2e3))}))}function C(a){B("copy",a)}function D(a){B("move",a)}function E(){_.forEach(M.selectedFolder.$cards,function(a){a.selected=!0}),M.mode.multiple=M.selectedFolder.$cards.length}function F(a){M.selectedFolder.$filter("",{sort:a})}function G(a){return j.$query.sort==a}function H(){M.mode.search=!0,k("search")}function I(){M.mode.search=!1,M.selectedFolder.$filter("")}function J(a,b){h.$findAll().then(function(c){var d=_.find(c,function(a){if(0===a.id)return a});d.$getMailboxes().then(function(c){d.$newMessage().then(function(c){angular.extend(c.editable,{to:b}),f.show({parent:angular.element(document.body),targetEvent:a,clickOutsideToClose:!1,escapeToClose:!1,templateUrl:"../Mail/UIxMailEditor",controller:"MessageEditorController",controllerAs:"editor",locals:{stateAccount:d,stateMessage:c}})})})})}function K(a,b,c){var d=[c+" <"+b+">"];M.newMessage(a,d),a.stopPropagation(),a.preventDefault()}function L(a){var c=_.filter(M.selectedFolder.$cards,function(a){return a.selected}),d=[],e=[];_.forEach(c,function(a){a.$isList({expandable:!0})?angular.isDefined(a.refs)&&a.refs.length?_.forEach(a.refs,function(a){a.email.length&&e.push(a.$shortFormat())}):d.push(a.$reload().then(function(a){_.forEach(a.refs,function(a){a.email.length&&e.push(a.$shortFormat())})})):a.c_mail.length&&e.push(a.$shortFormat())}),b.all(d).then(function(){e=_.uniq(e),e.length&&M.newMessage(a,e)})}var M=this,N=[];j.selectedFolder=q,M.service=j,M.selectedFolder=q,M.selectCard=s,M.toggleCardSelection=t,M.newComponent=u,M.unselectCards=v,M.confirmDeleteSelectedCards=A,M.copySelectedCards=C,M.moveSelectedCards=D,M.selectAll=E,M.sort=F,M.sortedBy=G,M.searchMode=H,M.cancelSearch=I,M.newMessage=J,M.newMessageWithSelectedCards=L,M.newMessageWithRecipient=K,M.mode={search:!1,multiple:0},r(N),a.$on("$destroy",function(){_.forEach(N,function(a){o.deregisterHotkey(a)})})}a.$inject=["$scope","$q","$window","$state","$timeout","$mdDialog","$mdToast","Account","Card","AddressBook","sgFocus","Dialog","sgSettings","sgHotkeys","stateAddressbooks","stateAddressbook"],angular.module("SOGo.ContactsUI").controller("AddressBookController",a)}(),function(){"use strict";function a(a,b,c,d,e,f,g,h,i,j,k,m,n,o,p,q,r,s,t,u){function v(a){a.push(n.createHotkey({key:"backspace",description:l("Delete selected card or address book"),callback:function(){q.selectedFolder&&!q.selectedFolder.hasSelectedCard()&&B()}})),_.forEach(a,function(a){n.registerHotkey(a)})}function w(b,c){a.params.addressbookId!=c.id&&J.editMode!=c.id?(J.editMode=!1,q.$query.value="",i(m["gt-md"])||j("left").close(),a.go("app.addressbook",{addressbookId:c.id})):(b.preventDefault(),b.stopPropagation())}function x(){r.prompt(l("New addressbook"),l("Name of new addressbook")).then(function(a){var b=new q({name:a,isEditable:!0,isRemote:!1,owner:UserLogin});q.$add(b)})}function y(a){a.isRemote||(J.editMode=a.id,J.originalAddressbook=angular.extend({},a.$omit()),o("addressBookName_"+a.id))}function z(a){a.name=J.originalAddressbook.name,J.editMode=!1}function A(a){var b=a.name;b&&b.length>0&&b!=J.originalAddressbook.name&&a.$rename(b).then(function(a){J.editMode=!1},function(a,b){r.alert(l("Warning"),a)})}function B(){J.service.selectedFolder.isSubscription?J.service.selectedFolder.$delete().then(function(){J.service.selectedFolder=null,a.go("app.addressbook",{addressbookId:"personal"})},function(a,b){r.alert(l('An error occured while deleting the addressbook "%{0}".',J.service.selectedFolder.name),l(a.error))}):r.confirm(l("Warning"),l('Are you sure you want to delete the addressbook "%{0}"?',J.service.selectedFolder.name),{ok:l("Delete")}).then(function(){return J.service.selectedFolder.$delete()}).then(function(){return J.service.selectedFolder=null,a.go("app.addressbook",{addressbookId:"personal"}),!0}).catch(function(a){if(a){var b=a.data.message||a.statusText;r.alert(l('An error occured while deleting the addressbook "%{0}".',J.service.selectedFolder.name),b)}})}function C(a,b){function c(a,b,c){function d(a){var b=0===a.type.indexOf("text")||/\.(ldif|vcf|vcard)$/.test(a.name);return b||h.show({template:["",'
',' error_outline'," "+l("Select a vCard or LDIF file.")+"","
","
"].join(""),position:"top right",hideDelay:3e3}),b}var e=this;e.uploader=new k({url:ApplicationBaseURL+[c.id,"import"].join("/"),autoUpload:!0,queueLimit:1,filters:[{name:d,fn:d}],onSuccessItem:function(a,c,d,e){var f;b.hide(),0===c.imported?f=l("No card was imported."):(f=l("A total of %{0} cards were imported in the addressbook.",c.imported),q.selectedFolder.$reload()),h.show(h.simple().content(f).position("top right").hideDelay(3e3))},onErrorItem:function(a,b,c,d){h.show({template:["",'
',' error_outline'," "+l("An error occured while importing contacts.")+"","
","
"].join(""),position:"top right",hideDelay:3e3})}}),e.close=function(){b.hide()}}g.show({parent:angular.element(document.body),targetEvent:a,clickOutsideToClose:!0,escapeToClose:!0,templateUrl:"UIxContactsImportDialog",controller:c,controllerAs:"$CardsImportDialogController",locals:{folder:b}}),c.$inject=["scope","$mdDialog","folder"]}function D(a){function b(a,b){function c(){a.hide()}this.addressbook=b,this.close=c}g.show({parent:angular.element(document.body),clickOutsideToClose:!0,escapeToClose:!0,templateUrl:a.id+"/links",controller:b,controllerAs:"links",locals:{addressbook:a}}),b.$inject=["$mdDialog","addressbook"]}function E(a){function b(a,b,c){function d(){f.addressbook.$save().then(function(){c.init(f.addressbook.$omit()),b.hide()})}function e(){b.cancel()}var f=this;f.addressbook=new q(c.$omit()),f.saveProperties=d,f.close=e}g.show({templateUrl:a.id+"/properties",controller:b,controllerAs:"properties",clickOutsideToClose:!0,escapeToClose:!0,locals:{srcAddressBook:a}}).catch(function(){}),b.$inject=["$scope","$mdDialog","srcAddressBook"]}function F(a){a.$acl.$users().then(function(){g.show({templateUrl:a.id+"/UIxAclEditor",controller:"AclController",controllerAs:"acl",clickOutsideToClose:!0,escapeToClose:!0,locals:{usersWithACL:a.$acl.users,User:t,folder:a}})})}function G(a){console.debug("subscribeToFolder "+a.owner+a.name),q.$subscribe(a.owner,a.name).then(function(a){h.show(h.simple().content(l("Successfully subscribed to address book")).position("top right").hideDelay(3e3))})}function H(a,b){return b.id!=a.id&&(b.isOwned||b.acls.objectCreator)}function I(b,c,d){var e,f,g,i,j,k,m;e=c.id,j=!1,f=b.$selectedCards(),0===f.length&&(f=[b.$selectedCard()]),g=_.filter(f,function(a){return a.$isCard()}),g.length!=f.length&&h.show(h.simple().content(l("Lists can't be moved or copied.")).position("top right").hideDelay(2e3)),g.length&&("copy"==d?(k=b.$copyCards(g,e),m=l("%{0} card(s) copied",g.length)):(k=b.$moveCards(g,e),m=l("%{0} card(s) moved",g.length),i=_.map(g,"id"),j=b.selectedCard&&i.indexOf(b.selectedCard)>=0),k.then(function(){j&&a.go("app.addressbook"),h.show(h.simple().content(m).position("top right").hideDelay(2e3))}))}var J=this,K=[];J.activeUser=s.activeUser,J.service=q,J.select=w,J.newAddressbook=x,J.edit=y,J.revertEditing=z,J.save=A,J.confirmDelete=B,J.importCards=C,J.showLinks=D,J.showProperties=E,J.share=F,J.subscribeToFolder=G,J.isDroppableFolder=H,J.dragSelectedCards=I,v(K),b.$on("$destroy",function(){_.forEach(K,function(a){n.deregisterHotkey(a)})})}a.$inject=["$state","$scope","$rootScope","$stateParams","$timeout","$window","$mdDialog","$mdToast","$mdMedia","$mdSidenav","FileUploader","sgConstant","sgHotkeys","sgFocus","Card","AddressBook","Dialog","sgSettings","User","stateAddressbooks"],angular.module("SOGo.ContactsUI").controller("AddressBooksController",a)}(),function(){"use strict";function a(a,b,c,d,e,f,g,h,i,j,k,m){function n(a){a.push(h.createHotkey({key:"backspace",description:l("Delete"),callback:function(a){0===E.currentFolder.$selectedCount()&&B(),a.preventDefault()}})),_.forEach(a,function(a){h.registerHotkey(a)})}function o(a){return angular.isString(a)?{value:a}:a}function p(){var a=E.card.$addOrgUnit("");i("orgUnit_"+a)}function q(){E.card.birthday=new Date}function r(){E.card.$addScreenName("")}function s(){var a=E.card.$addEmail("");i("email_"+a)}function t(){var a=E.card.$addPhone("");i("phone_"+a)}function u(){var a=E.card.$addUrl("","");i("url_"+a)}function v(){var a=E.card.$addAddress("","","","","","","","");i("address_"+a)}function w(a,b){return a.length"+a.$fullname()+""),{ok:l("Delete")}).then(function(){e.selectedFolder.$deleteCards([a]).then(function(){y()},function(b,c){g.alert(l("Warning"),l('An error occured while deleting the card "%{0}".',a.$fullname()))})})}function C(a){E.showRawSource||E.rawSource?E.showRawSource=!E.showRawSource:f.$$resource.post(E.currentFolder.id+"/"+E.card.id,"raw").then(function(a){E.rawSource=a,E.showRawSource=!0})}var D,E=this,F=[];E.card=m,E.currentFolder=e.selectedFolder,E.allEmailTypes=f.$EMAIL_TYPES,E.allTelTypes=f.$TEL_TYPES,E.allUrlTypes=f.$URL_TYPES,E.allAddressTypes=f.$ADDRESS_TYPES,E.categories={},E.userFilterResults=[],E.transformCategory=o,E.addOrgUnit=p,E.addBirthday=q,E.addScreenName=r,E.addEmail=s,E.addPhone=t,E.addUrl=u,E.addAddress=v,E.userFilter=w,E.save=x,E.close=y,E.reset=z,E.cancel=A,E.confirmDelete=B,E.toggleRawSource=C,E.showRawSource=!1,D=angular.isNumber(c.minimumSearchLength)?c.minimumSearchLength:2,n(F),a.$on("$destroy",function(){_.forEach(F,function(a){h.deregisterHotkey(a)})})}a.$inject=["$scope","$timeout","$window","$mdDialog","AddressBook","Card","Dialog","sgHotkeys","sgFocus","$state","$stateParams","stateCard"],angular.module("SOGo.ContactsUI").controller("CardController",a)}(),function(){"use strict";function a(){return{restrict:"A",scope:{data:"=sgAddress"},controller:["$scope",function(a){a.addressLines=function(a){var b=[],c=[];return a.street&&b.push(a.street),a.street2&&b.push(a.street2),a.locality&&c.push(a.locality),a.region&&c.push(a.region),c.length>0&&b.push(c.join(", ")),a.country&&b.push(a.country),a.postalcode&&b.push(a.postalcode),b.join("
")}}],template:'
'}}angular.module("SOGo.Common").directive("sgAddress",a)}(); //# sourceMappingURL=Contacts.js.map \ No newline at end of file diff --git a/UI/WebServerResources/js/Contacts.js.map b/UI/WebServerResources/js/Contacts.js.map index 3747d4eb6..c4f20ec11 100644 --- a/UI/WebServerResources/js/Contacts.js.map +++ b/UI/WebServerResources/js/Contacts.js.map @@ -1 +1 @@ -{"version":3,"sources":["Contacts/Contacts.app.js","Contacts/AddressBookController.js","Contacts/AddressBooksController.js","Contacts/CardController.js","Contacts/sgAddress.directive.js"],"names":["configure","$stateProvider","$urlRouterProvider","state","url","abstract","views","addressbooks","templateUrl","controller","controllerAs","resolve","stateAddressbooks","addressbook","stateAddressbook","card","stateCard","stateNewCard","template","onEnter","onEnterCard","onExit","onExitCard","card@app.addressbook","otherwise","AddressBook","$findAll","window","contactFolders","$q","$state","$stateParams","_","find","id","addressbookId","selectedCard","$reload","reject","Card","tag","contactType","pid","c_component","$cards","cardObject","cardId","go","stateMailbox","runBlock","$rootScope","$log","$on","event","toState","toParams","fromState","fromParams","error","current","previous","rejection","angular","module","config","run","$inject","AddressBookController","$scope","$window","$timeout","$mdDialog","$mdToast","Account","focus","Dialog","Settings","sgHotkeys","_registerHotkeys","keys","push","createHotkey","key","l","description","callback","searchMode","bind","vm","newComponent","toggleCardSelection","_nextCard","_previousCard","_addNextCardToSelection","_addPreviousCardToSelection","confirmDeleteSelectedCards","forEach","registerHotkey","selectCard","$event","selectedFolder","$selectedCard","selected","mode","multiple","preventDefault","stopPropagation","type","unselectCards","index","$selectedCardIndex","isDefined","$topIndex","length","getLength","hasSelectedCard","selectedCards","$selectedCards","size","confirm","ok","then","$deleteCards","_selectedCardsOperation","operation","dstId","srcFolder","allCards","cards","ids","clearCardView","promise","success","filter","$isCard","show","simple","content","position","hideDelay","$copyCards","$moveCards","map","indexOf","copySelectedCards","folder","moveSelectedCards","selectAll","sort","field","$filter","sortedBy","$query","search","cancelSearch","newMessage","recipients","accounts","account","o","$getMailboxes","mailboxes","$newMessage","message","extend","editable","to","parent","element","document","body","targetEvent","clickOutsideToClose","escapeToClose","locals","stateAccount","stateMessage","newMessageWithRecipient","recipient","fn","newMessageWithSelectedCards","promises","$isList","expandable","refs","ref","email","$shortFormat","c_mail","all","uniq","this","hotkeys","service","deregisterHotkey","AddressBooksController","$mdMedia","$mdSidenav","FileUploader","sgConstant","User","confirmDelete","select","params","editMode","value","close","newAddressbook","prompt","name","isEditable","isRemote","owner","UserLogin","$add","edit","originalAddressbook","$omit","revertEditing","save","$rename","data","status","alert","isSubscription","$delete","catch","response","statusText","importCards","CardsImportDialogController","scope","filterByExtension","item","isTextFile","test","join","uploader","ApplicationBaseURL","autoUpload","queueLimit","filters","onSuccessItem","headers","msg","hide","imported","onErrorItem","showLinks","LinksDialogController","showProperties","PropertiesDialogController","srcAddressBook","saveProperties","$save","init","cancel","share","$acl","$users","usersWithACL","users","subscribeToFolder","addressbookData","console","debug","$subscribe","isDroppableFolder","dstFolder","isOwned","acls","objectCreator","dragSelectedCards","activeUser","CardController","currentFolder","$selectedCount","transformCategory","input","isString","addOrgUnit","i","$addOrgUnit","addBirthday","birthday","Date","addScreenName","$addScreenName","addEmail","$addEmail","addPhone","$addPhone","addUrl","$addUrl","addAddress","$addAddress","userFilter","excludedCards","dry","excludeLists","$$cards","form","$valid","copy","reset","$reset","isNew","$fullname","toggleRawSource","showRawSource","rawSource","$$resource","post","allEmailTypes","$EMAIL_TYPES","allTelTypes","$TEL_TYPES","allUrlTypes","$URL_TYPES","allAddressTypes","$ADDRESS_TYPES","categories","userFilterResults","sgAddress","restrict","addressLines","lines","locality_region","street","street2","locality","region","country","postalcode","directive"],"mappings":"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","file":"Contacts.js","sourcesContent":["/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* JavaScript for SOGoContacts */\n\n(function() {\n 'use strict';\n\n angular.module('SOGo.ContactsUI', ['ngCookies', 'ui.router', 'angularFileUpload', 'ck', 'SOGo.Common', 'SOGo.PreferencesUI', 'SOGo.MailerUI'])\n .config(configure)\n .run(runBlock);\n\n /**\n * @ngInject\n */\n configure.$inject = ['$stateProvider', '$urlRouterProvider'];\n function configure($stateProvider, $urlRouterProvider) {\n $stateProvider\n .state('app', {\n url: '/addressbooks',\n abstract: true,\n views: {\n addressbooks: {\n templateUrl: 'UIxContactFoldersView', // UI/Templates/Contacts/UIxContactFoldersView.wox\n controller: 'AddressBooksController',\n controllerAs: 'app'\n }\n },\n resolve: {\n stateAddressbooks: stateAddressbooks\n }\n })\n .state('app.addressbook', {\n url: '/:addressbookId',\n views: {\n addressbook: {\n templateUrl: 'addressbook',\n controller: 'AddressBookController',\n controllerAs: 'addressbook'\n }\n },\n resolve: {\n stateAddressbook: stateAddressbook\n }\n })\n .state('app.addressbook.new', {\n url: '/{contactType:(?:card|list)}/new',\n views: {\n card: {\n templateUrl: 'UIxContactEditorTemplate', // UI/Templates/Contacts/UIxContactEditorTemplate.wox\n controller: 'CardController',\n controllerAs: 'editor'\n }\n },\n resolve: {\n stateCard: stateNewCard\n }\n })\n .state('app.addressbook.card', {\n url: '/:cardId',\n abstract: true,\n views: {\n card: {\n template: ''\n }\n },\n resolve: {\n stateCard: stateCard\n },\n onEnter: onEnterCard,\n onExit: onExitCard\n })\n .state('app.addressbook.card.view', {\n url: '/view',\n views: {\n 'card@app.addressbook': {\n templateUrl: 'UIxContactViewTemplate', // UI/Templates/Contacts/UIxContactViewTemplate.wox\n controller: 'CardController',\n controllerAs: 'editor'\n }\n }\n })\n .state('app.addressbook.card.editor', {\n url: '/edit',\n views: {\n 'card@app.addressbook': {\n templateUrl: 'UIxContactEditorTemplate', // UI/Templates/Contacts/UIxContactEditorTemplate.wox\n controller: 'CardController',\n controllerAs: 'editor'\n }\n }\n });\n\n // if none of the above states are matched, use this as the fallback\n $urlRouterProvider.otherwise('/addressbooks/personal');\n }\n\n /**\n * @ngInject\n */\n stateAddressbooks.$inject = ['AddressBook'];\n function stateAddressbooks(AddressBook) {\n return AddressBook.$findAll(window.contactFolders);\n }\n\n /**\n * @ngInject\n */\n stateAddressbook.$inject = ['$q', '$state', '$stateParams', 'AddressBook'];\n function stateAddressbook($q, $state, $stateParams, AddressBook) {\n var addressbook = _.find(AddressBook.$findAll(), function(addressbook) {\n return addressbook.id == $stateParams.addressbookId;\n });\n if (addressbook) {\n delete addressbook.selectedCard;\n addressbook.$reload();\n return addressbook;\n }\n return $q.reject('Addressbook ' + $stateParams.addressbookId + ' not found');\n }\n\n /**\n * @ngInject\n */\n stateNewCard.$inject = ['$stateParams', 'stateAddressbook', 'Card'];\n function stateNewCard($stateParams, stateAddressbook, Card) {\n var tag = 'v' + $stateParams.contactType,\n card = new Card({ pid: $stateParams.addressbookId, c_component: tag });\n stateAddressbook.selectedCard = true;\n return card;\n }\n\n /**\n * @ngInject\n */\n stateCard.$inject = ['$state', '$stateParams', 'stateAddressbook'];\n function stateCard($state, $stateParams, stateAddressbook) {\n var card;\n\n card = _.find(stateAddressbook.$cards, function(cardObject) {\n return (cardObject.id == $stateParams.cardId);\n });\n\n if (card) {\n return card.$reload();\n }\n else {\n // Card not found\n $state.go('app.addressbook');\n }\n }\n\n /**\n * @ngInject\n */\n onEnterCard.$inject = ['$stateParams', 'stateAddressbook'];\n function onEnterCard($stateParams, stateAddressbook) {\n stateAddressbook.selectedCard = $stateParams.cardId;\n }\n\n /**\n * @ngInject\n */\n onExitCard.$inject = ['stateAddressbook'];\n function onExitCard(stateMailbox) {\n delete stateAddressbook.selectedCard;\n }\n\n /**\n * @ngInject\n */\n runBlock.$inject = ['$rootScope', '$log', '$state'];\n function runBlock($rootScope, $log, $state) {\n $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {\n $log.error(error);\n $state.go('app.addressbook', { addressbookId: 'personal' });\n });\n $rootScope.$on('$routeChangeError', function(event, current, previous, rejection) {\n $log.error(event, current, previous, rejection);\n });\n }\n\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /**\n * @ngInject\n */\n AddressBookController.$inject = ['$scope', '$q', '$window', '$state', '$timeout', '$mdDialog', '$mdToast', 'Account', 'Card', 'AddressBook', 'sgFocus', 'Dialog', 'sgSettings', 'sgHotkeys', 'stateAddressbooks', 'stateAddressbook'];\n function AddressBookController($scope, $q, $window, $state, $timeout, $mdDialog, $mdToast, Account, Card, AddressBook, focus, Dialog, Settings, sgHotkeys, stateAddressbooks, stateAddressbook) {\n var vm = this, hotkeys = [];\n\n AddressBook.selectedFolder = stateAddressbook;\n\n vm.service = AddressBook;\n vm.selectedFolder = stateAddressbook;\n vm.selectCard = selectCard;\n vm.toggleCardSelection = toggleCardSelection;\n vm.newComponent = newComponent;\n vm.unselectCards = unselectCards;\n vm.confirmDeleteSelectedCards = confirmDeleteSelectedCards;\n vm.copySelectedCards = copySelectedCards;\n vm.moveSelectedCards = moveSelectedCards;\n vm.selectAll = selectAll;\n vm.sort = sort;\n vm.sortedBy = sortedBy;\n vm.searchMode = searchMode;\n vm.cancelSearch = cancelSearch;\n vm.newMessage = newMessage;\n vm.newMessageWithSelectedCards = newMessageWithSelectedCards;\n vm.newMessageWithRecipient = newMessageWithRecipient;\n vm.mode = { search: false, multiple: 0 };\n\n\n _registerHotkeys(hotkeys);\n\n $scope.$on('$destroy', function() {\n // Deregister hotkeys\n _.forEach(hotkeys, function(key) {\n sgHotkeys.deregisterHotkey(key);\n });\n });\n\n\n function _registerHotkeys(keys) {\n keys.push(sgHotkeys.createHotkey({\n key: l('hotkey_search'),\n description: l('Search'),\n callback: searchMode\n }));\n keys.push(sgHotkeys.createHotkey({\n key: l('key_create_card'),\n description: l('Create a new address book card'),\n callback: angular.bind(vm, newComponent, 'card')\n }));\n keys.push(sgHotkeys.createHotkey({\n key: l('key_create_list'),\n description: l('Create a new list'),\n callback: angular.bind(vm, newComponent, 'list')\n }));\n keys.push(sgHotkeys.createHotkey({\n key: 'space',\n description: l('Toggle item'),\n callback: toggleCardSelection\n }));\n keys.push(sgHotkeys.createHotkey({\n key: 'up',\n description: l('View next item'),\n callback: _nextCard\n }));\n keys.push(sgHotkeys.createHotkey({\n key: 'down',\n description: l('View previous item'),\n callback: _previousCard\n }));\n keys.push(sgHotkeys.createHotkey({\n key: 'shift+up',\n description: l('Add next item to selection'),\n callback: _addNextCardToSelection\n }));\n keys.push(sgHotkeys.createHotkey({\n key: 'shift+down',\n description: l('Add previous item to selection'),\n callback: _addPreviousCardToSelection\n }));\n keys.push(sgHotkeys.createHotkey({\n key: 'backspace',\n description: l('Delete selected card or address book'),\n callback: confirmDeleteSelectedCards\n }));\n\n // Register the hotkeys\n _.forEach(keys, function(key) {\n sgHotkeys.registerHotkey(key);\n });\n }\n\n function selectCard(card) {\n $state.go('app.addressbook.card.view', {cardId: card.id});\n }\n\n function toggleCardSelection($event, card) {\n if (!card) card = vm.selectedFolder.$selectedCard();\n card.selected = !card.selected;\n vm.mode.multiple += card.selected? 1 : -1;\n $event.preventDefault();\n $event.stopPropagation();\n }\n\n function newComponent(type) {\n $state.go('app.addressbook.new', { contactType: type });\n }\n\n function unselectCards() {\n _.forEach(vm.selectedFolder.$cards, function(card) {\n card.selected = false;\n });\n vm.mode.multiple = 0;\n }\n\n /**\n * User has pressed up arrow key\n */\n function _nextCard($event) {\n var index = vm.selectedFolder.$selectedCardIndex();\n\n if (angular.isDefined(index)) {\n index--;\n if (vm.selectedFolder.$topIndex > 0)\n vm.selectedFolder.$topIndex--;\n }\n else {\n // No message is selected, show oldest message\n index = vm.selectedFolder.$cards.length() - 1;\n vm.selectedFolder.$topIndex = vm.selectedFolder.getLength();\n }\n\n if (index > -1)\n selectCard(vm.selectedFolder.$cards[index]);\n\n $event.preventDefault();\n\n return index;\n }\n\n /**\n * User has pressed the down arrow key\n */\n function _previousCard($event) {\n var index = vm.selectedFolder.$selectedCardIndex();\n\n if (angular.isDefined(index)) {\n index++;\n if (vm.selectedFolder.$topIndex < vm.selectedFolder.$cards.length)\n vm.selectedFolder.$topIndex++;\n }\n else\n // No message is selected, show newest\n index = 0;\n\n if (index < vm.selectedFolder.$cards.length)\n selectCard(vm.selectedFolder.$cards[index]);\n else\n index = -1;\n\n $event.preventDefault();\n\n return index;\n }\n\n function _addNextCardToSelection($event) {\n var index;\n\n if (vm.selectedFolder.hasSelectedCard()) {\n index = _nextCard($event);\n if (index >= 0)\n toggleCardSelection($event, vm.selectedFolder.$cards[index]);\n }\n }\n\n function _addPreviousCardToSelection($event) {\n var index;\n\n if (vm.selectedFolder.hasSelectedCard()) {\n index = _previousCard($event);\n if (index >= 0)\n toggleCardSelection($event, vm.selectedFolder.$cards[index]);\n }\n }\n\n function confirmDeleteSelectedCards($event) {\n var selectedCards = vm.selectedFolder.$selectedCards();\n\n if (_.size(selectedCards) > 0)\n Dialog.confirm(l('Warning'),\n l('Are you sure you want to delete the selected contacts?'),\n { ok: l('Delete') })\n .then(function() {\n // User confirmed the deletion\n vm.selectedFolder.$deleteCards(selectedCards).then(function() {\n vm.mode.multiple = 0;\n if (!vm.selectedFolder.selectedCard)\n $state.go('app.addressbook');\n });\n });\n\n $event.preventDefault();\n }\n\n /**\n * @see AddressBooksController.dragSelectedCards\n */\n function _selectedCardsOperation(operation, dstId) {\n var srcFolder, allCards, cards, ids, clearCardView, promise, success;\n\n srcFolder = vm.selectedFolder;\n clearCardView = false;\n allCards = srcFolder.$selectedCards();\n cards = _.filter(allCards, function(card) {\n return card.$isCard();\n });\n\n if (cards.length != allCards.length)\n $mdToast.show(\n $mdToast.simple()\n .content(l(\"Lists can't be moved or copied.\"))\n .position('top right')\n .hideDelay(2000));\n\n if (cards.length) {\n if (operation == 'copy') {\n promise = srcFolder.$copyCards(cards, dstId);\n success = l('%{0} card(s) copied', cards.length);\n }\n else {\n promise = srcFolder.$moveCards(cards, dstId);\n success = l('%{0} card(s) moved', cards.length);\n // Check if currently displayed card will be moved\n ids = _.map(cards, 'id');\n clearCardView = (srcFolder.selectedCard && ids.indexOf(srcFolder.selectedCard) >= 0);\n }\n\n // Show success toast when action succeeds\n promise.then(function() {\n if (clearCardView)\n $state.go('app.addressbook');\n $mdToast.show(\n $mdToast.simple()\n .content(success)\n .position('top right')\n .hideDelay(2000));\n });\n }\n }\n\n function copySelectedCards(folder) {\n _selectedCardsOperation('copy', folder);\n }\n\n function moveSelectedCards(folder) {\n _selectedCardsOperation('move', folder);\n }\n\n function selectAll() {\n _.forEach(vm.selectedFolder.$cards, function(card) {\n card.selected = true;\n });\n vm.mode.multiple = vm.selectedFolder.$cards.length;\n }\n\n function sort(field) {\n vm.selectedFolder.$filter('', { sort: field });\n }\n\n function sortedBy(field) {\n return AddressBook.$query.sort == field;\n }\n\n function searchMode() {\n vm.mode.search = true;\n focus('search');\n }\n\n function cancelSearch() {\n vm.mode.search = false;\n vm.selectedFolder.$filter('');\n }\n\n function newMessage($event, recipients) {\n Account.$findAll().then(function(accounts) {\n var account = _.find(accounts, function(o) {\n if (o.id === 0)\n return o;\n });\n\n // We must initialize the Account with its mailbox\n // list before proceeding with message's creation\n account.$getMailboxes().then(function(mailboxes) {\n account.$newMessage().then(function(message) {\n angular.extend(message.editable, { to: recipients });\n $mdDialog.show({\n parent: angular.element(document.body),\n targetEvent: $event,\n clickOutsideToClose: false,\n escapeToClose: false,\n templateUrl: '../Mail/UIxMailEditor',\n controller: 'MessageEditorController',\n controllerAs: 'editor',\n locals: {\n stateAccount: account,\n stateMessage: message\n }\n });\n });\n });\n });\n }\n\n function newMessageWithRecipient($event, recipient, fn) {\n var recipients = [fn + ' <' + recipient + '>'];\n vm.newMessage($event, recipients);\n $event.stopPropagation();\n $event.preventDefault();\n }\n\n function newMessageWithSelectedCards($event) {\n var selectedCards = _.filter(vm.selectedFolder.$cards, function(card) { return card.selected; });\n var promises = [], recipients = [];\n\n _.forEach(selectedCards, function(card) {\n if (card.$isList({expandable: true})) {\n // If the list's members were already fetch, use them\n if (angular.isDefined(card.refs) && card.refs.length) {\n _.forEach(card.refs, function(ref) {\n if (ref.email.length)\n recipients.push(ref.$shortFormat());\n });\n }\n else {\n promises.push(card.$reload().then(function(card) {\n _.forEach(card.refs, function(ref) {\n if (ref.email.length)\n recipients.push(ref.$shortFormat());\n });\n }));\n }\n }\n else if (card.c_mail.length) {\n recipients.push(card.$shortFormat());\n }\n });\n\n $q.all(promises).then(function() {\n recipients = _.uniq(recipients);\n if (recipients.length)\n vm.newMessage($event, recipients);\n });\n }\n }\n\n angular\n .module('SOGo.ContactsUI')\n .controller('AddressBookController', AddressBookController);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /**\n * @ngInject\n */\n AddressBooksController.$inject = ['$state', '$scope', '$rootScope', '$stateParams', '$timeout', '$window', '$mdDialog', '$mdToast', '$mdMedia', '$mdSidenav', 'FileUploader', 'sgConstant', 'sgHotkeys', 'sgFocus', 'Card', 'AddressBook', 'Dialog', 'sgSettings', 'User', 'stateAddressbooks'];\n function AddressBooksController($state, $scope, $rootScope, $stateParams, $timeout, $window, $mdDialog, $mdToast, $mdMedia, $mdSidenav, FileUploader, sgConstant, sgHotkeys, focus, Card, AddressBook, Dialog, Settings, User, stateAddressbooks) {\n var vm = this, hotkeys = [];\n\n vm.activeUser = Settings.activeUser;\n vm.service = AddressBook;\n vm.select = select;\n vm.newAddressbook = newAddressbook;\n vm.edit = edit;\n vm.revertEditing = revertEditing;\n vm.save = save;\n vm.confirmDelete = confirmDelete;\n vm.importCards = importCards;\n vm.showLinks = showLinks;\n vm.showProperties = showProperties;\n vm.share = share;\n vm.subscribeToFolder = subscribeToFolder;\n vm.isDroppableFolder = isDroppableFolder;\n vm.dragSelectedCards = dragSelectedCards;\n\n\n _registerHotkeys(hotkeys);\n\n $scope.$on('$destroy', function() {\n // Deregister hotkeys\n _.forEach(hotkeys, function(key) {\n sgHotkeys.deregisterHotkey(key);\n });\n });\n\n\n function _registerHotkeys(keys) {\n keys.push(sgHotkeys.createHotkey({\n key: 'backspace',\n description: l('Delete selected card or address book'),\n callback: function() {\n if (AddressBook.selectedFolder && !AddressBook.selectedFolder.hasSelectedCard())\n confirmDelete();\n }\n }));\n\n // Register the hotkeys\n _.forEach(keys, function(key) {\n sgHotkeys.registerHotkey(key);\n });\n }\n\n function select($event, folder) {\n if ($state.params.addressbookId != folder.id &&\n vm.editMode != folder.id) {\n vm.editMode = false;\n AddressBook.$query.value = '';\n // Close sidenav on small devices\n if (!$mdMedia(sgConstant['gt-md']))\n $mdSidenav('left').close();\n $state.go('app.addressbook', {addressbookId: folder.id});\n }\n else {\n $event.preventDefault();\n $event.stopPropagation();\n }\n }\n\n function newAddressbook() {\n Dialog.prompt(l('New addressbook'),\n l('Name of new addressbook'))\n .then(function(name) {\n var addressbook = new AddressBook(\n {\n name: name,\n isEditable: true,\n isRemote: false,\n owner: UserLogin\n }\n );\n AddressBook.$add(addressbook);\n });\n }\n\n function edit(folder) {\n if (!folder.isRemote) {\n vm.editMode = folder.id;\n vm.originalAddressbook = angular.extend({}, folder.$omit());\n focus('addressBookName_' + folder.id);\n }\n }\n\n function revertEditing(folder) {\n folder.name = vm.originalAddressbook.name;\n vm.editMode = false;\n }\n\n function save(folder) {\n var name = folder.name;\n if (name && name.length > 0 && name != vm.originalAddressbook.name) {\n folder.$rename(name)\n .then(function(data) {\n vm.editMode = false;\n }, function(data, status) {\n Dialog.alert(l('Warning'), data);\n });\n }\n }\n\n function confirmDelete() {\n if (vm.service.selectedFolder.isSubscription) {\n // Unsubscribe without confirmation\n vm.service.selectedFolder.$delete()\n .then(function() {\n vm.service.selectedFolder = null;\n $state.go('app.addressbook', { addressbookId: 'personal' });\n }, function(data, status) {\n Dialog.alert(l('An error occured while deleting the addressbook \"%{0}\".',\n vm.service.selectedFolder.name),\n l(data.error));\n });\n }\n else {\n Dialog.confirm(l('Warning'), l('Are you sure you want to delete the addressbook \"%{0}\"?',\n vm.service.selectedFolder.name),\n { ok: l('Delete') })\n .then(function() {\n return vm.service.selectedFolder.$delete();\n })\n .then(function() {\n vm.service.selectedFolder = null;\n $state.go('app.addressbook', { addressbookId: 'personal' });\n return true;\n })\n .catch(function(response) {\n if (response) {\n var message = response.data.message || response.statusText;\n Dialog.alert(l('An error occured while deleting the addressbook \"%{0}\".',\n vm.service.selectedFolder.name),\n message);\n }\n });\n }\n }\n\n function importCards($event, folder) {\n $mdDialog.show({\n parent: angular.element(document.body),\n targetEvent: $event,\n clickOutsideToClose: true,\n escapeToClose: true,\n templateUrl: 'UIxContactsImportDialog',\n controller: CardsImportDialogController,\n controllerAs: '$CardsImportDialogController',\n locals: {\n folder: folder\n }\n });\n\n /**\n * @ngInject\n */\n CardsImportDialogController.$inject = ['scope', '$mdDialog', 'folder'];\n function CardsImportDialogController(scope, $mdDialog, folder) {\n var vm = this;\n\n vm.uploader = new FileUploader({\n url: ApplicationBaseURL + [folder.id, 'import'].join('/'),\n autoUpload: true,\n queueLimit: 1,\n filters: [{ name: filterByExtension, fn: filterByExtension }],\n onSuccessItem: function(item, response, status, headers) {\n var msg;\n\n $mdDialog.hide();\n\n if (response.imported === 0)\n msg = l('No card was imported.');\n else {\n msg = l('A total of %{0} cards were imported in the addressbook.', response.imported);\n AddressBook.selectedFolder.$reload();\n }\n\n $mdToast.show(\n $mdToast.simple()\n .content(msg)\n .position('top right')\n .hideDelay(3000));\n },\n onErrorItem: function(item, response, status, headers) {\n $mdToast.show({\n template: [\n '',\n '
',\n ' error_outline',\n ' ' + l('An error occured while importing contacts.') + '',\n '
',\n '
'\n ].join(''),\n position: 'top right',\n hideDelay: 3000\n });\n }\n });\n\n vm.close = function() {\n $mdDialog.hide();\n };\n\n function filterByExtension(item) {\n var isTextFile = item.type.indexOf('text') === 0 ||\n /\\.(ldif|vcf|vcard)$/.test(item.name);\n\n if (!isTextFile)\n $mdToast.show({\n template: [\n '',\n '
',\n ' error_outline',\n ' ' + l('Select a vCard or LDIF file.') + '',\n '
',\n '
'\n ].join(''),\n position: 'top right',\n hideDelay: 3000\n });\n\n return isTextFile;\n }\n }\n }\n\n function showLinks(addressbook) {\n $mdDialog.show({\n parent: angular.element(document.body),\n clickOutsideToClose: true,\n escapeToClose: true,\n templateUrl: addressbook.id + '/links',\n controller: LinksDialogController,\n controllerAs: 'links',\n locals: {\n addressbook: addressbook\n }\n });\n\n /**\n * @ngInject\n */\n LinksDialogController.$inject = ['$mdDialog', 'addressbook'];\n function LinksDialogController($mdDialog, addressbook) {\n var vm = this;\n this.addressbook = addressbook;\n this.close = close;\n\n function close() {\n $mdDialog.hide();\n }\n }\n }\n\n function showProperties(addressbook) {\n $mdDialog.show({\n templateUrl: addressbook.id + '/properties',\n controller: PropertiesDialogController,\n controllerAs: 'properties',\n clickOutsideToClose: true,\n escapeToClose: true,\n locals: {\n srcAddressBook: addressbook\n }\n }).catch(function() {\n // Do nothing\n });\n\n /**\n * @ngInject\n */\n PropertiesDialogController.$inject = ['$scope', '$mdDialog', 'srcAddressBook'];\n function PropertiesDialogController($scope, $mdDialog, srcAddressBook) {\n var vm = this;\n\n vm.addressbook = new AddressBook(srcAddressBook.$omit());\n vm.saveProperties = saveProperties;\n vm.close = close;\n\n function saveProperties() {\n vm.addressbook.$save().then(function() {\n // Refresh list instance\n srcAddressBook.init(vm.addressbook.$omit());\n $mdDialog.hide();\n });\n }\n\n function close() {\n $mdDialog.cancel();\n }\n }\n }\n\n function share(addressbook) {\n // Fetch list of ACL users\n addressbook.$acl.$users().then(function() {\n // Show ACL editor\n $mdDialog.show({\n templateUrl: addressbook.id + '/UIxAclEditor', // UI/Templates/UIxAclEditor.wox\n controller: 'AclController', // from the ng module SOGo.Common\n controllerAs: 'acl',\n clickOutsideToClose: true,\n escapeToClose: true,\n locals: {\n usersWithACL: addressbook.$acl.users,\n User: User,\n folder: addressbook\n }\n });\n });\n }\n\n /**\n * subscribeToFolder - Callback of sgSubscribe directive\n */\n function subscribeToFolder(addressbookData) {\n console.debug('subscribeToFolder ' + addressbookData.owner + addressbookData.name);\n AddressBook.$subscribe(addressbookData.owner, addressbookData.name).then(function(data) {\n $mdToast.show(\n $mdToast.simple()\n .content(l('Successfully subscribed to address book'))\n .position('top right')\n .hideDelay(3000));\n });\n }\n\n function isDroppableFolder(srcFolder, dstFolder) {\n return (dstFolder.id != srcFolder.id) && (dstFolder.isOwned || dstFolder.acls.objectCreator);\n }\n\n /**\n * @see AddressBookController._selectedCardsOperation\n */\n function dragSelectedCards(srcFolder, dstFolder, mode) {\n var dstId, allCards, cards, ids, clearCardView, promise, success;\n\n dstId = dstFolder.id;\n clearCardView = false;\n allCards = srcFolder.$selectedCards();\n if (allCards.length === 0)\n allCards = [srcFolder.$selectedCard()];\n cards = _.filter(allCards, function(card) {\n return card.$isCard();\n });\n\n if (cards.length != allCards.length)\n $mdToast.show(\n $mdToast.simple()\n .content(l(\"Lists can't be moved or copied.\"))\n .position('top right')\n .hideDelay(2000));\n\n if (cards.length) {\n if (mode == 'copy') {\n promise = srcFolder.$copyCards(cards, dstId);\n success = l('%{0} card(s) copied', cards.length);\n }\n else {\n promise = srcFolder.$moveCards(cards, dstId);\n success = l('%{0} card(s) moved', cards.length);\n // Check if currently displayed card will be moved\n ids = _.map(cards, 'id');\n clearCardView = (srcFolder.selectedCard && ids.indexOf(srcFolder.selectedCard) >= 0);\n }\n\n // Show success toast when action succeeds\n promise.then(function() {\n if (clearCardView)\n $state.go('app.addressbook');\n $mdToast.show(\n $mdToast.simple()\n .content(success)\n .position('top right')\n .hideDelay(2000));\n });\n }\n }\n\n }\n\n angular\n .module('SOGo.ContactsUI')\n .controller('AddressBooksController', AddressBooksController);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /**\n * Controller to view and edit a card\n * @ngInject\n */\n CardController.$inject = ['$scope', '$timeout', '$window', '$mdDialog', 'AddressBook', 'Card', 'Dialog', 'sgHotkeys', 'sgFocus', '$state', '$stateParams', 'stateCard'];\n function CardController($scope, $timeout, $window, $mdDialog, AddressBook, Card, Dialog, sgHotkeys, focus, $state, $stateParams, stateCard) {\n var vm = this, hotkeys = [];\n\n vm.card = stateCard;\n\n vm.currentFolder = AddressBook.selectedFolder;\n vm.allEmailTypes = Card.$EMAIL_TYPES;\n vm.allTelTypes = Card.$TEL_TYPES;\n vm.allUrlTypes = Card.$URL_TYPES;\n vm.allAddressTypes = Card.$ADDRESS_TYPES;\n vm.categories = {};\n vm.userFilterResults = [];\n vm.transformCategory = transformCategory;\n vm.addOrgUnit = addOrgUnit;\n vm.addBirthday = addBirthday;\n vm.addScreenName = addScreenName;\n vm.addEmail = addEmail;\n vm.addPhone = addPhone;\n vm.addUrl = addUrl;\n vm.addAddress = addAddress;\n vm.userFilter = userFilter;\n vm.save = save;\n vm.close = close;\n vm.reset = reset;\n vm.cancel = cancel;\n vm.confirmDelete = confirmDelete;\n vm.toggleRawSource = toggleRawSource;\n vm.showRawSource = false;\n\n\n _registerHotkeys(hotkeys);\n\n $scope.$on('$destroy', function() {\n // Deregister hotkeys\n _.forEach(hotkeys, function(key) {\n sgHotkeys.deregisterHotkey(key);\n });\n });\n\n\n function _registerHotkeys(keys) {\n keys.push(sgHotkeys.createHotkey({\n key: 'backspace',\n description: l('Delete'),\n callback: function($event) {\n if (vm.currentFolder.$selectedCount() === 0)\n confirmDelete();\n $event.preventDefault();\n }\n }));\n\n // Register the hotkeys\n _.forEach(keys, function(key) {\n sgHotkeys.registerHotkey(key);\n });\n }\n\n function transformCategory(input) {\n if (angular.isString(input))\n return { value: input };\n else\n return input;\n }\n function addOrgUnit() {\n var i = vm.card.$addOrgUnit('');\n focus('orgUnit_' + i);\n }\n function addBirthday() {\n vm.card.birthday = new Date();\n }\n function addScreenName() {\n vm.card.$addScreenName('');\n }\n function addEmail() {\n var i = vm.card.$addEmail('');\n focus('email_' + i);\n }\n function addPhone() {\n var i = vm.card.$addPhone('');\n focus('phone_' + i);\n }\n function addUrl() {\n var i = vm.card.$addUrl('', '');\n focus('url_' + i);\n }\n function addAddress() {\n var i = vm.card.$addAddress('', '', '', '', '', '', '', '');\n focus('address_' + i);\n }\n function userFilter($query, excludedCards) {\n AddressBook.selectedFolder.$filter($query, {dry: true, excludeLists: true}, excludedCards);\n return AddressBook.selectedFolder.$$cards;\n }\n function save(form) {\n if (form.$valid) {\n vm.card.$save()\n .then(function(data) {\n var i = _.indexOf(_.map(AddressBook.selectedFolder.$cards, 'id'), vm.card.id);\n if (i < 0) {\n // New card; reload contacts list and show addressbook in which the card has been created\n AddressBook.selectedFolder.$reload();\n }\n else {\n // Update contacts list with new version of the Card object\n AddressBook.selectedFolder.$cards[i] = angular.copy(vm.card);\n }\n $state.go('app.addressbook.card.view', { cardId: vm.card.id });\n });\n }\n }\n function close() {\n $state.go('app.addressbook').then(function() {\n vm.card = null;\n delete AddressBook.selectedFolder.selectedCard;\n });\n }\n function reset() {\n vm.card.$reset();\n }\n function cancel() {\n vm.card.$reset();\n if (vm.card.isNew) {\n // Cancelling the creation of a card\n vm.card = null;\n delete AddressBook.selectedFolder.selectedCard;\n $state.go('app.addressbook', { addressbookId: AddressBook.selectedFolder.id });\n }\n else {\n // Cancelling the edition of an existing card\n $state.go('app.addressbook.card.view', { cardId: vm.card.id });\n }\n }\n function confirmDelete() {\n var card = stateCard;\n\n Dialog.confirm(l('Warning'),\n l('Are you sure you want to delete the card of %{0}?', '' + card.$fullname() + ''),\n { ok: l('Delete') })\n .then(function() {\n // User confirmed the deletion\n AddressBook.selectedFolder.$deleteCards([card])\n .then(function() {\n close();\n }, function(data, status) {\n Dialog.alert(l('Warning'), l('An error occured while deleting the card \"%{0}\".',\n card.$fullname()));\n });\n });\n }\n\n function toggleRawSource($event) {\n if (!vm.showRawSource && !vm.rawSource) {\n Card.$$resource.post(vm.currentFolder.id + '/' + vm.card.id, \"raw\").then(function(data) {\n vm.rawSource = data;\n vm.showRawSource = true;\n });\n }\n else {\n vm.showRawSource = !vm.showRawSource;\n }\n }\n }\n\n angular\n .module('SOGo.ContactsUI')\n .controller('CardController', CardController);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /**\n * @name sgAddress\n * @memberof ContactsUI\n * @desc Directive to format a postal address.\n * @ngInject\n */\n function sgAddress() {\n return {\n restrict: 'A',\n scope: { data: '=sgAddress' },\n controller: ['$scope', function($scope) {\n $scope.addressLines = function(data) {\n var lines = [],\n locality_region = [];\n if (data.street) lines.push(data.street);\n if (data.street2) lines.push(data.street2);\n if (data.locality) locality_region.push(data.locality);\n if (data.region) locality_region.push(data.region);\n if (locality_region.length > 0) lines.push(locality_region.join(', '));\n if (data.country) lines.push(data.country);\n if (data.postalcode) lines.push(data.postalcode);\n return lines.join('
');\n };\n }],\n template: '
'\n };\n }\n \n angular\n .module('SOGo.Common')\n .directive('sgAddress', sgAddress);\n})();\n"]} \ No newline at end of file +{"version":3,"sources":["Contacts/Contacts.app.js","Contacts/AddressBookController.js","Contacts/AddressBooksController.js","Contacts/CardController.js","Contacts/sgAddress.directive.js"],"names":["configure","$stateProvider","$urlRouterProvider","state","url","abstract","views","addressbooks","templateUrl","controller","controllerAs","resolve","stateAddressbooks","addressbook","stateAddressbook","card","stateCard","stateNewCard","template","onEnter","onEnterCard","onExit","onExitCard","card@app.addressbook","otherwise","AddressBook","$findAll","window","contactFolders","$q","$state","$stateParams","_","find","id","addressbookId","selectedCard","$reload","reject","Card","tag","contactType","pid","c_component","$cards","cardObject","cardId","go","stateMailbox","runBlock","$rootScope","$log","$on","event","toState","toParams","fromState","fromParams","error","current","previous","rejection","angular","module","config","run","$inject","AddressBookController","$scope","$window","$timeout","$mdDialog","$mdToast","Account","focus","Dialog","Settings","sgHotkeys","_registerHotkeys","keys","push","createHotkey","key","l","description","callback","searchMode","bind","vm","newComponent","toggleCardSelection","_nextCard","_previousCard","_addNextCardToSelection","_addPreviousCardToSelection","confirmDeleteSelectedCards","forEach","registerHotkey","selectCard","$event","selectedFolder","$selectedCard","selected","mode","multiple","preventDefault","stopPropagation","type","unselectCards","index","$selectedCardIndex","isDefined","$topIndex","length","getLength","hasSelectedCard","selectedCards","$selectedCards","size","confirm","ok","then","$deleteCards","_selectedCardsOperation","operation","dstId","srcFolder","allCards","cards","ids","clearCardView","promise","success","filter","$isCard","show","simple","content","position","hideDelay","$copyCards","$moveCards","map","indexOf","copySelectedCards","folder","moveSelectedCards","selectAll","sort","field","$filter","sortedBy","$query","search","cancelSearch","newMessage","recipients","accounts","account","o","$getMailboxes","mailboxes","$newMessage","message","extend","editable","to","parent","element","document","body","targetEvent","clickOutsideToClose","escapeToClose","locals","stateAccount","stateMessage","newMessageWithRecipient","recipient","fn","newMessageWithSelectedCards","promises","$isList","expandable","refs","ref","email","$shortFormat","c_mail","all","uniq","this","hotkeys","service","deregisterHotkey","AddressBooksController","$mdMedia","$mdSidenav","FileUploader","sgConstant","User","confirmDelete","select","params","editMode","value","close","newAddressbook","prompt","name","isEditable","isRemote","owner","UserLogin","$add","edit","originalAddressbook","$omit","revertEditing","save","$rename","data","status","alert","isSubscription","$delete","catch","response","statusText","importCards","CardsImportDialogController","scope","filterByExtension","item","isTextFile","test","join","uploader","ApplicationBaseURL","autoUpload","queueLimit","filters","onSuccessItem","headers","msg","hide","imported","onErrorItem","showLinks","LinksDialogController","showProperties","PropertiesDialogController","srcAddressBook","saveProperties","$save","init","cancel","share","$acl","$users","usersWithACL","users","subscribeToFolder","addressbookData","console","debug","$subscribe","isDroppableFolder","dstFolder","isOwned","acls","objectCreator","dragSelectedCards","activeUser","CardController","currentFolder","$selectedCount","transformCategory","input","isString","addOrgUnit","i","$addOrgUnit","addBirthday","birthday","Date","addScreenName","$addScreenName","addEmail","$addEmail","addPhone","$addPhone","addUrl","$addUrl","addAddress","$addAddress","userFilter","excludedCards","minSearchLength","dry","excludeLists","$$cards","form","$valid","copy","reset","$reset","isNew","$fullname","toggleRawSource","showRawSource","rawSource","$$resource","post","allEmailTypes","$EMAIL_TYPES","allTelTypes","$TEL_TYPES","allUrlTypes","$URL_TYPES","allAddressTypes","$ADDRESS_TYPES","categories","userFilterResults","isNumber","minimumSearchLength","sgAddress","restrict","addressLines","lines","locality_region","street","street2","locality","region","country","postalcode","directive"],"mappings":"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","file":"Contacts.js","sourcesContent":["/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* JavaScript for SOGoContacts */\n\n(function() {\n 'use strict';\n\n angular.module('SOGo.ContactsUI', ['ngCookies', 'ui.router', 'angularFileUpload', 'ck', 'SOGo.Common', 'SOGo.PreferencesUI', 'SOGo.MailerUI'])\n .config(configure)\n .run(runBlock);\n\n /**\n * @ngInject\n */\n configure.$inject = ['$stateProvider', '$urlRouterProvider'];\n function configure($stateProvider, $urlRouterProvider) {\n $stateProvider\n .state('app', {\n url: '/addressbooks',\n abstract: true,\n views: {\n addressbooks: {\n templateUrl: 'UIxContactFoldersView', // UI/Templates/Contacts/UIxContactFoldersView.wox\n controller: 'AddressBooksController',\n controllerAs: 'app'\n }\n },\n resolve: {\n stateAddressbooks: stateAddressbooks\n }\n })\n .state('app.addressbook', {\n url: '/:addressbookId',\n views: {\n addressbook: {\n templateUrl: 'addressbook',\n controller: 'AddressBookController',\n controllerAs: 'addressbook'\n }\n },\n resolve: {\n stateAddressbook: stateAddressbook\n }\n })\n .state('app.addressbook.new', {\n url: '/{contactType:(?:card|list)}/new',\n views: {\n card: {\n templateUrl: 'UIxContactEditorTemplate', // UI/Templates/Contacts/UIxContactEditorTemplate.wox\n controller: 'CardController',\n controllerAs: 'editor'\n }\n },\n resolve: {\n stateCard: stateNewCard\n }\n })\n .state('app.addressbook.card', {\n url: '/:cardId',\n abstract: true,\n views: {\n card: {\n template: ''\n }\n },\n resolve: {\n stateCard: stateCard\n },\n onEnter: onEnterCard,\n onExit: onExitCard\n })\n .state('app.addressbook.card.view', {\n url: '/view',\n views: {\n 'card@app.addressbook': {\n templateUrl: 'UIxContactViewTemplate', // UI/Templates/Contacts/UIxContactViewTemplate.wox\n controller: 'CardController',\n controllerAs: 'editor'\n }\n }\n })\n .state('app.addressbook.card.editor', {\n url: '/edit',\n views: {\n 'card@app.addressbook': {\n templateUrl: 'UIxContactEditorTemplate', // UI/Templates/Contacts/UIxContactEditorTemplate.wox\n controller: 'CardController',\n controllerAs: 'editor'\n }\n }\n });\n\n // if none of the above states are matched, use this as the fallback\n $urlRouterProvider.otherwise('/addressbooks/personal');\n }\n\n /**\n * @ngInject\n */\n stateAddressbooks.$inject = ['AddressBook'];\n function stateAddressbooks(AddressBook) {\n return AddressBook.$findAll(window.contactFolders);\n }\n\n /**\n * @ngInject\n */\n stateAddressbook.$inject = ['$q', '$state', '$stateParams', 'AddressBook'];\n function stateAddressbook($q, $state, $stateParams, AddressBook) {\n var addressbook = _.find(AddressBook.$findAll(), function(addressbook) {\n return addressbook.id == $stateParams.addressbookId;\n });\n if (addressbook) {\n delete addressbook.selectedCard;\n addressbook.$reload();\n return addressbook;\n }\n return $q.reject('Addressbook ' + $stateParams.addressbookId + ' not found');\n }\n\n /**\n * @ngInject\n */\n stateNewCard.$inject = ['$stateParams', 'stateAddressbook', 'Card'];\n function stateNewCard($stateParams, stateAddressbook, Card) {\n var tag = 'v' + $stateParams.contactType,\n card = new Card({ pid: $stateParams.addressbookId, c_component: tag });\n stateAddressbook.selectedCard = true;\n return card;\n }\n\n /**\n * @ngInject\n */\n stateCard.$inject = ['$state', '$stateParams', 'stateAddressbook'];\n function stateCard($state, $stateParams, stateAddressbook) {\n var card;\n\n card = _.find(stateAddressbook.$cards, function(cardObject) {\n return (cardObject.id == $stateParams.cardId);\n });\n\n if (card) {\n return card.$reload();\n }\n else {\n // Card not found\n $state.go('app.addressbook');\n }\n }\n\n /**\n * @ngInject\n */\n onEnterCard.$inject = ['$stateParams', 'stateAddressbook'];\n function onEnterCard($stateParams, stateAddressbook) {\n stateAddressbook.selectedCard = $stateParams.cardId;\n }\n\n /**\n * @ngInject\n */\n onExitCard.$inject = ['stateAddressbook'];\n function onExitCard(stateMailbox) {\n delete stateAddressbook.selectedCard;\n }\n\n /**\n * @ngInject\n */\n runBlock.$inject = ['$rootScope', '$log', '$state'];\n function runBlock($rootScope, $log, $state) {\n $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {\n $log.error(error);\n $state.go('app.addressbook', { addressbookId: 'personal' });\n });\n $rootScope.$on('$routeChangeError', function(event, current, previous, rejection) {\n $log.error(event, current, previous, rejection);\n });\n }\n\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /**\n * @ngInject\n */\n AddressBookController.$inject = ['$scope', '$q', '$window', '$state', '$timeout', '$mdDialog', '$mdToast', 'Account', 'Card', 'AddressBook', 'sgFocus', 'Dialog', 'sgSettings', 'sgHotkeys', 'stateAddressbooks', 'stateAddressbook'];\n function AddressBookController($scope, $q, $window, $state, $timeout, $mdDialog, $mdToast, Account, Card, AddressBook, focus, Dialog, Settings, sgHotkeys, stateAddressbooks, stateAddressbook) {\n var vm = this, hotkeys = [];\n\n AddressBook.selectedFolder = stateAddressbook;\n\n vm.service = AddressBook;\n vm.selectedFolder = stateAddressbook;\n vm.selectCard = selectCard;\n vm.toggleCardSelection = toggleCardSelection;\n vm.newComponent = newComponent;\n vm.unselectCards = unselectCards;\n vm.confirmDeleteSelectedCards = confirmDeleteSelectedCards;\n vm.copySelectedCards = copySelectedCards;\n vm.moveSelectedCards = moveSelectedCards;\n vm.selectAll = selectAll;\n vm.sort = sort;\n vm.sortedBy = sortedBy;\n vm.searchMode = searchMode;\n vm.cancelSearch = cancelSearch;\n vm.newMessage = newMessage;\n vm.newMessageWithSelectedCards = newMessageWithSelectedCards;\n vm.newMessageWithRecipient = newMessageWithRecipient;\n vm.mode = { search: false, multiple: 0 };\n\n\n _registerHotkeys(hotkeys);\n\n $scope.$on('$destroy', function() {\n // Deregister hotkeys\n _.forEach(hotkeys, function(key) {\n sgHotkeys.deregisterHotkey(key);\n });\n });\n\n\n function _registerHotkeys(keys) {\n keys.push(sgHotkeys.createHotkey({\n key: l('hotkey_search'),\n description: l('Search'),\n callback: searchMode\n }));\n keys.push(sgHotkeys.createHotkey({\n key: l('key_create_card'),\n description: l('Create a new address book card'),\n callback: angular.bind(vm, newComponent, 'card')\n }));\n keys.push(sgHotkeys.createHotkey({\n key: l('key_create_list'),\n description: l('Create a new list'),\n callback: angular.bind(vm, newComponent, 'list')\n }));\n keys.push(sgHotkeys.createHotkey({\n key: 'space',\n description: l('Toggle item'),\n callback: toggleCardSelection\n }));\n keys.push(sgHotkeys.createHotkey({\n key: 'up',\n description: l('View next item'),\n callback: _nextCard\n }));\n keys.push(sgHotkeys.createHotkey({\n key: 'down',\n description: l('View previous item'),\n callback: _previousCard\n }));\n keys.push(sgHotkeys.createHotkey({\n key: 'shift+up',\n description: l('Add next item to selection'),\n callback: _addNextCardToSelection\n }));\n keys.push(sgHotkeys.createHotkey({\n key: 'shift+down',\n description: l('Add previous item to selection'),\n callback: _addPreviousCardToSelection\n }));\n keys.push(sgHotkeys.createHotkey({\n key: 'backspace',\n description: l('Delete selected card or address book'),\n callback: confirmDeleteSelectedCards\n }));\n\n // Register the hotkeys\n _.forEach(keys, function(key) {\n sgHotkeys.registerHotkey(key);\n });\n }\n\n function selectCard(card) {\n $state.go('app.addressbook.card.view', {cardId: card.id});\n }\n\n function toggleCardSelection($event, card) {\n if (!card) card = vm.selectedFolder.$selectedCard();\n card.selected = !card.selected;\n vm.mode.multiple += card.selected? 1 : -1;\n $event.preventDefault();\n $event.stopPropagation();\n }\n\n function newComponent(type) {\n $state.go('app.addressbook.new', { contactType: type });\n }\n\n function unselectCards() {\n _.forEach(vm.selectedFolder.$cards, function(card) {\n card.selected = false;\n });\n vm.mode.multiple = 0;\n }\n\n /**\n * User has pressed up arrow key\n */\n function _nextCard($event) {\n var index = vm.selectedFolder.$selectedCardIndex();\n\n if (angular.isDefined(index)) {\n index--;\n if (vm.selectedFolder.$topIndex > 0)\n vm.selectedFolder.$topIndex--;\n }\n else {\n // No message is selected, show oldest message\n index = vm.selectedFolder.$cards.length() - 1;\n vm.selectedFolder.$topIndex = vm.selectedFolder.getLength();\n }\n\n if (index > -1)\n selectCard(vm.selectedFolder.$cards[index]);\n\n $event.preventDefault();\n\n return index;\n }\n\n /**\n * User has pressed the down arrow key\n */\n function _previousCard($event) {\n var index = vm.selectedFolder.$selectedCardIndex();\n\n if (angular.isDefined(index)) {\n index++;\n if (vm.selectedFolder.$topIndex < vm.selectedFolder.$cards.length)\n vm.selectedFolder.$topIndex++;\n }\n else\n // No message is selected, show newest\n index = 0;\n\n if (index < vm.selectedFolder.$cards.length)\n selectCard(vm.selectedFolder.$cards[index]);\n else\n index = -1;\n\n $event.preventDefault();\n\n return index;\n }\n\n function _addNextCardToSelection($event) {\n var index;\n\n if (vm.selectedFolder.hasSelectedCard()) {\n index = _nextCard($event);\n if (index >= 0)\n toggleCardSelection($event, vm.selectedFolder.$cards[index]);\n }\n }\n\n function _addPreviousCardToSelection($event) {\n var index;\n\n if (vm.selectedFolder.hasSelectedCard()) {\n index = _previousCard($event);\n if (index >= 0)\n toggleCardSelection($event, vm.selectedFolder.$cards[index]);\n }\n }\n\n function confirmDeleteSelectedCards($event) {\n var selectedCards = vm.selectedFolder.$selectedCards();\n\n if (_.size(selectedCards) > 0)\n Dialog.confirm(l('Warning'),\n l('Are you sure you want to delete the selected contacts?'),\n { ok: l('Delete') })\n .then(function() {\n // User confirmed the deletion\n vm.selectedFolder.$deleteCards(selectedCards).then(function() {\n vm.mode.multiple = 0;\n if (!vm.selectedFolder.selectedCard)\n $state.go('app.addressbook');\n });\n });\n\n $event.preventDefault();\n }\n\n /**\n * @see AddressBooksController.dragSelectedCards\n */\n function _selectedCardsOperation(operation, dstId) {\n var srcFolder, allCards, cards, ids, clearCardView, promise, success;\n\n srcFolder = vm.selectedFolder;\n clearCardView = false;\n allCards = srcFolder.$selectedCards();\n cards = _.filter(allCards, function(card) {\n return card.$isCard();\n });\n\n if (cards.length != allCards.length)\n $mdToast.show(\n $mdToast.simple()\n .content(l(\"Lists can't be moved or copied.\"))\n .position('top right')\n .hideDelay(2000));\n\n if (cards.length) {\n if (operation == 'copy') {\n promise = srcFolder.$copyCards(cards, dstId);\n success = l('%{0} card(s) copied', cards.length);\n }\n else {\n promise = srcFolder.$moveCards(cards, dstId);\n success = l('%{0} card(s) moved', cards.length);\n // Check if currently displayed card will be moved\n ids = _.map(cards, 'id');\n clearCardView = (srcFolder.selectedCard && ids.indexOf(srcFolder.selectedCard) >= 0);\n }\n\n // Show success toast when action succeeds\n promise.then(function() {\n if (clearCardView)\n $state.go('app.addressbook');\n $mdToast.show(\n $mdToast.simple()\n .content(success)\n .position('top right')\n .hideDelay(2000));\n });\n }\n }\n\n function copySelectedCards(folder) {\n _selectedCardsOperation('copy', folder);\n }\n\n function moveSelectedCards(folder) {\n _selectedCardsOperation('move', folder);\n }\n\n function selectAll() {\n _.forEach(vm.selectedFolder.$cards, function(card) {\n card.selected = true;\n });\n vm.mode.multiple = vm.selectedFolder.$cards.length;\n }\n\n function sort(field) {\n vm.selectedFolder.$filter('', { sort: field });\n }\n\n function sortedBy(field) {\n return AddressBook.$query.sort == field;\n }\n\n function searchMode() {\n vm.mode.search = true;\n focus('search');\n }\n\n function cancelSearch() {\n vm.mode.search = false;\n vm.selectedFolder.$filter('');\n }\n\n function newMessage($event, recipients) {\n Account.$findAll().then(function(accounts) {\n var account = _.find(accounts, function(o) {\n if (o.id === 0)\n return o;\n });\n\n // We must initialize the Account with its mailbox\n // list before proceeding with message's creation\n account.$getMailboxes().then(function(mailboxes) {\n account.$newMessage().then(function(message) {\n angular.extend(message.editable, { to: recipients });\n $mdDialog.show({\n parent: angular.element(document.body),\n targetEvent: $event,\n clickOutsideToClose: false,\n escapeToClose: false,\n templateUrl: '../Mail/UIxMailEditor',\n controller: 'MessageEditorController',\n controllerAs: 'editor',\n locals: {\n stateAccount: account,\n stateMessage: message\n }\n });\n });\n });\n });\n }\n\n function newMessageWithRecipient($event, recipient, fn) {\n var recipients = [fn + ' <' + recipient + '>'];\n vm.newMessage($event, recipients);\n $event.stopPropagation();\n $event.preventDefault();\n }\n\n function newMessageWithSelectedCards($event) {\n var selectedCards = _.filter(vm.selectedFolder.$cards, function(card) { return card.selected; });\n var promises = [], recipients = [];\n\n _.forEach(selectedCards, function(card) {\n if (card.$isList({expandable: true})) {\n // If the list's members were already fetch, use them\n if (angular.isDefined(card.refs) && card.refs.length) {\n _.forEach(card.refs, function(ref) {\n if (ref.email.length)\n recipients.push(ref.$shortFormat());\n });\n }\n else {\n promises.push(card.$reload().then(function(card) {\n _.forEach(card.refs, function(ref) {\n if (ref.email.length)\n recipients.push(ref.$shortFormat());\n });\n }));\n }\n }\n else if (card.c_mail.length) {\n recipients.push(card.$shortFormat());\n }\n });\n\n $q.all(promises).then(function() {\n recipients = _.uniq(recipients);\n if (recipients.length)\n vm.newMessage($event, recipients);\n });\n }\n }\n\n angular\n .module('SOGo.ContactsUI')\n .controller('AddressBookController', AddressBookController);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /**\n * @ngInject\n */\n AddressBooksController.$inject = ['$state', '$scope', '$rootScope', '$stateParams', '$timeout', '$window', '$mdDialog', '$mdToast', '$mdMedia', '$mdSidenav', 'FileUploader', 'sgConstant', 'sgHotkeys', 'sgFocus', 'Card', 'AddressBook', 'Dialog', 'sgSettings', 'User', 'stateAddressbooks'];\n function AddressBooksController($state, $scope, $rootScope, $stateParams, $timeout, $window, $mdDialog, $mdToast, $mdMedia, $mdSidenav, FileUploader, sgConstant, sgHotkeys, focus, Card, AddressBook, Dialog, Settings, User, stateAddressbooks) {\n var vm = this, hotkeys = [];\n\n vm.activeUser = Settings.activeUser;\n vm.service = AddressBook;\n vm.select = select;\n vm.newAddressbook = newAddressbook;\n vm.edit = edit;\n vm.revertEditing = revertEditing;\n vm.save = save;\n vm.confirmDelete = confirmDelete;\n vm.importCards = importCards;\n vm.showLinks = showLinks;\n vm.showProperties = showProperties;\n vm.share = share;\n vm.subscribeToFolder = subscribeToFolder;\n vm.isDroppableFolder = isDroppableFolder;\n vm.dragSelectedCards = dragSelectedCards;\n\n\n _registerHotkeys(hotkeys);\n\n $scope.$on('$destroy', function() {\n // Deregister hotkeys\n _.forEach(hotkeys, function(key) {\n sgHotkeys.deregisterHotkey(key);\n });\n });\n\n\n function _registerHotkeys(keys) {\n keys.push(sgHotkeys.createHotkey({\n key: 'backspace',\n description: l('Delete selected card or address book'),\n callback: function() {\n if (AddressBook.selectedFolder && !AddressBook.selectedFolder.hasSelectedCard())\n confirmDelete();\n }\n }));\n\n // Register the hotkeys\n _.forEach(keys, function(key) {\n sgHotkeys.registerHotkey(key);\n });\n }\n\n function select($event, folder) {\n if ($state.params.addressbookId != folder.id &&\n vm.editMode != folder.id) {\n vm.editMode = false;\n AddressBook.$query.value = '';\n // Close sidenav on small devices\n if (!$mdMedia(sgConstant['gt-md']))\n $mdSidenav('left').close();\n $state.go('app.addressbook', {addressbookId: folder.id});\n }\n else {\n $event.preventDefault();\n $event.stopPropagation();\n }\n }\n\n function newAddressbook() {\n Dialog.prompt(l('New addressbook'),\n l('Name of new addressbook'))\n .then(function(name) {\n var addressbook = new AddressBook(\n {\n name: name,\n isEditable: true,\n isRemote: false,\n owner: UserLogin\n }\n );\n AddressBook.$add(addressbook);\n });\n }\n\n function edit(folder) {\n if (!folder.isRemote) {\n vm.editMode = folder.id;\n vm.originalAddressbook = angular.extend({}, folder.$omit());\n focus('addressBookName_' + folder.id);\n }\n }\n\n function revertEditing(folder) {\n folder.name = vm.originalAddressbook.name;\n vm.editMode = false;\n }\n\n function save(folder) {\n var name = folder.name;\n if (name && name.length > 0 && name != vm.originalAddressbook.name) {\n folder.$rename(name)\n .then(function(data) {\n vm.editMode = false;\n }, function(data, status) {\n Dialog.alert(l('Warning'), data);\n });\n }\n }\n\n function confirmDelete() {\n if (vm.service.selectedFolder.isSubscription) {\n // Unsubscribe without confirmation\n vm.service.selectedFolder.$delete()\n .then(function() {\n vm.service.selectedFolder = null;\n $state.go('app.addressbook', { addressbookId: 'personal' });\n }, function(data, status) {\n Dialog.alert(l('An error occured while deleting the addressbook \"%{0}\".',\n vm.service.selectedFolder.name),\n l(data.error));\n });\n }\n else {\n Dialog.confirm(l('Warning'), l('Are you sure you want to delete the addressbook \"%{0}\"?',\n vm.service.selectedFolder.name),\n { ok: l('Delete') })\n .then(function() {\n return vm.service.selectedFolder.$delete();\n })\n .then(function() {\n vm.service.selectedFolder = null;\n $state.go('app.addressbook', { addressbookId: 'personal' });\n return true;\n })\n .catch(function(response) {\n if (response) {\n var message = response.data.message || response.statusText;\n Dialog.alert(l('An error occured while deleting the addressbook \"%{0}\".',\n vm.service.selectedFolder.name),\n message);\n }\n });\n }\n }\n\n function importCards($event, folder) {\n $mdDialog.show({\n parent: angular.element(document.body),\n targetEvent: $event,\n clickOutsideToClose: true,\n escapeToClose: true,\n templateUrl: 'UIxContactsImportDialog',\n controller: CardsImportDialogController,\n controllerAs: '$CardsImportDialogController',\n locals: {\n folder: folder\n }\n });\n\n /**\n * @ngInject\n */\n CardsImportDialogController.$inject = ['scope', '$mdDialog', 'folder'];\n function CardsImportDialogController(scope, $mdDialog, folder) {\n var vm = this;\n\n vm.uploader = new FileUploader({\n url: ApplicationBaseURL + [folder.id, 'import'].join('/'),\n autoUpload: true,\n queueLimit: 1,\n filters: [{ name: filterByExtension, fn: filterByExtension }],\n onSuccessItem: function(item, response, status, headers) {\n var msg;\n\n $mdDialog.hide();\n\n if (response.imported === 0)\n msg = l('No card was imported.');\n else {\n msg = l('A total of %{0} cards were imported in the addressbook.', response.imported);\n AddressBook.selectedFolder.$reload();\n }\n\n $mdToast.show(\n $mdToast.simple()\n .content(msg)\n .position('top right')\n .hideDelay(3000));\n },\n onErrorItem: function(item, response, status, headers) {\n $mdToast.show({\n template: [\n '',\n '
',\n ' error_outline',\n ' ' + l('An error occured while importing contacts.') + '',\n '
',\n '
'\n ].join(''),\n position: 'top right',\n hideDelay: 3000\n });\n }\n });\n\n vm.close = function() {\n $mdDialog.hide();\n };\n\n function filterByExtension(item) {\n var isTextFile = item.type.indexOf('text') === 0 ||\n /\\.(ldif|vcf|vcard)$/.test(item.name);\n\n if (!isTextFile)\n $mdToast.show({\n template: [\n '',\n '
',\n ' error_outline',\n ' ' + l('Select a vCard or LDIF file.') + '',\n '
',\n '
'\n ].join(''),\n position: 'top right',\n hideDelay: 3000\n });\n\n return isTextFile;\n }\n }\n }\n\n function showLinks(addressbook) {\n $mdDialog.show({\n parent: angular.element(document.body),\n clickOutsideToClose: true,\n escapeToClose: true,\n templateUrl: addressbook.id + '/links',\n controller: LinksDialogController,\n controllerAs: 'links',\n locals: {\n addressbook: addressbook\n }\n });\n\n /**\n * @ngInject\n */\n LinksDialogController.$inject = ['$mdDialog', 'addressbook'];\n function LinksDialogController($mdDialog, addressbook) {\n var vm = this;\n this.addressbook = addressbook;\n this.close = close;\n\n function close() {\n $mdDialog.hide();\n }\n }\n }\n\n function showProperties(addressbook) {\n $mdDialog.show({\n templateUrl: addressbook.id + '/properties',\n controller: PropertiesDialogController,\n controllerAs: 'properties',\n clickOutsideToClose: true,\n escapeToClose: true,\n locals: {\n srcAddressBook: addressbook\n }\n }).catch(function() {\n // Do nothing\n });\n\n /**\n * @ngInject\n */\n PropertiesDialogController.$inject = ['$scope', '$mdDialog', 'srcAddressBook'];\n function PropertiesDialogController($scope, $mdDialog, srcAddressBook) {\n var vm = this;\n\n vm.addressbook = new AddressBook(srcAddressBook.$omit());\n vm.saveProperties = saveProperties;\n vm.close = close;\n\n function saveProperties() {\n vm.addressbook.$save().then(function() {\n // Refresh list instance\n srcAddressBook.init(vm.addressbook.$omit());\n $mdDialog.hide();\n });\n }\n\n function close() {\n $mdDialog.cancel();\n }\n }\n }\n\n function share(addressbook) {\n // Fetch list of ACL users\n addressbook.$acl.$users().then(function() {\n // Show ACL editor\n $mdDialog.show({\n templateUrl: addressbook.id + '/UIxAclEditor', // UI/Templates/UIxAclEditor.wox\n controller: 'AclController', // from the ng module SOGo.Common\n controllerAs: 'acl',\n clickOutsideToClose: true,\n escapeToClose: true,\n locals: {\n usersWithACL: addressbook.$acl.users,\n User: User,\n folder: addressbook\n }\n });\n });\n }\n\n /**\n * subscribeToFolder - Callback of sgSubscribe directive\n */\n function subscribeToFolder(addressbookData) {\n console.debug('subscribeToFolder ' + addressbookData.owner + addressbookData.name);\n AddressBook.$subscribe(addressbookData.owner, addressbookData.name).then(function(data) {\n $mdToast.show(\n $mdToast.simple()\n .content(l('Successfully subscribed to address book'))\n .position('top right')\n .hideDelay(3000));\n });\n }\n\n function isDroppableFolder(srcFolder, dstFolder) {\n return (dstFolder.id != srcFolder.id) && (dstFolder.isOwned || dstFolder.acls.objectCreator);\n }\n\n /**\n * @see AddressBookController._selectedCardsOperation\n */\n function dragSelectedCards(srcFolder, dstFolder, mode) {\n var dstId, allCards, cards, ids, clearCardView, promise, success;\n\n dstId = dstFolder.id;\n clearCardView = false;\n allCards = srcFolder.$selectedCards();\n if (allCards.length === 0)\n allCards = [srcFolder.$selectedCard()];\n cards = _.filter(allCards, function(card) {\n return card.$isCard();\n });\n\n if (cards.length != allCards.length)\n $mdToast.show(\n $mdToast.simple()\n .content(l(\"Lists can't be moved or copied.\"))\n .position('top right')\n .hideDelay(2000));\n\n if (cards.length) {\n if (mode == 'copy') {\n promise = srcFolder.$copyCards(cards, dstId);\n success = l('%{0} card(s) copied', cards.length);\n }\n else {\n promise = srcFolder.$moveCards(cards, dstId);\n success = l('%{0} card(s) moved', cards.length);\n // Check if currently displayed card will be moved\n ids = _.map(cards, 'id');\n clearCardView = (srcFolder.selectedCard && ids.indexOf(srcFolder.selectedCard) >= 0);\n }\n\n // Show success toast when action succeeds\n promise.then(function() {\n if (clearCardView)\n $state.go('app.addressbook');\n $mdToast.show(\n $mdToast.simple()\n .content(success)\n .position('top right')\n .hideDelay(2000));\n });\n }\n }\n\n }\n\n angular\n .module('SOGo.ContactsUI')\n .controller('AddressBooksController', AddressBooksController);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /**\n * Controller to view and edit a card\n * @ngInject\n */\n CardController.$inject = ['$scope', '$timeout', '$window', '$mdDialog', 'AddressBook', 'Card', 'Dialog', 'sgHotkeys', 'sgFocus', '$state', '$stateParams', 'stateCard'];\n function CardController($scope, $timeout, $window, $mdDialog, AddressBook, Card, Dialog, sgHotkeys, focus, $state, $stateParams, stateCard) {\n var vm = this, hotkeys = [], minSearchLength;\n\n vm.card = stateCard;\n\n vm.currentFolder = AddressBook.selectedFolder;\n vm.allEmailTypes = Card.$EMAIL_TYPES;\n vm.allTelTypes = Card.$TEL_TYPES;\n vm.allUrlTypes = Card.$URL_TYPES;\n vm.allAddressTypes = Card.$ADDRESS_TYPES;\n vm.categories = {};\n vm.userFilterResults = [];\n vm.transformCategory = transformCategory;\n vm.addOrgUnit = addOrgUnit;\n vm.addBirthday = addBirthday;\n vm.addScreenName = addScreenName;\n vm.addEmail = addEmail;\n vm.addPhone = addPhone;\n vm.addUrl = addUrl;\n vm.addAddress = addAddress;\n vm.userFilter = userFilter;\n vm.save = save;\n vm.close = close;\n vm.reset = reset;\n vm.cancel = cancel;\n vm.confirmDelete = confirmDelete;\n vm.toggleRawSource = toggleRawSource;\n vm.showRawSource = false;\n\n minSearchLength = angular.isNumber($window.minimumSearchLength)? $window.minimumSearchLength : 2;\n\n\n _registerHotkeys(hotkeys);\n\n $scope.$on('$destroy', function() {\n // Deregister hotkeys\n _.forEach(hotkeys, function(key) {\n sgHotkeys.deregisterHotkey(key);\n });\n });\n\n\n function _registerHotkeys(keys) {\n keys.push(sgHotkeys.createHotkey({\n key: 'backspace',\n description: l('Delete'),\n callback: function($event) {\n if (vm.currentFolder.$selectedCount() === 0)\n confirmDelete();\n $event.preventDefault();\n }\n }));\n\n // Register the hotkeys\n _.forEach(keys, function(key) {\n sgHotkeys.registerHotkey(key);\n });\n }\n\n function transformCategory(input) {\n if (angular.isString(input))\n return { value: input };\n else\n return input;\n }\n function addOrgUnit() {\n var i = vm.card.$addOrgUnit('');\n focus('orgUnit_' + i);\n }\n function addBirthday() {\n vm.card.birthday = new Date();\n }\n function addScreenName() {\n vm.card.$addScreenName('');\n }\n function addEmail() {\n var i = vm.card.$addEmail('');\n focus('email_' + i);\n }\n function addPhone() {\n var i = vm.card.$addPhone('');\n focus('phone_' + i);\n }\n function addUrl() {\n var i = vm.card.$addUrl('', '');\n focus('url_' + i);\n }\n function addAddress() {\n var i = vm.card.$addAddress('', '', '', '', '', '', '', '');\n focus('address_' + i);\n }\n function userFilter($query, excludedCards) {\n if ($query.length < minSearchLength)\n return [];\n\n AddressBook.selectedFolder.$filter($query, {dry: true, excludeLists: true}, excludedCards);\n return AddressBook.selectedFolder.$$cards;\n }\n function save(form) {\n if (form.$valid) {\n vm.card.$save()\n .then(function(data) {\n var i = _.indexOf(_.map(AddressBook.selectedFolder.$cards, 'id'), vm.card.id);\n if (i < 0) {\n // New card; reload contacts list and show addressbook in which the card has been created\n AddressBook.selectedFolder.$reload();\n }\n else {\n // Update contacts list with new version of the Card object\n AddressBook.selectedFolder.$cards[i] = angular.copy(vm.card);\n }\n $state.go('app.addressbook.card.view', { cardId: vm.card.id });\n });\n }\n }\n function close() {\n $state.go('app.addressbook').then(function() {\n vm.card = null;\n delete AddressBook.selectedFolder.selectedCard;\n });\n }\n function reset() {\n vm.card.$reset();\n }\n function cancel() {\n vm.card.$reset();\n if (vm.card.isNew) {\n // Cancelling the creation of a card\n vm.card = null;\n delete AddressBook.selectedFolder.selectedCard;\n $state.go('app.addressbook', { addressbookId: AddressBook.selectedFolder.id });\n }\n else {\n // Cancelling the edition of an existing card\n $state.go('app.addressbook.card.view', { cardId: vm.card.id });\n }\n }\n function confirmDelete() {\n var card = stateCard;\n\n Dialog.confirm(l('Warning'),\n l('Are you sure you want to delete the card of %{0}?', '' + card.$fullname() + ''),\n { ok: l('Delete') })\n .then(function() {\n // User confirmed the deletion\n AddressBook.selectedFolder.$deleteCards([card])\n .then(function() {\n close();\n }, function(data, status) {\n Dialog.alert(l('Warning'), l('An error occured while deleting the card \"%{0}\".',\n card.$fullname()));\n });\n });\n }\n\n function toggleRawSource($event) {\n if (!vm.showRawSource && !vm.rawSource) {\n Card.$$resource.post(vm.currentFolder.id + '/' + vm.card.id, \"raw\").then(function(data) {\n vm.rawSource = data;\n vm.showRawSource = true;\n });\n }\n else {\n vm.showRawSource = !vm.showRawSource;\n }\n }\n }\n\n angular\n .module('SOGo.ContactsUI')\n .controller('CardController', CardController);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /**\n * @name sgAddress\n * @memberof ContactsUI\n * @desc Directive to format a postal address.\n * @ngInject\n */\n function sgAddress() {\n return {\n restrict: 'A',\n scope: { data: '=sgAddress' },\n controller: ['$scope', function($scope) {\n $scope.addressLines = function(data) {\n var lines = [],\n locality_region = [];\n if (data.street) lines.push(data.street);\n if (data.street2) lines.push(data.street2);\n if (data.locality) locality_region.push(data.locality);\n if (data.region) locality_region.push(data.region);\n if (locality_region.length > 0) lines.push(locality_region.join(', '));\n if (data.country) lines.push(data.country);\n if (data.postalcode) lines.push(data.postalcode);\n return lines.join('
');\n };\n }],\n template: '
'\n };\n }\n \n angular\n .module('SOGo.Common')\n .directive('sgAddress', sgAddress);\n})();\n"]} \ No newline at end of file diff --git a/UI/WebServerResources/js/Preferences.js b/UI/WebServerResources/js/Preferences.js index 9b1a579bb..fa3fe3f92 100644 --- a/UI/WebServerResources/js/Preferences.js +++ b/UI/WebServerResources/js/Preferences.js @@ -1,2 +1,2 @@ -!function(){"use strict";function a(a,c){a.state("preferences",{abstract:!0,views:{preferences:{templateUrl:"preferences.html",controller:"PreferencesController",controllerAs:"app"}},resolve:{statePreferences:b}}).state("preferences.general",{url:"/general",views:{module:{templateUrl:"generalPreferences.html"}}}).state("preferences.calendars",{url:"/calendars",views:{module:{templateUrl:"calendarsPreferences.html"}}}).state("preferences.addressbooks",{url:"/addressbooks",views:{module:{templateUrl:"addressbooksPreferences.html"}}}).state("preferences.mailer",{url:"/mailer",views:{module:{templateUrl:"mailerPreferences.html"}}}),c.otherwise("/general")}function b(a){return a}function c(a){a.$on("$routeChangeError",function(a,b,c,d){console.error(a,b,c,d)})}angular.module("SOGo.PreferencesUI",["ui.router","ck","SOGo.Common","SOGo.MailerUI","SOGo.ContactsUI","SOGo.Authentication","as.sortable"]).config(a).run(c),a.$inject=["$stateProvider","$urlRouterProvider"],b.$inject=["Preferences"],c.$inject=["$rootScope"]}(),function(){"use strict";function a(a,b,c,d,e){function f(){return!(d>0)&&!e}function g(){a.cancel()}function h(){a.hide()}var i=this;i.defaults=b,i.account=c,i.accountId=d,i.customFromIsReadonly=f,i.cancel=g,i.save=h}a.$inject=["$mdDialog","defaults","account","accountId","mailCustomFromEnabled"],angular.module("SOGo.PreferencesUI").controller("AccountDialogController",a)}(),function(){"use strict";function a(a,b,c,d,e,f){function g(){c.cancel()}function h(){return o.filter.rules&&o.filter.rules.length>0&&o.filter.actions&&o.filter.actions.length>0}function i(a){c.hide()}function j(a){o.filter.rules||(o.filter.rules=[]),o.filter.rules.push({field:"subject",operator:"contains"})}function k(a){o.filter.rules.splice(a,1)}function m(a){o.filter.actions||(o.filter.actions=[]),o.filter.actions.push({method:"discard"})}function n(a){o.filter.actions.splice(a,1)}var o=this,p=b.sieveCapabilities,q=b.forwardEnabled;b.vacationEnabled;o.filter=d,o.mailboxes=e,o.labels=f,o.cancel=g,o.hasRulesAndActions=h,o.save=i,o.addMailFilterRule=j,o.removeMailFilterRule=k,o.addMailFilterAction=m,o.removeMailFilterAction=n,o.fieldLabels={subject:l("Subject"),from:l("From"),to:l("To"),cc:l("Cc"),to_or_cc:l("To or Cc"),size:l("Size (Kb)"),header:l("Header")},p.indexOf("body")>-1&&(o.fieldLabels.body=l("Body")),o.methodLabels={discard:l("Discard the message"),keep:l("Keep the message"),stop:l("Stop processing filter rules")},q&&(o.methodLabels.redirect=l("Forward the message to")),p.indexOf("reject")>-1&&(o.methodLabels.reject=l("Send a reject message")),p.indexOf("fileinto")>-1&&(o.methodLabels.fileinto=l("File the message in")),(p.indexOf("imapflags")>-1||p.indexOf("imap4flags")>-1)&&(o.methodLabels.addflag=l("Flag the message with")),o.numberOperatorLabels={under:l("is under"),over:l("is over")},o.textOperatorLabels={is:l("is"),is_not:l("is not"),contains:l("contains"),contains_not:l("does not contain"),matches:l("matches"),matches_not:l("does not match")},p.indexOf("regex")>-1&&(o.textOperatorLabels.regex=l("matches regex"),o.textOperatorLabels.regex_not=l("does not match regex")),o.flagLabels={seen:l("Seen"),deleted:l("Deleted"),answered:l("Answered"),flagged:l("Flagged"),junk:l("Junk"),not_junk:l("Not Junk")}}a.$inject=["$scope","$window","$mdDialog","filter","mailboxes","labels"],angular.module("SOGo.PreferencesUI").controller("FiltersDialogController",a)}(),function(){"use strict";function a(a,b,c,d,e,f,g,h,i,j,k,m,n){function o(a,b){b.$valid&&(d("xs")&&e("left").close(),c.go("preferences."+a))}function p(a){i.confirm(l("Warning"),l("Save preferences and reload page now?"),{ok:l("Yes"),cancel:l("No")}).then(function(){F(a,{quick:!0}).then(function(){b.location.reload(!0)})})}function q(a){K.preferences.defaults.SOGoCalendarCategoriesColors["New category"]="#aaa",K.preferences.defaults.SOGoCalendarCategories.push("New category"),h("calendarCategory_"+(K.preferences.defaults.SOGoCalendarCategories.length-1)),a.$setDirty()}function r(a,b){var c=K.preferences.defaults.SOGoCalendarCategories[a];K.preferences.defaults.SOGoCalendarCategories.splice(a,1),delete K.preferences.defaults.SOGoCalendarCategoriesColors[c],b.$setDirty()}function s(a){K.preferences.defaults.SOGoContactsCategories.push(""),h("contactCategory_"+(K.preferences.defaults.SOGoContactsCategories.length-1)),a.$setDirty()}function t(a,b){K.preferences.defaults.SOGoContactsCategories.splice(a,1),b.$setDirty()}function u(a,b){var c;K.preferences.defaults.AuxiliaryMailAccounts.push({}),c=_.last(K.preferences.defaults.AuxiliaryMailAccounts),c.name=l("New account"),c.identities=[{fullName:"",email:""}],c.receipts={receiptAction:"ignore",receiptNonRecipientAction:"ignore",receiptOutsideDomainAction:"ignore",receiptAnyAction:"ignore"},f.show({controller:"AccountDialogController",controllerAs:"$AccountDialogController",templateUrl:"editAccount?account=new",targetEvent:a,locals:{defaults:K.preferences.defaults,account:c,accountId:K.preferences.defaults.AuxiliaryMailAccounts.length-1,mailCustomFromEnabled:window.mailCustomFromEnabled}}).then(function(){b.$setDirty()})}function v(a,b,c){var d=K.preferences.defaults.AuxiliaryMailAccounts[b];f.show({controller:"AccountDialogController",controllerAs:"$AccountDialogController",templateUrl:"editAccount?account="+b,targetEvent:a,locals:{defaults:K.preferences.defaults,account:d,accountId:b,mailCustomFromEnabled:window.mailCustomFromEnabled}}).then(function(){K.preferences.defaults.AuxiliaryMailAccounts[b]=d,c.$setDirty()})}function w(a,b){K.preferences.defaults.AuxiliaryMailAccounts.splice(a,1),b.$setDirty()}function x(a){var b="_$$"+guid();K.preferences.defaults.SOGoMailLabelsColors[b]=["New label","#aaa"],a.$setDirty()}function y(a,b){delete K.preferences.defaults.SOGoMailLabelsColors[a],b.$setDirty()}function z(a,b){var c={match:"all"};f.show({templateUrl:"editFilter?filter=new",controller:"FiltersDialogController",controllerAs:"filterEditor",targetEvent:a,locals:{filter:c,mailboxes:L,labels:K.preferences.defaults.SOGoMailLabelsColors}}).then(function(){K.preferences.defaults.SOGoSieveFilters||(K.preferences.defaults.SOGoSieveFilters=[]),K.preferences.defaults.SOGoSieveFilters.push(c),b.$setDirty()})}function A(a,b,c){var d=angular.copy(K.preferences.defaults.SOGoSieveFilters[b]);f.show({templateUrl:"editFilter?filter="+b,controller:"FiltersDialogController",controllerAs:"filterEditor",targetEvent:null,locals:{filter:d,mailboxes:L,labels:K.preferences.defaults.SOGoMailLabelsColors}}).then(function(){K.preferences.defaults.SOGoSieveFilters[b]=d,c.$setDirty()})}function B(a,b){K.preferences.defaults.SOGoSieveFilters.splice(a,1),b.$setDirty()}function C(a){var b=[];angular.isDefined(K.preferences.defaults.Vacation.autoReplyEmailAddresses)&&(b=K.preferences.defaults.Vacation.autoReplyEmailAddresses.split(",")),K.preferences.defaults.Vacation.autoReplyEmailAddresses=_.union(window.defaultEmailAddresses.split(","),b).join(","),a.$setDirty()}function D(a,b){return j.$filter(a,b).then(function(a){return _.forEach(a,function(a){a.$$image||(a.image?a.$$image=a.image:K.preferences.avatar(a.c_email,32,{no_404:!0}).then(function(b){a.$$image=b}))}),a})}function E(a,c){var d;if(c.$dirty){for(a.preventDefault(),a.stopPropagation(),d=a.target;"A"!=d.tagName;)d=d.parentNode;i.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(){F(c,{quick:!0}).then(function(){b.location=d.href})},function(){b.location=d.href})}}function F(b,c){var d,e,f,h,j,k;if(e=!0,j=[],window.forwardConstraints>0&&angular.isDefined(K.preferences.defaults.Forward)&&K.preferences.defaults.Forward.enabled&&angular.isDefined(K.preferences.defaults.Forward.forwardAddress))for(f=K.preferences.defaults.Forward.forwardAddress.split(","),h=window.defaultEmailAddresses.split(/, */),_.forEach(h,function(a){var b=a.split("@")[1];b&&j.push(b.toLowerCase())}),d=0;d=0&&2==window.forwardConstraints&&(i.alert(l("Error"),l("You are not allowed to forward your messages to an internal email address.")),e=!1);return e?K.preferences.$save().then(function(a){c&&c.quick||(g.show(g.simple().content(l("Preferences saved")).position("bottom right").hideDelay(2e3)),b.$setPristine())}):a.reject()}function G(){return!!(K.passwords.newPassword&&K.passwords.newPassword.length>0&&K.passwords.newPasswordConfirmation&&K.passwords.newPasswordConfirmation.length&&K.passwords.newPassword==K.passwords.newPasswordConfirmation)}function H(){n.changePassword(K.passwords.newPassword).then(function(){var a=f.alert({title:l("Password"),content:l("The password was changed successfully."),ok:l("OK")});f.show(a).finally(function(){a=void 0})},function(a){var b=f.alert({title:l("Password"),content:a,ok:l("OK")});f.show(b).finally(function(){b=void 0})})}function I(a){return _.filter(K.timeZonesList,function(b){return b.toUpperCase().indexOf(a.toUpperCase())>=0})}var J,K=this,L=[];K.preferences=m,K.passwords={newPassword:null,newPasswordConfirmation:null},K.go=o,K.onLanguageChange=p,K.addCalendarCategory=q,K.removeCalendarCategory=r,K.addContactCategory=s,K.removeContactCategory=t,K.addMailAccount=u,K.editMailAccount=v,K.removeMailAccount=w,K.addMailLabel=x,K.removeMailLabel=y,K.addMailFilter=z,K.editMailFilter=A,K.removeMailFilter=B,K.addDefaultEmailAddresses=C,K.userFilter=D,K.confirmChanges=E,K.save=F,K.canChangePassword=G,K.changePassword=H,K.timeZonesList=window.timeZonesList,K.timeZonesListFilter=I,K.timeZonesSearchText="",K.sieveVariablesCapability=b.sieveCapabilities.indexOf("variables")>=0,J=new k({id:0}),J.$getMailboxes().then(function(){for(var a=J.$flattenMailboxes({all:!0}),b=-1,c=a.length;++b0)&&!e}function g(){a.cancel()}function h(){a.hide()}var i=this;i.defaults=b,i.account=c,i.accountId=d,i.customFromIsReadonly=f,i.cancel=g,i.save=h}a.$inject=["$mdDialog","defaults","account","accountId","mailCustomFromEnabled"],angular.module("SOGo.PreferencesUI").controller("AccountDialogController",a)}(),function(){"use strict";function a(a,b,c,d,e,f){function g(){c.cancel()}function h(){return o.filter.rules&&o.filter.rules.length>0&&o.filter.actions&&o.filter.actions.length>0}function i(a){c.hide()}function j(a){o.filter.rules||(o.filter.rules=[]),o.filter.rules.push({field:"subject",operator:"contains"})}function k(a){o.filter.rules.splice(a,1)}function m(a){o.filter.actions||(o.filter.actions=[]),o.filter.actions.push({method:"discard"})}function n(a){o.filter.actions.splice(a,1)}var o=this,p=b.sieveCapabilities,q=b.forwardEnabled;b.vacationEnabled;o.filter=d,o.mailboxes=e,o.labels=f,o.cancel=g,o.hasRulesAndActions=h,o.save=i,o.addMailFilterRule=j,o.removeMailFilterRule=k,o.addMailFilterAction=m,o.removeMailFilterAction=n,o.fieldLabels={subject:l("Subject"),from:l("From"),to:l("To"),cc:l("Cc"),to_or_cc:l("To or Cc"),size:l("Size (Kb)"),header:l("Header")},p.indexOf("body")>-1&&(o.fieldLabels.body=l("Body")),o.methodLabels={discard:l("Discard the message"),keep:l("Keep the message"),stop:l("Stop processing filter rules")},q&&(o.methodLabels.redirect=l("Forward the message to")),p.indexOf("reject")>-1&&(o.methodLabels.reject=l("Send a reject message")),p.indexOf("fileinto")>-1&&(o.methodLabels.fileinto=l("File the message in")),(p.indexOf("imapflags")>-1||p.indexOf("imap4flags")>-1)&&(o.methodLabels.addflag=l("Flag the message with")),o.numberOperatorLabels={under:l("is under"),over:l("is over")},o.textOperatorLabels={is:l("is"),is_not:l("is not"),contains:l("contains"),contains_not:l("does not contain"),matches:l("matches"),matches_not:l("does not match")},p.indexOf("regex")>-1&&(o.textOperatorLabels.regex=l("matches regex"),o.textOperatorLabels.regex_not=l("does not match regex")),o.flagLabels={seen:l("Seen"),deleted:l("Deleted"),answered:l("Answered"),flagged:l("Flagged"),junk:l("Junk"),not_junk:l("Not Junk")}}a.$inject=["$scope","$window","$mdDialog","filter","mailboxes","labels"],angular.module("SOGo.PreferencesUI").controller("FiltersDialogController",a)}(),function(){"use strict";function a(a,b,c,d,e,f,g,h,i,j,k,m,n){function o(a,b){b.$valid&&(d("xs")&&e("left").close(),c.go("preferences."+a))}function p(a){i.confirm(l("Warning"),l("Save preferences and reload page now?"),{ok:l("Yes"),cancel:l("No")}).then(function(){F(a,{quick:!0}).then(function(){b.location.reload(!0)})})}function q(a){M.preferences.defaults.SOGoCalendarCategoriesColors["New category"]="#aaa",M.preferences.defaults.SOGoCalendarCategories.push("New category"),h("calendarCategory_"+(M.preferences.defaults.SOGoCalendarCategories.length-1)),a.$setDirty()}function r(a,b){var c=M.preferences.defaults.SOGoCalendarCategories[a];M.preferences.defaults.SOGoCalendarCategories.splice(a,1),delete M.preferences.defaults.SOGoCalendarCategoriesColors[c],b.$setDirty()}function s(a){M.preferences.defaults.SOGoContactsCategories.push(""),h("contactCategory_"+(M.preferences.defaults.SOGoContactsCategories.length-1)),a.$setDirty()}function t(a,b){M.preferences.defaults.SOGoContactsCategories.splice(a,1),b.$setDirty()}function u(a,b){var c;M.preferences.defaults.AuxiliaryMailAccounts.push({}),c=_.last(M.preferences.defaults.AuxiliaryMailAccounts),c.name=l("New account"),c.identities=[{fullName:"",email:""}],c.receipts={receiptAction:"ignore",receiptNonRecipientAction:"ignore",receiptOutsideDomainAction:"ignore",receiptAnyAction:"ignore"},f.show({controller:"AccountDialogController",controllerAs:"$AccountDialogController",templateUrl:"editAccount?account=new",targetEvent:a,locals:{defaults:M.preferences.defaults,account:c,accountId:M.preferences.defaults.AuxiliaryMailAccounts.length-1,mailCustomFromEnabled:window.mailCustomFromEnabled}}).then(function(){b.$setDirty()})}function v(a,b,c){var d=M.preferences.defaults.AuxiliaryMailAccounts[b];f.show({controller:"AccountDialogController",controllerAs:"$AccountDialogController",templateUrl:"editAccount?account="+b,targetEvent:a,locals:{defaults:M.preferences.defaults,account:d,accountId:b,mailCustomFromEnabled:window.mailCustomFromEnabled}}).then(function(){M.preferences.defaults.AuxiliaryMailAccounts[b]=d,c.$setDirty()})}function w(a,b){M.preferences.defaults.AuxiliaryMailAccounts.splice(a,1),b.$setDirty()}function x(a){var b="_$$"+guid();M.preferences.defaults.SOGoMailLabelsColors[b]=["New label","#aaa"],a.$setDirty()}function y(a,b){delete M.preferences.defaults.SOGoMailLabelsColors[a],b.$setDirty()}function z(a,b){var c={match:"all"};f.show({templateUrl:"editFilter?filter=new",controller:"FiltersDialogController",controllerAs:"filterEditor",targetEvent:a,locals:{filter:c,mailboxes:N,labels:M.preferences.defaults.SOGoMailLabelsColors}}).then(function(){M.preferences.defaults.SOGoSieveFilters||(M.preferences.defaults.SOGoSieveFilters=[]),M.preferences.defaults.SOGoSieveFilters.push(c),b.$setDirty()})}function A(a,b,c){var d=angular.copy(M.preferences.defaults.SOGoSieveFilters[b]);f.show({templateUrl:"editFilter?filter="+b,controller:"FiltersDialogController",controllerAs:"filterEditor",targetEvent:null,locals:{filter:d,mailboxes:N,labels:M.preferences.defaults.SOGoMailLabelsColors}}).then(function(){M.preferences.defaults.SOGoSieveFilters[b]=d,c.$setDirty()})}function B(a,b){M.preferences.defaults.SOGoSieveFilters.splice(a,1),b.$setDirty()}function C(a){var b=[];angular.isDefined(M.preferences.defaults.Vacation.autoReplyEmailAddresses)&&(b=M.preferences.defaults.Vacation.autoReplyEmailAddresses.split(",")),M.preferences.defaults.Vacation.autoReplyEmailAddresses=_.union(window.defaultEmailAddresses.split(","),b).join(","),a.$setDirty()}function D(a,b){return j.$filter(a,b).then(function(a){return _.forEach(a,function(a){a.$$image||(a.image?a.$$image=a.image:M.preferences.avatar(a.c_email,32,{no_404:!0}).then(function(b){a.$$image=b}))}),a})}function E(a,c){var d;if(c.$dirty){for(a.preventDefault(),a.stopPropagation(),d=a.target;"A"!=d.tagName;)d=d.parentNode;i.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(){F(c,{quick:!0}).then(function(){b.location=d.href})},function(){b.location=d.href})}}function F(c,d){var e,f,h,j,k,m;if(f=!0,k=[],b.forwardConstraints>0&&angular.isDefined(M.preferences.defaults.Forward)&&M.preferences.defaults.Forward.enabled&&angular.isDefined(M.preferences.defaults.Forward.forwardAddress))for(h=M.preferences.defaults.Forward.forwardAddress.split(","),j=b.defaultEmailAddresses.split(/, */),_.forEach(j,function(a){var b=a.split("@")[1];b&&k.push(b.toLowerCase())}),e=0;e=0&&2==b.forwardConstraints&&(i.alert(l("Error"),l("You are not allowed to forward your messages to an internal email address.")),f=!1);return f?M.preferences.$save().then(function(a){d&&d.quick||(g.show(g.simple().content(l("Preferences saved")).position("bottom right").hideDelay(2e3)),c.$setPristine())}):a.reject()}function G(){return!!(M.passwords.newPassword&&M.passwords.newPassword.length>0&&M.passwords.newPasswordConfirmation&&M.passwords.newPasswordConfirmation.length&&M.passwords.newPassword==M.passwords.newPasswordConfirmation)}function H(){n.changePassword(M.passwords.newPassword).then(function(){var a=f.alert({title:l("Password"),content:l("The password was changed successfully."),ok:l("OK")});f.show(a).finally(function(){a=void 0})},function(a){var b=f.alert({title:l("Password"),content:a,ok:l("OK")});f.show(b).finally(function(){b=void 0})})}function I(a){return _.filter(M.timeZonesList,function(b){return b.toUpperCase().indexOf(a.toUpperCase())>=0})}function J(){m.defaults&&m.defaults.Vacation&&m.defaults.Vacation.startDateEnabled?M.vacationStartDate=m.defaults.Vacation.startDate:M.vacationStartDate=M.tomorrow}function K(){m.defaults&&m.defaults.Vacation&&m.defaults.Vacation.endDateEnabled?M.vacationEndDate=m.defaults.Vacation.endDate:M.vacationEndDate=void 0}var L,M=this,N=[],O=new Date;M.preferences=m,M.passwords={newPassword:null,newPasswordConfirmation:null},M.go=o,M.onLanguageChange=p,M.addCalendarCategory=q,M.removeCalendarCategory=r,M.addContactCategory=s,M.removeContactCategory=t,M.addMailAccount=u,M.editMailAccount=v,M.removeMailAccount=w,M.addMailLabel=x,M.removeMailLabel=y,M.addMailFilter=z,M.editMailFilter=A,M.removeMailFilter=B,M.addDefaultEmailAddresses=C,M.userFilter=D,M.confirmChanges=E,M.save=F,M.canChangePassword=G,M.changePassword=H,M.timeZonesList=window.timeZonesList,M.timeZonesListFilter=I,M.timeZonesSearchText="",M.sieveVariablesCapability=b.sieveCapabilities.indexOf("variables")>=0,M.tomorrow=O.addDays(1),M.updateVacationStartDate=J,M.updateVacationEndDate=K,L=new k({id:0}),L.$getMailboxes().then(function(){for(var a=L.$flattenMailboxes({all:!0}),b=-1,c=a.length;++b 0)\n return false;\n\n return !mailCustomFromEnabled;\n }\n\n function cancel() {\n $mdDialog.cancel();\n }\n\n function save() {\n $mdDialog.hide();\n }\n }\n\n angular\n .module('SOGo.PreferencesUI')\n .controller('AccountDialogController', AccountDialogController);\n\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* JavaScript for SOGoPreferences */\n\n(function() {\n 'use strict';\n\n /**\n * @ngInject\n */\n FiltersDialogController.$inject = ['$scope', '$window', '$mdDialog', 'filter', 'mailboxes', 'labels'];\n function FiltersDialogController($scope, $window, $mdDialog, filter, mailboxes, labels) {\n var vm = this,\n sieveCapabilities = $window.sieveCapabilities,\n forwardEnabled = $window.forwardEnabled,\n vacationEnabled = $window.vacationEnabled;\n\n vm.filter = filter;\n vm.mailboxes = mailboxes;\n vm.labels = labels;\n vm.cancel = cancel;\n vm.hasRulesAndActions = hasRulesAndActions;\n vm.save = save;\n vm.addMailFilterRule = addMailFilterRule;\n vm.removeMailFilterRule = removeMailFilterRule;\n vm.addMailFilterAction = addMailFilterAction;\n vm.removeMailFilterAction = removeMailFilterAction;\n\n vm.fieldLabels = {\n \"subject\": l(\"Subject\"),\n \"from\": l(\"From\"),\n \"to\": l(\"To\"),\n \"cc\": l(\"Cc\"),\n \"to_or_cc\": l(\"To or Cc\"),\n \"size\": l(\"Size (Kb)\"),\n \"header\": l(\"Header\")\n };\n\n if (sieveCapabilities.indexOf(\"body\") > -1)\n vm.fieldLabels.body = l(\"Body\");\n\n vm.methodLabels = {\n \"discard\": l(\"Discard the message\"),\n \"keep\": l(\"Keep the message\"),\n \"stop\": l(\"Stop processing filter rules\")\n };\n\n if (forwardEnabled)\n vm.methodLabels.redirect = l(\"Forward the message to\");\n\n //if (vacationEnabled)\n // vm.methodLabels.vacation = l(\"Send a vacation message\");\n\n if (sieveCapabilities.indexOf(\"reject\") > -1)\n vm.methodLabels.reject = l(\"Send a reject message\");\n\n if (sieveCapabilities.indexOf(\"fileinto\") > -1)\n vm.methodLabels.fileinto = l(\"File the message in\");\n\n if (sieveCapabilities.indexOf(\"imapflags\") > -1 || sieveCapabilities.indexOf(\"imap4flags\") > -1)\n vm.methodLabels.addflag = l(\"Flag the message with\");\n\n vm.numberOperatorLabels = {\n \"under\": l(\"is under\"),\n \"over\": l(\"is over\")\n };\n\n vm.textOperatorLabels = {\n \"is\": l(\"is\"),\n \"is_not\": l(\"is not\"),\n \"contains\": l(\"contains\"),\n \"contains_not\": l(\"does not contain\"),\n \"matches\": l(\"matches\"),\n \"matches_not\": l(\"does not match\")\n };\n\n if (sieveCapabilities.indexOf(\"regex\") > -1) {\n vm.textOperatorLabels.regex = l(\"matches regex\");\n vm.textOperatorLabels.regex_not = l(\"does not match regex\");\n }\n\n vm.flagLabels = {\n \"seen\": l(\"Seen\"),\n \"deleted\": l(\"Deleted\"),\n \"answered\": l(\"Answered\"),\n \"flagged\": l(\"Flagged\"),\n \"junk\": l(\"Junk\"),\n \"not_junk\": l(\"Not Junk\")\n };\n \n function cancel() {\n $mdDialog.cancel();\n }\n\n function hasRulesAndActions() {\n return vm.filter.rules && vm.filter.rules.length > 0 &&\n vm.filter.actions && vm.filter.actions.length > 0;\n }\n \n function save(form) {\n $mdDialog.hide();\n }\n\n function addMailFilterRule(event) {\n if (!vm.filter.rules)\n vm.filter.rules = [];\n\n vm.filter.rules.push({ field: 'subject', operator: 'contains' });\n }\n \n function removeMailFilterRule(index) {\n vm.filter.rules.splice(index, 1);\n }\n \n function addMailFilterAction(event) {\n if (!vm.filter.actions)\n vm.filter.actions = [];\n\n vm.filter.actions.push({ method: 'discard' });\n }\n \n function removeMailFilterAction(index) {\n vm.filter.actions.splice(index, 1);\n }\n }\n\n angular\n .module('SOGo.PreferencesUI')\n .controller('FiltersDialogController', FiltersDialogController);\n\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* JavaScript for SOGoPreferences */\n\n(function() {\n 'use strict';\n \n /**\n * @ngInject\n */\n PreferencesController.$inject = ['$q', '$window', '$state', '$mdMedia', '$mdSidenav', '$mdDialog', '$mdToast', 'sgFocus', 'Dialog', 'User', 'Account', 'statePreferences', 'Authentication'];\n function PreferencesController($q, $window, $state, $mdMedia, $mdSidenav, $mdDialog, $mdToast, focus, Dialog, User, Account, statePreferences, Authentication) {\n var vm = this, account, mailboxes = [];\n\n vm.preferences = statePreferences;\n vm.passwords = { newPassword: null, newPasswordConfirmation: null };\n\n vm.go = go;\n vm.onLanguageChange = onLanguageChange;\n vm.addCalendarCategory = addCalendarCategory;\n vm.removeCalendarCategory = removeCalendarCategory;\n vm.addContactCategory = addContactCategory;\n vm.removeContactCategory = removeContactCategory;\n vm.addMailAccount = addMailAccount;\n vm.editMailAccount = editMailAccount;\n vm.removeMailAccount = removeMailAccount;\n vm.addMailLabel = addMailLabel;\n vm.removeMailLabel = removeMailLabel;\n vm.addMailFilter = addMailFilter;\n vm.editMailFilter = editMailFilter;\n vm.removeMailFilter = removeMailFilter;\n vm.addDefaultEmailAddresses = addDefaultEmailAddresses;\n vm.userFilter = userFilter;\n vm.confirmChanges = confirmChanges;\n vm.save = save;\n vm.canChangePassword = canChangePassword;\n vm.changePassword = changePassword;\n vm.timeZonesList = window.timeZonesList;\n vm.timeZonesListFilter = timeZonesListFilter;\n vm.timeZonesSearchText = '';\n vm.sieveVariablesCapability = ($window.sieveCapabilities.indexOf('variables') >= 0);\n\n // Fetch a flatten version of the mailboxes list of the main account (0)\n // This list will be forwarded to the Sieve filter controller\n account = new Account({ id: 0 });\n account.$getMailboxes().then(function() {\n var allMailboxes = account.$flattenMailboxes({all: true}),\n index = -1,\n length = allMailboxes.length;\n while (++index < length) {\n mailboxes.push(allMailboxes[index]);\n }\n });\n\n // Set alternate avatar in User service\n statePreferences.ready().then(function() {\n if (statePreferences.defaults.SOGoAlternateAvatar)\n User.$alternateAvatar = statePreferences.defaults.SOGoAlternateAvatar;\n });\n\n function go(module, form) {\n if (form.$valid) {\n // Close sidenav on small devices\n if ($mdMedia('xs'))\n $mdSidenav('left').close();\n $state.go('preferences.' + module);\n }\n }\n\n function onLanguageChange(form) {\n Dialog.confirm(l('Warning'),\n l('Save preferences and reload page now?'),\n {ok: l('Yes'), cancel: l('No')})\n .then(function() {\n save(form, { quick: true }).then(function() {\n $window.location.reload(true);\n });\n });\n }\n\n function addCalendarCategory(form) {\n vm.preferences.defaults.SOGoCalendarCategoriesColors[\"New category\"] = \"#aaa\";\n vm.preferences.defaults.SOGoCalendarCategories.push(\"New category\");\n focus('calendarCategory_' + (vm.preferences.defaults.SOGoCalendarCategories.length - 1));\n form.$setDirty();\n }\n\n function removeCalendarCategory(index, form) {\n var key = vm.preferences.defaults.SOGoCalendarCategories[index];\n vm.preferences.defaults.SOGoCalendarCategories.splice(index, 1);\n delete vm.preferences.defaults.SOGoCalendarCategoriesColors[key];\n form.$setDirty();\n }\n\n function addContactCategory(form) {\n vm.preferences.defaults.SOGoContactsCategories.push(\"\");\n focus('contactCategory_' + (vm.preferences.defaults.SOGoContactsCategories.length - 1));\n form.$setDirty();\n }\n\n function removeContactCategory(index, form) {\n vm.preferences.defaults.SOGoContactsCategories.splice(index, 1);\n form.$setDirty();\n }\n\n function addMailAccount(ev, form) {\n var account;\n\n vm.preferences.defaults.AuxiliaryMailAccounts.push({});\n\n account = _.last(vm.preferences.defaults.AuxiliaryMailAccounts);\n account.name = l(\"New account\");\n account.identities = [\n {\n fullName: \"\",\n email: \"\"\n }\n ];\n account.receipts = {\n receiptAction: \"ignore\",\n receiptNonRecipientAction: \"ignore\",\n receiptOutsideDomainAction: \"ignore\",\n receiptAnyAction: \"ignore\"\n };\n\n $mdDialog.show({\n controller: 'AccountDialogController',\n controllerAs: '$AccountDialogController',\n templateUrl: 'editAccount?account=new',\n targetEvent: ev,\n locals: {\n defaults: vm.preferences.defaults,\n account: account,\n accountId: (vm.preferences.defaults.AuxiliaryMailAccounts.length-1),\n mailCustomFromEnabled: window.mailCustomFromEnabled\n }\n }).then(function() {\n form.$setDirty();\n });\n }\n\n function editMailAccount(event, index, form) {\n var account = vm.preferences.defaults.AuxiliaryMailAccounts[index];\n $mdDialog.show({\n controller: 'AccountDialogController',\n controllerAs: '$AccountDialogController',\n templateUrl: 'editAccount?account=' + index,\n targetEvent: event,\n locals: {\n defaults: vm.preferences.defaults,\n account: account,\n accountId: index,\n mailCustomFromEnabled: window.mailCustomFromEnabled\n }\n }).then(function() {\n vm.preferences.defaults.AuxiliaryMailAccounts[index] = account;\n form.$setDirty();\n });\n }\n\n function removeMailAccount(index, form) {\n vm.preferences.defaults.AuxiliaryMailAccounts.splice(index, 1);\n form.$setDirty();\n }\n \n function addMailLabel(form) {\n // See $omit() in the Preferences services for real key generation\n var key = '_$$' + guid();\n vm.preferences.defaults.SOGoMailLabelsColors[key] = [\"New label\", \"#aaa\"];\n form.$setDirty();\n }\n\n function removeMailLabel(key, form) {\n delete vm.preferences.defaults.SOGoMailLabelsColors[key];\n form.$setDirty();\n }\n\n function addMailFilter(ev, form) {\n var filter = { match: 'all' };\n\n $mdDialog.show({\n templateUrl: 'editFilter?filter=new',\n controller: 'FiltersDialogController',\n controllerAs: 'filterEditor',\n targetEvent: ev,\n locals: {\n filter: filter,\n mailboxes: mailboxes,\n labels: vm.preferences.defaults.SOGoMailLabelsColors\n }\n }).then(function() {\n if (!vm.preferences.defaults.SOGoSieveFilters)\n vm.preferences.defaults.SOGoSieveFilters = [];\n vm.preferences.defaults.SOGoSieveFilters.push(filter);\n form.$setDirty();\n });\n }\n \n function editMailFilter(ev, index, form) {\n var filter = angular.copy(vm.preferences.defaults.SOGoSieveFilters[index]);\n \n $mdDialog.show({\n templateUrl: 'editFilter?filter=' + index,\n controller: 'FiltersDialogController',\n controllerAs: 'filterEditor',\n targetEvent: null,\n locals: {\n filter: filter,\n mailboxes: mailboxes,\n labels: vm.preferences.defaults.SOGoMailLabelsColors\n }\n }).then(function() {\n vm.preferences.defaults.SOGoSieveFilters[index] = filter;\n form.$setDirty();\n });\n }\n\n function removeMailFilter(index, form) {\n vm.preferences.defaults.SOGoSieveFilters.splice(index, 1);\n form.$setDirty();\n }\n\n function addDefaultEmailAddresses(form) {\n var v = [];\n\n if (angular.isDefined(vm.preferences.defaults.Vacation.autoReplyEmailAddresses)) {\n v = vm.preferences.defaults.Vacation.autoReplyEmailAddresses.split(',');\n }\n\n vm.preferences.defaults.Vacation.autoReplyEmailAddresses = (_.union(window.defaultEmailAddresses.split(','), v)).join(',');\n form.$setDirty();\n }\n\n function userFilter(search, excludedUsers) {\n return User.$filter(search, excludedUsers).then(function(users) {\n // Set users avatars\n _.forEach(users, function(user) {\n if (!user.$$image) {\n if (user.image)\n user.$$image = user.image;\n else\n vm.preferences.avatar(user.c_email, 32, {no_404: true}).then(function(url) {\n user.$$image = url;\n });\n }\n });\n return users;\n });\n }\n\n function confirmChanges($event, form) {\n var target;\n\n if (form.$dirty) {\n // Stop default action\n $event.preventDefault();\n $event.stopPropagation();\n\n // Find target link\n target = $event.target;\n while (target.tagName != 'A')\n target = target.parentNode;\n\n Dialog.confirm(l('Unsaved Changes'),\n l('Do you want to save your changes made to the configuration?'),\n { ok: l('Save'), cancel: l('Don\\'t Save') })\n .then(function() {\n // Save & follow link\n save(form, { quick: true }).then(function() {\n $window.location = target.href;\n });\n }, function() {\n // Don't save & follow link\n $window.location = target.href;\n });\n }\n }\n\n function save(form, options) {\n var i, sendForm, addresses, defaultAddresses, domains, domain;\n\n sendForm = true;\n domains = [];\n\n // We do some sanity checks\n if (window.forwardConstraints > 0 &&\n angular.isDefined(vm.preferences.defaults.Forward) &&\n vm.preferences.defaults.Forward.enabled &&\n angular.isDefined(vm.preferences.defaults.Forward.forwardAddress)) {\n\n addresses = vm.preferences.defaults.Forward.forwardAddress.split(\",\");\n\n // We first extract the list of 'known domains' to SOGo\n defaultAddresses = window.defaultEmailAddresses.split(/, */);\n\n _.forEach(defaultAddresses, function(adr) {\n var domain = adr.split(\"@\")[1];\n if (domain) {\n domains.push(domain.toLowerCase());\n }\n });\n\n // We check if we're allowed or not to forward based on the domain defaults\n for (i = 0; i < addresses.length && sendForm; i++) {\n domain = addresses[i].split(\"@\")[1].toLowerCase();\n if (domains.indexOf(domain) < 0 && window.forwardConstraints == 1) {\n Dialog.alert(l('Error'), l(\"You are not allowed to forward your messages to an external email address.\"));\n sendForm = false;\n }\n else if (domains.indexOf(domain) >= 0 && window.forwardConstraints == 2) {\n Dialog.alert(l('Error'), l(\"You are not allowed to forward your messages to an internal email address.\"));\n sendForm = false;\n }\n }\n }\n\n if (sendForm)\n return vm.preferences.$save().then(function(data) {\n if (!options || !options.quick) {\n $mdToast.show(\n $mdToast.simple()\n .content(l('Preferences saved'))\n .position('bottom right')\n .hideDelay(2000));\n form.$setPristine();\n }\n });\n\n return $q.reject();\n }\n\n function canChangePassword() {\n if (vm.passwords.newPassword && vm.passwords.newPassword.length > 0 &&\n vm.passwords.newPasswordConfirmation && vm.passwords.newPasswordConfirmation.length &&\n vm.passwords.newPassword == vm.passwords.newPasswordConfirmation)\n return true;\n\n return false;\n }\n \n function changePassword() {\n Authentication.changePassword(vm.passwords.newPassword).then(function() {\n var alert = $mdDialog.alert({\n title: l('Password'),\n content: l('The password was changed successfully.'),\n ok: l('OK')\n });\n $mdDialog.show( alert )\n .finally(function() {\n alert = undefined;\n });\n }, function(msg) {\n var alert = $mdDialog.alert({\n title: l('Password'),\n content: msg,\n ok: l('OK')\n });\n $mdDialog.show( alert )\n .finally(function() {\n alert = undefined;\n });\n });\n }\n\n function timeZonesListFilter(filter) {\n return _.filter(vm.timeZonesList, function(value) {\n return value.toUpperCase().indexOf(filter.toUpperCase()) >= 0;\n });\n }\n }\n\n angular\n .module('SOGo.PreferencesUI')\n .controller('PreferencesController', PreferencesController);\n\n})();\n"]} \ No newline at end of file +{"version":3,"sources":["Preferences/Preferences.app.js","Preferences/AccountDialogController.js","Preferences/FiltersDialogController.js","Preferences/PreferencesController.js"],"names":["configure","$stateProvider","$urlRouterProvider","state","abstract","views","preferences","templateUrl","controller","controllerAs","resolve","statePreferences","url","module","otherwise","Preferences","runBlock","$rootScope","$on","event","current","previous","rejection","console","error","angular","config","run","$inject","AccountDialogController","$mdDialog","defaults","account","accountId","mailCustomFromEnabled","customFromIsReadonly","cancel","save","hide","vm","this","FiltersDialogController","$scope","$window","filter","mailboxes","labels","hasRulesAndActions","rules","length","actions","form","addMailFilterRule","push","field","operator","removeMailFilterRule","index","splice","addMailFilterAction","method","removeMailFilterAction","sieveCapabilities","forwardEnabled","vacationEnabled","fieldLabels","subject","l","from","to","cc","to_or_cc","size","header","indexOf","body","methodLabels","discard","keep","stop","redirect","reject","fileinto","addflag","numberOperatorLabels","under","over","textOperatorLabels","is","is_not","contains","contains_not","matches","matches_not","regex","regex_not","flagLabels","seen","deleted","answered","flagged","junk","not_junk","PreferencesController","$q","$state","$mdMedia","$mdSidenav","$mdToast","focus","Dialog","User","Account","Authentication","go","$valid","close","onLanguageChange","confirm","ok","then","quick","location","reload","addCalendarCategory","SOGoCalendarCategoriesColors","SOGoCalendarCategories","$setDirty","removeCalendarCategory","key","addContactCategory","SOGoContactsCategories","removeContactCategory","addMailAccount","ev","AuxiliaryMailAccounts","_","last","name","identities","fullName","email","receipts","receiptAction","receiptNonRecipientAction","receiptOutsideDomainAction","receiptAnyAction","show","targetEvent","locals","window","editMailAccount","removeMailAccount","addMailLabel","guid","SOGoMailLabelsColors","removeMailLabel","addMailFilter","match","SOGoSieveFilters","editMailFilter","copy","removeMailFilter","addDefaultEmailAddresses","v","isDefined","Vacation","autoReplyEmailAddresses","split","union","defaultEmailAddresses","join","userFilter","search","excludedUsers","$filter","users","forEach","user","$$image","image","avatar","c_email","no_404","confirmChanges","$event","target","$dirty","preventDefault","stopPropagation","tagName","parentNode","href","options","i","sendForm","addresses","defaultAddresses","domains","domain","forwardConstraints","Forward","enabled","forwardAddress","adr","toLowerCase","alert","$save","data","simple","content","position","hideDelay","$setPristine","canChangePassword","passwords","newPassword","newPasswordConfirmation","changePassword","title","finally","undefined","msg","timeZonesListFilter","timeZonesList","value","toUpperCase","updateVacationStartDate","startDateEnabled","vacationStartDate","startDate","tomorrow","updateVacationEndDate","endDateEnabled","vacationEndDate","endDate","today","Date","timeZonesSearchText","sieveVariablesCapability","addDays","id","$getMailboxes","allMailboxes","$flattenMailboxes","all","ready","SOGoAlternateAvatar","$alternateAvatar"],"mappings":"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","file":"Preferences.js","sourcesContent":["/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* JavaScript for SOGoPreferences */\n\n(function() {\n 'use strict';\n\n angular.module('SOGo.PreferencesUI', ['ui.router', 'ck', 'SOGo.Common', 'SOGo.MailerUI', 'SOGo.ContactsUI', 'SOGo.Authentication', 'as.sortable'])\n .config(configure)\n .run(runBlock);\n\n /**\n * @ngInject\n */\n configure.$inject = ['$stateProvider', '$urlRouterProvider'];\n function configure($stateProvider, $urlRouterProvider) {\n $stateProvider\n .state('preferences', {\n abstract: true,\n views: {\n preferences: {\n templateUrl: 'preferences.html',\n controller: 'PreferencesController',\n controllerAs: 'app'\n }\n },\n resolve: {\n statePreferences: statePreferences\n }\n })\n .state('preferences.general', {\n url: '/general',\n views: {\n module: {\n templateUrl: 'generalPreferences.html'\n }\n }\n })\n .state('preferences.calendars', {\n url: '/calendars',\n views: {\n module: {\n templateUrl: 'calendarsPreferences.html'\n }\n }\n })\n .state('preferences.addressbooks', {\n url: '/addressbooks',\n views: {\n module: {\n templateUrl: 'addressbooksPreferences.html'\n }\n }\n })\n .state('preferences.mailer', {\n url: '/mailer',\n views: {\n module: {\n templateUrl: 'mailerPreferences.html'\n }\n }\n });\n\n // if none of the above states are matched, use this as the fallback\n $urlRouterProvider.otherwise('/general');\n }\n\n /**\n * @ngInject\n */\n statePreferences.$inject = ['Preferences'];\n function statePreferences(Preferences) {\n return Preferences;\n }\n\n /**\n * @ngInject\n */\n runBlock.$inject = ['$rootScope'];\n function runBlock($rootScope) {\n $rootScope.$on('$routeChangeError', function(event, current, previous, rejection) {\n console.error(event, current, previous, rejection);\n });\n }\n\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* JavaScript for SOGoPreferences */\n\n(function() {\n 'use strict';\n\n /**\n * @ngInject\n */\n AccountDialogController.$inject = ['$mdDialog', 'defaults', 'account', 'accountId', 'mailCustomFromEnabled'];\n function AccountDialogController($mdDialog, defaults, account, accountId, mailCustomFromEnabled) {\n var vm = this;\n\n vm.defaults = defaults;\n vm.account = account;\n vm.accountId = accountId;\n vm.customFromIsReadonly = customFromIsReadonly;\n vm.cancel = cancel;\n vm.save = save;\n\n function customFromIsReadonly() {\n if (accountId > 0)\n return false;\n\n return !mailCustomFromEnabled;\n }\n\n function cancel() {\n $mdDialog.cancel();\n }\n\n function save() {\n $mdDialog.hide();\n }\n }\n\n angular\n .module('SOGo.PreferencesUI')\n .controller('AccountDialogController', AccountDialogController);\n\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* JavaScript for SOGoPreferences */\n\n(function() {\n 'use strict';\n\n /**\n * @ngInject\n */\n FiltersDialogController.$inject = ['$scope', '$window', '$mdDialog', 'filter', 'mailboxes', 'labels'];\n function FiltersDialogController($scope, $window, $mdDialog, filter, mailboxes, labels) {\n var vm = this,\n sieveCapabilities = $window.sieveCapabilities,\n forwardEnabled = $window.forwardEnabled,\n vacationEnabled = $window.vacationEnabled;\n\n vm.filter = filter;\n vm.mailboxes = mailboxes;\n vm.labels = labels;\n vm.cancel = cancel;\n vm.hasRulesAndActions = hasRulesAndActions;\n vm.save = save;\n vm.addMailFilterRule = addMailFilterRule;\n vm.removeMailFilterRule = removeMailFilterRule;\n vm.addMailFilterAction = addMailFilterAction;\n vm.removeMailFilterAction = removeMailFilterAction;\n\n vm.fieldLabels = {\n \"subject\": l(\"Subject\"),\n \"from\": l(\"From\"),\n \"to\": l(\"To\"),\n \"cc\": l(\"Cc\"),\n \"to_or_cc\": l(\"To or Cc\"),\n \"size\": l(\"Size (Kb)\"),\n \"header\": l(\"Header\")\n };\n\n if (sieveCapabilities.indexOf(\"body\") > -1)\n vm.fieldLabels.body = l(\"Body\");\n\n vm.methodLabels = {\n \"discard\": l(\"Discard the message\"),\n \"keep\": l(\"Keep the message\"),\n \"stop\": l(\"Stop processing filter rules\")\n };\n\n if (forwardEnabled)\n vm.methodLabels.redirect = l(\"Forward the message to\");\n\n //if (vacationEnabled)\n // vm.methodLabels.vacation = l(\"Send a vacation message\");\n\n if (sieveCapabilities.indexOf(\"reject\") > -1)\n vm.methodLabels.reject = l(\"Send a reject message\");\n\n if (sieveCapabilities.indexOf(\"fileinto\") > -1)\n vm.methodLabels.fileinto = l(\"File the message in\");\n\n if (sieveCapabilities.indexOf(\"imapflags\") > -1 || sieveCapabilities.indexOf(\"imap4flags\") > -1)\n vm.methodLabels.addflag = l(\"Flag the message with\");\n\n vm.numberOperatorLabels = {\n \"under\": l(\"is under\"),\n \"over\": l(\"is over\")\n };\n\n vm.textOperatorLabels = {\n \"is\": l(\"is\"),\n \"is_not\": l(\"is not\"),\n \"contains\": l(\"contains\"),\n \"contains_not\": l(\"does not contain\"),\n \"matches\": l(\"matches\"),\n \"matches_not\": l(\"does not match\")\n };\n\n if (sieveCapabilities.indexOf(\"regex\") > -1) {\n vm.textOperatorLabels.regex = l(\"matches regex\");\n vm.textOperatorLabels.regex_not = l(\"does not match regex\");\n }\n\n vm.flagLabels = {\n \"seen\": l(\"Seen\"),\n \"deleted\": l(\"Deleted\"),\n \"answered\": l(\"Answered\"),\n \"flagged\": l(\"Flagged\"),\n \"junk\": l(\"Junk\"),\n \"not_junk\": l(\"Not Junk\")\n };\n \n function cancel() {\n $mdDialog.cancel();\n }\n\n function hasRulesAndActions() {\n return vm.filter.rules && vm.filter.rules.length > 0 &&\n vm.filter.actions && vm.filter.actions.length > 0;\n }\n \n function save(form) {\n $mdDialog.hide();\n }\n\n function addMailFilterRule(event) {\n if (!vm.filter.rules)\n vm.filter.rules = [];\n\n vm.filter.rules.push({ field: 'subject', operator: 'contains' });\n }\n \n function removeMailFilterRule(index) {\n vm.filter.rules.splice(index, 1);\n }\n \n function addMailFilterAction(event) {\n if (!vm.filter.actions)\n vm.filter.actions = [];\n\n vm.filter.actions.push({ method: 'discard' });\n }\n \n function removeMailFilterAction(index) {\n vm.filter.actions.splice(index, 1);\n }\n }\n\n angular\n .module('SOGo.PreferencesUI')\n .controller('FiltersDialogController', FiltersDialogController);\n\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* JavaScript for SOGoPreferences */\n\n(function() {\n 'use strict';\n \n /**\n * @ngInject\n */\n PreferencesController.$inject = ['$q', '$window', '$state', '$mdMedia', '$mdSidenav', '$mdDialog', '$mdToast', 'sgFocus', 'Dialog', 'User', 'Account', 'statePreferences', 'Authentication'];\n function PreferencesController($q, $window, $state, $mdMedia, $mdSidenav, $mdDialog, $mdToast, focus, Dialog, User, Account, statePreferences, Authentication) {\n var vm = this, account, mailboxes = [], today = new Date();\n\n vm.preferences = statePreferences;\n vm.passwords = { newPassword: null, newPasswordConfirmation: null };\n\n vm.go = go;\n vm.onLanguageChange = onLanguageChange;\n vm.addCalendarCategory = addCalendarCategory;\n vm.removeCalendarCategory = removeCalendarCategory;\n vm.addContactCategory = addContactCategory;\n vm.removeContactCategory = removeContactCategory;\n vm.addMailAccount = addMailAccount;\n vm.editMailAccount = editMailAccount;\n vm.removeMailAccount = removeMailAccount;\n vm.addMailLabel = addMailLabel;\n vm.removeMailLabel = removeMailLabel;\n vm.addMailFilter = addMailFilter;\n vm.editMailFilter = editMailFilter;\n vm.removeMailFilter = removeMailFilter;\n vm.addDefaultEmailAddresses = addDefaultEmailAddresses;\n vm.userFilter = userFilter;\n vm.confirmChanges = confirmChanges;\n vm.save = save;\n vm.canChangePassword = canChangePassword;\n vm.changePassword = changePassword;\n vm.timeZonesList = window.timeZonesList;\n vm.timeZonesListFilter = timeZonesListFilter;\n vm.timeZonesSearchText = '';\n vm.sieveVariablesCapability = ($window.sieveCapabilities.indexOf('variables') >= 0);\n vm.tomorrow = today.addDays(1);\n vm.updateVacationStartDate = updateVacationStartDate;\n vm.updateVacationEndDate = updateVacationEndDate;\n\n // Fetch a flatten version of the mailboxes list of the main account (0)\n // This list will be forwarded to the Sieve filter controller\n account = new Account({ id: 0 });\n account.$getMailboxes().then(function() {\n var allMailboxes = account.$flattenMailboxes({all: true}),\n index = -1,\n length = allMailboxes.length;\n while (++index < length) {\n mailboxes.push(allMailboxes[index]);\n }\n });\n\n // Set alternate avatar in User service\n statePreferences.ready().then(function() {\n if (statePreferences.defaults.SOGoAlternateAvatar)\n User.$alternateAvatar = statePreferences.defaults.SOGoAlternateAvatar;\n updateVacationStartDate();\n updateVacationEndDate();\n });\n\n function go(module, form) {\n if (form.$valid) {\n // Close sidenav on small devices\n if ($mdMedia('xs'))\n $mdSidenav('left').close();\n $state.go('preferences.' + module);\n }\n }\n\n function onLanguageChange(form) {\n Dialog.confirm(l('Warning'),\n l('Save preferences and reload page now?'),\n {ok: l('Yes'), cancel: l('No')})\n .then(function() {\n save(form, { quick: true }).then(function() {\n $window.location.reload(true);\n });\n });\n }\n\n function addCalendarCategory(form) {\n vm.preferences.defaults.SOGoCalendarCategoriesColors[\"New category\"] = \"#aaa\";\n vm.preferences.defaults.SOGoCalendarCategories.push(\"New category\");\n focus('calendarCategory_' + (vm.preferences.defaults.SOGoCalendarCategories.length - 1));\n form.$setDirty();\n }\n\n function removeCalendarCategory(index, form) {\n var key = vm.preferences.defaults.SOGoCalendarCategories[index];\n vm.preferences.defaults.SOGoCalendarCategories.splice(index, 1);\n delete vm.preferences.defaults.SOGoCalendarCategoriesColors[key];\n form.$setDirty();\n }\n\n function addContactCategory(form) {\n vm.preferences.defaults.SOGoContactsCategories.push(\"\");\n focus('contactCategory_' + (vm.preferences.defaults.SOGoContactsCategories.length - 1));\n form.$setDirty();\n }\n\n function removeContactCategory(index, form) {\n vm.preferences.defaults.SOGoContactsCategories.splice(index, 1);\n form.$setDirty();\n }\n\n function addMailAccount(ev, form) {\n var account;\n\n vm.preferences.defaults.AuxiliaryMailAccounts.push({});\n\n account = _.last(vm.preferences.defaults.AuxiliaryMailAccounts);\n account.name = l(\"New account\");\n account.identities = [\n {\n fullName: \"\",\n email: \"\"\n }\n ];\n account.receipts = {\n receiptAction: \"ignore\",\n receiptNonRecipientAction: \"ignore\",\n receiptOutsideDomainAction: \"ignore\",\n receiptAnyAction: \"ignore\"\n };\n\n $mdDialog.show({\n controller: 'AccountDialogController',\n controllerAs: '$AccountDialogController',\n templateUrl: 'editAccount?account=new',\n targetEvent: ev,\n locals: {\n defaults: vm.preferences.defaults,\n account: account,\n accountId: (vm.preferences.defaults.AuxiliaryMailAccounts.length-1),\n mailCustomFromEnabled: window.mailCustomFromEnabled\n }\n }).then(function() {\n form.$setDirty();\n });\n }\n\n function editMailAccount(event, index, form) {\n var account = vm.preferences.defaults.AuxiliaryMailAccounts[index];\n $mdDialog.show({\n controller: 'AccountDialogController',\n controllerAs: '$AccountDialogController',\n templateUrl: 'editAccount?account=' + index,\n targetEvent: event,\n locals: {\n defaults: vm.preferences.defaults,\n account: account,\n accountId: index,\n mailCustomFromEnabled: window.mailCustomFromEnabled\n }\n }).then(function() {\n vm.preferences.defaults.AuxiliaryMailAccounts[index] = account;\n form.$setDirty();\n });\n }\n\n function removeMailAccount(index, form) {\n vm.preferences.defaults.AuxiliaryMailAccounts.splice(index, 1);\n form.$setDirty();\n }\n \n function addMailLabel(form) {\n // See $omit() in the Preferences services for real key generation\n var key = '_$$' + guid();\n vm.preferences.defaults.SOGoMailLabelsColors[key] = [\"New label\", \"#aaa\"];\n form.$setDirty();\n }\n\n function removeMailLabel(key, form) {\n delete vm.preferences.defaults.SOGoMailLabelsColors[key];\n form.$setDirty();\n }\n\n function addMailFilter(ev, form) {\n var filter = { match: 'all' };\n\n $mdDialog.show({\n templateUrl: 'editFilter?filter=new',\n controller: 'FiltersDialogController',\n controllerAs: 'filterEditor',\n targetEvent: ev,\n locals: {\n filter: filter,\n mailboxes: mailboxes,\n labels: vm.preferences.defaults.SOGoMailLabelsColors\n }\n }).then(function() {\n if (!vm.preferences.defaults.SOGoSieveFilters)\n vm.preferences.defaults.SOGoSieveFilters = [];\n vm.preferences.defaults.SOGoSieveFilters.push(filter);\n form.$setDirty();\n });\n }\n \n function editMailFilter(ev, index, form) {\n var filter = angular.copy(vm.preferences.defaults.SOGoSieveFilters[index]);\n \n $mdDialog.show({\n templateUrl: 'editFilter?filter=' + index,\n controller: 'FiltersDialogController',\n controllerAs: 'filterEditor',\n targetEvent: null,\n locals: {\n filter: filter,\n mailboxes: mailboxes,\n labels: vm.preferences.defaults.SOGoMailLabelsColors\n }\n }).then(function() {\n vm.preferences.defaults.SOGoSieveFilters[index] = filter;\n form.$setDirty();\n });\n }\n\n function removeMailFilter(index, form) {\n vm.preferences.defaults.SOGoSieveFilters.splice(index, 1);\n form.$setDirty();\n }\n\n function addDefaultEmailAddresses(form) {\n var v = [];\n\n if (angular.isDefined(vm.preferences.defaults.Vacation.autoReplyEmailAddresses)) {\n v = vm.preferences.defaults.Vacation.autoReplyEmailAddresses.split(',');\n }\n\n vm.preferences.defaults.Vacation.autoReplyEmailAddresses = (_.union(window.defaultEmailAddresses.split(','), v)).join(',');\n form.$setDirty();\n }\n\n function userFilter(search, excludedUsers) {\n return User.$filter(search, excludedUsers).then(function(users) {\n // Set users avatars\n _.forEach(users, function(user) {\n if (!user.$$image) {\n if (user.image)\n user.$$image = user.image;\n else\n vm.preferences.avatar(user.c_email, 32, {no_404: true}).then(function(url) {\n user.$$image = url;\n });\n }\n });\n return users;\n });\n }\n\n function confirmChanges($event, form) {\n var target;\n\n if (form.$dirty) {\n // Stop default action\n $event.preventDefault();\n $event.stopPropagation();\n\n // Find target link\n target = $event.target;\n while (target.tagName != 'A')\n target = target.parentNode;\n\n Dialog.confirm(l('Unsaved Changes'),\n l('Do you want to save your changes made to the configuration?'),\n { ok: l('Save'), cancel: l('Don\\'t Save') })\n .then(function() {\n // Save & follow link\n save(form, { quick: true }).then(function() {\n $window.location = target.href;\n });\n }, function() {\n // Don't save & follow link\n $window.location = target.href;\n });\n }\n }\n\n function save(form, options) {\n var i, sendForm, addresses, defaultAddresses, domains, domain;\n\n sendForm = true;\n domains = [];\n\n // We do some sanity checks\n if ($window.forwardConstraints > 0 &&\n angular.isDefined(vm.preferences.defaults.Forward) &&\n vm.preferences.defaults.Forward.enabled &&\n angular.isDefined(vm.preferences.defaults.Forward.forwardAddress)) {\n\n addresses = vm.preferences.defaults.Forward.forwardAddress.split(\",\");\n\n // We first extract the list of 'known domains' to SOGo\n defaultAddresses = $window.defaultEmailAddresses.split(/, */);\n\n _.forEach(defaultAddresses, function(adr) {\n var domain = adr.split(\"@\")[1];\n if (domain) {\n domains.push(domain.toLowerCase());\n }\n });\n\n // We check if we're allowed or not to forward based on the domain defaults\n for (i = 0; i < addresses.length && sendForm; i++) {\n domain = addresses[i].split(\"@\")[1].toLowerCase();\n if (domains.indexOf(domain) < 0 && $window.forwardConstraints == 1) {\n Dialog.alert(l('Error'), l(\"You are not allowed to forward your messages to an external email address.\"));\n sendForm = false;\n }\n else if (domains.indexOf(domain) >= 0 && $window.forwardConstraints == 2) {\n Dialog.alert(l('Error'), l(\"You are not allowed to forward your messages to an internal email address.\"));\n sendForm = false;\n }\n }\n }\n\n if (sendForm)\n return vm.preferences.$save().then(function(data) {\n if (!options || !options.quick) {\n $mdToast.show(\n $mdToast.simple()\n .content(l('Preferences saved'))\n .position('bottom right')\n .hideDelay(2000));\n form.$setPristine();\n }\n });\n\n return $q.reject();\n }\n\n function canChangePassword() {\n if (vm.passwords.newPassword && vm.passwords.newPassword.length > 0 &&\n vm.passwords.newPasswordConfirmation && vm.passwords.newPasswordConfirmation.length &&\n vm.passwords.newPassword == vm.passwords.newPasswordConfirmation)\n return true;\n\n return false;\n }\n \n function changePassword() {\n Authentication.changePassword(vm.passwords.newPassword).then(function() {\n var alert = $mdDialog.alert({\n title: l('Password'),\n content: l('The password was changed successfully.'),\n ok: l('OK')\n });\n $mdDialog.show( alert )\n .finally(function() {\n alert = undefined;\n });\n }, function(msg) {\n var alert = $mdDialog.alert({\n title: l('Password'),\n content: msg,\n ok: l('OK')\n });\n $mdDialog.show( alert )\n .finally(function() {\n alert = undefined;\n });\n });\n }\n\n function timeZonesListFilter(filter) {\n return _.filter(vm.timeZonesList, function(value) {\n return value.toUpperCase().indexOf(filter.toUpperCase()) >= 0;\n });\n }\n\n function updateVacationStartDate() {\n if (statePreferences.defaults &&\n statePreferences.defaults.Vacation &&\n statePreferences.defaults.Vacation.startDateEnabled)\n vm.vacationStartDate = statePreferences.defaults.Vacation.startDate;\n else\n vm.vacationStartDate = vm.tomorrow;\n }\n\n function updateVacationEndDate() {\n if (statePreferences.defaults &&\n statePreferences.defaults.Vacation &&\n statePreferences.defaults.Vacation.endDateEnabled)\n vm.vacationEndDate = statePreferences.defaults.Vacation.endDate;\n else\n vm.vacationEndDate = undefined;\n }\n }\n\n angular\n .module('SOGo.PreferencesUI')\n .controller('PreferencesController', PreferencesController);\n\n})();\n"]} \ No newline at end of file diff --git a/UI/WebServerResources/js/vendor/ng-sortable.min.js b/UI/WebServerResources/js/vendor/ng-sortable.min.js index 7adc8af1c..7e9da626a 100644 --- a/UI/WebServerResources/js/vendor/ng-sortable.min.js +++ b/UI/WebServerResources/js/vendor/ng-sortable.min.js @@ -1 +1 @@ -!function(){"use strict";angular.module("as.sortable",[]).constant("sortableConfig",{itemClass:"as-sortable-item",handleClass:"as-sortable-item-handle",placeHolderClass:"as-sortable-placeholder",dragClass:"as-sortable-drag",hiddenClass:"as-sortable-hidden",dragging:"as-sortable-dragging"})}(),function(){"use strict";var mainModule=angular.module("as.sortable");mainModule.factory("$helper",["$document","$window",function($document,$window){return{height:function(element){return element[0].getBoundingClientRect().height},width:function(element){return element[0].getBoundingClientRect().width},offset:function(element,scrollableContainer){var boundingClientRect=element[0].getBoundingClientRect();return scrollableContainer||(scrollableContainer=$document[0].documentElement),{width:boundingClientRect.width||element.prop("offsetWidth"),height:boundingClientRect.height||element.prop("offsetHeight"),top:boundingClientRect.top+($window.pageYOffset||scrollableContainer.scrollTop-scrollableContainer.offsetTop),left:boundingClientRect.left+($window.pageXOffset||scrollableContainer.scrollLeft-scrollableContainer.offsetLeft)}},eventObj:function(event){var obj=event;return void 0!==event.targetTouches?obj=event.targetTouches.item(0):void 0!==event.originalEvent&&void 0!==event.originalEvent.targetTouches&&(obj=event.originalEvent.targetTouches.item(0)),obj},isTouchInvalid:function(event){var touchInvalid=!1;return void 0!==event.touches&&event.touches.length>1?touchInvalid=!0:void 0!==event.originalEvent&&void 0!==event.originalEvent.touches&&event.originalEvent.touches.length>1&&(touchInvalid=!0),touchInvalid},positionStarted:function(event,target,scrollableContainer){var pos={};return pos.offsetX=event.pageX-this.offset(target,scrollableContainer).left,pos.offsetY=event.pageY-this.offset(target,scrollableContainer).top,pos.startX=pos.lastX=event.pageX,pos.startY=pos.lastY=event.pageY,pos.nowX=pos.nowY=pos.distX=pos.distY=pos.dirAx=0,pos.dirX=pos.dirY=pos.lastDirX=pos.lastDirY=pos.distAxX=pos.distAxY=0,pos},calculatePosition:function(pos,event){pos.lastX=pos.nowX,pos.lastY=pos.nowY,pos.nowX=event.pageX,pos.nowY=event.pageY,pos.distX=pos.nowX-pos.lastX,pos.distY=pos.nowY-pos.lastY,pos.lastDirX=pos.dirX,pos.lastDirY=pos.dirY,pos.dirX=0===pos.distX?0:pos.distX>0?1:-1,pos.dirY=0===pos.distY?0:pos.distY>0?1:-1;var newAx=Math.abs(pos.distX)>Math.abs(pos.distY)?1:0;pos.dirAx!==newAx?(pos.distAxX=0,pos.distAxY=0):(pos.distAxX+=Math.abs(pos.distX),0!==pos.dirX&&pos.dirX!==pos.lastDirX&&(pos.distAxX=0),pos.distAxY+=Math.abs(pos.distY),0!==pos.dirY&&pos.dirY!==pos.lastDirY&&(pos.distAxY=0)),pos.dirAx=newAx},movePosition:function(event,element,pos,container,containerPositioning,scrollableContainer){var bounds,useRelative="relative"===containerPositioning;element.x=event.pageX-pos.offsetX,element.y=event.pageY-pos.offsetY,container&&(bounds=this.offset(container,scrollableContainer),useRelative&&(element.x-=bounds.left,element.y-=bounds.top,bounds.left=0,bounds.top=0),element.x=bounds.width+bounds.left-this.offset(element).width&&(element.x=bounds.width+bounds.left-this.offset(element).width),element.y=bounds.height+bounds.top-this.offset(element).height&&(element.y=bounds.height+bounds.top-this.offset(element).height)),element.css({left:element.x+"px",top:element.y+"px"}),this.calculatePosition(pos,event)},dragItem:function(item){return{index:item.index(),parent:item.sortableScope,source:item,targetElement:null,targetElementOffset:null,sourceInfo:{index:item.index(),itemScope:item.itemScope,sortableScope:item.sortableScope},canMove:function(itemPosition,targetElement,targetElementOffset){return this.targetElement!==targetElement?(this.targetElement=targetElement,this.targetElementOffset=targetElementOffset,!0):itemPosition.dirX*(targetElementOffset.left-this.targetElementOffset.left)>0||itemPosition.dirY*(targetElementOffset.top-this.targetElementOffset.top)>0?(this.targetElementOffset=targetElementOffset,!0):!1},moveTo:function(parent,index){this.parent=parent,this.isSameParent()&&this.source.index()-1&&(removedItem=$scope.modelValue.splice(index,1)[0]),removedItem},$scope.isEmpty=function(){return $scope.modelValue&&0===$scope.modelValue.length},$scope.accept=function(sourceItemHandleScope,destScope,destItemScope){return $scope.callbacks.accept(sourceItemHandleScope,destScope,destItemScope)}}]),mainModule.directive("asSortable",function(){return{require:"ngModel",restrict:"A",scope:!0,controller:"as.sortable.sortableController",link:function(scope,element,attrs,ngModelController){var ngModel,callbacks;ngModel=ngModelController,ngModel&&(ngModel.$render=function(){scope.modelValue=ngModel.$modelValue},scope.element=element,element.data("_scope",scope),callbacks={accept:null,orderChanged:null,itemMoved:null,dragStart:null,dragMove:null,dragCancel:null,dragEnd:null},callbacks.accept=function(sourceItemHandleScope,destSortableScope,destItemScope){return!0},callbacks.orderChanged=function(event){},callbacks.itemMoved=function(event){},callbacks.dragStart=function(event){},callbacks.dragMove=angular.noop,callbacks.dragCancel=function(event){},callbacks.dragEnd=function(event){},scope.$watch(attrs.asSortable,function(newVal,oldVal){angular.forEach(newVal,function(value,key){callbacks[key]?"function"==typeof value&&(callbacks[key]=value):scope.options[key]=value}),scope.callbacks=callbacks},!0),angular.isDefined(attrs.isDisabled)&&scope.$watch(attrs.isDisabled,function(newVal,oldVal){angular.isUndefined(newVal)||(scope.isDisabled=newVal)},!0))}}})}(),function(){"use strict";function isParent(possibleParent,elem){return elem&&"HTML"!==elem.nodeName?elem.parentNode===possibleParent?!0:isParent(possibleParent,elem.parentNode):!1}var mainModule=angular.module("as.sortable");mainModule.controller("as.sortable.sortableItemHandleController",["$scope",function($scope){this.scope=$scope,$scope.itemScope=null,$scope.type="handle"}]),mainModule.directive("asSortableItemHandle",["sortableConfig","$helper","$window","$document","$timeout",function(sortableConfig,$helper,$window,$document,$timeout){return{require:"^asSortableItem",scope:!0,restrict:"A",controller:"as.sortable.sortableItemHandleController",link:function(scope,element,attrs,itemController){function insertBefore(targetElement,targetScope){"table-row"!==placeHolder.css("display")&&placeHolder.css("display","block"),targetScope.sortableScope.options.clone||(targetElement[0].parentNode.insertBefore(placeHolder[0],targetElement[0]),dragItemInfo.moveTo(targetScope.sortableScope,targetScope.index()))}function insertAfter(targetElement,targetScope){"table-row"!==placeHolder.css("display")&&placeHolder.css("display","block"),targetScope.sortableScope.options.clone||(targetElement.after(placeHolder),dragItemInfo.moveTo(targetScope.sortableScope,targetScope.index()+1))}function fetchScope(element){for(var scope;!scope&&element.length;)scope=element.data("_scope"),scope||(element=element.parent());return scope}function rollbackDragChanges(){scope.itemScope.sortableScope.cloning||placeElement.replaceWith(scope.itemScope.element),placeHolder.remove(),dragElement.remove(),dragElement=null,dragHandled=!1,containment.css("cursor",""),containment.removeClass("as-sortable-un-selectable")}var dragElement,placeHolder,placeElement,itemPosition,dragItemInfo,containment,containerPositioning,dragListen,scrollableContainer,dragStart,dragMove,dragEnd,dragCancel,isDraggable,placeHolderIndex,bindDrag,unbindDrag,bindEvents,unBindEvents,hasTouch,isIOS,longTouchStart,longTouchCancel,longTouchTimer,dragHandled,createPlaceholder,isPlaceHolderPresent,escapeListen,isDisabled=!1,isLongTouch=!1;hasTouch="ontouchstart"in $window,isIOS=/iPad|iPhone|iPod/.test($window.navigator.userAgent)&&!$window.MSStream,sortableConfig.handleClass&&element.addClass(sortableConfig.handleClass),scope.itemScope=itemController.scope,element.data("_scope",scope),scope.$watchGroup(["sortableScope.isDisabled","sortableScope.options.longTouch"],function(newValues){isDisabled!==newValues[0]?(isDisabled=newValues[0],isDisabled?unbindDrag():bindDrag()):isLongTouch!==newValues[1]?(isLongTouch=newValues[1],unbindDrag(),bindDrag()):bindDrag()}),scope.$on("$destroy",function(){angular.element($document[0].body).unbind("keydown",escapeListen)}),createPlaceholder=function(itemScope){return"function"==typeof scope.sortableScope.options.placeholder?angular.element(scope.sortableScope.options.placeholder(itemScope)):"string"==typeof scope.sortableScope.options.placeholder?angular.element(scope.sortableScope.options.placeholder):angular.element($document[0].createElement(itemScope.element.prop("tagName")))},dragListen=function(event){var startPosition,unbindMoveListen=function(){angular.element($document).unbind("mousemove",moveListen),angular.element($document).unbind("touchmove",moveListen),element.unbind("mouseup",unbindMoveListen),element.unbind("touchend",unbindMoveListen),element.unbind("touchcancel",unbindMoveListen)},moveListen=function(e){e.preventDefault();var eventObj=$helper.eventObj(e);startPosition||(startPosition={clientX:eventObj.clientX,clientY:eventObj.clientY}),Math.abs(eventObj.clientX-startPosition.clientX)+Math.abs(eventObj.clientY-startPosition.clientY)>10&&(unbindMoveListen(),dragStart(event))};angular.element($document).bind("mousemove",moveListen),angular.element($document).bind("touchmove",moveListen),element.bind("mouseup",unbindMoveListen),element.bind("touchend",unbindMoveListen),element.bind("touchcancel",unbindMoveListen),event.stopPropagation()},dragStart=function(event){var eventObj,tagName;(hasTouch||2!==event.button&&3!==event.which)&&(hasTouch&&$helper.isTouchInvalid(event)||!dragHandled&&isDraggable(event)&&(dragHandled=!0,event.preventDefault(),eventObj=$helper.eventObj(event),scope.sortableScope=scope.sortableScope||scope.itemScope.sortableScope,scope.callbacks=scope.callbacks||scope.itemScope.callbacks,scope.itemScope.sortableScope.options.clone||scope.itemScope.sortableScope.options.ctrlClone&&event.ctrlKey?scope.itemScope.sortableScope.cloning=!0:scope.itemScope.sortableScope.cloning=!1,scrollableContainer=angular.element($document[0].querySelector(scope.sortableScope.options.scrollableContainer)).length>0?$document[0].querySelector(scope.sortableScope.options.scrollableContainer):$document[0].documentElement,containment=scope.sortableScope.options.containment?$helper.findAncestor(element,scope.sortableScope.options.containment):angular.element($document[0].body),containment.css("cursor","move"),containment.css("cursor","-webkit-grabbing"),containment.css("cursor","-moz-grabbing"),containment.addClass("as-sortable-un-selectable"),containerPositioning=scope.sortableScope.options.containerPositioning||"absolute",dragItemInfo=$helper.dragItem(scope),tagName=scope.itemScope.element.prop("tagName"),dragElement=angular.element($document[0].createElement(scope.sortableScope.element.prop("tagName"))).addClass(scope.sortableScope.element.attr("class")).addClass(sortableConfig.dragClass),dragElement.css("width",$helper.width(scope.itemScope.element)+"px"),dragElement.css("height",$helper.height(scope.itemScope.element)+"px"),placeHolder=createPlaceholder(scope.itemScope).addClass(sortableConfig.placeHolderClass).addClass(scope.sortableScope.options.additionalPlaceholderClass),placeHolder.css("width",$helper.width(scope.itemScope.element)+"px"),placeHolder.css("height",$helper.height(scope.itemScope.element)+"px"),placeElement=angular.element($document[0].createElement(tagName)),sortableConfig.hiddenClass&&placeElement.addClass(sortableConfig.hiddenClass),itemPosition=$helper.positionStarted(eventObj,scope.itemScope.element,scrollableContainer),scope.itemScope.sortableScope.options.clone||scope.itemScope.element.after(placeHolder),scope.itemScope.sortableScope.cloning?dragElement.append(scope.itemScope.element.clone()):(scope.itemScope.element.after(placeElement),dragElement.append(scope.itemScope.element)),containment.append(dragElement),$helper.movePosition(eventObj,dragElement,itemPosition,containment,containerPositioning,scrollableContainer),scope.sortableScope.$apply(function(){scope.callbacks.dragStart(dragItemInfo.eventArgs())}),bindEvents()))},isDraggable=function(event){var elementClicked,sourceScope,isDraggable;for(elementClicked=angular.element(event.target),sourceScope=fetchScope(elementClicked),isDraggable=sourceScope&&"handle"===sourceScope.type;isDraggable&&elementClicked[0]!==element[0];)$helper.noDrag(elementClicked)&&(isDraggable=!1),elementClicked=elementClicked.parent();return isDraggable},dragMove=function(event){var eventObj,targetX,targetY,targetScope,targetElement;if((!hasTouch||!$helper.isTouchInvalid(event))&&dragHandled&&dragElement){if(event.preventDefault(),eventObj=$helper.eventObj(event),scope.callbacks.dragMove!==angular.noop&&scope.sortableScope.$apply(function(){scope.callbacks.dragMove(itemPosition,containment,eventObj)}),targetX=eventObj.pageX-$document[0].documentElement.scrollLeft,targetY=eventObj.pageY-($window.pageYOffset||$document[0].documentElement.scrollTop),dragElement.addClass(sortableConfig.hiddenClass),targetElement=angular.element($document[0].elementFromPoint(targetX,targetY)),dragElement.removeClass(sortableConfig.hiddenClass),$helper.movePosition(eventObj,dragElement,itemPosition,containment,containerPositioning,scrollableContainer),dragElement.addClass(sortableConfig.dragging),targetScope=fetchScope(targetElement),!targetScope||!targetScope.type)return;if("handle"===targetScope.type&&(targetScope=targetScope.itemScope),"item"!==targetScope.type&&"sortable"!==targetScope.type)return;if("item"===targetScope.type&&targetScope.accept(scope,targetScope.sortableScope,targetScope)){targetElement=targetScope.element;var targetElementOffset=$helper.offset(targetElement,scrollableContainer);if(!dragItemInfo.canMove(itemPosition,targetElement,targetElementOffset))return;var placeholderIndex=placeHolderIndex(targetScope.sortableScope.element);0>placeholderIndex?insertBefore(targetElement,targetScope):placeholderIndex<=targetScope.index()?insertAfter(targetElement,targetScope):insertBefore(targetElement,targetScope)}"sortable"===targetScope.type&&targetScope.accept(scope,targetScope)&&!isParent(targetScope.element[0],targetElement[0])&&(isPlaceHolderPresent(targetElement)||targetScope.options.clone||(targetElement[0].appendChild(placeHolder[0]),dragItemInfo.moveTo(targetScope,targetScope.modelValue.length)))}},placeHolderIndex=function(targetElement){var itemElements,i;if(targetElement.hasClass(sortableConfig.placeHolderClass))return 0;for(itemElements=targetElement.children(),i=0;i=0},dragEnd=function(event){dragHandled&&(event.preventDefault(),dragElement&&(rollbackDragChanges(),dragItemInfo.apply(),scope.sortableScope.$apply(function(){dragItemInfo.isSameParent()?dragItemInfo.isOrderChanged()&&scope.callbacks.orderChanged(dragItemInfo.eventArgs()):scope.callbacks.itemMoved(dragItemInfo.eventArgs())}),scope.sortableScope.$apply(function(){scope.callbacks.dragEnd(dragItemInfo.eventArgs())}),dragItemInfo=null),unBindEvents())},dragCancel=function(event){dragHandled&&(event.preventDefault(),dragElement&&(rollbackDragChanges(),scope.sortableScope.$apply(function(){scope.callbacks.dragCancel(dragItemInfo.eventArgs())}),dragItemInfo=null),unBindEvents())},bindDrag=function(){hasTouch&&(isLongTouch?isIOS?(element.bind("touchstart",longTouchStart),element.bind("touchend",longTouchCancel),element.bind("touchmove",longTouchCancel)):element.bind("contextmenu",dragListen):element.bind("touchstart",dragListen)),element.bind("mousedown",dragListen)},unbindDrag=function(){element.unbind("touchstart",longTouchStart),element.unbind("touchend",longTouchCancel),element.unbind("touchmove",longTouchCancel),element.unbind("contextmenu",dragListen),element.unbind("touchstart",dragListen),element.unbind("mousedown",dragListen)},longTouchStart=function(event){longTouchTimer=$timeout(function(){dragListen(event)},500)},longTouchCancel=function(){$timeout.cancel(longTouchTimer)},escapeListen=function(event){27===event.keyCode&&dragCancel(event)},angular.element($document[0].body).bind("keydown",escapeListen),bindEvents=function(){angular.element($document).bind("touchmove",dragMove),angular.element($document).bind("touchend",dragEnd),angular.element($document).bind("touchcancel",dragCancel),angular.element($document).bind("mousemove",dragMove),angular.element($document).bind("mouseup",dragEnd)},unBindEvents=function(){angular.element($document).unbind("touchend",dragEnd),angular.element($document).unbind("touchcancel",dragCancel),angular.element($document).unbind("touchmove",dragMove),angular.element($document).unbind("mouseup",dragEnd),angular.element($document).unbind("mousemove",dragMove)}}}}])}(),function(){"use strict";var mainModule=angular.module("as.sortable");mainModule.controller("as.sortable.sortableItemController",["$scope",function($scope){this.scope=$scope,$scope.sortableScope=null,$scope.modelValue=null,$scope.type="item",$scope.index=function(){return $scope.$index},$scope.itemData=function(){return $scope.sortableScope.modelValue[$scope.$index]}}]),mainModule.directive("asSortableItem",["sortableConfig",function(sortableConfig){return{require:["^asSortable","?ngModel"],restrict:"A",controller:"as.sortable.sortableItemController",link:function(scope,element,attrs,ctrl){var sortableController=ctrl[0],ngModelController=ctrl[1];sortableConfig.itemClass&&element.addClass(sortableConfig.itemClass),scope.sortableScope=sortableController.scope,ngModelController?ngModelController.$render=function(){scope.modelValue=ngModelController.$modelValue}:scope.modelValue=sortableController.scope.modelValue[scope.$index],scope.element=element,element.data("_scope",scope)}}}])}(); \ No newline at end of file +!function(){"use strict";angular.module("as.sortable",[]).constant("sortableConfig",{itemClass:"as-sortable-item",handleClass:"as-sortable-item-handle",placeHolderClass:"as-sortable-placeholder",dragClass:"as-sortable-drag",hiddenClass:"as-sortable-hidden",dragging:"as-sortable-dragging"})}(),function(){"use strict";var mainModule=angular.module("as.sortable");mainModule.factory("$helper",["$document","$window",function($document,$window){return{height:function(element){return element[0].getBoundingClientRect().height},width:function(element){return element[0].getBoundingClientRect().width},offset:function(element,scrollableContainer){var boundingClientRect=element[0].getBoundingClientRect();return scrollableContainer||(scrollableContainer=$document[0].documentElement),{width:boundingClientRect.width||element.prop("offsetWidth"),height:boundingClientRect.height||element.prop("offsetHeight"),top:boundingClientRect.top+($window.pageYOffset||scrollableContainer.scrollTop-scrollableContainer.offsetTop),left:boundingClientRect.left+($window.pageXOffset||scrollableContainer.scrollLeft-scrollableContainer.offsetLeft)}},eventObj:function(event){var obj=event;return void 0!==event.targetTouches?obj=event.targetTouches.item(0):void 0!==event.originalEvent&&void 0!==event.originalEvent.targetTouches&&(obj=event.originalEvent.targetTouches.item(0)),obj},isTouchInvalid:function(event){var touchInvalid=!1;return void 0!==event.touches&&event.touches.length>1?touchInvalid=!0:void 0!==event.originalEvent&&void 0!==event.originalEvent.touches&&event.originalEvent.touches.length>1&&(touchInvalid=!0),touchInvalid},positionStarted:function(event,target,scrollableContainer){var pos={};return pos.offsetX=event.pageX-this.offset(target,scrollableContainer).left,pos.offsetY=event.pageY-this.offset(target,scrollableContainer).top,pos.startX=pos.lastX=event.pageX,pos.startY=pos.lastY=event.pageY,pos.nowX=pos.nowY=pos.distX=pos.distY=pos.dirAx=0,pos.dirX=pos.dirY=pos.lastDirX=pos.lastDirY=pos.distAxX=pos.distAxY=0,pos},calculatePosition:function(pos,event){pos.lastX=pos.nowX,pos.lastY=pos.nowY,pos.nowX=event.pageX,pos.nowY=event.pageY,pos.distX=pos.nowX-pos.lastX,pos.distY=pos.nowY-pos.lastY,pos.lastDirX=pos.dirX,pos.lastDirY=pos.dirY,pos.dirX=0===pos.distX?0:pos.distX>0?1:-1,pos.dirY=0===pos.distY?0:pos.distY>0?1:-1;var newAx=Math.abs(pos.distX)>Math.abs(pos.distY)?1:0;pos.dirAx!==newAx?(pos.distAxX=0,pos.distAxY=0):(pos.distAxX+=Math.abs(pos.distX),0!==pos.dirX&&pos.dirX!==pos.lastDirX&&(pos.distAxX=0),pos.distAxY+=Math.abs(pos.distY),0!==pos.dirY&&pos.dirY!==pos.lastDirY&&(pos.distAxY=0)),pos.dirAx=newAx},movePosition:function(event,element,pos,container,containerPositioning,scrollableContainer){var bounds,useRelative="relative"===containerPositioning;element.x=event.pageX-pos.offsetX,element.y=event.pageY-pos.offsetY,container&&(bounds=this.offset(container,scrollableContainer),useRelative&&(element.x-=bounds.left,element.y-=bounds.top,bounds.left=0,bounds.top=0),element.x=bounds.width+bounds.left-this.offset(element).width&&(element.x=bounds.width+bounds.left-this.offset(element).width),element.y=bounds.height+bounds.top-this.offset(element).height&&(element.y=bounds.height+bounds.top-this.offset(element).height)),element.css({left:element.x+"px",top:element.y+"px"}),this.calculatePosition(pos,event)},dragItem:function(item){return{index:item.index(),parent:item.sortableScope,source:item,targetElement:null,targetElementOffset:null,sourceInfo:{index:item.index(),itemScope:item.itemScope,sortableScope:item.sortableScope},canMove:function(itemPosition,targetElement,targetElementOffset){return this.targetElement!==targetElement?(this.targetElement=targetElement,this.targetElementOffset=targetElementOffset,!0):itemPosition.dirX*(targetElementOffset.left-this.targetElementOffset.left)>0||itemPosition.dirY*(targetElementOffset.top-this.targetElementOffset.top)>0?(this.targetElementOffset=targetElementOffset,!0):!1},moveTo:function(parent,index){this.parent=parent,this.isSameParent()&&this.source.index()-1&&(removedItem=$scope.modelValue.splice(index,1)[0]),removedItem},$scope.isEmpty=function(){return $scope.modelValue&&0===$scope.modelValue.length},$scope.accept=function(sourceItemHandleScope,destScope,destItemScope){return $scope.callbacks.accept(sourceItemHandleScope,destScope,destItemScope)}}]),mainModule.directive("asSortable",function(){return{require:"ngModel",restrict:"A",scope:!0,controller:"as.sortable.sortableController",link:function(scope,element,attrs,ngModelController){var ngModel,callbacks;ngModel=ngModelController,ngModel&&(ngModel.$render=function(){scope.modelValue=ngModel.$modelValue},scope.element=element,element.data("_scope",scope),callbacks={accept:null,orderChanged:null,itemMoved:null,dragStart:null,dragMove:null,dragCancel:null,dragEnd:null},callbacks.accept=function(sourceItemHandleScope,destSortableScope,destItemScope){return!0},callbacks.orderChanged=function(event){},callbacks.itemMoved=function(event){},callbacks.dragStart=function(event){},callbacks.dragMove=angular.noop,callbacks.dragCancel=function(event){},callbacks.dragEnd=function(event){},scope.$watch(attrs.asSortable,function(newVal,oldVal){angular.forEach(newVal,function(value,key){callbacks[key]?"function"==typeof value&&(callbacks[key]=value):scope.options[key]=value}),scope.callbacks=callbacks},!0),angular.isDefined(attrs.isDisabled)&&scope.$watch(attrs.isDisabled,function(newVal,oldVal){angular.isUndefined(newVal)||(scope.isDisabled=newVal)},!0))}}})}(),function(){"use strict";function isParent(possibleParent,elem){return elem&&"HTML"!==elem.nodeName?elem.parentNode===possibleParent?!0:isParent(possibleParent,elem.parentNode):!1}var mainModule=angular.module("as.sortable");mainModule.controller("as.sortable.sortableItemHandleController",["$scope",function($scope){this.scope=$scope,$scope.itemScope=null,$scope.type="handle"}]),mainModule.directive("asSortableItemHandle",["sortableConfig","$helper","$window","$document","$timeout",function(sortableConfig,$helper,$window,$document,$timeout){return{require:"^asSortableItem",scope:!0,restrict:"A",controller:"as.sortable.sortableItemHandleController",link:function(scope,element,attrs,itemController){function insertBefore(targetElement,targetScope){"table-row"!==placeHolder.css("display")&&placeHolder.css("display","block"),targetScope.sortableScope.options.clone||(targetElement[0].parentNode.insertBefore(placeHolder[0],targetElement[0]),dragItemInfo.moveTo(targetScope.sortableScope,targetScope.index()))}function insertAfter(targetElement,targetScope){"table-row"!==placeHolder.css("display")&&placeHolder.css("display","block"),targetScope.sortableScope.options.clone||(targetElement.after(placeHolder),dragItemInfo.moveTo(targetScope.sortableScope,targetScope.index()+1))}function fetchScope(element){for(var scope;!scope&&element.length;)scope=element.data("_scope"),scope||(element=element.parent());return scope}function rollbackDragChanges(){scope.itemScope.sortableScope.cloning||placeElement.replaceWith(scope.itemScope.element),placeHolder.remove(),dragElement.remove(),dragElement=null,dragHandled=!1,containment.css("cursor",""),containment.removeClass("as-sortable-un-selectable")}var dragElement,placeHolder,placeElement,itemPosition,dragItemInfo,containment,containerPositioning,dragListen,scrollableContainer,dragStart,dragMove,dragEnd,dragCancel,isDraggable,placeHolderIndex,bindDrag,unbindDrag,bindEvents,unBindEvents,hasTouch,isIOS,longTouchStart,longTouchCancel,longTouchTimer,dragHandled,createPlaceholder,isPlaceHolderPresent,escapeListen,isDisabled=!1,isLongTouch=!1;hasTouch="ontouchstart"in $window,isIOS=/iPad|iPhone|iPod/.test($window.navigator.userAgent)&&!$window.MSStream,sortableConfig.handleClass&&element.addClass(sortableConfig.handleClass),scope.itemScope=itemController.scope,element.data("_scope",scope),scope.$watchGroup(["sortableScope.isDisabled","sortableScope.options.longTouch"],function(newValues){isDisabled!==newValues[0]?(isDisabled=newValues[0],isDisabled?unbindDrag():bindDrag()):isLongTouch!==newValues[1]?(isLongTouch=newValues[1],unbindDrag(),bindDrag()):bindDrag()}),scope.$on("$destroy",function(){angular.element($document[0].body).unbind("keydown",escapeListen)}),createPlaceholder=function(itemScope){return"function"==typeof scope.sortableScope.options.placeholder?angular.element(scope.sortableScope.options.placeholder(itemScope)):"string"==typeof scope.sortableScope.options.placeholder?angular.element(scope.sortableScope.options.placeholder):angular.element($document[0].createElement(itemScope.element.prop("tagName")))},dragListen=function(event){var startPosition,unbindMoveListen=function(){angular.element($document).unbind("mousemove",moveListen),angular.element($document).unbind("touchmove",moveListen),element.unbind("mouseup",unbindMoveListen),element.unbind("touchend",unbindMoveListen),element.unbind("touchcancel",unbindMoveListen)},moveListen=function(e){e.preventDefault();var eventObj=$helper.eventObj(e);startPosition||(startPosition={clientX:eventObj.clientX,clientY:eventObj.clientY}),Math.abs(eventObj.clientX-startPosition.clientX)+Math.abs(eventObj.clientY-startPosition.clientY)>10&&(unbindMoveListen(),dragStart(event))};angular.element($document).bind("mousemove",moveListen),angular.element($document).bind("touchmove",moveListen),element.bind("mouseup",unbindMoveListen),element.bind("touchend",unbindMoveListen),element.bind("touchcancel",unbindMoveListen),event.stopPropagation()},dragStart=function(event){var eventObj,tagName;(hasTouch||2!==event.button&&3!==event.which)&&(hasTouch&&$helper.isTouchInvalid(event)||!dragHandled&&isDraggable(event)&&(dragHandled=!0,event.preventDefault(),eventObj=$helper.eventObj(event),scope.sortableScope=scope.sortableScope||scope.itemScope.sortableScope,scope.callbacks=scope.callbacks||scope.itemScope.callbacks,scope.itemScope.sortableScope.options.clone||scope.itemScope.sortableScope.options.ctrlClone&&event.ctrlKey?scope.itemScope.sortableScope.cloning=!0:scope.itemScope.sortableScope.cloning=!1,scrollableContainer=angular.element($document[0].querySelector(scope.sortableScope.options.scrollableContainer)).length>0?$document[0].querySelector(scope.sortableScope.options.scrollableContainer):$document[0].documentElement,containment=scope.sortableScope.options.containment?$helper.findAncestor(element,scope.sortableScope.options.containment):angular.element($document[0].body),containment.css("cursor","move"),containment.css("cursor","-webkit-grabbing"),containment.css("cursor","-moz-grabbing"),containment.addClass("as-sortable-un-selectable"),containerPositioning=scope.sortableScope.options.containerPositioning||"absolute",dragItemInfo=$helper.dragItem(scope.itemScope),tagName=scope.itemScope.element.prop("tagName"),dragElement=angular.element($document[0].createElement(scope.sortableScope.element.prop("tagName"))).addClass(scope.sortableScope.element.attr("class")).addClass(sortableConfig.dragClass),dragElement.css("width",$helper.width(scope.itemScope.element)+"px"),dragElement.css("height",$helper.height(scope.itemScope.element)+"px"),placeHolder=createPlaceholder(scope.itemScope).addClass(sortableConfig.placeHolderClass).addClass(scope.sortableScope.options.additionalPlaceholderClass),placeHolder.css("width",$helper.width(scope.itemScope.element)+"px"),placeHolder.css("height",$helper.height(scope.itemScope.element)+"px"),placeElement=angular.element($document[0].createElement(tagName)),sortableConfig.hiddenClass&&placeElement.addClass(sortableConfig.hiddenClass),itemPosition=$helper.positionStarted(eventObj,scope.itemScope.element,scrollableContainer),scope.itemScope.sortableScope.options.clone||scope.itemScope.element.after(placeHolder),scope.itemScope.sortableScope.cloning?dragElement.append(scope.itemScope.element.clone()):(scope.itemScope.element.after(placeElement),dragElement.append(scope.itemScope.element)),containment.append(dragElement),$helper.movePosition(eventObj,dragElement,itemPosition,containment,containerPositioning,scrollableContainer),scope.sortableScope.$apply(function(){scope.callbacks.dragStart(dragItemInfo.eventArgs())}),bindEvents()))},isDraggable=function(event){var elementClicked,sourceScope,isDraggable;for(elementClicked=angular.element(event.target),sourceScope=fetchScope(elementClicked),isDraggable=sourceScope&&"handle"===sourceScope.type;isDraggable&&elementClicked[0]!==element[0];)$helper.noDrag(elementClicked)&&(isDraggable=!1),elementClicked=elementClicked.parent();return isDraggable},dragMove=function(event){var eventObj,targetX,targetY,targetScope,targetElement;if((!hasTouch||!$helper.isTouchInvalid(event))&&dragHandled&&dragElement){if(event.preventDefault(),eventObj=$helper.eventObj(event),scope.callbacks.dragMove!==angular.noop&&scope.sortableScope.$apply(function(){scope.callbacks.dragMove(itemPosition,containment,eventObj)}),targetX=eventObj.pageX-$document[0].documentElement.scrollLeft,targetY=eventObj.pageY-($window.pageYOffset||$document[0].documentElement.scrollTop),dragElement.addClass(sortableConfig.hiddenClass),targetElement=angular.element($document[0].elementFromPoint(targetX,targetY)),dragElement.removeClass(sortableConfig.hiddenClass),$helper.movePosition(eventObj,dragElement,itemPosition,containment,containerPositioning,scrollableContainer),dragElement.addClass(sortableConfig.dragging),targetScope=fetchScope(targetElement),!targetScope||!targetScope.type)return;if("handle"===targetScope.type&&(targetScope=targetScope.itemScope),"item"!==targetScope.type&&"sortable"!==targetScope.type)return;if("item"===targetScope.type&&targetScope.accept(scope,targetScope.sortableScope,targetScope)){targetElement=targetScope.element;var targetElementOffset=$helper.offset(targetElement,scrollableContainer);if(!dragItemInfo.canMove(itemPosition,targetElement,targetElementOffset))return;var placeholderIndex=placeHolderIndex(targetScope.sortableScope.element);0>placeholderIndex?insertBefore(targetElement,targetScope):placeholderIndex<=targetScope.index()?insertAfter(targetElement,targetScope):insertBefore(targetElement,targetScope)}"sortable"===targetScope.type&&targetScope.accept(scope,targetScope)&&!isParent(targetScope.element[0],targetElement[0])&&(isPlaceHolderPresent(targetElement)||targetScope.options.clone||(targetElement[0].appendChild(placeHolder[0]),dragItemInfo.moveTo(targetScope,targetScope.modelValue.length)))}},placeHolderIndex=function(targetElement){var itemElements,i;if(targetElement.hasClass(sortableConfig.placeHolderClass))return 0;for(itemElements=targetElement.children(),i=0;i=0},dragEnd=function(event){dragHandled&&(event.preventDefault(),dragElement&&(rollbackDragChanges(),dragItemInfo.apply(),scope.sortableScope.$apply(function(){dragItemInfo.isSameParent()?dragItemInfo.isOrderChanged()&&scope.callbacks.orderChanged(dragItemInfo.eventArgs()):scope.callbacks.itemMoved(dragItemInfo.eventArgs())}),scope.sortableScope.$apply(function(){scope.callbacks.dragEnd(dragItemInfo.eventArgs())}),dragItemInfo=null),unBindEvents())},dragCancel=function(event){dragHandled&&(event.preventDefault(),dragElement&&(rollbackDragChanges(),scope.sortableScope.$apply(function(){scope.callbacks.dragCancel(dragItemInfo.eventArgs())}),dragItemInfo=null),unBindEvents())},bindDrag=function(){hasTouch&&(isLongTouch?isIOS?(element.bind("touchstart",longTouchStart),element.bind("touchend",longTouchCancel),element.bind("touchmove",longTouchCancel)):element.bind("contextmenu",dragListen):element.bind("touchstart",dragListen)),element.bind("mousedown",dragListen)},unbindDrag=function(){element.unbind("touchstart",longTouchStart),element.unbind("touchend",longTouchCancel),element.unbind("touchmove",longTouchCancel),element.unbind("contextmenu",dragListen),element.unbind("touchstart",dragListen),element.unbind("mousedown",dragListen)},longTouchStart=function(event){longTouchTimer=$timeout(function(){dragListen(event)},500)},longTouchCancel=function(){$timeout.cancel(longTouchTimer)},escapeListen=function(event){27===event.keyCode&&dragCancel(event)},angular.element($document[0].body).bind("keydown",escapeListen),bindEvents=function(){angular.element($document).bind("touchmove",dragMove),angular.element($document).bind("touchend",dragEnd),angular.element($document).bind("touchcancel",dragCancel),angular.element($document).bind("mousemove",dragMove),angular.element($document).bind("mouseup",dragEnd)},unBindEvents=function(){angular.element($document).unbind("touchend",dragEnd),angular.element($document).unbind("touchcancel",dragCancel),angular.element($document).unbind("touchmove",dragMove),angular.element($document).unbind("mouseup",dragEnd),angular.element($document).unbind("mousemove",dragMove)}}}}])}(),function(){"use strict";var mainModule=angular.module("as.sortable");mainModule.controller("as.sortable.sortableItemController",["$scope",function($scope){this.scope=$scope,$scope.sortableScope=null,$scope.modelValue=null,$scope.type="item",$scope.index=function(){return $scope.$index},$scope.itemData=function(){return $scope.sortableScope.modelValue[$scope.$index]}}]),mainModule.directive("asSortableItem",["sortableConfig",function(sortableConfig){return{require:["^asSortable","?ngModel"],restrict:"A",controller:"as.sortable.sortableItemController",link:function(scope,element,attrs,ctrl){var sortableController=ctrl[0],ngModelController=ctrl[1];sortableConfig.itemClass&&element.addClass(sortableConfig.itemClass),scope.sortableScope=sortableController.scope,ngModelController?ngModelController.$render=function(){scope.modelValue=ngModelController.$modelValue}:scope.modelValue=sortableController.scope.modelValue[scope.$index],scope.element=element,element.data("_scope",scope)}}}])}(); \ No newline at end of file