mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-07 08:34:42 +01:00
show changes in participants, new and old start-date
for exceptions only sending the concerned recurrence, instead of the whole series, so user understands what has changed
This commit is contained in:
parent
42178c432e
commit
1509f30971
@ -570,10 +570,10 @@ class calendar_boupdate extends calendar_bo
|
|||||||
*
|
*
|
||||||
* @param array $new_event the updated event
|
* @param array $new_event the updated event
|
||||||
* @param array $old_event the event before the update
|
* @param array $old_event the event before the update
|
||||||
|
* @param int $notify_max_recurrences notify only about this number of single recurrences at maximum
|
||||||
*/
|
*/
|
||||||
function check4update($new_event,$old_event)
|
function check4update($new_event, $old_event, int $notify_max_recurrences=3)
|
||||||
{
|
{
|
||||||
//error_log(__METHOD__."($new_event[title])");
|
|
||||||
$modified = $added = $deleted = array();
|
$modified = $added = $deleted = array();
|
||||||
|
|
||||||
//echo "<p>calendar_boupdate::check4update() new participants = ".print_r($new_event['participants'],true).", old participants =".print_r($old_event['participants'],true)."</p>\n";
|
//echo "<p>calendar_boupdate::check4update() new participants = ".print_r($new_event['participants'],true).", old participants =".print_r($old_event['participants'],true)."</p>\n";
|
||||||
@ -582,6 +582,63 @@ class calendar_boupdate extends calendar_bo
|
|||||||
{
|
{
|
||||||
if($new_event[$field] !== $old_event[$field])
|
if($new_event[$field] !== $old_event[$field])
|
||||||
{
|
{
|
||||||
|
$n = 0;
|
||||||
|
switch($field)
|
||||||
|
{
|
||||||
|
case 'recur_exception':
|
||||||
|
foreach ($added_exceptions=array_diff($new_event[$field]??[],$old_event[$field]??[]) as $key => $recurrence)
|
||||||
|
{
|
||||||
|
if ($this->read($new_event['uid'], $recurrence))
|
||||||
|
{
|
||||||
|
unset($added_exceptions[$key]);
|
||||||
|
continue; // explicit exception --> no need to notify, already done for the exception itself
|
||||||
|
}
|
||||||
|
// send a cancel for each RECURRENCE-ID
|
||||||
|
$this->send_update(MSG_DELETED, $new_event['participants'], [
|
||||||
|
'recurrence' => $recurrence,
|
||||||
|
'start' => $recurrence,
|
||||||
|
'end' => $recurrence + $new_event['end'] - $new_event['start'],
|
||||||
|
]+$new_event);
|
||||||
|
// limit number of notifications to the first N recurrences
|
||||||
|
if (++$n >= $notify_max_recurrences) break;
|
||||||
|
}
|
||||||
|
$n = 0;
|
||||||
|
foreach($removed_exceptions=array_diff($old_event[$field]??[],$new_event[$field]??[]) as $key => $recurrence)
|
||||||
|
{
|
||||||
|
if ($this->read($new_event['uid'], $recurrence))
|
||||||
|
{
|
||||||
|
unset($removed_exceptions[$key]);
|
||||||
|
continue; // explicit exception --> no need to notify, already done for the exception itself
|
||||||
|
}
|
||||||
|
// send an add for each RECURRENCE-ID
|
||||||
|
$this->send_update(MSG_ADDED, $new_event['participants'], null, [
|
||||||
|
'recurrence' => $recurrence,
|
||||||
|
'start' => $recurrence,
|
||||||
|
'end' => $recurrence + $new_event['end'] - $new_event['start'],
|
||||||
|
]+$new_event);
|
||||||
|
// limit number of notifications to the first N recurrences
|
||||||
|
if (++$n >= $notify_max_recurrences) break;
|
||||||
|
}
|
||||||
|
continue 2;
|
||||||
|
|
||||||
|
case 'recur_rdates':
|
||||||
|
foreach(array_diff($new_event[$field]??[],$old_event[$field]??[]) as $recurrence)
|
||||||
|
{
|
||||||
|
// send an add for each RECURRENCE-ID
|
||||||
|
$this->send_update(MSG_ADDED, $new_event['participants'], null, [
|
||||||
|
'recurrence' => $recurrence,
|
||||||
|
'start' => $recurrence,
|
||||||
|
'end' => $recurrence + $new_event['end'] - $new_event['start'],
|
||||||
|
]+$new_event);
|
||||||
|
// limit number of notifications to the first N recurrences
|
||||||
|
if (++$n >= $notify_max_recurrences) break;
|
||||||
|
}
|
||||||
|
continue 2;
|
||||||
|
|
||||||
|
case 'recur_enddate':
|
||||||
|
if ($new_event['recur_type'] == MCAL_RECUR_RDATE) continue 2; // already handled above
|
||||||
|
break;
|
||||||
|
}
|
||||||
$modified = $new_event['participants'];
|
$modified = $new_event['participants'];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1288,7 +1345,7 @@ class calendar_boupdate extends calendar_bo
|
|||||||
'videoconference' => $details['videoconference'],
|
'videoconference' => $details['videoconference'],
|
||||||
), $event['id']);
|
), $event['id']);
|
||||||
}
|
}
|
||||||
if ($m_type === MSG_ALARM)
|
elseif ($m_type === MSG_ALARM)
|
||||||
{
|
{
|
||||||
$notification->set_popupdata('calendar',
|
$notification->set_popupdata('calendar',
|
||||||
array('egw_pr_notify' => 1,
|
array('egw_pr_notify' => 1,
|
||||||
@ -1299,6 +1356,10 @@ class calendar_boupdate extends calendar_bo
|
|||||||
)
|
)
|
||||||
+ ($alarm ? ['alarm-offset' => (int)$alarm['offset']] : []), $event['id']);
|
+ ($alarm ? ['alarm-offset' => (int)$alarm['offset']] : []), $event['id']);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$notification->set_popupdata('calendar', null, $event['id']);
|
||||||
|
}
|
||||||
$notification->set_popupmessage($subject . "\n\n" . $notify_body . "\n\n" . $details['description'] . "\n\n" . $details_body . "\n\n");
|
$notification->set_popupmessage($subject . "\n\n" . $notify_body . "\n\n" . $details['description'] . "\n\n" . $details_body . "\n\n");
|
||||||
$notification->set_popuplinks(array($details['link_arr'] + array('app' => 'calendar')));
|
$notification->set_popuplinks(array($details['link_arr'] + array('app' => 'calendar')));
|
||||||
|
|
||||||
|
@ -2225,14 +2225,6 @@ class calendar_uiforms extends calendar_ui
|
|||||||
// convert event from servertime returned by calendar_ical to user-time
|
// convert event from servertime returned by calendar_ical to user-time
|
||||||
$this->bo->server2usertime($event);
|
$this->bo->server2usertime($event);
|
||||||
|
|
||||||
// Check if this is an exception
|
|
||||||
if($event['recur_type'] && count($event['recur_exception']) && !$event['recurrence'])
|
|
||||||
{
|
|
||||||
$diff = $event['recur_exception'][0] - $event['start'];
|
|
||||||
$event['start'] += $diff;
|
|
||||||
$event['end'] += $diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($existing_event = $this->bo->read($event['uid'], $event['recurrence'], false, 'ts', null, true))) // true = read the exception
|
if (($existing_event = $this->bo->read($event['uid'], $event['recurrence'], false, 'ts', null, true))) // true = read the exception
|
||||||
{
|
{
|
||||||
// check if mail is from extern organizer
|
// check if mail is from extern organizer
|
||||||
@ -2251,6 +2243,20 @@ class calendar_uiforms extends calendar_ui
|
|||||||
{
|
{
|
||||||
$master = $this->bo->read($event['uid']);
|
$master = $this->bo->read($event['uid']);
|
||||||
}
|
}
|
||||||
|
$all_participants = ($event['participants'] ?? []) + ($existing_event['participants'] ?? []);
|
||||||
|
$event['participantChanges'] = array_map(function($uid, $status) use ($existing_event, $event) {
|
||||||
|
return [
|
||||||
|
'changed' => !isset($event['participants'][$uid]) ? 'meetingRequestParticipantDeleted' :
|
||||||
|
(!isset($existing_event['participants'][$uid]) ? 'meetingRequestChanged' :
|
||||||
|
($status !== $existing_event['participants'][$uid] ? 'meetingRequestChangedStatus' : '')),
|
||||||
|
'label' => $this->bo->participant_name($uid),
|
||||||
|
'status' => lang($this->bo->verbose_status[calendar_so::split_status($status, $quantity, $role)]),
|
||||||
|
'role' => $role === 'REQ-PARTICIPANT' ? '' : lang($this->bo->roles[$role] ??
|
||||||
|
(substr($role,0,6) === 'X-CAT-' && ($cat_id = (int)substr($role,6)) > 0 ?
|
||||||
|
$GLOBALS['egw']->categories->id2name($cat_id) : str_replace('X-','',$role))),
|
||||||
|
];
|
||||||
|
}, array_keys($all_participants), $all_participants);
|
||||||
|
|
||||||
switch(strtolower($ical_method))
|
switch(strtolower($ical_method))
|
||||||
{
|
{
|
||||||
case 'reply':
|
case 'reply':
|
||||||
@ -2338,22 +2344,14 @@ class calendar_uiforms extends calendar_ui
|
|||||||
$readonlys['button[reject]'] = $readonlys['button[cancel]'] = true;
|
$readonlys['button[reject]'] = $readonlys['button[cancel]'] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$all_participants = ($event['participants'] ?? []) + ($existing_event['participants'] ?? []);
|
|
||||||
$event['participantChanges'] = array_map(function($uid, $status) use ($existing_event, $event) {
|
|
||||||
return [
|
|
||||||
'changed' => !isset($event['participants'][$uid]) ? 'meetingRequestParticipantDeleted' :
|
|
||||||
(!isset($existing_event['participants'][$uid]) ? 'meetingRequestChanged' :
|
|
||||||
($status !== $existing_event['participants'][$uid] ? 'meetingRequestChangedStatus' : '')),
|
|
||||||
'label' => $this->bo->participant_name($uid),
|
|
||||||
'status' => lang($this->bo->verbose_status[calendar_so::split_status($status, $quantity, $role)]),
|
|
||||||
'role' => $role === 'REQ-PARTICIPANT' ? '' : lang($this->bo->roles[$role] ??
|
|
||||||
(substr($role,0,6) === 'X-CAT-' && ($cat_id = (int)substr($role,6)) > 0 ?
|
|
||||||
$GLOBALS['egw']->categories->id2name($cat_id) : str_replace('X-','',$role))),
|
|
||||||
];
|
|
||||||
}, array_keys($all_participants), $all_participants);
|
|
||||||
break;
|
break;
|
||||||
case 'cancel':
|
case 'cancel':
|
||||||
// first participant is the (external) organizer (our iCal parser adds owner first!)
|
// first participant is the (external) organizer (our iCal parser adds owner first!)
|
||||||
|
$event['changed'] = [
|
||||||
|
'start' => 'meetingRequestChangedValue',
|
||||||
|
'end' => 'meetingRequestChangedValue',
|
||||||
|
'participants' => 'meetingRequestParticipantDeleted',
|
||||||
|
];
|
||||||
$parts = $event['participants'] ?? [];
|
$parts = $event['participants'] ?? [];
|
||||||
unset($parts[$existing_event['owner']]);
|
unset($parts[$existing_event['owner']]);
|
||||||
$event['ical_sender_uid'] = key($parts);
|
$event['ical_sender_uid'] = key($parts);
|
||||||
@ -2600,6 +2598,18 @@ class calendar_uiforms extends calendar_ui
|
|||||||
unset($changes['recure']);
|
unset($changes['recure']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if start changed, make old start-time available to template
|
||||||
|
if (isset($changes['start']) && $_event['start'] != $changes['start'])
|
||||||
|
{
|
||||||
|
$_event['old_start'] = $changes['start'];
|
||||||
|
}
|
||||||
|
// if we have an explicit exception, always report that as a change from the regular recurrence
|
||||||
|
elseif (!empty($_event['recurrence']) && empty($_event['recur_type']) && $_event['recurrence'] != $_event['start'])
|
||||||
|
{
|
||||||
|
$_event['old_start'] = $changes['start'] = $_event['recurrence'];
|
||||||
|
$changes['end'] = $_event['recurrence'] + $_event['end']-$_event['start'];
|
||||||
|
}
|
||||||
|
|
||||||
return $changes;
|
return $changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@
|
|||||||
<et2-description value="Title"></et2-description>
|
<et2-description value="Title"></et2-description>
|
||||||
<et2-description id="title" noLang="1" class="@changed[title]"></et2-description>
|
<et2-description id="title" noLang="1" class="@changed[title]"></et2-description>
|
||||||
</row>
|
</row>
|
||||||
<row class="row" disabled="!$cont[location]$cont[##videoconference]">
|
<row class="row" disabled="!$cont[location]{$cont['##videoconference']}"> <!-- '##videoconference' must be in quotes because of #! -->
|
||||||
<et2-description value="Location"></et2-description>
|
<et2-description value="Location"></et2-description>
|
||||||
<et2-hbox>
|
<et2-hbox>
|
||||||
<et2-description id="location" noLang="1" class="@changed[location]"></et2-description>
|
<et2-description id="location" noLang="1" class="@changed[location]"></et2-description>
|
||||||
@ -90,6 +90,7 @@
|
|||||||
<et2-description value="Date"></et2-description>
|
<et2-description value="Date"></et2-description>
|
||||||
<et2-hbox class="dates">
|
<et2-hbox class="dates">
|
||||||
<et2-date-time id="start" readonly="true" class="@changed[start]"></et2-date-time>
|
<et2-date-time id="start" readonly="true" class="@changed[start]"></et2-date-time>
|
||||||
|
<et2-date-time id="old_start" readonly="true" class="meetingRequestChangedValue" disabled="!@old_start"></et2-date-time>
|
||||||
<et2-date-time label="-" id="end" readonly="true" class="@changed[end]"></et2-date-time>
|
<et2-date-time label="-" id="end" readonly="true" class="@changed[end]"></et2-date-time>
|
||||||
</et2-hbox>
|
</et2-hbox>
|
||||||
</row>
|
</row>
|
||||||
@ -111,7 +112,7 @@
|
|||||||
</row>
|
</row>
|
||||||
<row class="row" valign="top">
|
<row class="row" valign="top">
|
||||||
<et2-description value="Participants"></et2-description>
|
<et2-description value="Participants"></et2-description>
|
||||||
<grid id="participantChanges" class="meetingRequestParticipants">
|
<grid id="participantChanges" class="meetingRequestParticipants $cont[changed][participants]">
|
||||||
<columns>
|
<columns>
|
||||||
<column/>
|
<column/>
|
||||||
</columns>
|
</columns>
|
||||||
@ -169,6 +170,7 @@
|
|||||||
}
|
}
|
||||||
et2-hbox.dates {
|
et2-hbox.dates {
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
|
width: fit-content;
|
||||||
}
|
}
|
||||||
.meetingWarning tr.th {
|
.meetingWarning tr.th {
|
||||||
background-color: #dc2625;
|
background-color: #dc2625;
|
||||||
@ -176,7 +178,7 @@
|
|||||||
.meetingWarning tr.row td {
|
.meetingWarning tr.row td {
|
||||||
font-size: 120% !important;
|
font-size: 120% !important;
|
||||||
}
|
}
|
||||||
.meetingRequestError, .meetingRequestChanged, .meetingRequestChangedStatus et2-description[id$=status\]], .meetingRequestParticipantDeleted {
|
.meetingRequestError, .meetingRequestChanged, .meetingRequestChangedStatus et2-description[id$=status\]] {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
@ -184,7 +186,8 @@
|
|||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
padding-left: 0 !important;
|
padding-left: 0 !important;
|
||||||
}
|
}
|
||||||
.meetingRequestParticipantDeleted {
|
.meetingRequestParticipantDeleted, .meetingRequestChangedValue {
|
||||||
|
font-style: italic;
|
||||||
text-decoration: line-through;
|
text-decoration: line-through;
|
||||||
}
|
}
|
||||||
</styles>
|
</styles>
|
||||||
|
Loading…
Reference in New Issue
Block a user