IDEMPIERE-5527 Implement asynchronous rendering of dashboard gadget p… (#1621)

* IDEMPIERE-5527 Implement asynchronous rendering of dashboard gadget panel

* IDEMPIERE-5527 Implement asynchronous rendering of dashboard gadget panel

- add DashboardPanel.isLazy
- use background thread

* IDEMPIERE-5527 Implement asynchronous rendering of dashboard gadget panel

- Fix aynsc rendering of dashboard gadget
This commit is contained in:
hengsin 2023-01-17 00:58:37 +08:00 committed by GitHub
parent c047592862
commit a24de47473
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 362 additions and 196 deletions

View File

@ -57,6 +57,6 @@ Copyright (C) 2007 Ashley G Ramdass (ADempiere WebUI).
<!-- this js module doesn't actually exists and it is here for default theme version --> <!-- this js module doesn't actually exists and it is here for default theme version -->
<!-- since loading of js module is on demand, it doesn't cause any error as long as you don't try to load it --> <!-- since loading of js module is on demand, it doesn't cause any error as long as you don't try to load it -->
<javascript-module name="idempiere.theme.default" version="202211301708" /> <javascript-module name="idempiere.theme.default" version="202301160600" />
</language> </language>

View File

@ -57,6 +57,16 @@ public class WDocumentStatusIndicator extends Panel implements EventListener<Eve
* @param documentStatus * @param documentStatus
*/ */
public WDocumentStatusIndicator(MDocumentStatus documentStatus) public WDocumentStatusIndicator(MDocumentStatus documentStatus)
{
this(documentStatus, false);
}
/**
* Constructor
* @param documentStatus
* @param lazy
*/
public WDocumentStatusIndicator(MDocumentStatus documentStatus, boolean lazy)
{ {
super(); super();
@ -65,8 +75,11 @@ public class WDocumentStatusIndicator extends Panel implements EventListener<Eve
init(); init();
this.setSclass("activities-box"); this.setSclass("activities-box");
refresh(); if (!lazy)
updateUI(); {
refresh();
updateUI();
}
} // WDocumentStatusIndicator } // WDocumentStatusIndicator
private MDocumentStatus m_documentStatus = null; private MDocumentStatus m_documentStatus = null;

View File

@ -55,6 +55,8 @@ public class WDocumentStatusPanel extends Panel {
/** Document Status Indicators */ /** Document Status Indicators */
private MDocumentStatus[] m_indicators = null; private MDocumentStatus[] m_indicators = null;
private int lastRefreshCount;
/** Logger */ /** Logger */
private static final CLogger log = CLogger.getCLogger (WDocumentStatusPanel.class); private static final CLogger log = CLogger.getCLogger (WDocumentStatusPanel.class);
@ -102,27 +104,28 @@ public class WDocumentStatusPanel extends Panel {
Row row = new Row(); Row row = new Row();
rows.appendChild(row); rows.appendChild(row);
WDocumentStatusIndicator pi = new WDocumentStatusIndicator(m_indicators[i]); WDocumentStatusIndicator pi = new WDocumentStatusIndicator(m_indicators[i], true);
row.appendChild(pi); row.appendChild(pi);
indicatorList.add(pi); indicatorList.add(pi);
} }
} // init } // init
public void refresh() { public void refresh() {
int count = 0; lastRefreshCount = 0;
for (WDocumentStatusIndicator indicator : indicatorList) { for (WDocumentStatusIndicator indicator : indicatorList) {
indicator.refresh(); indicator.refresh();
if (indicator.getDocumentStatus().getAD_Client_ID() == 0) if (indicator.getDocumentStatus().getAD_Client_ID() == 0)
count += indicator.getStatusCount(); lastRefreshCount += indicator.getStatusCount();
} }
EventQueue<Event> queue = EventQueues.lookup(IDesktop.ACTIVITIES_EVENT_QUEUE, true);
Event event = new Event(IDesktop.ON_ACTIVITIES_CHANGED_EVENT, null, count);
queue.publish(event);
} }
public void updateUI() { public void updateUI() {
for (WDocumentStatusIndicator indicator : indicatorList) { for (WDocumentStatusIndicator indicator : indicatorList) {
indicator.updateUI(); indicator.updateUI();
} }
EventQueue<Event> queue = EventQueues.lookup(IDesktop.ACTIVITIES_EVENT_QUEUE, true);
Event event = new Event(IDesktop.ON_ACTIVITIES_CHANGED_EVENT, null, lastRefreshCount);
queue.publish(event);
} }
} }

View File

@ -178,4 +178,9 @@ public class DPActivities extends DashboardPanel implements EventListener<Event>
} }
} }
} }
@Override
public boolean isLazy() {
return true;
}
} }

View File

@ -597,4 +597,9 @@ public class DPCalendar extends DashboardPanel implements EventListener<Event>,
trx.removeTrxEventListener(this); trx.removeTrxEventListener(this);
} }
} }
@Override
public boolean isLazy() {
return true;
}
} }

View File

@ -52,7 +52,7 @@ public class DPDocumentStatus extends DashboardPanel implements EventListener<Ev
@Override @Override
public void refresh(ServerPushTemplate template) { public void refresh(ServerPushTemplate template) {
statusPanel.refresh(); statusPanel.refresh();
template.execute(this); template.executeAsync(this);
} }
@Override @Override
@ -104,4 +104,9 @@ public class DPDocumentStatus extends DashboardPanel implements EventListener<Ev
public boolean isPooling() { public boolean isPooling() {
return true; return true;
} }
@Override
public boolean isLazy() {
return true;
}
} }

View File

