IDEMPIERE-3528 Add to Favorite for Menu Search Panel

This commit is contained in:
Heng Sin Low 2017-10-24 00:33:20 +08:00
parent ffdc57cbe8
commit c036ed2e57
8 changed files with 394 additions and 108 deletions

View File

@ -0,0 +1,23 @@
SET SQLBLANKLINES ON
SET DEFINE OFF
-- IDEMPIERE-3528 Add to Favorite for Menu Search Panel
-- Oct 23, 2017 11:59:39 PM GMT+08:00
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Add To Favourite',0,0,'Y',TO_DATE('2017-10-23 23:59:38','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2017-10-23 23:59:38','YYYY-MM-DD HH24:MI:SS'),100,200435,'AddToFavourite','D','ddbf357f-3f1c-49dd-9ce7-3d8f0cc3b30a')
;
-- Oct 24, 2017 12:00:05 AM GMT+08:00
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Remove From Favourite',0,0,'Y',TO_DATE('2017-10-24 00:00:05','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2017-10-24 00:00:05','YYYY-MM-DD HH24:MI:SS'),100,200436,'RemoveFromFavourite','D','36985206-17fb-4bf2-a339-3aac5e2601f3')
;
-- Oct 24, 2017 12:00:51 AM GMT+08:00
UPDATE AD_Message SET MsgText='Add To Favourites', Value='AddToFavourites',Updated=TO_DATE('2017-10-24 00:00:51','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200435
;
-- Oct 24, 2017 12:00:58 AM GMT+08:00
UPDATE AD_Message SET MsgText='Remove From Favourites', Value='RemoveFromFavourites',Updated=TO_DATE('2017-10-24 00:00:58','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200436
;
SELECT register_migration_script('201710232100_IDEMPIERE-3528.sql') FROM dual
;

View File

@ -0,0 +1,20 @@
-- IDEMPIERE-3528 Add to Favorite for Menu Search Panel
-- Oct 23, 2017 11:59:39 PM GMT+08:00
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Add To Favourite',0,0,'Y',TO_TIMESTAMP('2017-10-23 23:59:38','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2017-10-23 23:59:38','YYYY-MM-DD HH24:MI:SS'),100,200435,'AddToFavourite','D','ddbf357f-3f1c-49dd-9ce7-3d8f0cc3b30a')
;
-- Oct 24, 2017 12:00:05 AM GMT+08:00
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Remove From Favourite',0,0,'Y',TO_TIMESTAMP('2017-10-24 00:00:05','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2017-10-24 00:00:05','YYYY-MM-DD HH24:MI:SS'),100,200436,'RemoveFromFavourite','D','36985206-17fb-4bf2-a339-3aac5e2601f3')
;
-- Oct 24, 2017 12:00:51 AM GMT+08:00
UPDATE AD_Message SET MsgText='Add To Favourites', Value='AddToFavourites',Updated=TO_TIMESTAMP('2017-10-24 00:00:51','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200435
;
-- Oct 24, 2017 12:00:58 AM GMT+08:00
UPDATE AD_Message SET MsgText='Remove From Favourites', Value='RemoveFromFavourites',Updated=TO_TIMESTAMP('2017-10-24 00:00:58','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200436
;
SELECT register_migration_script('201710232100_IDEMPIERE-3528.sql') FROM dual
;

View File

@ -35,6 +35,7 @@ import org.adempiere.webui.component.DrillCommand;
import org.adempiere.webui.component.TokenCommand; import org.adempiere.webui.component.TokenCommand;
import org.adempiere.webui.component.ZoomCommand; import org.adempiere.webui.component.ZoomCommand;
import org.adempiere.webui.desktop.DefaultDesktop; import org.adempiere.webui.desktop.DefaultDesktop;
import org.adempiere.webui.desktop.FavouriteController;
import org.adempiere.webui.desktop.IDesktop; import org.adempiere.webui.desktop.IDesktop;
import org.adempiere.webui.session.SessionContextListener; import org.adempiere.webui.session.SessionContextListener;
import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.session.SessionManager;
@ -281,6 +282,9 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
Env.setContext(ctx, "#LocalHttpAddr", localHttpAddr.toString()); Env.setContext(ctx, "#LocalHttpAddr", localHttpAddr.toString());
Clients.response(new AuScript("zAu.cmd0.clearBusy()")); Clients.response(new AuScript("zAu.cmd0.clearBusy()"));
//init favorite
FavouriteController.getInstance(currSess);
processParameters(); processParameters();
} }

View File

@ -20,6 +20,8 @@ import java.util.List;
import org.adempiere.webui.component.ListHead; import org.adempiere.webui.component.ListHead;
import org.adempiere.webui.component.ListItem; import org.adempiere.webui.component.ListItem;
import org.adempiere.webui.component.Listbox; import org.adempiere.webui.component.Listbox;
import org.adempiere.webui.component.ToolBarButton;
import org.adempiere.webui.desktop.FavouriteController;
import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.theme.ThemeManager;
import org.adempiere.webui.util.TreeItemAction; import org.adempiere.webui.util.TreeItemAction;
import org.adempiere.webui.util.TreeNodeAction; import org.adempiere.webui.util.TreeNodeAction;
@ -47,7 +49,6 @@ import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer; import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.ListitemRendererExt; import org.zkoss.zul.ListitemRendererExt;
import org.zkoss.zul.Textbox; import org.zkoss.zul.Textbox;
import org.zkoss.zul.Toolbarbutton;
import org.zkoss.zul.Tree; import org.zkoss.zul.Tree;
import org.zkoss.zul.Treechildren; import org.zkoss.zul.Treechildren;
import org.zkoss.zul.Treeitem; import org.zkoss.zul.Treeitem;
@ -61,14 +62,21 @@ import org.zkoss.zul.impl.LabelImageElement;
*/ */
public class MenuSearchController implements EventListener<Event>{ public class MenuSearchController implements EventListener<Event>{
public static final String M_TREE_NODE_ATTR = "MTreeNode";
private static final String Z_ICON_STAR_O = "z-icon-star-o";
private static final String Z_ICON_STAR = "z-icon-star";
private static final String ON_SEARCH_ECHO = "onSearchEcho"; private static final String ON_SEARCH_ECHO = "onSearchEcho";
private static final String ON_LOAD_MORE = "onLoadMore"; private static final String ON_LOAD_MORE = "onLoadMore";
private static final String ONSELECT_TIMESTAMP = "onselect.timestamp"; private static final String ONSELECT_TIMESTAMP = "onselect.timestamp";
private static final String STAR_BUTTON_NAME = "Star";
private static final String NEW_BUTTON_NAME = "New";
private Tree tree; private Tree tree;
private Listbox listbox; private Listbox listbox;
private ListModelList<MenuItem> model; private ListModelList<MenuItem> model;
private Vlayout layout; private Vlayout layout;
private ListModelList<MenuItem> fullModel; private ListModelList<MenuItem> fullModel;
private boolean inStarEvent;
private static final String ON_POST_SELECT_TREEITEM_EVENT = "onPostSelectTreeitem"; private static final String ON_POST_SELECT_TREEITEM_EVENT = "onPostSelectTreeitem";
@ -196,12 +204,21 @@ public class MenuSearchController implements EventListener<Event>{
Listheader listheader = new Listheader(); Listheader listheader = new Listheader();
listhead.appendChild(listheader); listhead.appendChild(listheader);
listheader = new Listheader(); listheader = new Listheader();
ZKUpdateUtil.setWidth(listheader, "32px"); listheader.setAlign("center");
ZKUpdateUtil.setWidth(listheader, "28px");
listhead.appendChild(listheader);
listheader = new Listheader();
listheader.setAlign("center");
ZKUpdateUtil.setWidth(listheader, "28px");
listhead.appendChild(listheader); listhead.appendChild(listheader);
layout.addEventListener(ON_SEARCH_ECHO, this); layout.addEventListener(ON_SEARCH_ECHO, this);
layout.addEventListener(ON_LOAD_MORE, this); layout.addEventListener(ON_LOAD_MORE, this);
updateListboxModel(model); updateListboxModel(model);
FavouriteController controller = FavouriteController.getInstance(Executions.getCurrent().getSession());
controller.addDeletedCallback(t -> onDeletedCallback(t));
controller.addInsertedCallback(t -> onInsertedCallback(t));
} }
@Override @Override
@ -221,7 +238,9 @@ public class MenuSearchController implements EventListener<Event>{
} else if (System.currentTimeMillis() - onSelect.longValue() > 1000) { } else if (System.currentTimeMillis() - onSelect.longValue() > 1000) {
onSelect(item, Boolean.FALSE); onSelect(item, Boolean.FALSE);
} }
} else if (event.getTarget() instanceof Toolbarbutton) { } else if (event.getTarget() instanceof ToolBarButton) {
ToolBarButton btn = (ToolBarButton) event.getTarget();
if (NEW_BUTTON_NAME.equals(btn.getName())) {
ListItem item = null; ListItem item = null;
Component parent = event.getTarget(); Component parent = event.getTarget();
while (parent != null) { while (parent != null) {
@ -234,6 +253,20 @@ public class MenuSearchController implements EventListener<Event>{
if (item != null) { if (item != null) {
onSelect(item, Boolean.TRUE); onSelect(item, Boolean.TRUE);
} }
} else if (STAR_BUTTON_NAME.equals(btn.getName())) {
inStarEvent = true;
FavouriteController controller = FavouriteController.getInstance(Executions.getCurrent().getSession());
if (Z_ICON_STAR_O.equals(btn.getIconSclass())) {
btn.setIconSclass(Z_ICON_STAR);
btn.setTooltiptext(Msg.getMsg(Env.getCtx(), "RemoveFromFavourites"));
controller.addNode((MTreeNode) btn.getAttribute(M_TREE_NODE_ATTR));
} else if (Z_ICON_STAR.equals(btn.getIconSclass())) {
btn.setIconSclass(Z_ICON_STAR_O);
btn.setTooltiptext(Msg.getMsg(Env.getCtx(), "AddToFavourites"));
controller.removeNode(((MTreeNode) btn.getAttribute(M_TREE_NODE_ATTR)).getNode_ID());
}
inStarEvent = false;
}
} }
} else if (event.getName().equals(ON_SEARCH_ECHO)) { } else if (event.getName().equals(ON_SEARCH_ECHO)) {
onSearchEcho((String) event.getData()); onSearchEcho((String) event.getData());
@ -242,6 +275,20 @@ public class MenuSearchController implements EventListener<Event>{
} }
} }
private void onInsertedCallback(MTreeNode node) {
if (inStarEvent) return;
ListModel<?> t = listbox.getModel();
listbox.setModel((ListModel<?>)null);
listbox.setModel(t);
}
private void onDeletedCallback(Integer nodeId) {
if (inStarEvent) return;
ListModel<?> t = listbox.getModel();
listbox.setModel((ListModel<?>)null);
listbox.setModel(t);
}
private void onSelect(ListItem selected, Boolean newRecord) { private void onSelect(ListItem selected, Boolean newRecord) {
MenuItem item = selected.getValue(); MenuItem item = selected.getValue();
if (item == null) return; if (item == null) return;
@ -438,6 +485,9 @@ public class MenuSearchController implements EventListener<Event>{
} }
private class MenuItemRenderer implements ListitemRenderer<MenuItem>, ListitemRendererExt { private class MenuItemRenderer implements ListitemRenderer<MenuItem>, ListitemRendererExt {
private static final String REMOVE_FROM_FAVOURITES_MSG = "RemoveFromFavourites";
private static final String ADD_TO_FAVOURITES_MSG = "AddToFavourites";
@Override @Override
public Listitem newListitem(org.zkoss.zul.Listbox listbox) { public Listitem newListitem(org.zkoss.zul.Listbox listbox) {
return new ListItem(); return new ListItem();
@ -466,13 +516,41 @@ public class MenuSearchController implements EventListener<Event>{
item.appendChild(cell); item.appendChild(cell);
boolean isWindow = data.getType() != null && data.getType().equals("window"); boolean isWindow = data.getType() != null && data.getType().equals("window");
if (isWindow) { if (isWindow) {
Toolbarbutton newBtn = new Toolbarbutton(null, ThemeManager.getThemeResource("images/New16.png")); ToolBarButton newBtn = new ToolBarButton();
newBtn.setImage(ThemeManager.getThemeResource("images/New16.png"));
newBtn.addEventListener(Events.ON_CLICK, MenuSearchController.this); newBtn.addEventListener(Events.ON_CLICK, MenuSearchController.this);
newBtn.setSclass("fav-new-btn"); newBtn.setSclass("fav-new-btn");
newBtn.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "New"))); newBtn.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), NEW_BUTTON_NAME)));
newBtn.setName(NEW_BUTTON_NAME);
cell.appendChild(newBtn); cell.appendChild(newBtn);
} }
}
cell = new Listcell();
item.appendChild(cell);
MTreeNode node = null;
if (data.getData() instanceof MTreeNode) {
node = (MTreeNode) data.getData();
} else if (data.getData() instanceof Treeitem) {
Treeitem value = (Treeitem) data.getData();
if (value != null) {
node = (MTreeNode) value.getAttribute(M_TREE_NODE_ATTR);
}
}
if (node != null) {
FavouriteController controller = FavouriteController.getInstance(Executions.getCurrent().getSession());
ToolBarButton starBtn = new ToolBarButton();
starBtn.setAttribute(M_TREE_NODE_ATTR, node);
starBtn.setName(STAR_BUTTON_NAME);
if (controller.hasNode(node.getNode_ID())) {
starBtn.setIconSclass(Z_ICON_STAR);
starBtn.setTooltiptext(Msg.getMsg(Env.getCtx(), REMOVE_FROM_FAVOURITES_MSG));
} else {
starBtn.setIconSclass(Z_ICON_STAR_O);
starBtn.setTooltiptext(Msg.getMsg(Env.getCtx(), ADD_TO_FAVOURITES_MSG));
}
cell.appendChild(starBtn);
starBtn.addEventListener(Events.ON_CLICK, MenuSearchController.this);
}
}
} }
} }

