Merge branch 'master' into fix-some-warnings

Conflicts:
	UI/Scheduler/UIxAppointmentActions.m
This commit is contained in:
Patrice Levesque
2016-02-16 14:32:50 -05:00
16 changed files with 382 additions and 108 deletions
+6 -2
View File
@@ -64,6 +64,7 @@
SOGoAppointmentFolder *targetCalendar, *sourceCalendar;
SOGoAppointmentFolders *folders;
BOOL forceSave;
id error;
rq = [context request];
params = [[rq contentAsString] objectFromJSONString];
@@ -72,7 +73,7 @@
startDelta = [params objectForKey: @"start"];
durationDelta = [params objectForKey: @"duration"];
destionationCalendar = [params objectForKey: @"destination"];
forceSave = NO;
forceSave = [[params objectForKey: @"ignoreConflicts"] boolValue];
if (daysDelta || startDelta || durationDelta)
{
@@ -146,8 +147,11 @@
if ([ex respondsToSelector: @selector(httpStatus)])
httpStatus = [ex httpStatus];
error = [[ex reason] objectFromJSONString];
if (error == nil)
error = [ex reason];
jsonResponse = [NSDictionary dictionaryWithObjectsAndKeys:
[ex reason], @"message",
error, @"message",
nil];
response = [self responseWithStatus: httpStatus
+6 -3
View File
@@ -454,6 +454,7 @@
SOGoAppointmentObject *co;
SoSecurityManager *sm;
WORequest *request;
id error;
unsigned int httpStatus;
BOOL forceSave;
@@ -477,7 +478,7 @@
else
{
[self setAttributes: params];
forceSave = NO;
forceSave = [[params objectForKey: @"ignoreConflicts"] boolValue];
if ([event hasRecurrenceRules])
[self _adjustRecurrentRules];
@@ -533,9 +534,11 @@
if ([ex respondsToSelector: @selector(httpStatus)])
httpStatus = [ex httpStatus];
error = [[ex reason] objectFromJSONString];
if (error == nil)
error = [ex reason];
jsonResponse = [NSDictionary dictionaryWithObjectsAndKeys:
[ex reason], @"message",
nil];
error, @"message", nil];
}
else
{
@@ -275,7 +275,7 @@
</div>
</md-dialog-content>
<!-- cancel/reset/save -->
<md-dialog-actions>
<md-dialog-actions ng-hide="editor.attendeeConflictError">
<md-button type="button" ng-click="editor.cancel()">
<var:string label:value="Cancel"/>
</md-button>
@@ -287,6 +287,65 @@
<var:string label:value="Save"/>
</md-button>
</md-dialog-actions>
<!-- attendee availability conflict -->
<md-dialog-content class="md-default-theme md-bg md-warn md-padding sg-dialog-message ng-hide"
ng-show="editor.attendeeConflictError.conflicts">
<div layout="row">
<div class="md-flex"><var:string label:value="A time conflict exists with one or more attendees.\nWould you like to keep the current settings anyway?"/></div>
<md-button class="md-icon-button" ng-click="editor.attendeeConflictError = false">
<md-icon label:aria-label="Close">close</md-icon>
</md-button>
</div>
<div class="md-flex" ng-show="editor.attendeeConflictError.attendee_email">
<md-icon>person</md-icon> {{editor.attendeeConflictError.attendee_name}} ({{editor.attendeeConflictError.attendee_email}})
</div>
<div layout="row"
ng-show="editor.attendeeConflictError.conflicts"
ng-repeat="conflict in editor.attendeeConflictError.conflicts">
<md-icon>schedule</md-icon>
<div class="pseudo-input-container">
<label class="pseudo-input-label"><var:string label:value="From"/></label>
<div>{{conflict.startDate}} <md-icon>trending_flat</md-icon></div>
</div>
<div class="pseudo-input-container md-flex">
<label class="pseudo-input-label"><var:string label:value="To"/></label>
<div>{{conflict.endDate}}</div>
</div>
</div>
</md-dialog-content>
<md-dialog-actions ng-show="editor.attendeeConflictError.conflicts">
<md-button type="button" ng-click="editor.cancel()">
<var:string label:value="Cancel"/>
</md-button>
<md-button type="button"
ng-click="editor.attendeeConflictError = false">
<var:string label:value="Edit"/>
</md-button>
<md-button class="md-warn" type="button"
ng-click="editor.save(eventForm, { ignoreConflicts: true })"
ng-disabled="editor.eventForm.$invalid">
<var:string label:value="Save"/>
</md-button>
</md-dialog-actions>
<!-- rejected attendee invitation -->
<md-dialog-content class="md-default-theme md-bg md-warn md-padding sg-dialog-message ng-hide" layout="row"
ng-show="editor.attendeeConflictError.reject">
<div class="md-flex">{{editor.attendeeConflictError.reject}}</div>
<md-button class="md-icon-button" ng-click="editor.attendeeConflictError = false">
<md-icon label:aria-label="Close">close</md-icon>
</md-button>
</md-dialog-content>
<md-dialog-actions ng-show="editor.attendeeConflictError.reject">
<md-button type="button" ng-click="editor.cancel()">
<var:string label:value="Cancel"/>
</md-button>
<md-button type="button"
ng-click="editor.attendeeConflictError = false">
<var:string label:value="Edit"/>
</md-button>
</md-dialog-actions>
</form>
</md-dialog>
</container>
@@ -211,26 +211,39 @@
</md-button>
<md-menu-content>
<md-menu-item>
<md-button class="md-warn"
ng-click="editor.deleteOccurrence()">
<var:string label:value="Delete This Occurrence"/>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button class="md-warn"
ng-click="editor.deleteAllOccurrences()">
<var:string label:value="Delete All Occurrences"/>
</md-button>
</md-menu-item>
<md-button class="md-warn"
ng-click="editor.deleteOccurrence()">
<md-icon>repeat_one</md-icon> <var:string label:value="Delete This Occurrence"/>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button class="md-warn"
ng-click="editor.deleteAllOccurrences()">
<md-icon>repeat</md-icon> <var:string label:value="Delete All Occurrences"/>
</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
<div class="md-flex"><!-- spacer --></div>
<md-button type="button" ng-click="editor.editAllOccurrences()">
<var:string label:value="Edit All Occurrences"/>
</md-button>
<md-button type="button" ng-click="editor.edit()">
<var:string label:value="Edit This Occurrence"/>
</md-button>
<md-menu>
<md-button label:aria-label="Edit"
ng-click="$mdOpenMenu()"
md-menu-origin="md-menu-origin">
<var:string label:value="Edit"/> <md-icon>arrow_drop_down</md-icon>
</md-button>
<md-menu-content>
<md-menu-item>
<md-button type="button" ng-click="editor.edit()">
<md-icon>repeat_one</md-icon> <var:string label:value="Edit This Occurrence"/>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button type="button" ng-click="editor.editAllOccurrences()">
<md-icon>repeat</md-icon> <var:string label:value="Edit All Occurrences"/>
</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
</md-dialog-actions>
<!-- invitation but not recurrent -->
<md-dialog-actions ng-show="editor.component.isInvitation()">
@@ -251,49 +264,41 @@
label:aria-label="Delete Event"
ng-click="$mdOpenMenu()"
md-menu-origin="md-menu-origin">
<var:string label:value="Delete"/>
<var:string label:value="Delete"/> <md-icon>arrow_drop_down</md-icon>
</md-button>
<md-menu-content>
<md-menu-item>
<md-button class="md-warn"
ng-click="editor.deleteOccurrence()">
<var:string label:value="Delete This Occurrence"/>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button class="md-warn"
ng-click="editor.deleteAllOccurrences()">
<var:string label:value="Delete All Occurrences"/>
</md-button>
</md-menu-item>
<md-button class="md-warn"
ng-click="editor.deleteOccurrence()">
<md-icon>repeat_one</md-icon> <var:string label:value="Delete This Occurrence"/>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button class="md-warn"
ng-click="editor.deleteAllOccurrences()">
<md-icon>repeat</md-icon> <var:string label:value="Delete All Occurrences"/>
</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
<div class="md-flex"><!-- spacer --></div>
<!-- On larger screens, show both buttons -->
<md-button type="button" class="hide-xs" ng-click="editor.replyAllOccurrences()">
<var:string label:value="Update All Occurrences"/>
</md-button>
<md-button type="button" class="hide-xs" ng-click="editor.reply()">
<var:string label:value="Update This Occurrence"/>
</md-button>
<!-- On small screens, show a md-menu with the two choices -->
<md-menu class="hide show-xs">
<md-menu>
<md-button label:aria-label="Update"
ng-click="$mdOpenMenu()"
md-menu-origin="md-menu-origin">
<var:string label:value="Update"/>
<var:string label:value="Update"/> <md-icon>arrow_drop_down</md-icon>
</md-button>
<md-menu-content>
<md-menu-item>
<md-button type="button" ng-click="editor.replyAllOccurrences()">
<var:string label:value="Update All Occurrences"/>
<md-button type="button" ng-click="editor.reply()">
<md-icon>repeat_one</md-icon> <var:string label:value="Update This Occurrence"/>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button type="button" ng-click="editor.reply()">
<var:string label:value="Update This Occurrence"/>
</md-button>
</md-menu-item>
</md-menu-item>
<md-menu-item>
<md-button type="button" ng-click="editor.replyAllOccurrences()">
<md-icon>repeat</md-icon> <var:string label:value="Update All Occurrences"/>
</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
</md-dialog-actions>
@@ -737,4 +737,46 @@
</md-dialog>
</script>
<!-- modal for attendee availability conflict -->
<script type="text/ng-template" id="UIxAttendeeConflictDialog">
<md-dialog flex="60" flex-xs="100">
<md-dialog-content class="md-dialog-content"
ng-show="$AttendeeConflictDialogController.conflictError.attendee_email">
<h2 class="md-title"><var:string label:value="Warning"/></h2>
<p><var:string label:value="A time conflict exists with one or more attendees.\nWould you like to keep the current settings anyway?"/></p>
<md-list>
<md-list-item>
<md-icon>person</md-icon> {{$AttendeeConflictDialogController.conflictError.attendee_name}} ({{$AttendeeConflictDialogController.conflictError.attendee_email}})
</md-list-item>
<md-list-item ng-repeat="conflict in $AttendeeConflictDialogController.conflictError.conflicts">
<md-icon>schedule</md-icon>
<div class="pseudo-input-container">
<label class="pseudo-input-label"><var:string label:value="From"/></label>
<div>{{conflict.startDate}}</div>
</div>
<div class="pseudo-input-container md-flex">
<label class="pseudo-input-label"><var:string label:value="To"/></label>
<div>{{conflict.endDate}}</div>
</div>
</md-list-item>
</md-list>
</md-dialog-content>
<md-dialog-content class="md-dialog-content"
ng-show="$AttendeeConflictDialogController.conflictError.reject">
<h2 class="md-title"><var:string label:value="Warning"/></h2>
<p>{{$AttendeeConflictDialogController.conflictError.reject}}</p>
</md-dialog-content>
<md-dialog-actions>
<md-button type="button" ng-click="$AttendeeConflictDialogController.cancel()">
<var:string label:value="Cancel"/>
</md-button>
<md-button class="md-warn" type="button"
ng-show="$AttendeeConflictDialogController.conflictError.conflicts"
ng-click="$AttendeeConflictDialogController.save()">
<var:string label:value="Save"/>
</md-button>
</md-dialog-actions>
</md-dialog>
</script>
</var:component>
@@ -82,7 +82,7 @@
<md-input-container flex-offset="5" md-no-float="md-no-float">
<input type="text"
label:placeholder="Email Address"
ng-value="properties.calendar.notifications.notifiedUserOnPersonalModifications"
ng-model="properties.calendar.notifications.notifiedUserOnPersonalModifications"
ng-disabled="!properties.calendar.notifications.notifyUserOnPersonalModifications"/>
</md-input-container>
</div>
@@ -66,7 +66,7 @@
function onHttpError(event, response) {
var message;
if (response.data && response.data.message)
if (response.data && response.data.message && angular.isString(response.data.message))
message = response.data.message;
else if (response.status)
message = response.statusText;
@@ -85,7 +85,7 @@
position: 'top right'
});
else
console.debug('untrap error');
$log.debug('untrap error');
}
// Listen to HTTP errors broadcasted from HTTP interceptor
@@ -162,8 +162,7 @@
component.setDelta(coordinates.duration * 15);
newComponent(null, component).finally(function() {
$timeout(function() {
Component.$ghost.pointerHandler = null;
Component.$ghost.component = null;
Component.$resetGhost();
});
});
}
@@ -186,8 +185,11 @@
// Immediately perform the adjustments
component.$adjust(params).then(function() {
$rootScope.$emit('calendars:list');
}, function(response) {
onComponentAdjustError(response, component, params);
}).finally(function() {
$timeout(function() {
Component.$ghost = {};
Component.$resetGhost();
});
});
else if (component.occurrenceId) {
@@ -199,7 +201,7 @@
params: params
},
template: [
'<md-dialog flex="50" md-flex="80" sm-flex="90">',
'<md-dialog flex="50" sm-flex="80" xs-flex="90">',
' <md-dialog-content class="md-dialog-content">',
' <p>' + l('editRepeatingItem') + '</p>',
' </md-dialog-content>',
@@ -214,7 +216,7 @@
$rootScope.$emit('calendars:list');
}).finally(function() {
$timeout(function() {
Component.$ghost = {};
Component.$resetGhost();
});
});
}
@@ -226,13 +228,58 @@
RecurrentComponentDialogController.$inject = ['$scope', '$mdDialog', 'component', 'params'];
function RecurrentComponentDialogController($scope, $mdDialog, component, params) {
$scope.updateThisOccurrence = function() {
component.$adjust(params).then($mdDialog.hide, $mdDialog.cancel);
component.$adjust(params).then($mdDialog.hide, function(response) {
$mdDialog.cancel().then(function() {
onComponentAdjustError(response, component, params);
});
});
};
$scope.updateAllOccurrences = function() {
delete component.occurrenceId;
component.$adjust(params).then($mdDialog.hide, $mdDialog.cancel);
component.$adjust(params).then($mdDialog.hide, function(response) {
$mdDialog.cancel().then(function() {
onComponentAdjustError(response, component, params);
});
});
};
}
function onComponentAdjustError(response, component, params) {
if (response.status == 403 &&
response.data && response.data.message && angular.isObject(response.data.message)) {
$mdDialog.show({
parent: angular.element(document.body),
clickOutsideToClose: false,
escapeToClose: false,
templateUrl: 'UIxAttendeeConflictDialog',
controller: AttendeeConflictDialogController,
controllerAs: '$AttendeeConflictDialogController',
locals: {
component: component,
params: params,
conflictError: response.data.message
}
}).then(function() {
$rootScope.$emit('calendars:list');
});
}
}
/**
* @ngInject
*/
AttendeeConflictDialogController.$inject = ['$scope', '$mdDialog', 'component', 'params', 'conflictError'];
function AttendeeConflictDialogController($scope, $mdDialog, component, params, conflictError) {
var vm = this;
vm.conflictError = conflictError;
vm.cancel = $mdDialog.cancel;
vm.save = save;
function save() {
component.$adjust(angular.extend({ ignoreConflicts: true }, params)).then($mdDialog.hide);
}
}
}
function filter(filterpopup) {
@@ -414,6 +414,15 @@
});
};
/**
* @function $resetGhost
* @desc Prepare the ghost object for the next drag by resetting appropriate attributes
*/
Component.$resetGhost = function() {
this.$ghost.pointerHandler = null;
this.$ghost.component = null;
};
/**
* @function $parseDate
* @desc Parse a date string with format YYYY-MM-DDTHH:MM
@@ -1035,8 +1044,9 @@
* @function $save
* @memberof Component.prototype
* @desc Save the component to the server.
* @param {object} extraAttributes - additional attributes to send to the server
*/
Component.prototype.$save = function() {
Component.prototype.$save = function(extraAttributes) {
var _this = this, options, path, component, date, dlp;
component = this.$omit();
@@ -1106,6 +1116,8 @@
if (this.occurrenceId)
path.push(this.occurrenceId);
angular.extend(component, extraAttributes);
return Component.$$resource.save(path.join('/'), component, options)
.then(function(data) {
// Make a copy of the data for an eventual reset
@@ -162,6 +162,7 @@
vm.addAttachUrl = addAttachUrl;
vm.cancel = cancel;
vm.save = save;
vm.attendeeConflictError = false;
vm.attendeesEditor = {
days: getDays(),
hours: getHours()
@@ -217,15 +218,18 @@
}
}
function save(form) {
function save(form, options) {
if (form.$valid) {
vm.component.$save()
vm.component.$save(options)
.then(function(data) {
$rootScope.$emit('calendars:list');
$mdDialog.hide();
Alarm.getAlarms();
}, function(data, status) {
$log.debug('failed');
}, function(response) {
if (response.status == 403 &&
response.data && response.data.message &&
angular.isObject(response.data.message))
vm.attendeeConflictError = response.data.message;
});
}
}
@@ -19,6 +19,22 @@ body.popup {
}
}
md-dialog {
md-dialog-content {
&.sg-dialog-message {
// Prepare content to receive a "close" button on the right
align-items: flex-start;
display: flex;
flex-shrink: 0;
transition: background-color $swift-ease-in-duration $swift-ease-in-timing-function;
&.ng-hide {
background-color: white !important;
transition-duration: 0s;
}
}
}
}
@media (max-width: $layout-breakpoint-xs) {
md-dialog {
&[flex-xs="100"],