Fix saving the note of a card

Fixes #3849
pull/225/head
Francis Lachapelle 2016-10-20 18:28:58 -04:00
parent 03661eef9e
commit f326ca5ae5
8 changed files with 75 additions and 45 deletions

1
NEWS
View File

@ -14,6 +14,7 @@ Bug fixes
- [web] improved detection of changes in CKEditor (#3839) - [web] improved detection of changes in CKEditor (#3839)
- [web] fixed vCard generation for tags with no type (#3826) - [web] fixed vCard generation for tags with no type (#3826)
- [web] only show the organizer field of an IMIP REPLY if one is defined - [web] only show the organizer field of an IMIP REPLY if one is defined
- [web] fixed saving the note of a card (#3849)
- [eas] improve handling of email folders without a parent - [eas] improve handling of email folders without a parent
- [eas] never send IMIP reply when the "initiator" is Outlook 2013/2016 - [eas] never send IMIP reply when the "initiator" is Outlook 2013/2016
- [core] only consider SMTP addresses for AD's proxyAddresses (#3842) - [core] only consider SMTP addresses for AD's proxyAddresses (#3842)

View File

@ -861,8 +861,11 @@ convention:
- (void) setNotes: (NSArray *) newNotes - (void) setNotes: (NSArray *) newNotes
{ {
NSArray *elements;
NSUInteger count, max; NSUInteger count, max;
elements = [self childrenWithTag: @"note"];
[self removeChildren: elements];
max = [newNotes count]; max = [newNotes count];
for (count = 0; count < max; count++) for (count = 0; count < max; count++)
{ {

View File

@ -476,7 +476,7 @@ static Class SOGoContactGCSEntryK = Nil;
} }
} }
[card setNote: [attributes objectForKey: @"note"]]; [card setNotes: [attributes objectForKey: @"notes"]];
if ([[attributes objectForKey: @"categories"] isKindOfClass: [NSArray class]]) if ([[attributes objectForKey: @"categories"] isKindOfClass: [NSArray class]])
{ {

View File

@ -705,28 +705,28 @@
// return [self _cardStringWithLabel: @"Timezone:" value: [card tz]]; // return [self _cardStringWithLabel: @"Timezone:" value: [card tz]];
// } // }
- (NSArray *) notes // - (NSArray *) notes
{ // {
NSMutableArray *notes; // NSMutableArray *notes;
NSString *note; // NSString *note;
NSUInteger count, max; // NSUInteger count, max;
notes = [NSMutableArray arrayWithArray: [card notes]]; // notes = [NSMutableArray arrayWithArray: [card notes]];
max = [notes count]; // max = [notes count];
for (count = 0; count < max; count++) // for (count = 0; count < max; count++)
{ // {
note = [notes objectAtIndex: count]; // note = [notes objectAtIndex: count];
note = [note stringByEscapingHTMLString]; // note = [note stringByEscapingHTMLString];
note = [note stringByReplacingString: @"\r\n" // note = [note stringByReplacingString: @"\r\n"
withString: @"<br />"]; // withString: @"<br />"];
note = [note stringByReplacingString: @"\n" // note = [note stringByReplacingString: @"\n"
withString: @"<br />"]; // withString: @"<br />"];
[notes replaceObjectAtIndex: count withObject: note]; // [notes replaceObjectAtIndex: count withObject: note];
} // }
return notes; // return notes;
} // }
/* hrefs */ /* hrefs */
@ -888,7 +888,7 @@
o = [self urls]; o = [self urls];
if ([o count]) [data setObject: o forKey: @"urls"]; if ([o count]) [data setObject: o forKey: @"urls"];
o = [self notes]; o = [card notes];
if (o) [data setObject: o forKey: @"notes"]; if (o) [data setObject: o forKey: @"notes"];
o = [self _fetchAndCombineCategoriesList]; o = [self _fetchAndCombineCategoriesList];
if (o) [data setObject: o forKey: @"allCategories"]; if (o) [data setObject: o forKey: @"allCategories"];

View File

@ -337,9 +337,10 @@
</div> </div>
<!-- note --> <!-- note -->
<md-input-container class="md-block md-flex"> <md-input-container class="md-block md-flex"
ng-repeat="note in editor.card.notes">
<label><var:string label:value="Note"/></label> <label><var:string label:value="Note"/></label>
<textarea ng-model="editor.card.note"><!-- note --></textarea> <textarea ng-model="note.value"><!-- note --></textarea>
</md-input-container> </md-input-container>
</form> </form>

View File

@ -147,11 +147,11 @@
</div> </div>
</div> </div>
<div class="section" ng-show="editor.card.notes"> <div class="section" ng-show="editor.card.notes[0].value.length">
<div class="pseudo-input-container" ng-repeat="note in editor.card.notes"> <div class="pseudo-input-container" ng-repeat="note in editor.card.notes">
<label class="pseudo-input-label"><var:string label:value="Note"/></label> <label class="pseudo-input-label"><var:string label:value="Note"/></label>
<div class="pseudo-input-field"> <div class="pseudo-input-field">
<div ng-bind-html="note"><!-- note --></div> <div ng-bind-html="note.value | ln2br"><!-- note --></div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,21 @@
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/**
* ln2br - A filter to convert line feeds and carriage returns to html line breaks
* @memberof SOGo.Common
*/
(function () {
'use strict';
/**
* @ngInject
*/
function ln2br() {
return function(text) {
return text ? String(text).replace(/\r?\n/gm, '<br>') : undefined;
};
}
angular.module('SOGo.Common')
.filter('ln2br', ln2br);
})();

View File

@ -140,7 +140,6 @@
this.refs = []; this.refs = [];
this.categories = []; this.categories = [];
this.notes = [this.note];
this.c_screenname = null; this.c_screenname = null;
angular.extend(this, data); angular.extend(this, data);
if (!this.$$fullname) if (!this.$$fullname)
@ -155,6 +154,25 @@
}); });
if (this.isgroup) if (this.isgroup)
this.c_component = 'vlist'; this.c_component = 'vlist';
if (this.notes && this.notes.length)
this.notes = _.map(this.notes, function(note) { return { 'value': note }; });
else
this.notes = [ { value: '' } ];
// Instanciate Card objects for list members
angular.forEach(this.refs, function(o, i) {
if (o.email) o.emails = [{value: o.email}];
o.id = o.reference;
_this.refs[i] = new Card(o);
});
// Instanciate date object of birthday
if (this.birthday) {
Card.$Preferences.ready().then(function() {
var dlp = Card.$Preferences.$mdDateLocaleProvider;
_this.birthday = _this.birthday.parseDate(dlp, '%Y-%m-%d');
_this.$birthday = dlp.formatDate(_this.birthday);
});
}
this.$loaded = angular.isDefined(this.c_name)? Card.STATUS.LOADED : Card.STATUS.NOT_LOADED; this.$loaded = angular.isDefined(this.c_name)? Card.STATUS.LOADED : Card.STATUS.NOT_LOADED;
// An empty attribute to trick md-autocomplete when adding attendees from the appointment editor // An empty attribute to trick md-autocomplete when adding attendees from the appointment editor
@ -497,12 +515,7 @@
delete _this[key]; delete _this[key];
} }
}); });
angular.extend(this, this.$shadowData); this.init(this.$shadowData);
// Reinstanciate Card objects for list members
angular.forEach(this.refs, function(o, i) {
if (o.email) o.emails = [{value: o.email}];
_this.refs[i] = new Card(o);
});
this.$shadowData = this.$omit(true); this.$shadowData = this.$omit(true);
}; };
@ -547,19 +560,6 @@
// Expose the promise // Expose the promise
this.$futureCardData = futureCardData.then(function(data) { this.$futureCardData = futureCardData.then(function(data) {
_this.init(data); _this.init(data);
// Instanciate Card objects for list members
angular.forEach(_this.refs, function(o, i) {
if (o.email) o.emails = [{value: o.email}];
o.id = o.reference;
_this.refs[i] = new Card(o);
});
if (_this.birthday) {
Card.$Preferences.ready().then(function() {
var dlp = Card.$Preferences.$mdDateLocaleProvider;
_this.birthday = _this.birthday.parseDate(dlp, '%Y-%m-%d');
_this.$birthday = dlp.formatDate(_this.birthday);
});
}
// Mark card as loaded // Mark card as loaded
_this.$loaded = Card.STATUS.LOADED; _this.$loaded = Card.STATUS.LOADED;
// Make a copy of the data for an eventual reset // Make a copy of the data for an eventual reset
@ -602,6 +602,10 @@
card.birthday = ''; card.birthday = '';
} }
// We flatten the notes to an array of strings
if (this.notes)
card.notes = _.map(this.notes, 'value');
return card; return card;
}; };