@ -13,13 +13,9 @@
*****************************************************************************/ *****************************************************************************/
package org.adempiere.webui.dashboard; package org.adempiere.webui.dashboard;
import org.adempiere.util.ContextRunnable;
import org.adempiere.webui.apps.AEnv;
import org.adempiere.webui.apps.DesktopRunnable;
import org.adempiere.webui.apps.graph.WPAPanel; import org.adempiere.webui.apps.graph.WPAPanel;
import org.adempiere.webui.apps.graph.WPerformanceIndicator.Options; import org.adempiere.webui.apps.graph.WPerformanceIndicator.Options;
import org.adempiere.webui.util.ServerPushTemplate; import org.adempiere.webui.util.ServerPushTemplate;
import org.compiere.Adempiere;
import org.compiere.model.MGoal; import org.compiere.model.MGoal;
import org.compiere.model.MSysConfig; import org.compiere.model.MSysConfig;
import org.compiere.util.Env; import org.compiere.util.Env;
@ -44,6 +40,7 @@ public class DPPerformance extends DashboardPanel {
private static final long serialVersionUID = -8878665031716441912L; private static final long serialVersionUID = -8878665031716441912L;
private WPAPanel paPanel; private WPAPanel paPanel;
private MGoal[] performanceData;
public DPPerformance() public DPPerformance()
{ {
@ -53,43 +50,18 @@ public class DPPerformance extends DashboardPanel {
// and can't update when finish load data // and can't update when finish load data
paPanel = new WPAPanel(); paPanel = new WPAPanel();
appendChild(paPanel); appendChild(paPanel);
Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(new LoadPerfomanceData(this), Executions.getCurrent().getDesktop()));
}
static class LoadPerfomanceData extends ContextRunnable{
private DPPerformance parentCtr;
public LoadPerfomanceData (DPPerformance parentCtr){
this.parentCtr = parentCtr;
}
@Override
protected void doRun() {
MGoal [] performanceData = WPAPanel.loadGoal();
AEnv.executeAsyncDesktopTask(new Runnable() {
@Override
public void run() {
if (performanceData != null && performanceData.length > 0){
parentCtr.paPanel.setGoals(performanceData, (Options)null);
if (parentCtr.getAttribute(ON_POST_RENDER_ATTR) == null) {
parentCtr.setAttribute(ON_POST_RENDER_ATTR, Boolean.TRUE);
Events.echoEvent("onPostRender", parentCtr, null);
}
}
}
});
}
} }
public void refresh(ServerPushTemplate template) { public void refresh(ServerPushTemplate template) {
super.refresh(template); performanceData = WPAPanel.loadGoal();
if (Executions.getCurrent() != null) { if (Executions.getCurrent() != null) {
updateUI();
if (this.getAttribute(ON_POST_RENDER_ATTR) == null && paPanel.getChildren().size() > 0) { if (this.getAttribute(ON_POST_RENDER_ATTR) == null && paPanel.getChildren().size() > 0) {
setAttribute(ON_POST_RENDER_ATTR, Boolean.TRUE); setAttribute(ON_POST_RENDER_ATTR, Boolean.TRUE);
Events.echoEvent("onPostRender", this, null); Events.echoEvent("onPostRender", this, null);
} }
} else {
template.executeAsync(this);
} }
} }
@ -121,4 +93,15 @@ public class DPPerformance extends DashboardPanel {
this.getFirstChild().invalidate(); this.getFirstChild().invalidate();
} }
} }
@Override
public void updateUI() {
paPanel.setGoals(performanceData, (Options)null);
performanceData = null;
}
@Override
public boolean isLazy() {
return true;
}
} }

View File

@ -93,7 +93,6 @@ public class DPRecentItems extends DashboardPanel implements EventListener<Event
ZKUpdateUtil.setHflex(bxRecentItems, "1"); ZKUpdateUtil.setHflex(bxRecentItems, "1");
this.setSclass("recentitems-box"); this.setSclass("recentitems-box");
recentItemsContent.appendChild(bxRecentItems); recentItemsContent.appendChild(bxRecentItems);
createRecentItemsPanel();
Toolbar recentItemsToolbar = new Toolbar(); Toolbar recentItemsToolbar = new Toolbar();
this.appendChild(recentItemsToolbar); this.appendChild(recentItemsToolbar);
@ -162,11 +161,6 @@ public class DPRecentItems extends DashboardPanel implements EventListener<Event
} }
} }
private void createRecentItemsPanel()
{
refresh();
}
/** /**
* Make Recent Item remove persistent * Make Recent Item remove persistent
* @param AD_RecentItem_ID Recent Item ID * @param AD_RecentItem_ID Recent Item ID
@ -365,6 +359,11 @@ public class DPRecentItems extends DashboardPanel implements EventListener<Event
cleanup(); cleanup();
} }
@Override
public boolean isLazy() {
return true;
}
static class TopicSubscriber implements ITopicSubscriber<Integer> { static class TopicSubscriber implements ITopicSubscriber<Integer> {
@Override @Override
public void onMessage(Integer message) { public void onMessage(Integer message) {

View File

@ -82,7 +82,6 @@ public class DPRunningJobs extends DashboardPanel implements EventListener<Event
ZKUpdateUtil.setHflex(bxJobs, "1"); ZKUpdateUtil.setHflex(bxJobs, "1");
this.setSclass("recentitems-box"); this.setSclass("recentitems-box");
jobsContent.appendChild(bxJobs); jobsContent.appendChild(bxJobs);
createJobsPanel();
Toolbar jobsToolbar = new Toolbar(); Toolbar jobsToolbar = new Toolbar();
this.appendChild(jobsToolbar); this.appendChild(jobsToolbar);
@ -133,11 +132,6 @@ public class DPRunningJobs extends DashboardPanel implements EventListener<Event
} }
} }
private void createJobsPanel()
{
refresh();
}
@Override @Override
public void onEvent(Event event) throws Exception public void onEvent(Event event) throws Exception
{ {
@ -281,6 +275,11 @@ public class DPRunningJobs extends DashboardPanel implements EventListener<Event
cleanup(); cleanup();
} }
@Override
public boolean isLazy() {
return true;
}
static class TopicSubscriber implements ITopicSubscriber<Integer> { static class TopicSubscriber implements ITopicSubscriber<Integer> {
@Override @Override
public void onMessage(Integer message) { public void onMessage(Integer message) {

View File

@ -33,9 +33,11 @@ public abstract class DashboardPanel extends Window implements IDashboardPanel {
super(); super();
} }
@Override
public void refresh(ServerPushTemplate template) { public void refresh(ServerPushTemplate template) {
} }
@Override
public void updateUI() { public void updateUI() {
} }
@ -45,4 +47,12 @@ public abstract class DashboardPanel extends Window implements IDashboardPanel {
public boolean isPooling() { public boolean isPooling() {
return false; return false;
} }
/**
* Override this together with refresh and updateUI to implement background loading of gadget
* @return true if panel created without loading of data
*/
public boolean isLazy() {
return false;
}
} }

View File

