Skip to content

Commit

Permalink
IDEMPIERE-6105 Implement recently access menu items (idempiere#2311)
Browse files Browse the repository at this point in the history
  • Loading branch information
hengsin authored Apr 20, 2024
1 parent 2d6e345 commit c34767b
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 78 deletions.
1 change: 1 addition & 0 deletions org.adempiere.base/src/org/compiere/model/SystemIDs.java
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ public class SystemIDs
public final static int WINDOW_LOT = 257;
public final static int WINDOW_MATERIAL_RECEIPT = 184;
public final static int WINDOW_MATERIALTRANSACTIONS_INDIRECTUSER = 223;
public final static int WINDOW_MENU = 105;
public final static int WINDOW_MY_REQUESTS = 237;
public final static int WINDOW_NOTICE = 193;
public final static int WINDOW_PAYMENTS_INTO_BATCH = 200031;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,9 @@ private void init() {
bandbox.setCtrlKeys("#up#down");
bandbox.addEventListener(Events.ON_CTRL_KEY, this);
bandbox.addEventListener(Events.ON_FOCUS, e -> {
if (!bandbox.isOpen())
bandbox.setOpen(true);
bandbox.setOpen(true);
if (Util.isEmpty(bandbox.getValue(), true) && tabbox.getSelectedIndex() == 0)
menuController.updateRecentItems();
});

Bandpopup popup = new Bandpopup();
Expand Down Expand Up @@ -224,6 +225,8 @@ public void onEvent(Event event) throws Exception {
}
}
} else if (event.getName().equals(Events.ON_SELECT)) {
if (tabbox.getSelectedIndex() == 0)
menuController.updateRecentItems();
String value = (String) bandbox.getAttribute(LAST_ONCHANGING_ATTR);
if (value == null) {
value = bandbox.getValue();
Expand Down Expand Up @@ -254,7 +257,7 @@ public void closePopup() {
* Handle client info event from browser.
*/
public void onClientInfo() {
ZKUpdateUtil.setWindowHeightX(bandbox.getDropdown(), ClientInfo.get().desktopHeight-50);
ZKUpdateUtil.setWindowHeightX(bandbox.getDropdown(), ClientInfo.get().desktopHeight-100);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@
import org.adempiere.webui.util.TreeUtils;
import org.adempiere.webui.util.ZKUpdateUtil;
import org.compiere.model.MMenu;
import org.compiere.model.MPreference;
import org.compiere.model.MToolBarButtonRestrict;
import org.compiere.model.MTreeNode;
import org.compiere.model.Query;
import org.compiere.model.SystemIDs;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.compiere.util.Util;
Expand Down Expand Up @@ -68,6 +71,9 @@
*/
public class MenuSearchController implements EventListener<Event>{

/** Initial number of menu items loaded into listbox */
private static final int INITIAL_LOADING_SIZE = 50;

/** Component attribute to hold reference of {@link MTreeNode} **/
public static final String M_TREE_NODE_ATTR = "MTreeNode";

Expand All @@ -77,7 +83,7 @@ public class MenuSearchController implements EventListener<Event>{
private static final String Z_ICON_STAR = "z-icon-star";
/** Event echo from {@link #search(String)} to initiate search action **/
private static final String ON_SEARCH_ECHO_EVENT = "onSearchEcho";
/** Event to load all menu items into {@link #listbox}. Default is to load the first 50 only. **/
/** Event to load all menu items into {@link #listbox}. Default is to load the first {@link #INITIAL_LOADING_SIZE} only. **/
private static final String ON_LOAD_MORE_EVENT = "onLoadMore";
/** {@link Listitem} attribute to store the last timestamp of ON_CLICK or ON_SELECT event **/
private static final String ONSELECT_TIMESTAMP_ATTR = "onselect.timestamp";
Expand All @@ -100,20 +106,58 @@ public class MenuSearchController implements EventListener<Event>{

private String highlightText = null;

/** List of recently access menu items (AD_Menu_ID) */
private List<String> recentMenuItemIds = new ArrayList<>();

/** Event post from {@link #selectTreeitem(Object, Boolean)} **/
private static final String ON_POST_SELECT_TREEITEM_EVENT = "onPostSelectTreeitem";

/**
* @param tree
* @param tree usually the tree instance from {@link}
*/
public MenuSearchController(Tree tree) {
this.tree = tree;
}

/**
* Load recently access menu items
*/
private List<String> loadRecentItems() {
List<String> recents = new ArrayList<String>();
int AD_User_ID = Env.getAD_User_ID(Env.getCtx());
int AD_Role_ID = Env.getAD_Role_ID(Env.getCtx());
int AD_Org_ID = 0;
String attribute = AD_Role_ID+"|RecentMenuItems";
Query query = new Query(Env.getCtx(), MPreference.Table_Name, "PreferenceFor=? AND Attribute=? AND AD_Org_ID=? AND AD_User_ID=? AND AD_Window_ID=?", null);
MPreference preference = query.setClient_ID().setParameters("W", attribute, AD_Org_ID, AD_User_ID, SystemIDs.WINDOW_MENU).first();
if (preference != null) {
String[] recentItems = preference.getValue().split("[,]");
for (String recentItem : recentItems) {
recents.add(recentItem);
}
}
return recents;
}

/**
* If there are changes in the recent menu items for user, reload and update menu items model
*/
public void updateRecentItems() {
List<String> recents = loadRecentItems();
if (!recents.equals(recentMenuItemIds)) {
recentMenuItemIds = recents;
sortMenuItemModel();
moveRecentItems();
if (fullModel != null)
updateListboxModel(model);
}
}

/**
* Populate {@link #model} from {@link #tree}
*/
public void refreshModel() {
recentMenuItemIds = loadRecentItems();
final List<MenuItem> list = new ArrayList<MenuItem>();
if (tree.getModel() == null) {
TreeUtils.traverse(tree, new TreeItemAction() {
Expand All @@ -130,15 +174,51 @@ public void run(DefaultTreeNode<?> treeNode) {
});
}
model = new ListModelList<MenuItem>(list, true);
model.sort(new Comparator<MenuItem>() {

sortMenuItemModel();
moveRecentItems();
}

/**
* Sort menu items model in alphabetical order
*/
private void sortMenuItemModel() {
model.sort(new Comparator<MenuItem>() {
@Override
public int compare(MenuItem o1, MenuItem o2) {
return o1.getLabel().compareTo(o2.getLabel());
}
}, true);
}

/**
* Move the 7 most recently access menu items to the top of menu items model
*/
private void moveRecentItems() {
if (recentMenuItemIds.size() > 0) {
List<MenuItem> recents = new ArrayList<MenuItem>();
for(String id : recentMenuItemIds) {
for(int i = 0; i < model.getSize(); i++) {
if (model.get(i).getData() instanceof Treeitem ti) {
if (ti.getValue() instanceof String tis) {
if (tis.equals(id)) {
recents.add(model.get(i));
break;
}
}
}
}
}
if (recents.size() > 0) {
for (MenuItem mi : recents) {
model.remove(mi);
}
for(int i = recents.size()-1; i >= 0; i--) {
model.add(0, recents.get(i));
}
}
}
}

/**
* Add treeNode to list
* @param list
Expand Down Expand Up @@ -373,16 +453,16 @@ private void onSelect(ListItem selected, Boolean newRecord) {

/**
* Load {@link #fullModel} to {@link #listbox}.
* Only first 50 loaded to {@link #listbox} initially.
* Only first {@link #INITIAL_LOADING_SIZE} loaded to {@link #listbox} initially.
*/
private void loadMore() {
ListModel<MenuItem> listModel = listbox.getModel();
ListModelList<MenuItem> lml = (ListModelList<MenuItem>) listModel;
lml.remove(lml.size()-1);
List<MenuItem> subList = fullModel.subList(50, fullModel.size());
List<MenuItem> subList = fullModel.subList(INITIAL_LOADING_SIZE, fullModel.size());
lml.addAll(subList);
fullModel = null;
listbox.setSelectedIndex(50);
listbox.setSelectedIndex(INITIAL_LOADING_SIZE);
Clients.scrollIntoView(listbox.getSelectedItem());
}

Expand Down Expand Up @@ -430,8 +510,8 @@ private void select(Treeitem selectedItem) {
}

/**
* Handle {@link #ON_POST_SELECT_TREEITEM_EVENT} event.
* Post ON_CLICK event to link ({@link A} or {@link Treerow}).
* Handle {@link #ON_POST_SELECT_TREEITEM_EVENT} event.<br/>
* Post ON_CLICK event to link ({@link A} or {@link Treerow}, handle in {@link AbstractMenuPanel}).
* @param newRecord
*/
private void onPostSelectTreeitem(Boolean newRecord) {
Expand All @@ -441,9 +521,10 @@ private void onPostSelectTreeitem(Boolean newRecord) {
event = new Event(Events.ON_CLICK, tree.getSelectedItem().getTreerow().getFirstChild().getFirstChild(), newRecord);
}
else
{
{
event = new Event(Events.ON_CLICK, tree.getSelectedItem().getTreerow(), newRecord);
}

Events.postEvent(event);
}

Expand Down Expand Up @@ -474,15 +555,15 @@ public void onSearchEcho(String value) {

/**
* Update {@link #listbox} with newModel.
* If newModel has > 50 items, only first 50 is loaded into {@link #listbox}.
* If newModel has > {@link #INITIAL_LOADING_SIZE} items, only first {@link #INITIAL_LOADING_SIZE} is loaded into {@link #listbox}.
* User has to click the load more link (...) to load the rest of the items into {@link #listbox}.
* @param newModel
*/
private void updateListboxModel(ListModelList<MenuItem> newModel) {
fullModel = null;
if (newModel.size() > 50) {
if (newModel.size() > INITIAL_LOADING_SIZE) {
List<MenuItem> list = newModel.getInnerList();
List<MenuItem> subList = list.subList(0, 50);
List<MenuItem> subList = list.subList(0, INITIAL_LOADING_SIZE);
fullModel = newModel;
newModel = new ListModelList<MenuItem>(subList.toArray(new MenuItem[0]));
MenuItem more = new MenuItem();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,12 @@
import java.util.Objects;
import java.util.logging.Level;

import org.adempiere.util.Callback;
import org.adempiere.webui.ClientInfo;
import org.adempiere.webui.adwindow.ADTabpanel;
import org.adempiere.webui.adwindow.ADWindow;
import org.adempiere.webui.desktop.AbstractDesktop;
import org.adempiere.webui.desktop.FavouriteController;
import org.adempiere.webui.desktop.IDesktop;
import org.adempiere.webui.exception.ApplicationException;
import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.theme.ThemeManager;
import org.compiere.model.MMenu;
import org.compiere.model.MQuery;
import org.compiere.model.MTable;
import org.compiere.model.MToolBarButtonRestrict;
import org.compiere.model.MTreeNode;
import org.compiere.util.CLogger;
Expand Down Expand Up @@ -331,27 +324,7 @@ private void onNewRecord(int menuID)
{
try
{
MMenu menu = (MMenu) MTable.get(Env.getCtx(), MMenu.Table_ID).getPO(menuID, null);
IDesktop desktop = SessionManager.getAppDesktop();
if (desktop instanceof AbstractDesktop)
((AbstractDesktop)desktop).setPredefinedContextVariables(menu.getPredefinedContextVariables());

MQuery query = new MQuery("");
query.addRestriction("1=2");
query.setRecordCount(0);

SessionManager.getAppDesktop().openWindow(menu.getAD_Window_ID(), query, new Callback<ADWindow>() {
@Override
public void onCallback(ADWindow result)
{
if (result == null)
return;

result.getADWindowContent().onNew();
ADTabpanel adtabpanel = (ADTabpanel) result.getADWindowContent().getADTab().getSelectedTabpanel();
adtabpanel.focusToFirstEditor(false);
}
});
SessionManager.getAppDesktop().onNewRecord(menuID);
}
catch (Exception e)
{
Expand Down
Loading

0 comments on commit c34767b

Please sign in to comment.