mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-03-13 10:51:24 +00:00
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
This commit is contained in:
@@ -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";
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -240,29 +240,15 @@
|
||||
</div>
|
||||
<div class="scrollView">
|
||||
<ul data-ng-repeat="account in accounts track by account.id">
|
||||
<li><label>{{account.name}}</label></li>
|
||||
<li data-ng-repeat="folder in account.$flattenMailboxes() track by folder.path"
|
||||
data-ng-class="{_selected: folder.id == currentFolder.id}"
|
||||
data-ng-click="setCurrentFolder(account, folder)">
|
||||
<span class="folder-container">
|
||||
<span class="folder-content">
|
||||
<i class="icon icon-ion-folder"
|
||||
data-ng-class="'childLevel' + folder.level"><!-- folder --></i>
|
||||
<form>
|
||||
<a data-ng-cloak="ng-cloak">{{folder.name}}</a>
|
||||
</form>
|
||||
<span class="icon ng-hide" data-ng-cloak="ng-cloak">
|
||||
<a class="icon" href="#"
|
||||
data-dropdown-toggle="#folderProperties"
|
||||
data-options="align:right"><i class="icon-cog"><!-- options --></i></a>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<li>
|
||||
<label>{{account.name}}
|
||||
<button class="icon" label:title="New Folder..."
|
||||
data-ng-click="newFolder(account)"><i class="icon-plus"><!-- new --></i></button></label>
|
||||
</li>
|
||||
<!--<sg-folder-tree data-ng-repeat="folder in account.$mailboxes track by folder.id"
|
||||
<sg-folder-tree data-ng-repeat="folder in account.$mailboxes track by folder.id"
|
||||
data-sg-root="account"
|
||||
data-sg-folder="folder"
|
||||
data-sg-set-folder="setCurrentFolder"> tree </sg-folder-tree>-->
|
||||
data-sg-set-folder="setCurrentFolder"><!-- tree --></sg-folder-tree>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -143,36 +143,28 @@
|
||||
.directive('sgFolderTree', function(RecursionHelper) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
scope: {
|
||||
root: '=sgRoot',
|
||||
folder: '=sgFolder',
|
||||
setFolder: '=sgSetFolder'
|
||||
},
|
||||
template:
|
||||
'<div>' +
|
||||
' <li>' +
|
||||
' <span class="folder-container">' +
|
||||
' <span class="folder-content">' +
|
||||
' <i class="icon icon-ion-folder"></i>' +
|
||||
' <form>' +
|
||||
' <a data-ng-cloak="ng-cloak"' +
|
||||
' >{{folder.name}}</a>' +
|
||||
' </form>' +
|
||||
' <span class="icon ng-hide" data-ng-cloak="ng-cloak">' +
|
||||
' <a class="icon" href="#"' +
|
||||
' data-dropdown-toggle="#folderProperties"' +
|
||||
' data-options="align:right"><i class="icon-cog"></i></a>' +
|
||||
' </span>' +
|
||||
'<li>' +
|
||||
' <span class="folder-container">' +
|
||||
' <span class="folder-content">' +
|
||||
' <i class="icon icon-ion-folder"></i>' +
|
||||
' <form>' +
|
||||
' <a data-ng-cloak="ng-cloak">{{folder.name}}</a>' +
|
||||
' </form>' +
|
||||
' <span class="icon ng-hide" data-ng-cloak="ng-cloak">' +
|
||||
' <a class="icon" href="#"' +
|
||||
' data-dropdown-toggle="#folderProperties"' +
|
||||
' data-options="align:right"><i class="icon-cog"></i></a>' +
|
||||
' </span>' +
|
||||
' </span>' +
|
||||
' </li>' +
|
||||
' <div>' +
|
||||
' <span ng-repeat="child in folder.children track by child.path">' +
|
||||
' <sg-folder-tree data-sg-root="root" data-sg-folder="child" data-sg-set-folder="setFolder"></sg-folder-tree>' +
|
||||
' </span>' +
|
||||
' </div>' +
|
||||
'</div>',
|
||||
' </span>' +
|
||||
'</li>' +
|
||||
'<sg-folder-tree ng-repeat="child in folder.children track by child.path" data-sg-root="root" data-sg-folder="child" data-sg-set-folder="setFolder"></sg-folder-tree>',
|
||||
compile: function(element) {
|
||||
return RecursionHelper.compile(element, function(scope, iElement, iAttrs, controller, transcludeFn) {
|
||||
// Set CSS class for folder hierarchical level
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) });
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user