diff --git a/pom.xml b/pom.xml index ca9fefbba..bcdebf2f1 100644 --- a/pom.xml +++ b/pom.xml @@ -156,8 +156,8 @@ 1.8 - INFO - OBFUSCATED + ALL + DETAILED 9 true true @@ -201,13 +201,13 @@ [%-5level] {%d{dd/MM/yyyy HH:mm:ss.SSS}} [%thread] %logger{35} - %msg%n - ERROR + ALL jdbc:postgresql://localhost:5432/sigmah - sigmah - sigmah + postgres + admin @@ -885,7 +885,8 @@ org.jacoco jacoco-maven-plugin - 0.7.4.201502262128 + 0.7.9 + @@ -932,7 +933,7 @@ / org.sigmah.Sigmah - -Xmx1G -Xss256M -XX:PermSize=256M -Djava.io.tmpdir=${project.build.directory} + -Xmx1G -Xss128M -Djava.io.tmpdir=${project.build.directory} @@ -1058,7 +1059,11 @@ - + jdbc:postgresql://localhost:5432/sigmah + postgres + admin + C:\\Users\\1\\Documents\\GitHub\\sigmah + C:\\Users\\1\\Documents\\GitHub\\sigmah\\archives @@ -1222,4 +1227,4 @@ - + \ No newline at end of file diff --git a/src/main/java/org/sigmah/client/ui/presenter/calendar/CalendarEventPresenter.java b/src/main/java/org/sigmah/client/ui/presenter/calendar/CalendarEventPresenter.java index 00f3847f9..0f49298d9 100644 --- a/src/main/java/org/sigmah/client/ui/presenter/calendar/CalendarEventPresenter.java +++ b/src/main/java/org/sigmah/client/ui/presenter/calendar/CalendarEventPresenter.java @@ -21,7 +21,6 @@ * . * #L% */ - import java.io.Serializable; import java.util.ArrayList; import java.util.Date; @@ -51,11 +50,17 @@ 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.DatePickerEvent; +import com.extjs.gxt.ui.client.event.Events; +import com.extjs.gxt.ui.client.event.Listener; import com.extjs.gxt.ui.client.event.SelectionListener; +import com.extjs.gxt.ui.client.widget.form.CheckBox; import com.extjs.gxt.ui.client.widget.form.DateField; +import com.extjs.gxt.ui.client.widget.form.FieldSet; +import com.extjs.gxt.ui.client.widget.form.Radio; +import com.extjs.gxt.ui.client.widget.form.RadioGroup; 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; @@ -63,345 +68,1684 @@ import com.google.inject.ImplementedBy; import com.google.inject.Inject; import com.google.inject.Singleton; +import static java.lang.Integer.parseInt; /** * Calendar event presenter which manages the {@link CalendarEventView}. - * + * * @author Denis Colliot (dcolliot@ideia.fr) */ @Singleton public class CalendarEventPresenter extends AbstractPagePresenter { - /** - * Description of the view managed by this presenter. - */ - @ImplementedBy(CalendarEventView.class) - public static interface View extends ViewInterface { - - FormPanel getForm(); - - TextField 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() { - - @Override - public void componentSelected(final ButtonEvent ce) { - hideView(); - } - }); - - // -- - // Save button listener. - // -- - view.getSaveButton().addSelectionListener(new SelectionListener() { - - @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 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 properties = new HashMap(); - 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 properties) { - - final CreateEntity createEntity = new CreateEntity(PersonalEventDTO.ENTITY_NAME, properties); - - dispatch.execute(createEntity, new CommandResultHandler() { - - @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 properties) { - - @SuppressWarnings("unchecked") - final UpdateEntity updateEntity = new UpdateEntity(PersonalEventDTO.ENTITY_NAME, event.getIdentifier(), (Map) properties); - - dispatch.execute(updateEntity, new CommandResultHandler() { - - @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 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 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 events = calendar.getEvents().get(day); - if (events == null) { - events = new ArrayList(); - 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()); - } - + private Event event; + private CalendarWrapper calendarWrapper; + + /** + * Description of the view managed by this presenter. + */ + @ImplementedBy(CalendarEventView.class) + public static interface View extends ViewInterface { + + /** + * + * @return + */ + FormPanel getForm(); + + /** + * + * @return + */ + TextField getEventSummaryField(); + + /** + * + * @return + */ + DateField getEventDateStartField(); + + /** + * + * @return + */ + DateField getEventDateEndField(); + + /** + * + * @return + */ + TimeField getEventStartTimeField(); + + /** + * + * @return + */ + TimeField getEventEndTimeField(); + + /** + * + * @return + */ + TextArea getEventDescriptionField(); + + /** + * + * @return + */ + Button getSaveButton(); + + /** + * + * @return + */ + Button getCancelButton(); + + /** + * + * @return + */ + CheckBox getAllDayCheckbox(); + + /** + * + * @return + */ + FieldSet getPanelYearly(); + + /** + * + * @return + */ + FieldSet getPanelMonthly(); + + /** + * + * @return + */ + FieldSet getPanelWeekly(); + + /** + * + * @return + */ + FieldSet getPanelDaily(); + + /** + * + * @return + */ + FieldSet getMonthlyRepSettings(); + + /** + * + * @return + */ + FieldSet getYearlyRepSettings(); + + /** + * + * @return + */ + Radio getOnceRepeatRB(); + + /** + * + * @return + */ + Radio getDailyRepeatRB(); + + /** + * + * @return + */ + Radio getWeeklyRepeatRB(); + + /** + * + * @return + */ + Radio getMonthlyRepeatRB(); + + /** + * + * @return + */ + Radio getYearlyRepeatRB(); + + /** + * + * @return + */ + RadioGroup getYearlyVariantRG(); + + /** + * + * @return + */ + RadioGroup getMontlyVariantRG(); + + /** + * + * @return + */ + Radio getYearlySameDayOfWeekRB(); + + /** + * + * @return + */ + Radio getYearlySameDateRB(); + + /** + * + * @return + */ + RadioGroup getRepeatEventPeriodRG(); + + /** + * + * @return + */ + RadioGroup getRepeatMultiEventPeriodRG(); + + /** + * + * @return + */ + Radio getRadioMonthlySameDate(); + + /** + * + * @return + */ + Radio getRadioMonthlySameDayOfWeek(); + + /** + * + * @return + */ + Radio getRadioRepetitionEndDate(); + + /** + * + * @return + */ + Radio getRadioNumberOfRepetitions(); + + /** + * + * @return + */ + Radio getDailyRadioRepetitionEndDate(); + + /** + * + * @return + */ + Radio getDailyRadioNumberOfRepetitions(); + + /** + * + * @return + */ + Radio getWeeklyRadioRepetitionEndDate(); + + /** + * + * @return + */ + Radio getWeeklyRadioNumberOfRepetitions(); + + /** + * + * @return + */ + Radio getYearlyRadioRepetitionEndDate(); + + /** + * + * @return + */ + Radio getYearlyRadioNumberOfRepetitions(); + + /** + * + * @return + */ + TextArea getNumberOfRepetitions(); + + /** + * + * @return + */ + DateField getRepetitionEndDate(); + + /** + * + * @return + */ + TextArea getWeeklyNumberOfRepetitions(); + + /** + * + * @return + */ + DateField getWeeklyRepetitionEndDate(); + + /** + * + * @return + */ + TextArea getYearlyNumberOfRepetitions(); + + /** + * + * @return + */ + DateField getYearlyRepetitionEndDate(); + + /** + * + * @return + */ + TextArea getDailyNumberOfRepetitions(); + + /** + * + * @return + */ + DateField getDailyRepetitionEndDate(); + + // void setShowAddEventView(boolean showAddEventView); + } + + /** + * The edited calendar event, or {@code null} if creation. + */ + /** + * 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() { + + @Override + public void componentSelected(final ButtonEvent ce) { + hideView(); + } + }); + + // -- + // Save button listener. + // -- + view.getSaveButton().addSelectionListener(new SelectionListener() { + + @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 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) { + prepareAddView(); + } else { + prepareEditView(); + } + } + + /** + * Create Edit Calendar Event View + */ + private void prepareEditView() { + this.calendarWrapper = new CalendarWrapper(event.getParent()); + + view.getForm().clearState(); + view.getEventSummaryField().setValue(event.getSummary()); + view.getEventDateStartField().setValue(event.getKey()); + view.getEventDateEndField().setValue(event.getDtend()); + view.getEventDateStartField().getDatePicker().addListener(Events.Select, new Listener() { + + @Override + public void handleEvent(DatePickerEvent be) { + if (view.getEventDateEndField().getValue() == null) { + view.getEventDateEndField().setValue(view.getEventDateStartField().getValue()); + } + } + }); + view.getEventDateEndField().getDatePicker().addListener(Events.Select, new Listener() { + + @Override + public void handleEvent(DatePickerEvent be) { + if (view.getEventDateStartField().getValue() == null) { + view.getEventDateStartField().setValue(view.getEventDateEndField().getValue()); + } + } + }); + /* view.getEventStartTimeField().addListener(Events.Select, new Listener() { + + @Override + public void handleEvent(DatePickerEvent be) { + if (view.getEventEndTimeField().getValue() == null) { + view.getEventEndTimeField().setValue(view.getEventStartTimeField().getValue()); + } + } + }); + view.getEventEndTimeField().addListener(Events.Select, new Listener() { + + @Override + public void handleEvent(DatePickerEvent be) { + if (view.getEventStartTimeField().getValue() == null) { + view.getEventStartTimeField().setValue(view.getEventEndTimeField().getValue()); + } + } + });*/ + if (view.getRepeatEventPeriodRG() != null) { + view.getRepeatEventPeriodRG().clear(); + view.getRepeatEventPeriodRG().clearInvalid(); + view.getRepeatEventPeriodRG().clearState(); + view.getRepeatEventPeriodRG().setSelectionRequired(false); + view.getRepeatEventPeriodRG().hide(); + + view.getPanelMonthly().hide(); + view.getMontlyVariantRG().hide(); + + view.getPanelYearly().hide(); + view.getYearlyVariantRG().hide(); + + view.getPanelWeekly().hide(); + + view.getPanelDaily().hide(); + + view.getYearlyVariantRG().hide(); + view.getMontlyVariantRG().hide(); + view.getRepeatEventPeriodRG().hide(); + view.getMonthlyRepeatRB().hide(); + view.getYearlySameDateRB().hide(); + view.getYearlySameDayOfWeekRB().hide(); + view.getRadioMonthlySameDate().hide(); + view.getRadioMonthlySameDayOfWeek().hide(); + + view.getRadioNumberOfRepetitions().setValue(true); + view.getNumberOfRepetitions().enable(); + view.getRepetitionEndDate().disable(); + view.getNumberOfRepetitions().setValue("1"); + view.getRepetitionEndDate().setValue(new Date()); + + view.getYearlyRadioNumberOfRepetitions().setValue(true); + view.getYearlyNumberOfRepetitions().enable(); + view.getYearlyRepetitionEndDate().disable(); + view.getYearlyNumberOfRepetitions().setValue("1"); + view.getYearlyRepetitionEndDate().setValue(new Date()); + + view.getWeeklyRadioNumberOfRepetitions().setValue(true); + view.getWeeklyNumberOfRepetitions().enable(); + view.getWeeklyRepetitionEndDate().disable(); + view.getWeeklyNumberOfRepetitions().setValue("1"); + view.getWeeklyRepetitionEndDate().setValue(new Date()); + + view.getDailyRadioNumberOfRepetitions().setValue(true); + view.getDailyNumberOfRepetitions().enable(); + view.getDailyRepetitionEndDate().disable(); + view.getDailyNumberOfRepetitions().setValue("1"); + view.getDailyRepetitionEndDate().setValue(new Date()); + } + if (event.getEventType().contains("F")) { + view.getAllDayCheckbox().setValue(true); + view.getEventStartTimeField().hide(); + view.getEventEndTimeField().hide(); + } else { + view.getAllDayCheckbox().setValue(false); + view.getEventStartTimeField().show(); + view.getEventEndTimeField().show(); + } + if (!event.getEventType().contains("F")) { + + 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()); + } + + /** + * Create Add Calendar Event View + */ + private void prepareAddView() { + if (view.getRepeatEventPeriodRG() != null) { + view.getRepeatEventPeriodRG().enable(); + view.getRepeatEventPeriodRG().show(); + view.getOnceRepeatRB().setValue(true); + view.getPanelMonthly().hide(); + view.getPanelYearly().hide(); + view.getPanelWeekly().hide(); + view.getPanelDaily().hide(); + // view.getMonthlyRepSettings().hide(); + // view.getYearlyRepSettings().hide(); + } + view.getEventStartTimeField().show(); + view.getEventEndTimeField().show(); + + view.getYearlyVariantRG().enable(); + view.getMontlyVariantRG().enable(); + view.getRepeatEventPeriodRG().enable(); + view.getMonthlyRepeatRB().enable(); + view.getYearlySameDateRB().enable(); + view.getYearlySameDayOfWeekRB().enable(); + view.getRadioMonthlySameDate().enable(); + view.getRadioMonthlySameDayOfWeek().enable(); + + view.getRepeatMultiEventPeriodRG().enable(); + view.getRadioNumberOfRepetitions().enable(); + view.getRadioRepetitionEndDate().enable(); + view.getNumberOfRepetitions().enable(); + view.getRepetitionEndDate().enable(); + + view.getRepeatMultiEventPeriodRG().show(); + view.getRadioNumberOfRepetitions().show(); + view.getRadioRepetitionEndDate().show(); + view.getNumberOfRepetitions().show(); + view.getRepetitionEndDate().show(); + + view.getEventDateStartField().getDatePicker().addListener(Events.Select, new Listener() { + + @Override + public void handleEvent(DatePickerEvent be) { + if (view.getEventDateEndField().getValue() == null) { + view.getEventDateEndField().setValue(view.getEventDateStartField().getValue()); + } + } + }); + view.getEventDateEndField().getDatePicker().addListener(Events.Select, new Listener() { + + @Override + public void handleEvent(DatePickerEvent be) { + if (view.getEventDateStartField().getValue() == null) { + view.getEventDateStartField().setValue(view.getEventDateEndField().getValue()); + } + } + }); + + /* view.getEventStartTimeField().addListener(Events.Select, new Listener() { + + @Override + public void handleEvent(DatePickerEvent be) { + if (view.getEventEndTimeField().getValue() == null) { + view.getEventEndTimeField().setValue(view.getEventStartTimeField().getValue()); + } + } + }); + view.getEventEndTimeField().addListener(Events.Select, new Listener() { + + @Override + public void handleEvent(DatePickerEvent be) { + if (view.getEventStartTimeField().getValue() == null) { + view.getEventStartTimeField().setValue(view.getEventEndTimeField().getValue()); + } + } + }); */ + view.getYearlyVariantRG().show(); + view.getMontlyVariantRG().show(); + view.getRepeatEventPeriodRG().show(); + view.getMonthlyRepeatRB().show(); + view.getYearlySameDateRB().show(); + view.getYearlySameDayOfWeekRB().show(); + view.getRadioMonthlySameDate().show(); + view.getRadioMonthlySameDayOfWeek().show(); + view.getEventDateEndField().show(); + view.getAllDayCheckbox().setValue(true); + view.getEventStartTimeField().hide(); + view.getEventEndTimeField().hide(); + + view.getRadioNumberOfRepetitions().setValue(true); + view.getNumberOfRepetitions().enable(); + view.getRepetitionEndDate().disable(); + view.getNumberOfRepetitions().setValue("1"); + view.getRepetitionEndDate().setValue(new Date()); + + view.getYearlyRadioNumberOfRepetitions().setValue(true); + view.getYearlyNumberOfRepetitions().enable(); + view.getYearlyRepetitionEndDate().disable(); + view.getYearlyNumberOfRepetitions().setValue("1"); + view.getYearlyRepetitionEndDate().setValue(new Date()); + + view.getWeeklyRadioNumberOfRepetitions().setValue(true); + view.getWeeklyNumberOfRepetitions().enable(); + view.getWeeklyRepetitionEndDate().disable(); + view.getWeeklyNumberOfRepetitions().setValue("1"); + view.getWeeklyRepetitionEndDate().setValue(new Date()); + + view.getDailyRadioNumberOfRepetitions().setValue(true); + view.getDailyNumberOfRepetitions().enable(); + view.getDailyRepetitionEndDate().disable(); + view.getDailyNumberOfRepetitions().setValue("1"); + view.getDailyRepetitionEndDate().setValue(new Date()); + } + + // --------------------------------------------------------------------------------------------------------------- + // + // UTILITY METHODS. + // + // --------------------------------------------------------------------------------------------------------------- + /** + * Method executed on save button action. + */ + @SuppressWarnings("deprecation") + private void onSaveAction() { + // Window.alert("onSaveAction"); + if (!view.getForm().isValid()) { + return; + } + // -- + // Building properties map. + // -- + final Map properties = new HashMap(); + properties.put(Event.CALENDAR_ID, calendarWrapper); + properties.put(Event.SUMMARY, view.getEventSummaryField().getValue()); + + String eventSummary = view.getEventSummaryField().getValue(); + String eventDescription = view.getEventDescriptionField().getValue(); + + final Date beginEventIntervalDate = view.getEventDateStartField().getValue(); + properties.put(Event.DATE, beginEventIntervalDate); + + Date endEventIntervalDate = (view.getEventDateEndField() != null ? view.getEventDateEndField().getValue() : null); + if (endEventIntervalDate == null) { + endEventIntervalDate = beginEventIntervalDate; + } + properties.put(Event.DATE_END, endEventIntervalDate); +//Window.alert("Date start: " +beginEventIntervalDate.getYear()+"." +beginEventIntervalDate.getMonth() + // + "." + beginEventIntervalDate.getDate() + " | Date end: " +endEventIntervalDate.getYear()+"." +endEventIntervalDate.getMonth() + // + "." + endEventIntervalDate.getDate());//temp for checker + Boolean isFullDayEvent = view.getAllDayCheckbox().getValue(); + + // Window.alert("isAllDayEvent=" + isFullDayEvent);//temp for checker + Date startDateTime = createStartDateTimeProperty(isFullDayEvent, beginEventIntervalDate, properties); + Date endDateTime = createEndDateTimeProperty(isFullDayEvent, beginEventIntervalDate, properties); + int daysdiff = calculateEventDurationInDays(beginEventIntervalDate, endEventIntervalDate); + properties.put(Event.DESCRIPTION, view.getEventDescriptionField().getValue()); + + if (event == null) { + processAddEvent(endEventIntervalDate, beginEventIntervalDate, startDateTime, endDateTime, properties, eventSummary, eventDescription); + } else { + + properties.put(Event.EVENT_TYPE, event.getEventType()); + properties.put(Event.REFERENCE_ID, event.getReferenceId()); + + if (isFullDayEvent) { + // Window.alert("#3 isFullDayEvent event.getEventType() = " + event.getEventType()); + if (event.getEventType() != null) { + if ("O".equals(event.getEventType()) + || "OH".equals(event.getEventType())) { + properties.put(Event.EVENT_TYPE, "OF"); + } else if ("D".equals(event.getEventType()) + || "DH".equals(event.getEventType())) { + properties.put(Event.EVENT_TYPE, "DF"); + } else if ("W".equals(event.getEventType()) + || "WH".equals(event.getEventType())) { + properties.put(Event.EVENT_TYPE, "WF"); + } else if ("M".equals(event.getEventType()) + || "MH".equals(event.getEventType())) { + properties.put(Event.EVENT_TYPE, "MF"); + } else if ("Y".equals(event.getEventType()) + || "YH".equals(event.getEventType())) { + properties.put(Event.EVENT_TYPE, "YF"); + } + } + } else { +// Window.alert("#4 not full day event.getEventType() = " + event.getEventType() +// + " daysdiff=" + daysdiff); + if (event.getEventType() != null) { + //Window.alert("111 event.getEventType()=" + event.getEventType() + " daysdiff=" + daysdiff); + if ("OF".equals(event.getEventType())) { + properties.put(Event.EVENT_TYPE, ("O" + (daysdiff > 1 ? "H" : ""))); + } else if ("DF".equals(event.getEventType())) { + properties.put(Event.EVENT_TYPE, ("D" + (daysdiff > 1 ? "H" : ""))); + } else if ("WF".equals(event.getEventType())) { + properties.put(Event.EVENT_TYPE, ("W" + (daysdiff > 1 ? "H" : ""))); + } else if ("MF".equals(event.getEventType())) { + properties.put(Event.EVENT_TYPE, ("M" + (daysdiff > 1 ? "H" : ""))); + } else if ("YF".equals(event.getEventType())) { + properties.put(Event.EVENT_TYPE, ("Y" + (daysdiff > 1 ? "H" : ""))); + } + } + } + editPersonalEvent(event, properties); + } + + } + + /** + * Add new calendar events processing. + * + * @param endEventIntervalDate the value of endEventIntervalDate + * @param beginEventIntervalDate the value of beginEventIntervalDate + * @param startDate the value of startDateTime + * @param endDate the value of endDateTime + * @param properties the value of properties + * @param eventSummary the value of eventSummary + * @param eventDescription the value of eventDescription + */ + private void processAddEvent(Date endEventIntervalDate, final Date beginEventIntervalDate, Date startDate, Date endDate, final Map properties, String eventSummary, String eventDescription) { + long milisPerDay = 86400000; //24 * 60 * 60 * 1000) + long milisPerWeek = 7 * milisPerDay; //7 days * (24hour * 60minutes * 60seconds * 1000mili seconds) + long diffInMilis = endEventIntervalDate.getTime() - beginEventIntervalDate.getTime(); + Boolean isDailyRepeatEvent = view.getDailyRepeatRB() != null ? view.getDailyRepeatRB().getValue() : Boolean.FALSE; + Boolean isWeeklyRepeatEvent = view.getWeeklyRepeatRB().getValue(); + Boolean isMonthlyRepeatEvent = view.getMonthlyRepeatRB().getValue(); + Boolean isYearlyRepeatEvent = view.getYearlyRepeatRB().getValue(); + + Boolean isMonthlySameDayOfWeek = view.getRadioMonthlySameDayOfWeek().getValue(); + + Boolean isYearlySameDayOfWeek = view.getYearlySameDayOfWeekRB().getValue(); + // Date endEventIntervalDate = (view.getEventDateEndField() != null ? view.getEventDateEndField().getValue() : null); + Date endEventIntervalDateRadio = view.getEventDateStartField().getValue(); + + if (isDailyRepeatEvent) { + long count = 0; + long lengthDailyEvent = ((endEventIntervalDate.getTime() - beginEventIntervalDate.getTime()) / milisPerDay) + 1; + if (view.getDailyRadioNumberOfRepetitions().getValue()) { + count = parseInt(view.getDailyNumberOfRepetitions().getValue()); + // Window.alert("Count1 = "+count); + } else { + endEventIntervalDateRadio = view.getDailyRepetitionEndDate().getValue(); + count = (((endEventIntervalDateRadio.getTime() - beginEventIntervalDate.getTime()) / milisPerDay) + 1) / lengthDailyEvent; + } + diffInMilis = endEventIntervalDateRadio.getTime() - beginEventIntervalDate.getTime(); + if (count <= 0) { + count = 1; + } + //Window.alert("Count2 = "+count); + processDailyEvents(count, lengthDailyEvent, milisPerDay, beginEventIntervalDate, endEventIntervalDateRadio, endEventIntervalDate, startDate, endDate, properties, eventSummary, eventDescription); + } else if (isWeeklyRepeatEvent) { + if (view.getWeeklyRadioNumberOfRepetitions().getValue()) { + endEventIntervalDateRadio.setDate(beginEventIntervalDate.getDate() + parseInt(view.getWeeklyNumberOfRepetitions().getValue()) * 7); + } else { + endEventIntervalDateRadio = view.getWeeklyRepetitionEndDate().getValue(); + } + diffInMilis = endEventIntervalDateRadio.getTime() - beginEventIntervalDate.getTime(); + processWeeklyEvents(beginEventIntervalDate, endEventIntervalDate, endEventIntervalDateRadio, startDate, endDate, properties, eventSummary, eventDescription); + } else if (isMonthlyRepeatEvent) { + if (view.getRadioNumberOfRepetitions().getValue()) { + endEventIntervalDateRadio.setMonth(beginEventIntervalDate.getMonth() + parseInt(view.getNumberOfRepetitions().getValue())); + } else { + endEventIntervalDateRadio = view.getRepetitionEndDate().getValue(); + } + processMonthlyEvents(beginEventIntervalDate, endEventIntervalDate, endEventIntervalDateRadio, properties, isMonthlySameDayOfWeek, startDate, endDate, eventSummary, eventDescription); + } else if (isYearlyRepeatEvent) { + if (view.getYearlyRadioNumberOfRepetitions().getValue()) { + endEventIntervalDateRadio.setYear(beginEventIntervalDate.getYear() + parseInt(view.getYearlyNumberOfRepetitions().getValue())); + } else { + endEventIntervalDateRadio = view.getYearlyRepetitionEndDate().getValue(); + } + processYearEvents(beginEventIntervalDate, endEventIntervalDate, endEventIntervalDateRadio, properties, isYearlySameDayOfWeek, startDate, endDate, eventSummary, eventDescription); + } else { + processOnceEvent(beginEventIntervalDate, diffInMilis, milisPerDay, startDate, endDate, properties, eventSummary, eventDescription); + } + } + + /** + * Create Start event date time property + * + * @param isFullDayEvent the value of isFullDayEvent + * @param beginEventIntervalDate the value of beginEventIntervalDate + * @param properties the value of properties + */ + private Date createStartDateTimeProperty(Boolean isFullDayEvent, final Date beginEventIntervalDate, final Map properties) { + + Date startDate = null; + if (!isFullDayEvent) { + startDate = view.getEventStartTimeField().getDateValue(); + } + if (startDate != null) { + startDate.setYear(beginEventIntervalDate.getYear()); + startDate.setMonth(beginEventIntervalDate.getMonth()); + startDate.setDate(beginEventIntervalDate.getDate()); + properties.put(Event.START_TIME, startDate.getTime()); + } else { + properties.put(Event.START_TIME, null); + } + return startDate; + } + + /** + * Create End event date time property + * + * @param isFullDayEvent the value of isFullDayEvent + * @param beginEventIntervalDate the value of beginEventIntervalDate + * @param properties the value of properties + */ + private Date createEndDateTimeProperty(Boolean isFullDayEvent, final Date beginEventIntervalDate, final Map properties) { + + Date endDate = null; + if (!isFullDayEvent) { + endDate = view.getEventEndTimeField().getDateValue(); + } + if (endDate != null) { + endDate.setYear(beginEventIntervalDate.getYear()); + endDate.setMonth(beginEventIntervalDate.getMonth()); + endDate.setDate(beginEventIntervalDate.getDate()); + properties.put(Event.END_TIME, endDate.getTime()); + } else { + properties.put(Event.END_TIME, null); + } + return endDate; + } + + private void processOnceEvent(final Date beginEventIntervalDate1, long diffInMilis, long milisPerDay, final Date startDate, final Date endDate, final Map properties, String eventSummary, String eventDescription) { + long daysDiff = diffInMilis / milisPerDay + 1; + long beginEventIntervalDate = beginEventIntervalDate1.getTime(); + properties.put(Event.SUMMARY, (String) properties.get(Event.SUMMARY)); + properties.put(Event.DESCRIPTION, (String) properties.get(Event.DESCRIPTION)); + // Window.alert("DaysDiff = "+daysDiff); + if (view.getAllDayCheckbox().getValue()) { + properties.put(Event.EVENT_TYPE, "OF"); + } else { + properties.put(Event.EVENT_TYPE, ("O" + (daysDiff > 1 ? "H" : ""))); + } + if (daysDiff == 1) { + addPersonalEvent(properties); + } else { + properties.put(Event.SUMMARY, (String) properties.get(Event.SUMMARY));// + " (Once event)"); + properties.put(Event.DESCRIPTION, (String) properties.get(Event.DESCRIPTION));// + " (Once event)"); +// properties.put(Event.EVENT_TYPE, "O"); +// if (view.getAllDayCheckbox().getValue()) { +// properties.put(Event.EVENT_TYPE, "OF"); +// } + addPersonalEventOnce(properties, daysDiff, beginEventIntervalDate, milisPerDay, startDate, endDate, eventSummary, eventDescription); + } + } + + private void addPersonalEventOnce(final Map properties, final long daysInterval, final long calBeginNextEventDateLong, final long milisPerDay, final Date startDate, final Date endDate, final String eventSummary, final String eventDescription) { + + final CreateEntity createEntity = new CreateEntity(PersonalEventDTO.ENTITY_NAME, properties); + + dispatch.execute(createEntity, new CommandResultHandler() { + + @Override + public void onCommandFailure(final Throwable caught) { + processAddEventError(caught); + } + + @Override + public void onCommandSuccess(final CreateResult result) { + + // Creating events. + final Event event = new Event(); + event.setIdentifier((Integer) result.getEntity().getId()); + properties.put(Event.REFERENCE_ID, (Integer) result.getEntity().getId()); + updateEvent(event, properties); + // addOnceSeriesEvent((Integer) result.getEntity().getId(), daysInterval, calBeginNextEventDateLong, milisPerDay, startDateTime, endDateTime, eventSummary, eventDescription); + } + }, view.getCancelButton(), view.getSaveButton()); + } + + /** + * Add new Daily calendar events processing. + * + * @param diffInMilis the value of diffInMilis + * @param milisPerDay the value of milisPerDay + * @param beginEventIntervalDate the value of beginEventIntervalDate + * @param startDate the value of startDateTime + * @param endDate the value of endDateTime + * @param properties the value of properties + * @param eventSummary the value of eventSummary + * @param eventDescription the value of eventDescription + */ + private void processDailyEvents(long count, long lengthDailyEvent, long milisPerDay, final Date beginEventIntervalDate, final Date endEventIntervalDateRadio, final Date endEventIntervalDate, final Date startDate, final Date endDate, final Map properties, String eventSummary, String eventDescription) { + long calBeginNextEventDateLong = beginEventIntervalDate.getTime(); + //Date calBeginNextEventDate = beginEventIntervalDate; + long daysInterval = ((endEventIntervalDate.getTime() - beginEventIntervalDate.getTime()) / milisPerDay) + 1; + + properties.put(Event.SUMMARY, (String) properties.get(Event.SUMMARY));// + " (Daily event 1 of " + count + ")"); + properties.put(Event.DESCRIPTION, (String) properties.get(Event.DESCRIPTION));// + " (Daily event 1 of " + count + ")"); + if (view.getAllDayCheckbox().getValue()) { + properties.put(Event.EVENT_TYPE, "DF"); + } else { + properties.put(Event.EVENT_TYPE, ("D" + (daysInterval > 1 ? "H" : ""))); + } + properties.put(Event.DATE_END, new Date(calBeginNextEventDateLong + milisPerDay * (lengthDailyEvent - 1))); + addPersonalEventDaily(properties, count, lengthDailyEvent, calBeginNextEventDateLong, milisPerDay, startDate, endDate, eventSummary, eventDescription); + + } + + private void addPersonalEventDaily(final Map properties, final long daysInterval, final long lengthDailyEvent, final long calBeginNextEventDateLong, final long milisPerDay, final Date startDate, final Date endDate, final String eventSummary, final String eventDescription) { + + final CreateEntity createEntity = new CreateEntity(PersonalEventDTO.ENTITY_NAME, properties); + + dispatch.execute(createEntity, new CommandResultHandler() { + + @Override + public void onCommandFailure(final Throwable caught) { + processAddEventError(caught); + } + + @Override + public void onCommandSuccess(final CreateResult result) { + + // Creating events. + final Event event = new Event(); + event.setIdentifier((Integer) result.getEntity().getId()); + properties.put(Event.REFERENCE_ID, (Integer) result.getEntity().getId()); + updateEvent(event, properties); + addDailySeriesEvent((Integer) result.getEntity().getId(), daysInterval, lengthDailyEvent, calBeginNextEventDateLong, milisPerDay, startDate, endDate, eventSummary, eventDescription); + // if (view.getAllDayCheckbox().getValue() == false) { + // addDailySeriesEventNew((Integer) result.getEntity().getId(), daysInterval, lengthDailyEvent, calBeginNextEventDateLong, milisPerDay, startDateTime, endDateTime, eventSummary, eventDescription); + // } + } + }, view.getCancelButton(), view.getSaveButton()); + } + + private void processAddEventError(final Throwable caught) { + if (Log.isErrorEnabled()) { + Log.error(I18N.CONSTANTS.calendarAddEventError(), caught); + } + N10N.error(I18N.CONSTANTS.error(), I18N.CONSTANTS.calendarAddEventError()); + } + + private void addDailySeriesEvent(Integer ids, long daysInterval, long lengthDailyEvent, long calBeginNextEventDateLong1, long milisPerDay, final Date startDate, final Date endDate, String eventSummary, String eventDescription) { + //Date calBeginNextEventDate; + long calBeginNextEventDateLong = calBeginNextEventDateLong1; + for (int i = 1; i < daysInterval; i++) { + + calBeginNextEventDateLong += (milisPerDay * lengthDailyEvent); + long calEndNextEventDateLong = calBeginNextEventDateLong + milisPerDay * (lengthDailyEvent - 1); + //calBeginNextEventDate = new Date(calBeginNextEventDateLong); + + Map dailyProperties = new HashMap(); + dailyProperties.put(Event.CALENDAR_ID, calendarWrapper); + dailyProperties.put(Event.SUMMARY, view.getEventSummaryField().getValue()); + + dailyProperties.put(Event.DATE, new Date(calBeginNextEventDateLong)); + if (view.getAllDayCheckbox().getValue()) { + dailyProperties.put(Event.EVENT_TYPE, "DF"); + } else { + dailyProperties.put(Event.EVENT_TYPE, ("D" + (daysInterval > 1 ? "H" : ""))); + } + dailyProperties.put(Event.DATE_END, new Date(calEndNextEventDateLong)); + setFullDayEvent(startDate, endDate, new Date(calBeginNextEventDateLong), dailyProperties); + + String newSummary = eventSummary; + String newDescription = eventDescription; +// newSummary += " (Daily event " + (i + 1) + " of " + daysInterval + ")"; +// newDescription += " (Daily event " + (i + 1) + " of " + daysInterval + ")"; + dailyProperties.put(Event.SUMMARY, newSummary); + dailyProperties.put(Event.DESCRIPTION, newDescription); + dailyProperties.put(Event.REFERENCE_ID, ids); + + addPersonalEvent(dailyProperties); + } + } + + /** + * Add new Weekly calendar events processing. + * + * @param diffInMilis the value of diffInMilis + * @param milisPerWeek the value of milisPerWeek + * @param beginEventIntervalDate the value of beginEventIntervalDate + * @param startDate the value of startDateTime + * @param endDate the value of endDateTime + * @param properties the value of properties + * @param eventSummary the value of eventSummary + * @param eventDescription the value of eventDescription + */ + private void processWeeklyEvents(final Date beginEventIntervalDate, final Date endEventIntervalDate, final Date endEventIntervalDateRadio, final Date startDate, final Date endDate, final Map properties, String eventSummary, String eventDescription) { + // Window.alert("processWeeklyEvents"); + long milisPerDay = 86400000; + long weekDiff = ((endEventIntervalDateRadio.getTime() - beginEventIntervalDate.getTime() + milisPerDay) / (milisPerDay * 7)); + int weeksInterval = (int) weekDiff; + if ((((endEventIntervalDateRadio.getTime() - beginEventIntervalDate.getTime() + milisPerDay) % (milisPerDay * 7)) >= ((endEventIntervalDate.getTime() - beginEventIntervalDate.getTime() + milisPerDay))) + && (view.getWeeklyRadioNumberOfRepetitions().getValue())) { + weeksInterval++; + } + if (weeksInterval <= 0) { + weeksInterval = 1; + } + if (endEventIntervalDate.getTime() - beginEventIntervalDate.getTime() == 0) { + weeksInterval--; + } + + long calBeginNextEventDateLong = beginEventIntervalDate.getTime(); + long calEndNextEventDateLong = endEventIntervalDate.getTime(); + long daysInterval = ((endEventIntervalDate.getTime() - beginEventIntervalDate.getTime()) / milisPerDay) + 1; + + properties.put(Event.SUMMARY, (String) properties.get(Event.SUMMARY)); + properties.put(Event.DESCRIPTION, (String) properties.get(Event.DESCRIPTION));// + " (Weekly event 1 of " + weeksInterval + ")"); +// Window.alert("#5 processWeeklyEvents event.getEventType() = " + (event!=null?event.getEventType():"NULL") +// + " daysInterval=" + daysInterval); + if (view.getAllDayCheckbox().getValue()) { + properties.put(Event.EVENT_TYPE, "WF"); + } else { + //Window.alert("W +daysInterval" + daysInterval); + properties.put(Event.EVENT_TYPE, ("W" + (daysInterval > 1 ? "H" : ""))); + } + addPersonalEventWeekly(properties, weeksInterval, calBeginNextEventDateLong, calEndNextEventDateLong, daysInterval, startDate, endDate, eventSummary, eventDescription); + + } + + private void addPersonalEventWeekly(final Map properties, final int weeksInterval, final long calBeginNextEventDateLong, final long calEndNextEventDateLong, final long daysInterval, final Date startDate, final Date endDate, final String eventSummary, final String eventDescription) { + + final CreateEntity createEntity = new CreateEntity(PersonalEventDTO.ENTITY_NAME, properties); + + dispatch.execute(createEntity, new CommandResultHandler() { + + @Override + public void onCommandFailure(final Throwable caught) { + processAddEventError(caught); + } + + @Override + public void onCommandSuccess(final CreateResult result) { + + // Creating events. + final Event event = new Event(); + event.setIdentifier((Integer) result.getEntity().getId()); + updateEvent(event, properties); + properties.put(Event.REFERENCE_ID, (Integer) result.getEntity().getId()); + long milisPerDay = 86400000; + addDailySeriesEventNew2((Integer) properties.get(Event.REFERENCE_ID), weeksInterval, calBeginNextEventDateLong, calEndNextEventDateLong, milisPerDay * 7, startDate, endDate, eventSummary, eventDescription); + } + }, view.getCancelButton(), view.getSaveButton()); + } + + private void addDailySeriesEventNew2(Integer ids, int daysInterval, long calBeginNextEventDateLong, long calEndNextEventDateLong, long milisPerWeek, final Date startDate, final Date endDate, String eventSummary, String eventDescription) { + long milisPerDay = 86400000; //24 * 60 * 60 * 1000) + + for (int i = 1; i < daysInterval; i++) { + + calBeginNextEventDateLong += milisPerWeek; + calEndNextEventDateLong += milisPerWeek; + + long daysLength = ((calEndNextEventDateLong - calBeginNextEventDateLong) / milisPerDay) + 1; + + Map dailyProperties = new HashMap(); + dailyProperties.put(Event.CALENDAR_ID, calendarWrapper); + dailyProperties.put(Event.SUMMARY, view.getEventSummaryField().getValue()); + + dailyProperties.put(Event.DATE, new Date(calBeginNextEventDateLong)); + + dailyProperties.put(Event.DATE_END, new Date(calEndNextEventDateLong)); + + setFullDayEvent(startDate, endDate, new Date(calBeginNextEventDateLong), dailyProperties); + + String newSummary = eventSummary; + String newDescription = eventDescription; + // newDescription += " (Weekly event " + (i + 1) + " of " + daysInterval + ")"; + dailyProperties.put(Event.SUMMARY, newSummary); + dailyProperties.put(Event.DESCRIPTION, newDescription); + if (view.getAllDayCheckbox().getValue()) { + dailyProperties.put(Event.EVENT_TYPE, "WF"); + } else { + //Window.alert("W2 +daysLength" + daysLength); + dailyProperties.put(Event.EVENT_TYPE, ("W" + (daysLength > 1 ? "H" : ""))); + } + dailyProperties.put(Event.REFERENCE_ID, ids); + + addPersonalEvent(dailyProperties); + } + } + + /** + * Set date and time values for Full day events. + * + * @param startDate the value of startDateTime + * @param endDate the value of endDateTime + * @param calBeginNextEventDate the value of calBeginNextEventDate + * @param thePeriodProperties the value of thePeriodProperties + */ + private void setFullDayEvent(final Date startDate, final Date endDate, Date calBeginNextEventDate, Map thePeriodProperties) { + if (startDate != null) { + calBeginNextEventDate.setHours(startDate.getHours()); + calBeginNextEventDate.setMinutes(startDate.getMinutes()); + thePeriodProperties.put(Event.START_TIME, calBeginNextEventDate.getTime()); + } else { + thePeriodProperties.put(Event.START_TIME, null); + } + + if (endDate != null) { + Date endD = calBeginNextEventDate; + endD.setHours(endDate.getHours()); + endD.setMinutes(endDate.getMinutes()); + thePeriodProperties.put(Event.END_TIME, endD.getTime()); + } else { + thePeriodProperties.put(Event.END_TIME, null); + } + } + + /** + * Add new Monthly calendar events processing. + * + * @param beginEventIntervalDate the value of beginEventIntervalDate + * @param endEventIntervalDate the value of endEventIntervalDate + * @param properties the value of properties + * @param isMonthlySameDayOfWeek the value of isMonthlySameDayOfWeek + * @param startDate the value of startDateTime + * @param endDate the value of endDateTime + * @param eventSummary the value of eventSummary + * @param eventDescription the value of eventDescription + */ + private void processMonthlyEvents(final Date beginEventIntervalDate, Date endEventIntervalDate, final Date endEventIntervalDateRadio, final Map properties, Boolean isMonthlySameDayOfWeek, final Date startDate, final Date endDate, String eventSummary, String eventDescription) { + long milisPerDay = 86400000; //24 * 60 * 60 * 1000) + long daysInterval = ((endEventIntervalDate.getTime() - beginEventIntervalDate.getTime()) / milisPerDay) + 1; + + if (view.getAllDayCheckbox().getValue()) { + properties.put(Event.EVENT_TYPE, "MF"); + } else { + //Window.alert("M +daysInterval" + daysInterval); + properties.put(Event.EVENT_TYPE, ("M" + (daysInterval > 1 ? "H" : ""))); + } + properties.put(Event.DATE_END, endEventIntervalDate); + Date endEventIntervalDate1 = endEventIntervalDate; + long milisDiff = endEventIntervalDate.getTime() - beginEventIntervalDate.getTime(); + endEventIntervalDate = endEventIntervalDateRadio; + int yearStart = beginEventIntervalDate.getYear(); + int yearEnd = endEventIntervalDate.getYear(); + int yearInterval = yearEnd - yearStart; + + int monthStart = beginEventIntervalDate.getMonth();//0 Jan 11 Dec + int monthEnd = endEventIntervalDate.getMonth(); + int monthInterval = 0; + if (yearInterval > 0) { + monthInterval = (yearInterval - 1) * 12 + (12 - monthStart) + (monthEnd + 1); + } else { + monthInterval = monthEnd - monthStart + 1; + } + if (view.getRadioNumberOfRepetitions().getValue()) { + monthInterval--; + } + if (monthInterval <= 0) { + monthInterval = 1; + } + properties.put(Event.SUMMARY, (String) properties.get(Event.SUMMARY));// + " (Monthly event 1 of " + monthInterval + ")"); + properties.put(Event.DESCRIPTION, (String) properties.get(Event.DESCRIPTION));// + " (Monthly event 1 of " + monthInterval + ")"); + addPersonalEventMonthly(endEventIntervalDate1, properties, monthInterval, beginEventIntervalDate, milisDiff, startDate, endDate, eventSummary, eventDescription, isMonthlySameDayOfWeek); + + } + + private void addPersonalEventMonthly(final Date endEventIntervalDate, final Map properties, final int monthInterval, final Date beginEventIntervalDate, final long milisDiff, final Date startDate, final Date endDate, final String eventSummary, final String eventDescription, final boolean isMonthlySameDayOfWeek) { + final CreateEntity createEntity = new CreateEntity(PersonalEventDTO.ENTITY_NAME, properties); + + dispatch.execute(createEntity, new CommandResultHandler() { + + @Override + public void onCommandFailure(final Throwable caught) { + processAddEventError(caught); + } + + @Override + public void onCommandSuccess(final CreateResult result) { + + // Creating events. + final Event event = new Event(); + event.setIdentifier((Integer) result.getEntity().getId()); + updateEvent(event, properties); + properties.put(Event.REFERENCE_ID, (Integer) result.getEntity().getId()); +// long milisPerDay = 86400000; +// long daysInterval = milisDiff / milisPerDay + 1; + addMonthlySeriesEvent(endEventIntervalDate, (String) result.getEntity().getId(), monthInterval, beginEventIntervalDate, startDate, endDate, eventSummary, eventDescription, isMonthlySameDayOfWeek); + } + }, view.getCancelButton(), view.getSaveButton()); + } + + private void addMonthlySeriesEvent(Date endEventIntervalDate, String ids, int monthInterval, Date beginEventIntervalDate, final Date startDate, final Date endDate, String eventSummary, String eventDescription, final boolean isMonthlySameDayOfWeek) { + Date calBeginNextEventDate = beginEventIntervalDate; + long diff = endEventIntervalDate.getTime() - beginEventIntervalDate.getTime(); + long milisPerDay = 86400000; //24 * 60 * 60 * 1000) + long daysInterval = ((endEventIntervalDate.getTime() - beginEventIntervalDate.getTime()) / milisPerDay) + 1; + + for (int i = 1; i < monthInterval; i++) { + calBeginNextEventDate = getMonthlySameDayOfWeek2(beginEventIntervalDate, calBeginNextEventDate, i, isMonthlySameDayOfWeek); + + Map monthlyProperties = new HashMap(); + monthlyProperties.put(Event.CALENDAR_ID, calendarWrapper); + monthlyProperties.put(Event.SUMMARY, view.getEventSummaryField().getValue()); + + monthlyProperties.put(Event.DATE, calBeginNextEventDate); + + monthlyProperties.put(Event.DATE_END, new Date(calBeginNextEventDate.getTime() + diff)); + if (view.getAllDayCheckbox().getValue()) { + monthlyProperties.put(Event.EVENT_TYPE, "MF"); + } else { + //Window.alert("M2 +daysInterval" + daysInterval); + monthlyProperties.put(Event.EVENT_TYPE, ("M" + (daysInterval > 1 ? "H" : ""))); + } + + setFullDayEvent(startDate, endDate, calBeginNextEventDate, monthlyProperties); + + String newSummary = eventSummary; + String newDescription = eventDescription; + // newSummary += " (Monthly event " + (i + 1) + " of " + monthInterval + ")"; + // newDescription += " (Monthly " + (isMonthlySameDayOfWeek ? "same Day of a week " : "same Date ") + "event " + (i + 1) + " of " + monthInterval + ")"; + monthlyProperties.put(Event.SUMMARY, newSummary); + monthlyProperties.put(Event.DESCRIPTION, newDescription); + + monthlyProperties.put(Event.REFERENCE_ID, ids); + addPersonalEvent(monthlyProperties); + } + } + + /** + * Add new Yearly calendar events processing. + * + * @param beginEventIntervalDate the value of beginEventIntervalDate + * @param endEventIntervalDate the value of endEventIntervalDate + * @param properties the value of properties + * @param isYearlySameDayOfWeek the value of isYearlySameDayOfWeek + * @param startDate the value of startDateTime + * @param endDate the value of endDateTime + * @param eventSummary the value of eventSummary + * @param eventDescription the value of eventDescription + */ + private void processYearEvents(final Date beginEventIntervalDate, Date endEventIntervalDate, final Date endEventIntervalDateRadio, final Map properties, Boolean isYearlySameDayOfWeek, final Date startDate, final Date endDate, String eventSummary, String eventDescription) { + + properties.put(Event.DATE_END, endEventIntervalDate); + long milisDiff = endEventIntervalDate.getTime() - beginEventIntervalDate.getTime(); + long milisPerDay = 86400000; //24 * 60 * 60 * 1000) + long daysInterval = ((endEventIntervalDate.getTime() - beginEventIntervalDate.getTime()) / milisPerDay) + 1; + + endEventIntervalDate = endEventIntervalDateRadio; + int yearStart = beginEventIntervalDate.getYear(); + int yearEnd = endEventIntervalDate.getYear(); + int yearInterval = yearEnd - yearStart + 1; + if (view.getYearlyRadioNumberOfRepetitions().getValue()) { + yearInterval--; + } + if (yearInterval <= 0) { + yearInterval = 1; + } + + if (view.getAllDayCheckbox().getValue()) { + properties.put(Event.EVENT_TYPE, "YF"); + } else { + //Window.alert("Y +daysInterval" + daysInterval); + properties.put(Event.EVENT_TYPE, ("Y" + (daysInterval > 1 ? "H" : ""))); + } + properties.put(Event.SUMMARY, (String) properties.get(Event.SUMMARY));// + " (Yearly event 1 of " + yearInterval + ")"); + properties.put(Event.DESCRIPTION, (String) properties.get(Event.DESCRIPTION));// + " (Yearly " + (isYearlySameDayOfWeek ? "same Day of a week " : "same Date ") + "event 1 of " + yearInterval + ")"); + + addPersonalEventYearly(milisDiff, properties, yearInterval, beginEventIntervalDate, endEventIntervalDate, startDate, endDate, eventSummary, eventDescription, isYearlySameDayOfWeek); + + } + + private void addPersonalEventYearly(final long milisDiff, final Map properties, final int yearInterval, final Date beginEventIntervalDate, final Date endEventIntervalDate, final Date startDate, final Date endDate, final String eventSummary, final String eventDescription, final boolean isYearlySameDayOfWeek) { + + final CreateEntity createEntity = new CreateEntity(PersonalEventDTO.ENTITY_NAME, properties); + + dispatch.execute(createEntity, new CommandResultHandler() { + + @Override + public void onCommandFailure(final Throwable caught) { + processAddEventError(caught); + } + + @Override + public void onCommandSuccess(final CreateResult result) { + + final Event event = new Event(); + event.setIdentifier((Integer) result.getEntity().getId()); + properties.put(Event.REFERENCE_ID, (Integer) result.getEntity().getId()); + updateEvent(event, properties); + long milisPerDay = 86400000; + long daysInterval = milisDiff / milisPerDay + 1; + + addYearlySeriesEvent(milisDiff, (String) result.getEntity().getId(), yearInterval, beginEventIntervalDate, endEventIntervalDate, startDate, endDate, eventSummary, eventDescription, isYearlySameDayOfWeek); + } + }, view.getCancelButton(), view.getSaveButton()); + } + + private void addYearlySeriesEvent(final long milisDiff, String ids, int yearInterval, Date beginEventIntervalDate, Date endEventIntervalDate, final Date startDate, final Date endDate, String eventSummary, String eventDescription, final boolean isYearlySameDayOfWeek) { + long milisPerDay = 86400000; //24 * 60 * 60 * 1000) + long daysInterval = ((endEventIntervalDate.getTime() - beginEventIntervalDate.getTime()) / milisPerDay) + 1; + + Date calBeginNextEventDate = beginEventIntervalDate; + for (int i = 1; i < yearInterval; i++) { + calBeginNextEventDate = getYearlySameDayOfWeek(beginEventIntervalDate, calBeginNextEventDate, i, isYearlySameDayOfWeek); + + Map yearlyProperties = new HashMap(); + yearlyProperties.put(Event.CALENDAR_ID, calendarWrapper); + yearlyProperties.put(Event.SUMMARY, view.getEventSummaryField().getValue()); + + yearlyProperties.put(Event.DATE, calBeginNextEventDate); + + if (view.getAllDayCheckbox().getValue()) { + yearlyProperties.put(Event.EVENT_TYPE, "YF"); + } else { + //Window.alert("Y2 +daysInterval" + daysInterval); + yearlyProperties.put(Event.EVENT_TYPE, ("Y" + (daysInterval > 1 ? "H" : ""))); + } + + yearlyProperties.put(Event.DATE_END, new Date(calBeginNextEventDate.getTime() + milisDiff)); + + setFullDayEvent(startDate, endDate, calBeginNextEventDate, yearlyProperties); + + String newSummary = eventSummary; + String newDescription = eventDescription; + // newSummary += " (Yearly event " + (i + 1) + " of " + yearInterval + ")"; + // newDescription += " (Yearly " + (isYearlySameDayOfWeek ? "same Day of a week " : "same Date ") + "event " + (i + 1) + " of " + yearInterval + ")"; + yearlyProperties.put(Event.SUMMARY, newSummary); + yearlyProperties.put(Event.DESCRIPTION, newDescription); + + yearlyProperties.put(Event.REFERENCE_ID, ids); + addPersonalEvent(yearlyProperties); + } + } + + /** + * Creates a new "Personal" calendar event. + * + * @param properties Properties of the new event. + */ + private void addPersonalEvent(final Map properties) { + + final CreateEntity createEntity = new CreateEntity(PersonalEventDTO.ENTITY_NAME, properties); + + dispatch.execute(createEntity, new CommandResultHandler() { + + @Override + public void onCommandFailure(final Throwable caught) { + processAddEventError(caught); + } + + @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 properties) { + + @SuppressWarnings("unchecked") + final UpdateEntity updateEntity = new UpdateEntity(PersonalEventDTO.ENTITY_NAME, event.getIdentifier(), (Map) properties); + + dispatch.execute(updateEntity, new CommandResultHandler() { + + @Override + public void onCommandFailure(final Throwable caught) { + processAddEventError(caught); + } + + @Override + public void onCommandSuccess(final VoidResult result) { + + final Calendar calendar = event.getParent(); + + final List oldEventList = calendar.getEvents().get(event.getKey()); + if (oldEventList != null && oldEventList.contains(event)) { + oldEventList.remove(event); + } + final List oldFullDayEventList = calendar.getFullDayEvents().get(event.getKey()); + if (oldFullDayEventList != null && oldFullDayEventList.contains(event)) { + oldFullDayEventList.remove(event); + } + final List oldHourMultidayEventList = calendar.getHourMultiDayEvents().get(event.getKey()); + if (oldHourMultidayEventList != null && oldHourMultidayEventList.contains(event)) { + oldHourMultidayEventList.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 properties) { + + // -- + // Updates the event. + // -- + event.setSummary((String) properties.get(Event.SUMMARY)); + event.setDescription((String) properties.get(Event.DESCRIPTION)); + event.setEventType((String) properties.get(Event.EVENT_TYPE)); + + event.setReferenceId((Integer) properties.get(Event.REFERENCE_ID)); + + final Date day = (Date) properties.get(Event.DATE); + final Date dayEnd = (Date) properties.get(Event.DATE_END); + 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 + ((dayEnd.getTime() - day.getTime()))); + //86400000 + event.setDtend(endHour); + } else { + event.setDtend(null); + } + + } else { + event.setDtstart(new Date(day.getYear(), day.getMonth(), day.getDate())); + event.setDtend(new Date(dayEnd.getYear(), dayEnd.getMonth(), dayEnd.getDate())); + } + + // Adding the new event to the calendar + final CalendarWrapper wrapper = (CalendarWrapper) properties.get(Event.CALENDAR_ID); + final Calendar calendar = wrapper.getCalendar(); + + event.setParent(calendar); + + if (calendar.getEvents() != null + && !event.getEventType().contains("F") + && !event.getEventType().contains("H")) { + List events = calendar.getEvents().get(day); + if (events == null) { + events = new ArrayList(); + calendar.getEvents().put(day, events); + } + events.add(event); + } + if (calendar.getHourMultiDayEvents() != null + && event.getEventType().contains("H")) { + List hourMultiDayEvents = calendar.getHourMultiDayEvents().get(day); + if (hourMultiDayEvents == null) { + hourMultiDayEvents = new ArrayList(); + calendar.getHourMultiDayEvents().put(day, hourMultiDayEvents); + } + hourMultiDayEvents.add(event); + } +// if (calendar.getFullDayEvents() != null && (event.getEventType().contains("F") +// && !event.getEventType().contains("H") +// || (event.getDtstart().getHours() == event.getDtend().getHours() +// && event.getDtstart().getMinutes() == event.getDtend().getMinutes()))) { + if (calendar.getFullDayEvents() != null + && event.getEventType().contains("F")) { + List fullDayEvents = calendar.getFullDayEvents().get(day); + if (fullDayEvents == null) { + fullDayEvents = new ArrayList(); + calendar.getFullDayEvents().put(day, fullDayEvents); + } + fullDayEvents.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()); + } + + /** + * + * @param firstDate + * @param nextDateOld + * @param numberMonths + * @return the java.util.Date + */ + @SuppressWarnings({"deprecation", "empty-statement"}) + public Date getMonthlySameDate(Date firstDate, Date nextDateOld, int numberMonths) { + Date nextDateNew = new Date(); + Date newDate = new Date(); + nextDateNew.setYear(nextDateOld.getYear()); + nextDateNew.setMonth(nextDateOld.getMonth() + 1); + nextDateNew.setDate(1);// to prevent month slip past (f.e. 31 jan -> 3 march instead of 29 febr) + newDate.setYear(nextDateOld.getYear()); + + int daysInNextDate = getDaysInMonth(nextDateNew.getYear(), nextDateNew.getMonth()); + + if (firstDate.getDate() <= daysInNextDate) {//if last day of the month + newDate.setMonth(0); + newDate.setDate(firstDate.getDate()); + newDate.setMonth(nextDateOld.getMonth() + 1); + + } else { + newDate.setDate(daysInNextDate); + newDate.setMonth(nextDateOld.getMonth() + 1); + + } + + return newDate; + } + + /** + * Calculates same date or same day of week in next month. + * + * @param firstDate + * @param nextDateOld + * @param numberMonths + * @param isSameDayOfWeek if the value is true then will be calculated Date + * of the nearest same day of week + * @return next month date + */ + public Date getMonthlySameDayOfWeek2(Date firstDate, Date nextDateOld, int numberMonths, boolean isSameDayOfWeek) { + + Date nextDateNew = new Date(); + Date newDate = new Date(); + nextDateNew.setDate(1);// to prevent month slip past (f.e. 31 jan -> 3 march instead of 29 febr) + newDate.setDate(1); + nextDateNew.setYear(nextDateOld.getYear()); + nextDateNew.setMonth(nextDateOld.getMonth() + 1); + newDate.setYear(nextDateOld.getYear()); + + int daysInNextDate = getDaysInMonth(nextDateNew.getYear(), nextDateNew.getMonth()); + + if (firstDate.getDate() <= daysInNextDate) {//if last day of the month + newDate.setMonth(0); + newDate.setDate(firstDate.getDate()); + newDate.setMonth(nextDateOld.getMonth() + 1); + + } else { + newDate.setDate(daysInNextDate); + newDate.setMonth(nextDateOld.getMonth() + 1); + + } + if (isSameDayOfWeek) { + Date newDate2 = getSameWeekDay(firstDate, newDate); //getSameWeekDay22 + + newDate = newDate2; + } + return newDate; + } + + /** + * Calculates same date or same day of week in next year. + * + * @param firstDate + * @param nextDateOld + * @param numberMonths + * @param isSameDayOfWeek if the value is true then will be calculated Date + * of the nearest same day of week + * @return + */ + @SuppressWarnings({"deprecation"}) + public Date getYearlySameDayOfWeek(Date firstDate, Date nextDateOld, int numberMonths, boolean isSameDayOfWeek) { + + Date nextDateNew = new Date(); + nextDateNew.setDate(1); + nextDateNew.setYear(nextDateOld.getYear()); + nextDateNew.setMonth(nextDateOld.getMonth()); + nextDateNew.setYear(nextDateOld.getYear() + 1); + + int daysInNextDate = getDaysInMonth(nextDateNew.getYear(), nextDateNew.getMonth()); + + if (firstDate.getDate() >= daysInNextDate) {//if last day of the month + + nextDateNew.setDate(daysInNextDate); + + } else { + + nextDateNew.setDate(firstDate.getDate()); + + } + + if (isSameDayOfWeek) { + + Date newDate = getSameWeekDay(firstDate, nextDateNew);//getSameWeekDay2 + + nextDateNew = newDate; + } + + return nextDateNew; + } + + /** + * Calculates same week day date(as in firstDate) for nextDate + * + * @param firstDate the value of firstDate + * @param nextDate the value of nextDate + */ + private Date getSameWeekDay(Date firstDate, Date nextDate) { + //Calculate same day of week + int dayOfFirst = firstDate.getDay(); + int dayOfCurrent = nextDate.getDay(); + Date newDate = new Date(); + Date curDate = nextDate; + int milSecInDay = 86400000; //24 * 60 * 60 * 1000 + if (dayOfFirst > dayOfCurrent) { + newDate = new Date(curDate.getTime() + (dayOfFirst - dayOfCurrent) * milSecInDay); + if (newDate.getMonth() != curDate.getMonth()) { //> + newDate = new Date(curDate.getTime() - (7 - (dayOfFirst - dayOfCurrent)) * milSecInDay); + } + + } else if (dayOfFirst < dayOfCurrent) {//< + newDate = new Date(curDate.getTime() - (dayOfCurrent - dayOfFirst) * milSecInDay); + if (newDate.getMonth() != curDate.getMonth()) { + newDate = new Date(curDate.getTime() + (7 - (dayOfCurrent - dayOfFirst)) * milSecInDay); + } + } else { + newDate = new Date(curDate.getTime()); + } + return newDate; + } + + /** + * Returns numver od days in the month of the year + * + * @param year the value of year + * @param month the value of month + * @return the int + */ + private int getDaysInMonth(int year, int month) { + int daysInMonth = 31; + + switch (month) { + case 3: + case 5: + case 8: + case 10: + return daysInMonth = 30; + case 1: + return daysInMonth = (isLeapYear(year)) ? 29 : 28; + default: + return daysInMonth; + } + } + + /** + * Validate if the year is leap year. + * + * @param year the value of year + * @return the boolean + */ + private boolean isLeapYear(int year) { + return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)); + } + + private static int calculateEventDurationInDays(final Date startDateTime, Date endDateTime) { + long diff = endDateTime.getTime() - startDateTime.getTime(); + long diffDays = diff / (24 * 60 * 60 * 1000) + 1; + int daysdiff = (int) diffDays; + return daysdiff; + } } diff --git a/src/main/java/org/sigmah/client/ui/presenter/calendar/CalendarPresenter.java b/src/main/java/org/sigmah/client/ui/presenter/calendar/CalendarPresenter.java index 93d828d98..19050eaff 100644 --- a/src/main/java/org/sigmah/client/ui/presenter/calendar/CalendarPresenter.java +++ b/src/main/java/org/sigmah/client/ui/presenter/calendar/CalendarPresenter.java @@ -21,8 +21,6 @@ * . * #L% */ - - import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -51,24 +49,20 @@ import org.sigmah.shared.dto.calendar.CalendarWrapper; import org.sigmah.shared.dto.calendar.Event; import org.sigmah.shared.dto.calendar.PersonalEventDTO; -import org.sigmah.shared.dto.referential.GlobalPermissionEnum; -import org.sigmah.shared.util.ProfileUtils; - import com.extjs.gxt.ui.client.event.ButtonEvent; import com.extjs.gxt.ui.client.event.SelectionChangedEvent; import com.extjs.gxt.ui.client.event.SelectionChangedListener; import com.extjs.gxt.ui.client.event.SelectionListener; import com.extjs.gxt.ui.client.store.ListStore; import com.extjs.gxt.ui.client.widget.selection.AbstractStoreSelectionModel; -import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.inject.ImplementedBy; import com.google.inject.Inject; +import java.util.Date; import org.sigmah.client.ui.presenter.reminder.ReminderType; import org.sigmah.client.util.profiler.Profiler; import org.sigmah.client.util.profiler.Scenario; import org.sigmah.shared.dto.calendar.CalendarIdentifier; import org.sigmah.shared.dto.calendar.PersonalCalendarIdentifier; -import org.sigmah.shared.util.ProjectUtils; /** * Calendar widget presenter. @@ -77,383 +71,483 @@ */ public class CalendarPresenter extends AbstractPresenter { - /** - * Description of the view managed by this presenter. - */ - @ImplementedBy(CalendarView.class) - public static interface View extends ViewInterface { + /** + * Description of the view managed by this presenter. + */ + @ImplementedBy(CalendarView.class) + public static interface View extends ViewInterface { - void initializeCalendarWidget(final CalendarWidget calendarWidget); + void initializeCalendarWidget(final CalendarWidget calendarWidget); - void setAddEventButtonEnabled(final boolean addEventButtonEnabled); + void setAddEventButtonEnabled(final boolean addEventButtonEnabled); - AbstractStoreSelectionModel getCalendarsSelectionModel(); + AbstractStoreSelectionModel getCalendarsSelectionModel(); - ListStore getCalendarsStore(); + ListStore getCalendarsStore(); - Button getAddEventButton(); + Button getAddEventButton(); - Button getTodayButton(); + Button getTodayButton(); - Button getWeekButton(); + Button getWeekButton(); - Button getMonthButton(); + Button getMonthButton(); - Button getPreviousButton(); + Button getPreviousButton(); - Button getNextButton(); + Button getNextButton(); Button getReminderAddButton(); - Button getMonitoredPointsAddButton(); + Button getMonitoredPointsAddButton(); - } + } - /** - * The calendar widget. - */ - private CalendarWidget calendar; + /** + * The calendar widget. + */ + private CalendarWidget calendar; private Integer projectId; + // @Inject + // private PersonalEventDAO personalEventDAO; + + /** + * Presenters's initialization. + * + * @param view Presenter's view interface. + * @param injector Injected client injector. + */ + @Inject + protected CalendarPresenter(final View view, final Injector injector) { + super(view, injector); + } + + /** + * {@inheritDoc} + */ + @Override + public void onBind() { + + // -- + // Initialize calendar widget. + // -- + calendar = new CalendarWidget(CalendarWidget.COLUMN_HEADERS, true, auth()); + calendar.today(); // Reset the current date. + calendar.setDisplayMode(CalendarWidget.DisplayMode.MONTH); + + view.initializeCalendarWidget(calendar); + + view.setAddEventButtonEnabled(false); + + // -- + // Configuring calendar delegate. + // -- + calendar.setDelegate(new CalendarWidget.Delegate() { + + @Override + public void edit(final Event event, final CalendarWidget calendarWidget) { + eventBus.navigateRequest(Page.CALENDAR_EVENT.request().addData(RequestParameter.DTO, event).addData(RequestParameter.CONTENT, getCalendars())); + } + + @Override + public void delete(final Event event, final CalendarWidget calendarWidget) { + final CalendarIdentifier calendarIdentifier = event.getParent().getIdentifier(); + final Integer parentId = calendarIdentifier instanceof PersonalCalendarIdentifier + ? ((PersonalCalendarIdentifier) calendarIdentifier).getId() : null; + dispatch.execute(new Delete(PersonalEventDTO.ENTITY_NAME, event.getIdentifier(), parentId), new CommandResultHandler() { + + @Override + public void onCommandFailure(final Throwable caught) { + N10N.error(I18N.CONSTANTS.error(), I18N.CONSTANTS.calendarDeleteEventError()); + } + + @Override + public void onCommandSuccess(final VoidResult result) { + + if (event.getEventType().contains("F")) { + final List oldFullDayEventList + = event.getParent().getFullDayEvents().get(event.getKey()); + oldFullDayEventList.remove(event); + } else if (event.getEventType().contains("H")) { + final List oldHourMultidayEventList + = event.getParent().getHourMultiDayEvents().get(event.getKey()); + oldHourMultidayEventList.remove(event); + } else { + final List oldEventList + = event.getParent().getEvents().get(event.getKey()); + oldEventList.remove(event); + } + calendar.refresh(); + } + }); + } + + public void deleteChildEvent(final Event next, Integer parentId, final Map> eventMap, final Date key) { + dispatch.execute(new Delete(PersonalEventDTO.ENTITY_NAME, next.getIdentifier(), parentId), new CommandResultHandler() { + + @Override + public void onCommandFailure(final Throwable caught) { + N10N.error(I18N.CONSTANTS.error(), I18N.CONSTANTS.calendarDeleteEventError()); + } + + @Override + public void onCommandSuccess(final VoidResult result) { + eventMap.get(key).remove(next); + calendar.refresh(); + } + }); + } + + public void deleteParentEvent(final Event next, Integer parentId, final Map> eventMap, final Date key, int mainId) { + dispatch.execute(new Delete(PersonalEventDTO.ENTITY_NAME, mainId, parentId), new CommandResultHandler() { + + @Override + public void onCommandFailure(final Throwable caught) { + N10N.error(I18N.CONSTANTS.error(), I18N.CONSTANTS.calendarDeleteEventError()); + } + + @Override + public void onCommandSuccess(final VoidResult result) { + eventMap.get(key).remove(next); + calendar.refresh(); + } + }); + } + + @Override + public void deleteChain(final Event event, final CalendarWidget calendarWidget) { + final CalendarIdentifier calendarIdentifier = event.getParent().getIdentifier(); + final Integer parentId = calendarIdentifier instanceof PersonalCalendarIdentifier + ? ((PersonalCalendarIdentifier) calendarIdentifier).getId() : null; + + final Map> eventMap = event.getParent().getEvents(); + final Map> fullDayEventMap = event.getParent().getFullDayEvents(); + final Map> hourMultiDayEventMap = event.getParent().getHourMultiDayEvents(); + + int eventId = event.getIdentifier(); + int eventRefId = 0; + if (event.getReferenceId() != null) { + eventRefId = event.getReferenceId().intValue(); + } + String typeStr = (String) event.getEventType(); + if (typeStr != null) { + deleteEventFromEventMap(eventMap, eventRefId, parentId, eventId); + deleteEventFromEventMap(fullDayEventMap, eventRefId, parentId, eventId); + deleteEventFromEventMap(hourMultiDayEventMap, eventRefId, parentId, eventId); + } else { + dispatch.execute(new Delete(PersonalEventDTO.ENTITY_NAME, eventId, parentId), new CommandResultHandler() { + + @Override + public void onCommandFailure(final Throwable caught) { + N10N.error(I18N.CONSTANTS.error(), I18N.CONSTANTS.calendarDeleteEventError()); + } + + @Override + public void onCommandSuccess(final VoidResult result) { + + if (event.getEventType().contains("F")) { + final List oldFullDayEventList + = event.getParent().getFullDayEvents().get(event.getKey()); + oldFullDayEventList.remove(event); + } else if (event.getEventType().contains("H")) { + final List oldHourMultidayEventList + = event.getParent().getHourMultiDayEvents().get(event.getKey()); + oldHourMultidayEventList.remove(event); + } else { + final List oldEventList + = event.getParent().getEvents().get(event.getKey()); + oldEventList.remove(event); + } + calendar.refresh(); + } + }); + } + } + + private void deleteEventFromEventMap(final Map> theEventMap, int eventRefId, final Integer parentId, int eventId) { + for (final Date key : theEventMap.keySet()) { + for (final Event nextEvent : theEventMap.get(key)) { + if (eventRefId != 0) { +// if (nextEvent.getReferenceId().intValue() == eventRefId) { +// deleteChildEvent(nextEvent, parentId, theEventMap, key); +// } + if ((nextEvent.getReferenceId() != null && (nextEvent.getReferenceId().intValue() == eventRefId)) + || ((nextEvent.getReferenceId() == null) && (nextEvent.getIdentifier().intValue() == eventRefId))) { + deleteChildEvent(nextEvent, parentId, theEventMap, key); + } + } else { + if (nextEvent.getReferenceId() != null && (nextEvent.getReferenceId().intValue() == eventId)) { + deleteChildEvent(nextEvent, parentId, theEventMap, key); + } else if (nextEvent.getReferenceId() == null && nextEvent.getIdentifier().intValue() == eventId) { + deleteParentEvent(nextEvent, parentId, theEventMap, key, eventId); + } + } + } + } + } + }); + + // -- + // Calendars selection change event. + // -- + view.getCalendarsSelectionModel().addSelectionChangedListener(new SelectionChangedListener() { + + @Override + public void selectionChanged(SelectionChangedEvent se) { + final List wrappers = se.getSelection(); + final ArrayList calendars = new ArrayList(); + for (final CalendarWrapper wrapper : wrappers) { + calendars.add(wrapper.getCalendar()); + } + calendar.setCalendars(calendars); + } + }); + + // -- + // Add event button. + // -- + view.getAddEventButton().addSelectionListener(new SelectionListener() { + + @Override + public void componentSelected(final ButtonEvent ce) { + + if (view.getCalendarsStore().getCount() == 0) { + N10N.warn(I18N.CONSTANTS.calendar_addEvent_noCalendar_ko()); + return; + } - /** - * Presenters's initialization. - * - * @param view - * Presenter's view interface. - * @param injector - * Injected client injector. - */ - @Inject - protected CalendarPresenter(final View view, final Injector injector) { - super(view, injector); - } - - /** - * {@inheritDoc} - */ - @Override - public void onBind() { - - // -- - // Initialize calendar widget. - // -- - - calendar = new CalendarWidget(CalendarWidget.COLUMN_HEADERS, true, auth()); - calendar.today(); // Reset the current date. - calendar.setDisplayMode(CalendarWidget.DisplayMode.MONTH); - - view.initializeCalendarWidget(calendar); - - view.setAddEventButtonEnabled(false); - - // -- - // Configuring calendar delegate. - // -- - - calendar.setDelegate(new CalendarWidget.Delegate() { - - @Override - public void edit(final Event event, final CalendarWidget calendarWidget) { - eventBus.navigateRequest(Page.CALENDAR_EVENT.request().addData(RequestParameter.DTO, event).addData(RequestParameter.CONTENT, getCalendars())); - } - - @Override - public void delete(final Event event, final CalendarWidget calendarWidget) { - final CalendarIdentifier calendarIdentifier = event.getParent().getIdentifier(); - final Integer parentId = calendarIdentifier instanceof PersonalCalendarIdentifier ? - ((PersonalCalendarIdentifier)calendarIdentifier).getId() : null; - - dispatch.execute(new Delete(PersonalEventDTO.ENTITY_NAME, event.getIdentifier(), parentId), new CommandResultHandler() { - - @Override - public void onCommandFailure(final Throwable caught) { - N10N.error(I18N.CONSTANTS.error(), I18N.CONSTANTS.calendarDeleteEventError()); - } - - @Override - public void onCommandSuccess(final VoidResult result) { - - final List oldEventList = - event.getParent().getEvents().get(event.getKey()); - oldEventList.remove(event); - calendar.refresh(); - } - }); - } - }); - - // -- - // Calendars selection change event. - // -- - - view.getCalendarsSelectionModel().addSelectionChangedListener(new SelectionChangedListener() { - - @Override - public void selectionChanged(SelectionChangedEvent se) { - final List wrappers = se.getSelection(); - final ArrayList calendars = new ArrayList(); - for (final CalendarWrapper wrapper : wrappers) { - calendars.add(wrapper.getCalendar()); - } - calendar.setCalendars(calendars); - } - }); - - // -- - // Add event button. - // -- - - view.getAddEventButton().addSelectionListener(new SelectionListener() { - - @Override - public void componentSelected(final ButtonEvent ce) { - - if (view.getCalendarsStore().getCount() == 0) { - N10N.warn(I18N.CONSTANTS.calendar_addEvent_noCalendar_ko()); - return; - } - - eventBus.navigateRequest(Page.CALENDAR_EVENT.request().addData(RequestParameter.CONTENT, getCalendars())); - } - }); - - // -- - // Today button. - // -- - - view.getTodayButton().addSelectionListener(new SelectionListener() { - - @Override - public void componentSelected(final ButtonEvent ce) { - calendar.today(); - } - }); - - // -- - // Week button. - // -- - - view.getWeekButton().addSelectionListener(new SelectionListener() { - - @Override - public void componentSelected(final ButtonEvent ce) { - calendar.setDisplayMode(CalendarWidget.DisplayMode.WEEK); - } - }); - - // -- - // Month button. - // -- - - view.getMonthButton().addSelectionListener(new SelectionListener() { - - @Override - public void componentSelected(final ButtonEvent ce) { - calendar.setDisplayMode(CalendarWidget.DisplayMode.MONTH); - } - }); - - // -- - // Previous button. - // -- - - view.getPreviousButton().addSelectionListener(new SelectionListener() { - - @Override - public void componentSelected(final ButtonEvent ce) { - calendar.previous(); - } - }); - - // -- - // Next button. - // -- - - view.getNextButton().addSelectionListener(new SelectionListener() { - - @Override - public void componentSelected(final ButtonEvent ce) { - calendar.next(); - } - }); - - // -- - // Reminders / Monitored Points add buttons handlers. - // -- - - view.getReminderAddButton().addSelectionListener(new SelectionListener() { - - @Override - public void componentSelected(final ButtonEvent event) { - eventBus.navigateRequest(Page.REMINDER_EDIT.requestWith(RequestParameter.TYPE, ReminderType.REMINDER).addParameter(RequestParameter.ID, - projectId)); - } - }); - - view.getMonitoredPointsAddButton().addSelectionListener(new SelectionListener() { - - @Override - public void componentSelected(final ButtonEvent event) { - eventBus.navigateRequest(Page.REMINDER_EDIT.requestWith(RequestParameter.TYPE, ReminderType.MONITORED_POINT).addParameter(RequestParameter.ID, - projectId)); - } - }); + eventBus.navigateRequest(Page.CALENDAR_EVENT.request().addData(RequestParameter.CONTENT, getCalendars())); + } + }); + + // -- + // Today button. + // -- + view.getTodayButton().addSelectionListener(new SelectionListener() { + + @Override + public void componentSelected(final ButtonEvent ce) { + calendar.today(); + } + }); + + // -- + // Week button. + // -- + view.getWeekButton().addSelectionListener(new SelectionListener() { + + @Override + public void componentSelected(final ButtonEvent ce) { + calendar.setDisplayMode(CalendarWidget.DisplayMode.WEEK); + } + }); + + // -- + // Month button. + // -- + view.getMonthButton().addSelectionListener(new SelectionListener() { + + @Override + public void componentSelected(final ButtonEvent ce) { + calendar.setDisplayMode(CalendarWidget.DisplayMode.MONTH); + } + }); + + // -- + // Previous button. + // -- + view.getPreviousButton().addSelectionListener(new SelectionListener() { + + @Override + public void componentSelected(final ButtonEvent ce) { + calendar.previous(); + } + }); + + // -- + // Next button. + // -- + view.getNextButton().addSelectionListener(new SelectionListener() { - // -- - // Update event handler. - // -- + @Override + public void componentSelected(final ButtonEvent ce) { + calendar.next(); + } + }); + + // -- + // Reminders / Monitored Points add buttons handlers. + // -- + view.getReminderAddButton().addSelectionListener(new SelectionListener() { + + @Override + public void componentSelected(final ButtonEvent event) { + eventBus.navigateRequest(Page.REMINDER_EDIT.requestWith(RequestParameter.TYPE, ReminderType.REMINDER).addParameter(RequestParameter.ID, + projectId)); + } + }); - registerHandler(eventBus.addHandler(UpdateEvent.getType(), new UpdateHandler() { + view.getMonitoredPointsAddButton().addSelectionListener(new SelectionListener() { + + @Override + public void componentSelected(final ButtonEvent event) { + eventBus.navigateRequest(Page.REMINDER_EDIT.requestWith(RequestParameter.TYPE, ReminderType.MONITORED_POINT).addParameter(RequestParameter.ID, + projectId)); + } + }); + + // -- + // Update event handler. + // -- + registerHandler(eventBus.addHandler(UpdateEvent.getType(), new UpdateHandler() { + + @Override + public void onUpdate(final UpdateEvent event) { + if (event.concern(UpdateEvent.CALENDAR_EVENT_UPDATE)) { + calendar.refresh(); + } - @Override - public void onUpdate(final UpdateEvent event) { - if (event.concern(UpdateEvent.CALENDAR_EVENT_UPDATE)) { - calendar.refresh(); - } - if (event.concern(UpdateEvent.REMINDER_UPDATED)) { // TODO appel reloadEventsOfReminderType((ReminderType) event.getParam(0)); calendar.refresh(); } - } - })); - } - - /** - * Reloads the calendars data (if necessary). - * - * @param calendars - * The calendar types with their corresponding identifier. - */ - public void reload(final Map calendars, boolean editable) { - Profiler.INSTANCE.markCheckpoint(Scenario.AGENDA, "Before refresh."); - - calendar.refresh(); - Profiler.INSTANCE.markCheckpoint(Scenario.AGENDA, "calendar.refresh ended."); + } + })); + } + + /** + * Reloads the calendars data (if necessary). + * + * @param calendars The calendar types with their corresponding identifier. + */ + public void reload(final Map calendars, boolean editable) { + Profiler.INSTANCE.markCheckpoint(Scenario.AGENDA, "Before refresh."); + calendar.refresh(); + + Profiler.INSTANCE.markCheckpoint(Scenario.AGENDA, "calendar.refresh ended."); this.projectId = calendars.get(CalendarType.Activity); - view.setAddEventButtonEnabled(editable); - Profiler.INSTANCE.markCheckpoint(Scenario.AGENDA, "Before refresh."); - reloadEvents(calendars); - } - - /** - * {@inheritDoc}
- * Updates the calendar view. - */ - @Override - public void onViewRevealed() { - calendar.refresh(); - } - - /** - * Returns the {@link CalendarWrapper} list from the view store. - * - * @return The collection. - */ - private List getCalendars() { - - final List calendars = new ArrayList(); - final ListStore store = view.getCalendarsStore(); - - for (int i = 0; i < store.getCount(); i++) { - calendars.add(store.getAt(i)); - } - - return calendars; - } - - /** - * Reloads the calendar events using a {@link GetCalendar} command. - * - * @param calendars - * The calendar types with their corresponding identifier. - */ - private void reloadEvents(final Map calendars) { - - view.getCalendarsStore().removeAll(); - - if (ClientUtils.isEmpty(calendars)) { - calendar.refresh(); - Profiler.INSTANCE.endScenario(Scenario.AGENDA); - return; - } - - final DispatchQueue queue = new DispatchQueue(dispatch, true) { - - @Override - protected void onComplete() { - calendar.refresh(); - Profiler.INSTANCE.endScenario(Scenario.AGENDA); - } - }; - - for (final Entry calendarEntry : calendars.entrySet()) { - - if (calendarEntry == null) { - continue; - } - - final CalendarType calendarType = calendarEntry.getKey(); - final Integer calendarId = calendarEntry.getValue(); - - queue.add(new GetCalendar(calendarType, CalendarType.getIdentifier(calendarType, calendarId)), new CommandResultHandler() { - - @Override - public void onCommandSuccess(final Calendar result) { - Profiler.INSTANCE.markCheckpoint(Scenario.AGENDA, calendarType + " ended."); - if(result != null) { - // Defines the color index of the calendar. - result.setStyle(calendarType.getColorCode()); + view.setAddEventButtonEnabled(editable); + Profiler.INSTANCE.markCheckpoint(Scenario.AGENDA, "Before refresh."); + reloadEvents(calendars); + } + + /** + * {@inheritDoc}
+ * Updates the calendar view. + */ + @Override + public void onViewRevealed() { + calendar.refresh(); + } + + /** + * Returns the {@link CalendarWrapper} list from the view store. + * + * @return The collection. + */ + private List getCalendars() { + + final List calendars = new ArrayList(); + final ListStore store = view.getCalendarsStore(); + + for (int i = 0; i < store.getCount(); i++) { + calendars.add(store.getAt(i)); + } + + return calendars; + } + + /** + * Reloads the calendar events using a {@link GetCalendar} command. + * + * @param calendars The calendar types with their corresponding identifier. + */ + private void reloadEvents(final Map calendars) { + + view.getCalendarsStore().removeAll(); + + if (ClientUtils.isEmpty(calendars)) { + calendar.refresh(); + Profiler.INSTANCE.endScenario(Scenario.AGENDA); + return; + } + + final DispatchQueue queue = new DispatchQueue(dispatch, true) { + + @Override + protected void onComplete() { + calendar.refresh(); + Profiler.INSTANCE.endScenario(Scenario.AGENDA); + } + }; + + for (final Entry calendarEntry : calendars.entrySet()) { + + if (calendarEntry == null) { + continue; + } + + final CalendarType calendarType = calendarEntry.getKey(); + final Integer calendarId = calendarEntry.getValue(); + + queue.add(new GetCalendar(calendarType, CalendarType.getIdentifier(calendarType, calendarId)), new CommandResultHandler() { + + @Override + public void onCommandSuccess(final Calendar result) { + Profiler.INSTANCE.markCheckpoint(Scenario.AGENDA, calendarType + " ended."); + if (result != null) { + // Defines the color index of the calendar. + result.setStyle(calendarType.getColorCode()); result.setType(calendarType); - view.getCalendarsStore().add(new CalendarWrapper(result)); - view.getCalendarsSelectionModel().select(view.getCalendarsStore().getCount() - 1, true); - } - } - - @Override - protected void onCommandFailure(Throwable caught) { - Profiler.INSTANCE.markCheckpoint(Scenario.AGENDA, calendarType + " ended with error."); - super.onCommandFailure(caught); - } - - }); - } - Profiler.INSTANCE.markCheckpoint(Scenario.AGENDA, "Before queue started."); - queue.start(); - } + view.getCalendarsStore().add(new CalendarWrapper(result)); + view.getCalendarsSelectionModel().select(view.getCalendarsStore().getCount() - 1, true); + } + } + + @Override + protected void onCommandFailure(Throwable caught) { + Profiler.INSTANCE.markCheckpoint(Scenario.AGENDA, calendarType + " ended with error."); + super.onCommandFailure(caught); + } + + }); + } + Profiler.INSTANCE.markCheckpoint(Scenario.AGENDA, "Before queue started."); + queue.start(); + } + /** * Reload a given type of reminder into the calendar. - * + * * @param reminderType Type of reminder to refresh. */ private void reloadEventsOfReminderType(final ReminderType reminderType) { final CalendarType calendarType = reminderType == ReminderType.REMINDER ? CalendarType.Reminder : CalendarType.MonitoredPoint; - + final List calendars = calendar.getCalendars(); for (int index = 0; index < calendars.size(); index++) { final Calendar currentCalendar = calendars.get(index); - + if (currentCalendar.getType() == calendarType) { final GetCalendar getCalendar = new GetCalendar(calendarType, currentCalendar.getIdentifier()); final int location = index; - + dispatch.execute(getCalendar, new CommandResultHandler() { - + @Override protected void onCommandSuccess(Calendar result) { - if(result != null) { + if (result != null) { result.setStyle(calendarType.getColorCode()); result.setType(calendarType); calendars.set(location, result); calendar.refresh(); } } - }); return; } diff --git a/src/main/java/org/sigmah/client/ui/view/calendar/CalendarEventView.java b/src/main/java/org/sigmah/client/ui/view/calendar/CalendarEventView.java index 85cf61775..dc7d1ca5c 100644 --- a/src/main/java/org/sigmah/client/ui/view/calendar/CalendarEventView.java +++ b/src/main/java/org/sigmah/client/ui/view/calendar/CalendarEventView.java @@ -21,7 +21,10 @@ * . * #L% */ - +import com.extjs.gxt.ui.client.Style; +import com.extjs.gxt.ui.client.event.Events; +import com.extjs.gxt.ui.client.event.FieldEvent; +import com.extjs.gxt.ui.client.event.Listener; import org.sigmah.client.i18n.I18N; import org.sigmah.client.ui.presenter.calendar.CalendarEventPresenter; import org.sigmah.client.ui.res.icon.IconImageBundle; @@ -32,140 +35,876 @@ import org.sigmah.client.ui.widget.popup.PopupWidget; import org.sigmah.shared.dto.calendar.Event; -import com.extjs.gxt.ui.client.widget.form.ComboBox.TriggerAction; import com.extjs.gxt.ui.client.widget.form.DateField; +import com.extjs.gxt.ui.client.widget.form.Radio; +import com.extjs.gxt.ui.client.widget.form.RadioGroup; 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.TimeField; +import com.extjs.gxt.ui.client.widget.form.CheckBox; +import com.extjs.gxt.ui.client.widget.form.FieldSet; import com.google.inject.Singleton; +import com.extjs.gxt.ui.client.widget.HorizontalPanel; +import com.extjs.gxt.ui.client.widget.VerticalPanel; +import com.extjs.gxt.ui.client.widget.form.ComboBox.TriggerAction; +import com.google.gwt.user.client.ui.HTML; +import java.util.Date; +/* +import com.gwtext.client.data.Record; +import com.gwtext.client.data.SimpleStore; +import com.gwtext.client.data.Store; +import com.gwtext.client.widgets.Panel; +import com.gwtext.client.widgets.form.ComboBox; +import com.gwtext.client.widgets.form.FormPanel; +import com.gwtext.client.widgets.form.event.ComboBoxListenerAdapter; + */ /** * Calendar event edit frame view used to create/edit a calendar event. - * + * * @author Denis Colliot (dcolliot@ideia.fr) */ @Singleton public class CalendarEventView extends AbstractPopupView implements CalendarEventPresenter.View { - private FormPanel form; - private TextField eventSummaryField; - private DateField eventDateField; - private TimeField eventStartTimeField; - private TimeField eventEndTimeField; - private TextArea eventDescriptionField; - - private Button saveButton; - private Button cancelButton; - - /** - * Builds the view. - */ - public CalendarEventView() { - super(new PopupWidget(true), 500); - } - - /** - * {@inheritDoc} - */ - @Override - public void initialize() { - - form = Forms.panel(); - - eventSummaryField = Forms.text(I18N.CONSTANTS.calendarEventObject(), true); - eventSummaryField.setName(Event.SUMMARY); - - eventDateField = Forms.date(I18N.CONSTANTS.calendarEventDate(), true); - eventDateField.setName(Event.DATE); - - eventStartTimeField = Forms.time(I18N.CONSTANTS.calendarEventStartHour(), false); - eventStartTimeField.setName(Event.START_TIME); - eventStartTimeField.setTriggerAction(TriggerAction.ALL); - - eventEndTimeField = Forms.time(I18N.CONSTANTS.calendarEventEndHour(), false); - eventEndTimeField.setName(Event.END_TIME); - eventEndTimeField.setTriggerAction(TriggerAction.ALL); - - eventDescriptionField = Forms.textarea(I18N.CONSTANTS.calendarEventDescription(), false); - eventDescriptionField.setName(Event.DESCRIPTION); - - saveButton = Forms.button(I18N.CONSTANTS.formWindowSubmitAction(), IconImageBundle.ICONS.save()); - cancelButton = Forms.button(I18N.CONSTANTS.cancel()); - - form.add(eventSummaryField); - form.add(eventDateField); - form.add(eventStartTimeField); - form.add(eventEndTimeField); - form.add(eventDescriptionField); - - form.addButton(cancelButton); - form.addButton(saveButton); - - initPopup(form); - } - - /** - * {@inheritDoc} - */ - @Override - public FormPanel getForm() { - return form; - } - - /** - * {@inheritDoc} - */ - @Override - public TextField getEventSummaryField() { - return eventSummaryField; - } - - /** - * {@inheritDoc} - */ - @Override - public DateField getEventDateField() { - return eventDateField; - } - - /** - * {@inheritDoc} - */ - @Override - public TimeField getEventStartTimeField() { - return eventStartTimeField; - } - - /** - * {@inheritDoc} - */ - @Override - public TimeField getEventEndTimeField() { - return eventEndTimeField; - } - - /** - * {@inheritDoc} - */ - @Override - public TextArea getEventDescriptionField() { - return eventDescriptionField; - } - - /** - * {@inheritDoc} - */ - @Override - public Button getSaveButton() { - return saveButton; - } - - /** - * {@inheritDoc} - */ - @Override - public Button getCancelButton() { - return cancelButton; - } + private FormPanel form; + private TextField eventSummaryField; + private DateField eventDateStartField; + private DateField eventDateEndField; + private TimeField eventStartTimeField; + private TimeField eventEndTimeField; + private TextArea eventDescriptionField; + + private Button saveButton; + private Button cancelButton; + + private CheckBox allDayCheckbox; + private RadioGroup yearlyVariantRG; + private RadioGroup montlyVariantRG; + private FieldSet panelYearly; + private FieldSet panelMonthly; + private FieldSet panelWeekly; + private FieldSet panelDaily; + private FieldSet monthlyRepSettings; + private FieldSet yearlyRepSettings; + + private Radio yearlySameDayOfWeekRB; + private Radio yearlySameDateRB; + + private Radio onceRepeatRB; + private Radio dailyRepeatRB; + private Radio weeklyRepeatRB; + private Radio monthlyRepeatRB; + private Radio yearlyRepeatRB; + private Radio radioMonthlySameDate; + private Radio radioMonthlySameDayOfWeek; + private Radio radioNumberOfRepetitions; + private Radio radioRepetitionEndDate; + + private Radio radioWeeklyNumberOfRepetitions; + private Radio radioWeeklyRepetitionEndDate; + private Radio radioYearlyNumberOfRepetitions; + private Radio radioYearlyRepetitionEndDate; + private Radio radioDailyNumberOfRepetitions; + private Radio radioDailyRepetitionEndDate; + + private DateField repetitionEndDate; + private TextArea numberOfRepetitions; + private DateField dailyRepetitionEndDate; + private TextArea dailyNumberOfRepetitions; + private DateField weeklyRepetitionEndDate; + private TextArea weeklyNumberOfRepetitions; + private DateField yearlyRepetitionEndDate; + private TextArea yearlyNumberOfRepetitions; + // private CheckBoxGroup allDayCheckboxGr; + + private RadioGroup RepeatEventPeriodRG; + private RadioGroup RepeatMultiEventPeriodRG; + private RadioGroup RepeatYearlyMultiEventPeriodRG; + private RadioGroup RepeatWeeklyMultiEventPeriodRG; + private RadioGroup RepeatDailyMultiEventPeriodRG; + + /** + * Builds the view. + */ + public CalendarEventView() { + super(new PopupWidget(true), 500); + } + + /** + * {@inheritDoc} + */ + @Override + public void initialize() { + form = Forms.panel(); + + createYearlyPanel(); + createMonthlyPanel(); + createWeeklyPanel(); + createDailyPanel(); + createRepeatEventPeriodRadioGroup(); + + eventSummaryField = Forms.text(I18N.CONSTANTS.calendarEventObject(), true); + eventSummaryField.setName(Event.SUMMARY); + + eventDateStartField = Forms.date(I18N.CONSTANTS.calendar_addEvent_dateStart_label(), true); + eventDateStartField.setName(Event.DATE); + + eventStartTimeField = Forms.time(I18N.CONSTANTS.calendarEventStartHour(), false); + eventStartTimeField.setName(Event.START_TIME); + eventStartTimeField.setTriggerAction(TriggerAction.ALL); + + eventEndTimeField = Forms.time(I18N.CONSTANTS.calendarEventEndHour(), false); + eventEndTimeField.setName(Event.END_TIME); + eventEndTimeField.setTriggerAction(TriggerAction.ALL); + + eventDateEndField = Forms.date(I18N.CONSTANTS.calendar_addEvent_dateEnd_label(), false); + eventDateEndField.setName(Event.DATE + "888end"); + + eventDescriptionField = Forms.textarea(I18N.CONSTANTS.calendarEventDescription(), false); + eventDescriptionField.setName(Event.DESCRIPTION); + eventDescriptionField.setId(Event.DESCRIPTION); + eventDescriptionField.setMaxLength(255); + + saveButton = Forms.button(I18N.CONSTANTS.formWindowSubmitAction(), IconImageBundle.ICONS.save()); + cancelButton = Forms.button(I18N.CONSTANTS.cancel()); + + form.add(eventSummaryField); + form.add(eventDateStartField); + form.add(eventDateEndField); + form.add(createAllDayCheckbox()); + + form.add(eventStartTimeField); + form.add(eventEndTimeField); + form.add(RepeatEventPeriodRG); + form.add(panelYearly); + form.add(panelMonthly); + form.add(panelWeekly); + form.add(panelDaily); + form.add(eventDescriptionField); + + form.addButton(cancelButton); + form.addButton(saveButton); + + initPopup(form); + } + + private CheckBox createAllDayCheckbox() { + + allDayCheckbox = Forms.checkbox(I18N.CONSTANTS.calendar_addEvent_isAllDayCB_boxLabel(), I18N.CONSTANTS.calendar_addEvent_isAllDayCB_allDayName(), false); + allDayCheckbox.setFieldLabel(I18N.CONSTANTS.calendar_addEvent_allDayCbGr_label()); + allDayCheckbox.validate(false); + allDayCheckbox.addListener(Events.OnChange, new Listener() { + @Override + public void handleEvent(FieldEvent event) { + eventStartTimeField.setVisible(!allDayCheckbox.getValue()); + eventEndTimeField.setVisible(!allDayCheckbox.getValue()); + } + }); + + return allDayCheckbox; + } + + private void createRepeatEventPeriodRadioGroup() { + createOnceRb(); + createDailyRb(); + createWeeklyRb(); + createMonthlyRb(); + createYearlyRb(); + + RepeatEventPeriodRG = Forms.radioGroup(I18N.CONSTANTS.calendar_addEvent_repeatPeriodRG_label(), + I18N.CONSTANTS.calendar_addEvent_repeatPeriodRG_name(), + Style.Orientation.HORIZONTAL, + onceRepeatRB, + dailyRepeatRB, + weeklyRepeatRB, + monthlyRepeatRB, + yearlyRepeatRB); + RepeatEventPeriodRG.setSelectionRequired(Boolean.TRUE); + RepeatEventPeriodRG.enable(); + } + + private void createYearlyRb() { + yearlyRepeatRB = Forms.radio(I18N.CONSTANTS.calendar_addEvent_repeatYearlyRB_label(), I18N.CONSTANTS.calendar_addEvent_repeatYearlyRB_label(), Boolean.FALSE); + yearlyRepeatRB.setToolTip(I18N.CONSTANTS.calendar_addEvent_repeatYearlyRB_toolTip()); + yearlyRepeatRB.addListener(Events.OnChange, new Listener() { + @Override + public void handleEvent(FieldEvent event) { + //add default description + //((TextArea) form.getItemByItemId(Event.DESCRIPTION)).setValue(I18N.CONSTANTS.calendar_addEvent_description_textArea_yearly()); + getPanelYearly().setVisible(getYearlyRepeatRB().getValue()); + getPanelWeekly().setVisible(!yearlyRepeatRB.getValue()); + getPanelMonthly().setVisible(!yearlyRepeatRB.getValue()); + getPanelDaily().setVisible(!yearlyRepeatRB.getValue()); + + getYearlySameDateRB().show(); + getYearlySameDayOfWeekRB().show(); + getYearlySameDateRB().setValue(true); + eventDateStartField.setAllowBlank(false); + } + }); + } + + private void createMonthlyRb() { + monthlyRepeatRB = Forms.radio(I18N.CONSTANTS.calendar_addEvent_repeatMonthlyRB_label(), I18N.CONSTANTS.calendar_addEvent_repeatMonthlyRB_label(), Boolean.FALSE); + monthlyRepeatRB.setToolTip(I18N.CONSTANTS.calendar_addEvent_repeatMonthlyRB_toolTip()); + monthlyRepeatRB.addListener(Events.OnChange, new Listener() { + @Override + public void handleEvent(FieldEvent event) { + //add default description + //((TextArea) form.getItemByItemId(Event.DESCRIPTION)).setValue(I18N.CONSTANTS.calendar_addEvent_description_textArea_monthly()); + getPanelWeekly().setVisible(!monthlyRepeatRB.getValue()); + getPanelYearly().setVisible(!monthlyRepeatRB.getValue()); + getPanelDaily().setVisible(!monthlyRepeatRB.getValue()); + getPanelMonthly().setVisible(getMonthlyRepeatRB().getValue()); + eventDateStartField.setAllowBlank(false); + getRadioMonthlySameDate().show(); + getRadioMonthlySameDayOfWeek().show(); + getRadioMonthlySameDayOfWeek().setValue(true); + } + }); + } + + private void createWeeklyRb() { + weeklyRepeatRB = Forms.radio(I18N.CONSTANTS.calendar_addEvent_repeatWeeklyRB_label(), I18N.CONSTANTS.calendar_addEvent_repeatWeeklyRB_label(), Boolean.FALSE); + weeklyRepeatRB.setToolTip(I18N.CONSTANTS.calendar_addEvent_repeatWeeklyRB_toolTip()); + weeklyRepeatRB.addListener(Events.OnChange, new Listener() { + @Override + public void handleEvent(FieldEvent event) { + //add default description + //((TextArea) form.getItemByItemId(Event.DESCRIPTION)).setValue(I18N.CONSTANTS.calendar_addEvent_description_textArea_weekly()); + getPanelYearly().setVisible(!weeklyRepeatRB.getValue()); + getPanelMonthly().setVisible(!weeklyRepeatRB.getValue()); + getPanelDaily().setVisible(!weeklyRepeatRB.getValue()); + getPanelWeekly().setVisible(getWeeklyRepeatRB().getValue()); + // Window.alert("Test"); + eventDateStartField.setAllowBlank(false); + } + }); + } + + /** + * + */ + private void createDailyRb() { + dailyRepeatRB = Forms.radio(I18N.CONSTANTS.calendar_addEvent_repeatDailyRB_label(), I18N.CONSTANTS.calendar_addEvent_repeatDailyRB_label(), Boolean.FALSE); + dailyRepeatRB.addListener(Events.OnChange, new Listener() { + @Override + public void handleEvent(FieldEvent event) { + //add default description + //((TextArea) form.getItemByItemId(Event.DESCRIPTION)).setValue(I18N.CONSTANTS.calendar_addEvent_description_textArea_daily()); + getPanelYearly().setVisible(!dailyRepeatRB.getValue()); + getPanelMonthly().setVisible(!dailyRepeatRB.getValue()); + getPanelWeekly().setVisible(!dailyRepeatRB.getValue()); + getPanelDaily().setVisible(getDailyRepeatRB().getValue()); + } + }); + } + + private void createOnceRb() { + onceRepeatRB = Forms.radio(I18N.CONSTANTS.calendar_addEvent_repeatOnceRB_label(), I18N.CONSTANTS.calendar_addEvent_repeatOnceRB_name(), Boolean.FALSE); + onceRepeatRB.setOriginalValue(Boolean.TRUE); + onceRepeatRB.setToolTip(I18N.CONSTANTS.calendar_addEvent_repeatOnceRB_toolTip()); + + onceRepeatRB.addListener(Events.OnChange, new Listener() { + @Override + public void handleEvent(FieldEvent event) { + + getPanelYearly().setVisible(!onceRepeatRB.getValue()); + getPanelMonthly().setVisible(!onceRepeatRB.getValue()); + getPanelWeekly().setVisible(!onceRepeatRB.getValue()); + getPanelDaily().setVisible(!onceRepeatRB.getValue()); + //add default description + //((TextArea) form.getItemByItemId(Event.DESCRIPTION)).setValue(I18N.CONSTANTS.calendar_addEvent_description_textArea_once()); + } + }); + } + + private void createDailyPanel() { + panelDaily = new FieldSet(); + panelDaily.setExpanded(true); + panelDaily.setBorders(true); + panelDaily.setHeadingHtml("Daily repetition details"); + panelDaily.setAutoHeight(true); + panelDaily.setVisible(false); + + radioDailyNumberOfRepetitions = Forms.radio("Number of repetitions"); + radioDailyNumberOfRepetitions.setName("Number of repetitonsYearly"); + radioDailyNumberOfRepetitions.setValue(Boolean.FALSE); + radioDailyNumberOfRepetitions.setOriginalValue(Boolean.FALSE); + radioDailyNumberOfRepetitions.setToolTip("Set a number of repetitons (Yearly)"); + + dailyNumberOfRepetitions = Forms.textarea("", false); + dailyNumberOfRepetitions.setName("numberOfRepetitionsyearly"); + dailyNumberOfRepetitions.setId("numberOfRepetitionsyearly"); + dailyNumberOfRepetitions.setMaxLength(255); + dailyNumberOfRepetitions.setHeight(19); + + radioDailyRepetitionEndDate = Forms.radio("Repetition end date"); + radioDailyRepetitionEndDate.setBoxLabel("Repetition end date"); + radioDailyRepetitionEndDate.setName("Repetition end dateyearly"); + radioDailyRepetitionEndDate.setValue(Boolean.FALSE); + radioDailyRepetitionEndDate.setToolTip("Set a repetition end date"); + + dailyRepetitionEndDate = Forms.date("", true); + dailyRepetitionEndDate.setName("RepetitionEndDateFieldyearly"); + dailyNumberOfRepetitions.disable(); + dailyRepetitionEndDate.disable(); + + radioDailyNumberOfRepetitions.addListener(Events.OnChange, new Listener() { + @Override + public void handleEvent(FieldEvent event) { + dailyNumberOfRepetitions.enable(); + dailyRepetitionEndDate.disable(); + } + }); + + radioDailyRepetitionEndDate.addListener(Events.OnChange, new Listener() { + @Override + public void handleEvent(FieldEvent event) { + + dailyRepetitionEndDate.enable(); + dailyNumberOfRepetitions.disable(); + } + }); + + RepeatDailyMultiEventPeriodRG = Forms.radioGroup("Multi-event periodRGyearly", + "Multi-event periodRGyearly", + Style.Orientation.VERTICAL, + radioDailyNumberOfRepetitions, + radioDailyRepetitionEndDate); + RepeatDailyMultiEventPeriodRG.setSelectionRequired(Boolean.TRUE); + RepeatDailyMultiEventPeriodRG.enable(); + + //panelMonthly.add(RepeatMultiEventPeriodRG); + VerticalPanel verticalPanel = new VerticalPanel(); + verticalPanel.add(dailyNumberOfRepetitions); + verticalPanel.add(dailyRepetitionEndDate); + HorizontalPanel horizontalPanel = new HorizontalPanel(); + horizontalPanel.add(RepeatDailyMultiEventPeriodRG); + horizontalPanel.add(verticalPanel); + + panelDaily.add(horizontalPanel); + } + + private void createWeeklyPanel() { + panelWeekly = new FieldSet(); + panelWeekly.setExpanded(true); + panelWeekly.setBorders(true); + panelWeekly.setHeadingHtml("Weekly repetition details"); + panelWeekly.setAutoHeight(true); + panelWeekly.setVisible(false); + + radioWeeklyNumberOfRepetitions = Forms.radio("Number of repetitions"); + radioWeeklyNumberOfRepetitions.setName("Number of repetitonsYearly"); + radioWeeklyNumberOfRepetitions.setValue(Boolean.FALSE); + radioWeeklyNumberOfRepetitions.setOriginalValue(Boolean.FALSE); + radioWeeklyNumberOfRepetitions.setToolTip("Set a number of repetitons"); + + weeklyNumberOfRepetitions = Forms.textarea("", false); + weeklyNumberOfRepetitions.setName("numberOfRepetitionsyearly"); + weeklyNumberOfRepetitions.setId("numberOfRepetitionsyearly"); + weeklyNumberOfRepetitions.setMaxLength(255); + weeklyNumberOfRepetitions.setHeight(19); + + radioWeeklyRepetitionEndDate = Forms.radio("Repetition end date"); + radioWeeklyRepetitionEndDate.setBoxLabel("Repetition end date"); + radioWeeklyRepetitionEndDate.setName("Repetition end dateyearly"); + radioWeeklyRepetitionEndDate.setValue(Boolean.FALSE); + radioWeeklyRepetitionEndDate.setToolTip("Set a repetition end date"); + + weeklyRepetitionEndDate = Forms.date("", true); + weeklyRepetitionEndDate.setName("RepetitionEndDateFieldyearly"); + weeklyNumberOfRepetitions.disable(); + weeklyRepetitionEndDate.disable(); + + radioWeeklyNumberOfRepetitions.addListener(Events.OnChange, new Listener() { + @Override + public void handleEvent(FieldEvent event) { + weeklyNumberOfRepetitions.enable(); + weeklyRepetitionEndDate.disable(); + } + }); + + radioWeeklyRepetitionEndDate.addListener(Events.OnChange, new Listener() { + @Override + public void handleEvent(FieldEvent event) { + + weeklyRepetitionEndDate.enable(); + weeklyNumberOfRepetitions.disable(); + } + }); + + RepeatWeeklyMultiEventPeriodRG = Forms.radioGroup("Multi-event periodRGyearly", + "Multi-event periodRGyearly", + Style.Orientation.VERTICAL, + radioWeeklyNumberOfRepetitions, + radioWeeklyRepetitionEndDate); + RepeatWeeklyMultiEventPeriodRG.setSelectionRequired(Boolean.TRUE); + RepeatWeeklyMultiEventPeriodRG.enable(); + + //panelMonthly.add(RepeatMultiEventPeriodRG); + VerticalPanel verticalPanel = new VerticalPanel(); + verticalPanel.add(weeklyNumberOfRepetitions); + verticalPanel.add(weeklyRepetitionEndDate); + HorizontalPanel horizontalPanel = new HorizontalPanel(); + horizontalPanel.add(RepeatWeeklyMultiEventPeriodRG); + horizontalPanel.add(verticalPanel); + + panelWeekly.add(horizontalPanel); + } + + private void createMonthlyPanel() { + panelMonthly = new FieldSet(); + panelMonthly.setExpanded(true); + panelMonthly.setBorders(true); + panelMonthly.setHeadingHtml(I18N.CONSTANTS.calendar_addEvent_repeatsSettings_headingHtml_monthly()); + panelMonthly.setAutoHeight(true); + panelMonthly.setVisible(false); + + radioMonthlySameDayOfWeek = Forms.radio(I18N.CONSTANTS.calendar_addEvent_repeatsSettings_SameDayOfWeekRB_label()); + radioMonthlySameDayOfWeek.setName(I18N.CONSTANTS.calendar_addEvent_repeatsSettings_SameDayOfWeekRB_monthly_name()); + radioMonthlySameDayOfWeek.setValue(Boolean.FALSE); + radioMonthlySameDayOfWeek.setOriginalValue(Boolean.FALSE); + radioMonthlySameDayOfWeek.setToolTip(I18N.CONSTANTS.calendar_addEvent_repeatsSettings_SameDayOfWeekRB_monthly_toolTip()); + + radioMonthlySameDate = Forms.radio(I18N.CONSTANTS.calendar_addEvent_repeatsSettings_SameDateRB_label()); + radioMonthlySameDate.setBoxLabel(I18N.CONSTANTS.calendar_addEvent_repeatsSettings_SameDateRB_label()); + radioMonthlySameDate.setName(I18N.CONSTANTS.calendar_addEvent_repeatsSettings_SameDateRB_monthly_name()); + radioMonthlySameDate.setValue(Boolean.FALSE); + radioMonthlySameDate.setToolTip(I18N.CONSTANTS.calendar_addEvent_repeatsSettings_SameDateRB_monthly_toolTip()); + + montlyVariantRG = Forms.radioGroup(I18N.CONSTANTS.calendar_addEvent_repeatsSettings_radioGroup_monthly_settings()); + montlyVariantRG.setSelectionRequired(Boolean.FALSE); + montlyVariantRG.setOrientation(Style.Orientation.HORIZONTAL); + montlyVariantRG.add(radioMonthlySameDayOfWeek); + montlyVariantRG.add(radioMonthlySameDate); + panelMonthly.add(montlyVariantRG); + + radioNumberOfRepetitions = Forms.radio("Number of repetitions"); + radioNumberOfRepetitions.setName("Number of repetitons"); + radioNumberOfRepetitions.setValue(Boolean.FALSE); + radioNumberOfRepetitions.setOriginalValue(Boolean.FALSE); + radioNumberOfRepetitions.setToolTip("Set a number of repetitions"); + + radioRepetitionEndDate = Forms.radio("Repetition end date"); + radioRepetitionEndDate.setBoxLabel("Repetition end date"); + radioRepetitionEndDate.setName("Repetition end date"); + radioRepetitionEndDate.setValue(Boolean.FALSE); + radioRepetitionEndDate.setToolTip("Set a repetition end date"); + + RepeatMultiEventPeriodRG = Forms.radioGroup("Multi-event periodRG"); + RepeatMultiEventPeriodRG.setSelectionRequired(Boolean.FALSE); + RepeatMultiEventPeriodRG.setOrientation(Style.Orientation.VERTICAL); + RepeatMultiEventPeriodRG.add(radioNumberOfRepetitions); + RepeatMultiEventPeriodRG.add(radioRepetitionEndDate); + panelMonthly.add(RepeatMultiEventPeriodRG); + + numberOfRepetitions = Forms.textarea("", false); + numberOfRepetitions.setName("numberOfRepetitions"); + numberOfRepetitions.setId("numberOfRepetitions"); + numberOfRepetitions.setMaxLength(255); + numberOfRepetitions.setHeight(19); + + repetitionEndDate = Forms.date("", true); + repetitionEndDate.setName("RepetitionEndDateField"); + repetitionEndDate.setData("", new Date()); + + radioNumberOfRepetitions.addListener(Events.OnChange, new Listener() { + @Override + public void handleEvent(FieldEvent event) { + numberOfRepetitions.enable(); + repetitionEndDate.disable(); + } + }); + + radioRepetitionEndDate.addListener(Events.OnChange, new Listener() { + @Override + public void handleEvent(FieldEvent event) { + + repetitionEndDate.enable(); + numberOfRepetitions.disable(); + } + }); + + /* monthlyRepSettings = new FieldSet(); + monthlyRepSettings.setExpanded(true); + monthlyRepSettings.setBorders(true); + monthlyRepSettings.setHeadingHtml("End of monthly repetition event"); + monthlyRepSettings.setAutoHeight(true); + monthlyRepSettings.setVisible(true);*/ + VerticalPanel verticalPanel = new VerticalPanel(); + VerticalPanel verticalPanel1 = new VerticalPanel(); + VerticalPanel verticalPanel2 = new VerticalPanel(); + VerticalPanel verticalPanel3 = new VerticalPanel(); + verticalPanel3.setHeight(5); + verticalPanel1.add(numberOfRepetitions); + verticalPanel2.add(repetitionEndDate); + + verticalPanel.add(verticalPanel1); + verticalPanel.add(verticalPanel3); + verticalPanel.add(verticalPanel2); + + HorizontalPanel horizontalPanel = new HorizontalPanel(); + horizontalPanel.add(RepeatMultiEventPeriodRG); + horizontalPanel.add(verticalPanel); + panelMonthly.add(new HTML("
")); + panelMonthly.add(horizontalPanel); + // verticalPanel1.setHeight(verticalPanel.getHeight()/2); + //verticalPanel2.setHeight(verticalPanel.getHeight()/2); + } + + private void createYearlyPanel() { + panelYearly = new FieldSet(); + panelYearly.setExpanded(true); + panelYearly.setBorders(true); + panelYearly.setHeadingHtml(I18N.CONSTANTS.calendar_addEvent_repeatsSettings_headingHtml_yearly()); + panelYearly.setAutoHeight(true); + panelYearly.setVisible(false); + + yearlySameDayOfWeekRB = Forms.radio(I18N.CONSTANTS.calendar_addEvent_repeatsSettings_SameDayOfWeekRB_label(), Boolean.FALSE); + yearlySameDayOfWeekRB.setToolTip(I18N.CONSTANTS.calendar_addEvent_repeatsSettings_SameDayOfWeekRB_yearly_toolTip()); + yearlySameDayOfWeekRB.setOriginalValue(Boolean.TRUE); + yearlySameDayOfWeekRB.setName(I18N.CONSTANTS.calendar_addEvent_repeatsSettings_SameDayOfWeekRB_yearly_name()); + yearlySameDayOfWeekRB.setValue(Boolean.TRUE); + + yearlySameDateRB = Forms.radio(I18N.CONSTANTS.calendar_addEvent_repeatsSettings_SameDateRB_label(), Boolean.FALSE); + yearlySameDateRB.setName(I18N.CONSTANTS.calendar_addEvent_repeatsSettings_SameDateRB_yearly_name()); + yearlyVariantRG = Forms.radioGroup(I18N.CONSTANTS.calendar_addEvent_repeatsSettings_radioGroup_yearly_settings(), + I18N.CONSTANTS.calendar_addEvent_repeatsSettings_radioGroup_yearly_settings_name(), + Style.Orientation.HORIZONTAL, + yearlySameDayOfWeekRB, + yearlySameDateRB); + yearlyVariantRG.setSelectionRequired(Boolean.FALSE); + panelYearly.add(yearlyVariantRG); + + radioYearlyNumberOfRepetitions = Forms.radio("Number of repetitions"); + radioYearlyNumberOfRepetitions.setName("Number of repetitionsYearly"); + radioYearlyNumberOfRepetitions.setValue(Boolean.FALSE); + radioYearlyNumberOfRepetitions.setOriginalValue(Boolean.FALSE); + radioYearlyNumberOfRepetitions.setToolTip("Set a number of repetitons"); + + yearlyNumberOfRepetitions = Forms.textarea("", false); + yearlyNumberOfRepetitions.setName("numberOfRepetitionsyearly"); + yearlyNumberOfRepetitions.setId("numberOfRepetitionsyearly"); + yearlyNumberOfRepetitions.setMaxLength(255); + yearlyNumberOfRepetitions.setHeight(19); + + radioYearlyRepetitionEndDate = Forms.radio("Repetition end date"); + radioYearlyRepetitionEndDate.setBoxLabel("Repetition end date"); + radioYearlyRepetitionEndDate.setName("Repetition end dateyearly"); + radioYearlyRepetitionEndDate.setValue(Boolean.FALSE); + radioYearlyRepetitionEndDate.setToolTip("Set a repetition end date"); + + yearlyRepetitionEndDate = Forms.date("", true); + yearlyRepetitionEndDate.setName("RepetitionEndDateFieldyearly"); + yearlyNumberOfRepetitions.disable(); + yearlyRepetitionEndDate.disable(); + + radioYearlyNumberOfRepetitions.addListener(Events.OnChange, new Listener() { + @Override + public void handleEvent(FieldEvent event) { + yearlyNumberOfRepetitions.enable(); + yearlyRepetitionEndDate.disable(); + } + }); + + radioYearlyRepetitionEndDate.addListener(Events.OnChange, new Listener() { + @Override + public void handleEvent(FieldEvent event) { + + yearlyRepetitionEndDate.enable(); + yearlyNumberOfRepetitions.disable(); + } + }); + + RepeatYearlyMultiEventPeriodRG = Forms.radioGroup("Multi-event periodRGyearly", + "Multi-event periodRGyearly", + Style.Orientation.VERTICAL, + radioYearlyNumberOfRepetitions, + radioYearlyRepetitionEndDate); + RepeatYearlyMultiEventPeriodRG.setSelectionRequired(Boolean.TRUE); + RepeatYearlyMultiEventPeriodRG.enable(); + + //panelMonthly.add(RepeatMultiEventPeriodRG); + VerticalPanel verticalPanel = new VerticalPanel(); + + VerticalPanel verticalPanel1 = new VerticalPanel(); + VerticalPanel verticalPanel2 = new VerticalPanel(); + verticalPanel1.setHeight(23); + verticalPanel1.setWidth(150); + verticalPanel1.add(yearlyNumberOfRepetitions); + verticalPanel2.setHeight(23); + verticalPanel2.setWidth(150); + verticalPanel2.add(yearlyRepetitionEndDate); + VerticalPanel verticalPanel3 = new VerticalPanel(); + verticalPanel3.setHeight(5); + + verticalPanel.add(verticalPanel1); + verticalPanel.add(verticalPanel3); + verticalPanel.add(verticalPanel2); + + HorizontalPanel horizontalPanel = new HorizontalPanel(); + horizontalPanel.add(RepeatYearlyMultiEventPeriodRG); + horizontalPanel.add(verticalPanel); + + panelYearly.add(new HTML("
")); + panelYearly.add(horizontalPanel); + } + + /** + * {@inheritDoc} + */ + @Override + public FormPanel getForm() { + return form; + } + + /** + * {@inheritDoc} + */ + @Override + public TextField getEventSummaryField() { + return eventSummaryField; + } + + /** + * {@inheritDoc} + */ + @Override + public DateField getEventDateStartField() { + return eventDateStartField; + } + + /** + * {@inheritDoc} + */ + @Override + public DateField getEventDateEndField() { + return eventDateEndField; + } + + /** + * {@inheritDoc} + */ + @Override + public TimeField getEventStartTimeField() { + return eventStartTimeField; + } + + /** + * {@inheritDoc} + */ + @Override + public TimeField getEventEndTimeField() { + return eventEndTimeField; + } + + /** + * {@inheritDoc} + */ + @Override + public TextArea getEventDescriptionField() { + return eventDescriptionField; + } + + /** + * {@inheritDoc} + */ + @Override + public Button getSaveButton() { + return saveButton; + } + + /** + * {@inheritDoc} + */ + @Override + public Button getCancelButton() { + return cancelButton; + } + + @Override + public CheckBox getAllDayCheckbox() { + return allDayCheckbox; + } + + @Override + public FieldSet getPanelYearly() { + return panelYearly; + } + + @Override + public FieldSet getMonthlyRepSettings() { + return monthlyRepSettings; + } + + @Override + public FieldSet getYearlyRepSettings() { + return yearlyRepSettings; + } + + @Override + public FieldSet getPanelMonthly() { + return panelMonthly; + } + + @Override + public FieldSet getPanelWeekly() { + return panelWeekly; + } + + @Override + public FieldSet getPanelDaily() { + return panelDaily; + } + + /** + * + * @return + */ + @Override + public Radio getOnceRepeatRB() { + return onceRepeatRB; + } + + @Override + public Radio getDailyRepeatRB() { + return dailyRepeatRB; + } + + @Override + public Radio getWeeklyRepeatRB() { + return weeklyRepeatRB; + } + + @Override + public Radio getMonthlyRepeatRB() { + return monthlyRepeatRB; + } + + @Override + public Radio getYearlyRepeatRB() { + return yearlyRepeatRB; + } + + @Override + public RadioGroup getYearlyVariantRG() { + return yearlyVariantRG; + } + + @Override + public RadioGroup getRepeatMultiEventPeriodRG() { + return RepeatMultiEventPeriodRG; + } + + @Override + public RadioGroup getMontlyVariantRG() { + return montlyVariantRG; + } + + @Override + public Radio getYearlySameDayOfWeekRB() { + return yearlySameDayOfWeekRB; + } + + @Override + public Radio getYearlySameDateRB() { + return yearlySameDateRB; + } + + @Override + public RadioGroup getRepeatEventPeriodRG() { + return RepeatEventPeriodRG; + } + + @Override + public Radio getRadioMonthlySameDate() { + return radioMonthlySameDate; + } + + @Override + public Radio getRadioMonthlySameDayOfWeek() { + return radioMonthlySameDayOfWeek; + } + + @Override + public Radio getRadioNumberOfRepetitions() { + return radioNumberOfRepetitions; + } + + @Override + public Radio getRadioRepetitionEndDate() { + return radioRepetitionEndDate; + } + + @Override + public Radio getYearlyRadioNumberOfRepetitions() { + return radioYearlyNumberOfRepetitions; + } + + @Override + public Radio getYearlyRadioRepetitionEndDate() { + return radioYearlyRepetitionEndDate; + } + + @Override + public Radio getDailyRadioNumberOfRepetitions() { + return radioDailyNumberOfRepetitions; + } + + @Override + public Radio getDailyRadioRepetitionEndDate() { + return radioDailyRepetitionEndDate; + } + + @Override + public Radio getWeeklyRadioNumberOfRepetitions() { + return radioWeeklyNumberOfRepetitions; + } + + @Override + public Radio getWeeklyRadioRepetitionEndDate() { + return radioWeeklyRepetitionEndDate; + } + + @Override + public TextArea getNumberOfRepetitions() { + return numberOfRepetitions; + } + + @Override + public DateField getRepetitionEndDate() { + return repetitionEndDate; + } + + @Override + public TextArea getWeeklyNumberOfRepetitions() { + return weeklyNumberOfRepetitions; + } + + @Override + public DateField getWeeklyRepetitionEndDate() { + return weeklyRepetitionEndDate; + } + + @Override + public TextArea getDailyNumberOfRepetitions() { + return dailyNumberOfRepetitions; + } + + @Override + public DateField getDailyRepetitionEndDate() { + return dailyRepetitionEndDate; + } + + @Override + public TextArea getYearlyNumberOfRepetitions() { + return yearlyNumberOfRepetitions; + } + @Override + public DateField getYearlyRepetitionEndDate() { + return yearlyRepetitionEndDate; + } } diff --git a/src/main/java/org/sigmah/client/ui/view/calendar/CalendarView.java b/src/main/java/org/sigmah/client/ui/view/calendar/CalendarView.java index f6418d16a..957035cc6 100644 --- a/src/main/java/org/sigmah/client/ui/view/calendar/CalendarView.java +++ b/src/main/java/org/sigmah/client/ui/view/calendar/CalendarView.java @@ -21,305 +21,303 @@ * . * #L% */ +import java.util.Arrays; - -import java.util.Arrays; - -import org.sigmah.client.i18n.I18N; -import org.sigmah.client.ui.presenter.calendar.CalendarPresenter; -import org.sigmah.client.ui.view.base.AbstractView; -import org.sigmah.client.ui.widget.CalendarWidget; -import org.sigmah.client.ui.widget.button.Button; -import org.sigmah.client.ui.widget.form.Forms; -import org.sigmah.client.ui.widget.layout.Layouts; -import org.sigmah.client.ui.widget.layout.Layouts.Margin; -import org.sigmah.client.ui.widget.panel.Panels; -import org.sigmah.shared.dto.calendar.CalendarWrapper; - -import com.extjs.gxt.ui.client.Style.LayoutRegion; -import com.extjs.gxt.ui.client.store.ListStore; -import com.extjs.gxt.ui.client.widget.Component; -import com.extjs.gxt.ui.client.widget.ContentPanel; -import com.extjs.gxt.ui.client.widget.grid.CheckBoxSelectionModel; -import com.extjs.gxt.ui.client.widget.grid.ColumnConfig; -import com.extjs.gxt.ui.client.widget.grid.ColumnData; -import com.extjs.gxt.ui.client.widget.grid.ColumnModel; -import com.extjs.gxt.ui.client.widget.grid.Grid; -import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer; -import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData; -import com.extjs.gxt.ui.client.widget.selection.AbstractStoreSelectionModel; -import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem; -import com.extjs.gxt.ui.client.widget.toolbar.ToolBar; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.i18n.client.LocaleInfo; -import com.google.gwt.i18n.shared.DateTimeFormatInfo; -import com.google.gwt.user.client.ui.SimplePanel; -import org.sigmah.client.ui.res.icon.IconImageBundle; - -/** - * Calendar widget presenter. - * - * @author Raphaël Calabro (rcalabro@ideia.fr) (v1.3) - * @author Denis Colliot (dcolliot@ideia.fr) (v2.0) - */ -public class CalendarView extends AbstractView implements CalendarPresenter.View { - - private ContentPanel calendarView; - - private ListStore calendarsStore; - private CheckBoxSelectionModel selectionModel; - - private ToolBar toolbar; - private Button addEventButton; - private Button todayButton; - private Button weekButton; - private Button monthButton; - private Button previousButton; - private Button nextButton; - - private Button reminderAddButton; - private Button monitoredPointsAddButton; - - /** - * {@inheritDoc} - */ - @Override - public void initialize() { - - // -- - // Calendars left panel. - // -- - - final BorderLayoutData calendarListData = Layouts.borderLayoutData(LayoutRegion.WEST, Layouts.LEFT_COLUMN_WIDTH); - calendarListData.setCollapsible(true); - add(createCalendarsGridPanel(), calendarListData); - - // -- - // Calendar center widget. - // -- - - add(createCalendarsMainPanel(), Layouts.borderLayoutData(LayoutRegion.CENTER, Margin.LEFT)); - } - - /** - * Creates the calendars panel + grid. - * - * @return The calendars panel. - */ - private Component createCalendarsGridPanel() { - - // Calendars panel. - final ContentPanel calendarsPanel = Panels.content(I18N.CONSTANTS.projectTabCalendar()); - - // Calendars grid. - final ColumnConfig calendarName = new ColumnConfig("name", I18N.CONSTANTS.name(), 180); - final ColumnConfig calendarColor = new ColumnConfig("color", "", 20); - calendarColor.setStyle(""); - calendarColor.setRenderer(new GridCellRenderer() { - - @Override - public Object render(CalendarWrapper model, String property, ColumnData config, int rowIndex, int colIndex, ListStore store, - Grid grid) { - - final SimplePanel panel = new SimplePanel(); - panel.setPixelSize(14, 14); - panel.getElement().getStyle().setMarginLeft(3, Unit.PX); - - panel.setStyleName("calendar-fullday-event-" + model.getCalendar().getStyle()); - return panel; - } - }); - - selectionModel = new CheckBoxSelectionModel(); - - final ColumnModel calendarColumnModel = new ColumnModel(Arrays.asList(selectionModel.getColumn(), calendarName, calendarColor)); - - calendarsStore = new ListStore(); - - final Grid calendarGrid = new Grid(calendarsStore, calendarColumnModel); - calendarGrid.setAutoExpandColumn("name"); - calendarGrid.setSelectionModel(selectionModel); - calendarGrid.addPlugin(selectionModel); - - calendarGrid.getView().setForceFit(true); - - calendarsPanel.add(calendarGrid); - return calendarsPanel; - } - - /** - * Creates the calendars main panel, place holder for the {@link CalendarWidget}. - * - * @return The calendars main panel. - */ - private Component createCalendarsMainPanel() { - - calendarView = Panels.content(I18N.CONSTANTS.loading(), "panel-background"); // Temporary title. - - // Toolbar - toolbar = new ToolBar(); - - // Today button - center the calendar on the current day - todayButton = Forms.button(I18N.CONSTANTS.today()); - toolbar.add(todayButton); - - toolbar.add(new SeparatorToolItem()); - - // Week button - changes the calendar to display weeks - weekButton = Forms.button(I18N.CONSTANTS.week()); - toolbar.add(weekButton); - - // Week button - changes the calendar to display monthes - monthButton = Forms.button(I18N.CONSTANTS.month()); - toolbar.add(monthButton); - - toolbar.add(new SeparatorToolItem()); - - // Previous button - move back from one unit of time (week / month) - previousButton = Forms.button(I18N.CONSTANTS.previous()); - toolbar.add(previousButton); - - // Next button - move forward from one unit of time (week / month) - nextButton = Forms.button(I18N.CONSTANTS.next()); - toolbar.add(nextButton); - - toolbar.add(new SeparatorToolItem()); - - addEventButton = Forms.button(I18N.CONSTANTS.calendarAddEvent()); - - reminderAddButton = new Button(I18N.CONSTANTS.reminderPoint(), IconImageBundle.ICONS.add()); - - monitoredPointsAddButton = new Button(I18N.CONSTANTS.monitoredPoint(), IconImageBundle.ICONS.add()); - - calendarView.setTopComponent(toolbar); - - return calendarView; - } - - /** - * {@inheritDoc} - */ - @Override - public void initializeCalendarWidget(final CalendarWidget calendarWidget) { - - // Defining the first day of the week - // BUGFIX #653: Contrary to the deprecated DateTimeConstants, firstDayOfTheWeek starts at 0 (and not 1). No substraction is needed. - final DateTimeFormatInfo constants = LocaleInfo.getCurrentLocale().getDateTimeFormatInfo(); - calendarWidget.setFirstDayOfWeek(constants.firstDayOfTheWeek()); - - // Retrieving the current calendar header - calendarView.setHeadingHtml(calendarWidget.getHeading()); - - // Listening for further calendar header changes - calendarWidget.setListener(new CalendarWidget.CalendarListener() { - - @Override - public void afterRefresh() { - calendarView.setHeadingHtml(calendarWidget.getHeading()); - } - }); - - calendarView.add(calendarWidget, Layouts.fitData(Margin.DOUBLE_TOP, Margin.DOUBLE_RIGHT, Margin.DOUBLE_BOTTOM, Margin.DOUBLE_LEFT)); - } - - /** - * {@inheritDoc} - */ - @Override - public void setAddEventButtonEnabled(final boolean addEventButtonEnabled) { - - if (toolbar.indexOf(addEventButton) != -1) { - toolbar.remove(addEventButton); - toolbar.remove(reminderAddButton); - toolbar.remove(monitoredPointsAddButton); - } - - if (addEventButtonEnabled) { - toolbar.add(addEventButton); - toolbar.add(reminderAddButton); - toolbar.add(monitoredPointsAddButton); - - } - } - - /** - * {@inheritDoc} - */ - @Override - public Button getAddEventButton() { - return addEventButton; - } - - /** - * {@inheritDoc} - */ - @Override - public Button getTodayButton() { - return todayButton; - } - - /** - * {@inheritDoc} - */ - @Override - public Button getWeekButton() { - return weekButton; - } - - /** - * {@inheritDoc} - */ - @Override - public Button getMonthButton() { - return monthButton; - } - - /** - * {@inheritDoc} - */ - @Override - public Button getPreviousButton() { - return previousButton; - } - - /** - * {@inheritDoc} - */ - @Override - public Button getNextButton() { - return nextButton; - } - - /** - * {@inheritDoc} - */ - @Override - public Button getReminderAddButton() { - return reminderAddButton; - } - - /** - * {@inheritDoc} - */ - @Override - public Button getMonitoredPointsAddButton() { - return monitoredPointsAddButton; - } - - /** - * {@inheritDoc} - */ - @Override - public AbstractStoreSelectionModel getCalendarsSelectionModel() { - return selectionModel; - } - - /** - * {@inheritDoc} - */ - @Override - public ListStore getCalendarsStore() { - return calendarsStore; - } - -} +import org.sigmah.client.i18n.I18N; +import org.sigmah.client.ui.presenter.calendar.CalendarPresenter; +import org.sigmah.client.ui.view.base.AbstractView; +import org.sigmah.client.ui.widget.CalendarWidget; +import org.sigmah.client.ui.widget.button.Button; +import org.sigmah.client.ui.widget.form.Forms; +import org.sigmah.client.ui.widget.layout.Layouts; +import org.sigmah.client.ui.widget.layout.Layouts.Margin; +import org.sigmah.client.ui.widget.panel.Panels; +import org.sigmah.shared.dto.calendar.CalendarWrapper; + +import com.extjs.gxt.ui.client.Style.LayoutRegion; +import com.extjs.gxt.ui.client.Style.Scroll; +import com.extjs.gxt.ui.client.store.ListStore; +import com.extjs.gxt.ui.client.widget.Component; +import com.extjs.gxt.ui.client.widget.ContentPanel; +import com.extjs.gxt.ui.client.widget.grid.CheckBoxSelectionModel; +import com.extjs.gxt.ui.client.widget.grid.ColumnConfig; +import com.extjs.gxt.ui.client.widget.grid.ColumnData; +import com.extjs.gxt.ui.client.widget.grid.ColumnModel; +import com.extjs.gxt.ui.client.widget.grid.Grid; +import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer; +import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData; +import com.extjs.gxt.ui.client.widget.selection.AbstractStoreSelectionModel; +import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem; +import com.extjs.gxt.ui.client.widget.toolbar.ToolBar; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.i18n.client.LocaleInfo; +import com.google.gwt.i18n.shared.DateTimeFormatInfo; +import com.google.gwt.user.client.ui.SimplePanel; +import org.sigmah.client.ui.res.icon.IconImageBundle; + +/** + * Calendar widget presenter. + * + * @author Raphaël Calabro (rcalabro@ideia.fr) (v1.3) + * @author Denis Colliot (dcolliot@ideia.fr) (v2.0) + */ +public class CalendarView extends AbstractView implements CalendarPresenter.View { + + private ContentPanel calendarView; + + private ListStore calendarsStore; + private CheckBoxSelectionModel selectionModel; + + private ToolBar toolbar; + private Button addEventButton; + private Button todayButton; + private Button weekButton; + private Button monthButton; + private Button previousButton; + private Button nextButton; + + private Button reminderAddButton; + private Button monitoredPointsAddButton; + + /** + * {@inheritDoc} + */ + @Override + public void initialize() { + + // -- + // Calendars left panel. + // -- + final BorderLayoutData calendarListData = Layouts.borderLayoutData(LayoutRegion.WEST, Layouts.LEFT_COLUMN_WIDTH); + calendarListData.setCollapsible(true); + add(createCalendarsGridPanel(), calendarListData); + + // -- + // Calendar center widget. + // -- + add(createCalendarsMainPanel(), Layouts.borderLayoutData(LayoutRegion.CENTER, Margin.LEFT)); + } + + /** + * Creates the calendars panel + grid. + * + * @return The calendars panel. + */ + private Component createCalendarsGridPanel() { + + // Calendars panel. + final ContentPanel calendarsPanel = Panels.content(I18N.CONSTANTS.projectTabCalendar()); + + // Calendars grid. + final ColumnConfig calendarName = new ColumnConfig("name", I18N.CONSTANTS.name(), 180); + final ColumnConfig calendarColor = new ColumnConfig("color", "", 20); + calendarColor.setStyle(""); + calendarColor.setRenderer(new GridCellRenderer() { + + @Override + public Object render(CalendarWrapper model, String property, ColumnData config, int rowIndex, int colIndex, ListStore store, + Grid grid) { + + final SimplePanel panel = new SimplePanel(); + panel.setPixelSize(14, 14); + panel.getElement().getStyle().setMarginLeft(3, Unit.PX); + + panel.setStyleName("calendar-fullday-event-" + model.getCalendar().getStyle()); + return panel; + } + }); + + selectionModel = new CheckBoxSelectionModel(); + + final ColumnModel calendarColumnModel = new ColumnModel(Arrays.asList(selectionModel.getColumn(), calendarName, calendarColor)); + + calendarsStore = new ListStore(); + + final Grid calendarGrid = new Grid(calendarsStore, calendarColumnModel); + calendarGrid.setAutoExpandColumn("name"); + calendarGrid.setSelectionModel(selectionModel); + calendarGrid.addPlugin(selectionModel); + + calendarGrid.getView().setForceFit(true); + + calendarsPanel.add(calendarGrid); + return calendarsPanel; + } + + /** + * Creates the calendars main panel, place holder for the + * {@link CalendarWidget}. + * + * @return The calendars main panel. + */ + private Component createCalendarsMainPanel() { + + calendarView = Panels.content(I18N.CONSTANTS.loading(), "panel-background"); // Temporary title. + + // Toolbar + toolbar = new ToolBar(); + + // Today button - center the calendar on the current day + todayButton = Forms.button(I18N.CONSTANTS.today()); + toolbar.add(todayButton); + + toolbar.add(new SeparatorToolItem()); + + // Week button - changes the calendar to display weeks + weekButton = Forms.button(I18N.CONSTANTS.week()); + toolbar.add(weekButton); + + // Week button - changes the calendar to display monthes + monthButton = Forms.button(I18N.CONSTANTS.month()); + toolbar.add(monthButton); + + toolbar.add(new SeparatorToolItem()); + + // Previous button - move back from one unit of time (week / month) + previousButton = Forms.button(I18N.CONSTANTS.previous()); + toolbar.add(previousButton); + + // Next button - move forward from one unit of time (week / month) + nextButton = Forms.button(I18N.CONSTANTS.next()); + toolbar.add(nextButton); + + toolbar.add(new SeparatorToolItem()); + + addEventButton = Forms.button(I18N.CONSTANTS.calendarAddEvent(), IconImageBundle.ICONS.add()); + reminderAddButton = new Button(I18N.CONSTANTS.reminderPoint(), IconImageBundle.ICONS.add()); + monitoredPointsAddButton = new Button(I18N.CONSTANTS.monitoredPoint(), IconImageBundle.ICONS.add()); + + calendarView.setTopComponent(toolbar); + + return calendarView; + } + + /** + * {@inheritDoc} + */ + @Override + public void initializeCalendarWidget(final CalendarWidget calendarWidget) { + + // Defining the first day of the week + // BUGFIX #653: Contrary to the deprecated DateTimeConstants, firstDayOfTheWeek starts at 0 (and not 1). No substraction is needed. + final DateTimeFormatInfo constants = LocaleInfo.getCurrentLocale().getDateTimeFormatInfo(); + calendarWidget.setFirstDayOfWeek(constants.firstDayOfTheWeek()); + + // Retrieving the current calendar header + calendarView.setHeadingHtml(calendarWidget.getHeading()); + + // Listening for further calendar header changes + calendarWidget.setListener(new CalendarWidget.CalendarListener() { + + @Override + public void afterRefresh() { + calendarView.setHeadingHtml(calendarWidget.getHeading()); + } + }); + calendarView.setScrollMode(Scroll.AUTOY);//ss + calendarView.add(calendarWidget, Layouts.fitData(Margin.DOUBLE_TOP, Margin.DOUBLE_RIGHT, Margin.DOUBLE_BOTTOM, Margin.DOUBLE_LEFT)); + + calendarView.add(calendarWidget, Layouts.fitData(Margin.DOUBLE_TOP, Margin.DOUBLE_RIGHT, Margin.DOUBLE_BOTTOM, Margin.DOUBLE_LEFT)); + } + + /** + * {@inheritDoc} + */ + @Override + public void setAddEventButtonEnabled(final boolean addEventButtonEnabled) { + + if (toolbar.indexOf(addEventButton) != -1) { + toolbar.remove(addEventButton); + toolbar.remove(reminderAddButton); + toolbar.remove(monitoredPointsAddButton); + } + + if (addEventButtonEnabled) { + toolbar.add(addEventButton); + toolbar.add(reminderAddButton); + toolbar.add(monitoredPointsAddButton); + + } + } + + /** + * {@inheritDoc} + */ + @Override + public Button getAddEventButton() { + return addEventButton; + } + + /** + * {@inheritDoc} + */ + @Override + public Button getTodayButton() { + return todayButton; + } + + /** + * {@inheritDoc} + */ + @Override + public Button getWeekButton() { + return weekButton; + } + + /** + * {@inheritDoc} + */ + @Override + public Button getMonthButton() { + return monthButton; + } + + /** + * {@inheritDoc} + */ + @Override + public Button getPreviousButton() { + return previousButton; + } + + /** + * {@inheritDoc} + */ + @Override + public Button getNextButton() { + return nextButton; + } + + /** + * {@inheritDoc} + */ + @Override + public Button getReminderAddButton() { + return reminderAddButton; + } + + /** + * {@inheritDoc} + */ + @Override + public Button getMonitoredPointsAddButton() { + return monitoredPointsAddButton; + } + + /** + * {@inheritDoc} + */ + @Override + public AbstractStoreSelectionModel getCalendarsSelectionModel() { + return selectionModel; + } + + /** + * {@inheritDoc} + */ + @Override + public ListStore getCalendarsStore() { + return calendarsStore; + } + +} diff --git a/src/main/java/org/sigmah/client/ui/widget/CalendarWidget.java b/src/main/java/org/sigmah/client/ui/widget/CalendarWidget.java index b223a6031..c4761e9ce 100644 --- a/src/main/java/org/sigmah/client/ui/widget/CalendarWidget.java +++ b/src/main/java/org/sigmah/client/ui/widget/CalendarWidget.java @@ -21,7 +21,6 @@ * . * #L% */ - import java.util.ArrayList; import java.util.Comparator; import java.util.Date; @@ -44,6 +43,7 @@ import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.i18n.client.DateTimeFormat; +import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.Composite; @@ -54,425 +54,539 @@ import com.google.gwt.user.client.ui.InlineLabel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.PopupPanel.PositionCallback; +import com.google.gwt.user.client.ui.Widget; +import org.sigmah.client.util.FormattingUtil; /** * This widget displays a calendar. - * + * * @author Raphaël Calabro (rcalabro@ideia.fr) */ @SuppressWarnings("deprecation") public class CalendarWidget extends Composite { - public static final int CELL_DEFAULT_WIDTH = 150; - public static final int CELL_DEFAULT_HEIGHT = 80; - - public interface CalendarListener { - - void afterRefresh(); - - } - - public interface Delegate { - - void edit(Event event, CalendarWidget calendarWidget); - - void delete(Event event, CalendarWidget calendarWidget); - - } - - /** - * Types of displays availables for a calendar. - * - * @author rca - */ - public static enum DisplayMode { - DAY(1, 1) { - - @Override - public Date getStartDate(Date date, int firstDay) { - return new Date(date.getYear(), date.getMonth(), date.getDate()); - } - - @Override - public void nextDate(Date currentDate) { - currentDate.setDate(currentDate.getDate() + 1); - } - - @Override - public void previousDate(Date currentDate) { - currentDate.setDate(currentDate.getDate() - 1); - } - - @Override - public void firstDay(Date currentDate, Date today, int firstDay) { - currentDate.setYear(today.getYear()); - currentDate.setMonth(today.getMonth()); - currentDate.setDate(today.getDate()); - } - - @Override - public String getStyleName() { - return "calendar-day"; - } - }, - WEEK(7, 1) { - - @Override - public Date getStartDate(Date date, int firstDay) { - return getFirstDateOfWeek(date, firstDay); - } - - @Override - public void nextDate(Date currentDate) { - currentDate.setDate(currentDate.getDate() + 7); - } - - @Override - public void previousDate(Date currentDate) { - currentDate.setDate(currentDate.getDate() - 7); - } - - @Override - public void firstDay(Date currentDate, Date today, int firstDay) { - int decal = (today.getDay() + 7 - firstDay) % 7; - currentDate.setYear(today.getYear()); - currentDate.setMonth(today.getMonth()); - currentDate.setDate(today.getDate() - decal); - final Date date = getFirstDateOfWeek(today, firstDay); - currentDate.setTime(date.getTime()); - } - - @Override - public String getStyleName() { - return "calendar-week"; - } - }, - MONTH(7, 6) { - - @Override - public Date getStartDate(Date date, int firstDay) { - Date firstDayOfMonth = new Date(date.getYear(), date.getMonth(), 1); - return getFirstDateOfWeek(firstDayOfMonth, firstDay); - } - - @Override - public void nextDate(Date currentDate) { - currentDate.setMonth(currentDate.getMonth() + 1); - } - - @Override - public void previousDate(Date currentDate) { - currentDate.setMonth(currentDate.getMonth() - 1); - } - - @Override - public void firstDay(Date currentDate, Date today, int firstDay) { - currentDate.setYear(today.getYear()); - currentDate.setMonth(today.getMonth()); - currentDate.setDate(1); - } - - @Override - public String getStyleName() { - return "calendar-month"; - } - }; - - private int columns; - private int rows; - - private DisplayMode(int columns, int rows) { - this.columns = columns; - this.rows = rows; - } - - public int getRows() { - return rows; - } - - public int getColumns() { - return columns; - } - - public abstract Date getStartDate(Date date, int firstDay); - - public abstract void nextDate(Date currentDate); - - public abstract void previousDate(Date currentDate); - - public abstract void firstDay(Date currentDate, Date today, int firstDay); - - public abstract String getStyleName(); - } - - public final static int NO_HEADERS = 0; - public final static int COLUMN_HEADERS = 1; - public final static int ALL_HEADERS = 2; - - private final static int UNDEFINED = -1; - private final static int EVENT_HEIGHT = 16; - private int eventLimit = UNDEFINED; - - private int firstDayOfWeek; - private DisplayMode displayMode = DisplayMode.MONTH; - private int displayHeaders = ALL_HEADERS; - private boolean displayWeekNumber = true; - - private List calendars; - - private Date today; - private Date startDate; - - private DateTimeFormat titleFormatter = DateTimeFormat.getFormat("MMMM y"); - private DateTimeFormat headerFormatter = DateTimeFormat.getFormat("EEEE"); - private DateTimeFormat dayFormatter = DateTimeFormat.getFormat("d"); - private DateTimeFormat hourFormatter = DateTimeFormat.getFormat("HH:mm"); - - private CalendarListener listener; - private Delegate delegate; - - private final Authentication authentication; - - public CalendarWidget(int displayHeaders, boolean displayWeekNumber, Authentication authentication) { - this.calendars = new ArrayList(); - this.displayHeaders = displayHeaders; - this.displayWeekNumber = displayWeekNumber; - this.authentication = authentication; - - // final SimplePanel container; - - final FlexTable grid = new FlexTable(); - grid.addStyleName("calendar"); - grid.addStyleName(displayMode.getStyleName()); - - initWidget(grid); - - final Date now = new Date(); - today = new Date(now.getYear(), now.getMonth(), now.getDate()); - startDate = new Date(0, 0, 0); - - today(); - } - - public void setDelegate(Delegate delegate) { - this.delegate = delegate; - } - - public void setListener(CalendarListener listener) { - this.listener = listener; - } - - public void next() { - displayMode.nextDate(startDate); - refresh(); - } - - public void previous() { - displayMode.previousDate(startDate); - refresh(); - } - - public final void today() { - displayMode.firstDay(startDate, today, firstDayOfWeek); - refresh(); - } - - /** - * Retrieves the current start date of the calendar. - * - * @return the current start date of the calendar. - */ - public Date getStartDate() { - return startDate; - } - - public void addCalendar(Calendar calendar) { - calendars.add(calendar); - refresh(); - } - - public List getCalendars() { - return calendars; - } - - public void setCalendars(List calendars) { - this.calendars = calendars; - refresh(); - } - - /** - * Defines the formatter used to display the title of the calendar.
- *
- * The default format is "MonthName FullYear " (pattern : "N y"). - * - * @param titleFormatter - * The formatter to use to display the title of the calendar. - */ - public void setTitleFormatter(DateTimeFormat titleFormatter) { - this.titleFormatter = titleFormatter; - refresh(); - } - - /** - * Defines the formatter used to display the title of each column.
- *
- * The default format is "WeekName" (pattern : "E"). - * - * @param headerFormatter - * The formatter to use to display the title of each column. - */ - public void setHeaderFormatter(DateTimeFormat headerFormatter) { - this.headerFormatter = headerFormatter; - refresh(); - } - - /** - * Defines the formatter used to display the title of each cell.
- *
- * The default format is "DayNumber" (pattern : "d"). - * - * @param dayFormatter - * The formatter to use to display the title of each cell. - */ - public void setDayFormatter(DateTimeFormat dayFormatter) { - this.dayFormatter = dayFormatter; - refresh(); - } - - /** - * Defines the display mode of the calendar and perform a redraw. - * - * @param displayMode - * Style of the calendar (day, week or month). - * @see CalendarWidget.DisplayMode - */ - public void setDisplayMode(DisplayMode displayMode) { - final FlexTable grid = (FlexTable) getWidget(); - - clear(); - - // Resetting the CSS style - grid.removeStyleName(this.displayMode.getStyleName()); - - this.displayMode = displayMode; - - // Applying the CSS style associated with the new display mode - grid.addStyleName(displayMode.getStyleName()); - - refresh(); - } - - /** - * Defines the first day of the week and refresh the calendar. - * - * @param firstDayOfWeek - * The first day of the week as an int (Sunday = 0, Saturday = 6) - */ - public void setFirstDayOfWeek(int firstDayOfWeek) { - this.firstDayOfWeek = firstDayOfWeek; - refresh(); - } - - public int getDisplayHeaders() { - return displayHeaders; - } - - public void setDisplayHeaders(int displayHeaders) { - clear(); - this.displayHeaders = displayHeaders; - refresh(); - } - - public boolean isDisplayWeekNumber() { - return displayWeekNumber; - } - - public void setDisplayWeekNumber(boolean displayWeekNumber) { - clear(); - this.displayWeekNumber = displayWeekNumber; - refresh(); - } - - /** - * Removes all rows. Must be when the structure of the calendar has been changed (display mode) - */ - private void clear() { - final FlexTable grid = (FlexTable) getWidget(); - grid.clear(); - grid.removeAllRows(); - } - - /** - * @param date1 - * @param date2 - * @return boolean indicating if date1 and date2 are on the same day - */ - public static boolean isSameDay(Date date1, Date date2) { - DateTimeFormat fmt = DateTimeFormat.getFormat("yyyyMMdd"); - return fmt.format(date1).equals(fmt.format(date2)); - } - - /** - * Normalizes the given {@code calendar}'s events map (needed particularly when there is a timezone difference between - * the client and the server). - * - * @param calendar - * The calendar instance. - * @return The map with each event with the right key. - */ - public static Map> normalize(final Calendar calendar) { - - final Map> eventMap = calendar.getEvents(); - final Map> eventMapNormalized = new HashMap>(); - - boolean isActivityCalendar = false; - if (calendar.getIdentifier() instanceof ActivityCalendarIdentifier) { - isActivityCalendar = true; - } - - for (final Date key : eventMap.keySet()) { - for (final Event event : eventMap.get(key)) { - Date normalizedKeyDate = new Date(key.getYear(), key.getMonth(), key.getDate()); - - // Activities events have different startDate from the key date - // They shouldn't be placed in their startDate list - if (!isSameDay(normalizedKeyDate, event.getDtstart()) && !isActivityCalendar) { - normalizedKeyDate = new Date(event.getDtstart().getYear(), event.getDtstart().getMonth(), event.getDtstart().getDate()); - } - - if (eventMapNormalized.get(normalizedKeyDate) == null) { - eventMapNormalized.put(normalizedKeyDate, new ArrayList()); - } - eventMapNormalized.get(normalizedKeyDate).add(event); - } - } - - return eventMapNormalized; - } - - /** - * Calculates the number of events that can be displayed in a cell. - */ - public void calibrateCalendar() { - final FlexTable grid = (FlexTable) getWidget(); - - final Element row = grid.getRowFormatter().getElement(displayHeaders); - row.setId("calendar-row-calibration"); - - final Element cell = grid.getCellFormatter().getElement(displayHeaders, displayWeekNumber ? 1 : 0); - cell.setId("calendar-cell-calibration"); - - eventLimit = (getCellHeight(CELL_DEFAULT_HEIGHT) / EVENT_HEIGHT) - 2; - if (eventLimit < 0) - eventLimit = 0; - } - - /** - * Calculates the height of the cell identified by "calendar-cell-calibration". - * - * @return height of a cell. - */ - private native int getCellHeight(int defaultHeight) /*-{ + public static final int CELL_DEFAULT_WIDTH = 150; + public static final int CELL_DEFAULT_HEIGHT = 80; + + /** + * Multiple calculated ("cached") values reused during laying out + * the month view elements. + */ + private static final int DAYS_IN_A_WEEK = 7; + private int calculatedWeekDayHeaderHeight; + private int calculatedDayHeaderHeight; + /** + * Height of each Cell (day), including the day's header. + */ + private float calculatedCellOffsetHeight; + + /** + * Height of each Cell (day), excluding the day's header. + */ + private float calculatedCellHeight; + + public interface CalendarListener { + + void afterRefresh(); + + } + + public interface Delegate { + + void edit(Event event, CalendarWidget calendarWidget); + + void delete(Event event, CalendarWidget calendarWidget); + + void deleteChain(Event event, CalendarWidget calendarWidget); + + } + + /** + * Types of displays availables for a calendar. + * + * @author rca + */ + public static enum DisplayMode { + DAY(1, 1) { + + @Override + public Date getStartDate(Date date, int firstDay) { + return new Date(date.getYear(), date.getMonth(), date.getDate()); + } + + @Override + public void nextDate(Date currentDate) { + currentDate.setDate(currentDate.getDate() + 1); + } + + @Override + public void previousDate(Date currentDate) { + currentDate.setDate(currentDate.getDate() - 1); + } + + @Override + public void firstDay(Date currentDate, Date today, int firstDay) { + currentDate.setYear(today.getYear()); + currentDate.setMonth(today.getMonth()); + currentDate.setDate(today.getDate()); + } + + @Override + public String getStyleName() { + return "calendar-day"; + } + }, + WEEK(DAYS_IN_A_WEEK, 1) { + + @Override + public Date getStartDate(Date date, int firstDay) { + return getFirstDateOfWeek(date, firstDay); + } + + @Override + public void nextDate(Date currentDate) { + currentDate.setDate(currentDate.getDate() + DAYS_IN_A_WEEK); + } + + @Override + public void previousDate(Date currentDate) { + currentDate.setDate(currentDate.getDate() - DAYS_IN_A_WEEK); + } + + @Override + public void firstDay(Date currentDate, Date today, int firstDay) { + int decal = (today.getDay() + DAYS_IN_A_WEEK - firstDay) % DAYS_IN_A_WEEK; + currentDate.setYear(today.getYear()); + currentDate.setMonth(today.getMonth()); + currentDate.setDate(today.getDate() - decal); + final Date date = getFirstDateOfWeek(today, firstDay); + currentDate.setTime(date.getTime()); + } + + @Override + public String getStyleName() { + return "calendar-week"; + } + }, + MONTH(7, 6) { + + @Override + public Date getStartDate(Date date, int firstDay) { + Date firstDayOfMonth = new Date(date.getYear(), date.getMonth(), 1); + return getFirstDateOfWeek(firstDayOfMonth, firstDay); + } + + @Override + public void nextDate(Date currentDate) { + currentDate.setMonth(currentDate.getMonth() + 1); + } + + @Override + public void previousDate(Date currentDate) { + currentDate.setMonth(currentDate.getMonth() - 1); + } + + @Override + public void firstDay(Date currentDate, Date today, int firstDay) { + currentDate.setYear(today.getYear()); + currentDate.setMonth(today.getMonth()); + currentDate.setDate(1); + } + + @Override + public String getStyleName() { + return "calendar-month"; + } + }; + + private int columns; + private int rows; + + private DisplayMode(int columns, int rows) { + this.columns = columns; + this.rows = rows; + } + + public int getRows() { + return rows; + } + + public int getColumns() { + return columns; + } + + public abstract Date getStartDate(Date date, int firstDay); + + public abstract void nextDate(Date currentDate); + + public abstract void previousDate(Date currentDate); + + public abstract void firstDay(Date currentDate, Date today, int firstDay); + + public abstract String getStyleName(); + } + + public final static int NO_HEADERS = 0; + public final static int COLUMN_HEADERS = 1; + public final static int ALL_HEADERS = 2; + + private final static int UNDEFINED = -1; + private final static int EVENT_HEIGHT = 16; + private int eventLimit = UNDEFINED; + + private int firstDayOfWeek; + private DisplayMode displayMode = DisplayMode.MONTH; + private int displayHeaders = ALL_HEADERS; + private boolean displayWeekNumber = true; + + private List calendars; + + private Date today; + private Date startDate; + + private DateTimeFormat titleFormatter = DateTimeFormat.getFormat("MMMM y"); + private DateTimeFormat headerFormatter = DateTimeFormat.getFormat("EEEE"); + private DateTimeFormat dayFormatter = DateTimeFormat.getFormat("d"); + private DateTimeFormat hourFormatter = DateTimeFormat.getFormat("HH:mm"); + + private CalendarListener listener; + private Delegate delegate; + + private final Authentication authentication; + + public CalendarWidget(int displayHeaders, boolean displayWeekNumber, Authentication authentication) { + this.calendars = new ArrayList(); + this.displayHeaders = displayHeaders; + this.displayWeekNumber = displayWeekNumber; + this.authentication = authentication; + + // final SimplePanel container; + final FlexTable grid = new FlexTable(); +// getColumnFormatter().getElement( column ).setAttribute( "width", +// grid.getFlexCellFormatter().getElement(0, 0) + grid.addStyleName("calendar"); + grid.addStyleName(displayMode.getStyleName()); +// VerticalPanel dialogContents = new VerticalPanel(); +// dialogContents.add(grid); +// initWidget(dialogContents); + initWidget(grid); + + final Date now = new Date(); + today = new Date(now.getYear(), now.getMonth(), now.getDate()); + startDate = new Date(0, 0, 0); + + today(); + } + + public void setDelegate(Delegate delegate) { + this.delegate = delegate; + } + + public void setListener(CalendarListener listener) { + this.listener = listener; + } + + public void next() { + displayMode.nextDate(startDate); + refresh(); + } + + public void previous() { + displayMode.previousDate(startDate); + refresh(); + } + + public final void today() { + displayMode.firstDay(startDate, today, firstDayOfWeek); + refresh(); + } + + /** + * Retrieves the current start date of the calendar. + * + * @return the current start date of the calendar. + */ + public Date getStartDate() { + return startDate; + } + + public void addCalendar(Calendar calendar) { + calendars.add(calendar); + refresh(); + } + + public List getCalendars() { + return calendars; + } + + public void setCalendars(List calendars) { + // this.calendars = calendars; +// Window.alert("SET setCalendars"); +// for (Calendar calendar : calendars) { +// if (!(calendar.getIdentifier() instanceof ActivityCalendarIdentifier)) { +// if (calendar.getEvents() != null) { +// //SSS final Map> eventMap = normalize(calendar.getEvents()); +// final Map> eventMap = normalizeHourEvents(calendar.getEvents()); +// calendar.setEvents(eventMap); +// } +// } +// } + this.calendars = calendars; + refresh(); + } + + /** + * Defines the formatter used to display the title of the calendar.
+ *
+ * The default format is "MonthName FullYear " + * (pattern : "N y"). + * + * @param titleFormatter The formatter to use to display the title of the + * calendar. + */ + public void setTitleFormatter(DateTimeFormat titleFormatter) { + this.titleFormatter = titleFormatter; + refresh(); + } + + /** + * Defines the formatter used to display the title of each column.
+ *
+ * The default format is "WeekName" (pattern : "E"). + * + * @param headerFormatter The formatter to use to display the title of each + * column. + */ + public void setHeaderFormatter(DateTimeFormat headerFormatter) { + this.headerFormatter = headerFormatter; + refresh(); + } + + /** + * Defines the formatter used to display the title of each cell.
+ *
+ * The default format is "DayNumber" (pattern : "d"). + * + * @param dayFormatter The formatter to use to display the title of each + * cell. + */ + public void setDayFormatter(DateTimeFormat dayFormatter) { + this.dayFormatter = dayFormatter; + refresh(); + } + + /** + * Defines the display mode of the calendar and perform a redraw. + * + * @param displayMode Style of the calendar (day, week or month). + * @see CalendarWidget.DisplayMode + */ + public void setDisplayMode(DisplayMode displayMode) { + final FlexTable grid = (FlexTable) getWidget(); + + clear(); + + // Resetting the CSS style + grid.removeStyleName(this.displayMode.getStyleName()); + + this.displayMode = displayMode; + + // Applying the CSS style associated with the new display mode + grid.addStyleName(displayMode.getStyleName()); + refresh(); + } + + /** + * Defines the first day of the week and refresh the calendar. + * + * @param firstDayOfWeek The first day of the week as an int (Sunday = 0, + * Saturday = 6) + */ + public void setFirstDayOfWeek(int firstDayOfWeek) { + this.firstDayOfWeek = firstDayOfWeek; + refresh(); + } + + public int getDisplayHeaders() { + return displayHeaders; + } + + public void setDisplayHeaders(int displayHeaders) { + clear(); + this.displayHeaders = displayHeaders; + refresh(); + } + + public boolean isDisplayWeekNumber() { + return displayWeekNumber; + } + + public void setDisplayWeekNumber(boolean displayWeekNumber) { + clear(); + this.displayWeekNumber = displayWeekNumber; + refresh(); + } + + /** + * Removes all rows. Must be when the structure of the calendar has been + * changed (display mode) + */ + private void clear() { + final FlexTable grid = (FlexTable) getWidget(); + grid.clear(); + grid.removeAllRows(); + } + + /** + * @param date1 + * @param date2 + * @return boolean indicating if date1 and date2 are on the same day + */ + public static boolean isSameDay(Date date1, Date date2) { + DateTimeFormat fmt = DateTimeFormat.getFormat("yyyyMMdd"); + return fmt.format(date1).equals(fmt.format(date2)); + } + + /** + * Normalizes the given {@code calendar}'s events map (needed particularly + * when there is a timezone difference between the client and the server). + * + * @param calendar The calendar instance. + * @return The map with each event with the right key. + */ + //public static Map> normalize(final Calendar calendar) { + public static Map> normalize(final Map> eventMap) { + +// final Map> eventMap = calendar.getEvents(); + final Map> eventMapNormalized = new HashMap>(); + +// boolean isActivityCalendar = false; +// if (calendar.getIdentifier() instanceof ActivityCalendarIdentifier) { +// isActivityCalendar = true; +// } + for (final Date key : eventMap.keySet()) { + for (final Event event : eventMap.get(key)) { + Date normalizedKeyDate = new Date(key.getYear(), key.getMonth(), key.getDate()); + + // Activities events have different startDate from the key date + // They shouldn't be placed in their startDate list + //if (!isSameDay(normalizedKeyDate, event.getDtstart()) && !isActivityCalendar) { + if (!isSameDay(normalizedKeyDate, event.getDtstart())) { + normalizedKeyDate = new Date(event.getDtstart().getYear(), event.getDtstart().getMonth(), event.getDtstart().getDate()); + } + + if (eventMapNormalized.get(normalizedKeyDate) == null) { + eventMapNormalized.put(normalizedKeyDate, new ArrayList()); + } + eventMapNormalized.get(normalizedKeyDate).add(event); + } + } + + return eventMapNormalized; + } + + public static Map> normalizeHourEvents(final Map> eventMap) { + + final Map> hourEventMapNormalized = new HashMap>(); + + for (final Date key : eventMap.keySet()) { + for (final Event event : eventMap.get(key)) { + Date normalizedKeyDate = new Date(key.getYear(), key.getMonth(), key.getDate()); + if (!isSameDay(event.getDtstart(), event.getDtend())) { + // Window.alert("! isSameDay" + event.getSummary()); + // if (event.getDtstart() != event.getDtend()) { + //1 + int daysdiff = calculateEventDurationInDays(event); + for (int i = 0; i < daysdiff; i++) { + long StartTime = event.getDtstart().getTime() + (24 * 60 * 60 * 1000) * i; + long EndTime = event.getDtstart().getTime() + (24 * 60 * 60 * 1000) * i; + + Date StartDate = new Date(StartTime); + + Date EndDate = new Date(EndTime); + EndDate.setHours(event.getDtend().getHours()); + EndDate.setMinutes(event.getDtend().getMinutes()); + + Event theNewEv = new Event(); + theNewEv.setDtstart(StartDate); + theNewEv.setDtend(EndDate); +// theNewEv.setIdentifier(event.getIdentifier()); +// theNewEv.setReferenceId(event.getReferenceId()); +// theNewEv.setParent(event.getParent()); + theNewEv.setSummary(event.getSummary());// + "-S-" + i); + theNewEv.setDescription(event.getDescription());// + "-D-" + i); +// theNewEv.setEventType(event.getEventType()); + //////////// + if (!isSameDay(normalizedKeyDate, theNewEv.getDtstart())) { + normalizedKeyDate = new Date(theNewEv.getDtstart().getYear(), theNewEv.getDtstart().getMonth(), theNewEv.getDtstart().getDate()); + } + + if (hourEventMapNormalized.get(normalizedKeyDate) == null) { + hourEventMapNormalized.put(normalizedKeyDate, new ArrayList()); + } + event.setSummary(theNewEv.getSummary()); + event.setDescription(theNewEv.getDescription()); + if (!hourEventMapNormalized.get(normalizedKeyDate).contains(event)) { + hourEventMapNormalized.get(normalizedKeyDate).add(event); + } + // ------------- +// if (!isSameDay(normalizedKeyDate, theNewEv.getDtstart())) { +// normalizedKeyDate = new Date(theNewEv.getDtstart().getYear(), theNewEv.getDtstart().getMonth(), theNewEv.getDtstart().getDate()); +// } +// +// if (hourEventMapNormalized.get(normalizedKeyDate) == null) { +// hourEventMapNormalized.put(normalizedKeyDate, new ArrayList()); +// } +// hourEventMapNormalized.get(normalizedKeyDate).add(theNewEv); + + /////// + } + } else { + // Window.alert("THE SameDay " + event.getSummary()); + if (!isSameDay(normalizedKeyDate, event.getDtstart())) { + normalizedKeyDate = new Date(event.getDtstart().getYear(), event.getDtstart().getMonth(), event.getDtstart().getDate()); + } + + if (hourEventMapNormalized.get(normalizedKeyDate) == null) { + hourEventMapNormalized.put(normalizedKeyDate, new ArrayList()); + } + if (!hourEventMapNormalized.get(normalizedKeyDate).contains(event)) { + hourEventMapNormalized.get(normalizedKeyDate).add(event); + } + } + } + } + + return hourEventMapNormalized; + } + + /** + * Calculates the number of events that can be displayed in a cell. + */ + public void calibrateCalendar() { + final FlexTable grid = (FlexTable) getWidget(); + + final Element row = grid.getRowFormatter().getElement(displayHeaders); + row.setId("calendar-row-calibration"); + + final Element cell = grid.getCellFormatter().getElement(displayHeaders, displayWeekNumber ? 1 : 0); + cell.setId("calendar-cell-calibration"); +//ss +// cell.setPropertyString(DEBUG_ID_PREFIX, DEBUG_ID_PREFIX);setAttribute("hight", "40px"); + eventLimit = (getCellHeight(CELL_DEFAULT_HEIGHT) / EVENT_HEIGHT) - 2; + if (eventLimit < 0) { + eventLimit = 0; + } + + } + + /** + * Calculates the height of the cell identified by + * "calendar-cell-calibration". + * + * @return height of a cell. + */ + private native int getCellHeight(int defaultHeight) /*-{ var height = 0; if (!$wnd.getComputedStyle) @@ -486,12 +600,13 @@ private native int getCellHeight(int defaultHeight) /*-{ return height; }-*/; - /** - * Calculates the width of the cell identified by "calendar-cell-calibration". - * - * @return width of a cell. - */ - private native int getCellWidth(int defaultWidth) /*-{ + /** + * Calculates the width of the cell identified by + * "calendar-cell-calibration". + * + * @return width of a cell. + */ + private native int getCellWidth(int defaultWidth) /*-{ var width = 0; if (!$wnd.getComputedStyle) @@ -505,353 +620,1194 @@ private native int getCellWidth(int defaultWidth) /*-{ return width; }-*/; - /** - * Retrieves the current heading of the calendar. - * - * @return The heading value. - */ - public String getHeading() { - final String title = titleFormatter.format(startDate); - return Character.toUpperCase(title.charAt(0)) + title.substring(1); - } - - /** - * Render the calendar. - */ - public void refresh() { - drawEmptyCells(); - - if (isAttached()) { - calibrateCalendar(); - drawEvents(); - } - if (listener != null) - listener.afterRefresh(); - } - - /** - * Render the whole calendar but do not render the events. - */ - public void drawEmptyCells() { - final FlexTable grid = (FlexTable) getWidget(); - - final int rows = displayMode.getRows() + displayHeaders; - final int columns = displayMode.getColumns() + (displayWeekNumber ? 1 : 0); - - Date date = displayMode.getStartDate(startDate, firstDayOfWeek); - - // Column headers - if (displayHeaders != NO_HEADERS) { - if (displayHeaders == ALL_HEADERS) { - // Header of the calendar - final Label calendarHeader = new Label(getHeading()); - calendarHeader.addStyleName("calendar-header"); - grid.setWidget(0, 0, calendarHeader); - grid.getFlexCellFormatter().setColSpan(0, 0, columns + (displayWeekNumber ? 1 : 0)); - } - - final Date currentHeader = new Date(date.getTime()); - for (int x = displayWeekNumber ? 1 : 0; x < columns; x++) { - final Label columnHeader = new Label(headerFormatter.format(currentHeader)); - columnHeader.addStyleName("calendar-column-header"); - grid.setWidget(displayHeaders == ALL_HEADERS ? 1 : 0, x, columnHeader); - - currentHeader.setDate(currentHeader.getDate() + 1); - } - } - - int currentMonth = startDate.getMonth(); - for (int y = displayHeaders; y < rows; y++) { - if (displayWeekNumber) { - grid.getCellFormatter().addStyleName(y, 0, "calendar-row-header"); - grid.setText(y, 0, Integer.toString(getWeekNumber(date, firstDayOfWeek))); - } - - for (int x = displayWeekNumber ? 1 : 0; x < columns; x++) { - drawCell(y, x, date, currentMonth); - date.setDate(date.getDate() + 1); - } - } - } - - /** - * Render the events for every cells. - */ - public void drawEvents() { - final int rows = displayMode.getRows() + displayHeaders; - final int columns = displayMode.getColumns() + (displayWeekNumber ? 1 : 0); - - Date date = displayMode.getStartDate(startDate, firstDayOfWeek); - - for (int y = displayHeaders; y < rows; y++) { - for (int x = displayWeekNumber ? 1 : 0; x < columns; x++) { - drawEvents(y, x, date); - date.setDate(date.getDate() + 1); - } - } - } - - /** - * Render the cell located at column, row - * - * @param row - * @param column - * @param date - * @param currentMonth - */ - private void drawCell(int row, int column, Date date, int currentMonth) { - final Label header = new Label(dayFormatter.format(date)); - header.addStyleName("calendar-cell-header"); - - final FlexTable grid = (FlexTable) getWidget(); - - grid.getCellFormatter().setStyleName(row, column, "calendar-cell"); - - FlowPanel cell = (FlowPanel) grid.getWidget(row, column); - if (cell == null) { - // New cell - cell = new FlowPanel(); - cell.setWidth("100%"); - - grid.setWidget(row, column, cell); - - } else { - // Reusing an existing cell - cell.clear(); - } - - if (currentMonth != date.getMonth()) - grid.getCellFormatter().addStyleName(row, column, "calendar-cell-other-month"); - if (date.equals(today)) - grid.getCellFormatter().addStyleName(row, column, "calendar-cell-today"); - - cell.add(header); - } - - /** - * Display the events for the cell located at column, row - * - * @param row - * @param column - * @param date - * @param currentMonth - */ - private void drawEvents(int row, int column, final Date date) { - final FlexTable grid = (FlexTable) getWidget(); - - // final VerticalPanel cell = (VerticalPanel) grid.getWidget(row, - // column); - final FlowPanel cell = (FlowPanel) grid.getWidget(row, column); - - if (cell == null) - throw new NullPointerException("The specified cell (" + row + ',' + column + ") doesn't exist."); - - // Displaying events - final TreeSet sortedEvents = new TreeSet(new Comparator() { - - @Override - public int compare(Event o1, Event o2) { - int compare = 0; - - if (o1 == null && o2 == null) - return 0; - else if (o2 == null) - return 1; - else if (o1 == null) - return -1; - - if (compare == 0 && o1.getDtstart() != null && o2.getDtstart() != null) { - long o1Start = o1.getDtstart().getTime(); - long o2Start = o2.getDtstart().getTime(); - - if (o1Start < o2Start) - compare = -1; - else if (o1Start > o2Start) - compare = 1; - } - - if (compare == 0 && o1.getSummary() != null && o2.getSummary() != null) - compare = o1.getSummary().compareTo(o2.getSummary()); - - return compare; - } - }); - - for (final Calendar calendar : calendars) { - final Map> eventMap = normalize(calendar); - - final List events = eventMap.get(date); - - if (events != null) { - sortedEvents.addAll(events); - } - } - - final Iterator iterator = sortedEvents.iterator(); - for (int i = 0; iterator.hasNext() && i < eventLimit; i++) { - final Event event = iterator.next(); - - final ClickableFlowPanel flowPanel = new ClickableFlowPanel(); - flowPanel.addStyleName("calendar-event"); - - boolean fullDayEvent = false; - - final StringBuilder eventDate = new StringBuilder(); - eventDate.append(hourFormatter.format(event.getDtstart())); - if (event.getDtend() != null) { - eventDate.append(" "); - eventDate.append(hourFormatter.format(event.getDtend())); - - if (event.getDtstart().getDate() != event.getDtend().getDate() - || event.getDtstart().getMonth() != event.getDtend().getMonth() - || event.getDtstart().getYear() != event.getDtend().getYear()) { - fullDayEvent = true; - flowPanel.addStyleName("calendar-fullday-event"); - } - } - - final InlineLabel dateLabel = new InlineLabel(eventDate.toString()); - dateLabel.addStyleName("calendar-event-date"); - - final InlineLabel eventLabel = new InlineLabel(event.getSummary()); - eventLabel.addStyleName("calendar-event-label"); - - if (fullDayEvent) - flowPanel.addStyleName("calendar-fullday-event-" + event.getParent().getStyle()); - else - eventLabel.addStyleName("calendar-event-" + event.getParent().getStyle()); - - if (!fullDayEvent) - flowPanel.add(dateLabel); - flowPanel.add(eventLabel); - - final DecoratedPopupPanel detailPopup = new DecoratedPopupPanel(true); - - final Grid popupContent = new Grid(event.getParent().isEditable() ? 5 : 3, 1); - popupContent.setText(0, 0, event.getSummary()); - popupContent.getCellFormatter().addStyleName(0, 0, "calendar-popup-header"); - - if (!fullDayEvent) { - popupContent.getCellFormatter().addStyleName(1, 0, "calendar-popup-date"); - popupContent.getCellFormatter().addStyleName(1, 0, "calendar-event-" + event.getParent().getStyle()); - popupContent.setText(1, 0, eventDate.toString()); - } else - popupContent.setText(1, 0, ""); - - if (event.getDescription() != null && !"".equals(event.getDescription())) { - popupContent.getCellFormatter().addStyleName(2, 0, "calendar-popup-description"); - popupContent.setText(2, 0, event.getDescription()); - } else - popupContent.setText(2, 0, ""); - - if (event.getParent().isEditable() - && ProfileUtils.isGranted(authentication, GlobalPermissionEnum.EDIT_PROJECT_AGENDA)) { - - final Anchor editAnchor = new Anchor(I18N.CONSTANTS.calendarEditEvent()); - editAnchor.addClickHandler(new ClickHandler() { - - @Override - public void onClick(ClickEvent clickEvent) { - delegate.edit(event, CalendarWidget.this); - } - }); - - final Anchor deleteAnchor = new Anchor(I18N.CONSTANTS.calendarDeleteEvent()); - deleteAnchor.addClickHandler(new ClickHandler() { - - @Override - public void onClick(ClickEvent clickEvent) { - delegate.delete(event, CalendarWidget.this); - detailPopup.hide(); - } - }); - - popupContent.setWidget(3, 0, editAnchor); - popupContent.setWidget(4, 0, deleteAnchor); - } - - detailPopup.setWidget(popupContent); - - flowPanel.addClickHandler(new ClickHandler() { - - @Override - public void onClick(ClickEvent event) { - final int left = flowPanel.getAbsoluteLeft() - 10; - final int bottom = Window.getClientHeight() - flowPanel.getAbsoluteTop(); - - detailPopup.setWidth((getCellWidth(CELL_DEFAULT_WIDTH) + 20) + "px"); - - // Show the popup - detailPopup.setPopupPositionAndShow(new PositionCallback() { - - @Override - public void setPosition(int offsetWidth, int offsetHeight) { - detailPopup.getElement().getStyle().setPropertyPx("left", left); - detailPopup.getElement().getStyle().setProperty("top", ""); - detailPopup.getElement().getStyle().setPropertyPx("bottom", bottom); - } - }); - } - }); - - cell.add(flowPanel); - } - - if (eventLimit != UNDEFINED && sortedEvents.size() > eventLimit) { - final Anchor eventLabel = new Anchor("\u25BC"); - final Date thisDate = new Date(date.getTime()); - eventLabel.addClickHandler(new ClickHandler() { - - @Override - public void onClick(ClickEvent event) { - startDate = thisDate; - setDisplayMode(DisplayMode.WEEK); - } - }); - eventLabel.addStyleName("calendar-event-limit"); - cell.add(eventLabel); - } - } - - /** - * Returns the first date of the week that includes the given date. - * - * @param day - * A date - * @param firstDay - * The first day of the week (such as {@link #SUNDAY}, {@link #MONDAY} or anything else). - * @return The first date of the week that includes day, as a {@link Date}. - */ - private static Date getFirstDateOfWeek(Date day, int firstDay) { - final int decal = (day.getDay() + 7 - firstDay) % 7; - return new Date(day.getYear(), day.getMonth(), day.getDate() - decal); - } - - /** - * Calculates the number of the week that includes the given date. - * - * @param date - * A date - * @param firstDay - * The first day of the week (such as {@link #SUNDAY}, {@link #MONDAY} or anything else). - * @return The number of the week that includes date. - */ - private static int getWeekNumber(Date date, int firstDay) { - int daysToThursday = 4 - date.getDay(); - - if (date.getDay() < firstDay) - daysToThursday -= 7; - - final Date thursday = new Date(date.getYear(), date.getMonth(), date.getDate() + daysToThursday); - - final Date januaryFourth = new Date(thursday.getYear(), 0, 4); - final int daysToMonday = 1 - januaryFourth.getDay(); // Essayer avec le - // 1er jour de - // la - // semaine - final Date monday = new Date(thursday.getYear(), 0, 4 + daysToMonday); - - final double diff = Math.floor((thursday.getTime() - monday.getTime()) / (1000 * 60 * 60 * 24)); - return (int) Math.ceil(diff / 7.0); - } + /** + * Retrieves the current heading of the calendar. + * + * @return The heading value. + */ + public String getHeading() { + final String title = titleFormatter.format(startDate); + return Character.toUpperCase(title.charAt(0)) + title.substring(1); + } + + /** + * Render the calendar. + */ + public void refresh() { + final FlexTable grid = (FlexTable) getWidget(); + grid.removeAllRows(); + drawEmptyCells(); + + if (isAttached()) { + calibrateCalendar(); + drawEvents(); + } + if (listener != null) { + listener.afterRefresh(); + } + } + + /** + * Render the whole calendar but do not render the events. + */ + public void drawEmptyCells() { + final FlexTable grid = (FlexTable) getWidget(); + + final int rows = displayMode.getRows() + displayHeaders; + final int columns = displayMode.getColumns() + (displayWeekNumber ? 1 : 0); + + Date date = displayMode.getStartDate(startDate, firstDayOfWeek); + + // Column headers + if (displayHeaders != NO_HEADERS) { + if (displayHeaders == ALL_HEADERS) { + // Header of the calendar + final Label calendarHeader = new Label(getHeading()); + calendarHeader.addStyleName("calendar-header"); + grid.setWidget(0, 0, calendarHeader); + grid.getFlexCellFormatter().setColSpan(0, 0, columns + (displayWeekNumber ? 1 : 0)); + } + + final Date currentHeader = new Date(date.getTime()); + for (int x = displayWeekNumber ? 1 : 0; x < columns; x++) { + final Label columnHeader = new Label(headerFormatter.format(currentHeader)); + columnHeader.addStyleName("calendar-column-header"); + grid.setWidget(displayHeaders == ALL_HEADERS ? 1 : 0, x, columnHeader); + + currentHeader.setDate(currentHeader.getDate() + 1); + } + } + + int currentMonth = startDate.getMonth(); + for (int y = displayHeaders; y < rows; y++) { + if (displayWeekNumber) { + grid.getCellFormatter().addStyleName(y, 0, "calendar-row-header"); + grid.setText(y, 0, Integer.toString(getWeekNumber(date, firstDayOfWeek))); + } + + for (int x = displayWeekNumber ? 1 : 0; x < columns; x++) { + drawCell(y, x, date, currentMonth); + date.setDate(date.getDate() + 1); + } + } + } + + /** + * Render the events for every cells. + */ + public void drawEvents() { + final int rows = displayMode.getRows() + displayHeaders; + final int columns = displayMode.getColumns() + (displayWeekNumber ? 1 : 0); + + Date date = displayMode.getStartDate(startDate, firstDayOfWeek); + List alreadyShownWeekViewEvents = new ArrayList(); + int[][] theShiftVecorOfFullDayEvents = new int[8][10]; + + for (int y = displayHeaders; y < rows; y++) { + for (int x = displayWeekNumber ? 1 : 0; x < columns; x++) { + + if (displayMode.equals(displayMode.MONTH)) { + drawFullDayEvents(y, x, date); + drawHourMultiDayEvents(y, x, date); + drawEvents(y, x, date, -1); + } else { + drawFullDayEventsForWeek(1, x, date, alreadyShownWeekViewEvents, theShiftVecorOfFullDayEvents); + drawHourMultiDayEventsForWeek(1, x, date, alreadyShownWeekViewEvents, theShiftVecorOfFullDayEvents); + drawEvents(1, x, date, getLastFDPanelInCellCounter(theShiftVecorOfFullDayEvents, x)); + } + date.setDate(date.getDate() + 1); + } + if (displayMode.equals(displayMode.WEEK)) { + break; + } + } + } + + private int getLastFDPanelInCellCounter(int[][] theShiftVecorOfFullDayEvents, int theDayColumn) { + int theFDEventInColumnMaxlength = theShiftVecorOfFullDayEvents[theDayColumn].length; + int theLastFDEventInCellPosition = 0; + for (int position = theFDEventInColumnMaxlength; position >= 0; position--) { + if (theShiftVecorOfFullDayEvents[theDayColumn][position] > 0) { + theLastFDEventInCellPosition = position; + break; + } + } + return theLastFDEventInCellPosition; + } + + /** + * Render the cell located at column, row + * + * @param row + * @param column + * @param date + * @param currentMonth + */ + private void drawCell(int row, int column, Date date, int currentMonth) { + final Label header = new Label(dayFormatter.format(date)); + header.addStyleName("calendar-cell-header"); + + final FlexTable grid = (FlexTable) getWidget(); + + grid.getCellFormatter().setStyleName(row, column, "calendar-cell"); + + FlowPanel cell = (FlowPanel) grid.getWidget(row, column); + if (cell == null) { + cell = new FlowPanel(); + cell.setWidth("100%"); + + grid.setWidget(row, column, cell); + } else { + // Reusing an existing cell + cell.clear(); + } + + if (currentMonth != date.getMonth()) { + grid.getCellFormatter().addStyleName(row, column, "calendar-cell-other-month"); + } + if (date.equals(today)) { + grid.getCellFormatter().addStyleName(row, column, "calendar-cell-today"); + } + + cell.add(header); + } + + /** + * Display the events for the cell located at column, + * row + * + * @param row + * @param column + * @param date + * @param currentMonth + */ + private void drawEvents(int row, int column, final Date date, int startDrawPosition) { + final FlexTable grid = (FlexTable) getWidget(); + int fullDayEventCounter = 0; + int hourMultiDayEventCounter = 0; + + final FlowPanel cell = (FlowPanel) grid.getWidget(row, column); + + if (cell == null) { + throw new NullPointerException("The specified cell (" + row + ',' + column + ") doesn't exist."); + } + + // Displaying events + TreeSet sortedHourEvents = createSortedEventsSet(); + // Displaying multi day events + TreeSet sortedHourMultiDayEvents = createSortedEventsSet(); + // Displaying full day events + TreeSet sortedFullDayEvents = createSortedEventsSet(); + + for (final Calendar calendar : calendars) { + if (!(calendar.getIdentifier() instanceof ActivityCalendarIdentifier)) { + if (calendar.getEvents() != null) { + // && calendar.getEvents().size()>0) { + //SSS final Map> eventMap = normalize(calendar.getEvents()); + //ss + Map> eventMap = normalizeHourEvents(calendar.getEvents()); + // final Map> eventMap = normalize(eventMap2); + //final Map> eventMap = calendar.getEvents(); + + final List events = eventMap.get(date); + if (events != null) { + sortedHourEvents.addAll(events); + } + } + hourMultiDayEventCounter = getHourMulriDayEventCounter(calendar, date, hourMultiDayEventCounter, sortedHourMultiDayEvents); + fullDayEventCounter = getFullDayEventCounter(calendar, date, fullDayEventCounter, sortedFullDayEvents); + } + } + + final Iterator iterator = sortedHourEvents.iterator(); + if (startDrawPosition == -1) { + eventLimit = 1; + } else { + eventLimit = 99; + } + + for (int i = 0; iterator.hasNext() && i < eventLimit; i++) { + final Event event = iterator.next(); + + final ClickableFlowPanel flowPanel = new ClickableFlowPanel(); + flowPanel.addStyleName("calendar-event"); + + boolean fullDayEvent = false; + + final StringBuilder eventDate = new StringBuilder(); + eventDate.append(hourFormatter.format(event.getDtstart())); + if (event.getDtend() != null) { + eventDate.append(" "); + eventDate.append(hourFormatter.format(event.getDtend())); +//SS +// if (event.getDtstart().getDate() != event.getDtend().getDate() +// || event.getDtstart().getMonth() != event.getDtend().getMonth() +// || event.getDtstart().getYear() != event.getDtend().getYear()) { + if (event.getEventType().contains("F")) { + fullDayEvent = true; + flowPanel.addStyleName("calendar-fullday-event"); + } + } + + final InlineLabel dateLabel = new InlineLabel(eventDate.toString()); + dateLabel.addStyleName("calendar-event-date"); + + //final InlineLabel eventLabel = new InlineLabel(event.getReferenceId()==null?event.getSummary():"--->>"); + // final InlineLabel eventLabel = new InlineLabel(row + "; " + (!(event.getReferenceId() != null && event.getReferenceId().intValue() > 0)? event.getSummary() : event.getSummary() + "->>serial")); + final InlineLabel eventLabel = new InlineLabel(event.getSummary()); + eventLabel.addStyleName("calendar-event-label"); + + if (fullDayEvent) { + flowPanel.addStyleName("calendar-fullday-event-" + event.getParent().getStyle()); + } else { + eventLabel.addStyleName("calendar-event-" + event.getParent().getStyle()); + } + + if (!fullDayEvent) { + flowPanel.add(dateLabel); + + int daysdiff = calculateEventDurationInDays(event); + + flowPanel.setTitle(createTitleForHourEvent(daysdiff, event)); + } + flowPanel.add(eventLabel); + if (event.getEventType().contains("H")) { + DOM.setStyleAttribute(flowPanel.getElement(), "background-color", "rgba(28,97,217)"); + // DOM.setStyleAttribute(flowPanel.getElement(), "background", "linear-gradient(-90deg, #1c61d9, #0000)"); + } + final DecoratedPopupPanel detailPopup = new DecoratedPopupPanel(true); + + final Grid popupContent = new Grid(event.getParent().isEditable() ? 6 : 3, 1); + popupContent.setText(0, 0, event.getSummary()); + popupContent.getCellFormatter().addStyleName(0, 0, "calendar-popup-header"); + + if (!fullDayEvent) { + popupContent.getCellFormatter().addStyleName(1, 0, "calendar-popup-date"); + popupContent.getCellFormatter().addStyleName(1, 0, "calendar-event-" + event.getParent().getStyle()); + popupContent.setText(1, 0, eventDate.toString()); + } else { + popupContent.setText(1, 0, ""); + } + + if (event.getDescription() != null && !"".equals(event.getDescription())) { + popupContent.getCellFormatter().addStyleName(2, 0, "calendar-popup-description"); + popupContent.setText(2, 0, event.getDescription()); + } else { + popupContent.setText(2, 0, ""); + } + + if (event.getParent().isEditable() + && ProfileUtils.isGranted(authentication, GlobalPermissionEnum.EDIT_PROJECT_AGENDA)) { + + final Anchor editAnchor = new Anchor(I18N.CONSTANTS.calendarEditEvent()); + editAnchor.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent clickEvent) { + delegate.edit(event, CalendarWidget.this); + } + }); + + final Anchor deleteAnchor = new Anchor(I18N.CONSTANTS.calendarDeleteEvent()); + deleteAnchor.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent clickEvent) { + delegate.delete(event, CalendarWidget.this); + detailPopup.hide(); + } + }); + + final Anchor deleteChainAnchor = new Anchor("Delete all recurrences"); + deleteChainAnchor.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent clickEvent) { + delegate.deleteChain(event, CalendarWidget.this); + refresh(); + detailPopup.hide(); + + } + }); + + popupContent.setWidget(3, 0, editAnchor); + popupContent.setWidget(4, 0, deleteAnchor); + if (!event.getEventType().contains("O")) { + popupContent.setWidget(5, 0, deleteChainAnchor); + } + } + + detailPopup.setWidget(popupContent); + + flowPanel.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + final int left = flowPanel.getAbsoluteLeft() - 10; + final int bottom = Window.getClientHeight() - flowPanel.getAbsoluteTop(); + + detailPopup.setWidth((getCellWidth(CELL_DEFAULT_WIDTH) + 20) + "px"); + + // Show the popup + detailPopup.setPopupPositionAndShow(new PositionCallback() { + + @Override + public void setPosition(int offsetWidth, int offsetHeight) { + detailPopup.getElement().getStyle().setPropertyPx("left", left); + detailPopup.getElement().getStyle().setProperty("top", ""); + detailPopup.getElement().getStyle().setPropertyPx("bottom", bottom); + } + }); + } + }); + + if (startDrawPosition != -1) { + int height = 12; + int top = startDrawPosition > 0 ? (startDrawPosition - 1) * height : 0; + DOM.setStyleAttribute(flowPanel.getElement(), "position", "relative"); + DOM.setStyleAttribute(flowPanel.getElement(), "top", top + "px"); + // startDrawPosition ++; + } + cell.add(flowPanel); + } + + // if (eventLimit != UNDEFINED && (fullDayEventCounter + sortedHourEvents.size()) > eventLimit) { + if (startDrawPosition == -1 && eventLimit != UNDEFINED && (hourMultiDayEventCounter + fullDayEventCounter + sortedHourEvents.size()) > 1) { + //final Anchor eventLabel = new Anchor("\u25BC +" + (sortedHourEvents.size()-eventLimit) + " st:" + fullDayEventCounter +" fd events"); + final Anchor eventLabel = new Anchor("\u25BC " + (sortedHourEvents.size() + hourMultiDayEventCounter + fullDayEventCounter) + " events"); + // eventLabel.setTitle("Click to view all events of the day."); + final Date thisDate = new Date(date.getTime()); + String theDateString = DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.YEAR_MONTH_WEEKDAY_DAY).format(thisDate); + eventLabel.setTitle(theDateString + "\nClick to view all events of the day:" + + "\nOne day events: " + sortedHourEvents.size() + + "\nMulti day events: " + hourMultiDayEventCounter + + "\nFull day events: " + fullDayEventCounter); + + eventLabel.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + startDate = thisDate; + setDisplayMode(DisplayMode.WEEK); + } + }); + eventLabel.addStyleName("calendar-event-limit"); + DOM.setStyleAttribute(eventLabel.getElement(), "border-color", "#1c61d9"); + DOM.setStyleAttribute(eventLabel.getElement(), "border-style", "solid"); + DOM.setStyleAttribute(eventLabel.getElement(), "border-width", "1px"); + +// if (fullDayEventCounter > 0 +// +// +// sortedHourEvents.size() //-- DOM.setStyleAttribute(eventLabel.getElement(), "position", "relative"); + // DOM.setStyleAttribute(eventLabel.getElement(), "top", (cell.getOffsetHeight()-16) + "px"); + //-- DOM.setStyleAttribute(eventLabel.getElement(), "top", (cell.getAbsoluteTop() + 30) + "px"); + // Window.alert(cell.getTitle() + " cell.getOffsetHeight()="+cell.getOffsetHeight() + // + " - " + " cell.getAbsoluteTop())=" + cell.getAbsoluteTop() + // + " Label OffsetHeight = " + eventLabel.getElement().getOffsetHeight()+ + // " cell.getElement() OffsetHeight =" + cell.getElement().getOffsetHeight()+ + // " cell.getElement() AbsoluteBottom=" + cell.getElement().getAbsoluteBottom()+ + // " cell.getElement() ClientHeight =" + cell.getElement().getClientHeight() + // ) ; +/* int chiled = grid.getCellFormatter().getElement(row, column).getChildCount(); + + int gridHeight = grid.getOffsetHeight(); + int weekdayRowHeight = grid.getRowFormatter() + .getElement(0).getOffsetHeight(); + */ +// Window.alert("chiled=" + chiled + " gridHeight =" + gridHeight +// + " weekdayRowHeight =" + weekdayRowHeight +// ); + cell.add(eventLabel); + } + } + + private int getHourMulriDayEventCounter(final Calendar calendar, final Date date, int hourMultiDayEventCounter, TreeSet sortedHourMultiDayEvents) { + //hourMultiDayEventCounter + if (calendar.getHourMultiDayEvents() != null) { + final Map> hourMultiDayEventMap = normalize(calendar.getHourMultiDayEvents()); + for (Map.Entry> entry : hourMultiDayEventMap.entrySet()) { + Date key = entry.getKey(); + List value = entry.getValue(); + for (Iterator iterator = value.iterator(); iterator.hasNext();) { + Event next = iterator.next(); +// Date theStartEventDate = next.getDtstart(); +// Date theEndEventDate = next.getDtend(); + + Date theStartEventDateWithTime = next.getDtstart(); + Date theEndEventDateWithTime = next.getDtend(); + + Date theStartEventDate = new Date(date.getTime()); + Date theEndEventDate = new Date(date.getTime()); + + theStartEventDate.setYear(theStartEventDateWithTime.getYear()); + theStartEventDate.setMonth(theStartEventDateWithTime.getMonth()); + theStartEventDate.setDate(theStartEventDateWithTime.getDate()); + + theEndEventDate.setYear(theEndEventDateWithTime.getYear()); + theEndEventDate.setMonth(theEndEventDateWithTime.getMonth()); + theEndEventDate.setDate(theEndEventDateWithTime.getDate()); +//<---- + + if (next.getEventType().contains("H") + && date.after(theStartEventDate) && date.before(theEndEventDate) + || date.equals(theStartEventDate) + || date.equals(theEndEventDate)) { + hourMultiDayEventCounter++; + } + } + } + final List fullDayEvents = hourMultiDayEventMap.get(date); + if (fullDayEvents != null) { + sortedHourMultiDayEvents.addAll(fullDayEvents); + } + } + return hourMultiDayEventCounter; + } + + private int getFullDayEventCounter(final Calendar calendar, final Date date, int fullDayEventCounter, TreeSet sortedFullDayEvents) { + if (calendar.getFullDayEvents() != null) { + final Map> fullDayEventMap = normalize(calendar.getFullDayEvents()); + for (Map.Entry> entry : fullDayEventMap.entrySet()) { + Date key = entry.getKey(); + List value = entry.getValue(); + for (Iterator iterator = value.iterator(); iterator.hasNext();) { + Event next = iterator.next(); + Date theStartEventDate = next.getDtstart(); + Date theEndEventDate = next.getDtend(); + if (next.getEventType().contains("F") + && date.after(theStartEventDate) && date.before(theEndEventDate) + || date.equals(theStartEventDate) + || date.equals(theEndEventDate)) { + fullDayEventCounter++; + } + } + + } + final List fullDayEvents = fullDayEventMap.get(date); + if (fullDayEvents != null) { + sortedFullDayEvents.addAll(fullDayEvents); + } + } + return fullDayEventCounter; + } + + private static int calculateEventDurationInDays(final Event event) { + long diff = event.getDtend().getTime() - event.getDtstart().getTime(); + long diffDays = diff / (24 * 60 * 60 * 1000) + 1; + int daysdiff = (int) diffDays; + return daysdiff; + } + + /** + * Returns the first date of the week that includes the given date. + * + * @param day A date + * @param firstDay The first day of the week (such as + * {@link #SUNDAY}, {@link #MONDAY} or anything else). + * @return The first date of the week that includes day, as a + * {@link Date}. + */ + private static Date getFirstDateOfWeek(Date day, int firstDay) { + final int decal = (day.getDay() + DAYS_IN_A_WEEK - firstDay) % DAYS_IN_A_WEEK; + return new Date(day.getYear(), day.getMonth(), day.getDate() - decal); + } + + /** + * Calculates the number of the week that includes the given date. + * + * @param date A date + * @param firstDay The first day of the week (such as + * {@link #SUNDAY}, {@link #MONDAY} or anything else). + * @return The number of the week that includes date. + */ + private static int getWeekNumber(Date date, int firstDay) { + int daysToThursday = 4 - date.getDay(); + + if (date.getDay() < firstDay) { + daysToThursday -= DAYS_IN_A_WEEK; + } + + final Date thursday = new Date(date.getYear(), date.getMonth(), date.getDate() + daysToThursday); + + final Date januaryFourth = new Date(thursday.getYear(), 0, 4); + final int daysToMonday = 1 - januaryFourth.getDay(); // Essayer avec le + // 1er jour de + // la + // semaine + final Date monday = new Date(thursday.getYear(), 0, 4 + daysToMonday); + + final double diff = Math.floor((thursday.getTime() - monday.getTime()) / (1000 * 60 * 60 * 24)); + return (int) Math.ceil(diff / 7.0); + } + + private void placeItemInGridMonth(Widget panel, int colStart, int colEnd, + int row, int cellPosition) { + final FlexTable grid = (FlexTable) getWidget(); + // FlowPanel cell = (FlowPanel) grid.getWidget(1, 1); + FlowPanel cell = (FlowPanel) grid.getWidget(row, colStart); + cell.add(panel); + calculatedCellOffsetHeight = cell.getElement().getClientHeight();//OffsetHeight(); + + int height = appointmentHeight(); + height = 12; + //float width = ((float) (colEnd - colStart) / (float) DAYS_IN_A_WEEK) * 100f - 1f; + float width = (colEnd - colStart) * 100f; + + float top = 0; + + cell = (FlowPanel) grid.getWidget(row, colStart); + + setFullDayEventStyle(panel, top, width, height); + } + + private static int appointmentPaddingTop() { + return 1 + (Math.abs(FormattingUtil.getBorderOffset()) * 3); + } + + private static int appointmentHeight() { + // TODO: calculate appointment height dynamically + return 12; + } + + /** + * Display full day events with started date + * + * @param row + * @param column + * @param date + */ + private void drawFullDayEvents(int row, int column, final Date date) { + + TreeSet sortedFullDayEvents = createSortedEventsSet(); + + for (final Calendar calendar : calendars) { + if (!(calendar.getIdentifier() instanceof ActivityCalendarIdentifier) + && calendar.getFullDayEvents() != null) { + final Map> fullDayEventMap = normalize(calendar.getFullDayEvents()); + final List fullDayEvents = fullDayEventMap.get(date); + if (fullDayEvents != null) { + sortedFullDayEvents.addAll(fullDayEvents); + } + } + } + + final Iterator iterator = sortedFullDayEvents.iterator(); + + eventLimit = 1;//999 + for (int i = 0; iterator.hasNext() && i < eventLimit; i++) { + final Event event = iterator.next(); + final ClickableFlowPanel flowPanelFullDayFirst = createFullDayPanel(event); + final ClickableFlowPanel flowPanelFullDayContinue = createFullDayPanel(event); + final FlexTable grid = (FlexTable) getWidget(); + int daysdiff = calculateEventDurationInDays(event); + + //String theDateString = DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.YEAR_MONTH_WEEKDAY_DAY).format(thisDate); + flowPanelFullDayFirst.setTitle(createTitleForFullDayEvent(daysdiff, event)); + + if (column + daysdiff - 1 < 8) { + placeItemInGridMonth(flowPanelFullDayFirst, column, column + daysdiff, row, i); + } else { + placeItemInGridMonth(flowPanelFullDayFirst, column, 8, row, i); + if (row <= 5) { + flowPanelFullDayContinue.setTitle(createTitleForFullDayEvent(daysdiff, event)); + placeItemInGridMonth(flowPanelFullDayContinue, 1, 1 + daysdiff - (8 - column), row + 1, i); + } + } + } + } + + /** + * Display full day events with started date + * + * @param row + * @param column + * @param date + */ + private void drawHourMultiDayEvents(int row, int column, final Date date) { + + TreeSet sortedFullDayEvents = createSortedEventsSet(); + + for (final Calendar calendar : calendars) { + if (!(calendar.getIdentifier() instanceof ActivityCalendarIdentifier) + && calendar.getFullDayEvents() != null) { + final Map> fullDayEventMap = normalize(calendar.getHourMultiDayEvents());//EE + final List fullDayEvents = fullDayEventMap.get(date); + if (fullDayEvents != null) { + sortedFullDayEvents.addAll(fullDayEvents); + } + } + } + + final Iterator iterator = sortedFullDayEvents.iterator(); + + eventLimit = 1;//999 + for (int i = 0; iterator.hasNext() && i < eventLimit; i++) { + final Event event = iterator.next(); + final ClickableFlowPanel flowPanelFullDayFirst = createFullDayPanel(event); + final ClickableFlowPanel flowPanelFullDayContinue = createFullDayPanel(event); + final FlexTable grid = (FlexTable) getWidget(); + int daysdiff = calculateEventDurationInDays(event); + + //String theDateString = DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.YEAR_MONTH_WEEKDAY_DAY).format(thisDate); + flowPanelFullDayFirst.setTitle(createTitleForHourMultiDayEvent(daysdiff, event));//EE3 + DOM.setStyleAttribute(flowPanelFullDayFirst.getElement(), "background-color", "rgba(28,97,217)"); + DOM.setStyleAttribute(flowPanelFullDayFirst.getElement(), "background", "linear-gradient(-90deg, #1c61d9, #0000)"); + if (column + daysdiff - 1 < 8) { + placeItemInGridMonth(flowPanelFullDayFirst, column, column + daysdiff, row, i); + } else { + placeItemInGridMonth(flowPanelFullDayFirst, column, 8, row, i); + if (row <= 5) { + flowPanelFullDayContinue.setTitle(createTitleForHourMultiDayEvent(daysdiff, event));//EE2 + DOM.setStyleAttribute(flowPanelFullDayContinue.getElement(), "background-color", "rgba(28,97,217)"); + DOM.setStyleAttribute(flowPanelFullDayContinue.getElement(), "background", "linear-gradient(-90deg, #1c61d9, #0000)"); + placeItemInGridMonth(flowPanelFullDayContinue, 1, 1 + daysdiff - (8 - column), row + 1, i); + } + } + } + } + + private static String createTitleForFullDayEvent(int daysdiff, final Event event) { + return "Event: " + event.getSummary() + + "\nDescr: " + (event.getDescription() != null ? event.getDescription() : "") + + "\nDuration: " + daysdiff + " full day" + (daysdiff > 1 ? "s." : ".") + + (event.getDtstart().equals(event.getDtend()) + ? (DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.YEAR_MONTH_WEEKDAY_DAY).format(event.getDtstart())) + : ("\nFrom " + DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.YEAR_MONTH_WEEKDAY_DAY).format(event.getDtstart()) + + " To " + DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.YEAR_MONTH_WEEKDAY_DAY).format(event.getDtend()))); + } + + private static String createTitleForHourMultiDayEvent(int daysdiff, final Event event) { + return "Event: " + event.getSummary() + + "\nDescr: " + (event.getDescription() != null ? event.getDescription() : "") + + "\nDuration: " + daysdiff + " day" + (daysdiff > 1 ? "s." : ".") + + (event.getDtstart().equals(event.getDtend()) + ? (DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.YEAR_MONTH_WEEKDAY_DAY).format(event.getDtstart())) + : ("\nFrom " + DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.YEAR_MONTH_WEEKDAY_DAY).format(event.getDtstart()) + + " " + DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.HOUR24_MINUTE).format(event.getDtstart()) + + " \nTo " + DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.YEAR_MONTH_WEEKDAY_DAY).format(event.getDtend()) + + " " + DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.HOUR24_MINUTE).format(event.getDtend()))); + } + + /** + * + * @param daysdiff the value of daysdiff + * @param event the value of event + * @return the java.lang.String + */ + private String createTitleForHourEvent(int daysdiff, final Event event) { + String duration = hourFormatter.format(new Date(event.getDtend().getTime() - event.getDtstart().getTime())); + long millis = event.getDtend().getTime() - event.getDtstart().getTime(); + long minute = (millis / (1000 * 60)) % 60; + long hour = (millis / (1000 * 60 * 60)) % 24; + return "Hour Event: " + event.getSummary() + + "\nDescr: " + (event.getDescription() != null ? event.getDescription() : "") + + "\nDuration: from " + hourFormatter.format(event.getDtstart()) + + " to " + hourFormatter.format(event.getDtend()) + // + " (" + duration + " hours" + (daysdiff > 0 ? " every day)" : ")") + + " (" + (hour > 0 ? (hour + " hours ") : "") + + (minute > 0 ? (minute + " minutes") : "") + (daysdiff > 1 ? " every day)" : ") ") + + (daysdiff > 1 ? (daysdiff + " days in row. ") : " ") + + (isSameDay(event.getDtstart(), event.getDtend()) + ? (DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.YEAR_MONTH_WEEKDAY_DAY).format(event.getDtstart())) + : ("\nFrom " + DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.YEAR_MONTH_WEEKDAY_DAY).format(event.getDtstart()) + + " to " + DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.YEAR_MONTH_WEEKDAY_DAY).format(event.getDtend()))); + } + + /** + * @param event + * @return + */ + private ClickableFlowPanel createFullDayPanel(final Event event) { + final ClickableFlowPanel flowPanel = new ClickableFlowPanel(); + flowPanel.addStyleName("calendar-event"); + + boolean fullDayEvent = false; + + final StringBuilder eventDate = new StringBuilder(); + eventDate.append(hourFormatter.format(event.getDtstart())); + if (event.getDtend() != null) { + eventDate.append(" "); + eventDate.append(hourFormatter.format(event.getDtend())); + fullDayEvent = true; + flowPanel.addStyleName("calendar-fullday-event"); + } + + final InlineLabel dateLabel = new InlineLabel(eventDate.toString()); + dateLabel.addStyleName("calendar-event-date"); + + final InlineLabel eventLabel = new InlineLabel(event.getEventType().contains("H") ? (hourFormatter.format(event.getDtstart()) + " " + event.getSummary()) : event.getSummary()); + //final InlineLabel eventLabel = new InlineLabel(event.getDtstart().getDate() + "; " + (event.getReferenceId()==null?event.getSummary():event.getSummary()) + "+>>"); + eventLabel.addStyleName("calendar-event-label"); + + if (fullDayEvent) { + flowPanel.addStyleName("calendar-fullday-event-" + event.getParent().getStyle()); + } else { + eventLabel.addStyleName("calendar-event-" + event.getParent().getStyle()); + } + + if (!fullDayEvent) { + flowPanel.add(dateLabel); + } + flowPanel.add(eventLabel);//ak + //flowPanel.setTitle(event.getSummary()); + + final DecoratedPopupPanel detailPopup = new DecoratedPopupPanel(true); + + final Grid popupContent = new Grid(event.getParent().isEditable() ? 6 : 3, 1); + popupContent.setText(0, 0, event.getSummary()); + popupContent.getCellFormatter().addStyleName(0, 0, "calendar-popup-header"); + + if (!fullDayEvent) { + popupContent.getCellFormatter().addStyleName(1, 0, "calendar-popup-date"); + popupContent.getCellFormatter().addStyleName(1, 0, "calendar-event-" + event.getParent().getStyle()); + popupContent.setText(1, 0, eventDate.toString()); + } else { + popupContent.setText(1, 0, ""); + } + + if (event.getDescription() != null && !"".equals(event.getDescription())) { + popupContent.getCellFormatter().addStyleName(2, 0, "calendar-popup-description"); + popupContent.setText(2, 0, event.getDescription()); + } else { + popupContent.setText(2, 0, ""); + } + + if (event.getParent().isEditable() + && ProfileUtils.isGranted(authentication, GlobalPermissionEnum.EDIT_PROJECT_AGENDA)) { + + final Anchor editAnchor = new Anchor(I18N.CONSTANTS.calendarEditEvent()); + editAnchor.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent clickEvent) { + delegate.edit(event, CalendarWidget.this); + } + }); + + final Anchor deleteAnchor = new Anchor(I18N.CONSTANTS.calendarDeleteEvent()); + deleteAnchor.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent clickEvent) { + delegate.delete(event, CalendarWidget.this); + refresh(); + detailPopup.hide(); + } + }); + + final Anchor deleteChainAnchor = new Anchor("Delete all recurrences"); + deleteChainAnchor.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent clickEvent) { + delegate.deleteChain(event, CalendarWidget.this); + refresh(); + detailPopup.hide(); + + } + }); + + popupContent.setWidget(3, 0, editAnchor); + popupContent.setWidget(4, 0, deleteAnchor); + if (!event.getEventType().contains("O")) { + popupContent.setWidget(5, 0, deleteChainAnchor); + } + } + + detailPopup.setWidget(popupContent); + + flowPanel.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + final int left = flowPanel.getAbsoluteLeft() - 10; + final int bottom = Window.getClientHeight() - flowPanel.getAbsoluteTop(); + + detailPopup.setWidth((getCellWidth(CELL_DEFAULT_WIDTH) + 20) + "px"); + + // Show the popup + detailPopup.setPopupPositionAndShow(new PositionCallback() { + + @Override + public void setPosition(int offsetWidth, int offsetHeight) { + detailPopup.getElement().getStyle().setPropertyPx("left", left); + detailPopup.getElement().getStyle().setProperty("top", ""); + detailPopup.getElement().getStyle().setPropertyPx("bottom", bottom); + } + }); + } + }); + return flowPanel; + } + + /** + * Calculates the height of each day cell in the Month grid. It excludes the + * height of each day's header, as well as the overall header that shows the + * weekday labels. + */ +// private void calculateCellHeight() { +// +// int gridHeight = monthCalendarGrid.getOffsetHeight(); +// int weekdayRowHeight = monthCalendarGrid.getRowFormatter() +// .getElement(0).getOffsetHeight(); +// int dayHeaderHeight = dayLabels.get(0).getOffsetHeight(); +// +// calculatedCellOffsetHeight = (float) (gridHeight - weekdayRowHeight) +// / monthViewRequiredRows; +// calculatedCellHeight = calculatedCellOffsetHeight - dayHeaderHeight; +// calculatedWeekDayHeaderHeight = weekdayRowHeight; +// calculatedDayHeaderHeight = dayHeaderHeight; +// } + private TreeSet createSortedEventsSet() { + + final TreeSet sortedEvents = new TreeSet(new Comparator() { + + @Override + public int compare(Event o1, Event o2) { + int compare = 0; + + if (o1 == null && o2 == null) { + return 0; + } else if (o2 == null) { + return 1; + } else if (o1 == null) { + return -1; + } + + if (compare == 0 && o1.getDtstart() != null && o2.getDtstart() != null) { + long o1Start = o1.getDtstart().getTime(); + long o2Start = o2.getDtstart().getTime(); + + if (o1Start < o2Start) { + compare = -1; + } else if (o1Start > o2Start) { + compare = 1; + } + } + + if (compare == 0 && o1.getSummary() != null && o2.getSummary() != null) { + compare = o1.getSummary().compareTo(o2.getSummary()); + } + + return compare; + } + }); + return sortedEvents; + } + + /** + * Display full day events with started date + * + * @param row + * @param column + * @param date + */ + private void drawFullDayEventsForWeek(int row, int column, final Date date, + List alreadyShownWeekViewEvents, + int[][] theShiftVecorOfFullDayEvents) { + + int theLastFDPanelInCellCounter = getLastFDPanelInCellCounter(theShiftVecorOfFullDayEvents, column); + // Window.alert("START column = " + column + "; theLastFullRaw =" + theLastFDPanelInCellCounter); + TreeSet sortedFullDayEvents = createSortedEventsSet(); + int eventCounter = 0; + int longFullDayEventShownCounter = 0; + + for (final Calendar calendar : calendars) { + if (!(calendar.getIdentifier() instanceof ActivityCalendarIdentifier)) { + if (calendar.getFullDayEvents() != null) { + final Map> fullDayEventMap = normalize(calendar.getFullDayEvents()); + for (Map.Entry> entry : fullDayEventMap.entrySet()) { + Date key = entry.getKey(); + List value = entry.getValue(); + for (Iterator iterator = value.iterator(); iterator.hasNext();) { + Event next = iterator.next(); + if (next.getEventType().contains("F")) { + if (!alreadyShownWeekViewEvents.contains(next)) { + Date theStartEventDate = next.getDtstart(); + Date theEndEventDate = next.getDtend(); + if (date.after(theStartEventDate) && date.before(theEndEventDate) + || date.equals(theStartEventDate) + || date.equals(theEndEventDate)) { + // In between + eventCounter++; + sortedFullDayEvents.add(next); + alreadyShownWeekViewEvents.add(next); + } + } else { + Date theStartEventDate = next.getDtstart(); + Date theEndEventDate = next.getDtend(); + if (date.after(theStartEventDate) && date.before(theEndEventDate) + || date.equals(theStartEventDate) + || date.equals(theEndEventDate)) { + + longFullDayEventShownCounter++; +// sortedEvents.add(next); +// alreadyShownWeekViewEvents.add(next); + } + } + } + } + } + } + } + } + + final Iterator iterator = sortedFullDayEvents.iterator(); + + int eventLimit = 100;//999 + int counterIvent = 0; + boolean foundRowToPlace = false; + int theRowToPlace = 0; + int last = theLastFDPanelInCellCounter; + for (int i = 0; iterator.hasNext() && i < eventLimit; i++) { + last = last + 1; + final Event event = iterator.next(); + + final ClickableFlowPanel fullDayFlowPanel = createFullDayPanel(event); + final FlexTable grid = (FlexTable) getWidget(); + ///ssss1 grid.setWidget(row, column, flowPanelFullDayFirst); + // RootPanel.get().add(flowPanelFullDayFirst); + // grid.add(flowPanelFullDayFirst); + + Date theStartEventDate = event.getDtstart(); + long startDTForWeekleView = 0; + long diff = event.getDtend().getTime() - event.getDtstart().getTime(); + if (date.after(theStartEventDate)) { + //diff = theStartEventDate.getTime() - event.getDtstart().getTime(); + diff = event.getDtend().getTime() - date.getTime(); + } + + long diffDays = diff / (24 * 60 * 60 * 1000) + 1; + int daysdiff = (int) diffDays; + + fullDayFlowPanel.setTitle(createTitleForFullDayEvent(daysdiff, event)); + //to show full day long event if it longer then 1 week + while (column + daysdiff - 1 >= 8) { + daysdiff--; + } + + if (column + daysdiff - 1 < 8) { + for (int day = column; day < column + daysdiff; day++) { + theShiftVecorOfFullDayEvents[day][last] += 1; + } + longFullDayEventShownCounter = theRowToPlace;// + counterIvent; + + int theLastFullDayLinePlace44 = getLastFDPanelInCellCounter(theShiftVecorOfFullDayEvents, column); + + placeItemInGridWeek(fullDayFlowPanel, column, column + daysdiff, counterIvent, theLastFDPanelInCellCounter); + + } + counterIvent++; + } + + } + + /////////////// + /** + * Display full day events with started date + * + * @param row + * @param column + * @param date + */ + private void drawHourMultiDayEventsForWeek(int row, int column, final Date date, + List alreadyShownWeekViewEvents, + int[][] theShiftVecorOfFullDayEvents) { + + int theLastFDPanelInCellCounter = getLastFDPanelInCellCounter(theShiftVecorOfFullDayEvents, column); + // Window.alert("START column = " + column + "; theLastFullRaw =" + theLastFDPanelInCellCounter); + TreeSet sortedFullDayEvents = createSortedEventsSet(); + int eventCounter = 0; + int longFullDayEventShownCounter = 0; + + for (final Calendar calendar : calendars) { + if (!(calendar.getIdentifier() instanceof ActivityCalendarIdentifier)) { + if (calendar.getFullDayEvents() != null) { + //final Map> fullDayEventMap = normalize(calendar.getHourMultiDayEvents());//EEE + final Map> fullDayEventMap = normalizeHourEvents(calendar.getHourMultiDayEvents()); + for (Map.Entry> entry : fullDayEventMap.entrySet()) { + Date key = entry.getKey(); + List value = entry.getValue(); + for (Iterator iterator = value.iterator(); iterator.hasNext();) { + Event next = iterator.next(); + ///----> + Date theStartEventDateWithTime = next.getDtstart(); + Date theEndEventDateWithTime = next.getDtend(); + + Date theStartEventDate = new Date(date.getTime()); + Date theEndEventDate = new Date(date.getTime()); + + theStartEventDate.setYear(theStartEventDateWithTime.getYear()); + theStartEventDate.setMonth(theStartEventDateWithTime.getMonth()); + theStartEventDate.setDate(theStartEventDateWithTime.getDate()); + + theEndEventDate.setYear(theEndEventDateWithTime.getYear()); + theEndEventDate.setMonth(theEndEventDateWithTime.getMonth()); + theEndEventDate.setDate(theEndEventDateWithTime.getDate()); + //<---- + if (next.getEventType().contains("H")) { + if (!alreadyShownWeekViewEvents.contains(next)) { +// Date theStartEventDate = next.getDtstart(); +// Date theEndEventDate = next.getDtend(); + if (date.after(theStartEventDate) && date.before(theEndEventDate) + || date.equals(theStartEventDate) + || date.equals(theEndEventDate)) { + // In between + eventCounter++; + sortedFullDayEvents.add(next); + alreadyShownWeekViewEvents.add(next); + } + } else { +// Date theStartEventDate = next.getDtstart(); +// Date theEndEventDate = next.getDtend(); + if (date.after(theStartEventDate) && date.before(theEndEventDate) + || date.equals(theStartEventDate) + || date.equals(theEndEventDate)) { + + longFullDayEventShownCounter++; +// sortedEvents.add(next); +// alreadyShownWeekViewEvents.add(next); + } + } + } + } + } + } + } + } + + final Iterator iterator = sortedFullDayEvents.iterator(); + + int eventLimit = 100;//999 + int counterIvent = 0; + boolean foundRowToPlace = false; + int theRowToPlace = 0; + int last = theLastFDPanelInCellCounter; + for (int i = 0; iterator.hasNext() && i < eventLimit; i++) { + last = last + 1; + final Event event = iterator.next(); + + final ClickableFlowPanel fullDayFlowPanel = createFullDayPanel(event); + final FlexTable grid = (FlexTable) getWidget(); + ///ssss1 grid.setWidget(row, column, flowPanelFullDayFirst); + // RootPanel.get().add(flowPanelFullDayFirst); + // grid.add(flowPanelFullDayFirst); + + Date theStartEventDate = event.getDtstart(); + Date theEndEventDate = event.getDtend(); + + long startDTForWeekleView = 0; + Date newDateStart = new Date(date.getTime());//date.getTime() + Date newDateEnd = new Date(date.getTime()); + + newDateStart.setYear(theStartEventDate.getYear()); + newDateStart.setMonth(theStartEventDate.getMonth());//+1 + newDateStart.setDate(theStartEventDate.getDate()); + + newDateEnd.setYear(theEndEventDate.getYear()); + newDateEnd.setMonth(theEndEventDate.getMonth());//+1 + newDateEnd.setDate(theEndEventDate.getDate()); + + long diff = newDateEnd.getTime() - newDateStart.getTime(); + // Window.alert("! diff=" + diff); +// if (date.after(newDateStart)) { +// //-->> diff = newDateStart.getTime() - newDateEnd.getTime(); +// diff = 8 - diff; +// Window.alert("date.after(newDateStart) 2 diff=" + diff); +// } + + + /* + long diff = event.getDtend().getTime() - event.getDtstart().getTime(); + if (date.after(theStartEventDate)) { + diff = theStartEventDate.getTime() - event.getDtstart().getTime(); + } + */ + if (date.after(newDateStart)) { + //-->> diff = newDateStart.getTime() - newDateEnd.getTime(); + diff = newDateEnd.getTime() - date.getTime(); + //Window.alert("date.after(newDateStart)"); + } + long diffDays = diff / (24 * 60 * 60 * 1000) + 1; + int daysdiff = (int) diffDays; + //Window.alert("date.after(newDateStart) 2 daysdiff=" + daysdiff); + + // Window.alert("3 daysdiff=" + daysdiff); + //---->> + //-->> daysdiff = calculateEventDurationInDays(event); + //Window.alert("@@@333 daysdiff=" + daysdiff + " column=" + column); + + fullDayFlowPanel.setTitle(createTitleForHourMultiDayEvent(daysdiff, event)); + //to show full day long event if it longer then 1 week + while (column + daysdiff - 1 >= 8) { + // Window.alert("4 daysdiff=" + daysdiff); + daysdiff--; + } + //Window.alert("5 daysdiff=" + daysdiff); + if (column + daysdiff - 1 < 8) { + for (int day = column; day < column + daysdiff; day++) { + theShiftVecorOfFullDayEvents[day][last] += 1; + } + longFullDayEventShownCounter = theRowToPlace;// + counterIvent; + + int theLastFullDayLinePlace44 = getLastFDPanelInCellCounter(theShiftVecorOfFullDayEvents, column); + // Window.alert("6 column=" + column); + placeItemInGridWeek(fullDayFlowPanel, column, column + daysdiff, counterIvent, theLastFDPanelInCellCounter); + + } else { + for (int day = 1; day < 1 + daysdiff - (8 - column); day++) { + theShiftVecorOfFullDayEvents[day][last] += 1; + } + longFullDayEventShownCounter = theRowToPlace;// + counterIvent; + + int theLastFullDayLinePlace44 = getLastFDPanelInCellCounter(theShiftVecorOfFullDayEvents, 1); + // Window.alert("6 column=" + column); + placeItemInGridWeek(fullDayFlowPanel, 1, 1 + daysdiff - (8 - column), counterIvent, theLastFDPanelInCellCounter); + + } + counterIvent++; + } + + } + //////////// + + private void placeItemInGridWeek(Widget panel, int colStart, int colEnd, + int row, int cellPosition) { + final FlexTable grid = (FlexTable) getWidget(); + //sss1FlowPanel cell = (FlowPanel) grid.getWidget(1, 1); + FlowPanel cell = (FlowPanel) grid.getWidget(1, colStart);//row + cell.add(panel);//sssss 111 +// calculatedCellOffsetHeight = cell.getElement().getClientHeight();//OffsetHeight(); +// float calculatedCellOffsetWidth = cell.getElement().getOffsetWidth();; +// NumberFormat percFormat = NumberFormat.getFormat("."); +// +// int paddingTop = appointmentPaddingTop() + 3; + int height = appointmentHeight();//12 + //float left = (float) colStart / (float) DAYS_IN_A_WEEK * 100f + .5f + //float left = (float) colStart / (float) DAYS_IN_A_WEEK * 50f + .5f + cellPosition * 5; + //float width = ((float) (colEnd - colStart) / (float) DAYS_IN_A_WEEK) * 100f - 1f; + float width = (colEnd - colStart) * 100f; +// float top = (row * (height + paddingTop)) + cellPosition * 3; + float top = cellPosition * height + cellPosition * 2; + + setFullDayEventStyle(panel, top, width, height); + } + + private void setFullDayEventStyle(Widget panel, float top, float width, int height) { + //final FlexTable grid = (FlexTable) getWidget(); + //cell = (FlowPanel) grid.getWidget(row, colStart); + //cell = (FlowPanel) grid.getWidget(1, colStart); + + DOM.setStyleAttribute(panel.getElement(), "position", "relative"); + DOM.setStyleAttribute(panel.getElement(), "top", top + "px"); + DOM.setStyleAttribute(panel.getElement(), "width", width + "%"); + DOM.setStyleAttribute(panel.getElement(), "height", height + "px"); + DOM.setStyleAttribute(panel.getElement(), "border-radius", "20px 20px 20px 20px"); + DOM.setStyleAttribute(panel.getElement(), "border-color", "#1c61d9"); + DOM.setStyleAttribute(panel.getElement(), "border-style", "solid"); + DOM.setStyleAttribute(panel.getElement(), "border-width", "1px"); + DOM.setStyleAttribute(panel.getElement(), "background-color", "rgba(28,97,217)"); + // DOM.setStyleAttribute(panel.getElement(), "background", "linear-gradient(-90deg, #0000, #1c61d9)"); + } } diff --git a/src/main/java/org/sigmah/client/util/FormattingImpl.java b/src/main/java/org/sigmah/client/util/FormattingImpl.java new file mode 100644 index 000000000..e13a13242 --- /dev/null +++ b/src/main/java/org/sigmah/client/util/FormattingImpl.java @@ -0,0 +1,12 @@ +package org.sigmah.client.util; + +/** + * + * @author Your Name + */ + public class FormattingImpl { + + public int getBorderOffset() { + return -1; + } +} \ No newline at end of file diff --git a/src/main/java/org/sigmah/client/util/FormattingUtil.java b/src/main/java/org/sigmah/client/util/FormattingUtil.java new file mode 100644 index 000000000..cef8c7f2e --- /dev/null +++ b/src/main/java/org/sigmah/client/util/FormattingUtil.java @@ -0,0 +1,28 @@ +package org.sigmah.client.util; + +import com.google.gwt.core.client.GWT; + +/** + * + * @author Your Name + */ +public class FormattingUtil { + + /** + * Implementation of formatting class. Holds browser-specific + * values, loaded by GWT deferred binding. + */ + private static FormattingImpl impl = GWT.create(FormattingImpl.class); + + /** + * All CSS2 compliant browsers count the border height in the + * overall height of an Element. This method returns an offset + * value that should be added to the height or width of an item + * before setting its size. This will ensure consistent sizing + * across compliant and non-compliant browsers. + * @return + */ + public static int getBorderOffset() { + return impl.getBorderOffset(); + } +} diff --git a/src/main/java/org/sigmah/offline/handler/CreateEntityAsyncHandler.java b/src/main/java/org/sigmah/offline/handler/CreateEntityAsyncHandler.java index 2459e8a52..fbaf09de0 100644 --- a/src/main/java/org/sigmah/offline/handler/CreateEntityAsyncHandler.java +++ b/src/main/java/org/sigmah/offline/handler/CreateEntityAsyncHandler.java @@ -22,6 +22,7 @@ * #L% */ +import com.allen_sauer.gwt.log.client.Log; import com.extjs.gxt.ui.client.data.RpcMap; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.inject.Inject; @@ -127,7 +128,7 @@ private void exception(CreateEntity command, boolean throwException) throws Unav } } - private void insertPersonalEvent(CreateEntity command, final AsyncCallback callback) { + private void insertPersonalEvent(final CreateEntity command, final AsyncCallback callback) { final Event event = buildPersonalEvent(command.getProperties()); final PersonalCalendarIdentifier identifier = (PersonalCalendarIdentifier) event.getParent().getIdentifier(); @@ -146,6 +147,9 @@ public void onFailure(Throwable caught) { @Override public void onSuccess(Calendar result) { List events = result.getEvents().get(key); + command.getProperties().put("myIDNow", result + " EEEE"); + Log.info("command.getProperties().put(\"myIDNow\"" + result); + Log.info("command.getProperties().get(\"myIDNow\")---->" + command.getProperties().get("myIDNow")); if(events == null) { events = new ArrayList(); result.getEvents().put(key, events); @@ -173,6 +177,7 @@ public void onSuccess(Calendar result) { // Persisting the new event. personalCalendarAsyncDAO.saveOrUpdate(result, calendarCallback); +// command.getProperties().put("myIDNow", result); } }); } diff --git a/src/main/java/org/sigmah/offline/indexeddb/IndexedDB.java b/src/main/java/org/sigmah/offline/indexeddb/IndexedDB.java index 51a940d50..63b04458f 100644 --- a/src/main/java/org/sigmah/offline/indexeddb/IndexedDB.java +++ b/src/main/java/org/sigmah/offline/indexeddb/IndexedDB.java @@ -51,8 +51,8 @@ public class IndexedDB { */ public static native boolean isSupported() /*-{ // FIXME : temporary disabling offline mode for v2.2 - // return typeof $wnd.indexedDB != 'undefined'; - return false; + return typeof $wnd.indexedDB != 'undefined'; + //return false; }-*/; /** diff --git a/src/main/java/org/sigmah/offline/js/PersonalEventJS.java b/src/main/java/org/sigmah/offline/js/PersonalEventJS.java index a86d01e11..cae716d5f 100644 --- a/src/main/java/org/sigmah/offline/js/PersonalEventJS.java +++ b/src/main/java/org/sigmah/offline/js/PersonalEventJS.java @@ -43,7 +43,9 @@ public static PersonalEventJS toJavaScript(Event event) { personalEventJS.setDescription(event.getDescription()); personalEventJS.setDtstart(Values.toJsDate(event.getDtstart())); personalEventJS.setDtend(Values.toJsDate(event.getDtend())); - + personalEventJS.setEventType(event.getEventType()); + personalEventJS.setReferenceId(event.getReferenceId()); + return personalEventJS; } @@ -55,7 +57,8 @@ public Event toEvent() { event.setDescription(getDescription()); event.setDtstart(Values.toDate(getDtstart())); event.setDtend(Values.toDate(getDtend())); - + event.setEventType(getEventType()); + event.setReferenceId(getReferenceId()); return event; } @@ -98,4 +101,20 @@ public native JsDate getDtend() /*-{ public native void setDtend(JsDate dtend) /*-{ this.dtend = dtend; }-*/; + + public native void setEventType(String eventtype) /*-{ + this.eventtype = eventtype; + }-*/; + + public native String getEventType() /*-{ + return this.eventtype; + }-*/; + + public native void setReferenceId(Integer referenceid) /*-{ + this.referenceid = referenceid; + }-*/; + + public native Integer getReferenceId() /*-{ + return this.referenceid; + }-*/; } diff --git a/src/main/java/org/sigmah/server/dao/PersonalEventDAO.java b/src/main/java/org/sigmah/server/dao/PersonalEventDAO.java index b239bba18..0806565bf 100644 --- a/src/main/java/org/sigmah/server/dao/PersonalEventDAO.java +++ b/src/main/java/org/sigmah/server/dao/PersonalEventDAO.java @@ -22,6 +22,7 @@ * #L% */ +import java.util.List; import org.sigmah.server.dao.base.DAO; import org.sigmah.server.domain.calendar.PersonalEvent; @@ -34,5 +35,6 @@ public interface PersonalEventDAO extends DAO { void merge(PersonalEvent event); + List findEventsByRefId (Integer refId); } diff --git a/src/main/java/org/sigmah/server/dao/impl/PersonalEventHibernateDAO.java b/src/main/java/org/sigmah/server/dao/impl/PersonalEventHibernateDAO.java index 48a295d37..e54f54135 100644 --- a/src/main/java/org/sigmah/server/dao/impl/PersonalEventHibernateDAO.java +++ b/src/main/java/org/sigmah/server/dao/impl/PersonalEventHibernateDAO.java @@ -22,6 +22,8 @@ * #L% */ +import java.util.List; +import javax.persistence.TypedQuery; import org.sigmah.server.dao.PersonalEventDAO; import org.sigmah.server.dao.base.AbstractDAO; import org.sigmah.server.domain.calendar.PersonalEvent; @@ -41,5 +43,14 @@ public class PersonalEventHibernateDAO extends AbstractDAO findEventsByRefId(final Integer refId) { + + final TypedQuery query = em().createQuery("SELECT pm FROM personalevent pm WHERE pm.calendarid = :refId", PersonalEvent.class); + query.setParameter("calendarid", refId); + + return query.getResultList(); + } } diff --git a/src/main/java/org/sigmah/server/domain/calendar/PersonalEvent.java b/src/main/java/org/sigmah/server/domain/calendar/PersonalEvent.java index aa593c631..bd42d8d96 100644 --- a/src/main/java/org/sigmah/server/domain/calendar/PersonalEvent.java +++ b/src/main/java/org/sigmah/server/domain/calendar/PersonalEvent.java @@ -80,6 +80,18 @@ public class PersonalEvent extends AbstractEntityId implements Deleteab private Integer calendarId; /** + * Type of the event. + */ + @Column(name = EntityConstants.PERSONAL_EVENT_COLUMN_TYPE) + @Size(max = EntityConstants.PERSONAL_EVENT_TYPE_MAX_LENGTH) + private String eventtype; + /** + * Reference ID of the event. + */ + @Column(name = EntityConstants.PERSONAL_EVENT_COLUMN_REFERENCE_ID) + private Integer referenceid; + + /** * Title of the event (a short description). */ @Column(name = EntityConstants.PERSONAL_EVENT_COLUMN_SUMMARY) @@ -144,12 +156,15 @@ public boolean isDeleted() { */ @Override protected void appendToString(ToStringBuilder builder) { + builder.append("eventtype", eventtype); + builder.append("referenceid", referenceid); builder.append("summary", summary); builder.append("description", description); builder.append("startDate", startDate); builder.append("endDate", endDate); builder.append("dateCreated", dateCreated); builder.append("dateDeleted", dateDeleted); + } // -------------------------------------------------------------------------------- @@ -223,4 +238,20 @@ public Date getDateDeleted() { public void setDateDeleted(Date dateDeleted) { this.dateDeleted = dateDeleted; } + + public String getEventType() { + return eventtype; + } + + public void setEventType(String eventtype) { + this.eventtype = eventtype; + } + + public Integer getReferenceId() { + return referenceid; + } + + public void setReferenceId(Integer referenceid) { + this.referenceid = referenceid; + } } diff --git a/src/main/java/org/sigmah/server/domain/util/EntityConstants.java b/src/main/java/org/sigmah/server/domain/util/EntityConstants.java index 66ade06cd..77ce487f8 100644 --- a/src/main/java/org/sigmah/server/domain/util/EntityConstants.java +++ b/src/main/java/org/sigmah/server/domain/util/EntityConstants.java @@ -1021,10 +1021,13 @@ private EntityConstants() { public static final String PERSONAL_EVENT_COLUMN_END_DATE = "enddate"; public static final String PERSONAL_EVENT_COLUMN_START_DATE = "startdate"; public static final String PERSONAL_EVENT_COLUMN_SUMMARY = "summary"; + public static final String PERSONAL_EVENT_COLUMN_TYPE = "eventtype"; + public static final String PERSONAL_EVENT_COLUMN_REFERENCE_ID = "referenceid"; + public static final int PERSONAL_EVENT_TYPE_MAX_LENGTH = 2; public static final int PERSONAL_EVENT_DESCRIPTION_MAX_LENGTH = 255; public static final int PERSONAL_EVENT_SUMMARY_MAX_LENGTH = 255; - + // -------------------------------------------------------------------------------- // // PHASE ENTITY. diff --git a/src/main/java/org/sigmah/server/handler/calendar/PersonalCalendarHandler.java b/src/main/java/org/sigmah/server/handler/calendar/PersonalCalendarHandler.java index 3bb77578e..8ce0a1ab2 100644 --- a/src/main/java/org/sigmah/server/handler/calendar/PersonalCalendarHandler.java +++ b/src/main/java/org/sigmah/server/handler/calendar/PersonalCalendarHandler.java @@ -84,32 +84,62 @@ public Calendar getCalendar(CalendarIdentifier identifier, EntityManager em) { if (events != null) { final HashMap> eventMap = new HashMap>(); - + final HashMap> fullDayEventMap = new HashMap>(); + final HashMap> hourMultiDayEventMap = new HashMap>(); + for (final PersonalEvent event : events) { final Date key = normalize(event.getStartDate()); - List list = eventMap.get(key); - if (list == null) { - list = new ArrayList(); - eventMap.put(key, list); + List eventList = eventMap.get(key); + + if (eventList == null) { + eventList = new ArrayList(); + eventMap.put(key, eventList); } + List fullDayList = fullDayEventMap.get(key); + + if (fullDayList == null) { + fullDayList = new ArrayList(); + fullDayEventMap.put(key, fullDayList); + } + + List hourMultiDayList = hourMultiDayEventMap.get(key); + + if (hourMultiDayList == null) { + hourMultiDayList = new ArrayList(); + hourMultiDayEventMap.put(key, hourMultiDayList); + } + final Event calendarEvent = new Event(); calendarEvent.setIdentifier(event.getId()); calendarEvent.setParent(calendar); calendarEvent.setSummary(event.getSummary()); calendarEvent.setDescription(event.getDescription()); calendarEvent.setDtstart(new Date(event.getStartDate().getTime())); - if (event.getEndDate() != null) + calendarEvent.setReferenceId(event.getReferenceId()); + calendarEvent.setEventType(event.getEventType()); + if (event.getEndDate() != null){ calendarEvent.setDtend(new Date(event.getEndDate().getTime())); - - list.add(calendarEvent); - } + } + + if(event.getEventType()!=null && event.getEventType().contains("F") +// || (event.getStartDate().getHours()==event.getEndDate().getHours() +// && event.getStartDate().getMinutes()==event.getEndDate().getMinutes()) + ){ + fullDayList.add(calendarEvent); + }else if (event.getEventType()!=null && event.getEventType().contains("H")){ + hourMultiDayList.add(calendarEvent); + }else{ + eventList.add(calendarEvent); + } calendar.setEvents(eventMap); - } - - return calendar; + calendar.setFullDayEvents(fullDayEventMap); + calendar.setHourMultiDayEvents(hourMultiDayEventMap); + } + } + return calendar; } @SuppressWarnings("deprecation") diff --git a/src/main/java/org/sigmah/server/service/PersonalEventService.java b/src/main/java/org/sigmah/server/service/PersonalEventService.java index 59496b0d1..ac5e70722 100644 --- a/src/main/java/org/sigmah/server/service/PersonalEventService.java +++ b/src/main/java/org/sigmah/server/service/PersonalEventService.java @@ -41,7 +41,7 @@ /** * {@link PersonalEvent} policy implementation. * - * @author Raphaël Calabro (rcalabro@ideia.fr) + * @author RaphaГ«l Calabro (rcalabro@ideia.fr) * @author Denis Colliot (dcolliot@ideia.fr) */ @Singleton @@ -91,25 +91,28 @@ private static void fillEvent(PersonalEvent event, PropertyMap properties) { event.setSummary((String) properties.get(Event.SUMMARY)); event.setDescription((String) properties.get(Event.DESCRIPTION)); - + event.setEventType((String) properties.get(Event.EVENT_TYPE)); + event.setReferenceId((Integer) properties.get(Event.REFERENCE_ID)); + final Date day = (Date) properties.get(Event.DATE); + final Date dayEnd = (Date) properties.get(Event.DATE_END); final Serializable startHourSerialized = properties.get(Event.START_TIME); final Serializable endHourSerialized = properties.get(Event.END_TIME); - if (startHourSerialized instanceof Long) { + if (startHourSerialized != null && startHourSerialized instanceof Long) { final Date startHour = new Date((Long) startHourSerialized); event.setStartDate(startHour); - if (endHourSerialized instanceof Long) { + if (endHourSerialized != null && endHourSerialized instanceof Long) { final Date endHour = new Date((Long) endHourSerialized); - event.setEndDate(endHour); + event.setEndDate(new Date(dayEnd.getTime()+(endHour.getTime()-day.getTime()))); } else { event.setEndDate(null); } } else { event.setStartDate(new Date(day.getYear(), day.getMonth(), day.getDate())); - event.setEndDate(new Date(day.getYear(), day.getMonth(), day.getDate() + 1)); + event.setEndDate(new Date(dayEnd.getYear(), dayEnd.getMonth(), dayEnd.getDate())); } } diff --git a/src/main/java/org/sigmah/shared/command/result/Calendar.java b/src/main/java/org/sigmah/shared/command/result/Calendar.java index 3947da4de..7be6ba5a6 100644 --- a/src/main/java/org/sigmah/shared/command/result/Calendar.java +++ b/src/main/java/org/sigmah/shared/command/result/Calendar.java @@ -21,7 +21,6 @@ * . * #L% */ - import java.util.Collection; import java.util.Date; import java.util.List; @@ -38,96 +37,113 @@ */ public class Calendar implements Result { - - private CalendarIdentifier identifier; - private CalendarType type; - private String name; - private Map> events; - private Collection tasks; - private int style; - private boolean editable; - - /** - * {@inheritDoc} - */ - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Calendar other = (Calendar) obj; - if (this.identifier != other.identifier && (this.identifier == null || !this.identifier.equals(other.identifier))) { - return false; - } - return true; - } - - /** - * {@inheritDoc} - */ - @Override - public int hashCode() { - int hash = 7; - hash = 97 * hash + (this.identifier != null ? this.identifier.hashCode() : 0); - return hash; - } - - public CalendarIdentifier getIdentifier() { - return identifier; - } - - public void setIdentifier(CalendarIdentifier identifier) { - this.identifier = identifier; - } - - public CalendarType getType() { - return type; - } - - public void setType(CalendarType type) { - this.type = type; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Map> getEvents() { - return events; - } - - public void setEvents(Map> events) { - this.events = events; - } - - public Collection getTasks() { - return tasks; - } - - public void setTasks(Collection tasks) { - this.tasks = tasks; - } - - public int getStyle() { - return style; - } - - public void setStyle(int style) { - this.style = style; - } - - public boolean isEditable() { - return editable; - } - - public void setEditable(boolean editable) { - this.editable = editable; - } + private CalendarIdentifier identifier; + private CalendarType type; + private String name; + private Map> events; + private Map> fullDayEvents; + private Map> hourMultiDayEvents; + private Collection tasks; + private int style; + private boolean editable; + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Calendar other = (Calendar) obj; + if (this.identifier != other.identifier && (this.identifier == null || !this.identifier.equals(other.identifier))) { + return false; + } + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + int hash = 7; + hash = 97 * hash + (this.identifier != null ? this.identifier.hashCode() : 0); + return hash; + } + + public CalendarIdentifier getIdentifier() { + return identifier; + } + + public void setIdentifier(CalendarIdentifier identifier) { + this.identifier = identifier; + } + + public CalendarType getType() { + return type; + } + + public void setType(CalendarType type) { + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Map> getEvents() { + return events; + } + + public void setEvents(Map> events) { + this.events = events; + } + + public Collection getTasks() { + return tasks; + } + + public void setTasks(Collection tasks) { + this.tasks = tasks; + } + + public int getStyle() { + return style; + } + + public void setStyle(int style) { + this.style = style; + } + + public boolean isEditable() { + return editable; + } + + public void setEditable(boolean editable) { + this.editable = editable; + } + + public void setFullDayEvents(Map> fullDayEvents) { + this.fullDayEvents = fullDayEvents; + } + + public Map> getFullDayEvents() { + return fullDayEvents; + } + + public void setHourMultiDayEvents(Map> hourMultiDayEvents) { + this.hourMultiDayEvents = hourMultiDayEvents; + } + + public Map> getHourMultiDayEvents() { + return hourMultiDayEvents; + } } diff --git a/src/main/java/org/sigmah/shared/dto/calendar/Event.java b/src/main/java/org/sigmah/shared/dto/calendar/Event.java index a2e2d9424..81c0eb970 100644 --- a/src/main/java/org/sigmah/shared/dto/calendar/Event.java +++ b/src/main/java/org/sigmah/shared/dto/calendar/Event.java @@ -44,27 +44,34 @@ public class Event implements Serializable { public static final String CALENDAR_ID = "calendarId"; public static final String SUMMARY = "summary"; public static final String DATE = "date"; + public static final String DATE_END = "dateEnd"; public static final String START_TIME = "startDate"; public static final String END_TIME = "endDate"; public static final String DESCRIPTION = "description"; - + public static final String REFERENCE_ID = "referenceid"; + public static final String EVENT_TYPE = "eventtype"; + + private String eventtype; private Integer identifier; private String summary; private String description; private Date dtstart; private Date dtend; private Calendar parent; + private Integer referenceid; public Event() { // Serialization. } - public Event(String summary, String description, Date dtstart, Date dtend, Calendar parent) { + public Event(String summary, String description, Date dtstart, Date dtend, Calendar parent, String eventtype, Integer referenceid) { this.summary = summary; this.description = description; this.dtstart = dtstart; this.dtend = dtend; this.parent = parent; + this.eventtype = eventtype; + this.referenceid = referenceid; } /** @@ -102,8 +109,11 @@ public void fillValues(Map values) { setSummary((String) values.get(Event.SUMMARY)); setDescription((String) values.get(Event.DESCRIPTION)); - + setEventType((String) values.get(Event.EVENT_TYPE)); + setReferenceId((Integer) values.get(Event.REFERENCE_ID)); + final Date day = (Date) values.get(Event.DATE); + final Date dayEnd = (Date) values.get(Event.DATE_END); final Object startHourSerialized = values.get(Event.START_TIME); final Object endHourSerialized = values.get(Event.END_TIME); @@ -112,7 +122,7 @@ public void fillValues(Map values) { setDtstart(startHour); if (endHourSerialized instanceof Long) { - final Date endHour = new Date((Long) endHourSerialized); + final Date endHour = new Date((Long) endHourSerialized+((dayEnd.getTime()-day.getTime()))); setDtend(endHour); } else { setDtend(null); @@ -120,7 +130,7 @@ public void fillValues(Map values) { } else { setDtstart(new Date(day.getYear(), day.getMonth(), day.getDate())); - setDtend(new Date(day.getYear(), day.getMonth(), day.getDate() + 1)); + setDtend(new Date(dayEnd.getYear(), dayEnd.getMonth(), dayEnd.getDate())); } } @@ -164,6 +174,22 @@ public void setSummary(String summary) { this.summary = summary; } + public String getEventType() { + return eventtype; + } + + public void setEventType(String eventtype) { + this.eventtype = eventtype; + } + + public Integer getReferenceId() { + return referenceid; + } + + public void setReferenceId(Integer referenceid) { + this.referenceid = referenceid; + } + public Calendar getParent() { return parent; } diff --git a/src/main/resources/org/sigmah/Sigmah.gwt.xml b/src/main/resources/org/sigmah/Sigmah.gwt.xml index 30e3cf35d..aafcb2932 100644 --- a/src/main/resources/org/sigmah/Sigmah.gwt.xml +++ b/src/main/resources/org/sigmah/Sigmah.gwt.xml @@ -20,51 +20,51 @@ . #L% --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/sigmah/client/i18n/UIConstants.properties b/src/main/resources/org/sigmah/client/i18n/UIConstants.properties index 603a1a054..d1abd6572 100644 --- a/src/main/resources/org/sigmah/client/i18n/UIConstants.properties +++ b/src/main/resources/org/sigmah/client/i18n/UIConstants.properties @@ -475,11 +475,19 @@ calendarEditEvent=Edit event calendarEmptyChoice=Select a calendar... calendarEventDate=Date calendarEventDescription=Description -calendarEventEndHour=End hour +calendarEventEndHour=End time calendarEventObject=Object -calendarEventStartHour=Start hour +calendarEventStartHour=Start time calendarNoCalendarSelected=No calendar selected calendar.addEvent.noCalendar.ko=You cannot add an event without a calendar. +# New Calnedar Event View +calendar.addEvent.repeatOnceRB.toolTip=Create single Calendar event. +calendar.addEvent.repeatWeeklyRB.toolTip=Create a recurring weekly Calendar events. +calendar.addEvent.repeatMonthlyRB.toolTip=Create a recurring monthly Calendar events. +calendar.addEvent.repeatYearlyRB.toolTip=Create a recurring yearly Calendar events. +calendar.addEvent.repeatPeriodRG.label=Repeats +calendar.addEvent.isAllDayCB.boxLabel=All day +calendar.addEvent.allDayCbGr.label=Duration cancel=Cancel cancelled=Cancelled cannotLoadMap=Google Maps could not be loaded. Please check your internet connection. @@ -1983,3 +1991,32 @@ contactFullName=Contact Name iterationName=Iteration Name seeIterationDetails=See details +calendar.addEvent.dateStart.label=Date start +calendar.addEvent.dateEnd.label=Date end +calendar.addEvent.isAllDayCB.allDayName=All day name +calendar.addEvent.repeatPeriodRG.name=Repeat event 999 +calendar.addEvent.repeatYearlyRB.label=yearly +calendar.addEvent.description.textArea.yearly=\ The Yearly event. +calendar.addEvent.repeatMonthlyRB.label=monthly +calendar.addEvent.description.textArea.monthly=\ The Monthly event. +calendar.addEvent.repeatWeeklyRB.label=weekly +calendar.addEvent.description.textArea.weekly=\ The Weekly event. +calendar.addEvent.repeatDailyRB.label=daily +calendar.addEvent.description.textArea.daily=\ The Daily event. +calendar.addEvent.repeatOnceRB.label=once +calendar.addEvent.repeatOnceRB.name=onceRepeatRBname +calendar.addEvent.description.textArea.once=\ The Once event. +calendar.addEvent.repeatsSettings.headingHtml.monthly=Monthly repetition details +calendar.addEvent.repeatsSettings.SameDayOfWeekRB.label=Same day of week +calendar.addEvent.repeatsSettings.SameDayOfWeekRB.monthly.name=radioMonthlySameDayOfWeek +calendar.addEvent.repeatsSettings.SameDayOfWeekRB.monthly.toolTip=Every next month at the same day of week. (with autochange to ...h) +calendar.addEvent.repeatsSettings.SameDateRB.label=Same date +calendar.addEvent.repeatsSettings.SameDateRB.monthly.name=radioMonthlySameDate +calendar.addEvent.repeatsSettings.SameDateRB.monthly.toolTip=Every next month at the same date. (with autochange to last day of month) +calendar.addEvent.repeatsSettings.radioGroup.monthly.settings=Montly settings 999 +calendar.addEvent.repeatsSettings.headingHtml.yearly=Yearly repetition details +calendar.addEvent.repeatsSettings.SameDayOfWeekRB.yearly.toolTip=Repeat Calendar event at the same DAY of week annually +calendar.addEvent.repeatsSettings.SameDayOfWeekRB.yearly.name=radioYearlySameDayOfWeek +calendar.addEvent.repeatsSettings.SameDateRB.yearly.name=radioYearlySameDate +calendar.addEvent.repeatsSettings.radioGroup.yearly.settings=Yearly settings 888 +calendar.addEvent.repeatsSettings.radioGroup.yearly.settings.name=Yearly settings name diff --git a/src/main/resources/org/sigmah/public/css/sigmah.css b/src/main/resources/org/sigmah/public/css/sigmah.css index 59af517e2..9ff6f4eb2 100644 --- a/src/main/resources/org/sigmah/public/css/sigmah.css +++ b/src/main/resources/org/sigmah/public/css/sigmah.css @@ -1,445 +1,445 @@ -/* - * #%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 - * . - * #L% - */ -.noscript{max-width:550px;font-family:sans-serif;font-weight:700;text-align:center;color:#FFF;background-color:red;border:3px solid red;position:relative;z-index:99999991;margin:50px auto 0;padding:8px;} - -.work-in-progress-label{color:#DF4848;font-weight:bold;background:url(../images/icon/traffic-cone.png) no-repeat 0 50%;padding-left:22px;height:22px;line-height:22px} - -/* Application view */ -body {font-family:Arial;font-size:8pt} -#header{height:56px;width:100%;float:left;background:url(../images/header/header-bg.jpg) repeat-x;clear:both;} -#header-left{height:56px;width:135px;float:left;padding-left:25px;background-color:#E86F00;background:url(../images/header/header-bg-left.jpg) no-repeat;} -#header-middle{height:56px;width:420px;float:left;background:url(../images/header/header-bg-middle.jpg) no-repeat;} -#header-right{height:56px;width:360px;float:right;background:url(../images/header/header-bg-right.jpg) no-repeat top right} -#orglogo{width:100%;height:100%;background-color:transparent;background-position:left center;background-repeat:no-repeat;opacity:0.5;} -#orgname{height:40px;width:420px;float:left;padding-top:9px;padding-left:6px;font-size:18px;font-weight:700;color:#fff;clear:both;text-transform:uppercase;} -#username{height:16px;width:340px;float:right;text-align:right;margin-right:80px;padding-top:2px;padding-left:10px;font-size:11px;color:#fff;clear:both;position:relative} -#username div{display:inline;padding-left:15px;background:transparent url(../images/header/username.png) left 1px no-repeat;} -#username span{display:block;position:absolute;top:16px;right:-0.5em;padding:4px 4px 4px 24px;background:#EC9235 url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAH2SURBVDjLjZNLTxNRGIaJv6ZNWeBwkZFLQtGAC4l/wKULV+7YILeSYukEUhJoSASVuCI0hpAYDSUQCJBSoAaC0wbBUi4aWphpO52Zlpa+nnOqCAptJ3k3M3me73LOlAAoyZfDqQdOEvyO89/vRcGZ5HeWmySFYdWHVOQN0vE58jrLJMFJ82hewVU4+bMfqdPxP9VBn+A4D88wP59PwFqmsH7UgeTJEMlsTuIyI5uRsDfCMcmtAtoyhVmOu5kkHZuFsiNA3XuEi+QCdhxluL0D/SvpoO+vhIksiItNiPqqyXgfIL403gjfoTsIL70gQBdim3VQvz2FFnwOxf8E8kYF0rIVYqcRM70Vgf/Pe/ohwsutOJdcpBpP4Mek+jPEfbWQVzkG+7tNcNsqt68tkcLZTIzM6YZ21IbolgHq9j1o+z04nKhHRnlH2p6A32LCvFD55fIYr960VHgSSqCFVDJBEeugh+zw2jnpc0/5rthuRMBaioWBqrVrFylXOUpankIi0AjJY0DC3wD9oA9rAnc2bat+n++2UkH8XHaTZfGQlg3QdlsIbIVX4KSPAv+60L+SO/PECmJiI1lYM9SQBR7b3einfn6kEMwEIZd5Q48sQQt1Qv/xFqt2Tp5x3B8sBmYC71h926az6njdUR6hMy8O17wqFqb5Bd2o/0SFzIZrAAAAAElFTkSuQmCC") no-repeat 4px center;text-decoration:underline;cursor:pointer} -#userlogout{float:right;font-size:11px;height:16px;margin-right:15px;padding-top:3px;text-align:right;width:92px;} -#userlogout a{color:#EE9329;text-decoration:none;background:transparent url(../images/header/logout.png) left 2px no-repeat;padding-left:15px;} -#userlogout a:hover{text-decoration:underline;} -#header-menu{color:#C2C1C1;float:right;font-size:11px;height:16px;padding-top:3px;text-align:right;width:245px;} -#header-menu a{color:#C2C1C1;font-size:11px;text-decoration:none;} -#header-menu a:hover{text-decoration:underline;} -#offline-status{color:#FFF;float:right;font-size:12px;font-weight:700;height:36px;line-height:36px;margin-right:145px;text-align:right;position:relative} -#app-loader{position:relative;width:23px;height:23px;left:239px;top:26px;background-color:transparent;background-position:center;background-repeat:no-repeat;} -#app-loader.loading{background-image:url(../images/loader/app-loader.gif);} -#menu{clear:both;} -#menu .bar{background:url(../images/menu/menu-bar-repeat.jpg) repeat-x scroll 0 0 rgba(0,0,0,0);clear:both;float:left;height:34px;overflow:hidden;position:relative;width:100%;} -#menu .bar-decoration-left{background-color:#E86F00;height:100%;left:0;position:absolute;width:15px;} -#menu .bar-decoration-left-round{background-image:url(../images/menu/menu-bar-top-left.png);height:5px;left:15px;position:absolute;width:5px;} -#menu .menu-buttons{background:url(../images/menu/menu-buttons-bg.png) no-repeat scroll 0 0 rgba(0,0,0,0);height:34px;position:absolute;right:0;width:55px;} -#menu .menu-buttons .gwt-Button{display:inline-block;background:transparent url(../images/menu/menu-buttons.png) repeat 0 0;border:1px solid #3C3C3E;height:34px;width:20px;} -#menu .menu-buttons .menu-button-left{border-bottom-left-radius:4px;border-top-left-radius:4px;} -#menu .menu-buttons .menu-button-left:hover{background-position:0 -32px;} -#menu .menu-buttons .menu-button-left:active{background-position:0 -64px;} -#menu .menu-buttons .menu-button-left:disabled{background-position:0 -96px;} -#menu .menu-buttons .menu-button-right{border-bottom-right-radius:4px;border-top-right-radius:4px;background-position:18px 0;} -#menu .menu-buttons .menu-button-right:hover{background-position:18px -32px;} -#menu .menu-buttons .menu-button-right:active{background-position:18px -64px;} -#menu .menu-buttons .menu-button-right:disabled{background-position:18px -96px;} -#menu .tabs {position:absolute;overflow:hidden;width:100%;height:100%;margin-left:15px;} -#menu .tabs .tab{cursor:default;float:left;position:absolute;overflow:hidden;} -#menu .tabs .tab .tab-left{float:left;width:11px;height:34px;background:transparent url(../images/menu/tab-left.png) no-repeat 0 0;} -#menu .tabs .tab .tab-middle{float:left;font-size:12px;height:34px;padding-top:13px;padding-right:5px;color:#B3B3B3;background:transparent url(../images/menu/tab-middle.png) repeat-x 0 0;} -#menu .tabs .tab .tab-right{float:left;width:3px;height:34px;padding-top:10px;padding-left:3px;background:transparent url(../images/menu/tab-right.png) no-repeat right top;} -#menu .tabs .tab.closeable .tab-right{width:19px;background-position:0 0;} -#menu .tabs .tab .tab-close{position:absolute;height:11px;width:11px;right:6px;bottom:22px;background:transparent url(../images/menu/close.png) no-repeat 0 0;} -#menu .tabs .tab .tab-close:hover{background-position:0 -11px;} -#menu .tabs .tab.home{margin-right:2px;} -#menu .tabs .tab.home .tab-left{width:37px;background-image:url(../images/menu/tab-home-left.jpg);} -#menu .tabs .tab.active .tab-left{background-image:url(../images/menu/tab-left-over.jpg);} -#menu .tabs .tab.active .tab-middle{color:#FFF;background-image:url(../images/menu/tab-middle-over.jpg);} -#menu .tabs .tab.active .tab-right{background-image:url(../images/menu/tab-right-over.jpg);} -#menu .tabs .tab.home.active .tab-left{background-image:url(../images/menu/tab-home-left-over.png);} -#app-message{clear:both;} -#app-message .message-panel,.popup-content .message-panel{padding:10px 15px 0 15px;} -#app-message .message,.popup-content .message{font-size:13px;border:1px solid #000;border-radius:4px;padding:5px 0 5px 30px;background-color:transparent;background-position:5px 6px;background-repeat:no-repeat;} -#app-message .message{background-position:5px 3px;} -#help{width:100%;} -#help .help-content{width:100%;} -#help .help-content iframe{width:100%;height:518px;border:0;} -#credits{width:100%;border-collapse:separate;border-spacing:10px;} -#credits .properties{width:100%;border-collapse:inherit;} -#credits .properties td:first-child{width:230px;} -#credits .version{width:100%;border-collapse:inherit;} -#credits .version td{text-align:center;} -#credits .version .version-logo{margin:0 auto;width:214px;height:167px;background:transparent url(../images/credits/logo.png) no-repeat center;} -#credits .version .version-name{padding-top:25px;font-weight:bold;} -#credits .version .version-number{padding-top:2px;font-weight:bold;} -#credits .version .version-ref{padding-top:2px;} -#credits .team{width:100%;border-collapse:inherit;} -#credits .team-scroll{max-height:240px;margin-left:15px;} -#credits .team .team-label{font-weight:bold;padding-top:20px;} -#credits .team tr:first-child td:first-child .team-label{padding-top:0;} -#credits .team table{width:100%;} -#credits .team table div{margin-left:15px;margin-top:3px;} -#credits .team a{color:#4B3E2D;} -#credits .timeline{width:100%;border-collapse:inherit;border-top:3px solid #1B3280;padding-top:10px;} -#credits .timeline .timeline-image{height:184px;background:transparent url(../images/credits/timeline.png) no-repeat center;} -#content {clear:both;background-color:transparent;}/*Paddings are dynamically set in ApplicationView.*/ -.layout-transparent{background:transparent} -.layout-with-v-scroll{overflow-y:scroll} -.layout-with-h-scroll{overflow-x:scroll} -.white-background{background:#fff} -.sigmah-tab-panel .x-tab-panel-header-plain .x-tab-strip-spacer{border:none;height:0} -.white-tab-body .x-tab-panel-body {background:#fff} - -/* Notifications N10N */ -#app-message .message-panel.info .message,.popup-content .message-panel.info .message{background-color:#E7F3FF;border-color:#7BA6D6;color:#5C7CA0;background-image:url(../images/icon/information.png);} -#app-message .message-panel.question .message,.popup-content .message-panel.question .message{background-color:#E7F3FF;border-color:#7BA6D6;color:#5C7CA0;background-image:url(../images/icon/question-mark.png);} -#app-message .message-panel.warning .message,.popup-content .message-panel.warning .message{background-color:#FEFFCF;border-color:#EBAE7F;color:#D85D01;background-image:url(../images/icon/error.png);} -#app-message .message-panel.error .message,.popup-content .message-panel.error .message{background-color:#FFE7E7;border-color:#E77D7B;color:#AD5E5C;background-image:url(../images/icon/exclamation.png);} -#app-message .message-panel.valid .message,.popup-content .message-panel.valid .message{background-color:#E7FFD6;border-color:#8CD76B;color:#69A150;background-image:url(../images/icon/accept.png);} -#app-message .message-panel.offline .message,.popup-content .message-panel.offline .message{background-color:#646263;border-color:#000;color:#FFF;background-image:url(../images/icon/information.png);} -.popup-content .message-panel{background-color:white;padding-bottom:10px} -.x-window.notification .popup-content .message-panel{padding:0;} -.x-window.notification .popup-content .message{border:none;} -.x-window.notification.info table.x-component tr:first-child td:first-child, -.x-window.notification.question table.x-component tr:first-child td:first-child, -.x-window.notification.confirmation.question .form-panel .x-panel-footer{background-color:#E7F3FF;} -.x-window.notification.warning table.x-component tr:first-child td:first-child{background-color:#FEFFCF;} -.x-window.notification.error table.x-component tr:first-child td:first-child{background-color:#FFE7E7;} -.x-window.notification.valid table.x-component tr:first-child td:first-child{background-color:#E7FFD6;} -.x-info.info .x-info-tl,.x-info.info .x-info-tr,.x-info.info .x-info-bl,.x-info.info .x-info-br{background-image:url(../images/notif/corners-sprite-info.png);} -.x-info.info .x-info-tc,.x-info.info .x-info-bc{background-image:url(../images/notif/top-bottom-info.png);} -.x-info.info .x-info-ml,.x-info.info .x-info-mr{background-image:url(../images/notif/left-right-info.png);} -.x-info.info .x-info-mc{background-color:#E7F3FF;} -.x-info.info .x-info-body{color:#5C7CA0;} -.x-info.warning .x-info-tl,.x-info.warning .x-info-tr,.x-info.warning .x-info-bl,.x-info.warning .x-info-br{background-image:url(../images/notif/corners-sprite-warning.png);} -.x-info.warning .x-info-tc,.x-info.warning .x-info-bc{background-image:url(../images/notif/top-bottom-warning.png);} -.x-info.warning .x-info-ml,.x-info.warning .x-info-mr{background-image:url(../images/notif/left-right-warning.png);} -.x-info.warning .x-info-mc{background-color:#FEFFCF;} -.x-info.warning .x-info-body{color:#D85D01;} -.x-info.error .x-info-tl,.x-info.error .x-info-tr,.x-info.error .x-info-bl,.x-info.error .x-info-br{background-image:url(../images/notif/corners-sprite-error.png);} -.x-info.error .x-info-tc,.x-info.error .x-info-bc{background-image:url(../images/notif/top-bottom-error.png);} -.x-info.error .x-info-ml,.x-info.error .x-info-mr{background-image:url(../images/notif/left-right-error.png);} -.x-info.error .x-info-mc{background-color:#FFE7E7;} -.x-info.error .x-info-body{color:#AD5E5C;} -.x-info.valid .x-info-tl,.x-info.valid .x-info-tr,.x-info.valid .x-info-bl,.x-info.valid .x-info-br{background-image:url(../images/notif/corners-sprite-valid.png);} -.x-info.valid .x-info-tc,.x-info.valid .x-info-bc{background-image:url(../images/notif/top-bottom-valid.png);} -.x-info.valid .x-info-ml,.x-info.valid .x-info-mr{background-image:url(../images/notif/left-right-valid.png);} -.x-info.valid .x-info-mc{background-color:#E7FFD6;} -.x-info.valid .x-info-body{color:#69A150;} -.x-info.offline .x-info-tl,.x-info.valid .x-info-tr,.x-info.valid .x-info-bl,.x-info.valid .x-info-br{background-image:url(../images/notif/corners-sprite-offline.png)} -.x-info.offline .x-info-tc,.x-info.valid .x-info-bc{background-image:url(../images/notif/top-bottom-offline.png)} -.x-info.offline .x-info-ml,.x-info.valid .x-info-mr{background-image:url(../images/notif/left-right-offline.png)} -.x-info.offline .x-info-mc{background-color:#646263} -.x-info.offline .x-info-body{color:#FFF} -.x-info .x-info-header-text{padding-left:23px;background-color:transparent;background-position:left center;background-repeat:no-repeat;} -.x-info.info .x-info-header-text{background-image:url(../images/icon/information.png);} -.x-info.warning .x-info-header-text{background-image:url(../images/icon/error.png);} -.x-info.error .x-info-header-text{background-image:url(../images/icon/exclamation.png);} -.x-info.valid .x-info-header-text{background-image:url(../images/icon/accept.png);} -.x-info.offline .x-info-header-text{background-image:url(../images/icon/information.png); color: #FFF} -.notif-message{margin-top:15px;} -.notif-message.notif-first{margin-top:0;} -.notif-message ul.notif-list{margin-top:3px;padding-left:15px;list-style:disc outside none;} - -/* Administration */ -.preview-wrapper{border:1px solid #ccc;padding:5px 0;text-align:center} -.backup-status{border:1px solid #ccc;padding:5px} -.backup-status .details-panel{margin-top:5px} -.backup-status .details-panel td{font-size:90%;color:#bbb;padding:2px;font-style:italic} -.backup-status .details-panel td.details-panel-label{font-weight:bold;padding-left:15px;padding-right:5px} - -/* Sub Menu and sub content container */ -/* TODO : finish color mantis 0000599 */ -#content .sub-menu.vertical{width:100%} -#content .sub-menu .sub-menu-item{cursor:pointer;font-weight:bold;color:white;text-decoration:underline;padding:5px;} -#content .sub-menu .sub-menu-item.active{cursor:default;color:black;text-decoration:none;background-color:white;border-radius:5px;text-align:center;} -#content .sub-menu.vertical .sub-menu-item{margin-bottom:15px;} - -/* MockUpView */ -#mockup fieldset{border:1px solid #FFF;margin-bottom:12px;padding:12px;} -#mockup fieldset legend{color:#FFF;font-size:13px;font-weight:bold;} - -/* LoginView */ -.login-background{position:absolute;top:0;left:0;width:100%;height:100%;background-color:#494748} -.login-box{position:absolute;left:50%;top:50%;width:650px;height:170px;margin-left:-325px;margin-top:-85px} -.login-box-logo{width:250px;height:150px;text-align:left} -.login-box-form{width:400px;height:150px;background-color:#e96f00;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px} -.login-box-form-label{font-family:tahoma,arial,helvetica,sans-serif;font-size:12px;color:#fff;text-align:right;width:120px;padding-right:8px} -.login-box-form-forgotten{font-family:tahoma,arial,helvetica,sans-serif;font-size:11px;font-weight:700;color:#fff} -.login-box-form-separator{width:33%;height:14px} - -/* Monitored points */ -.points-date-exceeded{color:red;} -.points-completed{text-decoration:line-through;cursor:pointer;} - -/* Create projects view */ -.create-project-type{text-align:right;} -.create-project-type table{display:inline-block;} -.create-project-type .create-project-type-label{margin-left:5px;} - -/* Flexibility */ -.flexibility-layout{padding:4px 20px 0 0} -.flexibility-layout td{vertical-align:top} -.flexibility-textarea{padding-bottom:16px} -.flexibility-element-label{font-size:8pt} -.flexibility-element-field-label{font-weight:bold} -.flexibility-text-field{padding-left:0;padding-right:0} -.flexibility-action{text-decoration:underline;cursor:pointer;color:#4B3E2D} -.flexibility-action-iconable{padding-left:4px} -.flexibility-label{font-family:tahoma,arial,helvetica,sans-serif} -.flexibility-link{color:#4B3E2D} -.hyperlink-label{text-decoration:underline;cursor:pointer} - -/* Project : Grid */ -.project-starred-icon{cursor:pointer} -.project-grid-node{font-weight:bold} -.project-grid-leaf{font-weight:normal} -.project-grid-code a{text-decoration:underline;cursor:pointer;color:#4B3E2D} -.project-grid-code-icon{padding-right:5px} -.project-refresh-button button{font-weight:bold} -.important-label{font-size:8pt;padding:5px} -.important-label-white{font-size:8pt;padding:5px;color:white} -.monitor-progress-bar{width:50%;z-index:200} -.filtered-column-header{font-weight:bold;font-style:italic;background:url("../images/icon/filter.png") no-repeat right} -.project-model-type-radio,.project-model-type-radio *{cursor:pointer} - -/* Project : RatioBar */ -.blockStat{border:1px solid #B9A48F;padding:1px;background:transparent url(../images/ratiobar/ratio-bar-bg.png) repeat-x scroll 0 1px} -.blockStat div{height:11px;line-height:10px;color:white;font-weight:bold;font-family:tahoma;font-size:11px;text-align:center;background-repeat:repeat-x;background-position:0 0} -.blockStatBgRed{background-color:red} -.blockStatBgYellow{background-image:url(../images/ratiobar/ratio-bar-bg-yellow.png)} -.blockStatBgOrange{background-image:url(../images/ratiobar/ratio-bar-bg-orange.png)} -.blockStatBgBlack{background-image:url(../images/ratiobar/ratio-bar-bg-black.png)} -.blockStatUndefined{background:url(../images/ratiobar/ratio-bar-bg-black.png) repeat-x;-webkit-animation:blockStatAnim .4s steps(6) infinite;-moz-animation:blockStatAnim .4s steps(6) infinite;-ms-animation:blockStatAnim .4s steps(6) infinite;-o-animation:blockStatAnim .4s steps(6) infinite;animation:blockStatAnim .4s steps(6) infinite} -@-webkit-keyframes blockStatAnim{from{background-position:0px} to{background-position:-6px}} -@-moz-keyframes blockStatAnim{from{background-position:0px} to{background-position:-6px}} -@-ms-keyframes blockStatAnim{from{background-position:0px} to{background-position:-6px}} -@-o-keyframes blockStatAnim{from{background-position:0px} to{background-position:-6px}} -@keyframes blockStatAnim{from{background-position:0px} to{background-position:-6px}} - -/* Offline */ -.offline #header-left{background:none} -.offline #header-middle{background:none} -.offline-button{cursor:pointer;display:inline-block;padding:4px} -.offline-button-active{background-color:#646263;border-bottom:1px solid #999} -.offline .bar-decoration-left{background:url(../images/menu/menu-bar-repeat.jpg) repeat-x scroll 0 0 transparent} -.offline .bar-decoration-left-round{background-image:none !important} -#offline-menu{position:absolute;top:32px;right:0px;width:320px;z-index:1;background-color:#646263;color:#FFF;text-align:left;border-radius:6px 0 6px 6px;;padding:6px;line-height:normal;font-weight:normal} -#offline-menu h1{font-weight:bold; margin:5px 0} -.offline-progress{position:absolute;top:28px;left:0;right:0;background-color:#646263;height:2px} -.offline-progress .blockStatBgBlack,.offline-progress .blockStatBgYellow,.offline-progress .blockStatBgOrange,.offline-progress .blockStatBgRed{height: 100%;background: #FFF none} -.offline-progress .blockStatUndefined{height: 100%} -.offline-menu-progress{display:inline-block;width:220px;background-color:#A88F64;height:6px;margin-top:3px;border-radius:1px} -.offline-menu-progress .blockStatBgBlack,.offline-menu-progress .blockStatBgYellow,.offline-menu-progress .blockStatBgOrange,.offline-menu-progress .blockStatBgRed{height: 100%;background: #FFF none} -.offline-menu-progress .blockStatUndefined{height: 100%} -.offline-menu-progress-label{display: inline-block;width:100px} -.offline-sync-progress{border:1px solid #B9A48F;padding:1px;background:transparent url(../images/ratiobar/ratio-bar-bg.png) repeat-x scroll 0 1px} -.offline-sync-progress .blockStatBgBlack,.offline-sync-progress .blockStatBgYellow,.offline-sync-progress .blockStatBgOrange,.offline-sync-progress .blockStatBgRed{height:11px;line-height:10px;color:white;font-weight:bold;font-family:tahoma;font-size:11px;text-align:center;background-repeat:repeat-x;background-position:0 0;background-image:url(../images/ratiobar/ratio-bar-bg-black.png)} -.offline-action{background-color:#FFF;border-radius:4px;color:#000;text-decoration:none;font-weight:bold;font-size:11px;display:block;text-align:center;margin:5px 0;padding:5px;line-height:1} -.offline-action-disabled{background-color:lightgray;color:gray;cursor:default} -.offline-action-separator{border:0;height:1px;background-color:#999} -.offline-action.update-database{background: #FFF url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAmBJREFUOBGNU11IVEEU/nadNlghNAXbXcJFUyoSayFYsIegNSupffKhegiKoof+IIieop576q0HISsKAh8qULI/yCepTdfNanN/hVzdNVfR3b1z79x7pzs39uqKkgOHc+bM931zZuYMsInx8ls/3whm32hhdf7Tzw948Pb+uiK2MjAvzfNwNoSJ2QgSuRgWluchUwaFKnBvd0NRGPbV78f17psWR3DNSWoxxocSg8gXc9i2tQZORzXsNhuYzsBU1fQyk/F1fBQdjYdx7eQNS8Sel/7wodgAKCvBW9sEB3FA5zokRk2jTDK8BKrJoFQYLRdtejKa+YLs8gya6poNERklWUI0HUU8FTfKZ8YxFHjcbjCm4qDHj1s9t63dhQIZ/z0GJ6lGQSmiREsIT4ThbzqEh2f6LGDwrpvv9bThztl7Vq5cBpmcmcTi0gJUmYGrwPG2U7gYuFwB7DxwDFeCV23DqY9c13Roqg7TGzHpaT8NTdOgr0oK9XfpAd7p7TaFBFnkMvkMBiOvUSwUQCUZW+AACezpqthNAJ//eMRDmRERWuPxSC9/P/EGvlYfbFV2zOZmUMzK/57RQhlBf/QZj+ejUI1LS2aT5iWKy3TVutDY4AVxEDCNmU96YncQZDX51a8X/Hsugua6FvNYO2u8JlgQRE8s0yVUMYJkOoV62w4caQ9UCkC3Q5YVUIVC03UoopEE2bCSVMTcwhympzNwEQ/Od12Au85jtNua8eRzLx+bDpmtm5hKmK0sWtpJnNjV0AJ/awcCvqPwGOQ11JWp+DiXes+t+3lWUP+Jng73bUrgLx+GPJMd2jBiAAAAAElFTkSuQmCC) 4px center no-repeat} -.offline-action.transfert-files{background: #FFF url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAA6hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxNS0wMy0wNFQxNzowMzozMTwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjMuMTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpDb21wcmVzc2lvbj41PC90aWZmOkNvbXByZXNzaW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj43MjwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6WFJlc29sdXRpb24+NzI8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4xNjwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+MTY8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4K/3M5/gAAAZ9JREFUOBGdUrEvQ0Ec/vrevddqYlGV1IwE6R9AiKSDwYCEwZ9gkA7ShE3EQmJisZmZ1GDDIGFi6S6xaLRqIdV39+7O3b32Rasol/ze9+6X3/f97nffAX9Y2aNV2VputSZ+2t+XCljcW2gSiWhC7mbZJLnP4TMfjPqgHgOt6aDwVGhM9aRAKcPrM0N+7cRwSaPjeGISXCgB4YfBOAfjDEyo4EFe493bLWY2ZuXZ5mnECOjOujAkqyKmhAJyHesCvkLKGKR0TG8joI99+XDe9tjeezBCPBZHKtWPcqkMr2LhYjtvRmhM0BGmV0bkRG6q6RI7IjaK5reWfidnj7963RBoh03vQHt8/1RoV/dtLryIuZ152d3rwHUdFF+KcGMuoio0ujGVjzpwXALiENjENoK7YweBjdrTSIxiaDANxyYYHhg16FiKZOuwQSxFrodt2biuXBkRY6OUEeMt9T0IycEtblDYIkDlubDUv9kLEEmg345e4QiZ9WkZTQgk+5IoFh9RrVXNCNGuYIx24+xnDkO+UdMea6/N5r+fjrz+JP4B9D3lCUxVRHUAAAAASUVORK5CYII=) 4px center no-repeat} -.offline-action.delete-database{margin:0;background: #FFF url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAD9SURBVBgZBcFLLkNRAADQc1/fU6qkhFRMMNIQn8TUQCJWYBE2YBkWYQWMJIZmNuAXCSoGFUGIInJf33VOSAAAAIAcgLOFt3079flaEdTS50M6nT7YeggJwPFle6nhAoVhc370rnaXcwBSp62GTdxoGdPrkAPQD5OSbRFr6oLvjByA53CqY9YUvjy68YQcgELTuTd/khENbQk5ANGqFUSFnq6WW2QA5Op4VuhreJVEZACUAKiJkogMgIEKANFARAZAKQKolColMgA+f7vVkBkRSeYjvf6QAfB1cnnXNWTUhHHrXuLoESEBYO/aYjNUSqX3snk/2DjshwQAAAD4B9GUWR0G4scKAAAAAElFTkSuQmCC) 4px center no-repeat} -.offline-menu-variable{margin-left: 5px} -.offline-icon{vertical-align:middle} - -/* Project / OrgUnit header banners */ -.banner{width:100%;height:100%;border-spacing:0;border-collapse:collapse} -.banner-logo{padding-left:12px;width:70px} -.banner-flex{padding-left:10px} - -/* Project dashboard : linked project edit button */ -.project-linkedProject-editButton{width:13px;height:13px} -.project-linkedProject-editButton-down-hovering{border-width:1px;border-style:solid;border-bottom-color:#FFFCEC;border-right-color:#FFFCEC;border-top-color:#FFF8D7;border-left-color:#FFF8D7} -.project-linkedProject-editButton-up-hovering{border-width:1px;border-style:solid;border-bottom-color:#FFF8D7;border-right-color:#FFF8D7;border-top-color:#FFFCEC;border-left-color:#FFFCEC} -.x-combo-list-item-disabled{font-weight:bold !important;text-align:center} - -/* Project dashboard : phases */ -.project-current-phase-panel{background-color:white} -.project-phase-active span.x-tab-strip-text {padding-left:14px;background:transparent url(../images/icon/bullet_star.png) no-repeat left center} -.project-phase-closed span.x-tab-strip-text{padding-left:14px;background:transparent url(../images/icon/bullet_star_black.png) no-repeat left center} - -/* Project details */ -.project-label-10{font-size: 10pt} - -/* Toolbar */ -.toolbar-title{font-weight:bold !important;margin-left:4px;margin-right:4px !important} - -/* Amendements */ -.amendment-action,.amendment-action:visited{font-weight:bold;color:#4B3E2D} - -/* Reminders/Monitored points */ -.header-label{font-size:11px;font-style:italic;display:block;margin-bottom:10px} -.points-date-exceeded{color:red} -.points-completed{text-decoration:line-through;cursor:pointer} - -/* Calendar */ -.calendar{border-collapse:collapse;padding:0;font-size:10pt} -.calendar-header{text-align:center;font-weight:700;font-size:14pt;padding-bottom:8px} -.calendar-column-header{text-align:center;font-weight:700} -.calendar-row-header{width:2%;padding-right:4px;vertical-align:top;color:#EE9329;font-weight:700} -.calendar-cell{border:1px solid lightgrey;vertical-align:top} -.calendar-day .calendar-cell{width:98%;height:96%} -.calendar-month .calendar-cell{width:14%;height:16%} -.calendar-week .calendar-cell{width:14%;height:96%} -.calendar-cell-other-month{background-color:#EFEFEF} -.calendar-cell-other-month .calendar-cell-header{color:lightgrey} -.calendar-cell-header{height:16px;font-weight:700;color:#555;padding-right:4px;text-align:right} -.calendar-cell-today{background-color:#eaeff8} -.calendar-event{overflow:hidden;height:16px;cursor:default} -.calendar-fullday-event{font-weight:700;color:#fff;background-color:#000} -.calendar-event-date{padding-left:4px;font-size:9pt} -.calendar-event-label{padding-left:4px} -.calendar-event-1{color:#EE9329} -.calendar-fullday-event-1{background-color:#EE9329} -.calendar-event-2{color:#1c61d9} -.calendar-fullday-event-2{background-color:#1c61d9} -.calendar-event-3{color:#8cbf40} -.calendar-fullday-event-3{background-color:#8cbf40} -.calendar-event-4{color:#ad2d2d} -.calendar-fullday-event-4{background-color:#ad2d2d} -.calendar-event-5{color:#9643a5} -.calendar-fullday-event-5{background-color:#9643a5} -.calendar-event-6{color:#737373} -.calendar-fullday-event-6{background-color:#737373} -.calendar-event-limit{color:#482A1E;text-align:center;font-weight:700;width:100%;height:16px;display:block;text-decoration:none} -.calendar-event-limit:hover{color:#EE9329} - -/* Calendar Popup */ -.gwt-DecoratedPopupPanel{background-color:#fff;border:1px solid darkgrey;font-size:10pt;padding:4px} -.calendar-popup-header{font-weight:700} -.calendar-popup-date{font-size:9pt;font-weight:700} -.calendar-popup-description{padding-top:4px;padding-bottom:4px;whitespace:pre!important} - -/* LogFrame */ -.logframe-grid-add-action,.logframe-grid-add-group-action{text-align:right;text-decoration:underline;cursor:pointer} -.logframe-grid-code-label{font-weight:700} -.logframe-grid-code-label-active{text-decoration:underline;cursor:pointer} -.logframe-grid-menu-button{display:block;color:#000;margin-left:8px;text-decoration:none;cursor:pointer;background-color:transparent;background-image:url(../images/icon/context_menu_icon.png);background-repeat:no-repeat;width:8px;height:8px} -.logframe-grid-menu-button-active{background-image:url(../images/icon/context_menu_icon_orange.png)} -.log-frame-indicators-table{table-layout:fixed;margin-bottom:8px} -.log-frame-indicators-table-cell{white-space:normal;width:50%;overflow:hidden;border-bottom:solid 1px #EDEDED;padding:5px 0 2px 2px} - -/* Flex table view */ -.flextable-view-group-cell{background-color:#E7D2A3} -.flextable-view-group-label{font-weight:bold;line-height: 20px} -.flextable-view-merged-row{border-top:0} - -/* GWT HTML Table */ -.html-grid-header-row{border-bottom:solid 1px #B7A076;background:url(../images/header/grid3-hrow-2.gif) 0 bottom #F9F9F9;text-align:right;white-space:normal} -.html-grid-header-row div.gwt-Label{white-space:normal} -.html-textbox{padding:0;border:0;overflow:auto;line-height:14px;font-family:arial,tahoma,helvetica,sans-serif;font-size:11px;color:#4B3E2D} -.html-textbox:focus{background-color:#EFE8D9} -.html-textbox-cell{padding:3px 3px 3px 5px} -.html-table-cell{border-top:solid 1px #EDEDED;border-right:solid 1px #EDEDED} - -/* Reports */ -.project-report{padding-top:4px;padding-left:8px;padding-right:32px;font-size:10pt} -.project-report-draft{font-size:10pt;color:#fff;width:100%;margin:0;background-color:#4a3f2b;padding-left:8px;padding-right:24px;line-height:32px} -.project-report-personalDraft{font-weight:700} -.project-report-draft-button{float:right;height:100%} -.project-report-field{margin-top:4px;margin-bottom:16px} -.project-report-field-empty{color:#888;margin-top:4px;margin-bottom:16px} -.project-report-level-1{margin-bottom:16px!important;width:100%} -.project-report-level-1 .fold-title{text-transform:uppercase;font-size:14pt;font-weight:700;color:#000} -.project-report-level-2 .fold-title{text-transform:none;font-size:12pt} -.project-report-level-3 .fold-title{font-size:10pt} -.project-report-key-question-label{font-size:12px;font-weight:700} -.project-report-key-question{margin:0;border:0;border-top:1px solid #000;background-color:#fff;display:block;width:100%} -.gwt-RichTextArea{border:1px solid #000;display:block;margin-top:4px;margin-bottom:4px;width:100%} -.fold{margin-top:4px;margin-bottom:4px} -.fold-title{cursor:pointer;padding-left:16px} -.fold-tool-button{float:left;cursor:pointer} -.fold-tool-button:hover{background-color:#e7d2a3!important;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px} -.fold-content{padding-left:20px} -.fold-folded{background:url(../images/tree/fold-folded.png) left center no-repeat} -.fold-collapsed{background:url(../images/tree/fold-expand.png) left center no-repeat} -.fold-expanded{background:url(../images/tree/fold-collapse.png) left center no-repeat} - -/* Administration */ -.form-header-label{padding:5px 0 8px 5px;margin:0 5px;border-bottom:1px solid #aaa;font-style:italic;color:#aaa} -.form-hint{padding-bottom:6px;display:block} - -/* Maintenance */ -.header-alert {color: black !important;background-color: rgb(255, 90, 90) !important;background-image: none !important;border: 1px black solid !important;} - -.list-combobox__elements { display: flex; flex-wrap: wrap; padding-bottom: 10px; } -.list-combobox__elements__element { display: flex; padding: 5px 10px 5px 0; } -.list-combobox__form { display: flex; } - -.messageElement{line-height: 1.8em;font-size: 12px;} - -/* trace */ -#trace-menu{position:absolute;top:32px;right:0px;width:320px;z-index:1;background-color:#646263;color:#FFF;text-align:left;border-radius:6px 0 6px 6px;;padding:6px;line-height:normal;font-weight:normal} -#trace-menu h1{font-weight:bold; margin:5px 0} -.trace-action{background-color:#FFF;border-radius:4px;color:#000;text-decoration:none;font-weight:bold;font-size:11px;display:block;text-align:center;margin:5px 0;padding:5px;line-height:1} -.trace-action-disabled{background-color:lightgray;color:gray;cursor:default} -.trace-action-separator{border:0;height:1px;background-color:#999} -.trace-action.send-report{background: #FFF url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAFzUkdCAK7OHOkAAAAEZ0FNQQAAsY8L/GEFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAFnRFWHRDcmVhdGlvbiBUaW1lADA0LzExLzA4YZUFlAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNAay06AAAAJASURBVDhPvZJNTxNRFIafO9MaaqltaaGCkYILQdPGKCsMTYz+AdzoysSNv8KNC1d+bPwbssMEkybGBag1NEAIoQlqkUocoLHTpmk7nemMdy6gLI0mvpObyZw75znnvucKT4p/kHb0/mv9P4BtOzRqTTZ33h9FDvVHHnS7Njvb33i9/oJasEhu/AE3svfUngLs7+9TqVRotVoqeFKu62H+qFOq5gmNVQgPW1S2atydes6l0etotm2r5HA4TCKRIB6P/1qxWAxPAsoHK3jJbQbSOl2tRuhsi/n1x3SsNsKyLG9tbY1Op0MulzuqeyjH7rG8+oHFvadcvjKOEDpfzHfomodhVIl1rqH5FgwODpLJZJibm0MCcRxHnrtLXZq2+v0l9YbJq/kFWnULTYCx06S9m8Rs7h1OwYf4Lc/MzJDP52k0GiqG7nD/1jNuxp8Qta7iykeWxHHb3J56yKM7b38D/JVMJkmn06qTarWqPCksL7H5aZX4QMT/VdoujRU2PdFWnwoghFDLr1wqlZiYmMD3pVAoYJom4f5+BdQCcCE2TbxvVHZhKUDAT3Rdl3K5rBJmZ2fRdV3Bms0m2WyWA6PG3tIbFlcWiEUj1Mw6p8+fUQAhK3gbGxtEIhEmJycJBoNq46Qc22Vr9yOfv5bodYWcwimyF6cZSZ1DGIbhFYtFNE1TF0mZJ3V8rGN/ZBp9fSF6vZ4EaAyPpEiPpRGyfXUTJUiN0G/bT/TvhT9OX4FAgFAopECpVIqhoSGi0aiMB/gJXawlNgZ2Ef4AAAAASUVORK5CYII=) 4px center no-repeat} -.trace-action.enable-trace{background: #FFF url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAA+VBMVEU4YwBAagBFbQFIcwJMdQlRfAxVfBZVfhNWfBZYeR5ahhRbfCNcihVdfiRdgx5dhB5dhB9ehx1ggCdggihhjhxjhCtjkR1kiydkjSJliydliyhljChmiC5mkyFmlyBoijBokShqmCRqnx9rjTRtlDFulDFulTJwmDJwnytwoyhxnTN1njt1pTF2nzt2nzx3oz14oz14qjJ7pz9+p0R+qEWCrEeEsUmGr02GsE6Iu0aKtVGNt1aQuViSvFqZxWOcr3qesX2esX6ltoSmt4iouYurvI6zw5m9yqXI0bbi49zj5Nzk5t/m5+Ho6uPo6+Pr7ebu7+v19PX////ye0A4AAAAiElEQVQY02MIQgMM+AQ8lZxQBLx07CydkQS8NWytbQw9gAL+7iC+j6KVuYWZMlBFgIimS1CQr5ipsYmRPNAMPx4DPTnXQB59bV0tGZAtblxqqmqyEuoqqgqiEGvtWaUlpcQlJQWFYe6wZxbg4+NnF0I4zJ6Rg42FF9mlDgxM3KhOd+QkznNgAABhT0M7fSgVFAAAAABJRU5ErkJggg==) 4px center no-repeat} -.trace-action.disable-trace{background: #FFF url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAAK/INwWK6QAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADYUExURcwiANU8HdZMMdoyENtIJttXPdxFJt5dQt9rU+I/HeNBH+Q6GORgROVQLuWOfeWQf+Z1XudiQOhHJelJJ+pLKeyYhuypm+13Ve2qne6vo/BwVfByUPK1qPNKKPNNK/RSMPRbOfWIcfdkQvdxT/fb1fhuT/h/ZPiolvjd1/m/s/ni3vpsSvt/XfxjQfyEavyTe/1hP/12V/2Mav2ScP3Asv6CYP6GZP7BtP7FuP7k3v7o5P9VM/9ePP9jQf9mRP97Wf+DaP+EYv+Zd/+qiP+xoP+yof/m4P///5IuMgkAAAC6SURBVBjTXc/JdgFRAIThMoSgEbO0mMcESdAdEVxDi//938jikpOjdl+tqsRdBHA+7Y3Zn863Yjnzj0Fw9GdLW3jjRSUqRSuLsQdi1Z/nHp7h0QTz/gox7Nbib/BrAtW6Q4Q7Sb9YP6UnLiJ/SFhnSRzyiOSucDWFXRLhdFpt69dWx0GUilPrn8G0WEKMYs0vfcD3+2czNkJQjTQ2W2O2m0akaqeXQ6n6el1Phcq3c71MWApnen9v/+cCydYyJ9Lg6qMAAAAASUVORK5CYII=") 4px center no-repeat} -.trace-menu-variable{margin-left: 5px} - -ul.x-tab-strip { - width: auto !important; -} - -/* Contact */ -.contact-grid-name a{text-decoration:underline;cursor:pointer;color:#4B3E2D} - -.contact-card-label { - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 5px 0; - font-size: 14px; -} -.contact-card-name { - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 5px 0; - font-size: 18px; - font-weight: bold; -} -.contact-card-organization { - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 5px 0; - font-size: 18px; -} -.contact-card-avatar { - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 5px; - background-repeat: no-repeat; - background-origin: content-box; - background-position: 50% 0%; - background-size: contain; -} -.contact-card-avatar-individual { - background-image: url("../images/icon/individual-128.png"); -} -.contact-card-avatar-organization { - background-image: url("../images/icon/organization-128.png"); -} -.contact-details-photo { - max-width: 150px; - max-height: 150px; -} -.contact-details-container .x-box-inner { - overflow: auto !important; -} +/* + * #%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 + * . + * #L% + */ +.noscript{max-width:550px;font-family:sans-serif;font-weight:700;text-align:center;color:#FFF;background-color:red;border:3px solid red;position:relative;z-index:99999991;margin:50px auto 0;padding:8px;} + +.work-in-progress-label{color:#DF4848;font-weight:bold;background:url(../images/icon/traffic-cone.png) no-repeat 0 50%;padding-left:22px;height:22px;line-height:22px} + +/* Application view */ +body {font-family:Arial;font-size:8pt} +#header{height:56px;width:100%;float:left;background:url(../images/header/header-bg.jpg) repeat-x;clear:both;} +#header-left{height:56px;width:135px;float:left;padding-left:25px;background-color:#E86F00;background:url(../images/header/header-bg-left.jpg) no-repeat;} +#header-middle{height:56px;width:420px;float:left;background:url(../images/header/header-bg-middle.jpg) no-repeat;} +#header-right{height:56px;width:360px;float:right;background:url(../images/header/header-bg-right.jpg) no-repeat top right} +#orglogo{width:100%;height:100%;background-color:transparent;background-position:left center;background-repeat:no-repeat;opacity:0.5;} +#orgname{height:40px;width:420px;float:left;padding-top:9px;padding-left:6px;font-size:18px;font-weight:700;color:#fff;clear:both;text-transform:uppercase;} +#username{height:16px;width:340px;float:right;text-align:right;margin-right:80px;padding-top:2px;padding-left:10px;font-size:11px;color:#fff;clear:both;position:relative} +#username div{display:inline;padding-left:15px;background:transparent url(../images/header/username.png) left 1px no-repeat;} +#username span{display:block;position:absolute;top:16px;right:-0.5em;padding:4px 4px 4px 24px;background:#EC9235 url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAH2SURBVDjLjZNLTxNRGIaJv6ZNWeBwkZFLQtGAC4l/wKULV+7YILeSYukEUhJoSASVuCI0hpAYDSUQCJBSoAaC0wbBUi4aWphpO52Zlpa+nnOqCAptJ3k3M3me73LOlAAoyZfDqQdOEvyO89/vRcGZ5HeWmySFYdWHVOQN0vE58jrLJMFJ82hewVU4+bMfqdPxP9VBn+A4D88wP59PwFqmsH7UgeTJEMlsTuIyI5uRsDfCMcmtAtoyhVmOu5kkHZuFsiNA3XuEi+QCdhxluL0D/SvpoO+vhIksiItNiPqqyXgfIL403gjfoTsIL70gQBdim3VQvz2FFnwOxf8E8kYF0rIVYqcRM70Vgf/Pe/ohwsutOJdcpBpP4Mek+jPEfbWQVzkG+7tNcNsqt68tkcLZTIzM6YZ21IbolgHq9j1o+z04nKhHRnlH2p6A32LCvFD55fIYr960VHgSSqCFVDJBEeugh+zw2jnpc0/5rthuRMBaioWBqrVrFylXOUpankIi0AjJY0DC3wD9oA9rAnc2bat+n++2UkH8XHaTZfGQlg3QdlsIbIVX4KSPAv+60L+SO/PECmJiI1lYM9SQBR7b3einfn6kEMwEIZd5Q48sQQt1Qv/xFqt2Tp5x3B8sBmYC71h926az6njdUR6hMy8O17wqFqb5Bd2o/0SFzIZrAAAAAElFTkSuQmCC") no-repeat 4px center;text-decoration:underline;cursor:pointer} +#userlogout{float:right;font-size:11px;height:16px;margin-right:15px;padding-top:3px;text-align:right;width:92px;} +#userlogout a{color:#EE9329;text-decoration:none;background:transparent url(../images/header/logout.png) left 2px no-repeat;padding-left:15px;} +#userlogout a:hover{text-decoration:underline;} +#header-menu{color:#C2C1C1;float:right;font-size:11px;height:16px;padding-top:3px;text-align:right;width:245px;} +#header-menu a{color:#C2C1C1;font-size:11px;text-decoration:none;} +#header-menu a:hover{text-decoration:underline;} +#offline-status{color:#FFF;float:right;font-size:12px;font-weight:700;height:36px;line-height:36px;margin-right:145px;text-align:right;position:relative} +#app-loader{position:relative;width:23px;height:23px;left:239px;top:26px;background-color:transparent;background-position:center;background-repeat:no-repeat;} +#app-loader.loading{background-image:url(../images/loader/app-loader.gif);} +#menu{clear:both;} +#menu .bar{background:url(../images/menu/menu-bar-repeat.jpg) repeat-x scroll 0 0 rgba(0,0,0,0);clear:both;float:left;height:34px;overflow:hidden;position:relative;width:100%;} +#menu .bar-decoration-left{background-color:#E86F00;height:100%;left:0;position:absolute;width:15px;} +#menu .bar-decoration-left-round{background-image:url(../images/menu/menu-bar-top-left.png);height:5px;left:15px;position:absolute;width:5px;} +#menu .menu-buttons{background:url(../images/menu/menu-buttons-bg.png) no-repeat scroll 0 0 rgba(0,0,0,0);height:34px;position:absolute;right:0;width:55px;} +#menu .menu-buttons .gwt-Button{display:inline-block;background:transparent url(../images/menu/menu-buttons.png) repeat 0 0;border:1px solid #3C3C3E;height:34px;width:20px;} +#menu .menu-buttons .menu-button-left{border-bottom-left-radius:4px;border-top-left-radius:4px;} +#menu .menu-buttons .menu-button-left:hover{background-position:0 -32px;} +#menu .menu-buttons .menu-button-left:active{background-position:0 -64px;} +#menu .menu-buttons .menu-button-left:disabled{background-position:0 -96px;} +#menu .menu-buttons .menu-button-right{border-bottom-right-radius:4px;border-top-right-radius:4px;background-position:18px 0;} +#menu .menu-buttons .menu-button-right:hover{background-position:18px -32px;} +#menu .menu-buttons .menu-button-right:active{background-position:18px -64px;} +#menu .menu-buttons .menu-button-right:disabled{background-position:18px -96px;} +#menu .tabs {position:absolute;overflow:hidden;width:100%;height:100%;margin-left:15px;} +#menu .tabs .tab{cursor:default;float:left;position:absolute;overflow:hidden;} +#menu .tabs .tab .tab-left{float:left;width:11px;height:34px;background:transparent url(../images/menu/tab-left.png) no-repeat 0 0;} +#menu .tabs .tab .tab-middle{float:left;font-size:12px;height:34px;padding-top:13px;padding-right:5px;color:#B3B3B3;background:transparent url(../images/menu/tab-middle.png) repeat-x 0 0;} +#menu .tabs .tab .tab-right{float:left;width:3px;height:34px;padding-top:10px;padding-left:3px;background:transparent url(../images/menu/tab-right.png) no-repeat right top;} +#menu .tabs .tab.closeable .tab-right{width:19px;background-position:0 0;} +#menu .tabs .tab .tab-close{position:absolute;height:11px;width:11px;right:6px;bottom:22px;background:transparent url(../images/menu/close.png) no-repeat 0 0;} +#menu .tabs .tab .tab-close:hover{background-position:0 -11px;} +#menu .tabs .tab.home{margin-right:2px;} +#menu .tabs .tab.home .tab-left{width:37px;background-image:url(../images/menu/tab-home-left.jpg);} +#menu .tabs .tab.active .tab-left{background-image:url(../images/menu/tab-left-over.jpg);} +#menu .tabs .tab.active .tab-middle{color:#FFF;background-image:url(../images/menu/tab-middle-over.jpg);} +#menu .tabs .tab.active .tab-right{background-image:url(../images/menu/tab-right-over.jpg);} +#menu .tabs .tab.home.active .tab-left{background-image:url(../images/menu/tab-home-left-over.png);} +#app-message{clear:both;} +#app-message .message-panel,.popup-content .message-panel{padding:10px 15px 0 15px;} +#app-message .message,.popup-content .message{font-size:13px;border:1px solid #000;border-radius:4px;padding:5px 0 5px 30px;background-color:transparent;background-position:5px 6px;background-repeat:no-repeat;} +#app-message .message{background-position:5px 3px;} +#help{width:100%;} +#help .help-content{width:100%;} +#help .help-content iframe{width:100%;height:518px;border:0;} +#credits{width:100%;border-collapse:separate;border-spacing:10px;} +#credits .properties{width:100%;border-collapse:inherit;} +#credits .properties td:first-child{width:230px;} +#credits .version{width:100%;border-collapse:inherit;} +#credits .version td{text-align:center;} +#credits .version .version-logo{margin:0 auto;width:214px;height:167px;background:transparent url(../images/credits/logo.png) no-repeat center;} +#credits .version .version-name{padding-top:25px;font-weight:bold;} +#credits .version .version-number{padding-top:2px;font-weight:bold;} +#credits .version .version-ref{padding-top:2px;} +#credits .team{width:100%;border-collapse:inherit;} +#credits .team-scroll{max-height:240px;margin-left:15px;} +#credits .team .team-label{font-weight:bold;padding-top:20px;} +#credits .team tr:first-child td:first-child .team-label{padding-top:0;} +#credits .team table{width:100%;} +#credits .team table div{margin-left:15px;margin-top:3px;} +#credits .team a{color:#4B3E2D;} +#credits .timeline{width:100%;border-collapse:inherit;border-top:3px solid #1B3280;padding-top:10px;} +#credits .timeline .timeline-image{height:184px;background:transparent url(../images/credits/timeline.png) no-repeat center;} +#content {clear:both;background-color:transparent;}/*Paddings are dynamically set in ApplicationView.*/ +.layout-transparent{background:transparent} +.layout-with-v-scroll{overflow-y:scroll} +.layout-with-h-scroll{overflow-x:scroll} +.white-background{background:#fff} +.sigmah-tab-panel .x-tab-panel-header-plain .x-tab-strip-spacer{border:none;height:0} +.white-tab-body .x-tab-panel-body {background:#fff} + +/* Notifications N10N */ +#app-message .message-panel.info .message,.popup-content .message-panel.info .message{background-color:#E7F3FF;border-color:#7BA6D6;color:#5C7CA0;background-image:url(../images/icon/information.png);} +#app-message .message-panel.question .message,.popup-content .message-panel.question .message{background-color:#E7F3FF;border-color:#7BA6D6;color:#5C7CA0;background-image:url(../images/icon/question-mark.png);} +#app-message .message-panel.warning .message,.popup-content .message-panel.warning .message{background-color:#FEFFCF;border-color:#EBAE7F;color:#D85D01;background-image:url(../images/icon/error.png);} +#app-message .message-panel.error .message,.popup-content .message-panel.error .message{background-color:#FFE7E7;border-color:#E77D7B;color:#AD5E5C;background-image:url(../images/icon/exclamation.png);} +#app-message .message-panel.valid .message,.popup-content .message-panel.valid .message{background-color:#E7FFD6;border-color:#8CD76B;color:#69A150;background-image:url(../images/icon/accept.png);} +#app-message .message-panel.offline .message,.popup-content .message-panel.offline .message{background-color:#646263;border-color:#000;color:#FFF;background-image:url(../images/icon/information.png);} +.popup-content .message-panel{background-color:white;padding-bottom:10px} +.x-window.notification .popup-content .message-panel{padding:0;} +.x-window.notification .popup-content .message{border:none;} +.x-window.notification.info table.x-component tr:first-child td:first-child, +.x-window.notification.question table.x-component tr:first-child td:first-child, +.x-window.notification.confirmation.question .form-panel .x-panel-footer{background-color:#E7F3FF;} +.x-window.notification.warning table.x-component tr:first-child td:first-child{background-color:#FEFFCF;} +.x-window.notification.error table.x-component tr:first-child td:first-child{background-color:#FFE7E7;} +.x-window.notification.valid table.x-component tr:first-child td:first-child{background-color:#E7FFD6;} +.x-info.info .x-info-tl,.x-info.info .x-info-tr,.x-info.info .x-info-bl,.x-info.info .x-info-br{background-image:url(../images/notif/corners-sprite-info.png);} +.x-info.info .x-info-tc,.x-info.info .x-info-bc{background-image:url(../images/notif/top-bottom-info.png);} +.x-info.info .x-info-ml,.x-info.info .x-info-mr{background-image:url(../images/notif/left-right-info.png);} +.x-info.info .x-info-mc{background-color:#E7F3FF;} +.x-info.info .x-info-body{color:#5C7CA0;} +.x-info.warning .x-info-tl,.x-info.warning .x-info-tr,.x-info.warning .x-info-bl,.x-info.warning .x-info-br{background-image:url(../images/notif/corners-sprite-warning.png);} +.x-info.warning .x-info-tc,.x-info.warning .x-info-bc{background-image:url(../images/notif/top-bottom-warning.png);} +.x-info.warning .x-info-ml,.x-info.warning .x-info-mr{background-image:url(../images/notif/left-right-warning.png);} +.x-info.warning .x-info-mc{background-color:#FEFFCF;} +.x-info.warning .x-info-body{color:#D85D01;} +.x-info.error .x-info-tl,.x-info.error .x-info-tr,.x-info.error .x-info-bl,.x-info.error .x-info-br{background-image:url(../images/notif/corners-sprite-error.png);} +.x-info.error .x-info-tc,.x-info.error .x-info-bc{background-image:url(../images/notif/top-bottom-error.png);} +.x-info.error .x-info-ml,.x-info.error .x-info-mr{background-image:url(../images/notif/left-right-error.png);} +.x-info.error .x-info-mc{background-color:#FFE7E7;} +.x-info.error .x-info-body{color:#AD5E5C;} +.x-info.valid .x-info-tl,.x-info.valid .x-info-tr,.x-info.valid .x-info-bl,.x-info.valid .x-info-br{background-image:url(../images/notif/corners-sprite-valid.png);} +.x-info.valid .x-info-tc,.x-info.valid .x-info-bc{background-image:url(../images/notif/top-bottom-valid.png);} +.x-info.valid .x-info-ml,.x-info.valid .x-info-mr{background-image:url(../images/notif/left-right-valid.png);} +.x-info.valid .x-info-mc{background-color:#E7FFD6;} +.x-info.valid .x-info-body{color:#69A150;} +.x-info.offline .x-info-tl,.x-info.valid .x-info-tr,.x-info.valid .x-info-bl,.x-info.valid .x-info-br{background-image:url(../images/notif/corners-sprite-offline.png)} +.x-info.offline .x-info-tc,.x-info.valid .x-info-bc{background-image:url(../images/notif/top-bottom-offline.png)} +.x-info.offline .x-info-ml,.x-info.valid .x-info-mr{background-image:url(../images/notif/left-right-offline.png)} +.x-info.offline .x-info-mc{background-color:#646263} +.x-info.offline .x-info-body{color:#FFF} +.x-info .x-info-header-text{padding-left:23px;background-color:transparent;background-position:left center;background-repeat:no-repeat;} +.x-info.info .x-info-header-text{background-image:url(../images/icon/information.png);} +.x-info.warning .x-info-header-text{background-image:url(../images/icon/error.png);} +.x-info.error .x-info-header-text{background-image:url(../images/icon/exclamation.png);} +.x-info.valid .x-info-header-text{background-image:url(../images/icon/accept.png);} +.x-info.offline .x-info-header-text{background-image:url(../images/icon/information.png); color: #FFF} +.notif-message{margin-top:15px;} +.notif-message.notif-first{margin-top:0;} +.notif-message ul.notif-list{margin-top:3px;padding-left:15px;list-style:disc outside none;} + +/* Administration */ +.preview-wrapper{border:1px solid #ccc;padding:5px 0;text-align:center} +.backup-status{border:1px solid #ccc;padding:5px} +.backup-status .details-panel{margin-top:5px} +.backup-status .details-panel td{font-size:90%;color:#bbb;padding:2px;font-style:italic} +.backup-status .details-panel td.details-panel-label{font-weight:bold;padding-left:15px;padding-right:5px} + +/* Sub Menu and sub content container */ +/* TODO : finish color mantis 0000599 */ +#content .sub-menu.vertical{width:100%} +#content .sub-menu .sub-menu-item{cursor:pointer;font-weight:bold;color:white;text-decoration:underline;padding:5px;} +#content .sub-menu .sub-menu-item.active{cursor:default;color:black;text-decoration:none;background-color:white;border-radius:5px;text-align:center;} +#content .sub-menu.vertical .sub-menu-item{margin-bottom:15px;} + +/* MockUpView */ +#mockup fieldset{border:1px solid #FFF;margin-bottom:12px;padding:12px;} +#mockup fieldset legend{color:#FFF;font-size:13px;font-weight:bold;} + +/* LoginView */ +.login-background{position:absolute;top:0;left:0;width:100%;height:100%;background-color:#494748} +.login-box{position:absolute;left:50%;top:50%;width:650px;height:170px;margin-left:-325px;margin-top:-85px} +.login-box-logo{width:250px;height:150px;text-align:left} +.login-box-form{width:400px;height:150px;background-color:#e96f00;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px} +.login-box-form-label{font-family:tahoma,arial,helvetica,sans-serif;font-size:12px;color:#fff;text-align:right;width:120px;padding-right:8px} +.login-box-form-forgotten{font-family:tahoma,arial,helvetica,sans-serif;font-size:11px;font-weight:700;color:#fff} +.login-box-form-separator{width:33%;height:14px} + +/* Monitored points */ +.points-date-exceeded{color:red;} +.points-completed{text-decoration:line-through;cursor:pointer;} + +/* Create projects view */ +.create-project-type{text-align:right;} +.create-project-type table{display:inline-block;} +.create-project-type .create-project-type-label{margin-left:5px;} + +/* Flexibility */ +.flexibility-layout{padding:4px 20px 0 0} +.flexibility-layout td{vertical-align:top} +.flexibility-textarea{padding-bottom:16px} +.flexibility-element-label{font-size:8pt} +.flexibility-element-field-label{font-weight:bold} +.flexibility-text-field{padding-left:0;padding-right:0} +.flexibility-action{text-decoration:underline;cursor:pointer;color:#4B3E2D} +.flexibility-action-iconable{padding-left:4px} +.flexibility-label{font-family:tahoma,arial,helvetica,sans-serif} +.flexibility-link{color:#4B3E2D} +.hyperlink-label{text-decoration:underline;cursor:pointer} + +/* Project : Grid */ +.project-starred-icon{cursor:pointer} +.project-grid-node{font-weight:bold} +.project-grid-leaf{font-weight:normal} +.project-grid-code a{text-decoration:underline;cursor:pointer;color:#4B3E2D} +.project-grid-code-icon{padding-right:5px} +.project-refresh-button button{font-weight:bold} +.important-label{font-size:8pt;padding:5px} +.important-label-white{font-size:8pt;padding:5px;color:white} +.monitor-progress-bar{width:50%;z-index:200} +.filtered-column-header{font-weight:bold;font-style:italic;background:url("../images/icon/filter.png") no-repeat right} +.project-model-type-radio,.project-model-type-radio *{cursor:pointer} + +/* Project : RatioBar */ +.blockStat{border:1px solid #B9A48F;padding:1px;background:transparent url(../images/ratiobar/ratio-bar-bg.png) repeat-x scroll 0 1px} +.blockStat div{height:11px;line-height:10px;color:white;font-weight:bold;font-family:tahoma;font-size:11px;text-align:center;background-repeat:repeat-x;background-position:0 0} +.blockStatBgRed{background-color:red} +.blockStatBgYellow{background-image:url(../images/ratiobar/ratio-bar-bg-yellow.png)} +.blockStatBgOrange{background-image:url(../images/ratiobar/ratio-bar-bg-orange.png)} +.blockStatBgBlack{background-image:url(../images/ratiobar/ratio-bar-bg-black.png)} +.blockStatUndefined{background:url(../images/ratiobar/ratio-bar-bg-black.png) repeat-x;-webkit-animation:blockStatAnim .4s steps(6) infinite;-moz-animation:blockStatAnim .4s steps(6) infinite;-ms-animation:blockStatAnim .4s steps(6) infinite;-o-animation:blockStatAnim .4s steps(6) infinite;animation:blockStatAnim .4s steps(6) infinite} +@-webkit-keyframes blockStatAnim{from{background-position:0px} to{background-position:-6px}} +@-moz-keyframes blockStatAnim{from{background-position:0px} to{background-position:-6px}} +@-ms-keyframes blockStatAnim{from{background-position:0px} to{background-position:-6px}} +@-o-keyframes blockStatAnim{from{background-position:0px} to{background-position:-6px}} +@keyframes blockStatAnim{from{background-position:0px} to{background-position:-6px}} + +/* Offline */ +.offline #header-left{background:none} +.offline #header-middle{background:none} +.offline-button{cursor:pointer;display:inline-block;padding:4px} +.offline-button-active{background-color:#646263;border-bottom:1px solid #999} +.offline .bar-decoration-left{background:url(../images/menu/menu-bar-repeat.jpg) repeat-x scroll 0 0 transparent} +.offline .bar-decoration-left-round{background-image:none !important} +#offline-menu{position:absolute;top:32px;right:0px;width:320px;z-index:1;background-color:#646263;color:#FFF;text-align:left;border-radius:6px 0 6px 6px;;padding:6px;line-height:normal;font-weight:normal} +#offline-menu h1{font-weight:bold; margin:5px 0} +.offline-progress{position:absolute;top:28px;left:0;right:0;background-color:#646263;height:2px} +.offline-progress .blockStatBgBlack,.offline-progress .blockStatBgYellow,.offline-progress .blockStatBgOrange,.offline-progress .blockStatBgRed{height: 100%;background: #FFF none} +.offline-progress .blockStatUndefined{height: 100%} +.offline-menu-progress{display:inline-block;width:220px;background-color:#A88F64;height:6px;margin-top:3px;border-radius:1px} +.offline-menu-progress .blockStatBgBlack,.offline-menu-progress .blockStatBgYellow,.offline-menu-progress .blockStatBgOrange,.offline-menu-progress .blockStatBgRed{height: 100%;background: #FFF none} +.offline-menu-progress .blockStatUndefined{height: 100%} +.offline-menu-progress-label{display: inline-block;width:100px} +.offline-sync-progress{border:1px solid #B9A48F;padding:1px;background:transparent url(../images/ratiobar/ratio-bar-bg.png) repeat-x scroll 0 1px} +.offline-sync-progress .blockStatBgBlack,.offline-sync-progress .blockStatBgYellow,.offline-sync-progress .blockStatBgOrange,.offline-sync-progress .blockStatBgRed{height:11px;line-height:10px;color:white;font-weight:bold;font-family:tahoma;font-size:11px;text-align:center;background-repeat:repeat-x;background-position:0 0;background-image:url(../images/ratiobar/ratio-bar-bg-black.png)} +.offline-action{background-color:#FFF;border-radius:4px;color:#000;text-decoration:none;font-weight:bold;font-size:11px;display:block;text-align:center;margin:5px 0;padding:5px;line-height:1} +.offline-action-disabled{background-color:lightgray;color:gray;cursor:default} +.offline-action-separator{border:0;height:1px;background-color:#999} +.offline-action.update-database{background: #FFF url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAmBJREFUOBGNU11IVEEU/nadNlghNAXbXcJFUyoSayFYsIegNSupffKhegiKoof+IIieop576q0HISsKAh8qULI/yCepTdfNanN/hVzdNVfR3b1z79x7pzs39uqKkgOHc+bM931zZuYMsInx8ls/3whm32hhdf7Tzw948Pb+uiK2MjAvzfNwNoSJ2QgSuRgWluchUwaFKnBvd0NRGPbV78f17psWR3DNSWoxxocSg8gXc9i2tQZORzXsNhuYzsBU1fQyk/F1fBQdjYdx7eQNS8Sel/7wodgAKCvBW9sEB3FA5zokRk2jTDK8BKrJoFQYLRdtejKa+YLs8gya6poNERklWUI0HUU8FTfKZ8YxFHjcbjCm4qDHj1s9t63dhQIZ/z0GJ6lGQSmiREsIT4ThbzqEh2f6LGDwrpvv9bThztl7Vq5cBpmcmcTi0gJUmYGrwPG2U7gYuFwB7DxwDFeCV23DqY9c13Roqg7TGzHpaT8NTdOgr0oK9XfpAd7p7TaFBFnkMvkMBiOvUSwUQCUZW+AACezpqthNAJ//eMRDmRERWuPxSC9/P/EGvlYfbFV2zOZmUMzK/57RQhlBf/QZj+ejUI1LS2aT5iWKy3TVutDY4AVxEDCNmU96YncQZDX51a8X/Hsugua6FvNYO2u8JlgQRE8s0yVUMYJkOoV62w4caQ9UCkC3Q5YVUIVC03UoopEE2bCSVMTcwhympzNwEQ/Od12Au85jtNua8eRzLx+bDpmtm5hKmK0sWtpJnNjV0AJ/awcCvqPwGOQ11JWp+DiXes+t+3lWUP+Jng73bUrgLx+GPJMd2jBiAAAAAElFTkSuQmCC) 4px center no-repeat} +.offline-action.transfert-files{background: #FFF url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAA6hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxNS0wMy0wNFQxNzowMzozMTwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjMuMTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpDb21wcmVzc2lvbj41PC90aWZmOkNvbXByZXNzaW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj43MjwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6WFJlc29sdXRpb24+NzI8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4xNjwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+MTY8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4K/3M5/gAAAZ9JREFUOBGdUrEvQ0Ec/vrevddqYlGV1IwE6R9AiKSDwYCEwZ9gkA7ShE3EQmJisZmZ1GDDIGFi6S6xaLRqIdV39+7O3b32Rasol/ze9+6X3/f97nffAX9Y2aNV2VputSZ+2t+XCljcW2gSiWhC7mbZJLnP4TMfjPqgHgOt6aDwVGhM9aRAKcPrM0N+7cRwSaPjeGISXCgB4YfBOAfjDEyo4EFe493bLWY2ZuXZ5mnECOjOujAkqyKmhAJyHesCvkLKGKR0TG8joI99+XDe9tjeezBCPBZHKtWPcqkMr2LhYjtvRmhM0BGmV0bkRG6q6RI7IjaK5reWfidnj7963RBoh03vQHt8/1RoV/dtLryIuZ152d3rwHUdFF+KcGMuoio0ujGVjzpwXALiENjENoK7YweBjdrTSIxiaDANxyYYHhg16FiKZOuwQSxFrodt2biuXBkRY6OUEeMt9T0IycEtblDYIkDlubDUv9kLEEmg345e4QiZ9WkZTQgk+5IoFh9RrVXNCNGuYIx24+xnDkO+UdMea6/N5r+fjrz+JP4B9D3lCUxVRHUAAAAASUVORK5CYII=) 4px center no-repeat} +.offline-action.delete-database{margin:0;background: #FFF url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAD9SURBVBgZBcFLLkNRAADQc1/fU6qkhFRMMNIQn8TUQCJWYBE2YBkWYQWMJIZmNuAXCSoGFUGIInJf33VOSAAAAIAcgLOFt3079flaEdTS50M6nT7YeggJwPFle6nhAoVhc370rnaXcwBSp62GTdxoGdPrkAPQD5OSbRFr6oLvjByA53CqY9YUvjy68YQcgELTuTd/khENbQk5ANGqFUSFnq6WW2QA5Op4VuhreJVEZACUAKiJkogMgIEKANFARAZAKQKolColMgA+f7vVkBkRSeYjvf6QAfB1cnnXNWTUhHHrXuLoESEBYO/aYjNUSqX3snk/2DjshwQAAAD4B9GUWR0G4scKAAAAAElFTkSuQmCC) 4px center no-repeat} +.offline-menu-variable{margin-left: 5px} +.offline-icon{vertical-align:middle} + +/* Project / OrgUnit header banners */ +.banner{width:100%;height:100%;border-spacing:0;border-collapse:collapse} +.banner-logo{padding-left:12px;width:70px} +.banner-flex{padding-left:10px} + +/* Project dashboard : linked project edit button */ +.project-linkedProject-editButton{width:13px;height:13px} +.project-linkedProject-editButton-down-hovering{border-width:1px;border-style:solid;border-bottom-color:#FFFCEC;border-right-color:#FFFCEC;border-top-color:#FFF8D7;border-left-color:#FFF8D7} +.project-linkedProject-editButton-up-hovering{border-width:1px;border-style:solid;border-bottom-color:#FFF8D7;border-right-color:#FFF8D7;border-top-color:#FFFCEC;border-left-color:#FFFCEC} +.x-combo-list-item-disabled{font-weight:bold !important;text-align:center} + +/* Project dashboard : phases */ +.project-current-phase-panel{background-color:white} +.project-phase-active span.x-tab-strip-text {padding-left:14px;background:transparent url(../images/icon/bullet_star.png) no-repeat left center} +.project-phase-closed span.x-tab-strip-text{padding-left:14px;background:transparent url(../images/icon/bullet_star_black.png) no-repeat left center} + +/* Project details */ +.project-label-10{font-size: 10pt} + +/* Toolbar */ +.toolbar-title{font-weight:bold !important;margin-left:4px;margin-right:4px !important} + +/* Amendements */ +.amendment-action,.amendment-action:visited{font-weight:bold;color:#4B3E2D} + +/* Reminders/Monitored points */ +.header-label{font-size:11px;font-style:italic;display:block;margin-bottom:10px} +.points-date-exceeded{color:red} +.points-completed{text-decoration:line-through;cursor:pointer} + +/* Calendar */ +.calendar{border-collapse:collapse;padding:0;font-size:10pt} +.calendar-header{text-align:center;font-weight:700;font-size:14pt;padding-bottom:8px} +.calendar-column-header{text-align:center;font-weight:700} +.calendar-row-header{width:2%;padding-right:4px;vertical-align:top;color:#EE9329;font-weight:700} +.calendar-cell{border:1px solid lightgrey;vertical-align:top} +.calendar-day .calendar-cell{width:98%;height:96%} +.calendar-month .calendar-cell{width:14%;height:16%} +.calendar-week .calendar-cell{width:14%;height:96%} +.calendar-cell-other-month{background-color:#EFEFEF} +.calendar-cell-other-month .calendar-cell-header{color:lightgrey} +.calendar-cell-header{height:16px;font-weight:700;color:#555;padding-right:4px;text-align:right} +.calendar-cell-today{background-color:#eaeff8} +.calendar-event{overflow:hidden;height:16px;cursor:default} +.calendar-fullday-event{font-weight:700;color:#fff;background-color:#000} +.calendar-event-date{padding-left:4px;font-size:9pt} +.calendar-event-label{padding-left:4px} +.calendar-event-1{color:#EE9329} +.calendar-fullday-event-1{background-color:#EE9329} +.calendar-event-2{color:#1c61d9} +.calendar-fullday-event-2{background-color:#1c61d9} +.calendar-event-3{color:#8cbf40} +.calendar-fullday-event-3{background-color:#8cbf40} +.calendar-event-4{color:#ad2d2d} +.calendar-fullday-event-4{background-color:#ad2d2d} +.calendar-event-5{color:#9643a5} +.calendar-fullday-event-5{background-color:#9643a5} +.calendar-event-6{color:#737373} +.calendar-fullday-event-6{background-color:#737373} +.calendar-event-limit{color:#482A1E;text-align:center;font-weight:700;width:100%;height:16px;display:block;text-decoration:none} +.calendar-event-limit:hover{color:#EE9329} + +/* Calendar Popup */ +.gwt-DecoratedPopupPanel{background-color:#fff;border:1px solid darkgrey;font-size:10pt;padding:4px} +.calendar-popup-header{font-weight:700} +.calendar-popup-date{font-size:9pt;font-weight:700} +.calendar-popup-description{padding-top:4px;padding-bottom:4px;whitespace:pre!important} + +/* LogFrame */ +.logframe-grid-add-action,.logframe-grid-add-group-action{text-align:right;text-decoration:underline;cursor:pointer} +.logframe-grid-code-label{font-weight:700} +.logframe-grid-code-label-active{text-decoration:underline;cursor:pointer} +.logframe-grid-menu-button{display:block;color:#000;margin-left:8px;text-decoration:none;cursor:pointer;background-color:transparent;background-image:url(../images/icon/context_menu_icon.png);background-repeat:no-repeat;width:8px;height:8px} +.logframe-grid-menu-button-active{background-image:url(../images/icon/context_menu_icon_orange.png)} +.log-frame-indicators-table{table-layout:fixed;margin-bottom:8px} +.log-frame-indicators-table-cell{white-space:normal;width:50%;overflow:hidden;border-bottom:solid 1px #EDEDED;padding:5px 0 2px 2px} + +/* Flex table view */ +.flextable-view-group-cell{background-color:#E7D2A3} +.flextable-view-group-label{font-weight:bold;line-height: 20px} +.flextable-view-merged-row{border-top:0} + +/* GWT HTML Table */ +.html-grid-header-row{border-bottom:solid 1px #B7A076;background:url(../images/header/grid3-hrow-2.gif) 0 bottom #F9F9F9;text-align:right;white-space:normal} +.html-grid-header-row div.gwt-Label{white-space:normal} +.html-textbox{padding:0;border:0;overflow:auto;line-height:14px;font-family:arial,tahoma,helvetica,sans-serif;font-size:11px;color:#4B3E2D} +.html-textbox:focus{background-color:#EFE8D9} +.html-textbox-cell{padding:3px 3px 3px 5px} +.html-table-cell{border-top:solid 1px #EDEDED;border-right:solid 1px #EDEDED} + +/* Reports */ +.project-report{padding-top:4px;padding-left:8px;padding-right:32px;font-size:10pt} +.project-report-draft{font-size:10pt;color:#fff;width:100%;margin:0;background-color:#4a3f2b;padding-left:8px;padding-right:24px;line-height:32px} +.project-report-personalDraft{font-weight:700} +.project-report-draft-button{float:right;height:100%} +.project-report-field{margin-top:4px;margin-bottom:16px} +.project-report-field-empty{color:#888;margin-top:4px;margin-bottom:16px} +.project-report-level-1{margin-bottom:16px!important;width:100%} +.project-report-level-1 .fold-title{text-transform:uppercase;font-size:14pt;font-weight:700;color:#000} +.project-report-level-2 .fold-title{text-transform:none;font-size:12pt} +.project-report-level-3 .fold-title{font-size:10pt} +.project-report-key-question-label{font-size:12px;font-weight:700} +.project-report-key-question{margin:0;border:0;border-top:1px solid #000;background-color:#fff;display:block;width:100%} +.gwt-RichTextArea{border:1px solid #000;display:block;margin-top:4px;margin-bottom:4px;width:100%} +.fold{margin-top:4px;margin-bottom:4px} +.fold-title{cursor:pointer;padding-left:16px} +.fold-tool-button{float:left;cursor:pointer} +.fold-tool-button:hover{background-color:#e7d2a3!important;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px} +.fold-content{padding-left:20px} +.fold-folded{background:url(../images/tree/fold-folded.png) left center no-repeat} +.fold-collapsed{background:url(../images/tree/fold-expand.png) left center no-repeat} +.fold-expanded{background:url(../images/tree/fold-collapse.png) left center no-repeat} + +/* Administration */ +.form-header-label{padding:5px 0 8px 5px;margin:0 5px;border-bottom:1px solid #aaa;font-style:italic;color:#aaa} +.form-hint{padding-bottom:6px;display:block} + +/* Maintenance */ +.header-alert {color: black !important;background-color: rgb(255, 90, 90) !important;background-image: none !important;border: 1px black solid !important;} + +.list-combobox__elements { display: flex; flex-wrap: wrap; padding-bottom: 10px; } +.list-combobox__elements__element { display: flex; padding: 5px 10px 5px 0; } +.list-combobox__form { display: flex; } + +.messageElement{line-height: 1.8em;font-size: 12px;} + +/* trace */ +#trace-menu{position:absolute;top:32px;right:0px;width:320px;z-index:1;background-color:#646263;color:#FFF;text-align:left;border-radius:6px 0 6px 6px;;padding:6px;line-height:normal;font-weight:normal} +#trace-menu h1{font-weight:bold; margin:5px 0} +.trace-action{background-color:#FFF;border-radius:4px;color:#000;text-decoration:none;font-weight:bold;font-size:11px;display:block;text-align:center;margin:5px 0;padding:5px;line-height:1} +.trace-action-disabled{background-color:lightgray;color:gray;cursor:default} +.trace-action-separator{border:0;height:1px;background-color:#999} +.trace-action.send-report{background: #FFF url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAFzUkdCAK7OHOkAAAAEZ0FNQQAAsY8L/GEFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAFnRFWHRDcmVhdGlvbiBUaW1lADA0LzExLzA4YZUFlAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNAay06AAAAJASURBVDhPvZJNTxNRFIafO9MaaqltaaGCkYILQdPGKCsMTYz+AdzoysSNv8KNC1d+bPwbssMEkybGBag1NEAIoQlqkUocoLHTpmk7nemMdy6gLI0mvpObyZw75znnvucKT4p/kHb0/mv9P4BtOzRqTTZ33h9FDvVHHnS7Njvb33i9/oJasEhu/AE3svfUngLs7+9TqVRotVoqeFKu62H+qFOq5gmNVQgPW1S2atydes6l0etotm2r5HA4TCKRIB6P/1qxWAxPAsoHK3jJbQbSOl2tRuhsi/n1x3SsNsKyLG9tbY1Op0MulzuqeyjH7rG8+oHFvadcvjKOEDpfzHfomodhVIl1rqH5FgwODpLJZJibm0MCcRxHnrtLXZq2+v0l9YbJq/kFWnULTYCx06S9m8Rs7h1OwYf4Lc/MzJDP52k0GiqG7nD/1jNuxp8Qta7iykeWxHHb3J56yKM7b38D/JVMJkmn06qTarWqPCksL7H5aZX4QMT/VdoujRU2PdFWnwoghFDLr1wqlZiYmMD3pVAoYJom4f5+BdQCcCE2TbxvVHZhKUDAT3Rdl3K5rBJmZ2fRdV3Bms0m2WyWA6PG3tIbFlcWiEUj1Mw6p8+fUQAhK3gbGxtEIhEmJycJBoNq46Qc22Vr9yOfv5bodYWcwimyF6cZSZ1DGIbhFYtFNE1TF0mZJ3V8rGN/ZBp9fSF6vZ4EaAyPpEiPpRGyfXUTJUiN0G/bT/TvhT9OX4FAgFAopECpVIqhoSGi0aiMB/gJXawlNgZ2Ef4AAAAASUVORK5CYII=) 4px center no-repeat} +.trace-action.enable-trace{background: #FFF url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAA+VBMVEU4YwBAagBFbQFIcwJMdQlRfAxVfBZVfhNWfBZYeR5ahhRbfCNcihVdfiRdgx5dhB5dhB9ehx1ggCdggihhjhxjhCtjkR1kiydkjSJliydliyhljChmiC5mkyFmlyBoijBokShqmCRqnx9rjTRtlDFulDFulTJwmDJwnytwoyhxnTN1njt1pTF2nzt2nzx3oz14oz14qjJ7pz9+p0R+qEWCrEeEsUmGr02GsE6Iu0aKtVGNt1aQuViSvFqZxWOcr3qesX2esX6ltoSmt4iouYurvI6zw5m9yqXI0bbi49zj5Nzk5t/m5+Ho6uPo6+Pr7ebu7+v19PX////ye0A4AAAAiElEQVQY02MIQgMM+AQ8lZxQBLx07CydkQS8NWytbQw9gAL+7iC+j6KVuYWZMlBFgIimS1CQr5ipsYmRPNAMPx4DPTnXQB59bV0tGZAtblxqqmqyEuoqqgqiEGvtWaUlpcQlJQWFYe6wZxbg4+NnF0I4zJ6Rg42FF9mlDgxM3KhOd+QkznNgAABhT0M7fSgVFAAAAABJRU5ErkJggg==) 4px center no-repeat} +.trace-action.disable-trace{background: #FFF url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAAK/INwWK6QAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADYUExURcwiANU8HdZMMdoyENtIJttXPdxFJt5dQt9rU+I/HeNBH+Q6GORgROVQLuWOfeWQf+Z1XudiQOhHJelJJ+pLKeyYhuypm+13Ve2qne6vo/BwVfByUPK1qPNKKPNNK/RSMPRbOfWIcfdkQvdxT/fb1fhuT/h/ZPiolvjd1/m/s/ni3vpsSvt/XfxjQfyEavyTe/1hP/12V/2Mav2ScP3Asv6CYP6GZP7BtP7FuP7k3v7o5P9VM/9ePP9jQf9mRP97Wf+DaP+EYv+Zd/+qiP+xoP+yof/m4P///5IuMgkAAAC6SURBVBjTXc/JdgFRAIThMoSgEbO0mMcESdAdEVxDi//938jikpOjdl+tqsRdBHA+7Y3Zn863Yjnzj0Fw9GdLW3jjRSUqRSuLsQdi1Z/nHp7h0QTz/gox7Nbib/BrAtW6Q4Q7Sb9YP6UnLiJ/SFhnSRzyiOSucDWFXRLhdFpt69dWx0GUilPrn8G0WEKMYs0vfcD3+2czNkJQjTQ2W2O2m0akaqeXQ6n6el1Phcq3c71MWApnen9v/+cCydYyJ9Lg6qMAAAAASUVORK5CYII=") 4px center no-repeat} +.trace-menu-variable{margin-left: 5px} + +ul.x-tab-strip { + width: auto !important; +} + +/* Contact */ +.contact-grid-name a{text-decoration:underline;cursor:pointer;color:#4B3E2D} + +.contact-card-label { + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 5px 0; + font-size: 14px; +} +.contact-card-name { + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 5px 0; + font-size: 18px; + font-weight: bold; +} +.contact-card-organization { + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 5px 0; + font-size: 18px; +} +.contact-card-avatar { + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 5px; + background-repeat: no-repeat; + background-origin: content-box; + background-position: 50% 0%; + background-size: contain; +} +.contact-card-avatar-individual { + background-image: url("../images/icon/individual-128.png"); +} +.contact-card-avatar-organization { + background-image: url("../images/icon/organization-128.png"); +} +.contact-details-photo { + max-width: 150px; + max-height: 150px; +} +.contact-details-container .x-box-inner { + overflow: auto !important; +} diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 52d1f4e67..4158db227 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -43,6 +43,16 @@ org.sigmah.server.inject.ServletContextListener + + ExportCalendar + ExportCalendar + Export Sigmah calendar events in iCal fromat + org.sigmah.client.ui.presenter.project.export.ExportCalendar + + + ExportCalendar + /ExportCalendar +