/******************************************************************************
* Copyright (C) 2008 Elaine Tan *
* Copyright (C) 2008 Idalica Corporation *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. 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, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.adempiere.webui.dashboard;
import java.lang.ref.WeakReference;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import org.adempiere.base.Core;
import org.adempiere.base.event.AbstractEventHandler;
import org.adempiere.base.event.EventManager;
import org.adempiere.base.event.IEventTopics;
import org.adempiere.webui.ClientInfo;
import org.adempiere.webui.component.Tabpanel;
import org.adempiere.webui.part.WindowContainer;
import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.theme.ThemeManager;
import org.adempiere.webui.util.ServerPushTemplate;
import org.compiere.model.I_R_Request;
import org.compiere.model.MSysConfig;
import org.compiere.model.PO;
import org.compiere.model.X_R_RequestType;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.DisplayType;
import org.compiere.util.Env;
import org.compiere.util.Trx;
import org.compiere.util.TrxEventListener;
import org.idempiere.distributed.IMessageService;
import org.idempiere.distributed.ITopic;
import org.idempiere.distributed.ITopicSubscriber;
import org.osgi.service.event.EventHandler;
import org.zkoss.calendar.Calendars;
import org.zkoss.calendar.api.CalendarEvent;
import org.zkoss.calendar.event.CalendarsEvent;
import org.zkoss.calendar.impl.SimpleCalendarModel;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Desktop;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.util.DesktopCleanup;
import org.zkoss.zul.Label;
import org.zkoss.zul.impl.LabelImageElement;
/**
* Dashboard gadget: Zk Calendar.
* Content created from "zul/calendar/calendar_mini.zul".
*
* @author Elaine
* @date November 20, 2008
*/
public class DPCalendar extends DashboardPanel implements EventListener, EventHandler {
/**
* generated serial id
*/
private static final long serialVersionUID = -224914882522997787L;
private static final String ON_MOBILE_SET_SELECTED_TAB_ECHO = "onMobileSetSelectedTabEcho";
private static final String ON_EVENT_EDIT_EVENT = "onEventEdit";
private static final String ON_EVENT_CREATE_EVENT = "onEventCreate";
private static final String ON_MOVE_DATE_EVENT = "onMoveDate";
private static final String ON_REQUEST_CHANGED_TOPIC = "onRequestChanged";
/** Zk Calendar instance */
private Calendars calendars;
/** Model for {@link #calendars} */
private SimpleCalendarModel scm;
/** Button to open Calendar window, to Refresh Calendar */
private LabelImageElement btnCal, btnRefresh;
private LabelImageElement btnCurrentDate;
/** Label for start and end date of current Calendar view */
private Label lblDate;
/** button to move Calendar to previous or next page */
private Component divArrowLeft, divArrowRight;
/** Window for event */
private EventWindow eventWin;
private WeakReference desktop;
/** List of Calendar (Request) events */
private ArrayList events;
/** Desktop cleanup listener to call {@link #cleanup()} */
private DesktopCleanup listener;
/** Event handler for R_Request model */
private static RequestEventHandler eventHandler;
/** Subscriber to {@link IMessageService} for "onRequestChanged" topic */
private static TopicSubscriber subscriber;
private static final CLogger log = CLogger.getCLogger(DPCalendar.class);
/**
* Default constructor
*/
public DPCalendar() {
super();
Component component = Executions.createComponents(ThemeManager.getThemeResource("zul/calendar/calendar_mini.zul"), this, null);
calendars = (Calendars) component.getFellow("cal");
btnCal = (LabelImageElement) component.getFellow("btnCal");
btnCal.addEventListener(Events.ON_CLICK, this);
btnRefresh = (LabelImageElement) component.getFellow("btnRefresh");
btnRefresh.addEventListener(Events.ON_CLICK, this);
btnCurrentDate = (LabelImageElement) component.getFellow("btnCurrentDate");
btnCurrentDate.addEventListener(Events.ON_CLICK, this);
lblDate = (Label) component.getFellow("lblDate");
lblDate.addEventListener(Events.ON_CREATE, this);
divArrowLeft = component.getFellow("divArrowLeft");
divArrowLeft.addEventListener(ON_MOVE_DATE_EVENT, this);
divArrowRight = component.getFellow("divArrowRight");
divArrowRight.addEventListener(ON_MOVE_DATE_EVENT, this);
this.appendChild(component);
calendars.addEventListener(ON_EVENT_CREATE_EVENT, this);
calendars.addEventListener(ON_EVENT_EDIT_EVENT, this);
createStaticListeners();
listener = new DesktopCleanup() {
@Override
public void cleanup(Desktop desktop) throws Exception {
DPCalendar.this.cleanup();
}
};
if (ClientInfo.isMobile()) {
addCallback(AFTER_PAGE_ATTACHED, t -> afterPageAttached());
addEventListener(ON_MOBILE_SET_SELECTED_TAB_ECHO, evt -> calendars.invalidate());
}
}
/**
* After page attached callback for mobile client.
* Setup listener for {@link WindowContainer#ON_MOBILE_SET_SELECTED_TAB} event.
*/
private void afterPageAttached() {
Component p = getParent();
while (p != null) {
if (p instanceof Tabpanel) {
p.addEventListener(WindowContainer.ON_MOBILE_SET_SELECTED_TAB, evt -> onMobileSelected());
break;
}
p = p.getParent();
}
}
/**
* {@link WindowContainer#ON_MOBILE_SET_SELECTED_TAB} event.
* Echo {@link #ON_MOBILE_SET_SELECTED_TAB_ECHO} event to redraw {@link #calendars}.
*/
private void onMobileSelected() {
Events.echoEvent(ON_MOBILE_SET_SELECTED_TAB_ECHO, this, null);
}
/**
* Setup {@link #eventHandler} and {@link #subscriber}
*/
private synchronized void createStaticListeners() {
if (eventHandler == null) {
eventHandler = new RequestEventHandler();
eventHandler.bindEventManager(EventManager.getInstance());
}
if (subscriber == null) {
subscriber = new TopicSubscriber();
IMessageService service = Core.getMessageService();
if (service != null) {
ITopic