From 494a8092765aed76c85e5b12a9bd4e2a3ab3b485 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Thu, 18 Dec 2014 15:22:29 -0500 Subject: [PATCH] Improve Mail module - JSONinfied mail folder create and delete actions - restored sgFolderTree directive - extended folder types with "shared" and "otherUsers" - added mailbox creation at the account level --- SoObjects/Mailer/SOGoMailAccount.m | 6 +- UI/MailerUI/UIxMailFolderActions.m | 13 ++-- UI/Templates/MailerUI/UIxMailMainFrame.wox | 26 ++------ UI/WebServerResources/js/Common/ui-desktop.js | 36 ++++------- .../js/Mailer/account-model.js | 25 +++++++- .../js/Mailer/mailbox-model.js | 64 ++++++++++++------- UI/WebServerResources/js/MailerUI.js | 9 +++ UI/WebServerResources/scss/MailerUI.scss | 32 +++++++++- 8 files changed, 137 insertions(+), 74 deletions(-) diff --git a/SoObjects/Mailer/SOGoMailAccount.m b/SoObjects/Mailer/SOGoMailAccount.m index 4350a9bfc..600f2d636 100644 --- a/SoObjects/Mailer/SOGoMailAccount.m +++ b/SoObjects/Mailer/SOGoMailAccount.m @@ -400,7 +400,7 @@ static NSString *inboxFolderName = @"INBOX"; { NSString *folderType; - if ([folderName isEqualToString: [NSString stringWithFormat: @"/%@", inboxFolderName]]) + if ([folderName isEqualToString: inboxFolderName]) folderType = @"inbox"; else if ([folderName isEqualToString: [self draftsFolderNameInContext: context]]) folderType = @"draft"; @@ -408,6 +408,10 @@ static NSString *inboxFolderName = @"INBOX"; folderType = @"sent"; else if ([folderName isEqualToString: [self trashFolderNameInContext: context]]) folderType = @"trash"; + else if ([folderName isEqualToString: otherUsersFolderName]) + folderType = @"otherUsers"; + else if ([folderName isEqualToString: sharedFoldersName]) + folderType = @"shared"; else folderType = @"folder"; diff --git a/UI/MailerUI/UIxMailFolderActions.m b/UI/MailerUI/UIxMailFolderActions.m index 1b45b902b..a88d716ba 100644 --- a/UI/MailerUI/UIxMailFolderActions.m +++ b/UI/MailerUI/UIxMailFolderActions.m @@ -187,6 +187,7 @@ NGImap4Connection *connection; NSException *error; NSURL *srcURL, *destURL; + NSDictionary *jsonResponse; NSMutableDictionary *moduleSettings, *threadsCollapsed; NSString *currentMailbox, *currentAccount, *keyForMsgUIDs; @@ -202,8 +203,10 @@ error = [connection moveMailboxAtURL: srcURL toURL: destURL]; if (error) { - response = [self responseWithStatus: 500]; - [response appendContentString: @"Unable to move folder."]; + jsonResponse = [NSDictionary dictionaryWithObject: [self labelForKey: @"Unable to move folder."] + forKey: @"error"]; + response = [self responseWithStatus: 500 + andString: [jsonResponse jsonRepresentation]]; } else { @@ -232,8 +235,10 @@ } else { - response = [self responseWithStatus: 500]; - [response appendContentString: @"Unable to move folder."]; + jsonResponse = [NSDictionary dictionaryWithObject: [self labelForKey: @"Unable to move folder."] + forKey: @"error"]; + response = [self responseWithStatus: 500 + andString: [jsonResponse jsonRepresentation]]; } return response; diff --git a/UI/Templates/MailerUI/UIxMailMainFrame.wox b/UI/Templates/MailerUI/UIxMailMainFrame.wox index b1d8215db..893c54cb2 100644 --- a/UI/Templates/MailerUI/UIxMailMainFrame.wox +++ b/UI/Templates/MailerUI/UIxMailMainFrame.wox @@ -240,29 +240,15 @@
diff --git a/UI/WebServerResources/js/Common/ui-desktop.js b/UI/WebServerResources/js/Common/ui-desktop.js index e7b64ab69..66e4000ea 100644 --- a/UI/WebServerResources/js/Common/ui-desktop.js +++ b/UI/WebServerResources/js/Common/ui-desktop.js @@ -143,36 +143,28 @@ .directive('sgFolderTree', function(RecursionHelper) { return { restrict: 'E', - replace: true, scope: { root: '=sgRoot', folder: '=sgFolder', setFolder: '=sgSetFolder' }, template: - '
' + - '
  • ' + - ' ' + - ' ' + - ' ' + - '
    ' + - ' {{folder.name}}' + - '
    ' + - ' ' + - ' ' + - ' ' + + '
  • ' + + ' ' + + ' ' + + ' ' + + '
    ' + + ' {{folder.name}}' + + '
    ' + + ' ' + + ' ' + ' ' + '
    ' + - '
  • ' + - '
    ' + - ' ' + - ' ' + - ' ' + - '
    ' + - '
    ', + ' ' + + '' + + '', compile: function(element) { return RecursionHelper.compile(element, function(scope, iElement, iAttrs, controller, transcludeFn) { // Set CSS class for folder hierarchical level diff --git a/UI/WebServerResources/js/Mailer/account-model.js b/UI/WebServerResources/js/Mailer/account-model.js index 1d40c2150..23d9a0e88 100644 --- a/UI/WebServerResources/js/Mailer/account-model.js +++ b/UI/WebServerResources/js/Mailer/account-model.js @@ -70,13 +70,14 @@ * @function $getMailboxes * @memberof Account.prototype * @desc Fetch the list of mailboxes for the current account. + * @param {object} [options] - force a reload * @returns a promise of the HTTP operation */ - Account.prototype.$getMailboxes = function() { + Account.prototype.$getMailboxes = function(options) { var _this = this, deferred = Account.$q.defer(); - if (this.$mailboxes) { + if (this.$mailboxes && !(options && options.reload)) { deferred.resolve(this.$mailboxes); } else { @@ -161,6 +162,26 @@ return mailbox; }; + /** + * @function $newMailbox + * @memberof Account.prototype + * @desc Create a new mailbox on the server and refresh the list of mailboxes. + * @returns a promise of the HTTP operations + */ + Account.prototype.$newMailbox = function(path, name) { + var _this = this, + deferred = Account.$q.defer(); + + Account.$$resource.post(path, 'createFolder', {name: name}).then(function() { + _this.$getMailboxes({reload: true}); + deferred.resolve(); + }, function(response) { + deferred.reject(response.error); + }); + + return deferred.promise; + }; + /** * @function $newMessage * @memberof Account.prototype diff --git a/UI/WebServerResources/js/Mailer/mailbox-model.js b/UI/WebServerResources/js/Mailer/mailbox-model.js index 65b7bd769..558ef7e2d 100644 --- a/UI/WebServerResources/js/Mailer/mailbox-model.js +++ b/UI/WebServerResources/js/Mailer/mailbox-model.js @@ -13,7 +13,15 @@ // Data is immediately available if (typeof futureMailboxData.then !== 'function') { angular.extend(this, futureMailboxData); - this.id = this.$id(); + if (this.name && !this.path) { + // Create a new mailbox on the server + var newMailboxData = Mailbox.$$resource.create('createFolder', this.name); + this.$unwrap(newMailboxData); + } + else { + this.id = this.$id(); + this.isEditable = this.$isEditable(); + } } else { // The promise will be unwrapped first @@ -49,28 +57,6 @@ /* Factory registration in Angular module */ .factory('sgMailbox', Mailbox.$factory); - /** - * @function $delete - * @memberof Mailbox.prototype - * @desc Delete the mailbox from the server - * @returns a promise of the HTTP operation - */ - Mailbox.prototype.$delete = function() { - var _this = this, - d = Mailbox.$q.defer(), - promise; - - promise = Mailbox.$$resource.remove(this.id); - - promise.then(function() { - _this.$account.$getMailboxes(); - d.resolve(true); - }, function(data, status) { - d.reject(data); - }); - return d.promise; - }; - /** * @memberof Mailbox * @desc Fetch list of mailboxes of a specific account @@ -207,6 +193,38 @@ return loaded; }; + /** + * @function $isEditable + * @memberof Mailbox.prototype + * @desc Checks if the mailbox is editable based on its type. + * @returns true if the mailbox is not a special folder. + */ + Mailbox.prototype.$isEditable = function() { + return _.contains(['folder', 'inbox', 'draft', 'sent', 'trash'], this.type); + }; + + /** + * @function $delete + * @memberof Mailbox.prototype + * @desc Delete the mailbox from the server + * @returns a promise of the HTTP operation + */ + Mailbox.prototype.$delete = function() { + var _this = this, + d = Mailbox.$q.defer(), + promise; + + promise = Mailbox.$$resource.remove(this.id); + + promise.then(function() { + _this.$account.$getMailboxes({reload: true}); + d.resolve(true); + }, function(data, status) { + d.reject(data); + }); + return d.promise; + }; + /** * @function $deleteMessages * @memberof Mailbox.prototype diff --git a/UI/WebServerResources/js/MailerUI.js b/UI/WebServerResources/js/MailerUI.js index 70b66ad2d..9c4dbba68 100644 --- a/UI/WebServerResources/js/MailerUI.js +++ b/UI/WebServerResources/js/MailerUI.js @@ -179,6 +179,15 @@ .controller('MailboxesCtrl', ['$scope', '$rootScope', '$stateParams', '$state', '$timeout', '$modal', 'sgFocus', 'encodeUriFilter', 'sgDialog', 'sgAccount', 'sgMailbox', 'stateAccounts', function($scope, $rootScope, $stateParams, $state, $timeout, $modal, focus, encodeUriFilter, Dialog, Account, Mailbox, stateAccounts) { $scope.accounts = stateAccounts; + $scope.newFolder = function(parentFolder) { + Dialog.prompt(l('New folder'), + l('Enter the new name of your folder :')) + .then(function(name) { + if (name && name.length > 0) { + parentFolder.$newMailbox(parentFolder.id, name); + } + }); + }; $scope.setCurrentFolder = function(account, folder) { $rootScope.currentFolder = folder; $state.go('mail.account.mailbox', { accountId: account.id, mailboxId: encodeUriFilter(folder.path) }); diff --git a/UI/WebServerResources/scss/MailerUI.scss b/UI/WebServerResources/scss/MailerUI.scss index b8bef8e7c..7089b5bae 100644 --- a/UI/WebServerResources/scss/MailerUI.scss +++ b/UI/WebServerResources/scss/MailerUI.scss @@ -148,8 +148,6 @@ $column-gutter: 0; #mailboxesList { position: absolute; - overflow: auto; - overflow-x: hidden; top: $topbar-height; bottom: 0; background-color: #333; @@ -157,6 +155,36 @@ $column-gutter: 0; @media #{$medium-up} { @include grid-column($columns:3); } + .newItemsToolbar { + margin-top: rem-calc(6); + text-align: center; + text-transform: uppercase; + } + .scrollView { + position: absolute; + overflow: auto; + overflow-x: hidden; + top: $topbar-height; + bottom: 0; + right: 0; + left: 0; + label { + padding-right: 0; + button { + float: right; + background-color: transparent; + padding: 0; + margin: 0; + width: 32px; + } + } + } + .buttonsToolbar { + border-top: $off-canvas-link-border-bottom; + position: absolute; + bottom: 0px; + width: 100%; + } } #messagesList, #messageEditor {