package org.sigmah.client.ui.presenter.calendar;
/*
* #%L
* Sigmah
* %%
* Copyright (C) 2010 - 2016 URD
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.sigmah.client.dispatch.CommandResultHandler;
import org.sigmah.client.event.UpdateEvent;
import org.sigmah.client.i18n.I18N;
import org.sigmah.client.inject.Injector;
import org.sigmah.client.page.Page;
import org.sigmah.client.page.PageRequest;
import org.sigmah.client.page.RequestParameter;
import org.sigmah.client.ui.notif.N10N;
import org.sigmah.client.ui.presenter.base.AbstractPagePresenter;
import org.sigmah.client.ui.view.base.ViewInterface;
import org.sigmah.client.ui.view.calendar.CalendarEventView;
import org.sigmah.client.ui.widget.button.Button;
import org.sigmah.client.ui.widget.form.FormPanel;
import org.sigmah.client.util.ClientUtils;
import org.sigmah.shared.command.CreateEntity;
import org.sigmah.shared.command.UpdateEntity;
import org.sigmah.shared.command.result.Calendar;
import org.sigmah.shared.command.result.CreateResult;
import org.sigmah.shared.command.result.VoidResult;
import org.sigmah.shared.dto.calendar.CalendarWrapper;
import org.sigmah.shared.dto.calendar.Event;
import org.sigmah.shared.dto.calendar.PersonalEventDTO;
import com.allen_sauer.gwt.log.client.Log;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.widget.form.DateField;
import com.extjs.gxt.ui.client.widget.form.TextArea;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.form.Time;
import com.extjs.gxt.ui.client.widget.form.TimeField;
import com.google.inject.ImplementedBy;
import com.google.inject.Inject;
import com.google.inject.Singleton;
/**
* Calendar event presenter which manages the {@link CalendarEventView}.
*
* @author Denis Colliot (dcolliot@ideia.fr)
*/
@Singleton
public class CalendarEventPresenter extends AbstractPagePresenter<CalendarEventPresenter.View> {
/**
* Description of the view managed by this presenter.
*/
@ImplementedBy(CalendarEventView.class)
public static interface View extends ViewInterface {
FormPanel getForm();
TextField<String> getEventSummaryField();
DateField getEventDateField();
TimeField getEventStartTimeField();
TimeField getEventEndTimeField();
TextArea getEventDescriptionField();
Button getSaveButton();
Button getCancelButton();
}
/**
* The edited calendar event, or {@code null} if creation.
*/
private Event event;
private CalendarWrapper calendarWrapper;
/**
* Presenters's initialization.
*
* @param view Presenter's view interface.
* @param injector Injected client injector.
*/
@Inject
public CalendarEventPresenter(final View view, final Injector injector) {
super(view, injector);
}
/**
* {@inheritDoc}
*/
@Override
public Page getPage() {
return Page.CALENDAR_EVENT;
}
/**
* {@inheritDoc}
*/
@Override
public void onBind() {
// --
// Cancel button listener.
// --
view.getCancelButton().addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(final ButtonEvent ce) {
hideView();
}
});
// --
// Save button listener.
// --
view.getSaveButton().addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(final ButtonEvent ce) {
onSaveAction();
}
});
}
/**
* {@inheritDoc}
*/
@Override
public void onPageRequest(final PageRequest request) {
view.getForm().clearAll();
// --
// Reading inputs into request.
// --
event = request.getData(RequestParameter.DTO);
final boolean creation = event == null;
final List<CalendarWrapper> calendars = request.getData(RequestParameter.CONTENT);
if (ClientUtils.isEmpty(calendars)) {
hideView();
throw new IllegalArgumentException("Provided calendars list is invalid.");
}
setPageTitle(creation ? I18N.CONSTANTS.calendarAddEvent() : I18N.CONSTANTS.calendarEditEvent());
// --
// Loading received calendars.
// --
for (final CalendarWrapper calendarWrapper : calendars) {
if (calendarWrapper.getCalendar().isEditable()) {
this.calendarWrapper = calendarWrapper;
}
}
// --
// Loading event on view (if edition).
// --
if (creation) {
return;
}
this.calendarWrapper = new CalendarWrapper(event.getParent());
view.getEventSummaryField().setValue(event.getSummary());
view.getEventDateField().setValue(event.getKey());
if (!isFullDayEvent(event)) {
final Time startTime = event.getDtstart() != null ? view.getEventStartTimeField().findModel(event.getDtstart()) : null;
view.getEventStartTimeField().setValue(startTime);
final Time endTime = event.getDtend() != null ? view.getEventEndTimeField().findModel(event.getDtend()) : null;
view.getEventEndTimeField().setValue(endTime);
}
view.getEventDescriptionField().setValue(event.getDescription());
}
// ---------------------------------------------------------------------------------------------------------------
//
// UTILITY METHODS.
//
// ---------------------------------------------------------------------------------------------------------------
/**
* Method executed on save button action.
*/
@SuppressWarnings("deprecation")
private void onSaveAction() {
if (!view.getForm().isValid()) {
return;
}
// --
// Building properties map.
// --
final Map<String, Serializable> properties = new HashMap<String, Serializable>();
properties.put(Event.CALENDAR_ID, calendarWrapper);
properties.put(Event.SUMMARY, view.getEventSummaryField().getValue());
final Date date = view.getEventDateField().getValue();
properties.put(Event.DATE, date);
final Date startDate = view.getEventStartTimeField().getDateValue();
if (startDate != null) {
startDate.setYear(date.getYear());
startDate.setMonth(date.getMonth());
startDate.setDate(date.getDate());
properties.put(Event.START_TIME, startDate.getTime());
} else {
properties.put(Event.START_TIME, null);
}
final Date endDate = view.getEventEndTimeField().getDateValue();
if (endDate != null) {
endDate.setYear(date.getYear());
endDate.setMonth(date.getMonth());
endDate.setDate(date.getDate());
properties.put(Event.END_TIME, endDate.getTime());
} else {
properties.put(Event.END_TIME, null);
}
properties.put(Event.DESCRIPTION, view.getEventDescriptionField().getValue());
if (event == null) {
addPersonalEvent(properties);
} else {
editPersonalEvent(event, properties);
}
}
/**
* Creates a new "Personal" calendar event.
*
* @param properties Properties of the new event.
*/
private void addPersonalEvent(final Map<String, Serializable> properties) {
final CreateEntity createEntity = new CreateEntity(PersonalEventDTO.ENTITY_NAME, properties);
dispatch.execute(createEntity, new CommandResultHandler<CreateResult>() {
@Override
public void onCommandFailure(final Throwable caught) {
if (Log.isErrorEnabled()) {
Log.error(I18N.CONSTANTS.calendarAddEventError(), caught);
}
N10N.error(I18N.CONSTANTS.error(), I18N.CONSTANTS.calendarAddEventError());
}
@Override
public void onCommandSuccess(final CreateResult result) {
// Creating events.
final Event event = new Event();
event.setIdentifier((Integer) result.getEntity().getId());
updateEvent(event, properties);
}
}, view.getCancelButton(), view.getSaveButton());
}
/**
* Edits the events.
*
* @param properties Properties of the new event.
*/
private void editPersonalEvent(final Event event, final Map<String, ?> properties) {
@SuppressWarnings("unchecked")
final UpdateEntity updateEntity = new UpdateEntity(PersonalEventDTO.ENTITY_NAME, event.getIdentifier(), (Map<String, Object>) properties);
dispatch.execute(updateEntity, new CommandResultHandler<VoidResult>() {
@Override
public void onCommandFailure(final Throwable caught) {
if (Log.isErrorEnabled()) {
Log.error(I18N.CONSTANTS.calendarAddEventError(), caught);
}
N10N.error(I18N.CONSTANTS.error(), I18N.CONSTANTS.calendarAddEventError());
}
@Override
public void onCommandSuccess(final VoidResult result) {
final Calendar calendar = event.getParent();
final List<Event> oldEventList =
calendar.getEvents().get(event.getKey());
oldEventList.remove(event);
updateEvent(event, properties);
}
}, view.getCancelButton(), view.getSaveButton());
}
/**
* Updates the given {@code event} with the given {@code properties}.
*
* @param event The event to update.
* @param properties The properties.
*/
@SuppressWarnings("deprecation")
private void updateEvent(final Event event, final Map<String, ?> properties) {
// --
// Updates the event.
// --
event.setSummary((String) properties.get(Event.SUMMARY));
event.setDescription((String) properties.get(Event.DESCRIPTION));
final Date day = (Date) properties.get(Event.DATE);
final Object startHourSerialized = properties.get(Event.START_TIME);
final Object endHourSerialized = properties.get(Event.END_TIME);
if (startHourSerialized != null) {
final Date startHour = new Date((Long) startHourSerialized);
event.setDtstart(startHour);
if (endHourSerialized != null) {
final Date endHour = new Date((Long) endHourSerialized);
event.setDtend(endHour);
} else {
event.setDtend(null);
}
} else {
event.setDtstart(new Date(day.getYear(), day.getMonth(), day.getDate()));
event.setDtend(new Date(day.getYear(), day.getMonth(), day.getDate() + 1));
}
// Adding the new event to the calendar
final CalendarWrapper wrapper = (CalendarWrapper) properties.get(Event.CALENDAR_ID);
final Calendar calendar = wrapper.getCalendar();
event.setParent(calendar);
List<Event> events = calendar.getEvents().get(day);
if (events == null) {
events = new ArrayList<Event>();
calendar.getEvents().put(day, events);
}
events.add(event);
// --
// Sends an update event on the event bus.
// --
eventBus.fireEvent(new UpdateEvent(UpdateEvent.CALENDAR_EVENT_UPDATE, event));
// calendarWidget.refresh();
// --
// Hides the view.
// --
hideView();
}
/**
* Returns if the given {@code event} is a full day event.
*
* @param event The event.
* @return {@code true} if the given {@code event} is a full day event.
*/
@SuppressWarnings("deprecation")
private static boolean isFullDayEvent(final Event event) {
if (event == null) {
return false;
}
return event.getDtend() != null
&& (event.getDtstart().getDate() != event.getDtend().getDate() || event.getDtstart().getMonth() != event.getDtend().getMonth() || event.getDtstart()
.getYear() != event.getDtend().getYear());
}
}