/** * */ package org.adempiere.webui.window; import java.util.ArrayList; import java.util.List; import org.adempiere.webui.component.ConfirmPanel; import org.adempiere.webui.component.Window; import org.adempiere.webui.session.SessionManager; import org.compiere.model.I_AD_CtxHelpMsg; import org.compiere.model.MCtxHelp; import org.compiere.model.MCtxHelpMsg; import org.compiere.model.MCtxHelpSuggestion; import org.compiere.model.MForm; import org.compiere.model.MInfoWindow; import org.compiere.model.MProcess; import org.compiere.model.MSysConfig; import org.compiere.model.MTab; import org.compiere.model.MTable; import org.compiere.model.MTask; import org.compiere.model.MUserDefInfo; import org.compiere.model.PO; import org.compiere.model.X_AD_CtxHelp; import org.compiere.util.DB; import org.compiere.util.Env; import org.compiere.util.Msg; import org.compiere.util.Trx; import org.compiere.util.Util; import org.compiere.wf.MWFNode; import org.compiere.wf.MWorkflow; import org.zkforge.ckez.CKeditor; 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.Borderlayout; import org.zkoss.zul.Cell; import org.zkoss.zul.Center; import org.zkoss.zul.Hbox; import org.zkoss.zul.Label; import org.zkoss.zul.South; import org.zkoss.zul.Vbox; /** * Dialog to capture suggestion for context help (AD_CtxHelp) * @author hengsin */ public class WCtxHelpSuggestion extends Window implements EventListener { /** * generated serial id */ private static final long serialVersionUID = 2068729997836800852L; private ConfirmPanel confirmPanel; private MCtxHelpMsg ctxHelpMsg; private CKeditor helpTextbox; private PO po; private String baseContent; private String translatedContent; /* SysConfig USE_ESC_FOR_TAB_CLOSING */ private boolean isUseEscForTabClosing = MSysConfig.getBooleanValue(MSysConfig.USE_ESC_FOR_TAB_CLOSING, false, Env.getAD_Client_ID(Env.getCtx())); /** * @param ctxHelpMsg */ public WCtxHelpSuggestion(MCtxHelpMsg ctxHelpMsg) { this.ctxHelpMsg = new MCtxHelpMsg(ctxHelpMsg.getCtx(), ctxHelpMsg.getAD_CtxHelpMsg_ID(), ctxHelpMsg.get_TrxName()); layout(); } /** * @param po * @param baseContent * @param translatedContent */ public WCtxHelpSuggestion(PO po, String baseContent, String translatedContent) { this.po = po; this.baseContent = baseContent; this.translatedContent = translatedContent; layout(); } /** * Layout dialog */ private void layout() { Borderlayout borderlayout = new Borderlayout(); appendChild(borderlayout); borderlayout.setHflex("1"); borderlayout.setVflex("1"); Center center = new Center(); center.setVflex("1"); center.setHflex("1"); borderlayout.appendChild(center); Vbox vlayout = new Vbox(); vlayout.setStyle("padding: 8px 16px"); vlayout.setWidth("100%"); vlayout.setHeight("100%"); vlayout.setPack("stretch"); center.appendChild(vlayout); Hbox hlayout = new Hbox(); hlayout.setVflex("min"); hlayout.setWidth("100%"); hlayout.setAlign("center"); Cell cell = new Cell(); cell.setWidth("15%"); cell.setStyle("padding-right: 8px;"); cell.setAlign("right"); cell.appendChild(new Label(Msg.getElement(Env.getCtx(), "AD_CtxHelp_ID") + " : ")); hlayout.appendChild(cell); cell = new Cell(); cell.setWidth("85%"); cell.setAlign("left"); cell.appendChild(new Label(ctxHelpMsg != null ? ctxHelpMsg.getAD_CtxHelp().getName() : getContextHelpName(po))); hlayout.appendChild(cell); vlayout.appendChild(hlayout); hlayout = new Hbox(); hlayout.setVflex("1"); hlayout.setHflex("1"); hlayout.setAlign("stretch"); cell = new Cell(); cell.setWidth("15%"); cell.setStyle("padding-right: 8px;"); cell.setAlign("right"); cell.appendChild(new Label(Msg.getElement(Env.getCtx(), "MsgText") + " : ")); hlayout.appendChild(cell); helpTextbox = new CKeditor(); helpTextbox.setCustomConfigurationsPath("/js/ckeditor/config-min.js"); helpTextbox.setToolbar("MyToolbar"); String msgText = ctxHelpMsg != null ? ctxHelpMsg.get_Translation("MsgText") : (Util.isEmpty(translatedContent) ? baseContent : translatedContent); msgText = removeHeaderTag(msgText); helpTextbox.setValue(msgText); helpTextbox.setWidth("99%"); helpTextbox.setVflex("1"); cell = new Cell(); cell.setWidth("85%"); cell.setHeight("100%"); cell.setAlign("left"); cell.appendChild(helpTextbox); hlayout.appendChild(cell); vlayout.appendChild(hlayout); confirmPanel = new ConfirmPanel(true); confirmPanel.addActionListener(this); South southPane = new South(); southPane.setSclass("dialog-footer"); borderlayout.appendChild(southPane); southPane.appendChild(confirmPanel); this.setSclass("popup-dialog"); this.setClosable(true); this.setBorder("normal"); this.setWidth("60%"); this.setHeight("650px"); this.setShadow(true); this.setAttribute(Window.MODE_KEY, Window.MODE_HIGHLIGHTED); this.setSizable(true); if (ctxHelpMsg != null && ctxHelpMsg.getAD_Client_ID() == Env.getAD_Client_ID(Env.getCtx())) { setTitle(Msg.getMsg(Env.getCtx(), "edit") + " " + Msg.getElement(Env.getCtx(), "AD_CtxHelpMsg_ID")); } else { setTitle(Msg.getElement(Env.getCtx(), "AD_CtxHelpSuggestion_ID")); } addEventListener(Events.ON_CANCEL, e -> onCancel()); } @Override public void onEvent(Event event) throws Exception { if (event.getTarget() == confirmPanel.getButton(ConfirmPanel.A_OK)) { onSave(); } else if (event.getTarget() == confirmPanel.getButton(ConfirmPanel.A_CANCEL)) { onCancel(); } } /** * Handle onCancel event */ private void onCancel() { // do not allow to close tab for Events.ON_CTRL_KEY event if(isUseEscForTabClosing) SessionManager.getAppDesktop().setCloseTabWithShortcut(false); this.detach(); } /** * Save changes to AD_CtxHelpMsg or AD_CtxHelpSuggestion */ private void onSave() { String trxName = Trx.createTrxName(); Trx trx = Trx.get(trxName, true); try { trx.start(); onSave0(trx); trx.commit(true); if (ctxHelpMsg != null && ctxHelpMsg.getAD_Client_ID() == Env.getAD_Client_ID(Env.getCtx())) { Dialog.info(0, Msg.getMsg(Env.getCtx(), "Your changes have been saved.")); } else { Dialog.info(0, Msg.getMsg(Env.getCtx(),"Your suggestions have been submitted for review")); } } catch (Exception e) { trx.rollback(); if (e instanceof RuntimeException) throw (RuntimeException)e; else throw new RuntimeException(e); } finally { trx.close(); } } /** * Save changes to AD_CtxHelpMsg or AD_CtxHelpSuggestion * @param trx */ private void onSave0(Trx trx) { if (ctxHelpMsg != null && ctxHelpMsg.getAD_Client_ID() == Env.getAD_Client_ID(Env.getCtx())) { if (Env.isBaseLanguage(Env.getCtx(), I_AD_CtxHelpMsg.Table_Name)) { ctxHelpMsg.setMsgText(helpTextbox.getValue()); ctxHelpMsg.saveEx(trx.getTrxName()); } StringBuilder update = new StringBuilder("UPDATE AD_CtxHelpMsg_Trl SET MsgText=? "); update.append("WHERE AD_CtxHelpMsg_ID=? AND AD_Client_ID=? AND AD_Language=? AND IsActive='Y' "); Object[] params = new Object[]{helpTextbox.getValue(), ctxHelpMsg.get_ID(), ctxHelpMsg.getAD_Client_ID(), Env.getAD_Language(Env.getCtx())}; DB.executeUpdateEx(update.toString(), params, trx.getTrxName()); } else { /* this whole block code is forcefully writing records on System tenant */ MCtxHelpSuggestion suggestion = new MCtxHelpSuggestion(Env.getCtx(), 0, trx.getTrxName()); suggestion.setClientOrg(0, 0); if (ctxHelpMsg != null) { suggestion.setAD_CtxHelp_ID(ctxHelpMsg.getAD_CtxHelp_ID()); suggestion.setAD_CtxHelpMsg_ID(ctxHelpMsg.get_ID()); } else { MCtxHelp ctxHelp = new MCtxHelp(Env.getCtx(), 0, trx.getTrxName()); setContextHelpInfo(po, ctxHelp); ctxHelp.setClientOrg(0, 0); ctxHelp.saveCrossTenantSafeEx(); if (po != null) { if (po.is_Immutable()) { // get a new not immutable PO MTable table = MTable.get(po.get_Table_ID()); PO mutablePO = table.getPO(po.get_ID(), trx.getTrxName()); mutablePO.set_ValueOfColumn("AD_CtxHelp_ID", ctxHelp.getAD_CtxHelp_ID()); mutablePO.saveCrossTenantSafeEx(trx.getTrxName()); po.load(trx.getTrxName()); } else { po.set_ValueOfColumn("AD_CtxHelp_ID", ctxHelp.getAD_CtxHelp_ID()); po.saveCrossTenantSafeEx(trx.getTrxName()); } } suggestion.setAD_CtxHelp_ID(ctxHelp.getAD_CtxHelp_ID()); MCtxHelpMsg msg = new MCtxHelpMsg(Env.getCtx(), 0, trx.getTrxName()); msg.setAD_CtxHelp_ID(ctxHelp.getAD_CtxHelp_ID()); msg.setClientOrg(0, 0); msg.setMsgText(baseContent); msg.saveCrossTenantSafeEx(); suggestion.setAD_CtxHelpMsg_ID(msg.getAD_CtxHelpMsg_ID()); if (!Util.isEmpty(translatedContent) && !Env.isBaseLanguage(Env.getCtx(), I_AD_CtxHelpMsg.Table_Name)) { int id = DB.getSQLValueEx(trx.getTrxName(), "SELECT AD_CtxHelpMsg_ID FROM AD_CtxHelpMsg_Trl WHERE AD_CtxHelpMsg_ID=? AND AD_Client_ID=? " + "AND IsActive='Y' AND AD_Language=?", msg.getAD_CtxHelpMsg_ID(), 0, Env.getAD_Language(Env.getCtx())); if (id == msg.getAD_CtxHelpMsg_ID()) { List params = new ArrayList(); StringBuilder update = new StringBuilder("UPDATE AD_CtxHelpMsg_Trl SET MsgText=? "); update.append("WHERE AD_CtxHelpMsg_ID=? AND AD_Language=? AND AD_Client_ID=?"); params.add(translatedContent); params.add(id); params.add(Env.getAD_Language(Env.getCtx())); params.add(0); DB.executeUpdateEx(update.toString(), params.toArray(), trx.getTrxName()); } else { StringBuilder insert = new StringBuilder("Insert Into AD_CtxHelpMsg_Trl (AD_Client_ID, AD_Org_ID, AD_CtxHelpMsg_ID, IsActive, IsTranslated, AD_Language, MsgText,"); insert.append("Created, CreatedBy, Updated, UpdatedBy, AD_CtxHelpMsg_Trl_UU)") .append(" Values (?, ?, ?, 'Y', 'N', ?, ?, getDate(), ?, getDate(), ?, generate_uuid()) "); List params = new ArrayList(); params.add(0); params.add(0); params.add(msg.getAD_CtxHelpMsg_ID()); params.add(Env.getAD_Language(Env.getCtx())); params.add(translatedContent); params.add(Env.getAD_User_ID(Env.getCtx())); params.add(Env.getAD_User_ID(Env.getCtx())); DB.executeUpdateEx(insert.toString(), params.toArray(), trx.getTrxName()); } } } suggestion.setAD_Language(Env.getAD_Language(Env.getCtx())); suggestion.setAD_User_ID(Env.getAD_User_ID(Env.getCtx())); suggestion.set_ValueOfColumn("AD_UserClient_ID", Env.getAD_Client_ID(Env.getCtx())); suggestion.setIsApproved(false); suggestion.setProcessed(false); suggestion.setMsgText(helpTextbox.getValue()); suggestion.setIsSaveAsTenantCustomization(false); suggestion.saveCrossTenantSafeEx(); } this.detach(); } /** * remove html header tag * @param htmlString * @return alter string */ private String removeHeaderTag(String htmlString) { htmlString = htmlString .replace("", "") .replace("", "") .replace("", "") .replace("", "") .replace("", "") .replace("", ""); return htmlString; } /** * @param po * @return context help name for po */ private String getContextHelpName(PO po) { if (po == null) { return "Home"; } else if (po instanceof MTab) { MTab tab = (MTab) po; return tab.getAD_Window().getName() + " / " + tab.getName(); } else if (po instanceof MProcess) { MProcess process = (MProcess) po; String name = process.getName(); return "Report/Process " + name; } else if (po instanceof MForm) { MForm form = (MForm) po; String name = form.getName(); return "Form " + name; } else if (po instanceof MWorkflow) { MWorkflow wf = (MWorkflow) po; String name = wf.getName(); return "Workflow " + name; } else if (po instanceof MInfoWindow) { MInfoWindow info = (MInfoWindow) po; String name = info.getName(); return "Info " + name; } else if (po instanceof MWFNode) { MWFNode node = (MWFNode) po; String name = "node"; return node.getAD_Workflow().getName() + " / " + name; } else if (po instanceof MTask) { MTask task = (MTask) po; String name = task.getName(); return "Task " + name; } else { return po.get_ValueAsString("Name"); } } /** * @param po * @param ctxHelp */ private void setContextHelpInfo(PO po, MCtxHelp ctxHelp) { if (po == null) { ctxHelp.setName("Home"); ctxHelp.setCtxType(X_AD_CtxHelp.CTXTYPE_Home); } else if (po instanceof MTab) { MTab tab = (MTab) po; String name = tab.getName(); String fullName = tab.getAD_Window().getName() + " / " + name; if (fullName.length() <= 60) { ctxHelp.setName(fullName); } else { ctxHelp.setDescription(fullName); String lname = "Tab " + name; if (lname.length() <= 60) { ctxHelp.setName(lname); } } ctxHelp.setCtxType(X_AD_CtxHelp.CTXTYPE_Tab); } else if (po instanceof MProcess) { MProcess process = (MProcess) po; String name = process.getName(); String fullName = "Report/Process " + name; if (fullName.length() <= 60) { ctxHelp.setName(fullName); } else { ctxHelp.setDescription(fullName); ctxHelp.setName(name); } ctxHelp.setCtxType(X_AD_CtxHelp.CTXTYPE_Process); } else if (po instanceof MForm) { MForm form = (MForm) po; String name = form.getName(); String fullName = "Form " + name; if (fullName.length() <= 60) { ctxHelp.setName(fullName); } else { ctxHelp.setDescription(fullName); ctxHelp.setName(name); } ctxHelp.setCtxType(X_AD_CtxHelp.CTXTYPE_Form); } else if (po instanceof MWorkflow) { MWorkflow wf = (MWorkflow) po; String name = wf.getName(); String fullName = "Workflow " + name; if (fullName.length() <= 60) { ctxHelp.setName(fullName); } else { ctxHelp.setDescription(fullName); ctxHelp.setName(name); } ctxHelp.setCtxType(X_AD_CtxHelp.CTXTYPE_Workflow); } else if (po instanceof MInfoWindow) { MInfoWindow info = (MInfoWindow) po; // Load User Def String name = info.getName(); MUserDefInfo userDef = MUserDefInfo.getBestMatch(Env.getCtx(), info.getAD_InfoWindow_ID()); if(userDef != null && !Util.isEmpty(userDef.getName())) { name = userDef.getName(); } String fullName = "Info " + name; if (fullName.length() <= 60) { ctxHelp.setName(fullName); } else { ctxHelp.setDescription(fullName); ctxHelp.setName(name); } ctxHelp.setCtxType(X_AD_CtxHelp.CTXTYPE_Info); } else if (po instanceof MWFNode) { MWFNode node = (MWFNode) po; String name = "node"; String fullName = node.getAD_Workflow().getName() + " / " + name; if (fullName.length() <= 60) { ctxHelp.setName(fullName); } else { ctxHelp.setDescription(fullName); ctxHelp.setName(name); } ctxHelp.setCtxType(X_AD_CtxHelp.CTXTYPE_Node); } else if (po instanceof MTask) { MTask task = (MTask) po; String name = task.getName(); String fullName = "Task " + name; if (fullName.length() <= 60) { ctxHelp.setName(fullName); } else { ctxHelp.setDescription(fullName); ctxHelp.setName(name); } ctxHelp.setCtxType(X_AD_CtxHelp.CTXTYPE_Task); } } }