fix(calendar(js)): conditional display of edit and delete buttons

This commit is contained in:
Francis Lachapelle
2022-08-15 15:31:19 -04:00
parent 3f7fef0788
commit 16459c7b3d
11 changed files with 57 additions and 40 deletions

View File

@@ -672,7 +672,8 @@
* @apiSuccess (Success 200) {String} endDate End date (ISO8601)
* @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) {Number} isEditable 1 if event can be edited by the active user
* @apiSuccess (Success 200) {Number} isErasable 1 if event can be deleted by the active user
* @apiSuccess (Success 200) {Number} userHasRSVP 1 if owner is invited
* @apiSuccess (Success 200) {Number} [reply] 0 if needs-action, 1 if accepted, 2 if declined, 3 if tentative, 4 if delegated
* @apiSuccess (Success 200) {Object[]} [attachUrls] Attached URLs
@@ -826,7 +827,8 @@
[componentCalendar nameInContainer], @"pid",
[componentCalendar displayName], @"calendar",
[NSNumber numberWithBool: isAllDay], @"isAllDay",
[NSNumber numberWithBool: [self isReadOnly]], @"isReadOnly",
[NSNumber numberWithBool: [self isEditable]], @"isEditable",
[NSNumber numberWithBool: [self isErasable]], @"isErasable",
[NSNumber numberWithBool: [self userHasRSVP]], @"userHasRSVP",
[eventStartDate iso8601DateString], @"startDate",
[eventEndDate iso8601DateString], @"endDate",

View File

