diff --git a/SoObjects/Appointments/iCalEntityObject+SOGo.m b/SoObjects/Appointments/iCalEntityObject+SOGo.m index c65ec663b..bbb67cf6d 100644 --- a/SoObjects/Appointments/iCalEntityObject+SOGo.m +++ b/SoObjects/Appointments/iCalEntityObject+SOGo.m @@ -103,9 +103,6 @@ NSNumber *iCalDistantFutureNumber = nil; value = [self comment]; if ([value length]) [data setObject: value forKey: @"comment"]; - value = [self attach]; - if (value && (value = [value absoluteString]) && [value length]) [data setObject: value forKey: @"attachUrl"]; - value = [self accessClass]; if ([value length]) [data setObject: [value lowercaseString] forKey: @"classification"]; @@ -365,10 +362,6 @@ NSNumber *iCalDistantFutureNumber = nil; if ([o isKindOfClass: [NSString class]]) [self setComment: [o stringByReplacingString: @"\r\n" withString: @"\n"]]; - o = [data objectForKey: @"attachUrl"]; - if ([o isKindOfClass: [NSString class]]) - [self setAttach: o]; - o = [data objectForKey: @"classification"]; if ([o isKindOfClass: [NSString class]]) [self setAccessClass: [o uppercaseString]]; diff --git a/UI/Scheduler/English.lproj/Localizable.strings b/UI/Scheduler/English.lproj/Localizable.strings index f7c274d25..7a4942cac 100644 --- a/UI/Scheduler/English.lproj/Localizable.strings +++ b/UI/Scheduler/English.lproj/Localizable.strings @@ -258,7 +258,7 @@ "All day Event" = "All day Event"; "check for conflicts" = "Check for conflicts"; -"Browse URL" = "Browse URL"; +"URL" = "URL"; "newAttendee" = "Add attendee"; diff --git a/UI/Scheduler/UIxAppointmentEditor.m b/UI/Scheduler/UIxAppointmentEditor.m index bbda6fec2..c82e36ffc 100644 --- a/UI/Scheduler/UIxAppointmentEditor.m +++ b/UI/Scheduler/UIxAppointmentEditor.m @@ -548,6 +548,8 @@ * @apiParam {Number} [resetAlarm] Mark alarm as triggered if set to 1 * @apiParam {Number} [snoozeAlarm] Snooze the alarm for this number of minutes * + * @apiSuccess {_} . _From [UIxAppointmentEditor viewAction]_ + * * @apiSuccess (Success 200) {String} id Event ID * @apiSuccess (Success 200) {String} pid Calendar ID (event's folder) * @apiSuccess (Success 200) {String} calendar Human readable name of calendar @@ -558,8 +560,10 @@ * @apiSuccess (Success 200) {String} localizedEndDate Formatted end date * @apiSuccess (Success 200) {String} [localizedEndTime] Formatted end time * @apiSuccess (Success 200) {Number} isReadOnly 1 if event is read-only + * @apiSuccess (Success 200) {Object[]} [attachUrls] Attached URLs + * @apiSuccess (Success 200) {String} attachUrls.value URL * - * @apiSuccess {_} . _From [UIxComponentEditor loadAlarm]_ + * @apiSuccess {_} .. _From [UIxComponentEditor alarm]_ * * @apiSuccess (Success 200) {Object[]} [alarm] Alarm definition * @apiSuccess (Success 200) {String} alarm.action Either display or email @@ -572,12 +576,12 @@ * @apiSuccess (Success 200) {String} alarm.attendees.email Attendee's email address * @apiSuccess (Success 200) {String} [alarm.attendees.uid] System user ID * - * @apiSuccess {_} .. _From [iCalEvent+SOGo attributes]_ + * @apiSuccess {_} ... _From [iCalEvent+SOGo attributes]_ * * @apiSuccess (Success 200) {Number} isAllDay 1 if event is all-day * @apiSuccess (Success 200) {Number} isTransparent 1 if the event is not opaque * - * @apiSuccess {_} ... _From [iCalEntityObject+SOGo attributes]_ + * @apiSuccess {_} .... _From [iCalEntityObject+SOGo attributes]_ * * @apiSuccess (Success 200) {Number} sendAppointmentNotifications 1 if notifications must be sent * @apiSuccess (Success 200) {String} component "vevent" @@ -585,7 +589,6 @@ * @apiSuccess (Success 200) {String} [location] Location * @apiSuccess (Success 200) {String} [comment] Comment * @apiSuccess (Success 200) {String} [status] Status (tentative, confirmed, or cancelled) - * @apiSuccess (Success 200) {String} [attachUrl] Attached URL * @apiSuccess (Success 200) {String} [createdBy] Value of custom header X-SOGo-Component-Created-By or organizer's "SENT-BY" * @apiSuccess (Success 200) {Number} priority Priority (0-9) * @apiSuccess (Success 200) {NSString} [classification] Either public, confidential or private @@ -604,7 +607,7 @@ * @apiSuccess (Success 200) {String} [attendees.delegatedTo] User that the original request was delegated to * @apiSuccess (Success 200) {String} [attendees.delegatedFrom] User the request was delegated from * - * @apiSuccess {_} .... _From [iCalRepeatableEntityObject+SOGo attributes]_ + * @apiSuccess {_} ..... _From [iCalRepeatableEntityObject+SOGo attributes]_ * * @apiSuccess (Success 200) {Object} [repeat] Recurrence rule definition * @apiSuccess (Success 200) {String} repeat.frequency Either daily, (every weekday), weekly, (bi-weekly), monthly, or yearly @@ -620,6 +623,7 @@ - (id ) viewAction { BOOL isAllDay; + NSArray *attachUrls; NSMutableDictionary *data; NSCalendarDate *eventStartDate, *eventEndDate; NSTimeZone *timeZone; @@ -685,9 +689,12 @@ [NSNumber numberWithBool: [self isReadOnly]], @"isReadOnly", [dateFormatter formattedDate: eventStartDate], @"localizedStartDate", [dateFormatter formattedDate: eventEndDate], @"localizedEndDate", - [self loadAlarm], @"alarm", + [self alarm], @"alarm", nil]; + attachUrls = [self attachUrls]; + if ([attachUrls count]) [data setObject: attachUrls forKey: @"attachUrls"]; + if (!isAllDay) { [data setObject: [dateFormatter formattedTime: eventStartDate] forKey: @"localizedStartTime"]; diff --git a/UI/Scheduler/UIxComponentEditor.h b/UI/Scheduler/UIxComponentEditor.h index 38c452b00..4d8d75ab5 100644 --- a/UI/Scheduler/UIxComponentEditor.h +++ b/UI/Scheduler/UIxComponentEditor.h @@ -36,7 +36,8 @@ - (BOOL) isReadOnly; - (void) setAttributes: (NSDictionary *) attributes; -- (NSDictionary *) loadAlarm; +- (NSDictionary *) alarm; +- (NSArray *) attachUrls; + (NSArray *) reminderValues; @end diff --git a/UI/Scheduler/UIxComponentEditor.m b/UI/Scheduler/UIxComponentEditor.m index 05309418f..f8207f045 100644 --- a/UI/Scheduler/UIxComponentEditor.m +++ b/UI/Scheduler/UIxComponentEditor.m @@ -545,7 +545,7 @@ static NSArray *reminderValues = nil; } } -- (NSDictionary *) loadAlarm +- (NSDictionary *) alarm { NSArray *attendees; NSMutableDictionary *alarmData; @@ -595,13 +595,41 @@ static NSArray *reminderValues = nil; return alarmData; } +- (NSArray *) attachUrls +{ + NSMutableArray *attachUrls; + NSArray *values; + NSString *attachUrl; + NSUInteger count, max; + + values = [component attach]; + max = [values count]; + if (max > 0) + { + attachUrls = [NSMutableArray arrayWithCapacity: max]; + for (count = 0; count < max; count++) + { + attachUrl = [values objectAtIndex: count]; + if ([attachUrl length] > 0) + [attachUrls addObject: [NSDictionary dictionaryWithObject: attachUrl forKey: @"value"]]; + } + } + else + attachUrls = nil; + + return attachUrls; +} + - (void) setAttributes: (NSDictionary *) data { + NSArray *values; NSCalendarDate *now; + NSMutableArray *attachUrls; NSMutableDictionary *dataWithOwner; NSString *owner; + NSUInteger i; SOGoAppointmentFolders *folders; - id destinationCalendar; + id destinationCalendar, o; now = [NSCalendarDate calendarDate]; owner = [componentCalendar ownerInContext: context]; @@ -624,6 +652,27 @@ static NSArray *reminderValues = nil; [self _handleOrganizer]; + if ([[data objectForKey: @"attachUrls"] isKindOfClass: [NSArray class]]) + { + values = [component childrenWithTag: @"attach"]; + [component removeChildren: values]; + values = [data objectForKey: @"attachUrls"]; + attachUrls = [NSMutableArray arrayWithCapacity: [values count]]; + for (i = 0; i < [values count]; i++) + { + o = [values objectAtIndex: i]; + if ([o isKindOfClass: [NSDictionary class]]) + { + [attachUrls addObject: [o objectForKey: @"value"]]; + } + } + } + else + { + attachUrls = nil; + } + [component setAttach: attachUrls]; + if ([[self clientObject] isNew]) { [component setCreated: now]; diff --git a/UI/Scheduler/UIxTaskEditor.m b/UI/Scheduler/UIxTaskEditor.m index 1f03039d3..d9cd1a252 100644 --- a/UI/Scheduler/UIxTaskEditor.m +++ b/UI/Scheduler/UIxTaskEditor.m @@ -409,7 +409,7 @@ * @apiSuccess (Success 200) {String} completedDate Completed date (ISO8601) * @apiSuccess (Success 200) {Number} percentComplete Percent completion * - * @apiSuccess {_} .. _From [UIxComponentEdtiror loadAlarm]_ + * @apiSuccess {_} .. _From [UIxComponentEdtiror alarm]_ * * @apiSuccess (Success 200) {Object[]} [alarm] Alarm definition * @apiSuccess (Success 200) {String} alarm.action Either display or email @@ -530,7 +530,7 @@ [thisFolder nameInContainer], @"pid", [thisFolder displayName], @"calendar", [NSNumber numberWithBool: [self isReadOnly]], @"isReadOnly", - [self loadAlarm], @"alarm", + [self alarm], @"alarm", nil]; if (startDate) diff --git a/UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox b/UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox index 62d420778..4e41e0c85 100644 --- a/UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox +++ b/UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox @@ -104,6 +104,29 @@ + +
+
+ + + + + + + +
+
+
+ + + + +
diff --git a/UI/Templates/SchedulerUI/UIxTaskEditorTemplate.wox b/UI/Templates/SchedulerUI/UIxTaskEditorTemplate.wox index 1665f3e27..7124cdf03 100644 --- a/UI/Templates/SchedulerUI/UIxTaskEditorTemplate.wox +++ b/UI/Templates/SchedulerUI/UIxTaskEditorTemplate.wox @@ -111,6 +111,29 @@ label:aria-label="% complete">
+ +
+
+ + + + + + + +
+
+
+ + + + +
diff --git a/UI/WebServerResources/js/Scheduler/Component.service.js b/UI/WebServerResources/js/Scheduler/Component.service.js index ac8eb84ed..f48575d40 100644 --- a/UI/WebServerResources/js/Scheduler/Component.service.js +++ b/UI/WebServerResources/js/Scheduler/Component.service.js @@ -514,6 +514,41 @@ this.attendees && this.attendees.length > 0; }; + /** + * @function addAttachUrl + * @memberof Component.prototype + * @desc Add a new attach URL if not already defined + * @param {string} attachUrl - the URL + * @returns the number of values in the list of attach URLs + */ + Component.prototype.addAttachUrl = function(attachUrl) { + if (angular.isUndefined(this.attachUrls)) { + this.attachUrls = [{value: attachUrl}]; + } + else { + for (var i = 0; i < this.attachUrls.length; i++) { + if (this.attachUrls[i].value == attachUrl) { + break; + } + } + if (i == this.attachUrls.length) + this.attachUrls.push({value: attachUrl}); + } + return this.attachUrls.length - 1; + }; + + /** + * @function deleteAttachUrl + * @memberof Component.prototype + * @desc Remove an attach URL + * @param {number} index - the URL index in the list of attach URLs + */ + Component.prototype.deleteAttachUrl = function(index) { + if (index > -1 && this.attachUrls.length > index) { + this.attachUrls.splice(index, 1); + } + }; + /** * @function $reset * @memberof Component.prototype diff --git a/UI/WebServerResources/js/Scheduler/ComponentController.js b/UI/WebServerResources/js/Scheduler/ComponentController.js index 170f7286a..0b08c0fb3 100644 --- a/UI/WebServerResources/js/Scheduler/ComponentController.js +++ b/UI/WebServerResources/js/Scheduler/ComponentController.js @@ -20,6 +20,7 @@ vm.cardFilter = cardFilter; vm.cardResults = []; vm.addAttendee = addAttendee; + vm.addAttachUrl = addAttachUrl; vm.cancel = cancel; vm.save = save; vm.attendeesEditor = { @@ -67,6 +68,11 @@ } }); + function addAttachUrl() { + var i = vm.component.addAttachUrl(''); + focus('attachUrl_' + i); + }; + function toggleRecurrenceEditor() { vm.showRecurrenceEditor = !vm.showRecurrenceEditor; vm.component.$hasCustomRepeat = vm.showRecurrenceEditor;