diff --git a/calendar/inc/class.calendar_rrule.inc.php b/calendar/inc/class.calendar_rrule.inc.php index a0179cde11..a9d15e4d77 100644 --- a/calendar/inc/class.calendar_rrule.inc.php +++ b/calendar/inc/class.calendar_rrule.inc.php @@ -699,7 +699,7 @@ class calendar_rrule implements Iterator case self::RDATE: $str_extra = array_map(static function (DateTime $rdate) { - return Api\DateTime::server2user($rdate, ''); + return str_replace(',', '', Api\DateTime::server2user($rdate, '')); }, $this->rdates); break; } @@ -719,6 +719,13 @@ class calendar_rrule implements Iterator { $str_extra[] = $this->time->getTimezone()->getName(); } + if ($this->exceptions_objs) + { + $str_extra[] = lang('Exceptions').': '.implode(', ', array_map(static function (DateTime $exdate) + { + return str_replace(',', '', Api\DateTime::server2user($exdate, '')); + }, $this->exceptions_objs)); + } if(count($str_extra)) { $str .= ' ('.implode(', ',$str_extra).')'; diff --git a/calendar/inc/class.calendar_uiforms.inc.php b/calendar/inc/class.calendar_uiforms.inc.php index 54acedeb04..c664c85727 100644 --- a/calendar/inc/class.calendar_uiforms.inc.php +++ b/calendar/inc/class.calendar_uiforms.inc.php @@ -2338,6 +2338,19 @@ class calendar_uiforms extends calendar_ui $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; case 'cancel': // first participant is the (external) organizer (our iCal parser adds owner first!) @@ -2369,6 +2382,7 @@ class calendar_uiforms extends calendar_ui } //error_log(__METHOD__."(...) parsed as ".array2string($event)); $event['recure'] = $this->bo->recure2string($master ?? null ?: $event); + if (!empty($master)) unset($event['changed']['recure']); $event['all_participants'] = implode(",\n",$this->bo->participants($event, true)); // EGroupware event has been deleted, don't let user resurrect it by accepting again diff --git a/calendar/templates/default/meeting.xet b/calendar/templates/default/meeting.xet index 6154e17767..6ff8511598 100644 --- a/calendar/templates/default/meeting.xet +++ b/calendar/templates/default/meeting.xet @@ -78,7 +78,7 @@ - + @@ -110,8 +110,21 @@ - - + + + + + + + + + + + + + + + @@ -163,10 +176,17 @@ .meetingWarning tr.row td { font-size: 120% !important; } - .meetingRequestError, .meetingRequestChanged { + .meetingRequestError, .meetingRequestChanged, .meetingRequestChangedStatus et2-description[id$=status\]], .meetingRequestParticipantDeleted { font-style: italic; color: red; } + #calendar-meeting table.et2_grid.meetingRequestParticipants td { + padding: 0 !important; + padding-left: 0 !important; + } + .meetingRequestParticipantDeleted { + text-decoration: line-through; + } \ No newline at end of file