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.
-
-
-
-
-
- color |
- className |
- result |
- classname |
- result |
-
-
-
- {{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