View File

@ -13,13 +13,13 @@
*****************************************************************************/ *****************************************************************************/
package org.adempiere.webui.dashboard; package org.adempiere.webui.dashboard;
import static org.compiere.model.SystemIDs.TREE_MENUPRIMARY; import java.util.ArrayList;
import java.util.List;
import java.util.Enumeration;
import org.adempiere.util.Callback; import org.adempiere.util.Callback;
import org.adempiere.webui.adwindow.ADTabpanel; import org.adempiere.webui.adwindow.ADTabpanel;
import org.adempiere.webui.adwindow.ADWindow; import org.adempiere.webui.adwindow.ADWindow;
import org.adempiere.webui.desktop.FavouriteController;
import org.adempiere.webui.exception.ApplicationException; import org.adempiere.webui.exception.ApplicationException;
import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.theme.ITheme; import org.adempiere.webui.theme.ITheme;
@ -27,13 +27,12 @@ import org.adempiere.webui.theme.ThemeManager;
import org.adempiere.webui.window.FDialog; import org.adempiere.webui.window.FDialog;
import org.compiere.model.MMenu; import org.compiere.model.MMenu;
import org.compiere.model.MQuery; import org.compiere.model.MQuery;
import org.compiere.model.MTree;
import org.compiere.model.MTreeNode; import org.compiere.model.MTreeNode;
import org.compiere.util.DB;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.compiere.util.Msg; import org.compiere.util.Msg;
import org.compiere.util.Util; import org.compiere.util.Util;
import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.DropEvent; import org.zkoss.zk.ui.event.DropEvent;
import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.EventListener;
@ -74,7 +73,9 @@ public class DPFavourites extends DashboardPanel implements EventListener<Event>
private Label lblMsg; private Label lblMsg;
private int m_AD_Tree_ID; private List<A> links = new ArrayList<>();
private boolean inCallingController;
public DPFavourites() public DPFavourites()
{ {
@ -108,35 +109,44 @@ public class DPFavourites extends DashboardPanel implements EventListener<Event>
private void createFavouritesPanel() private void createFavouritesPanel()
{ {
int AD_Role_ID = Env.getAD_Role_ID(Env.getCtx()); FavouriteController controller = FavouriteController.getInstance(Executions.getCurrent().getSession());
int AD_Tree_ID = DB.getSQLValue(null, List<MTreeNode> favorites = controller.getFavourites();
"SELECT COALESCE(r.AD_Tree_Menu_ID, ci.AD_Tree_Menu_ID)" for (MTreeNode nd : favorites)
+ "FROM AD_ClientInfo ci"
+ " INNER JOIN AD_Role r ON (ci.AD_Client_ID=r.AD_Client_ID) "
+ "WHERE AD_Role_ID=?", AD_Role_ID);
if (AD_Tree_ID <= 0)
AD_Tree_ID = TREE_MENUPRIMARY; // Menu
m_AD_Tree_ID = AD_Tree_ID;
MTree vTree = new MTree(Env.getCtx(), AD_Tree_ID, false, true, null);
MTreeNode m_root = vTree.getRoot();
Enumeration<?> enTop = m_root.children();
while(enTop.hasMoreElements())
{ {
MTreeNode ndTop = (MTreeNode)enTop.nextElement(); addNode(nd);
Enumeration<?> en = ndTop.preorderEnumeration();
while (en.hasMoreElements())
{
MTreeNode nd = (MTreeNode)en.nextElement();
if (nd.isOnBar()) {
addNode(nd.getNode_ID(), nd.toString().trim(), nd.getDescription(), getIconFile(nd), (nd.isWindow() && !nd.isForm()));
}
}
} }
lblMsg = new Label(Msg.getMsg(Env.getCtx(), "DropMenuItemHere")); lblMsg = new Label(Msg.getMsg(Env.getCtx(), "DropMenuItemHere"));
if(bxFav.getChildren().isEmpty()) bxFav.appendChild(lblMsg); if(bxFav.getChildren().isEmpty()) bxFav.appendChild(lblMsg);
controller.addInsertedCallback(t -> onInsertedCallback(t));
controller.addDeletedCallback(t -> onDeletedCallback(t));
}
private void addNode(MTreeNode nd) {
addNode(nd.getNode_ID(), nd.toString().trim(), nd.getDescription(), getIconFile(nd), (nd.isWindow() && !nd.isForm()));
}
private void onDeletedCallback(Integer nodeId) {
if (inCallingController) return;
for (A link : links) {
String id = (String) link.getAttribute(NODE_ID_ATTR);
if (id.equals(nodeId.toString())) {
removeLinkFromUI(link);
break;
}
}
}
private void onInsertedCallback(MTreeNode node) {
if (inCallingController) return;
for (A link : links) {
String id = (String) link.getAttribute(NODE_ID_ATTR);
if (id.equals(String.valueOf(node.getNode_ID()))) {
return;
}
}
addNode(node);
} }
protected void addNode(int nodeId, String label, String description, String imageSrc, boolean addNewBtn) { protected void addNode(int nodeId, String label, String description, String imageSrc, boolean addNewBtn) {
@ -168,52 +178,7 @@ public class DPFavourites extends DashboardPanel implements EventListener<Event>
newBtn.setSclass("fav-new-btn"); newBtn.setSclass("fav-new-btn");
newBtn.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "New"))); newBtn.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "New")));
} }
} links.add(btnFavItem);
/**
* Make Bar add/remove persistent
* @param add true if add - otherwise remove
* @param Node_ID Node ID
* @return true if updated
*/
private boolean barDBupdate(boolean add, int Node_ID)
{
int AD_Client_ID = Env.getAD_Client_ID(Env.getCtx());
int AD_Org_ID = Env.getContextAsInt(Env.getCtx(), "#AD_Org_ID");
int AD_User_ID = Env.getContextAsInt(Env.getCtx(), "#AD_User_ID");
StringBuilder sql = new StringBuilder();
if (add) {
// If record already exist, we will only make an update
if (DB.getSQLValueEx(null, "SELECT 1 FROM AD_TreeBar WHERE AD_Tree_ID = ? AND AD_User_ID = ? AND Node_ID = ?", m_AD_Tree_ID, AD_User_ID, Node_ID) == 1) {
sql.append("UPDATE AD_TreeBar SET IsFavourite = 'Y', Updated = Sysdate, UpdatedBy = ").append(AD_User_ID).append(" WHERE AD_Tree_ID = ").append(m_AD_Tree_ID)
.append(" AND AD_User_ID=").append(AD_User_ID)
.append(" AND Node_ID=").append(Node_ID);
}
else // we will create the record
sql.append("INSERT INTO AD_TreeBar "
+ "(AD_Tree_ID,AD_User_ID,Node_ID, "
+ "AD_Client_ID,AD_Org_ID, "
+ "IsActive,Created,CreatedBy,Updated,UpdatedBy)VALUES (")
.append(m_AD_Tree_ID).append(",").append(AD_User_ID).append(",").append(Node_ID).append(",")
.append(AD_Client_ID).append(",").append(AD_Org_ID).append(",")
.append("'Y',SysDate,").append(AD_User_ID).append(",SysDate,").append(AD_User_ID).append(")");
// if already exist, will result in ORA-00001: unique constraint (ADEMPIERE.AD_TREEBAR_KEY)
}
else {
// if the menu entry is opened at login, we will only remove it from favourites
if (DB.getSQLValueEx(null, "SELECT LoginOpenSeqNo FROM AD_TreeBar WHERE AD_Tree_ID = ? AND AD_User_ID = ? AND Node_ID = ?", m_AD_Tree_ID, AD_User_ID, Node_ID) > 0) {
sql.append("UPDATE AD_TreeBar SET IsFavourite = 'N', Updated = Sysdate, UpdatedBy = ").append(AD_User_ID).append(" WHERE AD_Tree_ID = ").append(m_AD_Tree_ID)
.append(" AND AD_User_ID=").append(AD_User_ID)
.append(" AND Node_ID=").append(Node_ID);
}
else // otherwise, we remove the record
sql.append("DELETE AD_TreeBar WHERE AD_Tree_ID=").append(m_AD_Tree_ID)
.append(" AND AD_User_ID=").append(AD_User_ID)
.append(" AND Node_ID=").append(Node_ID);
}
int no = DB.executeUpdate(sql.toString(), false, null);
return no == 1;
} }
public void onEvent(Event event) public void onEvent(Event event)
@ -318,18 +283,25 @@ public class DPFavourites extends DashboardPanel implements EventListener<Event>
if(value != null) if(value != null)
{ {
int Node_ID = Integer.valueOf(value.toString()); int Node_ID = Integer.valueOf(value.toString());
if(barDBupdate(false, Node_ID)) FavouriteController controller = FavouriteController.getInstance(Executions.getCurrent().getSession());
inCallingController = true;
if(controller.removeNode(Node_ID))
{ {
removeLinkFromUI(btn);
}
inCallingController = false;
}
}
private void removeLinkFromUI(A btn) {
if (btn.getParent() instanceof Hlayout) if (btn.getParent() instanceof Hlayout)
bxFav.removeChild(btn.getParent()); bxFav.removeChild(btn.getParent());
// bxFav.removeChild(btn);
if(bxFav.getChildren().isEmpty()) if(bxFav.getChildren().isEmpty())
bxFav.appendChild(lblMsg); bxFav.appendChild(lblMsg);
bxFav.invalidate(); bxFav.invalidate();
} links.remove(btn);
}
} }
/** /**
@ -341,7 +313,9 @@ public class DPFavourites extends DashboardPanel implements EventListener<Event>
if(value != null) if(value != null)
{ {
int Node_ID = Integer.valueOf(value.toString()); int Node_ID = Integer.valueOf(value.toString());
if(barDBupdate(true, Node_ID)) FavouriteController controller = FavouriteController.getInstance(Executions.getCurrent().getSession());
inCallingController = true;
if(controller.addNode(Node_ID))
{ {
String menuType = (String) treeitem.getAttribute("menu.type"); String menuType = (String) treeitem.getAttribute("menu.type");
boolean isWindow = menuType != null && menuType.equals("window"); boolean isWindow = menuType != null && menuType.equals("window");
@ -364,6 +338,7 @@ public class DPFavourites extends DashboardPanel implements EventListener<Event>
} else { } else {
FDialog.error(0, this, "BookmarkExist", null); FDialog.error(0, this, "BookmarkExist", null);
} }
inCallingController = false;
} }
} }

View File

@ -0,0 +1,187 @@
/**
*
*/
package org.adempiere.webui.desktop;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.adempiere.util.Callback;
import org.compiere.model.MTree;
import org.compiere.model.MTreeNode;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.zkoss.zk.ui.Session;
import static org.compiere.model.SystemIDs.TREE_MENUPRIMARY;
/**
* @author hengsin
*
*/
public class FavouriteController {
private static final String DESKTOP_FAVOURITE_CONTROLLER = "desktop.FavouriteController";
private Map<Integer, MTreeNode> nodeMap;
private int m_AD_Tree_ID;
private MTreeNode rootNode;
private List<Callback<Integer>> deletedCallbacks;
private List<Callback<MTreeNode>> insertedCallbacks;
private FavouriteController() {
init();
}
private void init() {
nodeMap = new LinkedHashMap<>();
deletedCallbacks = new ArrayList<>();
insertedCallbacks = new ArrayList<>();
int AD_Role_ID = Env.getAD_Role_ID(Env.getCtx());
int AD_Tree_ID = DB.getSQLValue(null,
"SELECT COALESCE(r.AD_Tree_Menu_ID, ci.AD_Tree_Menu_ID)"
+ "FROM AD_ClientInfo ci"
+ " INNER JOIN AD_Role r ON (ci.AD_Client_ID=r.AD_Client_ID) "
+ "WHERE AD_Role_ID=?", AD_Role_ID);
if (AD_Tree_ID <= 0)
AD_Tree_ID = TREE_MENUPRIMARY; // Menu
m_AD_Tree_ID = AD_Tree_ID;
MTree vTree = new MTree(Env.getCtx(), AD_Tree_ID, false, true, false, null);
rootNode = vTree.getRoot();
Enumeration<?> enTop = rootNode.children();
while(enTop.hasMoreElements())
{
MTreeNode ndTop = (MTreeNode)enTop.nextElement();
Enumeration<?> en = ndTop.preorderEnumeration();
while (en.hasMoreElements())
{
MTreeNode nd = (MTreeNode)en.nextElement();
if (nd.isOnBar()) {
nodeMap.put(nd.getNode_ID(), nd);
}
}
}
}
/**
* Get favourites controller instance for current session
* @param currSess
* @return FavouriteController session instance
*/
public static synchronized FavouriteController getInstance(Session currSess) {
FavouriteController controller = (FavouriteController) currSess.getAttribute(DESKTOP_FAVOURITE_CONTROLLER);
if (controller == null) {
controller = new FavouriteController();
currSess.setAttribute(DESKTOP_FAVOURITE_CONTROLLER, controller);
}
return controller;
}
private boolean barDBupdate(boolean add, int Node_ID)
{
int AD_Client_ID = Env.getAD_Client_ID(Env.getCtx());
int AD_Org_ID = Env.getContextAsInt(Env.getCtx(), "#AD_Org_ID");
int AD_User_ID = Env.getContextAsInt(Env.getCtx(), "#AD_User_ID");
StringBuilder sql = new StringBuilder();
if (add)
sql.append("INSERT INTO AD_TreeBar "
+ "(AD_Tree_ID,AD_User_ID,Node_ID, "
+ "AD_Client_ID,AD_Org_ID, "
+ "IsActive,Created,CreatedBy,Updated,UpdatedBy)VALUES (")
.append(m_AD_Tree_ID).append(",").append(AD_User_ID).append(",").append(Node_ID).append(",")
.append(AD_Client_ID).append(",").append(AD_Org_ID).append(",")
.append("'Y',SysDate,").append(AD_User_ID).append(",SysDate,").append(AD_User_ID).append(")");
// if already exist, will result in ORA-00001: unique constraint (ADEMPIERE.AD_TREEBAR_KEY)
else
sql.append("DELETE AD_TreeBar WHERE AD_Tree_ID=").append(m_AD_Tree_ID)
.append(" AND AD_User_ID=").append(AD_User_ID)
.append(" AND Node_ID=").append(Node_ID);
int no = DB.executeUpdate(sql.toString(), false, null);
return no == 1;
}
/**
* Add node (by node id) to favourties
* @param nodeId
* @return true if successfully added
*/
public boolean addNode(int nodeId) {
MTreeNode node = rootNode.findNode(nodeId);
if (node != null) {
return addNode(node);
}
return false;
}
/**
* add tree node to favourites
* @param node
* @return true if successfully added
*/
public boolean addNode(MTreeNode node) {
if(barDBupdate(true, node.getNode_ID())) {
nodeMap.put(node.getNode_ID(), node);
for (Callback<MTreeNode> callback : insertedCallbacks) {
callback.onCallback(node);
}
return true;
}
return false;
}
/**
* remove node (by node id) from favourites
* @param nodeId
* @return true if found and remove
*/
public boolean removeNode(int nodeId) {
if(barDBupdate(false, nodeId))
{
nodeMap.remove(nodeId);
for (Callback<Integer> callback : deletedCallbacks) {
callback.onCallback(nodeId);
}
return true;
}
return false;
}
/**
* @param nodeId
* @return true if node id is in the current favourites list
*/
public boolean hasNode(int nodeId) {
return nodeMap.keySet().contains(nodeId);
}
/**
* @return List of favourites node
*/
public List<MTreeNode> getFavourites() {
List<MTreeNode> list = new ArrayList<>();
for(int key : nodeMap.keySet()) {
list.add(nodeMap.get(key));
}
return list;
}
/**
* add callback for after add node to favourites
* @param callback
*/
public void addInsertedCallback(Callback<MTreeNode> callback) {
insertedCallbacks.add(callback);
}
/**
* add callback for after remove node from favourites
* @param callback
*/
public void addDeletedCallback(Callback<Integer> callback) {
deletedCallbacks.add(callback);
}
}

View File

@ -23,6 +23,7 @@ import java.util.Properties;
import org.adempiere.util.Callback; import org.adempiere.util.Callback;
import org.adempiere.webui.adwindow.ADTabpanel; import org.adempiere.webui.adwindow.ADTabpanel;
import org.adempiere.webui.adwindow.ADWindow; import org.adempiere.webui.adwindow.ADWindow;
import org.adempiere.webui.apps.MenuSearchController;
import org.adempiere.webui.exception.ApplicationException; import org.adempiere.webui.exception.ApplicationException;
import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.theme.ThemeManager;
@ -205,6 +206,7 @@ public abstract class AbstractMenuPanel extends Panel implements EventListener<E
link.setSclass("menu-href"); link.setSclass("menu-href");
treeitem.getTreerow().setDraggable("favourite"); // Elaine 2008/07/24 treeitem.getTreerow().setDraggable("favourite"); // Elaine 2008/07/24
treeitem.setAttribute(MenuSearchController.M_TREE_NODE_ATTR, mChildNode);
} }
} }
} }

View File

@ -1,7 +1,4 @@
.fav-new-btn { .fav-new-btn {
margin-left: 4px;
margin-bottom: 3px;
padding-left: 1px;
} }
.fav-new-btn img { .fav-new-btn img {