@ -33,10 +33,12 @@ import java.util.Properties;
import java.util.logging.Level; import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException; import org.adempiere.exceptions.AdempiereException;
import org.adempiere.util.ContextRunnable;
import org.adempiere.webui.ClientInfo; import org.adempiere.webui.ClientInfo;
import org.adempiere.webui.Extensions; import org.adempiere.webui.Extensions;
import org.adempiere.webui.LayoutUtils; import org.adempiere.webui.LayoutUtils;
import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.apps.AEnv;
import org.adempiere.webui.apps.BusyDialog;
import org.adempiere.webui.apps.graph.IChartRendererService; import org.adempiere.webui.apps.graph.IChartRendererService;
import org.adempiere.webui.apps.graph.WGraph; import org.adempiere.webui.apps.graph.WGraph;
import org.adempiere.webui.apps.graph.WPAWidget; import org.adempiere.webui.apps.graph.WPAWidget;
@ -49,8 +51,10 @@ import org.adempiere.webui.dashboard.DashboardRunnable;
import org.adempiere.webui.report.HTMLExtension; import org.adempiere.webui.report.HTMLExtension;
import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.theme.ThemeManager;
import org.adempiere.webui.util.ServerPushTemplate;
import org.adempiere.webui.util.ZKUpdateUtil; import org.adempiere.webui.util.ZKUpdateUtil;
import org.adempiere.webui.window.ZkReportViewerProvider; import org.adempiere.webui.window.ZkReportViewerProvider;
import org.compiere.Adempiere;
import org.compiere.model.I_AD_Menu; import org.compiere.model.I_AD_Menu;
import org.compiere.model.MChart; import org.compiere.model.MChart;
import org.compiere.model.MDashboardContent; import org.compiere.model.MDashboardContent;
@ -200,7 +204,7 @@ public class DashboardController implements EventListener<Event> {
int AD_User_ID = Env.getAD_User_ID(Env.getCtx()); int AD_User_ID = Env.getAD_User_ID(Env.getCtx());
int AD_Role_ID = Env.getAD_Role_ID(Env.getCtx()); int AD_Role_ID = Env.getAD_Role_ID(Env.getCtx());
MDashboardPreference[] dps = MDashboardPreference.getForSession(AD_User_ID, AD_Role_ID, true); MDashboardPreference[] dps = MDashboardPreference.getForSession(AD_User_ID, AD_Role_ID, true);
MDashboardContent [] dcs = MDashboardContentAccess.get(Env.getCtx(), AD_Role_ID, AD_User_ID, null); MDashboardContent [] dcs = MDashboardContentAccess.get(Env.getCtx(), AD_Role_ID, AD_User_ID, null);
if(dps.length == 0){ if(dps.length == 0){
@ -245,9 +249,9 @@ public class DashboardController implements EventListener<Event> {
{ {
dashboardColumnLayout = new Vlayout(); dashboardColumnLayout = new Vlayout();
dashboardColumnLayout.setSclass("dashboard-column"); dashboardColumnLayout.setSclass("dashboard-column");
dashboardColumnLayout.setAttribute(COLUMN_NO_ATTRIBUTE, columnNo); dashboardColumnLayout.setAttribute(COLUMN_NO_ATTRIBUTE, columnNo);
dashboardColumnLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard); dashboardColumnLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard);
dashboardColumnLayout.setAttribute(IS_ADDITIONAL_COLUMN_ATTRIBUTE, false); dashboardColumnLayout.setAttribute(IS_ADDITIONAL_COLUMN_ATTRIBUTE, false);
Anchorchildren dashboardColumn = new Anchorchildren(); Anchorchildren dashboardColumn = new Anchorchildren();
dashboardColumn.setAnchor(width + "%" + " 100%"); dashboardColumn.setAnchor(width + "%" + " 100%");
if (!ClientInfo.isMobile()) if (!ClientInfo.isMobile())
@ -269,19 +273,48 @@ public class DashboardController implements EventListener<Event> {
} else { } else {
panel = newGadgetPanel(dp, dc); panel = newGadgetPanel(dp, dc);
} }
if (panel != null && panel.getAttribute(PANEL_EMPTY_ATTRIBUTE) == null) if (panel != null && panel.getAttribute(PANEL_EMPTY_ATTRIBUTE) == null)
dashboardColumnLayout.appendChild(panel); dashboardColumnLayout.appendChild(panel);
if (!update) { if (!update) {
renderGadgetPanel(dc, panel); final Panel fp = panel;
ServerPushTemplate spt = new ServerPushTemplate(dashboardLayout.getDesktop());
IDesktop appDesktop = SessionManager.getAppDesktop();
String contextPath = Executions.getCurrent().getContextPath();
Panelchildren panelChildren = new Panelchildren();
fp.appendChild(panelChildren);
BusyDialog busyDialog = new BusyDialog();
busyDialog.setShadow(false);
panelChildren.appendChild(busyDialog);
//must create zulfile component in foreground UI thread
Component zComponent = null;
if (!Util.isEmpty(dc.getZulFilePath(), true)) {
try {
zComponent = Extensions.getDashboardGadget(dc.getZulFilePath(), panelChildren, dc);
} catch (Exception e) {
throw new AdempiereException(e);
}
}
final Component zulComponent = zComponent;
ContextRunnable cr = new ContextRunnable() {
@Override
protected void doRun() {
try {
asyncRenderGadgetPanel(spt, dc, fp, appDesktop, contextPath, panelChildren, zulComponent);
} catch (Exception e) {
e.printStackTrace();
}
}
};
Adempiere.getThreadPoolExecutor().submit(cr);
} }
} }
if (dps.length == 0) if (dps.length == 0)
{ {
dashboardColumnLayout = new Vlayout(); dashboardColumnLayout = new Vlayout();
dashboardColumnLayout.setAttribute(COLUMN_NO_ATTRIBUTE, "0"); dashboardColumnLayout.setAttribute(COLUMN_NO_ATTRIBUTE, "0");
dashboardColumnLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard); dashboardColumnLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard);
dashboardColumnLayout.setAttribute(IS_ADDITIONAL_COLUMN_ATTRIBUTE, true); dashboardColumnLayout.setAttribute(IS_ADDITIONAL_COLUMN_ATTRIBUTE, true);
Anchorchildren dashboardColumn = new Anchorchildren(); Anchorchildren dashboardColumn = new Anchorchildren();
dashboardColumn.setAnchor((width-5) + "%" + " 100%"); dashboardColumn.setAnchor((width-5) + "%" + " 100%");
if (!ClientInfo.isMobile()) if (!ClientInfo.isMobile())
@ -299,9 +332,9 @@ public class DashboardController implements EventListener<Event> {
// additional column // additional column
dashboardColumnLayout = new Vlayout(); dashboardColumnLayout = new Vlayout();
ZKUpdateUtil.setWidth(dashboardColumnLayout, "100%"); ZKUpdateUtil.setWidth(dashboardColumnLayout, "100%");
dashboardColumnLayout.setAttribute(COLUMN_NO_ATTRIBUTE, currentColumnNo + 1); dashboardColumnLayout.setAttribute(COLUMN_NO_ATTRIBUTE, currentColumnNo + 1);
dashboardColumnLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard); dashboardColumnLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard);
dashboardColumnLayout.setAttribute(IS_ADDITIONAL_COLUMN_ATTRIBUTE, true); dashboardColumnLayout.setAttribute(IS_ADDITIONAL_COLUMN_ATTRIBUTE, true);
Anchorchildren dashboardColumn = new Anchorchildren(); Anchorchildren dashboardColumn = new Anchorchildren();
dashboardColumn.setAnchor(extraWidth + "% 100%"); dashboardColumn.setAnchor(extraWidth + "% 100%");
if (!ClientInfo.isMobile()) if (!ClientInfo.isMobile())
@ -321,9 +354,9 @@ public class DashboardController implements EventListener<Event> {
} }
// //
if (!update && !dashboardRunnable.isEmpty()) if (!update)
{ {
startDashboardRunnable(parent); startDashboardRunnable(parent);
} }
} }
@ -387,19 +420,50 @@ public class DashboardController implements EventListener<Event> {
}); });
} }
private void renderGadgetPanel(MDashboardContent dc, Panel panel) throws Exception { /**
Panelchildren content = new Panelchildren(); * Render gadget panel in background thread
panel.appendChild(content); * @param spt
boolean panelEmpty = true; * @param dashboardContent
panelEmpty = !render(content, dc, dashboardRunnable); * @param panel
if (panelEmpty) { * @param appDesktop
panel.detach(); * @param contextPath
panel.setAttribute(PANEL_EMPTY_ATTRIBUTE, Boolean.TRUE); * @param panelChildren
} * @param zulComponent
* @throws Exception
*/
private void asyncRenderGadgetPanel(ServerPushTemplate spt, MDashboardContent dashboardContent, Panel panel, IDesktop appDesktop, String contextPath,
Panelchildren panelChildren, Component zulComponent) throws Exception {
List<Component> components = new ArrayList<>();
asyncRenderComponents(dashboardContent, dashboardRunnable, appDesktop, contextPath, panelChildren, components, zulComponent);
if (components.size() > 0) {
for(Component c : components) {
if (c.getParent() != panelChildren) {
spt.executeAsync(() -> panelChildren.appendChild(c));
}
if (c instanceof DashboardPanel) {
DashboardPanel dpanel = (DashboardPanel) c;
if (dpanel.isLazy()) {
try {
dpanel.refresh(spt);
} catch (Exception e) {
logger.log(Level.SEVERE, e.getMessage(), e);
}
}
}
}
spt.executeAsync(() -> {
if (panelChildren.getFirstChild() != null && panelChildren.getFirstChild() instanceof BusyDialog)
panelChildren.getFirstChild().detach();
});
} else {
spt.executeAsync(() -> {
panel.detach();
panel.setAttribute(PANEL_EMPTY_ATTRIBUTE, Boolean.TRUE);
});
}
} }
private void startDashboardRunnable(Component parent) { private void startDashboardRunnable(Component parent) {
dashboardRunnable.refreshDashboard(false);
// default Update every one minutes // default Update every one minutes
int interval = MSysConfig.getIntValue(MSysConfig.ZK_DASHBOARD_REFRESH_INTERVAL, 60000); int interval = MSysConfig.getIntValue(MSysConfig.ZK_DASHBOARD_REFRESH_INTERVAL, 60000);
dashboardTimer = new Timer(); dashboardTimer = new Timer();
@ -442,7 +506,7 @@ public class DashboardController implements EventListener<Event> {
int AD_User_ID = Env.getAD_User_ID(Env.getCtx()); int AD_User_ID = Env.getAD_User_ID(Env.getCtx());
int AD_Role_ID = Env.getAD_Role_ID(Env.getCtx()); int AD_Role_ID = Env.getAD_Role_ID(Env.getCtx());
MDashboardPreference[] dps = MDashboardPreference.getForSession(AD_User_ID, AD_Role_ID, false); MDashboardPreference[] dps = MDashboardPreference.getForSession(AD_User_ID, AD_Role_ID, false);
MDashboardContent [] dcs = MDashboardContentAccess.get(Env.getCtx(), AD_Role_ID, AD_User_ID, null); MDashboardContent [] dcs = MDashboardContentAccess.get(Env.getCtx(), AD_Role_ID, AD_User_ID, null);
if(dps.length == 0){ if(dps.length == 0){
@ -478,12 +542,12 @@ public class DashboardController implements EventListener<Event> {
int lineNo = dp.getLine().intValue(); int lineNo = dp.getLine().intValue();
int flexGrow = (flexGrow = dp.getFlexGrow()) > 0 ? flexGrow : DEFAULT_FLEX_GROW; int flexGrow = (flexGrow = dp.getFlexGrow()) > 0 ? flexGrow : DEFAULT_FLEX_GROW;
if(dashboardLineLayout == null || currentLineNo != lineNo) if(dashboardLineLayout == null || currentLineNo != lineNo)
{ {
dashboardLineLayout = new Hlayout(); dashboardLineLayout = new Hlayout();
dashboardLineLayout.setAttribute(LINE_ATTRIBUTE, lineNo); dashboardLineLayout.setAttribute(LINE_ATTRIBUTE, lineNo);
dashboardLineLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard); dashboardLineLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard);
dashboardLineLayout.setAttribute(IS_ADDITIONAL_ROW_ATTRIBUTE, false); dashboardLineLayout.setAttribute(IS_ADDITIONAL_ROW_ATTRIBUTE, false);
dashboardLineLayout.setSclass("dashboard-row"); dashboardLineLayout.setSclass("dashboard-row");
Anchorchildren dashboardLine = new Anchorchildren(); Anchorchildren dashboardLine = new Anchorchildren();
dashboardLine.setAnchor(width + "%"); dashboardLine.setAnchor(width + "%");
@ -503,24 +567,53 @@ public class DashboardController implements EventListener<Event> {
if (update) { if (update) {
panel = findPanel(dp.getPA_DashboardContent_ID(), dp.getPA_DashboardPreference_ID()); panel = findPanel(dp.getPA_DashboardContent_ID(), dp.getPA_DashboardPreference_ID());
} else { } else {
panel = newGadgetPanel(dp, dc); panel = newGadgetPanel(dp, dc);
panel.setAttribute(FLEX_GROW_ATTRIBUTE, String.valueOf(flexGrow)); panel.setAttribute(FLEX_GROW_ATTRIBUTE, String.valueOf(flexGrow));
ZKUpdateUtil.setHflex(panel, String.valueOf(flexGrow)); ZKUpdateUtil.setHflex(panel, String.valueOf(flexGrow));
} }
if (panel != null && panel.getAttribute(PANEL_EMPTY_ATTRIBUTE) == null) { if (panel != null && panel.getAttribute(PANEL_EMPTY_ATTRIBUTE) == null) {
dashboardLineLayout.appendChild(panel); dashboardLineLayout.appendChild(panel);
} }
if (!update) { if (!update) {
renderGadgetPanel(dc, panel); final Panel fp = panel;
ServerPushTemplate spt = new ServerPushTemplate(dashboardLayout.getDesktop());
IDesktop appDesktop = SessionManager.getAppDesktop();
String contextPath = Executions.getCurrent().getContextPath();
Panelchildren panelChildren = new Panelchildren();
fp.appendChild(panelChildren);
BusyDialog busyDialog = new BusyDialog();
busyDialog.setShadow(false);
panelChildren.appendChild(busyDialog);
//must create zulfile component in foreground UI thread
Component zComponent = null;
if (!Util.isEmpty(dc.getZulFilePath(), true)) {
try {
zComponent = Extensions.getDashboardGadget(dc.getZulFilePath(), panelChildren, dc);
} catch (Exception e) {
throw new AdempiereException(e);
}
}
final Component zulComponent = zComponent;
ContextRunnable cr = new ContextRunnable() {
@Override
protected void doRun() {
try {
asyncRenderGadgetPanel(spt, dc, fp, appDesktop, contextPath, panelChildren, zulComponent);
} catch (Exception e) {
e.printStackTrace();
}
}
};
Adempiere.getThreadPoolExecutor().submit(cr);
} }
} }
if (dps.length == 0) if (dps.length == 0)
{ {
dashboardLineLayout = new Hlayout(); dashboardLineLayout = new Hlayout();
dashboardLineLayout.setAttribute(LINE_ATTRIBUTE, "0"); dashboardLineLayout.setAttribute(LINE_ATTRIBUTE, "0");
dashboardLineLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard); dashboardLineLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard);
dashboardLineLayout.setAttribute(IS_ADDITIONAL_ROW_ATTRIBUTE, true); dashboardLineLayout.setAttribute(IS_ADDITIONAL_ROW_ATTRIBUTE, true);
dashboardLineLayout.setSclass("dashboard-row"); dashboardLineLayout.setSclass("dashboard-row");
Anchorchildren dashboardColumn = new Anchorchildren(); Anchorchildren dashboardColumn = new Anchorchildren();
dashboardColumn.setAnchor((width-5) + "%" + " 100%"); dashboardColumn.setAnchor((width-5) + "%" + " 100%");
@ -539,9 +632,9 @@ public class DashboardController implements EventListener<Event> {
// additional row // additional row
dashboardLineLayout = new Hlayout(); dashboardLineLayout = new Hlayout();
ZKUpdateUtil.setWidth(dashboardLineLayout, "100%"); ZKUpdateUtil.setWidth(dashboardLineLayout, "100%");
dashboardLineLayout.setAttribute(LINE_ATTRIBUTE, currentLineNo + 1); dashboardLineLayout.setAttribute(LINE_ATTRIBUTE, currentLineNo + 1);
dashboardLineLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard); dashboardLineLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard);
dashboardLineLayout.setAttribute(IS_ADDITIONAL_ROW_ATTRIBUTE, true); dashboardLineLayout.setAttribute(IS_ADDITIONAL_ROW_ATTRIBUTE, true);
dashboardLineLayout.setSclass("dashboard-row"); dashboardLineLayout.setSclass("dashboard-row");
Anchorchildren dashboardLine = new Anchorchildren(); Anchorchildren dashboardLine = new Anchorchildren();
dashboardLine.setAnchor(width + "% 1%"); dashboardLine.setAnchor(width + "% 1%");
@ -564,9 +657,9 @@ public class DashboardController implements EventListener<Event> {
} }
// //
if (!update && !dashboardRunnable.isEmpty()) if (!update)
{ {
startDashboardRunnable(parent); startDashboardRunnable(parent);
} }
} }
@ -585,18 +678,20 @@ public class DashboardController implements EventListener<Event> {
} }
/** /**
* * Create gadget components in background thread
* @param content * @param dashboardContent
* @param dc
* @param dashboardRunnable * @param dashboardRunnable
* @return * @param appDesktop
* @param contextPath
* @param parentComponent
* @param components
* @param zulComponent
* @throws Exception * @throws Exception
*/ */
public boolean render(Component content, MDashboardContent dc, DashboardRunnable dashboardRunnable) throws Exception { private void asyncRenderComponents(MDashboardContent dashboardContent, DashboardRunnable dashboardRunnable, IDesktop appDesktop, String contextPath,
boolean empty = true; HtmlBasedComponent parentComponent, List<Component> components, Component zulComponent) throws Exception {
// HTML content // HTML content
String htmlContent = dc.get_ID() > 0 ? dc.get_Translation(MDashboardContent.COLUMNNAME_HTML) : null; String htmlContent = dashboardContent.get_ID() > 0 ? dashboardContent.get_Translation(MDashboardContent.COLUMNNAME_HTML) : null;
if(htmlContent != null) if(htmlContent != null)
{ {
StringBuilder result = new StringBuilder("<html><head>"); StringBuilder result = new StringBuilder("<html><head>");
@ -614,8 +709,7 @@ public class DashboardController implements EventListener<Event> {
result.append("</style>"); result.append("</style>");
} catch (Exception e1) { } catch (Exception e1) {
logger.log(Level.SEVERE, e1.getLocalizedMessage(), e1); logger.log(Level.SEVERE, e1.getLocalizedMessage(), e1);
} } finally{
finally{
if (bufferedReader != null) { if (bufferedReader != null) {
try { try {
bufferedReader.close(); bufferedReader.close();
@ -629,56 +723,58 @@ public class DashboardController implements EventListener<Event> {
Html html = new Html(); Html html = new Html();
html.setContent(result.toString()); html.setContent(result.toString());
content.appendChild(html); components.add(html);
empty = false;
} }
// Window // Window
int AD_Window_ID = dc.getAD_Window_ID(); int AD_Window_ID = dashboardContent.getAD_Window_ID();
if(AD_Window_ID > 0) if(AD_Window_ID > 0)
{ {
int AD_Menu_ID = dc.getAD_Menu_ID(); int AD_Menu_ID = dashboardContent.getAD_Menu_ID();
Div div = new Div(); Div div = new Div();
ToolBarButton btn = new ToolBarButton(String.valueOf(AD_Menu_ID)); ToolBarButton btn = new ToolBarButton(String.valueOf(AD_Menu_ID));
I_AD_Menu menu = dc.getAD_Menu(); I_AD_Menu menu = dashboardContent.getAD_Menu();
btn.setLabel(menu.getName()); btn.setLabel(menu.getName());
btn.setAttribute("AD_Menu_ID", AD_Menu_ID); btn.setAttribute("AD_Menu_ID", AD_Menu_ID);
btn.addEventListener(Events.ON_CLICK, this); btn.addEventListener(Events.ON_CLICK, this);
div.appendChild(btn); div.appendChild(btn);
content.appendChild(div); components.add(div);
empty = false;
} }
//Report & Process //Report & Process
int AD_Process_ID = dc.getAD_Process_ID(); int AD_Process_ID = dashboardContent.getAD_Process_ID();
if(AD_Process_ID > 0) if(AD_Process_ID > 0)
{ {
String sql = "SELECT AD_MENU_ID FROM AD_MENU WHERE AD_Process_ID=?"; String sql = "SELECT AD_MENU_ID FROM AD_MENU WHERE AD_Process_ID=?";
int AD_Menu_ID = DB.getSQLValue(null, sql, AD_Process_ID); int AD_Menu_ID = DB.getSQLValueEx(null, sql, AD_Process_ID);
ToolBarButton btn = new ToolBarButton(); ToolBarButton btn = new ToolBarButton();
MMenu menu = new MMenu(Env.getCtx(), AD_Menu_ID, null); MMenu menu = new MMenu(Env.getCtx(), AD_Menu_ID, null);
btn.setAttribute("AD_Menu_ID", AD_Menu_ID); btn.setAttribute("AD_Menu_ID", AD_Menu_ID);
btn.addEventListener(Events.ON_CLICK, this); btn.addEventListener(Events.ON_CLICK, this);
empty = false;
if (dc.isEmbedReportContent()) if (dashboardContent.isEmbedReportContent())
{ {
String processParameters = dc.getProcessParameters(); String processParameters = dashboardContent.getProcessParameters();
Div layout = new Div();
layout.setHeight("100%");
layout.setStyle("display: flex;flex-direction: column;");
components.add(layout);
Iframe iframe = new Iframe(); Iframe iframe = new Iframe();
iframe.setSclass("dashboard-report-iframe"); iframe.setSclass("dashboard-report-iframe");
content.appendChild(iframe); iframe.setStyle("flex-grow: 1;");
iframe.setContent(generateReport(AD_Process_ID, dc.getAD_PrintFormat_ID(), processParameters)); layout.appendChild(iframe);
iframe.setContent(generateReport(AD_Process_ID, dashboardContent.getAD_PrintFormat_ID(), processParameters, appDesktop, contextPath));
Toolbar toolbar = new Toolbar(); Toolbar toolbar = new Toolbar();
content.appendChild(toolbar); layout.appendChild(toolbar);
btn.setLabel(Msg.getMsg(Env.getCtx(), "OpenRunDialog")); btn.setLabel(Msg.getMsg(Env.getCtx(), "OpenRunDialog"));
toolbar.appendChild(btn); toolbar.appendChild(btn);
btn = new ToolBarButton(); btn = new ToolBarButton();
btn.setAttribute("AD_Process_ID", AD_Process_ID); btn.setAttribute("AD_Process_ID", AD_Process_ID);
btn.setAttribute("ProcessParameters", processParameters); btn.setAttribute("ProcessParameters", processParameters);
btn.setAttribute("AD_PrintFormat_ID", dc.getAD_PrintFormat_ID()); btn.setAttribute("AD_PrintFormat_ID", dashboardContent.getAD_PrintFormat_ID());
btn.addEventListener(Events.ON_CLICK, this); btn.addEventListener(Events.ON_CLICK, this);
btn.setLabel(Msg.getMsg(Env.getCtx(), "ViewReportInNewTab")); btn.setLabel(Msg.getMsg(Env.getCtx(), "ViewReportInNewTab"));
toolbar.appendChild(new Separator("vertical")); toolbar.appendChild(new Separator("vertical"));
@ -692,32 +788,30 @@ public class DashboardController implements EventListener<Event> {
else else
btn.setImage(ThemeManager.getThemeResource("images/Refresh16.png")); btn.setImage(ThemeManager.getThemeResource("images/Refresh16.png"));
btn.addEventListener(Events.ON_CLICK, e -> iframe.setContent(generateReport(AD_Process_ID, dc.getAD_PrintFormat_ID(), processParameters))); btn.addEventListener(Events.ON_CLICK, e -> iframe.setContent(generateReport(AD_Process_ID, dashboardContent.getAD_PrintFormat_ID(), processParameters, appDesktop, contextPath)));
toolbar.appendChild(btn); toolbar.appendChild(btn);
} }
else else
{ {
btn.setLabel(menu.getName()); btn.setLabel(menu.getName());
content.appendChild(btn); components.add(btn);
} }
} }
// Goal // Goal
int PA_Goal_ID = dc.getPA_Goal_ID(); int PA_Goal_ID = dashboardContent.getPA_Goal_ID();
if(PA_Goal_ID > 0) if(PA_Goal_ID > 0)
{ {
String goalDisplay = dashboardContent.getGoalDisplay();
String goalDisplay = dc.getGoalDisplay();
MGoal goal = new MGoal(Env.getCtx(), PA_Goal_ID, null); MGoal goal = new MGoal(Env.getCtx(), PA_Goal_ID, null);
if(MDashboardContent.GOALDISPLAY_GaugeIndicator.equals(goalDisplay)) { if(MDashboardContent.GOALDISPLAY_GaugeIndicator.equals(goalDisplay)) {
WPerformanceIndicator.Options options = new WPerformanceIndicator.Options(); WPerformanceIndicator.Options options = new WPerformanceIndicator.Options();
options.colorMap = new HashMap<String, Color>(); options.colorMap = new HashMap<String, Color>();
options.colorMap.put(WPerformanceIndicator.DIAL_BACKGROUND, new Color(224, 224, 224, 1)); options.colorMap.put(WPerformanceIndicator.DIAL_BACKGROUND, new Color(224, 224, 224, 1));
WPAWidget paWidget = new WPAWidget(goal, options, dc.isShowTitle()); WPAWidget paWidget = new WPAWidget(goal, options, dashboardContent.isShowTitle());
((HtmlBasedComponent)content).setSclass("performance-gadget"); components.add(paWidget);
content.appendChild(paWidget); LayoutUtils.addSclass("performance-gadget", parentComponent);
} } else {
else {
//link to open performance detail //link to open performance detail
Div div = new Div(); Div div = new Div();
Toolbarbutton link = new Toolbarbutton(); Toolbarbutton link = new Toolbarbutton();
@ -734,57 +828,46 @@ public class DashboardController implements EventListener<Event> {
} }
}); });
div.appendChild(link); div.appendChild(link);
content.appendChild(div); components.add(div);
WGraph graph = new WGraph(goal, 55, false, true, WGraph graph = new WGraph(goal, 55, false, true,
!(MDashboardContent.GOALDISPLAY_Chart.equals(goalDisplay)), !(MDashboardContent.GOALDISPLAY_Chart.equals(goalDisplay)),
MDashboardContent.GOALDISPLAY_Chart.equals(goalDisplay)); MDashboardContent.GOALDISPLAY_Chart.equals(goalDisplay));
content.appendChild(graph); components.add(graph);
} }
empty = false;
} }
// ZUL file url // Component created from ZUL file url
String url = dc.getZulFilePath(); if(zulComponent != null)
if(url != null)
{ {
try { try {
if (zulComponent instanceof Include)
Component component = Extensions.getDashboardGadget(url, content, dc); zulComponent = zulComponent.getFirstChild();
if(component != null)
{ if (zulComponent instanceof DashboardPanel)
if (component instanceof Include) {
component = component.getFirstChild(); DashboardPanel dashboardPanel = (DashboardPanel) zulComponent;
if (!dashboardPanel.getChildren().isEmpty()) {
if (component instanceof DashboardPanel) components.add(dashboardPanel);
{ addDashboardPanel(dashboardPanel);
DashboardPanel dashboardPanel = (DashboardPanel) component;
if (!dashboardPanel.getChildren().isEmpty()) {
content.appendChild(dashboardPanel);
addDashboardPanel(dashboardPanel);
empty = false;
}
} }
else }
{ else
content.appendChild(component); {
empty = false; components.add(zulComponent);
} }
}
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.WARNING, "Failed to create components. zul="+url, e);
throw new AdempiereException(e); throw new AdempiereException(e);
} }
} }
//chart //chart
final int AD_Chart_ID = dc.getAD_Chart_ID(); final int AD_Chart_ID = dashboardContent.getAD_Chart_ID();
if (AD_Chart_ID > 0) { if (AD_Chart_ID > 0) {
final Div chartPanel = new Div(); final Div chartPanel = new Div();
chartPanel.setSclass("chart-gadget"); chartPanel.setSclass("chart-gadget");
final MChart chartModel = new MChart(Env.getCtx(), AD_Chart_ID, null); final MChart chartModel = new MChart(Env.getCtx(), AD_Chart_ID, null);
content.appendChild(chartPanel); components.add(chartPanel);
empty = false;
chartPanel.addEventListener(Events.ON_AFTER_SIZE, new EventListener<AfterSizeEvent>() { chartPanel.addEventListener(Events.ON_AFTER_SIZE, new EventListener<AfterSizeEvent>() {
@Override @Override
public void onEvent(AfterSizeEvent event) throws Exception { public void onEvent(AfterSizeEvent event) throws Exception {
@ -798,13 +881,13 @@ public class DashboardController implements EventListener<Event> {
chartPanel.getChildren().clear(); chartPanel.getChildren().clear();
ChartModel model = new ChartModel(); ChartModel model = new ChartModel();
model.chart = chartModel; model.chart = chartModel;
renderChart(chartPanel, width, height, model, dc.isShowTitle()); renderChart(chartPanel, width, height, model, dashboardContent.isShowTitle());
} }
}); });
} }
// Status Line // Status Line
final int AD_StatusLine_ID = dc.getAD_StatusLine_ID(); final int AD_StatusLine_ID = dashboardContent.getAD_StatusLine_ID();
if(AD_StatusLine_ID > 0) { if(AD_StatusLine_ID > 0) {
MStatusLine sl = new MStatusLine(Env.getCtx(), AD_StatusLine_ID, null); MStatusLine sl = new MStatusLine(Env.getCtx(), AD_StatusLine_ID, null);
final Html statusLineHtml = new Html(); final Html statusLineHtml = new Html();
@ -812,11 +895,49 @@ public class DashboardController implements EventListener<Event> {
Div div = new Div(); Div div = new Div();
div.appendChild(statusLineHtml); div.appendChild(statusLineHtml);
div.setSclass("statusline-gadget"); div.setSclass("statusline-gadget");
((HtmlBasedComponent) content.getParent()).setSclass("statusline-wrapper"); components.add(div);
content.appendChild(div); LayoutUtils.addSclass("statusline-wrapper", ((HtmlBasedComponent) parentComponent.getParent()));
empty = false;
} }
}
/**
* Synchronous render of gadget content in foreground ui thread
* @param content must be an instanceof {@link HtmlBasedComponent}
* @param dashboardContent
* @param dashboardRunnable
* @return true if gadget dashboard is not empty
* @throws Exception
*/
public boolean render(Component content, MDashboardContent dashboardContent, DashboardRunnable dashboardRunnable) throws Exception {
List<Component> components = new ArrayList<>();
Component zulComponent = null;
if (!Util.isEmpty(dashboardContent.getZulFilePath(), true)) {
try {
zulComponent = Extensions.getDashboardGadget(dashboardContent.getZulFilePath(), content, dashboardContent);
} catch (Exception e) {
throw new AdempiereException(e);
}
}
HtmlBasedComponent parentComponent = (HtmlBasedComponent) content;
asyncRenderComponents(dashboardContent, dashboardRunnable, SessionManager.getAppDesktop(), Executions.getCurrent().getContextPath(), parentComponent, components, zulComponent);
boolean empty = components.isEmpty();
ServerPushTemplate spt = new ServerPushTemplate(content.getDesktop());
for(Component c : components) {
if (c.getParent() != parentComponent) {
parentComponent.appendChild(c);
}
if (c instanceof DashboardPanel) {
DashboardPanel dpanel = (DashboardPanel) c;
if (dpanel.isLazy()) {
try {
dpanel.refresh(spt);
} catch (Exception e) {
logger.log(Level.SEVERE, e.getMessage(), e);
}
}
}
}
return !empty; return !empty;
} }
@ -866,8 +987,8 @@ public class DashboardController implements EventListener<Event> {
} }
panel.setSclass("dashboard-widget"); panel.setSclass("dashboard-widget");
//following 2 line needed for restore to size the panel correctly //following 2 line needed for restore to size the panel correctly
ZKUpdateUtil.setHflex(panel, (String)panel.getAttribute(FLEX_GROW_ATTRIBUTE)); ZKUpdateUtil.setHflex(panel, (String)panel.getAttribute(FLEX_GROW_ATTRIBUTE));
ZKUpdateUtil.setHeight(panel, "100%"); ZKUpdateUtil.setHeight(panel, "100%");
} }
} }
else if(eventName.equals(Events.ON_CLICK)) else if(eventName.equals(Events.ON_CLICK))
@ -964,7 +1085,7 @@ public class DashboardController implements EventListener<Event> {
if(comp instanceof Panel) if(comp instanceof Panel)
{ {
Panel panel = (Panel) comp; Panel panel = (Panel) comp;
Object value = panel.getAttribute(MDashboardPreference.COLUMNNAME_PA_DashboardPreference_ID); Object value = panel.getAttribute(MDashboardPreference.COLUMNNAME_PA_DashboardPreference_ID);
if (value != null) if (value != null)
{ {
int PA_DashboardPreference_ID = Integer.parseInt(value.toString()); int PA_DashboardPreference_ID = Integer.parseInt(value.toString());
@ -1064,7 +1185,7 @@ public class DashboardController implements EventListener<Event> {
if (child instanceof Panel) if (child instanceof Panel)
{ {
Panel panel = (Panel) child; Panel panel = (Panel) child;
value = panel.getAttribute(MDashboardPreference.COLUMNNAME_PA_DashboardPreference_ID); value = panel.getAttribute(MDashboardPreference.COLUMNNAME_PA_DashboardPreference_ID);
if (value != null) if (value != null)
{ {
++counter; ++counter;
@ -1100,9 +1221,9 @@ public class DashboardController implements EventListener<Event> {
// additional column // additional column
Vlayout dashboardColumnLayout = new Vlayout(); Vlayout dashboardColumnLayout = new Vlayout();
dashboardColumnLayout.setAttribute(COLUMN_NO_ATTRIBUTE, columnNo + 1); dashboardColumnLayout.setAttribute(COLUMN_NO_ATTRIBUTE, columnNo + 1);
dashboardColumnLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard); dashboardColumnLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard);
dashboardColumnLayout.setAttribute(IS_ADDITIONAL_COLUMN_ATTRIBUTE, true); dashboardColumnLayout.setAttribute(IS_ADDITIONAL_COLUMN_ATTRIBUTE, true);
Anchorchildren dashboardColumn = new Anchorchildren(); Anchorchildren dashboardColumn = new Anchorchildren();
dashboardColumn.setAnchor(extraWidth + "% 100%"); dashboardColumn.setAnchor(extraWidth + "% 100%");
if (!ClientInfo.isMobile()) { if (!ClientInfo.isMobile()) {
@ -1149,7 +1270,7 @@ public class DashboardController implements EventListener<Event> {
if (child instanceof Panel) if (child instanceof Panel)
{ {
Panel panel = (Panel) child; Panel panel = (Panel) child;
value = panel.getAttribute(MDashboardPreference.COLUMNNAME_PA_DashboardPreference_ID); value = panel.getAttribute(MDashboardPreference.COLUMNNAME_PA_DashboardPreference_ID);
if (value != null) if (value != null)
{ {
int PA_DashboardPreference_ID = Integer.parseInt(value.toString()); int PA_DashboardPreference_ID = Integer.parseInt(value.toString());
@ -1197,9 +1318,9 @@ public class DashboardController implements EventListener<Event> {
// additional row // additional row
Hlayout dashboardLineLayout = new Hlayout(); Hlayout dashboardLineLayout = new Hlayout();
ZKUpdateUtil.setWidth(dashboardLineLayout, "100%"); ZKUpdateUtil.setWidth(dashboardLineLayout, "100%");
dashboardLineLayout.setAttribute(LINE_ATTRIBUTE, lineNo + 1); dashboardLineLayout.setAttribute(LINE_ATTRIBUTE, lineNo + 1);
dashboardLineLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard); dashboardLineLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard);
dashboardLineLayout.setAttribute(IS_ADDITIONAL_ROW_ATTRIBUTE, true); dashboardLineLayout.setAttribute(IS_ADDITIONAL_ROW_ATTRIBUTE, true);
dashboardLineLayout.setSclass("dashboard-row"); dashboardLineLayout.setSclass("dashboard-row");
Anchorchildren dashboardLine = new Anchorchildren(); Anchorchildren dashboardLine = new Anchorchildren();
dashboardLine.setAnchor(width + "% 1%"); dashboardLine.setAnchor(width + "% 1%");
@ -1315,12 +1436,12 @@ public class DashboardController implements EventListener<Event> {
} }
private AMedia generateReport(int AD_Process_ID, int AD_PrintFormat_ID, String parameters) throws Exception { private AMedia generateReport(int AD_Process_ID, int AD_PrintFormat_ID, String parameters, IDesktop appDesktop, String contextPath) throws Exception {
ReportEngine re = runReport(AD_Process_ID, AD_PrintFormat_ID, parameters); ReportEngine re = runReport(AD_Process_ID, AD_PrintFormat_ID, parameters);
File file = FileUtil.createTempFile(re.getName(), ".html"); File file = FileUtil.createTempFile(re.getName(), ".html");
re.createHTML(file, false, AEnv.getLanguage(Env.getCtx()), new HTMLExtension(Executions.getCurrent().getContextPath(), "rp", re.createHTML(file, false, AEnv.getLanguage(Env.getCtx()), new HTMLExtension(contextPath, "rp",
SessionManager.getAppDesktop().getComponent().getUuid())); appDesktop.getComponent().getUuid()));
return new AMedia(re.getName(), "html", "text/html", file, false); return new AMedia(re.getName(), "html", "text/html", file, false);
} }
@ -1448,8 +1569,8 @@ public class DashboardController implements EventListener<Event> {
ts = (Timestamp)value; ts = (Timestamp)value;
else else
ts = Timestamp.valueOf(value.toString()); ts = Timestamp.valueOf(value.toString());
SimpleDateFormat dateFormat = DisplayType.getDateFormat(iPara.getDisplayType()); SimpleDateFormat dateFormat = DisplayType.getDateFormat(iPara.getDisplayType());
String info = dateFormat.format(ts); String info = dateFormat.format(ts);
if (isTo) { if (isTo) {
iPara.setP_Date_To(ts); iPara.setP_Date_To(ts);
iPara.setInfo_To(info); iPara.setInfo_To(info);

View File

@ -1,6 +1,27 @@
/** /***********************************************************************
* * This file is part of iDempiere ERP Open Source *
*/ * http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* 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 2 *
* 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, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - hengsin *
**********************************************************************/
package org.adempiere.webui.editor; package org.adempiere.webui.editor;
import java.util.logging.Level; import java.util.logging.Level;
@ -139,8 +160,6 @@ public class WDashboardContentEditor extends WEditor {
DashboardRunnable dashboardRunnable = new DashboardRunnable(panel.getDesktop()); DashboardRunnable dashboardRunnable = new DashboardRunnable(panel.getDesktop());
dashboardController.render(div, content, dashboardRunnable); dashboardController.render(div, content, dashboardRunnable);
if (!dashboardRunnable.isEmpty())
dashboardRunnable.refreshDashboard(false);
pc.appendChild(div); pc.appendChild(div);
} }

View File

@ -17,8 +17,13 @@
width: calc(100% - 10px); width: calc(100% - 10px);
} }
.dashboard-widget.z-panel {
display: flex;
flex-direction: column;
justify-content: stretch;
}
.dashboard-widget > .z-panel-body { .dashboard-widget > .z-panel-body {
height: 100%; flex-grow: 1;
} }
.statusline-wrapper { .statusline-wrapper {
@ -95,7 +100,6 @@
border: 1px solid lightgray; border: 1px solid lightgray;
margin:auto; margin:auto;
width: 99%; width: 99%;
height: 90%;
} }
.favourites-box { .favourites-box {