* Calendar: allow to create recurring events with explicit recurrences

This commit is contained in:
ralf 2024-06-29 11:52:34 +02:00
parent 76ade7bc89
commit cbd2e4c695
7 changed files with 71 additions and 24 deletions

View File

@ -129,7 +129,7 @@ class calendar_bo
MCAL_RECUR_MONTHLY_WDAY => 'Monthly (by day)',
MCAL_RECUR_MONTHLY_MDAY => 'Monthly (by date)',
MCAL_RECUR_YEARLY => 'Yearly',
MCAL_RECUR_RDATE/*calendar_rrule::PERIOD*/ => 'Explicit dates',
MCAL_RECUR_RDATE/*calendar_rrule::PERIOD*/ => 'Explicit recurrences',
);
/**
* @var array recur_days translates MCAL recur-days to verbose labels

View File

@ -82,7 +82,7 @@ class calendar_rrule implements Iterator
self::MONTHLY_WDAY => 'Monthly (by day)',
self::MONTHLY_MDAY => 'Monthly (by date)',
self::YEARLY => 'Yearly',
self::PERIOD => 'By date or period'
self::PERIOD => 'By date or period'
);
/**
@ -316,6 +316,15 @@ class calendar_rrule implements Iterator
}
$this->interval = (int)$interval;
if ($exceptions)
{
foreach($exceptions as $exception)
{
$exception->setTimezone($this->time->getTimezone());
$this->exceptions[] = $exception->format('Ymd');
}
$this->exceptions_objs = $exceptions;
}
$this->enddate = $enddate;
if($type == self::PERIOD)
{
@ -324,6 +333,11 @@ class calendar_rrule implements Iterator
$rdate->setTimezone($this->time->getTimezone());
$this->period[] = $rdate;
}
// if startdate is neither in the rdates, nor the exceptions --> prepend it to rdates
if (!in_array($this->time, $this->period) && !in_array($this->time, $this->exceptions_objs))
{
array_unshift($this->period, clone($this->time));
}
$enddate = clone(count($this->period) ? end($this->period) : $this->time);
// Make sure to include the last date as valid
$enddate->modify('+1 second');
@ -353,15 +367,6 @@ class calendar_rrule implements Iterator
{
$this->weekdays = self::getWeekday($this->time);
}
if ($exceptions)
{
foreach($exceptions as $exception)
{
$exception->setTimezone($this->time->getTimezone());
$this->exceptions[] = $exception->format('Ymd');
}
$this->exceptions_objs = $exceptions;
}
}
/**

View File

@ -336,6 +336,18 @@ class calendar_uiforms extends calendar_ui
}
$update_type = 'edit';
}
if (!empty($content['recur_rdates']['delete_rdate']))
{
$date = key($content['recur_rdates']['delete_rdate']);
// eT2 converts time to
if (!is_numeric($date)) $date = Api\DateTime::to(str_replace('Z', '', $date), 'ts');
unset($content['recur_rdates']['delete_rdate']);
if (($key = array_search($date, $content['recur_rdates'])) !== false)
{
unset($content['recur_rdates'][$key]);
$content['recur_rdates'] = array_values($content['recur_rdates']);
}
}
// delete an alarm
if (!empty($content['alarm']['delete_alarm']))
{
@ -667,10 +679,21 @@ class calendar_uiforms extends calendar_ui
switch((string)$button)
{
case 'exception': // create an exception in a recuring event
case 'exception': // create an exception in a recurring event
$msg = $this->_create_exception($event,$preserv);
break;
case 'add_rdate':
if (!empty($event['recur_rdate']) && array_search($event['recur_rdate'], (array)$event['recur_rdates']) === false)
{
$event['recur_rdates'][] = $event['recur_rdate'];
usort($event['recur_rdates'], static function($a, $b) {
return $a <=> $b;
});
$msg = lang('Added recurrence on %1.', Api\DateTime::to($event['recur_rdate']));
}
break;
case 'edit':
// Going from add dialog to full edit dialog
unset($preserv['template']);

View File

@ -1403,17 +1403,24 @@ export class CalendarApp extends EgwApp
}
/**
* Function for disabling the recur_data multiselect box
* Function for disabling the recur_data multiselect box and add_rdate hbox
*
*/
check_recur_type()
{
var recurType = <et2_selectbox> this.et2.getWidgetById('recur_type');
var recurData = <et2_selectbox> this.et2.getWidgetById('recur_data');
const recurType = <et2_selectbox> this.et2.getWidgetById('recur_type');
const recurData = <et2_selectbox> this.et2.getWidgetById('recur_data');
const addRdate = this.et2.getWidgetById('button[add_rdate]');
const recurRdate = this.et2.getWidgetById('recur_rdate');
if(recurType && recurData)
{
recurData.set_disabled(recurType.get_value() != 2 && recurType.get_value() != 4);
recurData.set_disabled(recurType.value != 2 && recurType.value != 4);
}
if (recurType && addRdate && recurRdate)
{
addRdate.set_disabled(recurType.value != 9);
recurRdate.set_disabled(recurType.value != 9);
}
}
@ -1435,11 +1442,18 @@ export class CalendarApp extends EgwApp
// Update recurring date limit, if not set it can't be before start
if(widget)
{
var recur_end = widget.getRoot().getWidgetById('recur_enddate');
const recur_end = widget.getRoot().getWidgetById('recur_enddate');
if(recur_end && recur_end.getValue && !recur_end.value)
{
recur_end.set_min(widget.value);
}
// update recur_rdate with start (specially time) and set start as minimum
const recur_rdate = widget.getRoot().getWidgetById('recur_rdate');
if (recur_rdate)
{
recur_rdate.set_min(widget.value);
recur_rdate.value = widget.value;
}
// Update end date, min duration is 1 minute
let end = <Et2Date>widget.getRoot().getWidgetById('end');
@ -1453,7 +1467,6 @@ export class CalendarApp extends EgwApp
}
// Update currently selected alarm time
this.alarm_custom_date();
}
/**

View File

@ -32,6 +32,7 @@ add current view as favorite calendar de Ansicht als Favorit zufügen
add new alarm calendar de Neuen Alarm erstellen
add new event calendar de Einen neuen Termin hinzufügen
add new participants or resource calendar de Neue(n) Teilnehmer oder Ressource auswählen
add recurrence calendar de Wiederholung hinzufügen
add timesheet entry calendar de Stundenzettel hinzufügen
added calendar de Neuer Termin
added by synchronization calendar de Durch Synchronisation hinzugefügt
@ -247,7 +248,7 @@ exclude weekend calendar de Wochenende ausschließen
execute a further action for this entry calendar de Führt einen weiteren Befehl für diesen Eintrag aus
existing links calendar de Bestehende Verknüpfungen
exists calendar de Existiert
explicit dates calendar de Explizite Termine
explicit recurrences calendar de Explizite Wiederholungen
export definition to use for nextmatch export calendar de Export Profil der Listenansicht (Disketten Symbol)
exports events from your calendar in ical format. calendar de Exportiert Termine im iCal-Format
exports events from your calendar into a csv file. calendar de Exportiert Termine im CSV-Format
@ -524,8 +525,6 @@ search string for the events calendar de Suchtext für Termine
select a %1 calendar de %1 auswählen
select a color for this calendar calendar de Wählen Sie eine Farbe für diesen Kalender
select a time calendar de Eine Zeit auswählen
select an action calendar de Befehl auswählen
select an action... calendar de Aktion auswählen ...
select multiple contacts for a further action calendar de Mehrere Adressen für weiteren Befehl auswählen
select resources calendar de Ressourcen auswählen
select whether you want the participant stati reset to unknown, if an event is shifted later on. calendar de Wählen Sie aus, in welchem Fall der Teilnehmerstatus von Teilnehmern zurückgesetzt werden soll, wenn ein Termin verschoben wird. Der Teilnehmerstatus von Externen wird immer zurückgesetzt!

View File

@ -32,6 +32,7 @@ add current view as favorite calendar en Add current view as favorite
add new alarm calendar en Add new alarm
add new event calendar en Add new appointment
add new participants or resource calendar en Add new participants or resource
add recurrence calendar en Add recurrence
add timesheet entry calendar en Add timesheet entry
added calendar en Added
added by synchronization calendar en Added by synchronization
@ -247,7 +248,7 @@ exclude weekend calendar en Exclude Weekend
execute a further action for this entry calendar en Execute a further action for this entry
existing links calendar en Existing links
exists calendar en Exists
explicit dates calendar en Explicit dates
explicit recurrences calendar en Explicit recurrences
export definition to use for nextmatch export calendar en Export definition to use for nextmatch export
exports events from your calendar in ical format. calendar en Exports events from your calendar in iCal format.
exports events from your calendar into a csv file. calendar en Exports events from your calendar into a CSV file.

View File

@ -123,16 +123,22 @@
<et2-vbox>
<et2-select-dow statustext="Days of the week for a weekly repeated event" id="recur_data" rows="6"
multiple="true" placeholder=""></et2-select-dow>
<grid id="recur_rdates" class="recur_rdates">
<grid id="recur_rdates" class="recur_rdates" disabled="!@recur_rdates">
<columns>
<column/>
<column/>
</columns>
<rows>
<row>
<et2-date-time id="$row" readonly="true"></et2-date-time>
<et2-button-icon statustext="Delete this recurrence" id="delete_rdate[$row_cont]" onclick="et2_dialog.confirm(widget,'Delete this recurrence','Delete')" image="delete"></et2-button-icon>
</row>
</rows>
</grid>
<et2-hbox>
<et2-date-time id="recur_rdate"></et2-date-time>
<et2-button id="button[add_rdate]" label="Add recurrence"></et2-button>
</et2-hbox>
</et2-vbox>
<et2-vbox>
<et2-description value="Exceptions"></et2-description>
@ -147,7 +153,7 @@
<rows>
<row>
<et2-date-time id="$row" readonly="true"></et2-date-time>
<et2-button statustext="Delete this exception" label="Delete" id="delete_exception[$row_cont]" onclick="et2_dialog.confirm(widget,'Delete this exception','Delete')" image="delete"></et2-button>
<et2-button-icon statustext="Delete this exception" id="delete_exception[$row_cont]" onclick="et2_dialog.confirm(widget,'Delete this exception','Delete')" image="delete"></et2-button-icon>
</row>
</rows>
</grid>