diff --git a/UI/WebServerResources/js/Common/ui-desktop.js b/UI/WebServerResources/js/Common/ui-desktop.js deleted file mode 100644 index e7bb2f16e..000000000 --- a/UI/WebServerResources/js/Common/ui-desktop.js +++ /dev/null @@ -1,383 +0,0 @@ -/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* JavaScript for common UI services */ - -(function() { - 'use strict'; - - angular.module('SOGo.Common') - - /* - * sgFolderTree - Provides hierarchical folders tree - * @memberof SOGo.Common - * @restrict element - * @param {object} sgRoot - * @param {object} sgFolder - * @param {function} sgSelectFolder - * @see https://github.com/marklagendijk/angular-recursion - * @example: - - - */ - .directive('sgFolderTree', function(RecursionHelper) { - return { - restrict: 'E', - scope: { - root: '=sgRoot', - folder: '=sgFolder', - selectFolder: '=sgSelectFolder' - }, - template: [ - '', - ' ', - ' ', - ' ', - ' '+ - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - '', - '' - ].join(''), - compile: function(element) { - return RecursionHelper.compile(element, function(scope, iElement, iAttrs, controller, transcludeFn) { - var level, link, inputContainer, input, edit; - - // Set CSS class for folder hierarchical level - level = scope.folder.path.split('/').length - 1; - angular.element(iElement.find('i')[0]).addClass('sg-child-level-' + level); - - // Select dynamic elements - link = angular.element(iElement.find('button')[0]); - inputContainer = angular.element(iElement.find('md-input-container')); - input = iElement.find('input')[0]; - - var edit = function() { - link.addClass('ng-hide'); - inputContainer.removeClass('ng-hide'); - input.focus(); - input.select(); - }; - - // jQLite listeners - - // click - call the directive's external function sgSelectFolder - link.on('click', function() { - var list, items; - if (!scope.mode.selected) { - list = iElement.parent(); - while (list[0].tagName != 'MD-LIST') { - list = list.parent(); - } - items = list.find('md-list-item'); - - // Highlight element as "loading" - items.removeClass('sg-active'); - items.removeClass('sg-loading'); - angular.element(iElement.find('md-list-item')[0]).addClass('sg-loading'); - - // Call external function - scope.selectFolder(scope.root, scope.folder); - } - }); - - // dblclick - enter edit mode - link.on('dblclick', function() { - edit(); - }); - - // Broadcast listeners - - // sgSelectFolder - broadcasted when the folder has been successfully loaded - scope.$on('sgSelectFolder', function(event, folderId) { - if (folderId == scope.folder.id) { - var list = iElement.parent(), - items; - - scope.mode.selected = true; - while (list[0].tagName != 'MD-LIST') { - list = list.parent(); - } - items = list.find('md-list-item'); - - // Hightlight element as "selected" - angular.element(iElement.find('md-list-item')[0]).addClass('sg-active'); - angular.element(iElement.find('md-list-item')[0]).removeClass('sg-loading'); - - // Show options button - angular.forEach(items, function(element) { - var li = angular.element(element); - var spans = li.find('span'); - angular.element(spans[0]).addClass('ng-hide'); - }); - angular.element(iElement.find('span')[0]).removeClass('ng-hide'); - } - else { - scope.mode.selected = false; - } - }); - - // sgEditFolder - broadcasted when the user wants to rename the folder - scope.$on('sgEditFolder', function(event, folderId) { - if (scope.mode.selected && folderId == scope.folder.id) { - edit(); - } - }); - - // Local scope variables and functions - - scope.mode = { selected: false }; - - scope.save = function() { - if (link.hasClass('ng-hide')) { - inputContainer.addClass('ng-hide'); - link.removeClass('ng-hide'); - scope.$emit('sgSaveFolder', scope.folder.id); - } - }; - - scope.revert = function() { - scope.$emit('sgRevertFolder', scope.folder.id); - }; - }); - } - }; - }) - - /* - * sgDropdownContentToggle - Provides dropdown content functionality - * @memberof SOGo.Common - * @restrict class or attribute - * @see https://github.com/pineconellc/angular-foundation/blob/master/src/dropdownToggle/dropdownToggle.js - * @example: - - My Dropdown Content - - */ - /* - .directive('sgDropdownContentToggle', ['$document', '$window', '$location', '$position', function ($document, $window, $location, $position) { - var openElement = null, - closeMenu = angular.noop; - return { - restrict: 'CA', // class and attribute - scope: { - dropdownToggle: '@sgDropdownContentToggle' - }, - link: function(scope, element, attrs, controller) { - var dropdown = angular.element($document[0].querySelector(scope.dropdownToggle)); - - scope.$watch('$location.path', function() { - closeMenu(); - }); - element.bind('click', function(event) { - var elementWasOpen = (element === openElement); - - event.preventDefault(); - event.stopPropagation(); - - if (!!openElement) { - closeMenu(); - } - - if (!elementWasOpen && !element.hasClass('disabled') && !element.prop('disabled')) { - dropdown.css('display', 'block'); - - var offset = $position.offset(element), - dropdownParentOffset = $position.offset(angular.element(dropdown[0].offsetParent)), - dropdownWidth = dropdown.prop('offsetWidth'), - dropdownHeight = dropdown.prop('offsetHeight'), - dropdownCss = {}, - left = Math.round(offset.left - dropdownParentOffset.left), - rightThreshold = $window.innerWidth - dropdownWidth - 8, - nub = angular.element(dropdown.children()[0]), - nubCss = {}; - - if (left > rightThreshold) { - // There's more place on the left side of the element - left = rightThreshold; - dropdown.removeClass('left').addClass('right'); - nub.removeClass('left').addClass('right'); - } - - dropdownCss.position = null; - dropdownCss['max-width'] = null; - // Place a third of the dropdown above the element - dropdownCss.top = Math.round(offset.top + offset.height / 2 - dropdownHeight / 3), - dropdownCss.left = Math.round(offset.left + offset.width + 10); - - if (dropdownCss.top + dropdownHeight > $window.innerHeight) { - // Position dropdown at the very top of the window - dropdownCss.top = $window.innerHeight - dropdownHeight - 5; - if (dropdownHeight > $window.innerHeight) { - // Resize height of dropdown to fit window - dropdownCss.top = 5; - dropdownCss.height = ($window.innerHeight - 10) + 'px'; - } - } - - // Place nub beside the element - nubCss.top = Math.round(offset.top - dropdownCss.top + offset.height / 2 - nub.prop('offsetHeight') / 2) + 'px'; - - // Apply CSS - dropdownCss.top += 'px'; - dropdownCss.left += 'px'; - dropdown.css(dropdownCss); - nub.css(nubCss); - - openElement = element; - closeMenu = function (event) { - if (event) { - // We ignore clicks that occur inside the dropdown content element, unless it's a button - var target = angular.element(event.target), - ignoreClick = false; - while (target[0]) { - if (target[0].tagName == 'BUTTON') break; - if (target[0] == dropdown[0]) { - ignoreClick = true; - break; - } - target = target.parent(); - } - if (ignoreClick) return; - } - - $document.unbind('click', closeMenu); - dropdown.css('display', 'none'); - closeMenu = angular.noop; - openElement = null; - }; - $document.bind('click', closeMenu); - } - }); - - if (dropdown) { - dropdown.css('display', 'none'); - } - } - }; - }]) - */ - - /* - * UserTypeahead - Typeahead of users, used internally by sgSubscribe - * @restrict attribute - * @param {String} sgModel - the folder type - * @param {Function} sgSubscribeOnSelect - the function to call when subscribing to a folder - * @see https://github.com/pineconellc/angular-foundation/blob/master/src/typeahead/typeahead.js - * @example: - -
- */ - .directive('sgUserTypeahead', ['$parse', '$q', '$timeout', 'User', function($parse, $q, $timeout, User) { - return { - restrict: 'A', - require: 'ngModel', - link: function(originalScope, element, attrs, controller) { - - var hasFocus, - scope, - resetMatches, - getMatchesAsync, - // Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later - timeoutPromise, - // Minimal number of characters that needs to be entered before typeahead kicks-in - minSearch = originalScope.$eval(attrs.sgSubscribeMinLength) || 3, - // Minimal wait time after last character typed before typehead kicks-in - waitTime = originalScope.$eval(attrs.sgSubscribeWaitMs) || 500, - // Binding to a variable that indicates if matches are being retrieved asynchronously - isLoadingSetter = $parse(attrs.sgSubscribeLoading).assign || angular.noop; - - // Create a child scope for the typeahead directive so we are not polluting original scope - // with typeahead-specific data (users, query, etc.) - scope = originalScope.$new(); - originalScope.$on('$destroy', function(){ - scope.$destroy(); - }); - - resetMatches = function() { - originalScope.users = []; - originalScope.selectedUser = undefined; - scope.activeIdx = -1; - }; - - getMatchesAsync = function(inputValue) { - isLoadingSetter(originalScope, true); - $q.when(User.$filter(inputValue)).then(function(matches) { - // It might happen that several async queries were in progress if a user were typing fast - // but we are interested only in responses that correspond to the current view value - if (inputValue === controller.$viewValue && hasFocus) { - if (matches.length > 0) { - scope.activeIdx = 0; - originalScope.users = matches; - originalScope.query = inputValue; // for the hightlighter - } - else { - resetMatches(); - } - isLoadingSetter(originalScope, false); - } - }, function(){ - resetMatches(); - isLoadingSetter(originalScope, false); - }); - }; - - resetMatches(); - - // We need to propagate user's query so we can higlight matches - originalScope.query = undefined; - - // Plug into $parsers pipeline to open a typeahead on view changes initiated from DOM - // $parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue - controller.$parsers.unshift(function (inputValue) { - if (inputValue && inputValue.length >= minSearch) { - if (waitTime > 0) { - if (timeoutPromise) { - $timeout.cancel(timeoutPromise); // cancel previous timeout - } - timeoutPromise = $timeout(function() { - getMatchesAsync(inputValue); - }, waitTime); - } - else { - getMatchesAsync(inputValue); - } - } - else { - isLoadingSetter(originalScope, false); - resetMatches(); - } - return inputValue; - }); - - element.bind('blur', function (evt) { - hasFocus = false; - }); - - element.bind('focus', function (evt) { - hasFocus = true; - }); - } - }; - }]) - -})(); diff --git a/UI/WebServerResources/js/Common/ui-mobile.js b/UI/WebServerResources/js/Common/ui-mobile.js deleted file mode 100644 index 4f25b812c..000000000 --- a/UI/WebServerResources/js/Common/ui-mobile.js +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* JavaScript for common UI services for mobile theme */ - -(function() { - 'use strict'; - - /** - * @name Dialog - * @constructor - */ - function Dialog() { - } - - Dialog.alert = function(title, content) { - var alertPopup = this.$ionicPopup.alert({ - title: title, - template: content - }); - return alertPopup; - }; - - Dialog.confirm = function(title, content) { - var confirmPopup = this.$ionicPopup.confirm({ - title: title, - template: content - }); - return confirmPopup; - }; - - Dialog.prompt = function(title, content) { - var promptPopup = this.$ionicPopup.prompt({ - title: title, - inputPlaceholder: content - }); - return promptPopup; - }; - - /** - * @memberof Dialog - * @desc The factory we'll register as sgDialog in the Angular module SOGo.UIMobile - */ - Dialog.$factory = ['$ionicPopup', function($ionicPopup) { - angular.extend(Dialog, { $ionicPopup: $ionicPopup }); - - return Dialog; // return constructor - }]; - - /* Angular module instanciation */ - angular.module('SOGo.UIMobile', ['ionic', 'RecursionHelper']) - - /* Factory registration in Angular module */ - .factory('sgDialog', Dialog.$factory) - - /* - * sgFolderTree - Provides hierarchical folders tree - * @memberof SOGo.UIDesktop - * @restrict element - * @see https://github.com/marklagendijk/angular-recursion - * @example: - - - */ - .directive("sgFolderTree", function(RecursionHelper) { - return { - restrict: "E", - scope: { - root: '=sgRoot', - folder: '=sgFolder', - setFolder: '=sgSetFolder', - edit: '=sgEdit' - }, - template: - '' + - ' {{folder.name}}' + - ' ' + - ' {{"Edit" | loc}}' + - '' + - '
' + - ' ' + - ' ' + - ' ' + - '
', - compile: function(element) { - return RecursionHelper.compile(element, function(scope, iElement, iAttrs, controller, transcludeFn) { - var level = scope.folder.path.split('/').length - 1; - iElement.find('ion-item').addClass('childLevel' + level); - }); - } - }; - }); - -})(); diff --git a/UI/WebServerResources/js/mobile/ContactsUI.js b/UI/WebServerResources/js/mobile/ContactsUI.js deleted file mode 100644 index 190a144c0..000000000 --- a/UI/WebServerResources/js/mobile/ContactsUI.js +++ /dev/null @@ -1,568 +0,0 @@ -/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* JavaScript for SOGo.ContactsUI (mobile) module */ - -(function() { - 'use strict'; - - angular.module('SOGo.Common', []); - - angular.module('SOGo.ContactsUI', ['ionic', 'SOGo.Common', 'SOGo.UIMobile']) - - .constant('sgSettings', { - baseURL: ApplicationBaseURL, - activeUser: { - login: UserLogin, - language: UserLanguage, - folderURL: UserFolderURL, - isSuperUser: IsSuperUser - } - }) - - .run(function($ionicPlatform) { - $ionicPlatform.ready(function() { - // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard - // for form inputs) - if (window.cordova && window.cordova.plugins.Keyboard) { - cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true); - } - if (window.StatusBar) { - // org.apache.cordova.statusbar required - StatusBar.styleDefault(); - } - }); - }) - - .config(function($stateProvider, $urlRouterProvider) { - $stateProvider - .state('app', { - url: '/app', - abstract: true, - templateUrl: 'menu.html', - controller: 'AppCtrl' - }) - - .state('app.addressbooks', { - url: '/addressbooks', - views: { - menuContent: { - templateUrl: 'addressbooks.html', - controller: 'AddressBooksCtrl' - } - } - }) - - .state('app.addressbook', { - url: '/addressbook/:addressbookId', - views: { - menuContent: { - templateUrl: 'addressbook.html', - controller: 'AddressBookCtrl', - resolve: { - stateAddressbook: ['$stateParams', 'sgAddressBook', function($stateParams, AddressBook) { - return AddressBook.$find($stateParams.addressbookId); - }] - } - } - } - }) - - .state('app.newCard', { - url: '/addressbook/:addressbookId/:contactType/new', - views: { - menuContent: { - templateUrl: 'card.html', - controller: 'CardCtrl', - resolve: { - stateCard: ['$rootScope', '$stateParams', 'sgAddressBook', 'sgCard', function($rootScope, $stateParams, sgAddressBook, Card) { - var tag = 'v' + $stateParams.contactType; - if (!$rootScope.addressbook) { - $rootScope.addressbook = sgAddressBook.$find($stateParams.addressbookId); - } - return new Card( - { - pid: $stateParams.addressbookId, - tag: tag, - isNew: true - } - ); - }] - } - } - } - }) - - .state('app.card', { - url: '/addressbook/:addressbookId/:cardId', - views: { - menuContent: { - templateUrl: 'card.html', - controller: 'CardCtrl', - resolve: { - stateCard: ['$rootScope', '$stateParams', 'sgAddressBook', function($rootScope, $stateParams, AddressBook) { - if (!$rootScope.addressbook) { - $rootScope.addressbook = AddressBook.$find($stateParams.addressbookId); - } - return $rootScope.addressbook.$getCard($stateParams.cardId); - }] - } - } - } - }); - - // if none of the above states are matched, use this as the fallback - $urlRouterProvider.otherwise('/app/addressbooks'); - }) - - // Inspired from http://codepen.io/gastonbesada/pen/eqvJK - .directive('ionSearch', function() { - return { - restrict: 'E', - replace: true, - scope: { - getData: '=source', - clearData: '&clear', - model: '=?', - search: '=?filter' - }, - link: function(scope, element, attrs) { - attrs.minLength = attrs.minLength || 0; - scope.placeholder = attrs.placeholder || ''; - scope.search = {value: ''}; - - if (attrs.class) - element.addClass(attrs.class); - - if (attrs.source) { - scope.$watch('search.value', function(newValue, oldValue) { - if (newValue.length > attrs.minLength) { - scope.getData(newValue).then(function(results) { - scope.model = results; - }); - } - }); - } - scope.clearSearch = function() { - scope.search.value = ''; - scope.clearData(); - }; - }, - template: '
' + - '' + - '' + - '' + - '
' - }; - }) - - .controller('AppCtrl', ['$scope', '$http', function($scope, $http) { - $scope.UserLogin = UserLogin; - $scope.UserFolderURL = UserFolderURL; - $scope.ApplicationBaseURL = ApplicationBaseURL; - // $scope.logout = function(url) { - // $http.get(url) - // .success(function(data, status, headers) { - // console.debug(headers); - // }); - // }; - }]) - - .controller('AddressBooksCtrl', ['$scope', '$state', '$rootScope', '$ionicModal', '$ionicListDelegate', '$ionicActionSheet', 'sgDialog', 'sgAddressBook', 'sgUser', function($scope, $state, $rootScope, $ionicModal, $ionicListDelegate, $ionicActionSheet, Dialog, AddressBook, User) { - // Initialize with data from template - $scope.addressbooks = AddressBook.$findAll(contactFolders); - $scope.newAddressbook = function() { - Dialog.prompt(l('Create addressbook'), - l('Name of new addressbook')) - .then(function(res) { - if (res && res.length > 0) { - var addressbook = new AddressBook( - { - name: res, - isEditable: true, - isRemote: false - } - ); - AddressBook.$add(addressbook); - } - }); - }; - $scope.edit = function(addressbook) { - $ionicActionSheet.show({ - buttons: [ - { text: l('Rename') }, - { text: l('Set Access Rights') } - ], - destructiveText: l('Delete'), - cancelText: l('Cancel'), - buttonClicked: function(index) { - if (index == 0) { - // Rename - Dialog.prompt(l('Rename addressbook'), addressbook.name) - .then(function(name) { - if (name && name.length > 0) { - addressbook.$rename(name); // TODO check error - } - }); - } - else if (index == 1) { - // Set Access Rights - $ionicModal.fromTemplateUrl('acl-modal.html', { scope: $scope }).then(function(modal) { - var aclUsers = {}; - - function refreshUsers(users) { - $scope.users = []; - $scope.search.active = false; - angular.forEach(users, function(user) { - user.inAclList = true; - $scope.users.push(user); - aclUsers[user.uid] = user; - }) - }; - - if ($scope.aclEditorModal) { - $scope.aclEditorModal.remove(); - } - - $scope.title = addressbook.name; - $scope.aclEditorModal = modal; - $scope.showDelete = false; - $scope.search = {active: false}; - - // Load ACL users - addressbook.$acl.$users().then(function(users) { - refreshUsers(users); - }, function(data, status) { - Dialog.alert(l('Warning'), l('An error occurs while trying to fetch users from the server.')); - }); - - $scope.closeModal = function() { - $scope.aclEditorModal.remove(); - }; - $scope.displayIcon = function(user) { - if (user.inAclList) - return ($scope.userIsSelected(user) ? 'ion-ios7-arrow-down' : 'ion-ios7-arrow-right'); - else - return 'ion-plus'; - } - $scope.toggleUser = function(user) { - if (user.inAclList) { - if ($scope.userIsSelected(user)) { - // Close rights editor - delete $scope.selectedUser; - } - else { - // Edit user rights - $scope.editUser(user); - } - } - else { - // Add user - $scope.addUser(user); - } - }; - $scope.userIsSelected = function(user) { - return $scope.selectedUser && $scope.selectedUser.uid == user.uid; - }; - $scope.searchUsers = function(search) { - $scope.users = []; - $scope.search.active = true; - return User.$filter(search).then(function(results) { - angular.forEach(results, function(userFound) { - userFound.inAclList = (aclUsers[userFound.uid]) ? true : false; - $scope.users.push(userFound); - }) - }); - }; - $scope.cancelSearch = function() { - addressbook.$acl.$users().then(function(users) { - refreshUsers(users); - }, function(data, status) { - Dialog.alert(l('Warning'), l('An error occured please try again.')); - }); - }; - $scope.toggleDelete = function(boolean) { - $scope.showDelete = boolean; - }; - $scope.editUser = function(user) { - if ($scope.selectedUser != user) { - $scope.selectedUser = user; - $scope.selectedUser.$rights(); - } - }; - $scope.confirmChange = function(user) { - var confirmation = user.$confirmRights(); - if (confirmation) { - Dialog.confirm(l('Warning'), confirmation).then(function(res) { - if (!res) - user.$resetRights(true); - }); - } - }; - $scope.saveModal = function() { - addressbook.$acl.$saveUsersRights().then(function() { - $scope.aclEditorModal.remove(); - }, function(data, status) { - Dialog.alert(l('Warning'), l('An error occured please try again.')); - }); - }; - $scope.removeUser = function(user) { - if (user) { - addressbook.$acl.$removeUser(user.uid).then(function() { - delete aclUsers[user.uid]; - delete $scope.selectedUser; - $scope.users = _.reject($scope.users, function(o) { - return o.uid == user.uid; - }); - }, function(data, status) { - Dialog.alert(l('Warning'), l('An error occured please try again.')) - }); - } - }; - $scope.addUser = function(user) { - if (user.uid) { - addressbook.$acl.$addUser(user).then(function() { - user.inAclList = true; - aclUsers[user.uid] = user; - }, function(data, status) { - Dialog.alert(l('Warning'), l('An error occured please try again.')) - }); - } - else { - Dialog.alert(l('Warning'), l('Please select a user inside your domain')); - } - }; - - // Show modal - $scope.aclEditorModal.show(); - }); - } - return true; - }, - destructiveButtonClicked: function() { - // Delete addressbook - addressbook.$delete() - .then(function() { - addressbook = null; - }, function(data) { - Dialog.alert(l('An error occured while deleting the addressbook "%{0}".', - addressbook.name), - l(data.error)); - }); - return true; - } - // cancel: function() { - // }, - }); - $ionicListDelegate.closeOptionButtons(); - }; - }]) - - .controller('AddressBookCtrl', ['$scope', '$rootScope', '$stateParams', '$state', '$ionicActionSheet', 'sgAddressBook', 'sgCard', 'stateAddressbook', function($scope, $rootScope, $stateParams, $state, $ionicActionSheet, AddressBook, Card, stateAddressbook) { - $rootScope.addressbook = stateAddressbook; - - $scope.search = { status: null, filter: null, lastFilter: null }; - - $scope.addCard = function() { - $ionicActionSheet.show({ - //titleText: l('Create a new card or a new list'), - buttons: [ - { text: l('New Card') }, - { text: l('New List') } - ], - canceltext: l('Cancel'), - buttonClicked: function(index) { - if (index == 0) { - $state.go('app.newCard', { addressbookId: stateAddressbook.id, contactType: 'card' }); - } - else if (index == 1) { - $state.go('app.newCard', { addressbookId: stateAddressbook.id, contactType: 'list' }); - } - return true; - } - }); - }; - - $scope.doSearch = function(keyEvent) { - if ($scope.search.lastFilter != $scope.search.filter) { - if ($scope.search.filter.length > 2) { - $rootScope.addressbook.$filter($scope.search.filter).then(function(data) { - if (data.length == 0) - $scope.search.status = 'no-result'; - else - $scope.search.status = ''; - }); - } - else if ($scope.search.filter.length == 0) { - $scope.searchStatus = ''; - $rootScope.addressbook = AddressBook.$find($rootScope.addressbook.id); - } - else { - $scope.search.status = 'min-char'; - $rootScope.addressbook.cards = []; - } - } - $scope.search.lastFilter = $scope.search.filter; - }; - }]) - - .controller('CardCtrl', ['$scope', '$rootScope', '$state', '$stateParams', '$ionicModal', '$ionicPopover', 'sgDialog', 'sgAddressBook', 'sgCard', 'stateCard', function($scope, $rootScope, $state, $stateParams, $ionicModal, $ionicPopover, Dialog, AddressBook, Card, stateCard) { - $scope.card = stateCard; - - $scope.UserFolderURL = UserFolderURL; - $scope.allEmailTypes = Card.$EMAIL_TYPES; - $scope.allTelTypes = Card.$TEL_TYPES; - $scope.allUrlTypes = Card.$URL_TYPES; - $scope.allAddressTypes = Card.$ADDRESS_TYPES; - - $scope.search = {query: ''}; - $scope.cardsFilter = function(item) { - var query, id = false; - if (item.tag == 'vcard' && $scope.search.query) { - query = $scope.search.query.toLowerCase(); - if (item.emails && item.emails.length > 0) { - // Is one of the email addresses match the query string? - if (_.find(item.emails, function(email) { - return (email.value.toLowerCase().indexOf(query) >= 0); - })) { - id = item.id; - } - } - if (!id && item.fn) { - // Is the fn attribute matches the query string? - if (item.fn.toLowerCase().indexOf(query) >= 0) { - id = item.id; - } - } - if (id) { - // Is the card already part of the members? If so, ignore it. - if (_.find($scope.card.refs, function(ref) { - return ref.reference == id; - })) { - id = false; - } - } - } - return id; - }; - $scope.resetSearch = function() { - $scope.search.query = null; - }; - $scope.addMember = function(member) { - var i = $scope.card.$addMember(''), - email = member.$preferredEmail($scope.search.query); - $scope.card.$updateMember(i, email, member); - $scope.popover.hide(); - }; - $ionicPopover.fromTemplateUrl('searchFolderContacts.html', { - scope: $scope - }).then(function(popover) { - $scope.popover = popover; - }); - - $scope.edit = function() { - // Build modal editor - $ionicModal.fromTemplateUrl('cardEditor.html', { - scope: $scope, - focusFirstInput: false - }).then(function(modal) { - if ($scope.$cardEditorModal) { - // Delete previous modal - $scope.$cardEditorModal.remove(); - } - $scope.$cardEditorModal = modal; - // Show modal - $scope.$cardEditorModal.show(); - }); - }; - $scope.cancel = function() { - if ($scope.card.isNew) { - $scope.$cardEditorModal.hide().then(function() { - // Go back to addressbook - $state.go('app.addressbook', { addressbookId: $rootScope.addressbook.id }); - }); - } - else { - $scope.card.$reset(); - $scope.$cardEditorModal.hide() - } - }; - $scope.addOrgUnit = function() { - var i = $scope.card.$addOrgUnit(''); - focus('orgUnit_' + i); - }; - $scope.addCategory = function() { - var i = $scope.card.$addCategory(''); - focus('category_' + i); - }; - $scope.addEmail = function() { - var i = $scope.card.$addEmail(''); - focus('email_' + i); - }; - $scope.addPhone = function() { - var i = $scope.card.$addPhone(''); - focus('phone_' + i); - }; - $scope.addUrl = function() { - var i = $scope.card.$addUrl('', ''); - focus('url_' + i); - }; - $scope.addAddress = function() { - var i = $scope.card.$addAddress('', '', '', '', '', '', '', ''); - focus('address_' + i); - }; - $scope.showPopOver = function(keyEvent) { - $scope.popover.show(keyEvent); - } - $scope.save = function(form) { - if (form.$valid) { - $scope.card.$save() - .then(function(data) { - var i; - delete $scope.card.isNew; - i = _.indexOf(_.pluck($rootScope.addressbook.cards, 'id'), $scope.card.id); - if (i < 0) { - // New card - // Reload contacts list and show addressbook in which the card has been created - $rootScope.addressbook = AddressBook.$find(data.pid); - $state.go('app.addressbook', { addressbookId: data.pid }); - } - else { - // Update contacts list with new version of the Card object - $rootScope.addressbook.cards[i] = angular.copy($scope.card); - } - // Close editor - $scope.$cardEditorModal.hide(); - }); - } - }; - $scope.confirmDelete = function(card) { - Dialog.confirm(l('Warning'), - l('Are you sure you want to delete the card of %{0}?', card.$fullname())) - .then(function(res) { - if (res) { - // User confirmed the deletion - card.$delete() - .then(function() { - // Remove card from list of addressbook - $rootScope.addressbook.cards = _.reject($rootScope.addressbook.cards, function(o) { - return o.id == card.id; - }); - // Remove card object from scope - delete $scope.card; - // Delete modal editor - $scope.$cardEditorModal.remove(); - // Go back to addressbook - $state.go('app.addressbook', { addressbookId: $rootScope.addressbook.id }); - }, function(data, status) { - Dialog.alert(l('Warning'), l('An error occured while deleting the card "%{0}".', - card.$fullname())); - }); - } - }); - }; - - if ($scope.card && $scope.card.isNew) { - // New contact - $scope.edit(); - } - }]); -})(); diff --git a/UI/WebServerResources/js/mobile/MailerUI.js b/UI/WebServerResources/js/mobile/MailerUI.js deleted file mode 100644 index 17110cbff..000000000 --- a/UI/WebServerResources/js/mobile/MailerUI.js +++ /dev/null @@ -1,178 +0,0 @@ -/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* JavaScript for SOGo.Mailer (mobile) */ - -(function() { - 'use strict'; - - angular.module('SOGo.Common', []); - - angular.module('SOGo.MailerUI', ['ionic', 'SOGo.Common', 'SOGo.UICommon', 'SOGo.UIMobile']) - - .constant('sgSettings', { - baseURL: ApplicationBaseURL - }) - - .run(function($ionicPlatform) { - $ionicPlatform.ready(function() { - // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard - // for form inputs) - if (window.cordova && window.cordova.plugins.Keyboard) { - cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true); - } - if (window.StatusBar) { - // org.apache.cordova.statusbar required - StatusBar.styleDefault(); - } - }); - }) - - .config(function($stateProvider, $urlRouterProvider) { - $stateProvider - .state('app', { - url: '/app', - abstract: true, - templateUrl: 'menu.html', - controller: 'AppCtrl' - }) - .state('app.mail', { - url: '/mail', - views: { - menuContent: { - templateUrl: 'mailboxes.html', - controller: 'MailboxesCtrl', - } - }, - resolve: { - stateAccounts: ['$q', 'sgAccount', function($q, Account) { - var accounts = Account.$findAll(mailAccounts); - var promises = []; - // Resolve mailboxes of each account - angular.forEach(accounts, function(account, i) { - var mailboxes = account.$getMailboxes(); - promises.push(mailboxes.then(function(objects) { - return account; - })); - }); - return $q.all(promises); - }] - } - }) - .state('app.mail.account', { - url: '/:accountId', - abstract: true, - resolve: { - stateAccount: ['$stateParams', 'stateAccounts', function($stateParams, stateAccounts) { - return _.find(stateAccounts, function(account) { - return account.id == $stateParams.accountId; - }); - }] - } - }) - .state('app.mail.account.mailbox', { - url: '/:mailboxId', - views: { - 'menuContent@app': { - templateUrl: 'mailbox.html', - controller: 'MailboxCtrl' - } - }, - resolve: { - stateMailbox: ['$stateParams', 'stateAccount', 'decodeUriFilter', function($stateParams, stateAccount, decodeUriFilter) { - var mailboxId = decodeUriFilter($stateParams.mailboxId); - // Recursive find function - var _find = function(mailboxes) { - var mailbox = _.find(mailboxes, function(o) { - return o.path == mailboxId; - }); - if (!mailbox) { - angular.forEach(mailboxes, function(o) { - if (!mailbox && o.children && o.children.length > 0) { - mailbox = _find(o.children); - } - }); - } - return mailbox; - }; - return _find(stateAccount.$mailboxes); - }], - stateMessages: ['stateMailbox', function(stateMailbox) { - return stateMailbox.$reload(); - }] - } - }) - .state('app.mail.account.mailbox.message', { - url: "/:messageId", - views: { - 'menuContent@app': { - templateUrl: "message.html", - controller: 'MessageCtrl' - } - }, - resolve: { - stateMessage: ['$stateParams', 'stateMailbox', 'stateMessages', function($stateParams, stateMailbox, stateMessages) { - var message = _.find(stateMessages, function(messageObject) { - return messageObject.uid == $stateParams.messageId; - }); - return message; - }] - } - }); - - - // if none of the above states are matched, use this as the fallback - $urlRouterProvider.otherwise('/app/mail'); - }) - - .controller('AppCtrl', ['$scope', '$http', function($scope, $http) { - $scope.UserLogin = UserLogin; - $scope.UserFolderURL = UserFolderURL; - $scope.ApplicationBaseURL = ApplicationBaseURL; - }]) - - .controller('MailboxesCtrl', ['$scope', '$http', '$state', '$ionicActionSheet', '$ionicListDelegate', 'sgAccount', 'sgMailbox', 'encodeUriFilter', 'stateAccounts', function($scope, $http, $state, $ionicActionSheet, $ionicListDelegate, Account, Mailbox, encodeUriFilter, stateAccounts) { - $scope.accounts = stateAccounts - - $scope.setCurrentFolder = function(account, folder) { - $state.go('app.mail.account.mailbox', { accountId: account.id, mailboxId: encodeUriFilter(folder.path) }); - }; - $scope.edit = function(folder) { - $ionicActionSheet.show({ - buttons: [ - { text: l('Rename') }, - { text: l('Set Access Rights') } - ], - destructiveText: l('Delete'), - cancelText: l('Cancel'), - buttonClicked: function(index) { - // TODO - return true; - }, - destructiveButtonClicked: function() { - // Delete mailbox - folder.$delete() - .then(function() { - folder = null; - }, function(data) { - Dialog.alert(l('An error occured while deleting the mailbox "%{0}".', - folder.name), - l(data.error)); - }); - return true; - } - // cancel: function() { - // }, - }); - $ionicListDelegate.closeOptionButtons(); - }; - }]) - - .controller('MailboxCtrl', ['$scope', 'stateAccount', 'stateMailbox', function($scope, stateAccount, stateMailbox) { - $scope.account = stateAccount; - $scope.mailbox = stateMailbox; - }]) - - .controller('MessageCtrl', ['$scope', '$stateParams', 'stateMessage', function($scope, $stateParams, stateMessage) { - $scope.message = stateMessage; - }]); - -})(); diff --git a/UI/WebServerResources/js/mobile/SOGoRootPage.js b/UI/WebServerResources/js/mobile/SOGoRootPage.js deleted file mode 100644 index b3a0742f6..000000000 --- a/UI/WebServerResources/js/mobile/SOGoRootPage.js +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* JavaScript for SOGoRootPage (mobile) */ - -(function() { - 'use strict'; - - angular.module('SOGo.MainUI', ['SOGo.Authentication', 'SOGo.UIMobile', 'ionic']) - - .constant('sgSettings', { - baseURL: ApplicationBaseURL - }) - - .run(function($ionicPlatform) { - $ionicPlatform.ready(function() { - // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard - // for form inputs) - if(window.cordova && window.cordova.plugins.Keyboard) { - cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true); - } - if(window.StatusBar) { - // org.apache.cordova.statusbar required - StatusBar.styleDefault(); - } - }); - }) - - .config(function($stateProvider, $urlRouterProvider) { - $stateProvider - - .state('app', { - url: '/app', - abstract: true, - templateUrl: 'menu.html', - controller: 'AppCtrl' - }) - - .state('app.login', { - url: '/login', - views: { - menuContent: { - templateUrl: 'login.html', - controller: 'LoginCtrl' - } - } - }); - - // if none of the above states are matched, use this as the fallback - $urlRouterProvider.otherwise('/app/login'); - }) - - .controller('AppCtrl', ['$scope', 'sgSettings', function($scope, Settings) { - $scope.ApplicationBaseURL = Settings.baseURL; - }]) - - .controller('LoginCtrl', ['$scope', 'Authentication', 'sgDialog', function($scope, Authentication, Dialog) { - $scope.creds = { 'username': null, 'password': null }; - $scope.login = function(creds) { - Authentication.login(creds) - .then(function(url) { - window.location.href = url; - }, function(msg) { - Dialog.alert(l('Warning'), msg.error); - }); - }; - }]); -})(); diff --git a/UI/WebServerResources/md-colors/README.md b/UI/WebServerResources/md-colors/README.md deleted file mode 100755 index 7dcea5a0a..000000000 --- a/UI/WebServerResources/md-colors/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Adapted from : http://plnkr.co/edit/SHkXcAQDNPHWloBnVxrw?p=preview - -Author : Sander Elias (https://github.com/SanderElias) \ No newline at end of file diff --git a/UI/WebServerResources/md-colors/colors.js b/UI/WebServerResources/md-colors/colors.js deleted file mode 100755 index 2ba9893e0..000000000 --- a/UI/WebServerResources/md-colors/colors.js +++ /dev/null @@ -1,106 +0,0 @@ -(function () { - "use strict"; - - //module global to keep an reference to the dynamic style sheet - var customSheet; - //module global to available color pallettes - var colorStore = {}; - - angular - .module('mdColors',['ngMaterial']) - .service("ThemeColors", ThemeColors) - .config(configColors) - .run(loadDefaults); - - configColors.$inject = ['$mdThemingProvider']; - function configColors($mdThemingProvider) { - //fetch the colores out of the themeing provider - //console.log($mdThemingProvider._THEMES.default.colors.primary.name) - Object.keys($mdThemingProvider._PALETTES).forEach(parsePallete); - return; - - // clone the pallete colors to the colorStore var - function parsePallete(palleteName) { - var pallete = $mdThemingProvider._PALETTES[palleteName]; - var colors = []; - colorStore[palleteName]=colors; - Object.keys(pallete).forEach(copyColors); - return ; - - function copyColors(colorName) { - // use an regex to look for hex colors, ignore the rest - if (/#[0-9A-Fa-f]{6}|0-9A-Fa-f]{8}\b/.exec(pallete[colorName])) { - colors.push({color:colorName,value:pallete[colorName]}); - } - } - } - } - - loadDefaults.$inject=['ThemeColors']; - function loadDefaults(ThemeColors) { - // this sets the default that is stored in the config-fase into the service! - ThemeColors.themes=Object.keys(colorStore); - ThemeColors.loadColors('amber'); - } - - ThemeColors.$inject = ['$interpolate']; - function ThemeColors ($interpolate) { - // wrap all of the above up in a reusable service. - var service = this; - service.theme = 'amber'; - service.colors = []; - service.themes = []; - service.loadColors = loadColors; - - return service; - - function loadColors(newPallete) { - service.theme=newPallete; - service.colors=colorStore[newPallete]; - createStyleSheet(); - } - - function createStyleSheet () { - var colors = service.colors; - var fg, bg; - if (typeof customSheet === 'undefined') { - // use closure for caching the styleSheet - newStyleSheet(); - } else { - // remove existing rules - // TODO: look into disabling/enabling pre-build style-guides - // in stead of delete and recreate! - while (customSheet.cssRules.length > 0 ) { - customSheet.deleteRule(0); - } - } - - // set up interpolation functions to build css rules. - fg = $interpolate('.md-fg-{{color}} { color:{{value}};}'); - bg = $interpolate('.md-bg-{{color}} { background-color:{{value}};}'); - - colors.forEach(function (color) { - // insert foreground color rule - customSheet.insertRule(fg(color)); - // insert background color rule - customSheet.insertRule(bg(color)); - }); - } - } - - function newStyleSheet() { - // function to ad an dynamic style-sheet to the document - var style = document.createElement("style"); - style.title = 'Dynamic Generated my Angular-Material'; - // WebKit hack... (not sure if still needed) - style.appendChild(document.createTextNode("")); - - document.head.appendChild(style); - // store the sheet in the closure for reuse - // creating a new sheet is a 'costly' operation, and I - // just need one. - customSheet = style.sheet; - return style.sheet; - } - -}()); \ No newline at end of file diff --git a/UI/WebServerResources/md-colors/index.html b/UI/WebServerResources/md-colors/index.html deleted file mode 100755 index a8f95249e..000000000 --- a/UI/WebServerResources/md-colors/index.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - MD Template - - - - - - - -
- Hello angular {{vm.version}} -
-
- - - -

Color Pallete Sample

- - -

This is a sample that goes with this github issue

- - - -
-

Select a color-theme above!

-

This wil override the md-bg-[colorname] and md-fg-[colorname] css-rules.

-
- - - - - - - - - - - - - - - - - - - -
colorclassNameresultclassnameresult
{{color.color}}md-fg-{{color.color}}: -
Foreground
-
md-bg-{{color.color}}: -
Background
-
-

Those color will be available application wide, and will not change with local themes.

-
-
- - - - - - - - - - - - - - - diff --git a/UI/WebServerResources/md-colors/script.js b/UI/WebServerResources/md-colors/script.js deleted file mode 100755 index 064f579c4..000000000 --- a/UI/WebServerResources/md-colors/script.js +++ /dev/null @@ -1,20 +0,0 @@ -(function() { - "use strict"; - //Use an IIFE - - AppController.$inject = ['ThemeColors'] - function AppController(ThemeColors) { - this.version = angular.version.full + " " + angular.version.codeName; - - this.th = ThemeColors; - } - - - //Hook up all my function into angular - angular.module('myPlunk', [ - 'ngMaterial', - 'mdColors' - ]) - .controller('AppController', AppController) - -}()); \ No newline at end of file