From f326ca5ae58effae5505397513ea10859b7d996e Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Thu, 20 Oct 2016 18:28:58 -0400 Subject: [PATCH] Fix saving the note of a card Fixes #3849 --- NEWS | 1 + SoObjects/Contacts/NGVCard+SOGo.m | 3 ++ UI/Contacts/UIxContactEditor.m | 2 +- UI/Contacts/UIxContactView.m | 42 +++++++++--------- .../ContactsUI/UIxContactEditorTemplate.wox | 5 ++- .../ContactsUI/UIxContactViewTemplate.wox | 4 +- .../js/Common/ln2br.filter.js | 21 +++++++++ .../js/Contacts/Card.service.js | 44 ++++++++++--------- 8 files changed, 76 insertions(+), 46 deletions(-) create mode 100644 UI/WebServerResources/js/Common/ln2br.filter.js diff --git a/NEWS b/NEWS index 8067839a07..5ddc441e44 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,7 @@ Bug fixes - [web] improved detection of changes in CKEditor (#3839) - [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] fixed saving the note of a card (#3849) - [eas] improve handling of email folders without a parent - [eas] never send IMIP reply when the "initiator" is Outlook 2013/2016 - [core] only consider SMTP addresses for AD's proxyAddresses (#3842) diff --git a/SoObjects/Contacts/NGVCard+SOGo.m b/SoObjects/Contacts/NGVCard+SOGo.m index ca01b8d7f8..d94b806aa7 100644 --- a/SoObjects/Contacts/NGVCard+SOGo.m +++ b/SoObjects/Contacts/NGVCard+SOGo.m @@ -861,8 +861,11 @@ - (NSCalendarDate *) birthday - (void) setNotes: (NSArray *) newNotes { + NSArray *elements; NSUInteger count, max; + elements = [self childrenWithTag: @"note"]; + [self removeChildren: elements]; max = [newNotes count]; for (count = 0; count < max; count++) { diff --git a/UI/Contacts/UIxContactEditor.m b/UI/Contacts/UIxContactEditor.m index 64aabeac4f..519cecbf1a 100644 --- a/UI/Contacts/UIxContactEditor.m +++ b/UI/Contacts/UIxContactEditor.m @@ -476,7 +476,7 @@ - (void) setAttributes: (NSDictionary *) attributes } } - [card setNote: [attributes objectForKey: @"note"]]; + [card setNotes: [attributes objectForKey: @"notes"]]; if ([[attributes objectForKey: @"categories"] isKindOfClass: [NSArray class]]) { diff --git a/UI/Contacts/UIxContactView.m b/UI/Contacts/UIxContactView.m index f590707de6..23089646ed 100644 --- a/UI/Contacts/UIxContactView.m +++ b/UI/Contacts/UIxContactView.m @@ -705,28 +705,28 @@ - (NSArray *) deliveryAddresses // return [self _cardStringWithLabel: @"Timezone:" value: [card tz]]; // } -- (NSArray *) notes -{ - NSMutableArray *notes; - NSString *note; - NSUInteger count, max; +// - (NSArray *) notes +// { +// NSMutableArray *notes; +// NSString *note; +// NSUInteger count, max; - notes = [NSMutableArray arrayWithArray: [card notes]]; - max = [notes count]; - for (count = 0; count < max; count++) - { - note = [notes objectAtIndex: count]; - note = [note stringByEscapingHTMLString]; - note = [note stringByReplacingString: @"\r\n" - withString: @"
"]; - note = [note stringByReplacingString: @"\n" - withString: @"
"]; - - [notes replaceObjectAtIndex: count withObject: note]; - } +// notes = [NSMutableArray arrayWithArray: [card notes]]; +// max = [notes count]; +// for (count = 0; count < max; count++) +// { +// note = [notes objectAtIndex: count]; +// note = [note stringByEscapingHTMLString]; +// note = [note stringByReplacingString: @"\r\n" +// withString: @"
"]; +// note = [note stringByReplacingString: @"\n" +// withString: @"
"]; + +// [notes replaceObjectAtIndex: count withObject: note]; +// } - return notes; -} +// return notes; +// } /* hrefs */ @@ -888,7 +888,7 @@ - (NSArray *) notes o = [self urls]; if ([o count]) [data setObject: o forKey: @"urls"]; - o = [self notes]; + o = [card notes]; if (o) [data setObject: o forKey: @"notes"]; o = [self _fetchAndCombineCategoriesList]; if (o) [data setObject: o forKey: @"allCategories"]; diff --git a/UI/Templates/ContactsUI/UIxContactEditorTemplate.wox b/UI/Templates/ContactsUI/UIxContactEditorTemplate.wox index 6e58eef62c..95faaf95ba 100644 --- a/UI/Templates/ContactsUI/UIxContactEditorTemplate.wox +++ b/UI/Templates/ContactsUI/UIxContactEditorTemplate.wox @@ -337,9 +337,10 @@ - + - + diff --git a/UI/Templates/ContactsUI/UIxContactViewTemplate.wox b/UI/Templates/ContactsUI/UIxContactViewTemplate.wox index 4944a06aa7..2ba066281c 100644 --- a/UI/Templates/ContactsUI/UIxContactViewTemplate.wox +++ b/UI/Templates/ContactsUI/UIxContactViewTemplate.wox @@ -147,11 +147,11 @@ -
+
-
+
diff --git a/UI/WebServerResources/js/Common/ln2br.filter.js b/UI/WebServerResources/js/Common/ln2br.filter.js new file mode 100644 index 0000000000..1ffaba288d --- /dev/null +++ b/UI/WebServerResources/js/Common/ln2br.filter.js @@ -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, '
') : undefined; + }; + } + + angular.module('SOGo.Common') + .filter('ln2br', ln2br); +})(); diff --git a/UI/WebServerResources/js/Contacts/Card.service.js b/UI/WebServerResources/js/Contacts/Card.service.js index a5266014f5..6db51ebc88 100644 --- a/UI/WebServerResources/js/Contacts/Card.service.js +++ b/UI/WebServerResources/js/Contacts/Card.service.js @@ -140,7 +140,6 @@ this.refs = []; this.categories = []; - this.notes = [this.note]; this.c_screenname = null; angular.extend(this, data); if (!this.$$fullname) @@ -155,6 +154,25 @@ }); if (this.isgroup) 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; // An empty attribute to trick md-autocomplete when adding attendees from the appointment editor @@ -497,12 +515,7 @@ delete _this[key]; } }); - angular.extend(this, 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.init(this.$shadowData); this.$shadowData = this.$omit(true); }; @@ -547,19 +560,6 @@ // Expose the promise this.$futureCardData = futureCardData.then(function(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 _this.$loaded = Card.STATUS.LOADED; // Make a copy of the data for an eventual reset @@ -602,6 +602,10 @@ card.birthday = ''; } + // We flatten the notes to an array of strings + if (this.notes) + card.notes = _.map(this.notes, 'value'); + return card; };