Closed schube closed 3 months ago
Since the release of version 2 of domino-ui we already had this feature, but we never documented it, we implemented this a similar way of how Datatable plugins works, and due to this lack of documentation - or lack of time and funding to do the documentation - it have never been tested, I just tried to implement some simple plugins similar to the is described in the issue above and will share them here until the time come to add them to the official documentation samples
import org.dominokit.domino.ui.datepicker.CalendarDay;
import org.dominokit.domino.ui.datepicker.CalendarPlugin;
public class DisableWeekendDaysPlugin implements CalendarPlugin {
@Override
public void onCalendarDayAdded(CalendarDay calendarDay) {
if (calendarDay.isWeekend()) {
calendarDay.disable();
calendarDay.addCss("dui-mark-weekend-day");
}
}
}
The result will be something like this
import elemental2.dom.HTMLDivElement;
import org.dominokit.domino.ui.datepicker.Calendar;
import org.dominokit.domino.ui.datepicker.CalendarDay;
import org.dominokit.domino.ui.datepicker.CalendarPlugin;
import org.dominokit.domino.ui.elements.DivElement;
import org.dominokit.domino.ui.popover.Popover;
import org.dominokit.domino.ui.typography.BlockHeader;
import org.dominokit.domino.ui.utils.BaseDominoElement;
import org.gwtproject.i18n.client.DateTimeFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static java.util.Objects.nonNull;
import static org.dominokit.domino.ui.style.ColorsCss.dui_bg_accent;
import static org.dominokit.domino.ui.style.ColorsCss.dui_fg_white;
import static org.dominokit.domino.ui.style.DisplayCss.dui_flex;
import static org.dominokit.domino.ui.style.SpacingCss.*;
import static org.dominokit.domino.ui.utils.Domino.div;
public class SimpleEventsPlugin implements CalendarPlugin {
private Map<Long, List<CalendarEvent>> eventsMap = new HashMap<>();
private Calendar calendar;
public SimpleEventsPlugin(Collection<CalendarEvent> events) {
if (nonNull(events)) {
events.forEach(event -> {
long longDate = toPlainDate(event.getDate());
if (!eventsMap.containsKey(longDate)) {
eventsMap.put(longDate, new ArrayList<>());
}
eventsMap.get(longDate).add(event);
});
}
}
@Override
public void onInit(Calendar calendar) {
this.calendar = calendar;
}
@Override
public void onCalendarDayAdded(CalendarDay calendarDay) {
long longDate = toPlainDate(calendarDay.getDate());
calendarDay.addCss(dui_justify_start);
if (eventsMap.containsKey(longDate)) {
calendarDay.appendChild(div()
.addCss(dui_w_4, dui_h_4, dui_rounded_full, dui_bg_accent, dui_self_center)
.apply(self -> {
Popover.create(self)
.addCss(dui_rounded_md)
.apply(popover -> {
DivElement eventsElement = div().addCss(dui_flex, dui_flex_col, dui_gap_2, dui_p_4);
popover.appendChild(eventsElement);
eventsMap.get(longDate)
.forEach(event -> {
eventsElement.appendChild(div()
.addCss(dui_w_64, dui_rounded_md, dui_bg_accent, dui_p_2, dui_fg_white)
.appendChild(BlockHeader.create(toTimeString(event.date), event.getDescription()))
);
});
});
})
);
}
}
private String toTimeString(Date date){
return DateTimeFormat.getFormat(this.calendar.getDateTimeFormatInfo().formatHour12Minute()).format(date);
}
private long toPlainDate(Date date) {
long timeInMillis = date.getTime();
// Convert to the beginning of the day
long millisInDay = 24 * 60 * 60 * 1000; // Milliseconds in a day
long millisSinceMidnight = timeInMillis % millisInDay;
return timeInMillis - millisSinceMidnight;
}
public static class CalendarEvent {
private final String description;
private final Date date;
private String color;
public CalendarEvent(String description, Date date) {
this.description = description;
this.date = date;
}
public CalendarEvent(String description, Date date, String color) {
this(description, date);
this.color = color;
}
public static CalendarEvent of(String description, Date date) {
return new CalendarEvent(description, date);
}
public String getDescription() {
return description;
}
public Date getDate() {
return date;
}
public String getColor() {
return color;
}
}
public static class EventComponent extends BaseDominoElement<HTMLDivElement, EventComponent> {
private final DivElement root;
private final CalendarEvent event;
public EventComponent(CalendarEvent event) {
this.event = event;
this.root = div();
init(this);
}
public DivElement getRoot() {
return root;
}
public CalendarEvent getEvent() {
return event;
}
@Override
public HTMLDivElement element() {
return root.element();
}
}
}
The result will be something like this
To use the plugin feature pass to the calendar constructor the calendar config instance with the registered plugins
Calendar.create(new CalendarInitConfig()
.addPlugin(new DisableWeekendDaysPlugin())
.addPlugin(new SimpleEventsPlugin(Arrays.asList(SimpleEventsPlugin.CalendarEvent.of("My best friend birthday", new Date()))))
)
The feature is not as rich as it is with the datatable plugin, but it works as a baseline to build on top of based on feedback and requests.
The commit on this issue is just a few bugs and adjustments to make sure the plugins works as intended but the feature was there for some time now, please test and send us some feedback and we will look at it.
Thank you, that works great! This is the perfect starting point for my next task! I really appreciate your help and all the effort you put into DominoUI!
The Datepicker from https://dominokit.com/domino-ui/demo/v2/forms/datepicker is a wonderful component, but I miss one feature: I do not want all days to be selectable. For example a site where you can book events: 1.) You cannot events in the past 2.) You cannot book events, when there is no event (for example on Mondays) 3.) You cannot book events, when all tickets are booked / event is sold out.
So I would like to access the single days and have the ability to style them. No event days could be grey, sold out days could be "italic" or any any other styling. Also, they should not be clickable.
See https://demo.mobiscroll.com/jquery/calendar/appointment-booking for example. (In that example, there is also a price on each day, which is not necessary at the moment). But you get the idea :-)
Thank you!