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.ZoomCommand;
import org.adempiere.webui.desktop.DefaultDesktop;
import org.adempiere.webui.desktop.FavouriteController;
import org.adempiere.webui.desktop.IDesktop;
import org.adempiere.webui.session.SessionContextListener;
import org.adempiere.webui.session.SessionManager;
@ -233,7 +234,7 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
mSession.saveEx();
}
currSess.setAttribute("Check_AD_User_ID", Env.getAD_User_ID(ctx));
currSess.setAttribute("Check_AD_User_ID", Env.getAD_User_ID(ctx));
//enable full interface, relook into this when doing preference
Env.setContext(ctx, "#ShowTrl", true);
@ -281,6 +282,9 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
Env.setContext(ctx, "#LocalHttpAddr", localHttpAddr.toString());
Clients.response(new AuScript("zAu.cmd0.clearBusy()"));
//init favorite
FavouriteController.getInstance(currSess);
processParameters();
}

View File

@ -20,6 +20,8 @@ import java.util.List;
import org.adempiere.webui.component.ListHead;
import org.adempiere.webui.component.ListItem;
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.util.TreeItemAction;
import org.adempiere.webui.util.TreeNodeAction;
@ -47,7 +49,6 @@ import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.ListitemRendererExt;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Toolbarbutton;
import org.zkoss.zul.Tree;
import org.zkoss.zul.Treechildren;
import org.zkoss.zul.Treeitem;
@ -61,14 +62,21 @@ import org.zkoss.zul.impl.LabelImageElement;
*/
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_LOAD_MORE = "onLoadMore";
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 Listbox listbox;
private ListModelList<MenuItem> model;
private Vlayout layout;
private ListModelList<MenuItem> fullModel;
private boolean inStarEvent;
private static final String ON_POST_SELECT_TREEITEM_EVENT = "onPostSelectTreeitem";
@ -196,12 +204,21 @@ public class MenuSearchController implements EventListener<Event>{
Listheader listheader = new Listheader();
listhead.appendChild(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);
layout.addEventListener(ON_SEARCH_ECHO, this);
layout.addEventListener(ON_LOAD_MORE, this);
updateListboxModel(model);
FavouriteController controller = FavouriteController.getInstance(Executions.getCurrent().getSession());
controller.addDeletedCallback(t -> onDeletedCallback(t));
controller.addInsertedCallback(t -> onInsertedCallback(t));
}
@Override
@ -221,18 +238,34 @@ public class MenuSearchController implements EventListener<Event>{
} else if (System.currentTimeMillis() - onSelect.longValue() > 1000) {
onSelect(item, Boolean.FALSE);
}
} else if (event.getTarget() instanceof Toolbarbutton) {
ListItem item = null;
Component parent = event.getTarget();
while (parent != null) {
if (parent instanceof ListItem) {
item = (ListItem) parent;
break;
} else if (event.getTarget() instanceof ToolBarButton) {
ToolBarButton btn = (ToolBarButton) event.getTarget();
if (NEW_BUTTON_NAME.equals(btn.getName())) {
ListItem item = null;
Component parent = event.getTarget();
while (parent != null) {
if (parent instanceof ListItem) {
item = (ListItem) parent;
break;
}
parent = parent.getParent();
}
parent = parent.getParent();
}
if (item != null) {
onSelect(item, Boolean.TRUE);
if (item != null) {
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)) {
@ -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) {
MenuItem item = selected.getValue();
if (item == null) return;
@ -438,6 +485,9 @@ public class MenuSearchController implements EventListener<Event>{
}
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
public Listitem newListitem(org.zkoss.zul.Listbox listbox) {
return new ListItem();
@ -466,13 +516,41 @@ public class MenuSearchController implements EventListener<Event>{
item.appendChild(cell);
boolean isWindow = data.getType() != null && data.getType().equals("window");
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.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 = 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;
import static org.compiere.model.SystemIDs.TREE_MENUPRIMARY;
import java.util.Enumeration;
import java.util.ArrayList;
import java.util.List;
import org.adempiere.util.Callback;
import org.adempiere.webui.adwindow.ADTabpanel;
import org.adempiere.webui.adwindow.ADWindow;
import org.adempiere.webui.desktop.FavouriteController;
import org.adempiere.webui.exception.ApplicationException;
import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.theme.ITheme;
@ -27,13 +27,12 @@ import org.adempiere.webui.theme.ThemeManager;
import org.adempiere.webui.window.FDialog;
import org.compiere.model.MMenu;
import org.compiere.model.MQuery;
import org.compiere.model.MTree;
import org.compiere.model.MTreeNode;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.compiere.util.Util;
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.Event;
import org.zkoss.zk.ui.event.EventListener;
@ -74,7 +73,9 @@ public class DPFavourites extends DashboardPanel implements EventListener<Event>
private Label lblMsg;
private int m_AD_Tree_ID;
private List<A> links = new ArrayList<>();
private boolean inCallingController;
public DPFavourites()
{
@ -108,35 +109,44 @@ public class DPFavourites extends DashboardPanel implements EventListener<Event>
private void createFavouritesPanel()
{
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, null);
MTreeNode m_root = vTree.getRoot();
Enumeration<?> enTop = m_root.children();
while(enTop.hasMoreElements())
FavouriteController controller = FavouriteController.getInstance(Executions.getCurrent().getSession());
List<MTreeNode> favorites = controller.getFavourites();
for (MTreeNode nd : favorites)
{
MTreeNode ndTop = (MTreeNode)enTop.nextElement();
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()));
}
}
addNode(nd);
}
lblMsg = new Label(Msg.getMsg(Env.getCtx(), "DropMenuItemHere"));
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) {
@ -168,52 +178,7 @@ public class DPFavourites extends DashboardPanel implements EventListener<Event>
newBtn.setSclass("fav-new-btn");
newBtn.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "New")));
}
}
/**
* 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;
links.add(btnFavItem);
}
public void onEvent(Event event)
@ -318,20 +283,27 @@ public class DPFavourites extends DashboardPanel implements EventListener<Event>
if(value != null)
{
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))
{
if (btn.getParent() instanceof Hlayout)
bxFav.removeChild(btn.getParent());
// bxFav.removeChild(btn);
if(bxFav.getChildren().isEmpty())
bxFav.appendChild(lblMsg);
bxFav.invalidate();
removeLinkFromUI(btn);
}
inCallingController = false;
}
}
private void removeLinkFromUI(A btn) {
if (btn.getParent() instanceof Hlayout)
bxFav.removeChild(btn.getParent());
if(bxFav.getChildren().isEmpty())
bxFav.appendChild(lblMsg);
bxFav.invalidate();
links.remove(btn);
}
/**
* Add menu treeitem into the user favorite panel
* @param treeitem
@ -341,7 +313,9 @@ public class DPFavourites extends DashboardPanel implements EventListener<Event>
if(value != null)
{
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");
boolean isWindow = menuType != null && menuType.equals("window");
@ -364,6 +338,7 @@ public class DPFavourites extends DashboardPanel implements EventListener<Event>
} else {
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.webui.adwindow.ADTabpanel;
import org.adempiere.webui.adwindow.ADWindow;
import org.adempiere.webui.apps.MenuSearchController;
import org.adempiere.webui.exception.ApplicationException;
import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.theme.ThemeManager;
@ -205,6 +206,7 @@ public abstract class AbstractMenuPanel extends Panel implements EventListener<E
link.setSclass("menu-href");
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 {
margin-left: 4px;
margin-bottom: 3px;
padding-left: 1px;
}
.fav-new-btn img {