stefanuebe/vaadin-fullcalendar

Recurring event does not extend infinitely

Opened this issue ยท 9 comments

I created a test view for recurring events as such:

@route(value = "ctest")
public class CalendarTest extends VerticalLayout {

private static final long serialVersionUID = 7733363567261805869L;

public CalendarTest() {
	var provider = new InMemoryEntryProvider<Entry>(makeTestEntries());
	FullCalendar calendar = makeCalendar(provider);
	this.setSizeFull();
	add(calendar);
}

private List<Entry> makeTestEntries() {
	var entry1 = new Entry(UUID.randomUUID().toString());
	entry1.setGroupId(UUID.randomUUID().toString());
	entry1.setRecurringStartDate(LocalDate.of(2024, 2, 20));
	entry1.setRecurringStartTime(LocalTime.of(12, 0));
	entry1.setRecurringStartTime(LocalTime.of(13, 0));
	return Arrays.asList(entry1);
}

private FullCalendar makeCalendar(InMemoryEntryProvider<Entry> provider2) {

	var ret = FullCalendarBuilder.create().build();
	ret.setSizeFull();
	ret.setFirstDay(DayOfWeek.MONDAY);
	ret.addThemeVariants(FullCalendarVariant.LUMO);
	ret.setTimeslotsSelectable(true);
	ret.setEntryProvider(provider2);
	ret.setOption(Option.SELECT_OVERLAP, false);
	ret.setOption(Option.ALL_DAY_SLOT, false);
	ret.changeView(CalendarViewImpl.TIME_GRID_WEEK);

	// https://www.oracle.com/java/technologies/javase/jdk11-suported-locales.html
	ret.setLocale(Locale.forLanguageTag("fi-FI"));

	return ret;
}

}

When I open this view the recurrence seems to be working fine
kuva

but if I drag the event one day backwards the recurrence seems to stop
kuva

flow Fullcalendar version: 6.2.1

This bug is also in vanilla FullCalendar. I made an issue about this in their repo. fullcalendar/fullcalendar#7603

From your code I would assume, that this is a pure FC lib issue and nothing that I can change. I'd say a workaround is to set a dummy date somewhere in the future, e.g. in the year 9999, which then always can be checked against at to see if it is an entry with an infinite date.,

Small update: I got it working correctly, when calling this code inside the entry dropped event listener

if (entry.isRecurring()) {
    event.applyChangesOnEntry();
    entry.setRecurringStartDate(entry.getStartAsLocalDate()); // apply changes on entry does not update the recurring date
   
    getCalendar().getEntryProvider().refreshItem(entry);
}

But the above example is just very rudimentary and does not take into account, that one of "middle" entries might be moved. In Google Calendar for instance, when moving some recurring event, it does not automatically affect all other auto generated items but allow to customize the recurrence somehow.

Therefore there might be some more complex logic necessary, like

  • delete the current recurring definition
  • create a new recurring definition up to the latest unedited entry before the current moved event
  • create a new entry without any recurrence at the dropped point
  • create a new recurring entry starting after the dropped entry with the first unedited entry
  • keep the connection between all these entries alive so that modifying one of them still may affect all others

This of course has to be reflected somehow in your backing model.

  • delete the current recurring definition

  • create a new recurring definition up to the latest unedited entry before the current moved event

  • create a new entry without any recurrence at the dropped point

  • create a new recurring entry starting after the dropped entry with the first unedited entry

  • keep the connection between all these entries alive so that modifying one of them still may affect all others

That's pretty much the functionality I need for my use case. Although I think it might be less convoluted to have dragging move the entire recurring event by default and splicing the recurring event as you described would require more input from the user.

@stefanuebe This might be a bit off-topic, but do you have any ideas on how to find out from which part of the recurring event the user started dragging? It seems the only data there is, is the original entry and where the dragging stopped.

I made a feature request for that fullcalendar/fullcalendar#7607

It is indeed the original entry, as for the model there is just one entry.

On the client side, the event info (the listener parameter) also contains the "oldEvent", which contains the source time. This can be added to the event listener information for the server side.

As a workaround however, you also get the delta of the drop so based on the delta plus the drop time you can calculate the original date.

As a workaround however, you also get the delta of the drop so based on the delta plus the drop time you can calculate the original date.

Ah, I see, thanks for the clarification.

I was doing some testing on recurring event dnd and when I dropped an event, the start and end values were simply set to be the drop location value, no matter where the drag started. So I thought Delta would be the difference between those values.