/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/
package org.olat.commons.calendar.ui;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.olat.commons.calendar.CalendarManager;
import org.olat.commons.calendar.CalendarManagerFactory;
import org.olat.commons.calendar.CalendarUtils;
import org.olat.commons.calendar.GotoDateEvent;
import org.olat.commons.calendar.ImportCalendarManager;
import org.olat.commons.calendar.model.Kalendar;
import org.olat.commons.calendar.model.KalendarComparator;
import org.olat.commons.calendar.model.KalendarEvent;
import org.olat.commons.calendar.ui.components.KalendarRenderWrapper;
import org.olat.commons.calendar.ui.components.WeeklyCalendarComponent;
import org.olat.commons.calendar.ui.events.KalendarGUIAddEvent;
import org.olat.commons.calendar.ui.events.KalendarGUIEditEvent;
import org.olat.commons.calendar.ui.events.KalendarModifiedEvent;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.components.link.LinkFactory;
import org.olat.core.gui.components.panel.Panel;
import org.olat.core.gui.components.util.ComponentUtil;
import org.olat.core.gui.components.velocity.VelocityContainer;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.controller.BasicController;
import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
import org.olat.core.gui.control.generic.modal.DialogBoxController;
import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
import org.olat.core.gui.translator.PackageTranslator;
import org.olat.core.gui.translator.Translator;
import org.olat.core.util.CodeHelper;
import org.olat.core.util.Util;
import org.olat.core.util.coordinate.CoordinatorManager;
import org.olat.core.util.event.GenericEventListener;
import org.olat.core.util.notifications.ContextualSubscriptionController;
import org.olat.core.util.notifications.NotificationsManager;
import org.olat.core.util.notifications.SubscriptionContext;
import org.olat.core.util.resource.OresHelper;
import de.bps.olat.util.notifications.SubscriptionProvider;
import de.bps.olat.util.notifications.SubscriptionProviderImpl;
public class WeeklyCalendarController extends BasicController implements CalendarController, GenericEventListener {
private static final String PACKAGE = CalendarManager.class.getPackage().getName();
private static final String VELOCITY_ROOT = Util.getPackageVelocityRoot(CalendarManager.class);
private static final String CMD_PREVIOUS_WEEK = "pw";
private static final String CMD_NEXT_WEEK = "nw";
public static final String CALLER_HOME = "home";
public static final String CALLER_PROFILE = "profile";
public static final String CALLER_COLLAB = "collab";
public static final String CALLER_COURSE = "course";
private Panel mainPanel;
private VelocityContainer vcMain;
private Translator translator;
private List<KalendarRenderWrapper> calendarWrappers;
private List<KalendarRenderWrapper> importedCalendarWrappers;
private WeeklyCalendarComponent weeklyCalendar;
private KalendarConfigurationController calendarConfig;
private ImportedCalendarConfigurationController importedCalendarConfig;
private KalendarEntryDetailsController editController;
private SearchAllCalendarsController searchController;
private CalendarSubscription calendarSubscription;
private Controller subscriptionController;
private String caller;
private boolean dirty = false;
private Link thisWeekLink;
private Link searchLink;
private Link subscribeButton;
private Link unsubscribeButton;
private CloseableModalController cmc;
private GotoDateCalendarsForm gotoDateForm;
private SubscriptionContext subsContext;
private ContextualSubscriptionController csc;
/**
* three options:
* 1. edit sequence
* 2. delete single date
* 3. delete whole sequence
*/
private DialogBoxController dbcSequence;
private DialogBoxController deleteSingleYesNoController, deleteSequenceYesNoController;
private String modifiedCalendarId;
private boolean modifiedCalenderDirty = false;
/**
* Display week view of calendar. Add the calendars to be displayed via
* addKalendarWrapper(KalendarRenderWrapper kalendarWrapper) method.
*
* @param ureq
* @param wControl
*/
public WeeklyCalendarController(UserRequest ureq, WindowControl wControl, List<KalendarRenderWrapper> calendarWrappers, String caller) {
this(ureq, wControl, calendarWrappers, new ArrayList<KalendarRenderWrapper>(), caller, null);
}
public WeeklyCalendarController(UserRequest ureq, WindowControl wControl, List<KalendarRenderWrapper> calendarWrappers, List<KalendarRenderWrapper> importedCalendarWrappers, String caller) {
this(ureq, wControl, calendarWrappers, importedCalendarWrappers, caller, null);
}
public WeeklyCalendarController(UserRequest ureq, WindowControl wControl, List<KalendarRenderWrapper> calendarWrappers, String caller, CalendarSubscription calendarSubscription) {
this(ureq, wControl, calendarWrappers, new ArrayList<KalendarRenderWrapper>(), caller, calendarSubscription);
}
/**
* Display week view of calendar. Add the calendars to be displayed via
* addKalendarWrapper(KalendarRenderWrapper kalendarWrapper) method.
*
* @param ureq
* @param wControl
* @param calendarSubscription Provide a CalendarSubscription component or null if no subscription available.
*/
public WeeklyCalendarController(UserRequest ureq, WindowControl wControl, List<KalendarRenderWrapper> calendarWrappers, List<KalendarRenderWrapper> importedCalendarWrappers, String caller, CalendarSubscription calendarSubscription) {
super(ureq,wControl);
this.calendarWrappers = calendarWrappers;
this.importedCalendarWrappers = importedCalendarWrappers;
this.calendarSubscription = calendarSubscription;
this.caller = caller;
// translator
translator = new PackageTranslator(PACKAGE, ureq.getLocale());
// main panel
mainPanel = new Panel("mainPanel");
// main velocity controller
vcMain = new VelocityContainer("calMain", VELOCITY_ROOT + "/indexWeekly.html", translator, this);
thisWeekLink = LinkFactory.createLink("cal.thisweek", vcMain, this);
gotoDateForm = new GotoDateCalendarsForm(ureq, wControl, translator);
this.listenTo(gotoDateForm);
vcMain.put("cal.gotodate", gotoDateForm.getInitialComponent());
searchLink = LinkFactory.createLink("cal.search.button", vcMain, this);
subscribeButton = LinkFactory.createButtonXSmall("cal.subscribe", vcMain, this);
unsubscribeButton = LinkFactory.createButtonXSmall("cal.unsubscribe", vcMain, this);
vcMain.contextPut("caller", caller);
mainPanel.setContent(vcMain);
Collections.sort(calendarWrappers, KalendarComparator.getInstance());
Collections.sort(importedCalendarWrappers, KalendarComparator.getInstance());
List<KalendarRenderWrapper> allCalendarWrappers = new ArrayList<KalendarRenderWrapper>(calendarWrappers);
allCalendarWrappers.addAll(importedCalendarWrappers);
weeklyCalendar = new WeeklyCalendarComponent("weeklyCalendar", allCalendarWrappers, 7, getTranslator());
weeklyCalendar.addListener(this);
// subscription, see OLAT-3861
SubscriptionProvider provider = new SubscriptionProviderImpl(caller, calendarWrappers.get(0));
subsContext = provider.getSubscriptionContext();
// if sc is null, then no subscription is desired
if (subsContext != null) {
csc = provider.getContextualSubscriptionController(ureq, getWindowControl());
vcMain.put("calsubscription", csc.getInitialComponent());
}
ComponentUtil.registerForValidateEvents(vcMain, this);
vcMain.put("calendar", weeklyCalendar);
// calendarConfiguration component
calendarConfig = new KalendarConfigurationController(calendarWrappers, ureq, getWindowControl(), false, true);
calendarConfig.addControllerListener(this);
vcMain.put("calendarConfig", calendarConfig.getInitialComponent());
importedCalendarConfig = new ImportedCalendarConfigurationController(importedCalendarWrappers, ureq, getWindowControl(), false);
importedCalendarConfig.addControllerListener(this);
vcMain.put("importedCalendarConfig", importedCalendarConfig.getInitialComponent());
// calendar subscription
if (calendarSubscription == null) {
vcMain.contextPut("hasSubscription", Boolean.FALSE);
} else {
vcMain.contextPut("hasSubscription", Boolean.TRUE);
vcMain.contextPut("isSubscribed", new Boolean(calendarSubscription.isSubscribed()));
}
this.putInitialPanel(mainPanel);
CoordinatorManager.getCoordinator().getEventBus().registerFor(this, ureq.getIdentity(), OresHelper.lookupType(CalendarManager.class));
}
public void setEnableRemoveFromPersonalCalendar(boolean enable) {
calendarConfig.setEnableRemoveFromPersonalCalendar(enable);
}
public void setFocus(Date date) {
Calendar focus = CalendarUtils.createCalendarInstance(getLocale());
focus.setTime(date);
weeklyCalendar.setFocus(focus.get(Calendar.YEAR), focus.get(Calendar.WEEK_OF_YEAR));
}
@Override
public void setFocusOnEvent(String eventId) {
if (eventId.length() > 0) {
for(KalendarRenderWrapper wrapper:calendarWrappers) {
KalendarEvent event = wrapper.getKalendar().getEvent(eventId);
if(event != null) {
setFocus(event.getBegin());
break;
}
}
}
}
public void setCalendars(List calendars) {
setCalendars(calendars, new ArrayList());
}
public void setCalendars(List calendars, List importedCalendars) {
this.calendarWrappers = calendars;
Collections.sort(calendarWrappers, KalendarComparator.getInstance());
weeklyCalendar.setKalendars(calendarWrappers);
calendarConfig.setCalendars(calendarWrappers);
this.importedCalendarWrappers = importedCalendars;
Collections.sort(calendarWrappers, KalendarComparator.getInstance());
Collections.sort(importedCalendarWrappers, KalendarComparator.getInstance());
ArrayList allCalendarWrappers = new ArrayList(calendarWrappers);
allCalendarWrappers.addAll(importedCalendarWrappers);
weeklyCalendar.setKalendars(allCalendarWrappers);
calendarConfig.setCalendars(calendarWrappers);
importedCalendarConfig.setCalendars(importedCalendarWrappers);
}
public void setDirty() {
dirty = true;
}
public void event(UserRequest ureq, Component source, Event event) {
if (event == ComponentUtil.VALIDATE_EVENT && dirty) {
dirty = false;
fireEvent(ureq, new KalendarModifiedEvent());
} else if (event == ComponentUtil.VALIDATE_EVENT && weeklyCalendar.isDirty() && modifiedCalenderDirty ) {
KalendarRenderWrapper kalendarRenderWrapper = weeklyCalendar.getKalendarRenderWrapper(modifiedCalendarId);
kalendarRenderWrapper.reloadKalendar();
}else if (source == vcMain) {
if (event.getCommand().equals(CMD_PREVIOUS_WEEK)) {
weeklyCalendar.previousWeek();
} else if (event.getCommand().equals(CMD_NEXT_WEEK)) {
weeklyCalendar.nextWeek();
}
} else if (source == thisWeekLink){
Calendar cal = CalendarUtils.createCalendarInstance(ureq.getLocale());
weeklyCalendar.setFocus(cal.get(Calendar.YEAR), cal.get(Calendar.WEEK_OF_YEAR));
} else if (source == searchLink) {
if (searchController != null) searchController.dispose();
ArrayList allCalendarWrappers = new ArrayList(calendarWrappers);
allCalendarWrappers.addAll(importedCalendarWrappers);
searchController = new SearchAllCalendarsController(ureq, getWindowControl(), translator, allCalendarWrappers);
searchController.addControllerListener(this);
if (cmc != null) cmc.dispose();
cmc = new CloseableModalController(getWindowControl(), translator.translate("close"), searchController.getInitialComponent());
cmc.activate();
} else if (source == subscribeButton || source == unsubscribeButton) {
if (subscriptionController != null) subscriptionController.dispose();
if(calendarSubscription.isSubscribed() == (source == unsubscribeButton)) {
subscriptionController = calendarSubscription.triggerSubscribeAction();
}
if (subscriptionController != null) {
// activate subscription controller
subscriptionController.addControllerListener(this);
mainPanel.setContent(subscriptionController.getInitialComponent());
} else {
vcMain.contextPut("isSubscribed", new Boolean(calendarSubscription.isSubscribed()));
CoordinatorManager.getCoordinator().getEventBus().fireEventToListenersOf(new KalendarModifiedEvent(), OresHelper.lookupType(CalendarManager.class));
}
} else if (source == weeklyCalendar) {
if (event instanceof KalendarGUIEditEvent) {
KalendarGUIEditEvent guiEvent = (KalendarGUIEditEvent) event;
KalendarEvent kalendarEvent = guiEvent.getKalendarEvent();
if (kalendarEvent == null) {
// event already deleted
getWindowControl().setError(translator.translate("cal.error.eventDeleted"));
return;
}
String recurrence = kalendarEvent.getRecurrenceRule();
boolean isImported = false;
KalendarRenderWrapper kalendarRenderWrapper = guiEvent.getKalendarRenderWrapper();
if (kalendarRenderWrapper!=null) {
isImported = kalendarRenderWrapper.isImported();
}
if( !isImported && recurrence != null && !recurrence.equals("") ) {
List<String> btnLabels = new ArrayList<String>();
btnLabels.add(translator.translate("cal.edit.dialog.sequence"));
btnLabels.add(translator.translate("cal.edit.dialog.delete.single"));
btnLabels.add(translator.translate("cal.edit.dialog.delete.sequence"));
if (dbcSequence != null) dbcSequence.dispose();
dbcSequence = DialogBoxUIFactory.createGenericDialog(ureq, getWindowControl(), translator.translate("cal.edit.dialog.title"), translator.translate("cal.edit.dialog.text"), btnLabels);
dbcSequence.addControllerListener(this);
dbcSequence.setUserObject(guiEvent);
dbcSequence.activate();
return;
}
KalendarRenderWrapper kalendarWrapper = guiEvent.getKalendarRenderWrapper();
pushEditEventController(ureq, kalendarEvent, kalendarWrapper);
} else if (event instanceof KalendarGUIAddEvent) {
pushAddEventController((KalendarGUIAddEvent)event, ureq);
}
}
}
public void event(UserRequest ureq, Controller source, Event event) {
Kalendar affectedCal = null;
if (dirty) {
dirty = false;
fireEvent(ureq, new KalendarModifiedEvent());
}
if (source == editController) {
affectedCal = editController.getKalendarEvent().getCalendar();
cmc.deactivate();
weeklyCalendar.setDirty(true);
} else if(source == cmc && event == CloseableModalController.CLOSE_MODAL_EVENT){
//DO NOT DEACTIVATE AS ALREADY CLOSED BY CloseableModalController INTERNALLY
weeklyCalendar.setDirty(true);
} else if (source == calendarConfig || source == importedCalendarConfig) {
if (event instanceof KalendarGUIAddEvent) {
pushAddEventController((KalendarGUIAddEvent)event, ureq);
} else if (event == Event.CHANGED_EVENT) {
importedCalendarWrappers = ImportCalendarManager.getImportedCalendarsForIdentity(ureq);
importedCalendarConfig.setCalendars(importedCalendarWrappers);
this.setCalendars(calendarWrappers, importedCalendarWrappers);
weeklyCalendar.setDirty(true);
vcMain.setDirty(true);
}
} else if (source == searchController) {
if (event instanceof GotoDateEvent) {
Date gotoDate = ((GotoDateEvent)event).getGotoDate();
weeklyCalendar.setDate(gotoDate);
}
cmc.deactivate();
} else if (source == subscriptionController) {
// nothing to do here
mainPanel.setContent(vcMain);
vcMain.contextPut("isSubscribed", new Boolean(calendarSubscription.isSubscribed()));
} else if (source == gotoDateForm) {
weeklyCalendar.setDate(gotoDateForm.getGotoDate());
} else if (source == dbcSequence) {
if(event != Event.CANCELLED_EVENT) {
int pos = DialogBoxUIFactory.getButtonPos(event);
KalendarGUIEditEvent guiEvent = (KalendarGUIEditEvent)dbcSequence.getUserObject();
KalendarRenderWrapper kalendarWrapper = guiEvent.getKalendarRenderWrapper();
KalendarEvent kalendarEvent = guiEvent.getKalendarEvent();
if(pos == 0) { // edit the sequence
// load the parent event of this sequence
KalendarEvent parentEvent = kalendarWrapper.getKalendar().getEvent(kalendarEvent.getID());
pushEditEventController(ureq, parentEvent, kalendarWrapper);
} else if(pos == 1) { // delete a single event of the sequence
deleteSingleYesNoController = activateYesNoDialog(ureq, null, translator.translate("cal.delete.dialogtext"), deleteSingleYesNoController);
deleteSingleYesNoController.setUserObject(kalendarEvent);
} else if(pos == 2) { // delete the whole sequence
deleteSequenceYesNoController = activateYesNoDialog(ureq, null, translator.translate("cal.delete.dialogtext.sequence"), deleteSequenceYesNoController);
deleteSequenceYesNoController.setUserObject(kalendarEvent);
}
}
dbcSequence.dispose();
} else if (source == deleteSingleYesNoController) {
if (DialogBoxUIFactory.isYesEvent(event)) {
KalendarEvent kalendarEvent = (KalendarEvent)deleteSingleYesNoController.getUserObject();
affectedCal = kalendarEvent.getCalendar();
KalendarEvent kEvent = affectedCal.getEvent(kalendarEvent.getID());
kEvent.addRecurrenceExc(kalendarEvent.getBegin());
CalendarManagerFactory.getInstance().getCalendarManager().updateEventFrom(affectedCal, kEvent);
deleteSingleYesNoController.dispose();
weeklyCalendar.setDirty(true);
vcMain.setDirty(true);
}
} else if (source == deleteSequenceYesNoController) {
if (DialogBoxUIFactory.isYesEvent(event)) {
KalendarEvent kalendarEvent = (KalendarEvent)deleteSequenceYesNoController.getUserObject();
affectedCal = kalendarEvent.getCalendar();
CalendarManagerFactory.getInstance().getCalendarManager().removeEventFrom(affectedCal, kalendarEvent);
deleteSequenceYesNoController.dispose();
weeklyCalendar.setDirty(true);
vcMain.setDirty(true);
}
}
if (weeklyCalendar.isDirty()) {
if (subsContext != null) {
// group or course calendar -> prepared subscription context is the right one
NotificationsManager.getInstance().markPublisherNews(subsContext, ureq.getIdentity());
} else if(this.caller.equals(CALLER_HOME) && affectedCal != null) {
// one can add/edit/remove dates of group and course calendars from the home calendar view -> choose right subscription context
KalendarRenderWrapper calWrapper = null;
for( Object calWrapperObj : calendarWrappers) {
calWrapper = (KalendarRenderWrapper) calWrapperObj;
if(affectedCal == calWrapper.getKalendar()) break;
}
if(calWrapper != null) {
SubscriptionProvider provider = new SubscriptionProviderImpl(calWrapper);
SubscriptionContext tmpSubsContext = provider.getSubscriptionContext();
NotificationsManager.getInstance().markPublisherNews(tmpSubsContext, ureq.getIdentity());
}
}
}
}
/**
* @param ureq
* @param kalendarEvent
* @param kalendarWrapper
*/
private void pushEditEventController(UserRequest ureq, KalendarEvent kalendarEvent, KalendarRenderWrapper kalendarWrapper) {
if (editController != null) editController.dispose();
editController = new KalendarEntryDetailsController(ureq, kalendarEvent, kalendarWrapper, calendarWrappers, false, caller, getWindowControl());
editController.addControllerListener(this);
if (cmc != null) cmc.dispose();
cmc = new CloseableModalController(getWindowControl(), translator.translate("close"), editController.getInitialComponent());
cmc.addControllerListener(this);
cmc.activate();
}
private void pushAddEventController(KalendarGUIAddEvent addEvent, UserRequest ureq) {
KalendarRenderWrapper calendarWrapper = weeklyCalendar.getKalendarRenderWrapper(addEvent.getCalendarID());
// create new KalendarEvent
KalendarEvent newEvent = new KalendarEvent(CodeHelper.getGlobalForeverUniqueID(), "", addEvent.getStartDate(), (1000 * 60 * 60 * 1));
if (calendarWrapper.getKalendar().getType().equals(CalendarManager.TYPE_COURSE) ||
calendarWrapper.getKalendar().getType().equals(CalendarManager.TYPE_GROUP))
newEvent.setClassification(KalendarEvent.CLASS_PUBLIC);
if (editController != null) editController.dispose();
ArrayList allCalendarWrappers = new ArrayList(calendarWrappers);
allCalendarWrappers.addAll(importedCalendarWrappers);
editController = new KalendarEntryDetailsController(ureq, newEvent,
calendarWrapper, allCalendarWrappers, true, caller, getWindowControl());
editController.addControllerListener(this);
if (cmc != null) cmc.dispose();
cmc = new CloseableModalController(getWindowControl(), translator.translate("close"), editController.getInitialComponent());
cmc.addControllerListener(this);
cmc.activate();
}
protected void doDispose() {
CoordinatorManager.getCoordinator().getEventBus().deregisterFor(this, OresHelper.lookupType(CalendarManager.class));
if (editController != null) {
editController.dispose();
editController = null;
}
if (calendarConfig != null) {
calendarConfig.dispose();
calendarConfig = null;
}
if (searchController != null) {
searchController.dispose();
searchController = null;
}
if (cmc != null) {
cmc.dispose();
cmc = null;
}
if (subscriptionController != null) {
subscriptionController.dispose();
subscriptionController = null;
}
}
public void event(Event event) {
if (event instanceof KalendarModifiedEvent) {
KalendarModifiedEvent kalendarModifiedEvent = (KalendarModifiedEvent)event;
if (kalendarModifiedEvent.getType()!=null
&& kalendarModifiedEvent.getCalendarId()!=null
&& weeklyCalendar.getKalendarRenderWrapper(kalendarModifiedEvent.getCalendarId())!=null
&& kalendarModifiedEvent.getType().equals(weeklyCalendar.getKalendarRenderWrapper(kalendarModifiedEvent.getCalendarId()).getKalendar().getType())
&& kalendarModifiedEvent.getCalendarId().equals(weeklyCalendar.getKalendarRenderWrapper(kalendarModifiedEvent.getCalendarId()).getKalendar().getCalendarID())) {
// the event is for my calendar => reload it
//keeping a reference to the dirty calendar as reloading here raises an nested do in sync error. Using the component validation event to reload
modifiedCalendarId = kalendarModifiedEvent.getCalendarId();
modifiedCalenderDirty = true;
weeklyCalendar.setDirty(true);
}
}
}
}