From e528c6f8cbb6245787134b33db683d45417c749e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Tak=C3=A1cs?= <93127072+PeterTakacs300@users.noreply.github.com> Date: Tue, 30 Aug 2022 10:11:42 +0200 Subject: [PATCH] IDEMPIERE-5389 - Dashboard row layout (#1448) * IDEMPIERE-5389 - Dashboard row layout * IDEMPIERE-5389 - taking changes related to ticket 5393 * IDEMPIERE-5389 - added Flex Grow to Preference * IDEMPIERE-5389 - fixing gadget heights * IDEMPIERE-5389 - center alignment for Status Line * IDEMPIERE-5389 - fall back to column layout * IDEMPIERE-5389 - pr1448 patch * IDEMPIERE-5389 - FixOracleMigration patch --- .../oracle/202208181113_IDEMPIERE-5389.sql | 46 ++ .../202208181113_IDEMPIERE-5389.sql | 43 ++ .../model/I_PA_DashboardPreference.java | 23 +- .../compiere/model/MDashboardPreference.java | 152 ++-- .../src/org/compiere/model/MSysConfig.java | 1 + .../model/X_PA_DashboardPreference.java | 23 +- .../webui/dashboard/DashboardRunnable.java | 5 + .../webui/desktop/DashboardController.java | 679 +++++++++++++----- .../theme/default/css/fragment/gadget.css.dsp | 20 +- 9 files changed, 779 insertions(+), 213 deletions(-) create mode 100644 migration/iD10/oracle/202208181113_IDEMPIERE-5389.sql create mode 100644 migration/iD10/postgresql/202208181113_IDEMPIERE-5389.sql diff --git a/migration/iD10/oracle/202208181113_IDEMPIERE-5389.sql b/migration/iD10/oracle/202208181113_IDEMPIERE-5389.sql new file mode 100644 index 0000000000..66dcd8c9bf --- /dev/null +++ b/migration/iD10/oracle/202208181113_IDEMPIERE-5389.sql @@ -0,0 +1,46 @@ +-- IDEMPIERE-5389 +SELECT register_migration_script('202208181113_IDEMPIERE-5389.sql') FROM dual; + +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Aug 16, 2022, 4:52:58 PM CEST +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 (200203,0,0,TO_TIMESTAMP('2022-08-16 16:52:58','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2022-08-16 16:52:58','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','DASHBOARD_LAYOUT_ORIENTATION','R','C - columns (vertical layout) / R - rows (horizontal layout)','D','C','4de26350-c352-4552-87be-44abe331f821') +; + +-- Aug 23, 2022, 4:20:08 PM CEST +INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,PrintName,EntityType,AD_Element_UU) VALUES (203636,0,0,'Y',TO_TIMESTAMP('2022-08-23 16:20:08','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-08-23 16:20:08','YYYY-MM-DD HH24:MI:SS'),100,'FlexGrow','Flex Grow','This defines the ability for a flex item to grow if necessary. It accepts a unitless value that serves as a proportion. It dictates what amount of the available space inside the flex container the item should take up.','Flex Grow','D','8e8273ad-4c34-4f21-bc01-a8b621bf3c38') +; + +-- Aug 23, 2022, 4:20:44 PM CEST +INSERT INTO AD_Column (AD_Column_ID,Version,Name,Description,AD_Table_ID,ColumnName,DefaultValue,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_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,IsHtml) VALUES (215100,0,'Flex Grow','This defines the ability for a flex item to grow if necessary. It accepts a unitless value that serves as a proportion. It dictates what amount of the available space inside the flex container the item should take up.',200013,'FlexGrow','1',14,'N','N','Y','N','N',0,'N',11,0,0,'Y',TO_TIMESTAMP('2022-08-24 14:02:11','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-08-24 14:02:11','YYYY-MM-DD HH24:MI:SS'),100,203636,'Y','N','D','N','N','N','Y','5de27289-cab8-4533-9639-9eb66cd84c7f','Y',0,'N','N','N') +; + +-- Aug 23, 2022, 4:20:44 PM CEST +ALTER TABLE PA_DashboardPreference ADD FlexGrow NUMBER(10) DEFAULT 1 NOT NULL +; + +-- Aug 23, 2022, 4:21:32 PM CEST +INSERT INTO AD_Field (AD_Field_ID,Name,Description,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,SortNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,XPosition,ColumnSpan,NumLines,IsQuickEntry,IsDefaultFocus,IsAdvancedField,IsQuickForm) VALUES (207136,'Flex Grow','This defines the ability for a flex item to grow if necessary. It accepts a unitless value that serves as a proportion. It dictates what amount of the available space inside the flex container the item should take up.',200011,215100,'Y',0,110,0,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2022-08-23 16:21:32','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-08-23 16:21:32','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','7bf531c3-d79b-493c-b3ec-84160feb5927','Y',110,1,1,1,'N','N','N','N') +; + +-- Aug 23, 2022, 4:21:54 PM CEST +UPDATE AD_Field SET IsDisplayed='Y', SeqNo=90, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, XPosition=1, ColumnSpan=2, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-08-23 16:21:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=207136 +; + +-- Aug 23, 2022, 4:21:54 PM CEST +UPDATE AD_Field SET SeqNo=100, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-08-23 16:21:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=200300 +; + +-- Aug 23, 2022, 4:21:54 PM CEST +UPDATE AD_Field SET SeqNo=110, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-08-23 16:21:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=200307 +; + +-- Aug 23, 2022, 4:21:54 PM CEST +UPDATE AD_Field SET SeqNo=0, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-08-23 16:21:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=200303 +; + +-- Aug 23, 2022, 4:21:54 PM CEST +UPDATE AD_Field SET SeqNo=0, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-08-23 16:21:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=204983 +; + diff --git a/migration/iD10/postgresql/202208181113_IDEMPIERE-5389.sql b/migration/iD10/postgresql/202208181113_IDEMPIERE-5389.sql new file mode 100644 index 0000000000..1add81be5b --- /dev/null +++ b/migration/iD10/postgresql/202208181113_IDEMPIERE-5389.sql @@ -0,0 +1,43 @@ +-- IDEMPIERE-5389 +SELECT register_migration_script('202208181113_IDEMPIERE-5389.sql') FROM dual; + +-- Aug 16, 2022, 4:52:58 PM CEST +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 (200203,0,0,TO_TIMESTAMP('2022-08-16 16:52:58','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2022-08-16 16:52:58','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','DASHBOARD_LAYOUT_ORIENTATION','R','C - columns (vertical layout) / R - rows (horizontal layout)','D','C','4de26350-c352-4552-87be-44abe331f821') +; + +-- Aug 23, 2022, 4:20:08 PM CEST +INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,PrintName,EntityType,AD_Element_UU) VALUES (203636,0,0,'Y',TO_TIMESTAMP('2022-08-23 16:20:08','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-08-23 16:20:08','YYYY-MM-DD HH24:MI:SS'),100,'FlexGrow','Flex Grow','This defines the ability for a flex item to grow if necessary. It accepts a unitless value that serves as a proportion. It dictates what amount of the available space inside the flex container the item should take up.','Flex Grow','D','8e8273ad-4c34-4f21-bc01-a8b621bf3c38') +; + +-- Aug 23, 2022, 4:20:44 PM CEST +INSERT INTO AD_Column (AD_Column_ID,Version,Name,Description,AD_Table_ID,ColumnName,DefaultValue,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_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,IsHtml) VALUES (215100,0,'Flex Grow','This defines the ability for a flex item to grow if necessary. It accepts a unitless value that serves as a proportion. It dictates what amount of the available space inside the flex container the item should take up.',200013,'FlexGrow','1',14,'N','N','Y','N','N',0,'N',11,0,0,'Y',TO_TIMESTAMP('2022-08-24 14:02:11','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-08-24 14:02:11','YYYY-MM-DD HH24:MI:SS'),100,203636,'Y','N','D','N','N','N','Y','5de27289-cab8-4533-9639-9eb66cd84c7f','Y',0,'N','N','N') +; + +-- Aug 23, 2022, 4:20:44 PM CEST +ALTER TABLE PA_DashboardPreference ADD COLUMN FlexGrow NUMERIC(10) DEFAULT '1' NOT NULL +; + +-- Aug 23, 2022, 4:21:32 PM CEST +INSERT INTO AD_Field (AD_Field_ID,Name,Description,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,SortNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,XPosition,ColumnSpan,NumLines,IsQuickEntry,IsDefaultFocus,IsAdvancedField,IsQuickForm) VALUES (207136,'Flex Grow','This defines the ability for a flex item to grow if necessary. It accepts a unitless value that serves as a proportion. It dictates what amount of the available space inside the flex container the item should take up.',200011,215100,'Y',0,110,0,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2022-08-23 16:21:32','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-08-23 16:21:32','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','7bf531c3-d79b-493c-b3ec-84160feb5927','Y',110,1,1,1,'N','N','N','N') +; + +-- Aug 23, 2022, 4:21:54 PM CEST +UPDATE AD_Field SET IsDisplayed='Y', SeqNo=90, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, XPosition=1, ColumnSpan=2, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-08-23 16:21:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=207136 +; + +-- Aug 23, 2022, 4:21:54 PM CEST +UPDATE AD_Field SET SeqNo=100, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-08-23 16:21:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=200300 +; + +-- Aug 23, 2022, 4:21:54 PM CEST +UPDATE AD_Field SET SeqNo=110, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-08-23 16:21:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=200307 +; + +-- Aug 23, 2022, 4:21:54 PM CEST +UPDATE AD_Field SET SeqNo=0, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-08-23 16:21:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=200303 +; + +-- Aug 23, 2022, 4:21:54 PM CEST +UPDATE AD_Field SET SeqNo=0, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-08-23 16:21:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=204983 +; + diff --git a/org.adempiere.base/src/org/compiere/model/I_PA_DashboardPreference.java b/org.adempiere.base/src/org/compiere/model/I_PA_DashboardPreference.java index dc6b9030d0..12c6f1a7b7 100644 --- a/org.adempiere.base/src/org/compiere/model/I_PA_DashboardPreference.java +++ b/org.adempiere.base/src/org/compiere/model/I_PA_DashboardPreference.java @@ -22,7 +22,7 @@ import org.compiere.util.KeyNamePair; /** Generated Interface for PA_DashboardPreference * @author iDempiere (generated) - * @version Release 9 + * @version Release 10 */ public interface I_PA_DashboardPreference { @@ -44,8 +44,8 @@ public interface I_PA_DashboardPreference /** Column name AD_Client_ID */ public static final String COLUMNNAME_AD_Client_ID = "AD_Client_ID"; - /** Get Client. - * Client/Tenant for this installation. + /** Get Tenant. + * Tenant for this installation. */ public int getAD_Client_ID(); @@ -53,12 +53,12 @@ public interface I_PA_DashboardPreference public static final String COLUMNNAME_AD_Org_ID = "AD_Org_ID"; /** Set Organization. - * Organizational entity within client + * Organizational entity within tenant */ public void setAD_Org_ID (int AD_Org_ID); /** Get Organization. - * Organizational entity within client + * Organizational entity within tenant */ public int getAD_Org_ID(); @@ -121,6 +121,19 @@ public interface I_PA_DashboardPreference */ public int getCreatedBy(); + /** Column name FlexGrow */ + public static final String COLUMNNAME_FlexGrow = "FlexGrow"; + + /** Set Flex Grow. + * Defines the number of units taken from max gadget + */ + public void setFlexGrow (int FlexGrow); + + /** Get Flex Grow. + * This defines the ability for a flex item to grow if necessary. It accepts a unitless value that serves as a proportion. It dictates what amount of the available space inside the flex container the item should take up. + */ + public int getFlexGrow(); + /** Column name IsActive */ public static final String COLUMNNAME_IsActive = "IsActive"; diff --git a/org.adempiere.base/src/org/compiere/model/MDashboardPreference.java b/org.adempiere.base/src/org/compiere/model/MDashboardPreference.java index 9283dbc3e6..76b14090bf 100644 --- a/org.adempiere.base/src/org/compiere/model/MDashboardPreference.java +++ b/org.adempiere.base/src/org/compiere/model/MDashboardPreference.java @@ -30,55 +30,103 @@ public class MDashboardPreference extends X_PA_DashboardPreference { /** * - */ - private static final long serialVersionUID = -3887344231734476767L; - - public static int getForSessionColumnCount(boolean isShowInDashboard, int AD_User_ID, int AD_Role_ID) - { - int noOfCols = getForSessionQuery(isShowInDashboard, AD_User_ID, AD_Role_ID) + */ + private static final long serialVersionUID = -3887344231734476767L; + + /** + * + * @param isShowInDashboard + * @param AD_User_ID + * @param AD_Role_ID + * @return number of column + */ + public static int getForSessionColumnCount(boolean isShowInDashboard, int AD_User_ID, int AD_Role_ID) + { + int noOfCols = getForSessionQuery(isShowInDashboard, AD_User_ID, AD_Role_ID) .setOnlyActiveRecords(true) .aggregate("DISTINCT "+COLUMNNAME_ColumnNo, Query.AGGREGATE_COUNT, Integer.class); - return noOfCols; - } - - public static MDashboardPreference[] getForSession(boolean isShowInDashboard, int AD_User_ID, int AD_Role_ID) - { - List list = getForSessionQuery(isShowInDashboard, AD_User_ID, AD_Role_ID).list(); - return list.toArray(new MDashboardPreference[list.size()]); - } - - public static Query getForSessionQuery(boolean isShowInDashboard, int AD_User_ID, int AD_Role_ID) - { - Properties ctx = Env.getCtx(); - + return noOfCols; + } + + /** + * + * @param isShowInDashboard + * @param AD_User_ID + * @param AD_Role_ID + * @return number of row + */ + public static int getForSessionRowCount(boolean isShowInDashboard, int AD_User_ID, int AD_Role_ID) + { + int noOfCols = getForSessionQuery(isShowInDashboard, AD_User_ID, AD_Role_ID) + .setOnlyActiveRecords(true) + .aggregate("DISTINCT "+COLUMNNAME_Line, Query.AGGREGATE_COUNT, Integer.class); + return noOfCols; + } + + /** + * + * @param isShowInDashboard + * @param AD_User_ID + * @param AD_Role_ID + * @return MDashboardPreference[] + */ + public static MDashboardPreference[] getForSession(boolean isShowInDashboard, int AD_User_ID, int AD_Role_ID) + { + List list = getForSessionQuery(isShowInDashboard, AD_User_ID, AD_Role_ID).list(); + return list.toArray(new MDashboardPreference[list.size()]); + } + + private static Query getForSessionQuery(boolean isShowInDashboard, int AD_User_ID, int AD_Role_ID) + { + return getForSessionQuery(isShowInDashboard, AD_User_ID, AD_Role_ID, -1); + } + + private static Query getForSessionQuery(boolean isShowInDashboard, int AD_User_ID, int AD_Role_ID, int lineNo) + { + Properties ctx = Env.getCtx(); + StringBuilder whereClause = new StringBuilder(COLUMNNAME_IsShowInDashboard).append("=?") .append(" AND ").append(COLUMNNAME_AD_Role_ID).append("=?") .append(" AND ").append(COLUMNNAME_AD_User_ID).append("=?") .append(" AND ").append(COLUMNNAME_AD_Org_ID).append("=0"); + if(lineNo >= 0) + whereClause.append(" AND ").append(COLUMNNAME_Line).append("=?"); List parameters = new ArrayList(); parameters.add(isShowInDashboard); parameters.add(AD_Role_ID); parameters.add(AD_User_ID); + if(lineNo >= 0) + parameters.add(lineNo); + + String orderByClause = (lineNo < 0) ? COLUMNNAME_ColumnNo+","+COLUMNNAME_AD_Client_ID+","+COLUMNNAME_Line + : COLUMNNAME_Line+","+COLUMNNAME_ColumnNo+","+COLUMNNAME_AD_Client_ID; return new Query(ctx, Table_Name, whereClause.toString(), null) .setParameters(parameters) .setOnlyActiveRecords(false) .setApplyAccessFilter(true, false) - .setOrderBy(COLUMNNAME_ColumnNo+","+COLUMNNAME_AD_Client_ID+","+COLUMNNAME_Line); - } - - public static MDashboardPreference[] getForSession(int AD_User_ID, int AD_Role_ID) - { - List list = getForSessionQuery(AD_User_ID, AD_Role_ID).list(); - return list.toArray(new MDashboardPreference[list.size()]); - } - - public static Query getForSessionQuery(int AD_User_ID, int AD_Role_ID) - { - Properties ctx = Env.getCtx(); - + .setOrderBy(orderByClause); + } + + /** + * + * @param AD_User_ID + * @param AD_Role_ID + * @param isCol + * @return MDashboardPreference[] + */ + public static MDashboardPreference[] getForSession(int AD_User_ID, int AD_Role_ID, boolean isCol) + { + List list = getForSessionQuery(AD_User_ID, AD_Role_ID, isCol).list(); + return list.toArray(new MDashboardPreference[list.size()]); + } + + private static Query getForSessionQuery(int AD_User_ID, int AD_Role_ID, boolean isCol) + { + Properties ctx = Env.getCtx(); + StringBuilder whereClause = new StringBuilder() .append(COLUMNNAME_AD_Role_ID).append("=?") .append(" AND ").append(COLUMNNAME_AD_User_ID).append("=?") @@ -88,21 +136,39 @@ public class MDashboardPreference extends X_PA_DashboardPreference parameters.add(AD_Role_ID); parameters.add(AD_User_ID); + String orderByClause = ""; + if(isCol) + orderByClause = COLUMNNAME_ColumnNo+","+COLUMNNAME_AD_Client_ID+","+ COLUMNNAME_Line; + else + orderByClause = COLUMNNAME_Line+","+COLUMNNAME_AD_Client_ID+","+ COLUMNNAME_ColumnNo; + return new Query(ctx, Table_Name, whereClause.toString(), null) .setParameters(parameters) .setOnlyActiveRecords(false) .setApplyAccessFilter(true, false) - .setOrderBy(COLUMNNAME_ColumnNo+","+COLUMNNAME_AD_Client_ID+","+COLUMNNAME_Line); - } - - public MDashboardPreference (Properties ctx, int PA_DashboardPreference_ID, String trxName) - { - super (ctx, PA_DashboardPreference_ID, trxName); - } - - public MDashboardPreference (Properties ctx, ResultSet rs, String trxName) - { - super (ctx, rs, trxName); + .setOrderBy(orderByClause); + } + + /** + * + * @param ctx + * @param PA_DashboardPreference_ID + * @param trxName + */ + public MDashboardPreference (Properties ctx, int PA_DashboardPreference_ID, String trxName) + { + super (ctx, PA_DashboardPreference_ID, trxName); + } + + /** + * + * @param ctx + * @param rs + * @param trxName + */ + public MDashboardPreference (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); } /** Set User/Contact. diff --git a/org.adempiere.base/src/org/compiere/model/MSysConfig.java b/org.adempiere.base/src/org/compiere/model/MSysConfig.java index 4d116f9d9d..bd2dc59e1b 100644 --- a/org.adempiere.base/src/org/compiere/model/MSysConfig.java +++ b/org.adempiere.base/src/org/compiere/model/MSysConfig.java @@ -84,6 +84,7 @@ public class MSysConfig extends X_AD_SysConfig public static final String CHECK_CREDIT_ON_CASH_POS_ORDER = "CHECK_CREDIT_ON_CASH_POS_ORDER"; public static final String CHECK_CREDIT_ON_PREPAY_ORDER = "CHECK_CREDIT_ON_PREPAY_ORDER"; public static final String CLIENT_ACCOUNTING = "CLIENT_ACCOUNTING"; + public static final String DASHBOARD_LAYOUT_ORIENTATION = "DASHBOARD_LAYOUT_ORIENTATION"; public static final String DEFAULT_COA_PATH = "DEFAULT_COA_PATH"; public static final String DEFAULT_ENTITYTYPE = "DEFAULT_ENTITYTYPE"; // used as default in entity type columns with get_sysconfig public static final String DB_READ_REPLICA_NORMAL_MAX_ITERATIONS = "DB_READ_REPLICA_NORMAL_MAX_ITERATIONS"; diff --git a/org.adempiere.base/src/org/compiere/model/X_PA_DashboardPreference.java b/org.adempiere.base/src/org/compiere/model/X_PA_DashboardPreference.java index 25e5fbb517..9ed708886b 100644 --- a/org.adempiere.base/src/org/compiere/model/X_PA_DashboardPreference.java +++ b/org.adempiere.base/src/org/compiere/model/X_PA_DashboardPreference.java @@ -24,7 +24,7 @@ import org.compiere.util.Env; /** Generated Model for PA_DashboardPreference * @author iDempiere (generated) - * @version Release 9 - $Id$ */ + * @version Release 10 - $Id$ */ @org.adempiere.base.Model(table="PA_DashboardPreference") public class X_PA_DashboardPreference extends PO implements I_PA_DashboardPreference, I_Persistent { @@ -32,7 +32,7 @@ public class X_PA_DashboardPreference extends PO implements I_PA_DashboardPrefer /** * */ - private static final long serialVersionUID = 20220116L; + private static final long serialVersionUID = 20220823L; /** Standard Constructor */ public X_PA_DashboardPreference (Properties ctx, int PA_DashboardPreference_ID, String trxName) @@ -175,6 +175,25 @@ public class X_PA_DashboardPreference extends PO implements I_PA_DashboardPrefer return ii.intValue(); } + /** Set Flex Grow. + @param FlexGrow This defines the ability for a flex item to grow if necessary. It accepts a unitless value that serves as a proportion. It dictates what amount of the available space inside the flex container the item should take up. + */ + public void setFlexGrow (int FlexGrow) + { + set_Value (COLUMNNAME_FlexGrow, Integer.valueOf(FlexGrow)); + } + + /** Get Flex Grow. + @return This defines the ability for a flex item to grow if necessary. It accepts a unitless value that serves as a proportion. It dictates what amount of the available space inside the flex container the item should take up. + */ + public int getFlexGrow() + { + Integer ii = (Integer)get_Value(COLUMNNAME_FlexGrow); + if (ii == null) + return 0; + return ii.intValue(); + } + /** Set Collapsed By Default. @param IsCollapsedByDefault Flag to set the initial state of collapsible field group. */ diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/DashboardRunnable.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/DashboardRunnable.java index 2c12a404bd..781c2c6b0f 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/DashboardRunnable.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/DashboardRunnable.java @@ -75,12 +75,17 @@ public class DashboardRunnable implements Runnable, Serializable desktop = null; } + /** + * @param tmp + * @param desktop + */ public DashboardRunnable(DashboardRunnable tmp, Desktop desktop) { this(desktop); this.dashboardPanels = tmp.dashboardPanels; tmp.cleanup(); } + @Override public void run() { if (dashboardPanels != null && desktop != null && desktop.get() != null diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/DashboardController.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/DashboardController.java index b53241eb3e..043bc2e243 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/DashboardController.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/DashboardController.java @@ -89,6 +89,7 @@ import org.zkoss.zul.Anchorchildren; import org.zkoss.zul.Anchorlayout; import org.zkoss.zul.Caption; import org.zkoss.zul.Div; +import org.zkoss.zul.Hlayout; import org.zkoss.zul.Html; import org.zkoss.zul.Iframe; import org.zkoss.zul.Include; @@ -106,25 +107,38 @@ import org.zkoss.zul.Vlayout; */ public class DashboardController implements EventListener { - /** Logger */ - protected transient CLogger log = CLogger.getCLogger (getClass()); - - private static final String PANEL_EMPTY_ATTR = "panel.empty"; private final static CLogger logger = CLogger.getCLogger(DashboardController.class); + //original parent and sibling for maximized gadget private Component prevParent; private Component prevNext; private List panelList = new ArrayList(); private List columnList; + private List rowList; private Anchorlayout dashboardLayout; private Anchorchildren maximizedHolder; private DashboardRunnable dashboardRunnable; private Timer dashboardTimer; private boolean isShowInDashboard; private int noOfCols; - + + private static final String PANEL_EMPTY_ATTRIBUTE = "panel.empty"; + private static final String COLUMN_NO_ATTRIBUTE = "ColumnNo"; + private static final String LINE_ATTRIBUTE = "Line"; + private static final String IS_ADDITIONAL_ROW_ATTRIBUTE = "IsAdditionalRow"; + private static final String IS_ADDITIONAL_COLUMN_ATTRIBUTE = "IsAdditionalColumn"; + private static final String IS_SHOW_IN_DASHBOARD_ATTRIBUTE = "IsShowInDashboard"; + private static final String FLEX_GROW_ATTRIBUTE = "FlexGrow"; + private final static int DEFAULT_DASHBOARD_WIDTH = 99; + private final static String DASHBOARD_LAYOUT_COLUMNS = "C"; + private final static String DASHBOARD_LAYOUT_ROWS = "R"; + private final static int MAX_NO_OF_PREFS_IN_ROW = 10; + private final static int DEFAULT_FLEX_GROW = 1; + /** + * default constructor + */ public DashboardController() { dashboardLayout = new Anchorlayout(); dashboardLayout.setSclass("dashboard-layout"); @@ -136,11 +150,21 @@ public class DashboardController implements EventListener { maximizedHolder.setStyle("overflow: hidden; border: none; margin: 0; padding: 0;"); } + /** + * + * @param parent + * @param desktopImpl + * @param isShowInDashboard + */ public void render(Component parent, IDesktop desktopImpl, boolean isShowInDashboard) { - render(parent, desktopImpl, isShowInDashboard, false); + String layoutOrientation = MSysConfig.getValue(MSysConfig.DASHBOARD_LAYOUT_ORIENTATION, Env.getAD_Client_ID(Env.getCtx())); + if(layoutOrientation.equals(DASHBOARD_LAYOUT_ROWS) && isShowInDashboard) + renderRows(parent, desktopImpl, isShowInDashboard, false); + else + renderColumns(parent, desktopImpl, isShowInDashboard, false); } - protected void render(Component parent, IDesktop desktopImpl, boolean isShowInDashboard, boolean update) { + protected void renderColumns(Component parent, IDesktop desktopImpl, boolean isShowInDashboard, boolean update) { this.isShowInDashboard = isShowInDashboard; if (!update) parent.appendChild(dashboardLayout); @@ -168,15 +192,15 @@ public class DashboardController implements EventListener { int AD_User_ID = Env.getAD_User_ID(Env.getCtx()); int AD_Role_ID = Env.getAD_Role_ID(Env.getCtx()); - MDashboardPreference[] dps = MDashboardPreference.getForSession(AD_User_ID, AD_Role_ID); + MDashboardPreference[] dps = MDashboardPreference.getForSession(AD_User_ID, AD_Role_ID, true); MDashboardContent [] dcs = MDashboardContentAccess.get(Env.getCtx(), AD_Role_ID, AD_User_ID, null); if(dps.length == 0){ createDashboardPreference(AD_User_ID, AD_Role_ID); - dps = MDashboardPreference.getForSession(AD_User_ID, AD_Role_ID); + dps = MDashboardPreference.getForSession(AD_User_ID, AD_Role_ID, true); }else{ if(updatePreferences(dps, dcs,Env.getCtx())){ - dps = MDashboardPreference.getForSession(AD_User_ID, AD_Role_ID); + dps = MDashboardPreference.getForSession(AD_User_ID, AD_Role_ID, true); } } @@ -213,9 +237,9 @@ public class DashboardController implements EventListener { { dashboardColumnLayout = new Vlayout(); dashboardColumnLayout.setSclass("dashboard-column"); - dashboardColumnLayout.setAttribute("ColumnNo", columnNo); - dashboardColumnLayout.setAttribute("IsShowInDashboard", isShowInDashboard); - dashboardColumnLayout.setAttribute("IsAdditionalColumn", false); + dashboardColumnLayout.setAttribute(COLUMN_NO_ATTRIBUTE, columnNo); + dashboardColumnLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard); + dashboardColumnLayout.setAttribute(IS_ADDITIONAL_COLUMN_ATTRIBUTE, false); Anchorchildren dashboardColumn = new Anchorchildren(); dashboardColumn.setAnchor(width + "%" + " 100%"); if (!ClientInfo.isMobile()) @@ -235,54 +259,21 @@ public class DashboardController implements EventListener { if (update) { panel = findPanel(dp.getPA_DashboardContent_ID(), dp.getPA_DashboardPreference_ID()); } else { - panel = new Panel(); - Caption caption = new Caption(dc.get_Translation(MDashboardContent.COLUMNNAME_Name)); - panel.appendChild(caption); - panel.setAttribute("PA_DashboardContent_ID", dp.getPA_DashboardContent_ID()); - panel.setAttribute("PA_DashboardPreference_ID", dp.getPA_DashboardPreference_ID()); - panelList.add(panel); - panel.addEventListener(Events.ON_MAXIMIZE, this); - panel.setSclass("dashboard-widget"); - panel.setMaximizable(true); - - String description = dc.get_Translation(MDashboardContent.COLUMNNAME_Description); - if(description != null) - panel.setTooltiptext(description); - - panel.setCollapsible(dc.isCollapsible()); - panel.setOpen(!dp.isCollapsedByDefault()); - panel.addEventListener(Events.ON_OPEN, this); - - if (!ClientInfo.isMobile()) { - panel.setDroppable("true"); - panel.getCaption().setDraggable("true"); - panel.addEventListener(Events.ON_DROP, this); - } - panel.setBorder("normal"); + panel = newGadgetPanel(dp, dc); } - if (panel != null && panel.getAttribute(PANEL_EMPTY_ATTR) == null) + if (panel != null && panel.getAttribute(PANEL_EMPTY_ATTRIBUTE) == null) dashboardColumnLayout.appendChild(panel); if (!update) { - Panelchildren content = new Panelchildren(); - panel.appendChild(content); - - boolean panelEmpty = true; - - panelEmpty = !render(content, dc, dashboardRunnable); - - if (panelEmpty) { - panel.detach(); - panel.setAttribute(PANEL_EMPTY_ATTR, Boolean.TRUE); - } + renderGadgetPanel(dc, panel); } } if (dps.length == 0) { dashboardColumnLayout = new Vlayout(); - dashboardColumnLayout.setAttribute("ColumnNo", "0"); - dashboardColumnLayout.setAttribute("IsShowInDashboard", isShowInDashboard); - dashboardColumnLayout.setAttribute("IsAdditionalColumn", true); + dashboardColumnLayout.setAttribute(COLUMN_NO_ATTRIBUTE, "0"); + dashboardColumnLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard); + dashboardColumnLayout.setAttribute(IS_ADDITIONAL_COLUMN_ATTRIBUTE, true); Anchorchildren dashboardColumn = new Anchorchildren(); dashboardColumn.setAnchor((width-5) + "%" + " 100%"); if (!ClientInfo.isMobile()) @@ -300,9 +291,9 @@ public class DashboardController implements EventListener { // additional column dashboardColumnLayout = new Vlayout(); ZKUpdateUtil.setWidth(dashboardColumnLayout, "100%"); - dashboardColumnLayout.setAttribute("ColumnNo", currentColumnNo + 1); - dashboardColumnLayout.setAttribute("IsShowInDashboard", isShowInDashboard); - dashboardColumnLayout.setAttribute("IsAdditionalColumn", true); + dashboardColumnLayout.setAttribute(COLUMN_NO_ATTRIBUTE, currentColumnNo + 1); + dashboardColumnLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard); + dashboardColumnLayout.setAttribute(IS_ADDITIONAL_COLUMN_ATTRIBUTE, true); Anchorchildren dashboardColumn = new Anchorchildren(); dashboardColumn.setAnchor(extraWidth + "% 100%"); if (!ClientInfo.isMobile()) @@ -324,29 +315,227 @@ public class DashboardController implements EventListener { if (!update && !dashboardRunnable.isEmpty()) { - dashboardRunnable.refreshDashboard(false); - - // default Update every one minutes - int interval = MSysConfig.getIntValue(MSysConfig.ZK_DASHBOARD_REFRESH_INTERVAL, 60000); - dashboardTimer = new Timer(); - dashboardTimer.setDelay(interval); - dashboardTimer.setRepeats(true); - dashboardTimer.addEventListener(Events.ON_TIMER, new EventListener() { - @Override - public void onEvent(Event event) throws Exception { - if (dashboardRunnable != null && !dashboardRunnable.isEmpty()) { - dashboardRunnable.run(); - } - } - }); - dashboardTimer.setPage(parent.getPage()); + startDashboardRunnable(parent); } } + private Panel newGadgetPanel(MDashboardPreference dp, MDashboardContent dc) { + Panel panel; + panel = new Panel(); + Caption caption = new Caption(dc.get_Translation(MDashboardContent.COLUMNNAME_Name)); + panel.appendChild(caption); + panel.setAttribute(MDashboardPreference.COLUMNNAME_PA_DashboardContent_ID, dp.getPA_DashboardContent_ID()); + panel.setAttribute(MDashboardPreference.COLUMNNAME_PA_DashboardPreference_ID, dp.getPA_DashboardPreference_ID()); + panelList.add(panel); + panel.addEventListener(Events.ON_MAXIMIZE, this); + panel.setSclass("dashboard-widget"); + panel.setMaximizable(true); + + String description = dc.get_Translation(MDashboardContent.COLUMNNAME_Description); + if(description != null) + panel.setTooltiptext(description); + + panel.setCollapsible(dc.isCollapsible()); + panel.setOpen(!dp.isCollapsedByDefault()); + panel.addEventListener(Events.ON_OPEN, this); + if (!ClientInfo.isMobile()) { + panel.setDroppable("true"); + panel.getCaption().setDraggable("true"); + panel.addEventListener(Events.ON_DROP, this); + } + panel.setBorder("normal"); + + return panel; + } + + private void renderGadgetPanel(MDashboardContent dc, Panel panel) throws Exception { + Panelchildren content = new Panelchildren(); + panel.appendChild(content); + boolean panelEmpty = true; + panelEmpty = !render(content, dc, dashboardRunnable); + if (panelEmpty) { + panel.detach(); + panel.setAttribute(PANEL_EMPTY_ATTRIBUTE, Boolean.TRUE); + } + } + + private void startDashboardRunnable(Component parent) { + dashboardRunnable.refreshDashboard(false); + // default Update every one minutes + int interval = MSysConfig.getIntValue(MSysConfig.ZK_DASHBOARD_REFRESH_INTERVAL, 60000); + dashboardTimer = new Timer(); + dashboardTimer.setDelay(interval); + dashboardTimer.setRepeats(true); + dashboardTimer.addEventListener(Events.ON_TIMER, new EventListener() { + @Override + public void onEvent(Event event) throws Exception { + if (dashboardRunnable != null && !dashboardRunnable.isEmpty()) { + dashboardRunnable.run(); + } + } + }); + dashboardTimer.setPage(parent.getPage()); + } + + protected void renderRows(Component parent, IDesktop desktopImpl, boolean isShowInDashboard, boolean update) { + this.isShowInDashboard = isShowInDashboard; + if (!update) + parent.appendChild(dashboardLayout); + if (!update && isShowInDashboard) + ((HtmlBasedComponent)parent).setStyle("overflow-x: auto;"); + dashboardLayout.getChildren().clear(); + + if (!dashboardLayout.getDesktop().isServerPushEnabled()) + dashboardLayout.getDesktop().enableServerPush(true); + + if (!update) + dashboardRunnable = new DashboardRunnable(parent.getDesktop()); + + rowList = new ArrayList(); + + // Dashboard content + Hlayout dashboardLineLayout = null; + int currentLineNo = 0; + int noOfLines = 0; + int width = 100; + try + { + int AD_User_ID = Env.getAD_User_ID(Env.getCtx()); + int AD_Role_ID = Env.getAD_Role_ID(Env.getCtx()); + + MDashboardPreference[] dps = MDashboardPreference.getForSession(AD_User_ID, AD_Role_ID, false); + MDashboardContent [] dcs = MDashboardContentAccess.get(Env.getCtx(), AD_Role_ID, AD_User_ID, null); + + if(dps.length == 0){ + createDashboardPreference(AD_User_ID, AD_Role_ID); + dps = MDashboardPreference.getForSession(AD_User_ID, AD_Role_ID, false); + }else{ + if(updatePreferences(dps, dcs,Env.getCtx())){ + dps = MDashboardPreference.getForSession(AD_User_ID, AD_Role_ID, false); + } + } + + noOfLines = MDashboardPreference.getForSessionRowCount(isShowInDashboard, AD_User_ID, AD_Role_ID); + if (ClientInfo.isMobile() && isShowInDashboard) { + if (ClientInfo.maxWidth(ClientInfo.MEDIUM_WIDTH-1)) { + if (ClientInfo.maxWidth(ClientInfo.SMALL_WIDTH-1)) { + noOfLines = 1; + } else if (noOfLines > 2) { + noOfLines = 2; + } + } + } + + for (final MDashboardPreference dp : dps) + { + if(!dp.isActive()) + continue; + + if (dp.isShowInDashboard() != isShowInDashboard) + continue; + + MDashboardContent dc = new MDashboardContent(dp.getCtx(), dp.getPA_DashboardContent_ID(), dp.get_TrxName()); + + int lineNo = dp.getLine().intValue(); + + int flexGrow = (flexGrow = dp.getFlexGrow()) > 0 ? flexGrow : DEFAULT_FLEX_GROW; + if(dashboardLineLayout == null || currentLineNo != lineNo) + { + dashboardLineLayout = new Hlayout(); + dashboardLineLayout.setAttribute(LINE_ATTRIBUTE, lineNo); + dashboardLineLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard); + dashboardLineLayout.setAttribute(IS_ADDITIONAL_ROW_ATTRIBUTE, false); + dashboardLineLayout.setSclass("dashboard-row"); + Anchorchildren dashboardLine = new Anchorchildren(); + dashboardLine.setAnchor(width + "%"); + ZKUpdateUtil.setHflex(dashboardLine, "min"); + if (!ClientInfo.isMobile()) + { + dashboardLine.setDroppable("true"); + dashboardLine.addEventListener(Events.ON_DROP, this); + } + dashboardLine.appendChild(dashboardLineLayout); + rowList.add(dashboardLine); + dashboardLayout.appendChild(dashboardLine); + currentLineNo = lineNo; + } + + Panel panel = null; + if (update) { + panel = findPanel(dp.getPA_DashboardContent_ID(), dp.getPA_DashboardPreference_ID()); + } else { + panel = newGadgetPanel(dp, dc); + panel.setAttribute(FLEX_GROW_ATTRIBUTE, String.valueOf(flexGrow)); + ZKUpdateUtil.setHflex(panel, String.valueOf(flexGrow)); + ZKUpdateUtil.setHeight(panel, "100%"); + } + if (panel != null && panel.getAttribute(PANEL_EMPTY_ATTRIBUTE) == null) { + dashboardLineLayout.appendChild(panel); + } + if (!update) { + renderGadgetPanel(dc, panel); + } + } + + if (dps.length == 0) + { + dashboardLineLayout = new Hlayout(); + dashboardLineLayout.setAttribute(LINE_ATTRIBUTE, "0"); + dashboardLineLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard); + dashboardLineLayout.setAttribute(IS_ADDITIONAL_ROW_ATTRIBUTE, true); + dashboardLineLayout.setSclass("dashboard-row"); + Anchorchildren dashboardColumn = new Anchorchildren(); + dashboardColumn.setAnchor((width-5) + "%" + " 100%"); + if (!ClientInfo.isMobile()) + { + dashboardColumn.setDroppable("true"); + dashboardColumn.addEventListener(Events.ON_DROP, this); + } + dashboardColumn.appendChild(dashboardLineLayout); + rowList.add(dashboardColumn); + dashboardLayout.appendChild(dashboardColumn); + ZKUpdateUtil.setWidth(dashboardLineLayout, "100%"); + } + else if (isShowInDashboard) + { + // additional row + dashboardLineLayout = new Hlayout(); + ZKUpdateUtil.setWidth(dashboardLineLayout, "100%"); + dashboardLineLayout.setAttribute(LINE_ATTRIBUTE, currentLineNo + 1); + dashboardLineLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard); + dashboardLineLayout.setAttribute(IS_ADDITIONAL_ROW_ATTRIBUTE, true); + dashboardLineLayout.setSclass("dashboard-row"); + Anchorchildren dashboardLine = new Anchorchildren(); + dashboardLine.setAnchor(width + "% 10%"); + ZKUpdateUtil.setHflex(dashboardLine, "min"); + if (!ClientInfo.isMobile()) + { + dashboardLine.setDroppable("true"); + dashboardLine.addEventListener(Events.ON_DROP, this); + } + dashboardLine.appendChild(dashboardLineLayout); + rowList.add(dashboardLine); + dashboardLayout.appendChild(dashboardLine); + ZKUpdateUtil.setWidth(dashboardLineLayout, "100%"); + ZKUpdateUtil.setHflex(dashboardLineLayout, "1"); + } + } + catch (Exception e) + { + logger.log(Level.WARNING, "Failed to create dashboard content", e); + } + // + + if (!update && !dashboardRunnable.isEmpty()) + { + startDashboardRunnable(parent); + } + } + private Panel findPanel(int PA_DashboardContent_ID, int PA_DashboardPreference_ID) { for(Panel panel : panelList) { - Object value1 = panel.getAttribute("PA_DashboardContent_ID"); - Object value2 = panel.getAttribute("PA_DashboardPreference_ID"); + Object value1 = panel.getAttribute(MDashboardPreference.COLUMNNAME_PA_DashboardContent_ID); + Object value2 = panel.getAttribute(MDashboardPreference.COLUMNNAME_PA_DashboardPreference_ID); if (value1 != null && value1 instanceof Number && value2 != null && value2 instanceof Number) { int id1 = ((Number)value1).intValue(); int id2 = ((Number)value2).intValue(); @@ -357,6 +546,14 @@ public class DashboardController implements EventListener { return null; } + /** + * + * @param content + * @param dc + * @param dashboardRunnable + * @return + * @throws Exception + */ public boolean render(Component content, MDashboardContent dc, DashboardRunnable dashboardRunnable) throws Exception { boolean empty = true; @@ -389,9 +586,6 @@ public class DashboardController implements EventListener { } } result.append("
\n"); - -// if(description != null) -// result.append("

" + description + "

\n"); result.append(stripHtml(htmlContent, false) + "
\n"); result.append("
\n\n"); @@ -517,8 +711,7 @@ public class DashboardController implements EventListener { DashboardPanel dashboardPanel = (DashboardPanel) component; if (!dashboardPanel.getChildren().isEmpty()) { content.appendChild(dashboardPanel); - if (dashboardRunnable != null) - dashboardRunnable.add(dashboardPanel); + addDashboardPanel(dashboardPanel); empty = false; } } @@ -568,7 +761,10 @@ public class DashboardController implements EventListener { statusLineHtml.setContent(sl.parseLine(0)); Div div = new Div(); div.appendChild(statusLineHtml); - div.setSclass("statusline-gadget"); + if(content instanceof HtmlBasedComponent) + ((HtmlBasedComponent) content).setSclass("statusline-gadget"); + else + div.setSclass("statusline-gadget"); content.appendChild(div); empty = false; } @@ -576,9 +772,14 @@ public class DashboardController implements EventListener { return !empty; } + @Override public void onEvent(Event event) throws Exception { Component comp = event.getTarget(); String eventName = event.getName(); + String layoutOrientation = MSysConfig.getValue(MSysConfig.DASHBOARD_LAYOUT_ORIENTATION, Env.getAD_Client_ID(Env.getCtx())); + + if(!layoutOrientation.equals(DASHBOARD_LAYOUT_ROWS) && !layoutOrientation.equals(DASHBOARD_LAYOUT_COLUMNS)) + layoutOrientation = DASHBOARD_LAYOUT_COLUMNS; if (event instanceof MaximizeEvent) { @@ -588,8 +789,15 @@ public class DashboardController implements EventListener { prevParent = panel.getParent(); prevNext = panel.getNextSibling(); panel.detach(); - for (Anchorchildren anchorChildren : columnList) { - anchorChildren.detach(); + if(columnList != null) { + for (Anchorchildren anchorChildren : columnList) { + anchorChildren.detach(); + } + } + else { + for (Anchorchildren anchorChildren : rowList) { + anchorChildren.detach(); + } } dashboardLayout.appendChild(maximizedHolder); maximizedHolder.appendChild(panel); @@ -598,13 +806,20 @@ public class DashboardController implements EventListener { maximizedHolder.detach(); panel.detach(); prevParent.insertBefore(panel, prevNext); - for (Anchorchildren anchorChildren : columnList) { - dashboardLayout.appendChild(anchorChildren); + if(columnList != null) { + for (Anchorchildren anchorChildren : columnList) { + dashboardLayout.appendChild(anchorChildren); + } + } + else { + for (Anchorchildren anchorChildren : rowList) { + dashboardLayout.appendChild(anchorChildren); + } } panel.setSclass("dashboard-widget"); //following 2 line needed for restore to size the panel correctly - ZKUpdateUtil.setWidth(panel, null); - ZKUpdateUtil.setHeight(panel, null); + ZKUpdateUtil.setHflex(panel, (String)panel.getAttribute(FLEX_GROW_ATTRIBUTE)); + ZKUpdateUtil.setHeight(panel, "100%"); } } else if(eventName.equals(Events.ON_CLICK)) @@ -645,22 +860,52 @@ public class DashboardController implements EventListener { { Panel target = (Panel) comp; - if (target.getParent() != null && target.getParent() instanceof Vlayout) + boolean isParentHVlayout = false; + if(layoutOrientation.equals(DASHBOARD_LAYOUT_ROWS)) + isParentHVlayout = target.getParent() instanceof Hlayout; + else + isParentHVlayout = target.getParent() instanceof Vlayout; + + if (target.getParent() != null && isParentHVlayout) { - Vlayout dashboardColumnLayout = (Vlayout) target.getParent(); + Component dashboardColumnLayout; + if(layoutOrientation.equals(DASHBOARD_LAYOUT_ROWS)) { + dashboardColumnLayout = (Hlayout) target.getParent(); + List children = dashboardColumnLayout.getParent().getChildren(); + if(children != null && (children.size() >= MAX_NO_OF_PREFS_IN_ROW)) + return; + } + else + dashboardColumnLayout = (Vlayout) target.getParent(); + Component prevParent = panel.getParent(); dashboardColumnLayout.insertBefore(panel, target); - saveDashboardPreference(dashboardColumnLayout); + saveDashboardPreference(dashboardColumnLayout, prevParent); } } else if (comp instanceof Anchorchildren) { - Anchorchildren target = (Anchorchildren) comp; + Anchorchildren target = (Anchorchildren) comp; - if (target.getFirstChild() != null && target.getFirstChild() instanceof Vlayout) + boolean isFirstChildHVlayout = false; + if(layoutOrientation.equals(DASHBOARD_LAYOUT_ROWS)) { + isFirstChildHVlayout = target.getFirstChild() instanceof Hlayout; + List children = target.getChildren(); + if(children != null && (children.size() >= MAX_NO_OF_PREFS_IN_ROW)) + return; + } + else + isFirstChildHVlayout = target.getFirstChild() instanceof Vlayout; + + if (target.getFirstChild() != null && isFirstChildHVlayout) { - Vlayout dashboardColumnLayout = (Vlayout) target.getFirstChild(); + Component dashboardColumnLayout; + if(layoutOrientation.equals(DASHBOARD_LAYOUT_ROWS)) + dashboardColumnLayout = (Hlayout) target.getFirstChild(); + else + dashboardColumnLayout = (Vlayout) target.getFirstChild(); + Component prevParent = panel.getParent(); dashboardColumnLayout.appendChild(panel); - saveDashboardPreference(dashboardColumnLayout); + saveDashboardPreference(dashboardColumnLayout, prevParent); } } } @@ -670,7 +915,7 @@ public class DashboardController implements EventListener { if(comp instanceof Panel) { Panel panel = (Panel) comp; - Object value = panel.getAttribute("PA_DashboardPreference_ID"); + Object value = panel.getAttribute(MDashboardPreference.COLUMNNAME_PA_DashboardPreference_ID); if (value != null) { int PA_DashboardPreference_ID = Integer.parseInt(value.toString()); @@ -749,82 +994,184 @@ public class DashboardController implements EventListener { return change; } - private void saveDashboardPreference(Vlayout layout) + private void saveDashboardPreference(Component layout, Component prevLayout) { - Object value = layout.getAttribute("ColumnNo"); - if (value != null) - { - int columnNo = Integer.parseInt(value.toString()); - - value = layout.getAttribute("IsShowInDashboard"); + String layoutOrientation = MSysConfig.getValue(MSysConfig.DASHBOARD_LAYOUT_ORIENTATION, Env.getAD_Client_ID(Env.getCtx())); + if(layoutOrientation.equals(DASHBOARD_LAYOUT_COLUMNS)) { + Object value = layout.getAttribute(COLUMN_NO_ATTRIBUTE); if (value != null) { - boolean isShowInDashboard = Boolean.parseBoolean(value.toString()); - - List children = layout.getChildren(); - int counter = 0; - for (Component child : children) - { - if (child instanceof Panel) - { - Panel panel = (Panel) child; - value = panel.getAttribute("PA_DashboardPreference_ID"); - if (value != null) - { - ++counter; - - int PA_DashboardPreference_ID = Integer.parseInt(value.toString()); - MDashboardPreference preference = new MDashboardPreference(Env.getCtx(), PA_DashboardPreference_ID, null); - preference.setColumnNo(columnNo); - preference.setLine(new BigDecimal(counter * 10)); - preference.setIsShowInDashboard(isShowInDashboard); - if (!preference.save()) - logger.log(Level.SEVERE, "Failed to save dashboard preference " + preference.toString()); - } - } - } + int columnNo = Integer.parseInt(value.toString()); - if (isShowInDashboard) + value = layout.getAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE); + if (value != null) { - value = layout.getAttribute("IsAdditionalColumn"); - if (value != null) + boolean isShowInDashboard = Boolean.parseBoolean(value.toString()); + + List children = layout.getChildren(); + int counter = 0; + for (Component child : children) { - boolean isAdditionalColumn = Boolean.parseBoolean(value.toString()); - if (isAdditionalColumn) + if (child instanceof Panel) { - layout.setAttribute("IsAdditionalColumn", false); - - int noOfCols = columnList.size(); - int dashboardWidth = DEFAULT_DASHBOARD_WIDTH; - int width = noOfCols <= 0 ? dashboardWidth : dashboardWidth / noOfCols; - int extraWidth = 100 - (noOfCols <= 0 ? dashboardWidth : width * noOfCols) - (100 - dashboardWidth - 1); - - for (Anchorchildren column : columnList) - column.setAnchor(width + "%" + " 100%"); - - // additional column - Vlayout dashboardColumnLayout = new Vlayout(); - dashboardColumnLayout.setAttribute("ColumnNo", columnNo + 1); - dashboardColumnLayout.setAttribute("IsShowInDashboard", isShowInDashboard); - dashboardColumnLayout.setAttribute("IsAdditionalColumn", true); - Anchorchildren dashboardColumn = new Anchorchildren(); - dashboardColumn.setAnchor(extraWidth + "% 100%"); - if (!ClientInfo.isMobile()) { - dashboardColumn.setDroppable("true"); - dashboardColumn.addEventListener(Events.ON_DROP, this); - } - dashboardColumn.appendChild(dashboardColumnLayout); - columnList.add(dashboardColumn); - dashboardLayout.appendChild(dashboardColumn); - ZKUpdateUtil.setWidth(dashboardColumnLayout, "100%"); - - dashboardLayout.invalidate(); + Panel panel = (Panel) child; + value = panel.getAttribute(MDashboardPreference.COLUMNNAME_PA_DashboardPreference_ID); + if (value != null) + { + ++counter; + + int PA_DashboardPreference_ID = Integer.parseInt(value.toString()); + MDashboardPreference preference = new MDashboardPreference(Env.getCtx(), PA_DashboardPreference_ID, null); + preference.setColumnNo(columnNo); + preference.setLine(new BigDecimal(counter * 10)); + preference.setIsShowInDashboard(isShowInDashboard); + if (!preference.save()) + logger.log(Level.SEVERE, "Failed to save dashboard preference " + preference.toString()); + } } } + + if (isShowInDashboard) + { + value = layout.getAttribute(IS_ADDITIONAL_COLUMN_ATTRIBUTE); + if (value != null) + { + boolean isAdditionalColumn = Boolean.parseBoolean(value.toString()); + if (isAdditionalColumn) + { + layout.setAttribute(IS_ADDITIONAL_COLUMN_ATTRIBUTE, false); + + int noOfCols = columnList.size(); + int dashboardWidth = DEFAULT_DASHBOARD_WIDTH; + int width = noOfCols <= 0 ? dashboardWidth : dashboardWidth / noOfCols; + int extraWidth = 100 - (noOfCols <= 0 ? dashboardWidth : width * noOfCols) - (100 - dashboardWidth - 1); + + for (Anchorchildren column : columnList) + column.setAnchor(width + "%" + " 100%"); + + // additional column + Vlayout dashboardColumnLayout = new Vlayout(); + dashboardColumnLayout.setAttribute(COLUMN_NO_ATTRIBUTE, columnNo + 1); + dashboardColumnLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard); + dashboardColumnLayout.setAttribute(IS_ADDITIONAL_COLUMN_ATTRIBUTE, true); + Anchorchildren dashboardColumn = new Anchorchildren(); + dashboardColumn.setAnchor(extraWidth + "% 100%"); + if (!ClientInfo.isMobile()) { + dashboardColumn.setDroppable("true"); + dashboardColumn.addEventListener(Events.ON_DROP, this); + } + dashboardColumn.appendChild(dashboardColumnLayout); + columnList.add(dashboardColumn); + dashboardLayout.appendChild(dashboardColumn); + ZKUpdateUtil.setWidth(dashboardColumnLayout, "100%"); + + dashboardLayout.invalidate(); + } + } + } + + if (!dashboardRunnable.isEmpty()) + dashboardRunnable.refreshDashboard(false); } + } + } + else { + + // detach row if empty + if(prevLayout != null) { + if((prevLayout.getChildren() == null) || (prevLayout.getChildren().size() <= 0)) + prevLayout.getParent().detach(); + } + + Object value = layout.getAttribute(LINE_ATTRIBUTE); + if (value != null) + { + int lineNo = Integer.parseInt(value.toString()); - if (!dashboardRunnable.isEmpty()) - dashboardRunnable.refreshDashboard(false); + value = layout.getAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE); + if (value != null) + { + boolean isShowInDashboard = Boolean.parseBoolean(value.toString()); + + List children = layout.getChildren(); + int counter = 0; + for (Component child : children) + { + if (child instanceof Panel) + { + Panel panel = (Panel) child; + value = panel.getAttribute(MDashboardPreference.COLUMNNAME_PA_DashboardPreference_ID); + if (value != null) + { + int PA_DashboardPreference_ID = Integer.parseInt(value.toString()); + MDashboardPreference preference = new MDashboardPreference(Env.getCtx(), PA_DashboardPreference_ID, null); + preference.setColumnNo(counter++); + preference.setLine(new BigDecimal(lineNo)); + preference.setIsShowInDashboard(isShowInDashboard); + if (!preference.save()) + logger.log(Level.SEVERE, "Failed to save dashboard preference " + preference.toString()); + if(layout instanceof Hlayout) { + int flexGrow = (flexGrow = preference.getFlexGrow()) > 0 ? flexGrow : DEFAULT_FLEX_GROW; + ZKUpdateUtil.setHflex(panel, String.valueOf(flexGrow)); + } + } + } + } + + if (isShowInDashboard) + { + value = layout.getAttribute(IS_ADDITIONAL_ROW_ATTRIBUTE); + if (value != null) + { + boolean isAdditionalRow = Boolean.parseBoolean(value.toString()); + if (isAdditionalRow) + { + if(layout instanceof Hlayout) { + Anchorchildren anchorCh = ((Anchorchildren) layout.getParent()); + Component parent = anchorCh.getParent(); + rowList.remove(anchorCh); + anchorCh.detach(); + anchorCh = new Anchorchildren("100%"); + ZKUpdateUtil.setHflex(anchorCh, "min"); + if (!ClientInfo.isMobile()) + { + anchorCh.setDroppable("true"); + anchorCh.addEventListener(Events.ON_DROP, this); + } + rowList.add(anchorCh); + anchorCh.appendChild(layout); + parent.appendChild(anchorCh); + } + layout.setAttribute(IS_ADDITIONAL_ROW_ATTRIBUTE, false); + int width = 100; + + // additional row + Hlayout dashboardLineLayout = new Hlayout(); + ZKUpdateUtil.setWidth(dashboardLineLayout, "100%"); + dashboardLineLayout.setAttribute(LINE_ATTRIBUTE, lineNo + 1); + dashboardLineLayout.setAttribute(IS_SHOW_IN_DASHBOARD_ATTRIBUTE, isShowInDashboard); + dashboardLineLayout.setAttribute(IS_ADDITIONAL_ROW_ATTRIBUTE, true); + dashboardLineLayout.setSclass("dashboard-row"); + Anchorchildren dashboardLine = new Anchorchildren(); + dashboardLine.setAnchor(width + "% 10%"); + ZKUpdateUtil.setHflex(dashboardLine, "min"); + if (!ClientInfo.isMobile()) + { + dashboardLine.setDroppable("true"); + dashboardLine.addEventListener(Events.ON_DROP, this); + } + dashboardLine.appendChild(dashboardLineLayout); + rowList.add(dashboardLine); + dashboardLayout.appendChild(dashboardLine); + ZKUpdateUtil.setWidth(dashboardLineLayout, "100%"); + ZKUpdateUtil.setHflex(dashboardLineLayout, "1"); + } + } + } + + if (!dashboardRunnable.isEmpty()) + dashboardRunnable.refreshDashboard(false); + } } } } @@ -858,7 +1205,7 @@ public class DashboardController implements EventListener { dashboardLayout = null; } - public void addDashboardPanel(DashboardPanel dashboardPanel) { + private void addDashboardPanel(DashboardPanel dashboardPanel) { if (dashboardRunnable != null) { dashboardRunnable.add(dashboardPanel); } @@ -917,7 +1264,7 @@ public class DashboardController implements EventListener { } - public AMedia generateReport(int AD_Process_ID, String parameters) throws Exception { + private AMedia generateReport(int AD_Process_ID, String parameters) throws Exception { ReportEngine re = runReport(AD_Process_ID, parameters); File file = FileUtil.createTempFile(re.getName(), ".html"); @@ -1007,7 +1354,7 @@ public class DashboardController implements EventListener { } if( DisplayType.isText(iPara.getDisplayType()) && Util.isEmpty(String.valueOf(value))) { - if (log.isLoggable(Level.FINE)) log.fine(iPara.getParameterName() + " - empty string"); + if (logger.isLoggable(Level.FINE)) logger.fine(iPara.getParameterName() + " - empty string"); break; } @@ -1126,6 +1473,10 @@ public class DashboardController implements EventListener { return Integer.toString(id); } + /** + * + * @param clientInfo + */ public void updateLayout(ClientInfo clientInfo) { if (isShowInDashboard) { if (ClientInfo.isMobile()) { @@ -1138,7 +1489,11 @@ public class DashboardController implements EventListener { } } if (noOfCols > 0 && n > 0 && noOfCols != n) { - render(null, null, true, true); + String layoutOrientation = MSysConfig.getValue(MSysConfig.DASHBOARD_LAYOUT_ORIENTATION, Env.getAD_Client_ID(Env.getCtx())); + if(layoutOrientation.equals(DASHBOARD_LAYOUT_ROWS)) + renderRows(null, null, true, true); + else + renderColumns(null, null, true, true); dashboardLayout.invalidate(); } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/css/fragment/gadget.css.dsp b/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/css/fragment/gadget.css.dsp index ac41007b5e..f548864e0e 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/css/fragment/gadget.css.dsp +++ b/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/css/fragment/gadget.css.dsp @@ -10,6 +10,10 @@ background-image: none; background-color: #FFFFFF; } +.dashboard-widget > .z-panel-body { + height: 100%; +} + .z-panel { border-radius: 5px; border: 1px solid #d8d8d8; @@ -68,6 +72,10 @@ overflow: auto; } +.dashboard-widget > .z-panel-body > .z-panelchildren { + height: 100% !important; +} + .dashboard-report-iframe { min-height:300px; border: 1px solid lightgray; @@ -213,7 +221,9 @@ } .statusline-gadget { - padding: 0px 10px 10px; + display: flex; + justify-content: center; + align-items: center; } .help-content @@ -271,3 +281,11 @@ vertical-align: middle; } <%-- User Favorite Dashboard Panel End --%> + +.z-anchorchildren .z-hlayout { + white-space: normal; +} + +.dashboard-row { + padding-bottom: 5px; +} \ No newline at end of file