IDEMPIERE-5609 Dashboard Performance Indicators incrementally redrawed on DC drag and drop (#1736)
This commit is contained in:
parent
efcd7352f2
commit
e479eb5cfb
|
@ -198,6 +198,8 @@ public class MSysConfig extends X_AD_SysConfig
|
||||||
public static final String ZK_BUTTON_STYLE = "ZK_BUTTON_STYLE";
|
public static final String ZK_BUTTON_STYLE = "ZK_BUTTON_STYLE";
|
||||||
public static final String ZK_DASHBOARD_CALENDAR_REQUEST_DISPLAY_MODE = "ZK_DASHBOARD_CALENDAR_REQUEST_DISPLAY_MODE";
|
public static final String ZK_DASHBOARD_CALENDAR_REQUEST_DISPLAY_MODE = "ZK_DASHBOARD_CALENDAR_REQUEST_DISPLAY_MODE";
|
||||||
public static final String ZK_DASHBOARD_PERFORMANCE_REFRESH_INTERVAL = "ZK_DASHBOARD_PERFORMANCE_REFRESH_INTERVAL";
|
public static final String ZK_DASHBOARD_PERFORMANCE_REFRESH_INTERVAL = "ZK_DASHBOARD_PERFORMANCE_REFRESH_INTERVAL";
|
||||||
|
/** @deprecated not use for the new billboard implementation */
|
||||||
|
@Deprecated(forRemoval = true, since = "11")
|
||||||
public static final String ZK_DASHBOARD_PERFORMANCE_TIMEOUT = "ZK_DASHBOARD_PERFORMANCE_TIMEOUT";
|
public static final String ZK_DASHBOARD_PERFORMANCE_TIMEOUT = "ZK_DASHBOARD_PERFORMANCE_TIMEOUT";
|
||||||
public static final String ZK_DASHBOARD_REFRESH_INTERVAL = "ZK_DASHBOARD_REFRESH_INTERVAL";
|
public static final String ZK_DASHBOARD_REFRESH_INTERVAL = "ZK_DASHBOARD_REFRESH_INTERVAL";
|
||||||
public static final String ZK_DECIMALBOX_PROCESS_DOTKEYPAD = "ZK_DECIMALBOX_PROCESS_DOTKEYPAD";
|
public static final String ZK_DECIMALBOX_PROCESS_DOTKEYPAD = "ZK_DECIMALBOX_PROCESS_DOTKEYPAD";
|
||||||
|
|
|
@ -1,5 +1,36 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* 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 *
|
||||||
|
* - carlos *
|
||||||
|
* - elaine *
|
||||||
|
* - hieplq *
|
||||||
|
**********************************************************************/
|
||||||
package org.adempiere.webui.apps.graph;
|
package org.adempiere.webui.apps.graph;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import org.adempiere.webui.apps.graph.WPerformanceIndicator.Options;
|
import org.adempiere.webui.apps.graph.WPerformanceIndicator.Options;
|
||||||
import org.adempiere.webui.component.Grid;
|
import org.adempiere.webui.component.Grid;
|
||||||
import org.adempiere.webui.component.Panel;
|
import org.adempiere.webui.component.Panel;
|
||||||
|
@ -16,15 +47,14 @@ import org.zkoss.zul.Label;
|
||||||
|
|
||||||
public class WPAPanel extends Panel implements EventListener<Event>
|
public class WPAPanel extends Panel implements EventListener<Event>
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* generated serial id
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = -6367672112341229048L;
|
private static final long serialVersionUID = -6367672112341229048L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Panel if User has Performance Goals
|
* Load Performance Goals for current login user
|
||||||
* @return panel pr null
|
* @return MGoal[]
|
||||||
*/
|
*/
|
||||||
public static MGoal[] loadGoal()
|
public static MGoal[] loadGoal()
|
||||||
{
|
{
|
||||||
|
@ -33,16 +63,23 @@ public class WPAPanel extends Panel implements EventListener<Event>
|
||||||
return goals;
|
return goals;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**
|
||||||
* Constructor
|
* Default Constructor
|
||||||
*/
|
*/
|
||||||
public WPAPanel ()
|
public WPAPanel ()
|
||||||
{
|
{
|
||||||
super ();
|
super ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set performance goals and render charts
|
||||||
|
* @param goals
|
||||||
|
* @param options color map options
|
||||||
|
*/
|
||||||
public void setGoals (MGoal[] goals, Options options){
|
public void setGoals (MGoal[] goals, Options options){
|
||||||
m_goals = goals;
|
m_goals = goals;
|
||||||
|
if (getChildren().size() > 0)
|
||||||
|
getChildren().clear();
|
||||||
init(options);
|
init(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +90,7 @@ public class WPAPanel extends Panel implements EventListener<Event>
|
||||||
private static final CLogger log = CLogger.getCLogger (WPAPanel.class);
|
private static final CLogger log = CLogger.getCLogger (WPAPanel.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static/Dynamic Init
|
* Layout panel and render charts
|
||||||
* @param options
|
* @param options
|
||||||
*/
|
*/
|
||||||
private void init(Options options)
|
private void init(Options options)
|
||||||
|
@ -67,6 +104,7 @@ public class WPAPanel extends Panel implements EventListener<Event>
|
||||||
grid.appendChild(rows);
|
grid.appendChild(rows);
|
||||||
|
|
||||||
Row row = null;
|
Row row = null;
|
||||||
|
List<WPerformanceIndicator> list = new ArrayList<>();
|
||||||
for (int i = 0; i < m_goals.length; i++)
|
for (int i = 0; i < m_goals.length; i++)
|
||||||
{
|
{
|
||||||
if (row == null || i % 2 == 0)
|
if (row == null || i % 2 == 0)
|
||||||
|
@ -79,6 +117,14 @@ public class WPAPanel extends Panel implements EventListener<Event>
|
||||||
row.appendChild(div);
|
row.appendChild(div);
|
||||||
div.setSclass("performance-indicator-box");
|
div.setSclass("performance-indicator-box");
|
||||||
WPerformanceIndicator pi = new WPerformanceIndicator(m_goals[i], options);
|
WPerformanceIndicator pi = new WPerformanceIndicator(m_goals[i], options);
|
||||||
|
list.add(pi);
|
||||||
|
pi.addEventListener(WPerformanceIndicator.ON_AFTER_RENDER_CHART_EVENT, e -> {
|
||||||
|
boolean removed = list.remove(e.getTarget());
|
||||||
|
if (removed && list.isEmpty()) {
|
||||||
|
//notify all chart have been rendered
|
||||||
|
Events.sendEvent(WPAPanel.this, new Event(WPerformanceIndicator.ON_AFTER_RENDER_CHART_EVENT));
|
||||||
|
}
|
||||||
|
});
|
||||||
div.appendChild(pi);
|
div.appendChild(pi);
|
||||||
pi.addEventListener(Events.ON_CLICK, this);
|
pi.addEventListener(Events.ON_CLICK, this);
|
||||||
Div titleDiv = new Div();
|
Div titleDiv = new Div();
|
||||||
|
@ -90,14 +136,16 @@ public class WPAPanel extends Panel implements EventListener<Event>
|
||||||
} // init
|
} // init
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action Listener for Drill Down
|
* Event Listener for Drill Down
|
||||||
* @param e event
|
* @param e event
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void onEvent(Event e) throws Exception
|
public void onEvent(Event e) throws Exception
|
||||||
{
|
{
|
||||||
if (e.getTarget() instanceof WPerformanceIndicator)
|
if (e.getTarget() instanceof WPerformanceIndicator)
|
||||||
{
|
{
|
||||||
WPerformanceIndicator pi = (WPerformanceIndicator) e.getTarget();
|
WPerformanceIndicator pi = (WPerformanceIndicator) e.getTarget();
|
||||||
|
if (log.isLoggable(Level.INFO))
|
||||||
log.info(pi.toString());
|
log.info(pi.toString());
|
||||||
MGoal goal = pi.getGoal();
|
MGoal goal = pi.getGoal();
|
||||||
if (goal.getMeasure() != null)
|
if (goal.getMeasure() != null)
|
||||||
|
|
|
@ -42,23 +42,29 @@ import org.zkoss.zul.Menupopup;
|
||||||
*/
|
*/
|
||||||
public class WPerformanceIndicator extends Panel implements EventListener<Event>
|
public class WPerformanceIndicator extends Panel implements EventListener<Event>
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* generated serial id
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 4102528939759426552L;
|
||||||
|
|
||||||
|
/** Event after chart have been rendered */
|
||||||
|
public static final String ON_AFTER_RENDER_CHART_EVENT = "onAfterRenderChart";
|
||||||
public static final String TICK_COLOR = "tickColor";
|
public static final String TICK_COLOR = "tickColor";
|
||||||
public static final String NEEDLE_COLOR = "needleColor";
|
public static final String NEEDLE_COLOR = "needleColor";
|
||||||
public static final String DIAL_BACKGROUND = "dialBackground";
|
public static final String DIAL_BACKGROUND = "dialBackground";
|
||||||
public static final String CHART_BACKGROUND = "chartBackground";
|
public static final String CHART_BACKGROUND = "chartBackground";
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static final long serialVersionUID = 3580494126343850939L;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param goal
|
||||||
|
*/
|
||||||
public WPerformanceIndicator(MGoal goal)
|
public WPerformanceIndicator(MGoal goal)
|
||||||
{
|
{
|
||||||
this(goal, null);
|
this(goal, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
|
||||||
* @param goal goal model
|
* @param goal goal model
|
||||||
|
* @param options
|
||||||
*/
|
*/
|
||||||
public WPerformanceIndicator(MGoal goal, Options options)
|
public WPerformanceIndicator(MGoal goal, Options options)
|
||||||
{
|
{
|
||||||
|
@ -99,7 +105,7 @@ public class WPerformanceIndicator extends Panel implements EventListener<Event>
|
||||||
/** Integer Number Format */
|
/** Integer Number Format */
|
||||||
private static DecimalFormat s_format = DisplayType.getNumberFormat(DisplayType.Integer);
|
private static DecimalFormat s_format = DisplayType.getNumberFormat(DisplayType.Integer);
|
||||||
|
|
||||||
Menupopup popupMenu = new Menupopup();
|
protected Menupopup popupMenu = new Menupopup();
|
||||||
private Menuitem mRefresh = new Menuitem(Msg.getMsg(Env.getCtx(), "Refresh"), ThemeManager.getThemeResource("images/Refresh16.png"));
|
private Menuitem mRefresh = new Menuitem(Msg.getMsg(Env.getCtx(), "Refresh"), ThemeManager.getThemeResource("images/Refresh16.png"));
|
||||||
|
|
||||||
private Color chartBackground = new Color(0.0f, 0.0f, 0.0f, 0.0f);
|
private Color chartBackground = new Color(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
@ -107,7 +113,7 @@ public class WPerformanceIndicator extends Panel implements EventListener<Event>
|
||||||
private Color needleColor = Color.darkGray;
|
private Color needleColor = Color.darkGray;
|
||||||
private Color tickColor = Color.darkGray;
|
private Color tickColor = Color.darkGray;
|
||||||
|
|
||||||
ChartPanel chartPanel;
|
protected ChartPanel chartPanel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Goal
|
* Get Goal
|
||||||
|
@ -119,7 +125,7 @@ public class WPerformanceIndicator extends Panel implements EventListener<Event>
|
||||||
} // getGoal
|
} // getGoal
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init Graph Display
|
* Initialization
|
||||||
* Kinamo (pelgrim)
|
* Kinamo (pelgrim)
|
||||||
*/
|
*/
|
||||||
private void init()
|
private void init()
|
||||||
|
@ -143,9 +149,11 @@ public class WPerformanceIndicator extends Panel implements EventListener<Event>
|
||||||
.append(s_format.format(m_goal.getMeasureTarget()));
|
.append(s_format.format(m_goal.getMeasureTarget()));
|
||||||
setTooltiptext(text.toString());
|
setTooltiptext(text.toString());
|
||||||
|
|
||||||
|
//chart render in after size event
|
||||||
addEventListener(Events.ON_AFTER_SIZE, this);
|
addEventListener(Events.ON_AFTER_SIZE, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onEvent(Event event) throws Exception
|
public void onEvent(Event event) throws Exception
|
||||||
{
|
{
|
||||||
if (Events.ON_AFTER_SIZE.equals(event.getName()))
|
if (Events.ON_AFTER_SIZE.equals(event.getName()))
|
||||||
|
@ -159,6 +167,10 @@ public class WPerformanceIndicator extends Panel implements EventListener<Event>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle after size event. Call {@link #renderChart(int, int)}
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
private void onAfterSize(AfterSizeEvent event) {
|
private void onAfterSize(AfterSizeEvent event) {
|
||||||
int width = event.getWidth();
|
int width = event.getWidth();
|
||||||
if (width == 0)
|
if (width == 0)
|
||||||
|
@ -184,13 +196,22 @@ public class WPerformanceIndicator extends Panel implements EventListener<Event>
|
||||||
}
|
}
|
||||||
this.getChildren().clear();
|
this.getChildren().clear();
|
||||||
renderChart(width, height);
|
renderChart(width, height);
|
||||||
|
Events.sendEvent(this, new Event(ON_AFTER_RENDER_CHART_EVENT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return title
|
||||||
|
*/
|
||||||
public String getTitle()
|
public String getTitle()
|
||||||
{
|
{
|
||||||
return m_text;
|
return m_text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* render chart
|
||||||
|
* @param chartWidth
|
||||||
|
* @param chartHeight
|
||||||
|
*/
|
||||||
private void renderChart(int chartWidth, int chartHeight)
|
private void renderChart(int chartWidth, int chartHeight)
|
||||||
{
|
{
|
||||||
IndicatorModel model = new IndicatorModel();
|
IndicatorModel model = new IndicatorModel();
|
||||||
|
@ -207,6 +228,9 @@ public class WPerformanceIndicator extends Panel implements EventListener<Event>
|
||||||
this.getFirstChild().addEventListener(Events.ON_CLICK, this);
|
this.getFirstChild().addEventListener(Events.ON_CLICK, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for color map options
|
||||||
|
*/
|
||||||
public static class Options {
|
public static class Options {
|
||||||
public Map<String, Color> colorMap;
|
public Map<String, Color> colorMap;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,16 +14,13 @@
|
||||||
package org.adempiere.webui.dashboard;
|
package org.adempiere.webui.dashboard;
|
||||||
|
|
||||||
import org.adempiere.webui.apps.graph.WPAPanel;
|
import org.adempiere.webui.apps.graph.WPAPanel;
|
||||||
|
import org.adempiere.webui.apps.graph.WPerformanceIndicator;
|
||||||
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.model.MGoal;
|
import org.compiere.model.MGoal;
|
||||||
import org.compiere.model.MSysConfig;
|
|
||||||
import org.compiere.util.Env;
|
|
||||||
import org.zkoss.zk.au.out.AuScript;
|
import org.zkoss.zk.au.out.AuScript;
|
||||||
import org.zkoss.zk.ui.Component;
|
import org.zkoss.zk.ui.Component;
|
||||||
import org.zkoss.zk.ui.Executions;
|
import org.zkoss.zk.ui.Executions;
|
||||||
import org.zkoss.zk.ui.Page;
|
|
||||||
import org.zkoss.zk.ui.event.Events;
|
|
||||||
import org.zkoss.zk.ui.util.Clients;
|
import org.zkoss.zk.ui.util.Clients;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,65 +29,51 @@ import org.zkoss.zk.ui.util.Clients;
|
||||||
* @date November 20, 2008
|
* @date November 20, 2008
|
||||||
*/
|
*/
|
||||||
public class DPPerformance extends DashboardPanel {
|
public class DPPerformance extends DashboardPanel {
|
||||||
|
|
||||||
private static final String ON_POST_RENDER_ATTR = "onPostRender.Event.Posted";
|
|
||||||
/**
|
/**
|
||||||
*
|
* generated serial id
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = -8878665031716441912L;
|
private static final long serialVersionUID = -8878665031716441912L;
|
||||||
|
|
||||||
|
/** performance chart panel */
|
||||||
private WPAPanel paPanel;
|
private WPAPanel paPanel;
|
||||||
private MGoal[] performanceData;
|
private MGoal[] performanceData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor
|
||||||
|
*/
|
||||||
public DPPerformance()
|
public DPPerformance()
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
setSclass("performance-widget");
|
setSclass("performance-widget");
|
||||||
// have to add at least a child component, other it will be remove from DashboardController
|
|
||||||
// and can't update when finish load data
|
|
||||||
paPanel = new WPAPanel();
|
paPanel = new WPAPanel();
|
||||||
appendChild(paPanel);
|
appendChild(paPanel);
|
||||||
|
paPanel.addEventListener(WPerformanceIndicator.ON_AFTER_RENDER_CHART_EVENT, e -> onPostRender());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void refresh(ServerPushTemplate template) {
|
public void refresh(ServerPushTemplate template) {
|
||||||
performanceData = WPAPanel.loadGoal();
|
performanceData = WPAPanel.loadGoal();
|
||||||
|
//usually, this should be call in non UI/Event listener thread (i.e Executions.getCurrent() should be null)
|
||||||
if (Executions.getCurrent() != null) {
|
if (Executions.getCurrent() != null) {
|
||||||
updateUI();
|
updateUI();
|
||||||
if (this.getAttribute(ON_POST_RENDER_ATTR) == null && paPanel.getChildren().size() > 0) {
|
|
||||||
setAttribute(ON_POST_RENDER_ATTR, Boolean.TRUE);
|
|
||||||
Events.echoEvent("onPostRender", this, null);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
template.executeAsync(this);
|
template.executeAsync(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void onPageAttached(Page newpage, Page oldpage) {
|
* Adjust {@link #paPanel} height to match chart/content height
|
||||||
super.onPageAttached(newpage, oldpage);
|
*/
|
||||||
if (newpage != null) {
|
|
||||||
if (Executions.getCurrent() != null) {
|
|
||||||
if (this.getAttribute(ON_POST_RENDER_ATTR) == null && paPanel.getChildren().size() > 0) {
|
|
||||||
setAttribute(ON_POST_RENDER_ATTR, Boolean.TRUE);
|
|
||||||
Events.echoEvent("onPostRender", this, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//adjust window height to match grid height
|
|
||||||
public void onPostRender()
|
public void onPostRender()
|
||||||
{
|
{
|
||||||
removeAttribute(ON_POST_RENDER_ATTR);
|
|
||||||
if (this.getFirstChild() != null)
|
if (this.getFirstChild() != null)
|
||||||
{
|
{
|
||||||
int timeout = MSysConfig.getIntValue(MSysConfig.ZK_DASHBOARD_PERFORMANCE_TIMEOUT, 500, Env.getAD_Client_ID(Env.getCtx()));
|
//first child of paPanel, the Grid layout
|
||||||
Component grid = this.getFirstChild().getFirstChild();
|
Component grid = this.getFirstChild().getFirstChild();
|
||||||
String script = "setTimeout(function() { let grid = jq('#" + grid.getUuid() + "');";
|
String script = "setTimeout(function() { let grid = jq('#" + grid.getUuid() + "');";
|
||||||
script = script + "grid.parent().height(grid.css('height'));}, " + timeout + ");";
|
script = script + "grid.parent().height(grid.css('height'));}, 10);";
|
||||||
if (Executions.getCurrent() != null)
|
if (Executions.getCurrent() != null)
|
||||||
Clients.response(new AuScript(script));
|
Clients.response(new AuScript(script));
|
||||||
this.getFirstChild().invalidate();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue