diff --git a/UI/WebServerResources/Gruntfile.js b/UI/WebServerResources/Gruntfile.js
index a575838c4..3120350be 100644
--- a/UI/WebServerResources/Gruntfile.js
+++ b/UI/WebServerResources/Gruntfile.js
@@ -45,6 +45,7 @@ module.exports = function(grunt) {
'<%= src %>/angular-animate/angular-animate{,.min}.js{,.map}',
'<%= src %>/angular-sanitize/angular-sanitize{,.min}.js{,.map}',
'<%= src %>/angular-ui-router/release/angular-ui-router{,.min}.js',
+ '<%= src %>/angular-recursion/angular-recursion{,.min}.js',
'<%= src %>/angular-foundation/mm-foundation-tpls{,.min}.js',
'<%= src %>/foundation/js/foundation{,.min}.js',
'<%= src %>/ionic/release/js/ionic.bundle{,.min}.js',
diff --git a/UI/WebServerResources/bower.json b/UI/WebServerResources/bower.json
index 128175c2b..4ca677f8c 100644
--- a/UI/WebServerResources/bower.json
+++ b/UI/WebServerResources/bower.json
@@ -6,6 +6,7 @@
"angular-animate": "~1.2",
"angular-ui-router": "~0.2",
"angular-foundation": "~0.3",
+ "angular-recursion": "~1.0",
"foundation": ">5.3",
"ionic": "1.0.0-beta.11",
"underscore": "~1.6"
diff --git a/UI/WebServerResources/js/Common/ui-desktop.js b/UI/WebServerResources/js/Common/ui-desktop.js
index 846477701..18ee36272 100644
--- a/UI/WebServerResources/js/Common/ui-desktop.js
+++ b/UI/WebServerResources/js/Common/ui-desktop.js
@@ -109,7 +109,7 @@
}];
/* Angular module instanciation */
- angular.module('SOGo.UIDesktop', ['mm.foundation'])
+ angular.module('SOGo.UIDesktop', ['mm.foundation', 'RecursionHelper'])
/* Factory registration in Angular module */
.factory('sgDialog', Dialog.$factory)
@@ -128,20 +128,118 @@
};
})
-/*
- * sgDropdownContentToggle - Provides dropdown content functionality
- * @restrict class or attribute
- * @see https://github.com/pineconellc/angular-foundation/blob/master/src/dropdownToggle/dropdownToggle.js
- * @example:
+ /*
+ * sgFolderTree - Provides hierarchical folders tree
+ * @memberof SOGo.UIDesktop
+ * @restrict element
+ * @see https://github.com/marklagendijk/angular-recursion
+ * @example:
- My Dropdown Content
-
- */
+
+ */
+ .directive('sgFolderTree', function(RecursionHelper) {
+ return {
+ restrict: 'E',
+ replace: true,
+ scope: {
+ root: '=sgRoot',
+ folder: '=sgFolder',
+ setFolder: '=sgSetFolder'
+ },
+ template:
+ '' +
+ '
' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ '
' +
+ ' ' +
+ ' ' +
+ ' ' +
+ '
' +
+ '
',
+ compile: function(element) {
+ return RecursionHelper.compile(element, function(scope, iElement, iAttrs, controller, transcludeFn) {
+ // Set CSS class for folder hierarchical level
+ var level = scope.folder.path.split('/').length - 1;
+ angular.element(iElement.find('i')[0]).addClass('childLevel' + level);
+
+ var link = iElement.find('a');
+ link.on('click', function() {
+ var list = iElement.parent();
+ while (list[0].tagName != 'UL') {
+ list = list.parent();
+ }
+ var items = list.find('li');
+
+ // Highlight element as "loading"
+ items.removeClass('_selected');
+ items.removeClass('_loading');
+ angular.element(iElement.find('li')[0]).addClass('_loading');
+
+ // Call external function
+ scope.setFolder(scope.root, scope.folder);
+ });
+ // TODO: rename folder on dbl-click
+ // link.on('dblclick', function() {
+ // });
+ scope.$on('sgSelectFolder', function(event, folderId) {
+ console.debug('select folder ' + folderId + ' = ' + scope.folder.id);
+ if (folderId == scope.folder.id) {
+ var list = iElement.parent();
+ while (list[0].tagName != 'UL') {
+ list = list.parent();
+ }
+ var items = list.find('li');
+
+ // Hightlight element as "selected"
+ angular.element(iElement.find('li')[0]).removeClass('_loading');
+ angular.element(iElement.find('li')[0]).addClass('_selected');
+
+ // Show options button
+ angular.forEach(items, function(element) {
+ var li = angular.element(element);
+ var spans = li.find('span');
+ angular.element(spans[2]).addClass('ng-hide');
+ });
+ angular.element(iElement.find('span')[2]).removeClass('ng-hide');
+ }
+ });
+ });
+ }
+ };
+ })
+
+ /*
+ * sgDropdownContentToggle - Provides dropdown content functionality
+ * @memberof SOGo.UIDesktop
+ * @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;
@@ -244,15 +342,15 @@
};
}])
-/*
- * sgSubscribe - Common subscription widget
- * @restrict class or attribute
- * @param {String} sgSubscribe - the folder type
- * @param {Function} sgSubscribeOnSelect - the function to call when subscribing to a folder
- * @example:
+ /*
+ * sgSubscribe - Common subscription widget
+ * @restrict class or attribute
+ * @param {String} sgSubscribe - the folder type
+ * @param {Function} sgSubscribeOnSelect - the function to call when subscribing to a folder
+ * @example:
-
- */
+
+ */
.directive('sgSubscribe', [function() {
return {
restrict: 'CA',
@@ -279,16 +377,16 @@
};
}])
-/*
- * sgUserTypeahead - 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:
+ /*
+ * sgUserTypeahead - 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', '$position', 'sgUser', function($parse, $q, $timeout, $position, User) {
return {
restrict: 'A',
diff --git a/UI/WebServerResources/js/Common/ui-mobile.js b/UI/WebServerResources/js/Common/ui-mobile.js
index 561997a02..bece843b0 100644
--- a/UI/WebServerResources/js/Common/ui-mobile.js
+++ b/UI/WebServerResources/js/Common/ui-mobile.js
@@ -46,8 +46,51 @@
}];
/* Angular module instanciation */
- angular.module('SOGo.UIMobile', ['ionic'])
+ angular.module('SOGo.UIMobile', ['ionic', 'RecursionHelper'])
/* Factory registration in Angular module */
- .factory('sgDialog', Dialog.$factory);
+ .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'
+ },
+ 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);
+ });
+ }
+ };
+ });
+
})();