diff --git a/org.adempiere.base/src/org/compiere/model/MAttachment.java b/org.adempiere.base/src/org/compiere/model/MAttachment.java
index 50fca012ab..700e5f481a 100644
--- a/org.adempiere.base/src/org/compiere/model/MAttachment.java
+++ b/org.adempiere.base/src/org/compiere/model/MAttachment.java
@@ -51,17 +51,30 @@ public class MAttachment extends X_AD_Attachment
*/
private static final long serialVersionUID = -8261865873158774665L;
+ /**
+ *
+ * @param ctx
+ * @param AD_Table_ID
+ * @param Record_ID
+ * @return attachment or null
+ */
+ public static MAttachment get (Properties ctx, int AD_Table_ID, int Record_ID)
+ {
+ return get(ctx, AD_Table_ID, Record_ID, (String)null);
+ }
+
/**
* Get Attachment (if there are more than one attachment it gets the first in no specific order)
* @param ctx context
* @param AD_Table_ID table
* @param Record_ID record
+ * @param trxName
* @return attachment or null
*/
- public static MAttachment get (Properties ctx, int AD_Table_ID, int Record_ID)
+ public static MAttachment get (Properties ctx, int AD_Table_ID, int Record_ID, String trxName)
{
final String whereClause = I_AD_Attachment.COLUMNNAME_AD_Table_ID+"=? AND "+I_AD_Attachment.COLUMNNAME_Record_ID+"=?";
- MAttachment retValue = new Query(ctx,I_AD_Attachment.Table_Name,whereClause, null)
+ MAttachment retValue = new Query(ctx,I_AD_Attachment.Table_Name,whereClause, trxName)
.setParameters(AD_Table_ID, Record_ID)
.first();
return retValue;
diff --git a/org.adempiere.ui.zk/META-INF/MANIFEST.MF b/org.adempiere.ui.zk/META-INF/MANIFEST.MF
index 5dae697633..8c5f926bb2 100644
--- a/org.adempiere.ui.zk/META-INF/MANIFEST.MF
+++ b/org.adempiere.ui.zk/META-INF/MANIFEST.MF
@@ -4,7 +4,8 @@ Bundle-Name: Zk Web Client
Bundle-SymbolicName: org.adempiere.ui.zk;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
-Import-Package: javax.servlet,
+Import-Package: javax.activation;version="1.1.1",
+ javax.servlet,
javax.servlet.http,
metainfo.zk,
org.apache.commons.codec.binary,
@@ -58,4 +59,4 @@ Bundle-Activator: org.adempiere.webui.WebUIActivator
Eclipse-ExtensibleAPI: true
Eclipse-RegisterBuddy: org.zkoss.zk.library
Web-ContextPath: webui
-Service-Component: OSGI-INF/reportviewerprovider.xml, OSGI-INF/defaultinfofactory.xml, OSGI-INF/defaulteditorfactory.xml, OSGI-INF/jrviewerprovider.xml, OSGI-INF/resourcefinder.xml, OSGI-INF/defaultpaymentformfactory.xml, OSGI-INF/processfactory.xml, OSGI-INF/defaultprintshippinglabel.xml, OSGI-INF/defaultcreatefromfactory.xml, OSGI-INF/defaultformfactory.xml
+Service-Component: OSGI-INF/reportviewerprovider.xml, OSGI-INF/defaultinfofactory.xml, OSGI-INF/defaulteditorfactory.xml, OSGI-INF/jrviewerprovider.xml, OSGI-INF/resourcefinder.xml, OSGI-INF/defaultpaymentformfactory.xml, OSGI-INF/processfactory.xml, OSGI-INF/defaultprintshippinglabel.xml, OSGI-INF/defaultcreatefromfactory.xml, OSGI-INF/defaultformfactory.xml, OSGI-INF/feedbackservice.xml
diff --git a/org.adempiere.ui.zk/OSGI-INF/feedbackservice.xml b/org.adempiere.ui.zk/OSGI-INF/feedbackservice.xml
new file mode 100644
index 0000000000..64c69dd91f
--- /dev/null
+++ b/org.adempiere.ui.zk/OSGI-INF/feedbackservice.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java
index 99c9728d1c..aa2f1b1e76 100644
--- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java
@@ -436,10 +436,14 @@ public class AdempiereWebUI extends Window implements EventListener, IWeb
ClientInfoEvent c = (ClientInfoEvent)event;
clientInfo = new ClientInfo();
clientInfo.colorDepth = c.getColorDepth();
+ clientInfo.screenHeight = c.getScreenHeight();
+ clientInfo.screenWidth = c.getScreenWidth();
+ clientInfo.devicePixelRatio = c.getDevicePixelRatio();
clientInfo.desktopHeight = c.getDesktopHeight();
clientInfo.desktopWidth = c.getDesktopWidth();
clientInfo.desktopXOffset = c.getDesktopXOffset();
clientInfo.desktopYOffset = c.getDesktopYOffset();
+ clientInfo.orientation = c.getOrientation();
clientInfo.timeZone = c.getTimeZone();
if (appDesktop != null)
appDesktop.setClientInfo(clientInfo);
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/ClientInfo.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/ClientInfo.java
index ee68868fe0..1f7a61858d 100644
--- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/ClientInfo.java
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/ClientInfo.java
@@ -37,7 +37,42 @@ public class ClientInfo implements Serializable {
public int desktopYOffset;
public int screenHeight;
public int screenWidth;
+ public String orientation;
public TimeZone timeZone;
public String userAgent;
public boolean tablet;
+ public double devicePixelRatio;
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("User Agent: ")
+ .append(userAgent)
+ .append("\r\n")
+ .append("Time Zone: ")
+ .append(timeZone.getID())
+ .append("\r\n")
+ .append("Screen Size: ")
+ .append(screenWidth)
+ .append(" x ")
+ .append(screenHeight)
+ .append("\r\n")
+ .append("Browser Desktop Size: ")
+ .append(desktopWidth)
+ .append(" x ")
+ .append(desktopHeight)
+ .append("\r\n")
+ .append("Orientation: ")
+ .append(orientation)
+ .append("\r\n")
+ .append("Color Depth: ")
+ .append(colorDepth)
+ .append("\r\n")
+ .append("Pixel Ratio: ")
+ .append(devicePixelRatio);
+
+ return builder.toString();
+ }
+
+
}
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/FeedbackRequestWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/FeedbackRequestWindow.java
new file mode 100644
index 0000000000..1e6d9fd021
--- /dev/null
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/FeedbackRequestWindow.java
@@ -0,0 +1,334 @@
+/******************************************************************************
+ * Copyright (C) 2013 Heng Sin Low *
+ * Copyright (C) 2013 Trek Global *
+ * 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.apps;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+
+import javax.activation.DataSource;
+
+import org.adempiere.webui.component.AttachmentItem;
+import org.adempiere.webui.component.Button;
+import org.adempiere.webui.component.ConfirmPanel;
+import org.adempiere.webui.component.Grid;
+import org.adempiere.webui.component.GridFactory;
+import org.adempiere.webui.component.Label;
+import org.adempiere.webui.component.Row;
+import org.adempiere.webui.component.Rows;
+import org.adempiere.webui.component.Textbox;
+import org.adempiere.webui.component.Window;
+import org.adempiere.webui.editor.WTableDirEditor;
+import org.adempiere.webui.util.FeedbackManager;
+import org.adempiere.webui.window.FDialog;
+import org.apache.commons.io.IOUtils;
+import org.compiere.model.MAttachment;
+import org.compiere.model.MColumn;
+import org.compiere.model.MLookup;
+import org.compiere.model.MLookupFactory;
+import org.compiere.model.MRequest;
+import org.compiere.model.MRole;
+import org.compiere.util.ByteArrayDataSource;
+import org.compiere.util.CLogger;
+import org.compiere.util.DisplayType;
+import org.compiere.util.Env;
+import org.compiere.util.Msg;
+import org.compiere.util.Trx;
+import org.zkoss.util.media.Media;
+import org.zkoss.zk.ui.WrongValueException;
+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.event.UploadEvent;
+import org.zkoss.zk.ui.util.Clients;
+import org.zkoss.zul.Div;
+import org.zkoss.zul.Separator;
+import org.zkoss.zul.Vlayout;
+
+/**
+ *
+ * @author hengsin
+ *
+ */
+public class FeedbackRequestWindow extends Window implements EventListener {
+
+ /**
+ * generated serial id
+ */
+ private static final long serialVersionUID = 8586980192148533197L;
+
+ private static CLogger log = CLogger.getCLogger(FeedbackRequestWindow.class);
+
+ private WTableDirEditor requestTypeField, priorityField, salesRepField;
+ private Textbox txtSummary;
+ private ConfirmPanel confirmPanel;
+
+ private List attachments = new ArrayList();
+ private Div attachmentBox;
+
+ public FeedbackRequestWindow() {
+
+ super();
+
+ setTitle(Msg.getMsg(Env.getCtx(), "RequestNew"));
+ setAttribute(Window.MODE_KEY, Window.MODE_HIGHLIGHTED);
+ setWidth("400px");
+ this.setBorder("normal");
+ this.setClosable(true);
+
+ boolean readOnly = !MRole.getDefault().canUpdate(
+ Env.getAD_Client_ID(Env.getCtx()), Env.getAD_Org_ID(Env.getCtx()),
+ MRequest.Table_ID, 0, false);
+
+ if (readOnly)
+ {
+ throw new RuntimeException(Msg.getMsg(Env.getCtx(), "AccessTableNoUpdate"));
+ }
+
+ Label lblRequestType = new Label("Request Type");
+ Label lblPriority = new Label("Priority");
+ Label lblSummary = new Label("Summary");
+ Label lblSalesRep = new Label("Sales Representative");
+
+ int columnID = MColumn.getColumn_ID(MRequest.Table_Name, MRequest.COLUMNNAME_R_RequestType_ID);
+ MLookup lookup = MLookupFactory.get(Env.getCtx(), 0, 0, columnID, DisplayType.TableDir);
+ requestTypeField = new WTableDirEditor("R_RequestType_ID", true, false, true, lookup);
+ requestTypeField.setValue(Env.getContext(Env.getCtx(), "P232|R_RequestType_ID"));
+ if(requestTypeField.getValue() == null || requestTypeField.getValue().equals(""))
+ if(requestTypeField.getComponent().getItemCount() > 1)
+ requestTypeField.setValue(requestTypeField.getComponent().getItemAtIndex(1).getValue());
+
+ columnID = MColumn.getColumn_ID(MRequest.Table_Name, MRequest.COLUMNNAME_Priority);
+ lookup = MLookupFactory.get(Env.getCtx(), 0, 0, columnID, DisplayType.List);
+ priorityField = new WTableDirEditor("Priority", true, false, true, lookup);
+ priorityField.setValue(Env.getContext(Env.getCtx(), "P232|Priority"));
+ if(priorityField.getValue() == null || priorityField.getValue().equals(""))
+ if(priorityField.getComponent().getItemCount() > 1)
+ priorityField.setValue(priorityField.getComponent().getItemAtIndex(1).getValue());
+
+ columnID = MColumn.getColumn_ID(MRequest.Table_Name, MRequest.COLUMNNAME_SalesRep_ID);
+ lookup = MLookupFactory.get(Env.getCtx(), 0, 0, columnID, DisplayType.TableDir);
+ salesRepField = new WTableDirEditor("SalesRep_ID", true, false, true, lookup);
+ salesRepField.setValue(Env.getContextAsInt(Env.getCtx(), "SalesRep_ID"));
+ if(salesRepField.getValue() == null || salesRepField.getValue().equals("0"))
+ if(salesRepField.getComponent().getItemCount() > 1)
+ salesRepField.setValue(salesRepField.getComponent().getItemAtIndex(1).getValue());
+
+ txtSummary = new Textbox();
+ txtSummary.setRows(10);
+ txtSummary.setWidth("95%");
+
+ confirmPanel = new ConfirmPanel(true);
+ confirmPanel.addActionListener(this);
+
+
+ Grid grid = GridFactory.newGridLayout();
+ grid.setVflex("min");
+
+ Rows rows = new Rows();
+ grid.appendChild(rows);
+
+ Row row = rows.newRow();
+ row.setStyle("padding: 4px 4px 0px 6px");
+ row.appendChild(lblRequestType);
+
+ row = rows.newRow();
+ row.setStyle("padding: 0px 4px 4px 6px");
+ row.appendChild(requestTypeField.getComponent());
+
+
+ row = rows.newRow();
+ row.setStyle("padding: 4px 4px 0px 6px");
+ row.appendChild(lblPriority);
+
+ row = rows.newRow();
+ row.setStyle("padding: 0px 4px 4px 6px");
+ row.appendChild(priorityField.getComponent());
+
+ row = rows.newRow();
+ row.setStyle("padding: 4px 4px 0px 6px");
+ row.appendChild(lblSummary);
+
+ row = rows.newRow();
+ row.setStyle("padding: 0px 4px 4px 6px");
+ row.appendChild(txtSummary);
+
+ row = rows.newRow();
+ row.setStyle("padding: 4px 4px 0px 6px");
+ row.appendChild(lblSalesRep);
+
+ row = rows.newRow();
+ row.setStyle("padding: 0px 4px 4px 6px");
+ row.appendChild(salesRepField.getComponent());
+
+ row = rows.newRow();
+ row.setStyle("padding: 4px 4px 0px 6px");
+ row.appendChild(new Label(Msg.getMsg(Env.getCtx(), "Attachment")));
+
+ attachmentBox = new Div();
+ attachmentBox.setHflex("1");
+ attachmentBox.setVflex("1");
+ row = rows.newRow();
+ row.setStyle("padding: 0px 4px 4px 6px");
+ row.appendChild(attachmentBox);
+
+ Vlayout vlayout = new Vlayout();
+ appendChild(vlayout);
+
+ vlayout.appendChild(grid);
+ grid.setVflex("min");
+ grid.setHflex("1");
+
+ Separator separator = new Separator();
+ separator.setOrient("horizontal");
+ vlayout.appendChild(separator);
+ vlayout.appendChild(confirmPanel);
+
+ Button btn = new Button();
+ btn.setImage("/images/Attachment24.png");
+ btn.setUpload("true");
+ btn.addEventListener(Events.ON_UPLOAD, this);
+ btn.setTooltiptext(Msg.getMsg(Env.getCtx(), "Attachment"));
+ confirmPanel.addComponentsLeft(btn);
+ confirmPanel.getButton(ConfirmPanel.A_OK).setWidgetListener("onClick", "zAu.cmd0.showBusy(null)");
+
+ addAttachment(FeedbackManager.getLogAttachment(false), false);
+ }
+
+ public void onEvent(Event e) throws Exception {
+ if (e.getTarget() == confirmPanel.getButton(ConfirmPanel.A_OK)) {
+ Clients.clearBusy();
+ // Check Mandatory fields
+ if (requestTypeField.getValue() == null || requestTypeField.getValue().equals("0"))
+ throw new WrongValueException(requestTypeField.getComponent(), Msg.translate(Env.getCtx(), "FillMandatory"));
+ if (priorityField.getValue() == null || priorityField.getValue().equals(""))
+ throw new WrongValueException(priorityField.getComponent(), Msg.translate(Env.getCtx(), "FillMandatory"));
+ if (txtSummary.getText() == null || txtSummary.getText().equals(""))
+ throw new WrongValueException(txtSummary, Msg.translate(Env.getCtx(), "FillMandatory"));
+ if (salesRepField.getValue() == null || salesRepField.getValue().equals("0"))
+ throw new WrongValueException(salesRepField.getComponent(), Msg.translate(Env.getCtx(), "FillMandatory"));
+
+ Trx trx = Trx.get(Trx.createTrxName("SaveNewRequest"), true);
+ try {
+ trx.start();
+ MRequest request = new MRequest(Env.getCtx(), 0, trx.getTrxName());
+ request.setAD_Org_ID(Env.getAD_Org_ID(Env.getCtx()));
+ request.setR_RequestType_ID((Integer) requestTypeField.getValue());
+ request.setPriority((String) priorityField.getValue());
+ request.setSummary(txtSummary.getText());
+ request.setSalesRep_ID((Integer) salesRepField.getValue());
+
+ boolean success = request.save();
+ if (success)
+ {
+ MAttachment attachment = null;
+ for(DataSource ds : attachments)
+ {
+ if (attachment == null)
+ {
+ attachment = new MAttachment(Env.getCtx(), 0, request.get_TrxName());
+ attachment.setAD_Table_ID(request.get_Table_ID());
+ attachment.setRecord_ID(request.get_ID());
+ }
+
+ attachment.addEntry(ds.getName(), IOUtils.toByteArray(ds.getInputStream()));
+ }
+ if (attachment != null)
+ success = attachment.save();
+
+ if (success)
+ success = trx.commit();
+
+ }
+
+ if (success)
+ {
+ FDialog.info(0, null, Msg.getMsg(Env.getCtx(), "Saved"));
+ }
+ else
+ {
+ trx.rollback();
+ FDialog.error(0, this, Msg.getMsg(Env.getCtx(), "SaveError"));
+ }
+ } finally {
+ trx.close();
+ }
+
+ this.detach();
+ }
+ else if (e.getTarget() == confirmPanel.getButton(ConfirmPanel.A_CANCEL))
+ {
+ this.detach();
+ }
+ else if (e instanceof UploadEvent)
+ {
+ UploadEvent ue = (UploadEvent) e;
+ Media media = ue.getMedia();
+ if (media != null)
+ {
+ byte[] data = getMediaData(media);
+ ByteArrayDataSource dataSource = new ByteArrayDataSource(data, media.getContentType());
+ dataSource.setName(media.getName());
+ addAttachment(dataSource, true);
+ getFirstChild().invalidate();
+ }
+ }
+ }
+
+ private void addAttachment(DataSource dataSource, boolean removable) {
+ attachments.add(dataSource);
+ AttachmentItem item = new AttachmentItem(dataSource, attachments, removable);
+ attachmentBox.appendChild(item);
+ }
+
+ private byte[] getMediaData(Media media) {
+ byte[] bytes = null;
+
+ try {
+ if (media.inMemory()) {
+ bytes = media.isBinary() ? media.getByteData() : media.getStringData().getBytes(getCharset(media.getContentType()));
+ } else {
+
+ InputStream is = media.getStreamData();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] buf = new byte[ 1000 ];
+ int byteread = 0;
+
+ while (( byteread=is.read(buf) )!=-1)
+ baos.write(buf,0,byteread);
+
+ bytes = baos.toByteArray();
+ }
+ } catch (IOException e) {
+ log.log(Level.SEVERE, e.getLocalizedMessage(), e);
+ throw new IllegalStateException(e.getLocalizedMessage());
+ }
+
+ return bytes;
+ }
+
+ private String getCharset(String contentType) {
+ if (contentType != null) {
+ int j = contentType.indexOf("charset=");
+ if (j >= 0) {
+ String cs = contentType.substring(j + 8).trim();
+ if (cs.length() > 0) return cs;
+ }
+ }
+ return "UTF-8";
+ }
+}
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/AttachmentItem.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/AttachmentItem.java
new file mode 100644
index 0000000000..b314878010
--- /dev/null
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/AttachmentItem.java
@@ -0,0 +1,60 @@
+/******************************************************************************
+ * Copyright (C) 2013 Heng Sin Low *
+ * Copyright (C) 2013 Trek Global *
+ * 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.component;
+
+import java.util.List;
+
+import javax.activation.DataSource;
+
+import org.zkoss.zk.ui.event.Event;
+import org.zkoss.zk.ui.event.EventListener;
+import org.zkoss.zk.ui.event.Events;
+import org.zkoss.zul.A;
+import org.zkoss.zul.Hlayout;
+
+/**
+ *
+ * @author hengsin
+ *
+ */
+public class AttachmentItem extends Hlayout implements EventListener{
+ /**
+ * generate serial id
+ */
+ private static final long serialVersionUID = 9105759170502414466L;
+ private DataSource ds;
+ private List list;
+
+ public AttachmentItem(DataSource ds, List list, boolean removable) {
+ setStyle("border: 1px solid #dcdcdc; background-color: #f5f5f5; " +
+ "width: auto !important;display: inline-block; height: 21px; " +
+ "margin-right: 5px; margin-bottom: 5px;padding-left: 5px; padding-right: 5px;");
+ appendChild(new Label(ds.getName()));
+ if (removable) {
+ A x = new A("", "/images/X8.png");
+ x.setStyle("float: right; background-color: #f5f5f5");
+ appendChild(x);
+ this.ds = ds;
+ this.list = list;
+ x.addEventListener(Events.ON_CLICK, this);
+ }
+ setHflex("0");
+ }
+
+ @Override
+ public void onEvent(Event event) throws Exception {
+ list.remove(ds);
+ this.detach();
+ }
+}
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultFeedbackService.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultFeedbackService.java
new file mode 100644
index 0000000000..706a564b79
--- /dev/null
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultFeedbackService.java
@@ -0,0 +1,77 @@
+/******************************************************************************
+ * Copyright (C) 2013 Heng Sin Low *
+ * Copyright (C) 2013 Trek Global *
+ * 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.factory;
+
+import javax.activation.DataSource;
+
+import org.adempiere.webui.apps.AEnv;
+import org.adempiere.webui.apps.FeedbackRequestWindow;
+import org.adempiere.webui.component.Window;
+import org.adempiere.webui.util.FeedbackManager;
+import org.adempiere.webui.window.WEMailDialog;
+import org.compiere.model.MSystem;
+import org.compiere.model.MUser;
+import org.compiere.util.Env;
+import org.compiere.util.Msg;
+import org.compiere.util.Util;
+import org.zkoss.zul.Window.Mode;
+
+/**
+ * @author hengsin
+ *
+ */
+public class DefaultFeedbackService implements IFeedbackService {
+
+ /**
+ * default constructor
+ */
+ public DefaultFeedbackService() {
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.webui.factory.IFeedbackService#emailSupport(boolean)
+ */
+ @Override
+ public void emailSupport(boolean errorOnly) {
+ DataSource ds = FeedbackManager.getLogAttachment(errorOnly);
+
+ WEMailDialog dialog = new WEMailDialog(
+ Msg.getMsg(Env.getCtx(), "EMailSupport"),
+ MUser.get(Env.getCtx()),
+ "", // to
+ "iDempiere " + Msg.getMsg(Env.getCtx(), "TraceInfo"),
+ "", ds);
+ dialog.setAttribute(Window.MODE_KEY, Mode.OVERLAPPED);
+
+ MSystem system = MSystem.get(Env.getCtx());
+ if (!Util.isEmpty(system.getSupportEMail()))
+ {
+ dialog.addTo(system.getSupportEMail(), true);
+ }
+ AEnv.showWindow(dialog);
+ dialog.focus();
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.webui.factory.IFeedbackService#createNewRequest()
+ */
+ @Override
+ public void createNewRequest() {
+ FeedbackRequestWindow window = new FeedbackRequestWindow();
+ AEnv.showWindow(window);
+ window.focus();
+ }
+
+}
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/IFeedbackService.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/IFeedbackService.java
new file mode 100644
index 0000000000..dab66b0de0
--- /dev/null
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/IFeedbackService.java
@@ -0,0 +1,33 @@
+/******************************************************************************
+ * Copyright (C) 2013 Heng Sin Low *
+ * Copyright (C) 2013 Trek Global *
+ * 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.factory;
+
+/**
+ *
+ * @author hengsin
+ *
+ */
+public interface IFeedbackService {
+
+ /**
+ * Email to support
+ * @param errorOnly
+ */
+ public void emailSupport(boolean errorOnly);
+
+ /**
+ * Create new support request
+ */
+ public void createNewRequest();
+}
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java
index 2186053dcc..a567b47eb1 100644
--- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java
@@ -483,6 +483,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
else
contentPanel.setStyle("width: 99%; margin: 0px auto;");
contentPanel.setVflex(true);
+ contentPanel.setSizedByContent(true);
North north = new North();
layout.appendChild(north);
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoGeneralPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoGeneralPanel.java
index 119ec82857..fc2d42c04b 100644
--- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoGeneralPanel.java
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoGeneralPanel.java
@@ -169,6 +169,7 @@ public class InfoGeneralPanel extends InfoPanel implements EventListener
else
contentPanel.setStyle("width: 99%; margin: 0px auto;");
contentPanel.setVflex(true);
+ contentPanel.setSizedByContent(true);
div.setStyle("width :100%; height: 100%");
center.appendChild(div);
div.setVflex("1");
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/UserPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/UserPanel.java
index a98fea3a1d..900ec5aa83 100644
--- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/UserPanel.java
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/UserPanel.java
@@ -21,9 +21,11 @@ import java.util.Properties;
import org.adempiere.webui.LayoutUtils;
import org.adempiere.webui.component.Label;
+import org.adempiere.webui.component.Menupopup;
import org.adempiere.webui.component.Messagebox;
import org.adempiere.webui.component.ToolBarButton;
import org.adempiere.webui.session.SessionManager;
+import org.adempiere.webui.util.FeedbackManager;
import org.adempiere.webui.window.WPreference;
import org.compiere.model.MClient;
import org.compiere.model.MOrg;
@@ -35,6 +37,7 @@ import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Hbox;
+import org.zkoss.zul.Menuitem;
import org.zkoss.zul.Separator;
import org.zkoss.zul.Vbox;
@@ -56,9 +59,12 @@ public class UserPanel extends Vbox implements EventListener
private ToolBarButton logout = new ToolBarButton();
private ToolBarButton changeRole = new ToolBarButton();
private ToolBarButton preference = new ToolBarButton();
+ private ToolBarButton feedback = new ToolBarButton();
private Label lblUserNameValue = new Label();
private WPreference preferencePopup;
+
+ private Menupopup feedbackMenu;
public UserPanel()
{
@@ -87,6 +93,18 @@ public class UserPanel extends Vbox implements EventListener
vbox.appendChild(hbox);
hbox.setAlign("center");
+ feedback.setLabel(Msg.getMsg(Env.getCtx(), "Feedback"));
+ feedback.setId("feedback");
+ feedback.addEventListener(Events.ON_CLICK, this);
+ LayoutUtils.addSclass("desktop-header-font", feedback);
+ LayoutUtils.addSclass("link", feedback);
+ feedback.setParent(hbox);
+
+ Separator sep = new Separator("vertical");
+ sep.setBar(true);
+ sep.setHeight("13px");
+ sep.setParent(hbox);
+
preference.setLabel(Msg.getMsg(Env.getCtx(), "Preference"));
preference.setId("preference");
preference.addEventListener(Events.ON_CLICK, this);
@@ -94,7 +112,7 @@ public class UserPanel extends Vbox implements EventListener
LayoutUtils.addSclass("link", preference);
preference.setParent(hbox);
- Separator sep = new Separator("vertical");
+ sep = new Separator("vertical");
sep.setBar(true);
sep.setHeight("13px");
sep.setParent(hbox);
@@ -117,6 +135,16 @@ public class UserPanel extends Vbox implements EventListener
LayoutUtils.addSclass("desktop-header-font", logout);
LayoutUtils.addSclass("link", logout);
logout.setParent(hbox);
+
+ feedbackMenu = new Menupopup();
+ Menuitem mi = new Menuitem(Msg.getMsg(Env.getCtx(), "RequestNew"));
+ mi.setId("CreateRequest");
+ feedbackMenu.appendChild(mi);
+ mi.addEventListener(Events.ON_CLICK, this);
+ mi = new Menuitem(Msg.getMsg(Env.getCtx(), "EMailSupport"));
+ mi.setId("EmailSupport");
+ mi.addEventListener(Events.ON_CLICK, this);
+ feedbackMenu.appendChild(mi);
}
private String getUserName()
@@ -180,6 +208,26 @@ public class UserPanel extends Vbox implements EventListener
preferencePopup.setPage(this.getPage());
preferencePopup.open(preference, "after_start");
}
+ else if (feedback == event.getTarget())
+ {
+ if (feedbackMenu.getPage() == null)
+ {
+ this.appendChild(feedbackMenu);
+ }
+ feedbackMenu.open(feedback, "after_start");
+ }
+ else if (event.getTarget() instanceof Menuitem)
+ {
+ Menuitem mi = (Menuitem) event.getTarget();
+ if ("CreateRequest".equals(mi.getId()))
+ {
+ FeedbackManager.createNewRequest();
+ }
+ else if ("EmailSupport".equals(mi.getId()))
+ {
+ FeedbackManager.emailSupport(false);
+ }
+ }
}
}
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/WAttachment.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/WAttachment.java
index 4cf9421799..955173a607 100644
--- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/WAttachment.java
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/WAttachment.java
@@ -115,7 +115,7 @@ public class WAttachment extends Window implements EventListener
autoPreviewList.add("image/jpeg");
autoPreviewList.add("image/png");
autoPreviewList.add("image/gif");
- autoPreviewList.add("text/plan");
+ autoPreviewList.add("text/plain");
autoPreviewList.add("application/pdf");
}
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/FeedbackManager.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/FeedbackManager.java
new file mode 100644
index 0000000000..c53f108d12
--- /dev/null
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/FeedbackManager.java
@@ -0,0 +1,69 @@
+/******************************************************************************
+ * Copyright (C) 2013 Heng Sin Low *
+ * Copyright (C) 2013 Trek Global *
+ * 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.util;
+
+import javax.activation.DataSource;
+
+import org.adempiere.base.Service;
+import org.adempiere.webui.ClientInfo;
+import org.adempiere.webui.factory.IFeedbackService;
+import org.adempiere.webui.session.SessionManager;
+import org.compiere.util.ByteArrayDataSource;
+import org.compiere.util.CLogErrorBuffer;
+import org.compiere.util.Env;
+
+/**
+ * @author hengsin
+ *
+ */
+public class FeedbackManager {
+
+ /**
+ *
+ * @param errorOnly
+ * @return attachment datasource
+ */
+ public static DataSource getLogAttachment(boolean errorOnly)
+ {
+ String context = CLogErrorBuffer.get(true).getErrorInfo(Env.getCtx(), errorOnly);
+ ClientInfo browserInfo = SessionManager.getAppDesktop().getClientInfo();
+ StringBuilder info = new StringBuilder(browserInfo.toString());
+ info.append("\r\n").append(context);
+
+ ByteArrayDataSource ds = new ByteArrayDataSource(info.toString(), "UTF-8", "text/plain");
+ ds.setName("idempiere-log.txt");
+
+ return ds;
+ }
+
+ /**
+ * EMail Support
+ */
+ public static void emailSupport(boolean errorOnly)
+ {
+ IFeedbackService service = Service.locator().locate(IFeedbackService.class).getService();
+ if (service != null)
+ service.emailSupport(errorOnly);
+ }
+
+ /**
+ * Create new support request
+ */
+ public static void createNewRequest()
+ {
+ IFeedbackService service = Service.locator().locate(IFeedbackService.class).getService();
+ if (service != null)
+ service.createNewRequest();
+ }
+}
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/AboutWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/AboutWindow.java
index ac9c79d1d8..1b3752ab56 100644
--- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/AboutWindow.java
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/AboutWindow.java
@@ -36,6 +36,7 @@ import org.adempiere.webui.component.Tabs;
import org.adempiere.webui.component.ToolBarButton;
import org.adempiere.webui.component.Window;
import org.adempiere.webui.theme.ThemeManager;
+import org.adempiere.webui.util.FeedbackManager;
import org.compiere.Adempiere;
import org.compiere.model.MUser;
import org.compiere.util.CLogErrorBuffer;
@@ -550,13 +551,7 @@ public class AboutWindow extends Window implements EventListener {
*/
private void cmd_errorEMail()
{
- new WEMailDialog(this,
- "EMail Trace",
- MUser.get(Env.getCtx()),
- "", // to
- "Adempiere Trace Info",
- CLogErrorBuffer.get(true).getErrorInfo(Env.getCtx(), bErrorsOnly.isSelected()),
- null);
-
+ this.detach();
+ FeedbackManager.emailSupport(bErrorsOnly.isSelected());
} // cmd_errorEMail
}
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/WEMailDialog.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/WEMailDialog.java
index 102b671692..30f9c8fdf3 100644
--- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/WEMailDialog.java
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/WEMailDialog.java
@@ -18,11 +18,18 @@
package org.adempiere.webui.window;
import java.beans.PropertyVetoException;
-import java.io.File;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
import java.util.StringTokenizer;
import java.util.logging.Level;
-import org.adempiere.webui.apps.AEnv;
+import javax.activation.DataSource;
+
+import org.adempiere.webui.component.AttachmentItem;
+import org.adempiere.webui.component.Button;
import org.adempiere.webui.component.Column;
import org.adempiere.webui.component.Columns;
import org.adempiere.webui.component.ConfirmPanel;
@@ -35,24 +42,28 @@ import org.adempiere.webui.component.Window;
import org.adempiere.webui.editor.WSearchEditor;
import org.adempiere.webui.event.ValueChangeEvent;
import org.adempiere.webui.event.ValueChangeListener;
-import org.adempiere.webui.panel.StatusBarPanel;
import org.compiere.model.Lookup;
import org.compiere.model.MClient;
import org.compiere.model.MLookupFactory;
import org.compiere.model.MUser;
import org.compiere.model.MUserMail;
+import org.compiere.util.ByteArrayDataSource;
import org.compiere.util.CLogger;
import org.compiere.util.DisplayType;
import org.compiere.util.EMail;
import org.compiere.util.Env;
import org.compiere.util.Msg;
+import org.compiere.util.Util;
+import org.zkoss.util.media.Media;
+import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
-import org.zkoss.zul.Borderlayout;
-import org.zkoss.zul.Center;
-import org.zkoss.zul.South;
+import org.zkoss.zk.ui.event.Events;
+import org.zkoss.zk.ui.event.UploadEvent;
+import org.zkoss.zk.ui.util.Clients;
+import org.zkoss.zul.Cell;
import org.zkoss.zul.Div;
-import org.zkoss.zul.Separator;
+import org.zkoss.zul.Vlayout;
/**
* EMail Dialog
@@ -77,7 +88,6 @@ public class WEMailDialog extends Window implements EventListener, ValueC
/**
* EMail Dialog
- * @param owner calling window
* @param title title
* @param from from
* @param to to
@@ -85,16 +95,17 @@ public class WEMailDialog extends Window implements EventListener, ValueC
* @param message message
* @param attachment optional attachment
*/
- public WEMailDialog (Window owner, String title, MUser from, String to,
- String subject, String message, File attachment)
+ public WEMailDialog (String title, MUser from, String to,
+ String subject, String message, DataSource attachment)
{
super();
this.setTitle(title);
- this.setWidth("500px");
+ this.setWidth("550px");
this.setHeight("600px");
this.setClosable(true);
+ this.setMaximizable(true);
this.setBorder("normal");
- this.setStyle("position:absolute");
+ this.setStyle("position:absolute; margin: 0; padding: 0;");
commonInit(from, to, subject, message, attachment);
} // EmailDialog
@@ -108,7 +119,7 @@ public class WEMailDialog extends Window implements EventListener, ValueC
* @param attachment optional attachment
*/
private void commonInit (MUser from, String to,
- String subject, String message, File attachment)
+ String subject, String message, DataSource attachment)
{
m_client = MClient.get(Env.getCtx());
try
@@ -124,7 +135,6 @@ public class WEMailDialog extends Window implements EventListener, ValueC
fUser.addValueChangeListener(this);
fCcUser = new WSearchEditor(lookup, "AD_User_ID", "", false, false, true);
fCcUser.addValueChangeListener(this);
- jbInit();
}
catch(Exception ex)
{
@@ -133,7 +143,6 @@ public class WEMailDialog extends Window implements EventListener, ValueC
set(from, to, subject, message);
setAttachment(attachment);
setAttribute(Window.MODE_KEY, Window.MODE_HIGHLIGHTED);
- AEnv.showWindow(this);
} // commonInit
@@ -151,7 +160,10 @@ public class WEMailDialog extends Window implements EventListener, ValueC
private String m_subject;
private String m_message;
/** File to be optionally attached */
- private File m_attachFile;
+ private DataSource m_attachment;
+
+ private List attachments = new ArrayList();
+
/** Logger */
private static CLogger log = CLogger.getCLogger(WEMailDialog.class);
@@ -166,15 +178,24 @@ public class WEMailDialog extends Window implements EventListener, ValueC
private Label lCc = new Label();
private Label lSubject = new Label();
private Label lAttachment = new Label();
- private Textbox fAttachment = new Textbox();//40);
private Textbox fMessage = new Textbox();
private ConfirmPanel confirmPanel = new ConfirmPanel(true);
- private StatusBarPanel statusBar = new StatusBarPanel();
+
+ private Div attachmentBox;
+
+ @Override
+ public void onPageAttached(Page newpage, Page oldpage) {
+ super.onPageAttached(newpage, oldpage);
+ try {
+ render();
+ } catch (Exception e) {
+ }
+ }
/**
* Static Init
*/
- void jbInit() throws Exception
+ protected void render() throws Exception
{
lFrom.setValue(Msg.getMsg(Env.getCtx(), "From") + ":");
lTo.setValue(Msg.getMsg(Env.getCtx(), "To") + ":");
@@ -182,13 +203,11 @@ public class WEMailDialog extends Window implements EventListener, ValueC
lSubject.setValue(Msg.getMsg(Env.getCtx(), "Subject") + ":");
lAttachment.setValue(Msg.getMsg(Env.getCtx(), "Attachment") + ":");
fFrom.setReadonly(true);
- statusBar.setStatusDB(null);
//
Grid grid = new Grid();
grid.setWidth("100%");
- grid.setHeight("100%");
- grid.setStyle("margin:0; padding:0; position: absolute; align: center; valign: center; border:0");
+ grid.setStyle("margin:0; padding:0; align: center; valign: center; border:0");
grid.makeNoStrip();
Columns columns = new Columns();
@@ -241,11 +260,7 @@ public class WEMailDialog extends Window implements EventListener, ValueC
row.appendChild(new Label(""));
row.appendChild(fCc);
fCc.setHflex("1");
-
- row = new Row();
- rows.appendChild(row);
- row.appendCellChild(new Separator(), 2);
-
+
row = new Row();
rows.appendChild(row);
div = new Div();
@@ -255,18 +270,29 @@ public class WEMailDialog extends Window implements EventListener, ValueC
row.appendChild(fSubject);
fSubject.setHflex("1");
- row = new Row();
- rows.appendChild(row);
- row.appendCellChild(new Separator(), 2);
-
row = new Row();
rows.appendChild(row);
div = new Div();
div.setStyle("text-align: right;");
div.appendChild(lAttachment);
- row.appendChild(div);
- row.appendChild(fAttachment);
- fAttachment.setHflex("1");
+ Cell cell = new Cell();
+ cell.appendChild(lAttachment);
+ cell.setValign("top");
+ cell.setAlign("right");
+ row.appendChild(cell);
+
+ attachmentBox = new Div();
+ attachmentBox.setHflex("1");
+ attachmentBox.setVflex("1");
+ row.appendChild(attachmentBox);
+ for (DataSource ds : attachments) {
+ boolean removable = true;
+ if (ds == m_attachment) {
+ removable = false;
+ }
+ AttachmentItem item = new AttachmentItem(ds, attachments, removable);
+ attachmentBox.appendChild(item);
+ }
row = new Row();
rows.appendChild(row);
@@ -276,29 +302,28 @@ public class WEMailDialog extends Window implements EventListener, ValueC
confirmPanel.addActionListener(this);
- Borderlayout layout = new Borderlayout();
- layout.setWidth("95%");
- layout.setHeight("92%");
- layout.setStyle("background-color: white; position: absolute; margin:0; border:0; padding:0");
+ Vlayout vlayout = new Vlayout();
+ vlayout.setStyle("width: 99%; margin: auto; height: 100%;");
- Center center = new Center();
- grid.setHflex("true");
- grid.setVflex("true");
- center.appendChild(grid);
- layout.appendChild(center);
- center.setStyle("background-color: white; border: 0");
+ grid.setVflex("1");
+ vlayout.appendChild(grid);
- South south = new South();
Div southDiv = new Div();
- south.appendChild(southDiv);
- layout.appendChild(south);
- south.setStyle("background-color: white; border: 0");
+
+ Button btn = new Button();
+ btn.setImage("/images/Attachment24.png");
+ btn.setUpload("true");
+ btn.addEventListener(Events.ON_UPLOAD, this);
+ btn.setTooltiptext(Msg.getMsg(Env.getCtx(), "Attachment"));
+ confirmPanel.addComponentsLeft(btn);
+ confirmPanel.getButton(ConfirmPanel.A_OK).setWidgetListener("onClick", "zAu.cmd0.showBusy(null)");
southDiv.appendChild(confirmPanel);
- southDiv.appendChild(statusBar);
+ southDiv.setVflex("min");
+ vlayout.appendChild(southDiv);
- this.appendChild(layout);
- } // jbInit
+ this.appendChild(vlayout);
+ } // render
/**
* Set all properties
@@ -310,8 +335,6 @@ public class WEMailDialog extends Window implements EventListener, ValueC
setTo(to);
setSubject(subject);
setMessage(message);
- //
- statusBar.setStatusLine(m_client.getSMTPHost());
} // set
/**
@@ -360,8 +383,7 @@ public class WEMailDialog extends Window implements EventListener, ValueC
|| !newFrom.isEMailValid()
|| !newFrom.isCanSendEMail())
{
-// confirmPanel.getOKButton().setEnabled(false);
- fFrom.setText("**Invalid**");
+ fFrom.setText("");
}
else
fFrom.setText(m_from.getEMail());
@@ -415,29 +437,19 @@ public class WEMailDialog extends Window implements EventListener, ValueC
/**
* Set Attachment
*/
- public void setAttachment (File attachment)
+ public void setAttachment (DataSource attachment)
{
- m_attachFile = attachment;
- if (attachment == null)
- {
- lAttachment.setVisible(false);
- fAttachment.setVisible(false);
- }
- else
- {
- lAttachment.setVisible(true);
- fAttachment.setVisible(true);
- fAttachment.setText(attachment.getName());
- fAttachment.setReadonly(true);
- }
+ m_attachment = attachment;
+ if (attachment != null)
+ attachments.add(attachment);
} // setAttachment
/**
* Get Attachment
*/
- public File getAttachment()
+ public DataSource getAttachment()
{
- return m_attachFile;
+ return m_attachment;
} // getAttachment
/**************************************************************************
@@ -446,14 +458,15 @@ public class WEMailDialog extends Window implements EventListener, ValueC
public void onEvent(Event event) throws Exception {
if (event.getTarget().getId().equals(ConfirmPanel.A_CANCEL))
onClose();
-
- if (getTo() == null || getTo().length() == 0)
- {
- return;
- }
+
// Send
- if (event.getTarget().getId().equals(ConfirmPanel.A_OK))
+ else if (event.getTarget().getId().equals(ConfirmPanel.A_OK))
{
+ Clients.clearBusy();
+ if (getTo() == null || getTo().length() == 0)
+ {
+ return;
+ }
StringTokenizer st = new StringTokenizer(getTo(), " ,;", false);
String to = st.nextToken();
@@ -472,8 +485,11 @@ public class WEMailDialog extends Window implements EventListener, ValueC
email.addCc(cc);
}
// Attachment
- if (m_attachFile != null && m_attachFile.exists())
- email.addAttachment(m_attachFile);
+ for(DataSource ds : attachments)
+ {
+ email.addAttachment(ds);
+ }
+
status = email.send();
//
if (m_user != null)
@@ -488,14 +504,61 @@ public class WEMailDialog extends Window implements EventListener, ValueC
}
else
FDialog.error(0, this, "MessageNotSent", status);
- //
-// confirmPanel.getOKButton().setEnabled(false);
-// setCursor(Cursor.getDefaultCursor());
}
- else if (event.getTarget().getId().equals(ConfirmPanel.A_CANCEL))
- onClose();
+ else if (event instanceof UploadEvent)
+ {
+ UploadEvent ue = (UploadEvent) event;
+ Media media = ue.getMedia();
+ if (media != null)
+ {
+ byte[] data = getMediaData(media);
+ ByteArrayDataSource dataSource = new ByteArrayDataSource(data, media.getContentType());
+ dataSource.setName(media.getName());
+ attachments.add(dataSource);
+ AttachmentItem item = new AttachmentItem(dataSource, attachments, true);
+ attachmentBox.appendChild(item);
+ getFirstChild().invalidate();
+ }
+ }
}
+ private byte[] getMediaData(Media media) {
+ byte[] bytes = null;
+
+ try {
+ if (media.inMemory()) {
+ bytes = media.isBinary() ? media.getByteData() : media.getStringData().getBytes(getCharset(media.getContentType()));
+ } else {
+
+ InputStream is = media.getStreamData();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] buf = new byte[ 1000 ];
+ int byteread = 0;
+
+ while (( byteread=is.read(buf) )!=-1)
+ baos.write(buf,0,byteread);
+
+ bytes = baos.toByteArray();
+ }
+ } catch (IOException e) {
+ log.log(Level.SEVERE, e.getLocalizedMessage(), e);
+ throw new IllegalStateException(e.getLocalizedMessage());
+ }
+
+ return bytes;
+ }
+
+ private String getCharset(String contentType) {
+ if (contentType != null) {
+ int j = contentType.indexOf("charset=");
+ if (j >= 0) {
+ String cs = contentType.substring(j + 8).trim();
+ if (cs.length() > 0) return cs;
+ }
+ }
+ return "UTF-8";
+ }
+
/**
* Vetoable Change - User selected
* @param evt
@@ -518,7 +581,14 @@ public class WEMailDialog extends Window implements EventListener, ValueC
{
int AD_User_ID = ((Integer)value).intValue();
m_user = MUser.get(Env.getCtx(), AD_User_ID);
- fTo.setValue(m_user.getEMail());
+ if (Util.isEmpty(m_user.getEMail()))
+ {
+ FDialog.error(0, Msg.getMsg(Env.getCtx(), "UserNoEmailAddress"));
+ }
+ else
+ {
+ addTo(m_user.getEMail(), true);
+ }
}
} else {
// fCcUser
@@ -526,11 +596,41 @@ public class WEMailDialog extends Window implements EventListener, ValueC
{
int AD_User_ID = ((Integer)value).intValue();
m_ccuser = MUser.get(Env.getCtx(), AD_User_ID);
- fCc.setValue(m_ccuser.getEMail());
+ if (Util.isEmpty(m_ccuser.getEMail()))
+ {
+ FDialog.error(0, Msg.getMsg(Env.getCtx(), "UserNoEmailAddress"));
+ }
+ else
+ {
+ addCC(m_ccuser.getEMail(), true);
+ }
}
}
return;
}
-
+
+ public void addTo(String email, boolean first) {
+ if (Util.isEmpty(email))
+ return;
+
+ String to = fTo.getValue();
+ if (!Util.isEmpty(to)) {
+ fTo.setValue(first ? email+","+to : to+","+email);
+ } else {
+ fTo.setValue(email);
+ }
+ }
+
+ public void addCC(String email, boolean first) {
+ if (Util.isEmpty(email))
+ return;
+
+ String to = fCc.getValue();
+ if (!Util.isEmpty(to)) {
+ fCc.setValue(first ? email+","+to : to+","+email);
+ } else {
+ fCc.setValue(email);
+ }
+ }
} // VEMailDialog
\ No newline at end of file
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkReportViewer.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkReportViewer.java
index abd9c36240..4350835c59 100644
--- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkReportViewer.java
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkReportViewer.java
@@ -27,6 +27,7 @@ import java.sql.SQLException;
import java.util.Properties;
import java.util.logging.Level;
+import javax.activation.FileDataSource;
import javax.servlet.http.HttpServletRequest;
import org.adempiere.exceptions.AdempiereException;
@@ -775,9 +776,9 @@ public class ZkReportViewer extends Window implements EventListener, ITab
log.log(Level.SEVERE, "", e);
}
- new WEMailDialog (this,
- Msg.getMsg(Env.getCtx(), "SendMail"),
- from, to, subject, message, attachment);
+ WEMailDialog dialog = new WEMailDialog (Msg.getMsg(Env.getCtx(), "SendMail"),
+ from, to, subject, message, new FileDataSource(attachment));
+ AEnv.showWindow(dialog);
} // cmd_sendMail
/**
diff --git a/org.adempiere.ui.zk/build.properties b/org.adempiere.ui.zk/build.properties
index c483da351d..79fca455a6 100644
--- a/org.adempiere.ui.zk/build.properties
+++ b/org.adempiere.ui.zk/build.properties
@@ -29,7 +29,8 @@ bin.includes = META-INF/,\
WEB-INF/lib/atmosphere-compat-tomcat7-1.0.4.jar,\
WEB-INF/lib/atmosphere-runtime-1.0.4.jar,\
OSGI-INF/defaultcreatefromfactory.xml,\
- OSGI-INF/defaultformfactory.xml
+ OSGI-INF/defaultformfactory.xml,\
+ OSGI-INF/feedbackservice.xml
src.includes = WEB-INF/classes/,\
WEB-INF/tld/,\
WEB-INF/web.xml,\
diff --git a/org.adempiere.ui.zk/images/X8.png b/org.adempiere.ui.zk/images/X8.png
new file mode 100644
index 0000000000..6b68fb15c6
Binary files /dev/null and b/org.adempiere.ui.zk/images/X8.png differ