mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-03-28 01:22:44 +00:00
Add tags input to edit mail recipients
This commit is contained in:
@@ -84,7 +84,7 @@
|
||||
NSString *sourceFolder;
|
||||
NSString *text;
|
||||
NSMutableArray *fromEMails;
|
||||
NSDictionary *from;
|
||||
NSString *from;
|
||||
SOGoMailFolder *sentFolder;
|
||||
BOOL isHTML;
|
||||
|
||||
@@ -114,7 +114,7 @@ static NSArray *infoKeys = nil;
|
||||
@"from", @"inReplyTo",
|
||||
@"replyTo",
|
||||
@"priority", @"receipt",
|
||||
@"content", nil];
|
||||
@"text", nil];
|
||||
}
|
||||
|
||||
- (id) init
|
||||
@@ -245,21 +245,20 @@ static NSArray *infoKeys = nil;
|
||||
ASSIGN (from, newFrom);
|
||||
}
|
||||
|
||||
- (NSDictionary *) _emailFromIdentity: (NSDictionary *) identity
|
||||
- (NSString *) _emailFromIdentity: (NSDictionary *) identity
|
||||
{
|
||||
static NSArray *keys = nil;
|
||||
NSString *fullName, *format;
|
||||
|
||||
if (!keys)
|
||||
{
|
||||
keys = [NSArray arrayWithObjects: @"email", @"fullName", nil];
|
||||
[keys retain];
|
||||
}
|
||||
fullName = [identity objectForKey: @"fullName"];
|
||||
if ([fullName length])
|
||||
format = @"%{fullName} <%{email}>";
|
||||
else
|
||||
format = @"%{email}";
|
||||
|
||||
return [NSDictionary dictionaryWithObjects: [identity objectsForKeys: keys notFoundMarker: [NSNull null]]
|
||||
forKeys: [NSArray arrayWithObjects: @"email", @"name", nil]];
|
||||
return [identity keysWithFormat: format];
|
||||
}
|
||||
|
||||
- (NSDictionary *) from
|
||||
- (NSString *) from
|
||||
{
|
||||
NSDictionary *identity;
|
||||
|
||||
@@ -412,7 +411,7 @@ static NSArray *infoKeys = nil;
|
||||
{
|
||||
NSArray *identities;
|
||||
int count, max;
|
||||
NSDictionary *email;
|
||||
NSString *email;
|
||||
SOGoMailAccount *account;
|
||||
|
||||
if (!fromEMails)
|
||||
@@ -453,7 +452,7 @@ static NSArray *infoKeys = nil;
|
||||
[self setTo: [filteredParams objectForKey: @"to"]];
|
||||
[self setCc: [filteredParams objectForKey: @"cc"]];
|
||||
[self setBcc: [filteredParams objectForKey: @"bcc"]];
|
||||
[self setText: [filteredParams objectForKey: @"content"]];
|
||||
[self setText: [filteredParams objectForKey: @"text"]];
|
||||
|
||||
return filteredParams;
|
||||
}
|
||||
@@ -713,9 +712,9 @@ static NSArray *infoKeys = nil;
|
||||
[self setSourceFolder: [co sourceFolder]];
|
||||
|
||||
data = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSArray arrayWithObject: [self from]], @"from",
|
||||
[self from], @"from",
|
||||
[self localeCode], @"locale",
|
||||
text, @"content",
|
||||
text, @"text",
|
||||
nil];
|
||||
if ((value = [self replyTo]))
|
||||
[data setObject: value forKey: @"replyTo"];
|
||||
|
||||
@@ -10,13 +10,14 @@
|
||||
<form>
|
||||
<label><var:string label:value="From"/>
|
||||
<select name="from"
|
||||
data-ng-model="message.from"
|
||||
data-ng-options="identity.full as identity.full for identity in identities"><!-- from --></select></label>
|
||||
data-ng-model="message.editable.from"
|
||||
data-ng-options="identity for identity in identities"><!-- from --></select></label>
|
||||
<label><var:string label:value="To"/>
|
||||
<input type="text" name="to" ng-model="message.to"/></label>
|
||||
<tags-input type="text" name="to"
|
||||
ng-model="message.editable.to"><!-- to --></tags-input></label>
|
||||
<label><var:string label:value="Subject"/>
|
||||
<input type="text" name="subject" ng-model="message.subject"/></label>
|
||||
<textarea name="content" var:class="editorClass" ng-model="message.content"/>
|
||||
<input type="text" name="subject" ng-model="message.editable.subject"/></label>
|
||||
<textarea name="content" var:class="editorClass" ng-model="message.editable.text"/>
|
||||
<div class="buttonsToolbar">
|
||||
<span>
|
||||
<a class="button tiny radius"
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
title="title"
|
||||
const:userDefaultsKeys="SOGoMailMessageCheck,SOGoRefreshViewCheck,SOGoMailSortByThreads,SOGoMailListViewColumnsOrder,SOGoMailDisplayRemoteInlineImages,SOGoMailComposeMessageType,SOGoMailReplyPlacement"
|
||||
const:userSettingsKeys="Mail"
|
||||
const:jsFiles="Common/resource.js, Mailer/message-model.js, Mailer/mailbox-model.js, Mailer/account-model.js, vendor/ckeditor/ckeditor.js, vendor/ckeditor/ck.js">
|
||||
const:jsFiles="Common/resource.js, Mailer/message-model.js, Mailer/mailbox-model.js, Mailer/account-model.js, vendor/ckeditor/ckeditor.js, vendor/ckeditor/ck.js, vendor/ng-tags-input.js, vendor/angular-file-upload.js"
|
||||
const:cssFiles="ng-tags-input.css">
|
||||
<script type="text/javascript">
|
||||
var mailAccounts = <var:string value="mailAccounts" const:escapeHTML="NO"/>;
|
||||
var userNames = <var:string value="userNames" const:escapeHTML="NO" />;
|
||||
|
||||
@@ -39,8 +39,10 @@ module.exports = function(grunt) {
|
||||
var options = {
|
||||
'src': 'bower_components',
|
||||
'js_dest': 'js/vendor/',
|
||||
'fonts_dest': 'fonts/'
|
||||
'fonts_dest': 'fonts/',
|
||||
'css_dest': 'css/'
|
||||
};
|
||||
grunt.log.subhead('Copying JavaScript files');
|
||||
var js = [
|
||||
'<%= src %>/angular/angular{,.min}.js{,.map}',
|
||||
'<%= src %>/angular-animate/angular-animate{,.min}.js{,.map}',
|
||||
@@ -48,6 +50,8 @@ module.exports = function(grunt) {
|
||||
'<%= src %>/angular-ui-router/release/angular-ui-router{,.min}.js',
|
||||
'<%= src %>/angular-recursion/angular-recursion{,.min}.js',
|
||||
'<%= src %>/angular-vs-repeat/src/angular-vs-repeat{,.min}.js',
|
||||
'<%= src %>/angular-file-upload/angular-file-upload{,.min}.js{,map}',
|
||||
'<%= src %>/ng-tags-input/ng-tags-input{,.min}.js',
|
||||
'<%= src %>/angular-foundation/mm-foundation-tpls{,.min}.js',
|
||||
'<%= src %>/foundation/js/foundation{,.min}.js',
|
||||
'<%= src %>/ionic/release/js/ionic.bundle{,.min}.js',
|
||||
@@ -63,6 +67,7 @@ module.exports = function(grunt) {
|
||||
grunt.log.ok("copy " + src + " => " + dest);
|
||||
}
|
||||
}
|
||||
grunt.log.subhead('Copying font files');
|
||||
var fonts = grunt.file.expand(
|
||||
grunt.template.process('<%= src %>/ionic/release/fonts/ionicons.*',
|
||||
{data: options})
|
||||
@@ -74,6 +79,18 @@ module.exports = function(grunt) {
|
||||
grunt.file.copy(src, dest);
|
||||
grunt.log.ok("copy " + src + " => " + dest);
|
||||
}
|
||||
grunt.log.subhead('Copying CSS files');
|
||||
var css = grunt.file.expand(
|
||||
grunt.template.process('<%= src %>/ng-tags-input/ng-tags-input*.css',
|
||||
{data: options})
|
||||
);
|
||||
for (var i = 0; i < css.length; i++) {
|
||||
var src = css[i];
|
||||
var paths = src.split('/');
|
||||
var dest = options.css_dest + paths[paths.length-1];
|
||||
grunt.file.copy(src, dest);
|
||||
grunt.log.ok("copy " + src + " => " + dest);
|
||||
}
|
||||
});
|
||||
grunt.task.registerTask('build', ['static', 'sass']);
|
||||
grunt.task.registerTask('default', ['build','watch']);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"angular-foundation": "~0.3",
|
||||
"angular-recursion": "~1.0",
|
||||
"angular-vs-repeat": ">=1.0",
|
||||
"ng-tags-input": "~2.0",
|
||||
"foundation": ">5.3",
|
||||
"ionic": "1.0.0-beta.11",
|
||||
"underscore": "~1.6"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
angular.module('SOGo.Common', []);
|
||||
|
||||
angular.module('SOGo.MailerUI', ['ngSanitize', 'ui.router', 'mm.foundation', 'vs-repeat', 'ck', 'SOGo.Common', 'SOGo.UICommon', 'SOGo.UIDesktop'])
|
||||
angular.module('SOGo.MailerUI', ['ngSanitize', 'ui.router', 'mm.foundation', 'vs-repeat', 'ck', 'ngTagsInput', 'SOGo.Common', 'SOGo.UICommon', 'SOGo.UIDesktop'])
|
||||
|
||||
.constant('sgSettings', {
|
||||
baseURL: ApplicationBaseURL,
|
||||
@@ -18,7 +18,7 @@
|
||||
}
|
||||
})
|
||||
|
||||
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
|
||||
.config(['$stateProvider', '$urlRouterProvider', 'tagsInputConfigProvider', function($stateProvider, $urlRouterProvider, tagsInputConfigProvider) {
|
||||
$stateProvider
|
||||
.state('mail', {
|
||||
url: '/Mail',
|
||||
@@ -112,6 +112,11 @@
|
||||
templateUrl: 'editorTemplate', // UI/Templates/MailerUI/UIxMailEditor.wox
|
||||
controller: 'MessageEditorCtrl'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
stateContent: ['stateMessage', function(stateMessage) {
|
||||
return stateMessage.$editableContent();
|
||||
}]
|
||||
}
|
||||
})
|
||||
.state('mail.newMessage', {
|
||||
@@ -133,6 +138,13 @@
|
||||
|
||||
// if none of the above states are matched, use this as the fallback
|
||||
$urlRouterProvider.otherwise('/Mail');
|
||||
|
||||
// Set default configuration for tags input
|
||||
tagsInputConfigProvider.setDefaults('tagsInput', {
|
||||
addOnComma: false,
|
||||
replaceSpacesWithDashes: false,
|
||||
allowedTagsPattern: /([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)/i
|
||||
});
|
||||
}])
|
||||
|
||||
.run(function($rootScope) {
|
||||
@@ -220,16 +232,12 @@
|
||||
.controller('MessageEditorCtrl', ['$scope', '$rootScope', '$stateParams', 'stateAccounts', 'stateMessage', '$timeout', '$modal', 'sgFocus', 'sgDialog', 'sgAccount', 'sgMailbox', function($scope, $rootScope, $stateParams, stateAccounts, stateMessage, $timeout, $modal, focus, Dialog, Account, Mailbox) {
|
||||
if (angular.isDefined(stateMessage)) {
|
||||
$scope.message = stateMessage;
|
||||
// Flatten addresses as strings
|
||||
_.each(['from', 'to', 'cc', 'bcc', 'reply-to'], function(type) {
|
||||
if ($scope.message[type])
|
||||
$scope.message[type] = _.pluck($scope.message[type], 'full').join(', ');
|
||||
});
|
||||
}
|
||||
$scope.identities = _.flatten(_.pluck(stateAccounts, 'identities'));
|
||||
$scope.identities = _.pluck(_.flatten(_.pluck(stateAccounts, 'identities')), 'full');
|
||||
$scope.send = function(message) {
|
||||
message.$send().then(function(data) {
|
||||
console.debug('success ' + JSON.stringify(data, undefined, 2));
|
||||
$rootScope.message = null;
|
||||
$state.go('mail.account.mailbox', { accountId: stateAccount.id, mailboxId: encodeUriFilter(stateMailbox.path) });
|
||||
}, function(data) {
|
||||
console.debug('failure ' + JSON.stringify(data, undefined, 2));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user