IDEMPIERE-4835 Grid View: Implement optional hide empty column feature (#727)

* IDEMPIERE-4835 Grid View: Implement optional hide empty column feature

* IDEMPIERE-4835 Grid View: Implement optional hide empty column feature

- fix issue with save width saving 0px width to
ad_tab_customization.custom
- added ad_tab_customization.IsAutoHideEmptyColumn
This commit is contained in:
hengsin 2021-06-19 15:24:08 +08:00 committed by GitHub
parent 66a15865d6
commit ded9693163
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 241 additions and 6 deletions

View File

@ -0,0 +1,22 @@
SET SQLBLANKLINES ON
SET DEFINE OFF
-- Jun 17, 2021, 4:31:48 PM MYT
INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200175,0,0,TO_DATE('2021-06-17 16:31:47','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2021-06-17 16:31:47','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','ZK_GRID_AUTO_HIDE_EMPTY_COLUMNS','N','Y/N - Auto hide column with empty content','D','C','b1bcee77-fbb7-413a-a22b-f250929b3e65')
;
-- Jun 19, 2021, 1:50:21 PM MYT
INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,PrintName,EntityType,AD_Element_UU) VALUES (203516,0,0,'Y',TO_DATE('2021-06-19 13:50:20','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-06-19 13:50:20','YYYY-MM-DD HH24:MI:SS'),100,'IsAutoHideEmptyColumn','Auto Hide Empty Column','Auto Hide Empty Column','D','557fd34c-cf85-45c9-9ef0-63b233f4d572')
;
-- Jun 19, 2021, 1:52:02 PM MYT
INSERT INTO AD_Column (AD_Column_ID,Version,Name,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Reference_Value_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (214505,0,'Auto Hide Empty Column',200008,'IsAutoHideEmptyColumn',1,'N','N','N','N','N',0,'N',17,319,0,0,'Y',TO_DATE('2021-06-19 13:52:01','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-06-19 13:52:01','YYYY-MM-DD HH24:MI:SS'),100,203516,'Y','N','D','N','N','N','Y','18b6313e-2902-4e33-abd6-d135b6b5f4b3','Y',0,'N','N','N','N')
;
-- Jun 19, 2021, 1:52:14 PM MYT
ALTER TABLE AD_Tab_Customization ADD IsAutoHideEmptyColumn CHAR(1) DEFAULT NULL
;
SELECT Register_Migration_Script ('202106171641_IDEMPIERE-4835.sql') FROM DUAL
;

View File

@ -0,0 +1,19 @@
-- Jun 17, 2021, 4:31:48 PM MYT
INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200175,0,0,TO_TIMESTAMP('2021-06-17 16:31:47','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2021-06-17 16:31:47','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','ZK_GRID_AUTO_HIDE_EMPTY_COLUMNS','N','Y/N - Auto hide column with empty content','D','C','b1bcee77-fbb7-413a-a22b-f250929b3e65')
;
-- Jun 19, 2021, 1:50:21 PM MYT
INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,PrintName,EntityType,AD_Element_UU) VALUES (203516,0,0,'Y',TO_TIMESTAMP('2021-06-19 13:50:20','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-06-19 13:50:20','YYYY-MM-DD HH24:MI:SS'),100,'IsAutoHideEmptyColumn','Auto Hide Empty Column','Auto Hide Empty Column','D','557fd34c-cf85-45c9-9ef0-63b233f4d572')
;
-- Jun 19, 2021, 1:52:02 PM MYT
INSERT INTO AD_Column (AD_Column_ID,Version,Name,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Reference_Value_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (214505,0,'Auto Hide Empty Column',200008,'IsAutoHideEmptyColumn',1,'N','N','N','N','N',0,'N',17,319,0,0,'Y',TO_TIMESTAMP('2021-06-19 13:52:01','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-06-19 13:52:01','YYYY-MM-DD HH24:MI:SS'),100,203516,'Y','N','D','N','N','N','Y','18b6313e-2902-4e33-abd6-d135b6b5f4b3','Y',0,'N','N','N','N')
;
-- Jun 19, 2021, 1:52:14 PM MYT
ALTER TABLE AD_Tab_Customization ADD COLUMN IsAutoHideEmptyColumn CHAR(1) DEFAULT NULL
;
SELECT Register_Migration_Script ('202106171641_IDEMPIERE-4835.sql') FROM DUAL
;

View File

@ -63,12 +63,30 @@ public class MTabCustomization extends X_AD_Tab_Customization {
* @return True if save successfully
*/
public static boolean saveData(Properties ctx, int AD_Tab_ID, int AD_User_ID, String Custom, String DisplayedGrid, String trxName, boolean isQuickForm) {
return saveData(ctx, AD_Tab_ID, AD_User_ID, Custom, DisplayedGrid, trxName, isQuickForm, null);
}
/**
* Save Tab Customization Data
*
* @param ctx - Context
* @param AD_Tab_ID - Tab ID
* @param AD_User_ID - User ID
* @param Custom - Customized Field IDs with it's Size
* @param DisplayedGrid - Default preference of Grid view
* @param trxName - Transaction
* @param isQuickForm - Is Quick Form
* @param isAutoHide - is auto hide empty column
* @return True if save successfully
*/
public static boolean saveData(Properties ctx, int AD_Tab_ID, int AD_User_ID, String Custom, String DisplayedGrid, String trxName, boolean isQuickForm, String isAutoHide) {
MTabCustomization tabCust = get(ctx, AD_User_ID, AD_Tab_ID, trxName, isQuickForm);
if (tabCust != null && tabCust.getAD_Tab_Customization_ID() > 0)
{
tabCust.setCustom(Custom);
tabCust.setIsDisplayedGrid(DisplayedGrid);
tabCust.setIsAutoHideEmptyColumn(isAutoHide);
}
else
{
@ -78,6 +96,7 @@ public class MTabCustomization extends X_AD_Tab_Customization {
tabCust.setCustom(Custom);
tabCust.setIsDisplayedGrid(DisplayedGrid);
tabCust.setIsQuickForm(isQuickForm);
tabCust.setIsAutoHideEmptyColumn(isAutoHide);
}
if (Util.isEmpty(tabCust.getCustom(), true))

View File

@ -148,6 +148,15 @@ public interface I_AD_Tab_Customization
*/
public boolean isActive();
/** Column name IsAutoHideEmptyColumn */
public static final String COLUMNNAME_IsAutoHideEmptyColumn = "IsAutoHideEmptyColumn";
/** Set Auto Hide Empty Column */
public void setIsAutoHideEmptyColumn (String IsAutoHideEmptyColumn);
/** Get Auto Hide Empty Column */
public String getIsAutoHideEmptyColumn();
/** Column name IsDisplayedGrid */
public static final String COLUMNNAME_IsDisplayedGrid = "IsDisplayedGrid";

View File

@ -180,6 +180,7 @@ public class MSysConfig extends X_AD_SysConfig
public static final String ZK_FOOTER_SERVER_DATETIME_FORMAT = "ZK_FOOTER_SERVER_DATETIME_FORMAT";
public static final String ZK_FOOTER_SERVER_MSG = "ZK_FOOTER_SERVER_MSG";
public static final String ZK_GRID_AFTER_FIND = "ZK_GRID_AFTER_FIND";
public static final String ZK_GRID_AUTO_HIDE_EMPTY_COLUMNS = "ZK_GRID_AUTO_HIDE_EMPTY_COLUMNS";
public static final String ZK_GRID_EDIT_MODELESS = "ZK_GRID_EDIT_MODELESS";
public static final String ZK_GRID_MOBILE_EDITABLE = "ZK_GRID_MOBILE_EDITABLE";
public static final String ZK_GRID_MOBILE_EDIT_MODELESS = "ZK_GRID_MOBILE_EDIT_MODELESS";

View File

@ -29,7 +29,7 @@ public class X_AD_Tab_Customization extends PO implements I_AD_Tab_Customization
/**
*
*/
private static final long serialVersionUID = 20201220L;
private static final long serialVersionUID = 20210619L;
/** Standard Constructor */
public X_AD_Tab_Customization (Properties ctx, int AD_Tab_Customization_ID, String trxName)
@ -174,6 +174,27 @@ public class X_AD_Tab_Customization extends PO implements I_AD_Tab_Customization
return (String)get_Value(COLUMNNAME_Custom);
}
/** IsAutoHideEmptyColumn AD_Reference_ID=319 */
public static final int ISAUTOHIDEEMPTYCOLUMN_AD_Reference_ID=319;
/** Yes = Y */
public static final String ISAUTOHIDEEMPTYCOLUMN_Yes = "Y";
/** No = N */
public static final String ISAUTOHIDEEMPTYCOLUMN_No = "N";
/** Set Auto Hide Empty Column.
@param IsAutoHideEmptyColumn Auto Hide Empty Column */
public void setIsAutoHideEmptyColumn (String IsAutoHideEmptyColumn)
{
set_Value (COLUMNNAME_IsAutoHideEmptyColumn, IsAutoHideEmptyColumn);
}
/** Get Auto Hide Empty Column.
@return Auto Hide Empty Column */
public String getIsAutoHideEmptyColumn ()
{
return (String)get_Value(COLUMNNAME_IsAutoHideEmptyColumn);
}
/** IsDisplayedGrid AD_Reference_ID=319 */
public static final int ISDISPLAYEDGRID_AD_Reference_ID=319;
/** Yes = Y */

View File

@ -195,14 +195,32 @@ public class GridTabRowRenderer implements RowRenderer<Object[]>, RowRendererExt
return textBox;
}
/**
* Check existence of readonly editor and return display text
* @param value
* @param gridField
* @param rowIndex
* @return display text
*/
protected String getDisplayTextWithEditorCheck(Object value, GridField gridField, int rowIndex) {
WEditor readOnlyEditor = readOnlyEditors.get(gridField);
if (readOnlyEditor == null) {
readOnlyEditor = WebEditorFactory.getEditor(gridField, true, readOnlyEditorConfiguration);
if (readOnlyEditor != null) {
readOnlyEditors.put(gridField, readOnlyEditor);
}
}
return getDisplayText(value, gridField, rowIndex);
}
/**
* call {@link #getDisplayText(Object, GridField, int, boolean)} with isForceGetValue = false
* @param value
* @param gridField
* @param rowIndex
* @return
* @return display text
*/
private String getDisplayText(Object value, GridField gridField, int rowIndex){
public String getDisplayText(Object value, GridField gridField, int rowIndex){
return getDisplayText(value, gridField, rowIndex, false);
}
@ -212,7 +230,7 @@ public class GridTabRowRenderer implements RowRenderer<Object[]>, RowRendererExt
* @param gridField
* @param rowIndex
* @param isForceGetValue
* @return
* @return display text
*/
private String getDisplayText(Object value, GridField gridField, int rowIndex, boolean isForceGetValue)
{
@ -431,7 +449,8 @@ public class GridTabRowRenderer implements RowRenderer<Object[]>, RowRendererExt
columnCount = gridPanelFields.length;
gridTabFields = gridTab.getFields();
isGridViewCustomized = gridTabFields.length != gridPanelFields.length;
}
}
gridPanel.autoHideEmptyColumns();
}
if (grid == null)

View File

@ -52,6 +52,7 @@ import org.zkoss.zk.au.out.AuFocus;
import org.zkoss.zk.au.out.AuScript;
import org.zkoss.zk.ui.AbstractComponent;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.IdSpace;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
@ -75,6 +76,14 @@ import org.zkoss.zul.impl.CustomGridDataLoader;
*/
public class GridView extends Vlayout implements EventListener<Event>, IdSpace, IFieldEditorContainer, StateChangeListener
{
public static final String ZERO_PX_WIDTH = "0px";
private static final String GRID_VIEW_GRID_FIELD_INDEX = "gridView.gridField.index";
public static final String COLUMN_WIDTH_ORIGINAL = "column.width.original";
private static final String COLUMN_HFLEX_ORIGINAL = "column.hflex.original";
private static final int MIN_COLUMN_MOBILE_WIDTH = 100;
/**
@ -148,6 +157,8 @@ public class GridView extends Vlayout implements EventListener<Event>, IdSpace,
private boolean showCurrentRowIndicatorColumn = true;
private String m_isAutoHideEmptyColumn;
public GridView()
{
this(0);
@ -306,6 +317,8 @@ public class GridView extends Vlayout implements EventListener<Event>, IdSpace,
updateListIndex();
autoHideEmptyColumns();
this.init = true;
showRecordsCount();
@ -360,6 +373,7 @@ public class GridView extends Vlayout implements EventListener<Event>, IdSpace,
columnWidthMap.put(gridField[i].getAD_Field_ID(), widths[i]);
}
}
m_isAutoHideEmptyColumn = tabCustomization.getIsAutoHideEmptyColumn();
} else {
ArrayList<GridField> gridFieldList = new ArrayList<GridField>();
@ -586,6 +600,7 @@ public class GridView extends Vlayout implements EventListener<Event>, IdSpace,
colnames.put(index, gridField[i].getHeader());
index++;
org.zkoss.zul.Column column = new Column();
column.setAttribute(GRID_VIEW_GRID_FIELD_INDEX, i);
column.setHeight("2em");
int colindex =tableModel.findColumn(gridField[i].getColumnName());
column.setSortAscending(new SortComparator(colindex, true, Env.getLanguage(Env.getCtx())));
@ -706,6 +721,93 @@ public class GridView extends Vlayout implements EventListener<Event>, IdSpace,
}
/**
* auto hide empty columns
*/
protected void autoHideEmptyColumns() {
if (!isAutoHideEmptyColumns()) {
return;
}
String attr = listbox.getUuid()+".autoHideEmptyColumns";
if (Executions.getCurrent().getAttribute(attr) != null) {
return;
} else {
Executions.getCurrent().setAttribute(attr, Boolean.TRUE);
}
org.zkoss.zul.Columns columns = listbox.getColumns();
List<Column> columnList = columns.getChildren();
int rowCount = listModel.getSize();
GridField[] gridTabFields = gridTab.getFields();
Map<Integer, Integer> indexMap = new HashMap<Integer, Integer>();
if (rowCount > 0) {
for(Column column : columnList) {
Object value = column.getAttribute(GRID_VIEW_GRID_FIELD_INDEX);
if (value == null || !(value instanceof Integer))
continue;
int index = (Integer)value;
for(int i = 0; i < gridTabFields.length; i++) {
if (gridField[index].getAD_Field_ID() == gridTabFields[i].getAD_Field_ID()) {
indexMap.put(index, i);
break;
}
}
}
}
for(Column column : columnList) {
Object value = column.getAttribute(GRID_VIEW_GRID_FIELD_INDEX);
if (value == null || !(value instanceof Integer))
continue;
int index = (Integer)value;
boolean hideColumn = false;
if (rowCount > 0) {
int valueIndex = indexMap.get(index);
hideColumn = true;
for (int i = 0; i < rowCount; i++) {
Object[] values = (Object[]) listModel.getElementAt(i);
int rowIndex = i;
if (paging != null && paging.getPageSize() > 0) {
rowIndex = (paging.getActivePage() * paging.getPageSize()) + rowIndex;
}
String display = renderer.getDisplayTextWithEditorCheck(values[valueIndex], gridField[index], rowIndex);
if (!Util.isEmpty(display, true)) {
hideColumn = false;
break;
}
}
}
if (hideColumn && column.isVisible() && !ZERO_PX_WIDTH.equals(column.getWidth())) {
String width = column.getWidth();
String hflex = column.getHflex();
if (!Util.isEmpty(hflex, true)) {
column.setAttribute(COLUMN_HFLEX_ORIGINAL, hflex);
column.setHflex(null);
}
column.setWidth(ZERO_PX_WIDTH);
if (column.getAttribute(COLUMN_WIDTH_ORIGINAL) == null)
column.setAttribute(COLUMN_WIDTH_ORIGINAL, width != null ? width : "");
} else if (!hideColumn && column.isVisible() && ZERO_PX_WIDTH.equals(column.getWidth()) && column.getAttribute(COLUMN_WIDTH_ORIGINAL) != null) {
if (column.getAttribute(COLUMN_HFLEX_ORIGINAL) != null ) {
String hflex = (String)column.getAttribute(COLUMN_HFLEX_ORIGINAL);
column.setWidth(null);
column.setHflex(hflex);
} else {
column.setWidth((String) column.getAttribute(COLUMN_WIDTH_ORIGINAL));
}
}
}
}
private boolean isAutoHideEmptyColumns() {
if (!Util.isEmpty(m_isAutoHideEmptyColumn, true))
return "Y".equalsIgnoreCase(m_isAutoHideEmptyColumn);
else
return MSysConfig.getBooleanValue(MSysConfig.ZK_GRID_AUTO_HIDE_EMPTY_COLUMNS, false, Env.getAD_Client_ID(Env.getCtx()));
}
private void updateEmptyMessage() {
if (gridTab.getRowCount() == 0)
{

View File

@ -47,6 +47,7 @@ import org.compiere.model.I_AD_Field;
import org.compiere.model.MField;
import org.compiere.model.MRefList;
import org.compiere.model.MRole;
import org.compiere.model.MSysConfig;
import org.compiere.model.MTab;
import org.compiere.model.Query;
import org.compiere.model.X_AD_Tab_Customization;
@ -122,6 +123,7 @@ public class CustomizeGridViewPanel extends Panel
private Checkbox chkSaveWidth = new Checkbox();
private Label lblGridMode = new Label();
private Listbox lstGridMode = new Listbox();
private Checkbox chkAutoHideEmptyColumn = new Checkbox();
//
SimpleListModel noModel = new SimpleListModel();
@ -275,6 +277,11 @@ public class CustomizeGridViewPanel extends Panel
lstGridMode.setStyle("margin-left: 2px");
southPanel.appendChild(lstGridMode);
sep = new Separator();
southPanel.appendChild(sep);
chkAutoHideEmptyColumn.setLabel(Msg.getElement(Env.getCtx(), "IsAutoHideEmptyColumn"));
southPanel.appendChild(chkAutoHideEmptyColumn);
sep = new Separator();
sep.setSpacing("2px");
southPanel.appendChild(sep);
@ -386,6 +393,13 @@ public class CustomizeGridViewPanel extends Panel
if (m_tabcust != null && m_tabcust.getCustom().indexOf("px") > 0)
chkSaveWidth.setChecked(true);
if (m_tabcust != null && m_tabcust.getIsAutoHideEmptyColumn() != null) {
chkAutoHideEmptyColumn.setChecked("Y".equalsIgnoreCase(m_tabcust.getIsAutoHideEmptyColumn()));
chkAutoHideEmptyColumn.setAttribute("ad_tab_customization.value", m_tabcust.getIsAutoHideEmptyColumn());
} else {
chkAutoHideEmptyColumn.setChecked(MSysConfig.getBooleanValue(MSysConfig.ZK_GRID_AUTO_HIDE_EMPTY_COLUMNS, false, Env.getAD_Client_ID(Env.getCtx())));
}
} // loadData
/**
@ -557,7 +571,13 @@ public class CustomizeGridViewPanel extends Panel
gridview = lstGridMode.getSelectedItem().toString();
final String dView = gridview;
ok = MTabCustomization.saveData(Env.getCtx(), m_AD_Tab_ID, m_AD_User_ID, custom.toString(), dView, null, false);
String isAutoHide = null;
if (chkAutoHideEmptyColumn.isChecked() != MSysConfig.getBooleanValue(MSysConfig.ZK_GRID_AUTO_HIDE_EMPTY_COLUMNS, false, Env.getAD_Client_ID(Env.getCtx()))) {
isAutoHide = chkAutoHideEmptyColumn.isChecked() ? "Y" : "N";
} else if (chkAutoHideEmptyColumn.getAttribute("ad_tab_customization.value") != null) {
isAutoHide = chkAutoHideEmptyColumn.isChecked() ? "Y" : "N";
}
ok = MTabCustomization.saveData(Env.getCtx(), m_AD_Tab_ID, m_AD_User_ID, custom.toString(), dView, null, false, isAutoHide);
if(ok) {
m_saved = true;
// FDialog.info(m_WindowNo, null, "Saved");

View File

@ -121,6 +121,9 @@ public class CustomizeGridViewDialog extends Window {
int offset = tabPanel.getGridView().isShowCurrentRowIndicatorColumn() ? 2 : 1;
Column column = (Column) columnList.get(i+offset);
String width = column.getWidth();
if (GridView.ZERO_PX_WIDTH.equals(width) && column.getAttribute(GridView.COLUMN_WIDTH_ORIGINAL) != null) {
width = (String) column.getAttribute(GridView.COLUMN_WIDTH_ORIGINAL);
}
columnsWidth.put(fields[i].getAD_Field_ID(), width);
gridFieldIds.add(fields[i].getAD_Field_ID());