@@ -1,6 +1,6 @@
/* UIxComponentEditor.h - this file is part of SOGo
*
* Copyright (C) 2006-2015 Inverse inc.
* Copyright (C) 2006-2022 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,7 +33,8 @@
SOGoAppointmentFolder *componentCalendar;
}
- (BOOL) isReadOnly;
- (BOOL) isEditable;
- (BOOL) isErasable;
- (BOOL) userHasRSVP;
- (NSNumber *) reply;
- (BOOL) isChildOccurrence;

View File

@@ -837,10 +837,21 @@ static NSArray *reminderValues = nil;
return rc;
}
- (BOOL) isReadOnly
- (BOOL) isEditable
{
return [self getEventRWType] != componentReadableWritable;
return [self getEventRWType] == componentReadableWritable;
}
- (BOOL) isErasable
{
NSString *owner, *userLogin;
userLogin = [[context activeUser] login];
owner = [componentCalendar ownerInContext: context];
return ([owner isEqualToString: userLogin] || [[componentCalendar aclsForUser: userLogin] containsObject: SOGoRole_ObjectEraser]);
}
//
//- (NSString *) emailAlarmsEnabled
//{

View File

@@ -431,7 +431,8 @@
* @apiSuccess (Success 200) {String} localizedDueTime Formatted due time
* @apiSuccess (Success 200) {String} localizedCompletedDate Formatted completed date
* @apiSuccess (Success 200) {String} localizedCompletedTime Formatted completed time
* @apiSuccess (Success 200) {Number} isReadOnly 1 if task is read-only
* @apiSuccess (Success 200) {Number} isEditable 1 if task can be edited by the active user
* @apiSuccess (Success 200) {Number} isErasable 1 if task can be deleted by the active user
* @apiSuccess (Success 200) {Object[]} [attachUrls] Attached URLs
* @apiSuccess (Success 200) {String} attachUrls.value URL
*
@@ -561,7 +562,8 @@
data = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[componentCalendar nameInContainer], @"pid",
[componentCalendar displayName], @"calendar",
[NSNumber numberWithBool: [self isReadOnly]], @"isReadOnly",
[NSNumber numberWithBool: [self isEditable]], @"isEditable",
[NSNumber numberWithBool: [self isErasable]], @"isErasable",
[self alarm], @"alarm",
nil];

View File

@@ -35,7 +35,7 @@
<label><var:string label:value="Calendar"/></label>
<md-select ng-model="editor.component.destinationCalendar"
ng-change="editor.changeCalendar()">
<md-option ng-repeat="calendar in editor.service.$findAll(null, true)"
<md-option ng-repeat="calendar in editor.destinationCalendars()"
ng-value="calendar.id">
<div layout="row" layout-align="start center">
<div class="sg-color-chip"

View File

@@ -49,7 +49,7 @@
</md-menu-content>
</md-menu>
</md-menu-item>
<md-menu-item ng-show="editor.component.isMovable()">
<md-menu-item ng-show="editor.component.isErasable">
<md-menu>
<md-button label:aria-label="Move To" ng-click="$mdMenu.open($event)">
<var:string label:value="Move To"/>
@@ -272,20 +272,23 @@
<!-- actions -->
<!-- editable but not recurrent -->
<md-dialog-actions ng-show="::editor.component.isEditable()">
<md-dialog-actions ng-show="::editor.component.isActionable()">
<md-button class="md-warn"
label:aria-label="Delete Event"
ng-show="::editor.component.isErasable"
ng-click="editor.deleteAllOccurrences()">
<var:string label:value="Delete"/>
</md-button>
<div class="md-flex"><!-- spacer --></div>
<md-button type="button" ng-click="editor.edit()">
<md-button type="button"
ng-show="::editor.component.isEditable"
ng-click="editor.edit()">
<var:string label:value="Edit"/>
</md-button>
</md-dialog-actions>
<!-- editable and recurrent -->
<md-dialog-actions ng-show="::editor.component.isEditableOccurrence()">
<md-menu>
<md-dialog-actions ng-show="::editor.component.isActionableOccurrence()">
<md-menu ng-show="::editor.component.isErasable">
<md-button class="md-warn"
label:aria-label="Delete Event"
ng-click="$mdMenu.open()"
@@ -310,7 +313,7 @@
</md-menu-content>
</md-menu>
<div class="md-flex"><!-- spacer --></div>
<md-menu>
<md-menu ng-show="::editor.component.isEditable">
<md-button label:aria-label="Edit"
ng-click="$mdMenu.open()"
md-menu-origin="md-menu-origin">

View File

@@ -34,7 +34,7 @@
<md-input-container flex="50" flex-xs="100">
<label><var:string label:value="Calendar"/></label>
<md-select ng-model="editor.component.destinationCalendar">
<md-option ng-repeat="calendar in editor.service.$findAll(null, true)"
<md-option ng-repeat="calendar in editor.destinationCalendars()"
ng-value="calendar.id">
<div layout="row" layout-align="start center">
<div class="sg-color-chip"

View File

@@ -125,19 +125,22 @@
<!-- actions -->
<!-- editable but not recurrent -->
<md-dialog-actions ng-show="::editor.component.isEditable()">
<md-dialog-actions ng-show="::editor.component.isActionable()">
<md-button class="md-warn" label:aria-label="Delete Task"
ng-show="::editor.component.isErasable"
ng-click="editor.deleteAllOccurrences()">
<var:string label:value="Delete"/>
</md-button>
<div class="md-flex"><!-- spacer --></div>
<md-button ng-click="editor.edit()">
<md-button type="button"
ng-show="::editor.component.isEditable"
ng-click="editor.edit()">
<var:string label:value="Edit"/>
</md-button>
</md-dialog-actions>
<!-- editable and recurrent -->
<md-dialog-actions ng-show="::editor.component.isEditableOccurrence()">
<md-menu>
<md-dialog-actions ng-show="::editor.component.isActionableOccurrence()">
<md-menu ng-show="::editor.component.isErasable">
<md-button class="md-warn"
label:aria-label="Delete Task"
ng-click="$mdMenu.open()"
@@ -162,7 +165,7 @@
</md-menu-content>
</md-menu>
<div class="md-flex"><!-- spacer --></div>
<md-menu>
<md-menu ng-show="::editor.component.isEditable">
<md-button label:aria-label="Edit"
ng-click="$mdMenu.open()"
md-menu-origin="md-menu-origin">

View File

@@ -116,7 +116,7 @@
* @param {bool} [writable] - if true, returns only the list of writable calendars
* @returns the list of calendars
*/
Calendar.$findAll = function(data, writable) {
Calendar.$findAll = function(data, writable, contextId) {
var _this = this;
if (data) {
this.$calendars = [];
@@ -144,7 +144,7 @@
if (writable) {
return _.union(this.$calendars, _.filter(this.$subscriptions, function(calendar) {
return calendar.isOwned || calendar.acls.objectCreator;
return calendar.isOwned || calendar.acls.objectCreator || calendar.id == contextId;
}));
}

View File

@@ -672,8 +672,8 @@
* @desc Check if the component is editable and not an occurrence of a recurrent component
* @returns true or false
*/
Component.prototype.isEditable = function() {
return (!this.occurrenceId && !this.isReadOnly);
Component.prototype.isActionable = function() {
return (!this.occurrenceId && !this.userHasRSVP && (this.isEditable || this.isErasable));
};
/**
@@ -682,8 +682,8 @@
* @desc Check if the component is editable and an occurrence of a recurrent component
* @returns true or false
*/
Component.prototype.isEditableOccurrence = function() {
return (this.occurrenceId && !this.isReadOnly);
Component.prototype.isActionableOccurrence = function() {
return (this.occurrenceId && !this.userHasRSVP && (this.isEditable || this.isErasable));
};
/**
@@ -706,18 +706,6 @@
return (this.occurrenceId && this.userHasRSVP);
};
/**
* @function isMovable
* @memberof Component.prototype
* @desc Return true if the component can be moved to a different calendar which occurs in two cases:
* - the component is editable, ie is owned by the current user;
* - the component is an invitation and the current user is an attendee.
* @returns true or false
*/
Component.prototype.isMovable = function() {
return (!this.isReadOnly || this.userHasRSVP);
};
/**
* @function showPercentComplete
* @memberof Component.prototype
@@ -810,7 +798,7 @@
*/
Component.prototype.canRemindAttendeesByEmail = function() {
return this.alarm.action == 'email' &&
!this.isReadOnly &&
this.isEditable &&
this.attendees && this.attendees.length > 0;
};

View File

@@ -278,6 +278,13 @@
this.showRecurrenceEditor = true;
};
this.destinationCalendars = function () {
if (this.component.isErasable)
return Calendar.$findAll(null, true, this.component.pid);
else
return [Calendar.$get(this.component.pid)];
};
this.changeCalendar = function () {
var updateRequired = (this.component.attendees && this.component.attendees.length > 0);
if (updateRequired)