IDEMPIERE-5681 - Improve Date Picker by "Ago" option (#1792)

* IDEMPIERE-5681 - Improve Date Picker by "Ago" option

* IDEMPIERE-5681 - improve code readability

- added javadoc, modified method names

* IDEMPIERE-5681 - fix wrong comment
This commit is contained in:
Peter Takács 2023-04-25 10:25:21 +02:00 committed by GitHub
parent 23713f6461
commit 6a94b815cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 218 additions and 42 deletions

View File

@ -0,0 +1,38 @@
-- IDEMPIERE-5681
SELECT register_migration_script('202304201135_IDEMPIERE-5681.sql') FROM dual;
SET SQLBLANKLINES ON
SET DEFINE OFF
-- Apr 20, 2023, 11:35:56 AM CEST
UPDATE AD_Ref_List SET Value='09',Updated=TO_TIMESTAMP('2023-04-20 11:35:56','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=200568
;
-- Apr 20, 2023, 11:36:02 AM CEST
UPDATE AD_Ref_List SET Value='08',Updated=TO_TIMESTAMP('2023-04-20 11:36:02','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=200567
;
-- Apr 20, 2023, 11:36:06 AM CEST
UPDATE AD_Ref_List SET Value='07',Updated=TO_TIMESTAMP('2023-04-20 11:36:06','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=200566
;
-- Apr 20, 2023, 11:36:10 AM CEST
UPDATE AD_Ref_List SET Value='06',Updated=TO_TIMESTAMP('2023-04-20 11:36:10','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=200565
;
-- Apr 20, 2023, 11:36:31 AM CEST
UPDATE AD_Ref_List SET Value='05',Updated=TO_TIMESTAMP('2023-04-20 11:36:31','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=200564
;
-- Apr 20, 2023, 11:36:41 AM CEST
INSERT INTO AD_Ref_List (AD_Ref_List_ID,Name,AD_Reference_ID,Value,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,EntityType,AD_Ref_List_UU) VALUES (200635,'Ago',200217,'04',0,0,'Y',TO_TIMESTAMP('2023-04-20 11:36:41','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-20 11:36:41','YYYY-MM-DD HH24:MI:SS'),100,'D','f6f26e66-3b5e-4d01-a675-74a82dc0bf8c')
;
-- Apr 20, 2023, 12:02:28 PM CEST
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','{0} {1,choice,1#{1}|1<{1}s} Ago',0,0,'Y',TO_TIMESTAMP('2023-04-20 12:02:28','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-20 12:02:28','YYYY-MM-DD HH24:MI:SS'),100,200834,'DatePickerAgo','D','ff71fce9-778d-4ce8-81bc-b6720527b05f')
;
-- Apr 20, 2023, 12:09:09 PM CEST
UPDATE AD_Message SET MsgText='{0} {1}{0,choice,1#|1<s} Ago',Updated=TO_TIMESTAMP('2023-04-20 12:09:09','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200834
;

View File

@ -0,0 +1,35 @@
-- IDEMPIERE-5681
SELECT register_migration_script('202304201135_IDEMPIERE-5681.sql') FROM dual;
-- Apr 20, 2023, 11:35:56 AM CEST
UPDATE AD_Ref_List SET Value='09',Updated=TO_TIMESTAMP('2023-04-20 11:35:56','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=200568
;
-- Apr 20, 2023, 11:36:02 AM CEST
UPDATE AD_Ref_List SET Value='08',Updated=TO_TIMESTAMP('2023-04-20 11:36:02','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=200567
;
-- Apr 20, 2023, 11:36:06 AM CEST
UPDATE AD_Ref_List SET Value='07',Updated=TO_TIMESTAMP('2023-04-20 11:36:06','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=200566
;
-- Apr 20, 2023, 11:36:10 AM CEST
UPDATE AD_Ref_List SET Value='06',Updated=TO_TIMESTAMP('2023-04-20 11:36:10','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=200565
;
-- Apr 20, 2023, 11:36:31 AM CEST
UPDATE AD_Ref_List SET Value='05',Updated=TO_TIMESTAMP('2023-04-20 11:36:31','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=200564
;
-- Apr 20, 2023, 11:36:41 AM CEST
INSERT INTO AD_Ref_List (AD_Ref_List_ID,Name,AD_Reference_ID,Value,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,EntityType,AD_Ref_List_UU) VALUES (200635,'Ago',200217,'04',0,0,'Y',TO_TIMESTAMP('2023-04-20 11:36:41','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-20 11:36:41','YYYY-MM-DD HH24:MI:SS'),100,'D','f6f26e66-3b5e-4d01-a675-74a82dc0bf8c')
;
-- Apr 20, 2023, 12:02:28 PM CEST
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','{0} {1,choice,1#{1}|1<{1}s} Ago',0,0,'Y',TO_TIMESTAMP('2023-04-20 12:02:28','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-04-20 12:02:28','YYYY-MM-DD HH24:MI:SS'),100,200834,'DatePickerAgo','D','ff71fce9-778d-4ce8-81bc-b6720527b05f')
;
-- Apr 20, 2023, 12:09:09 PM CEST
UPDATE AD_Message SET MsgText='{0} {1}{0,choice,1#|1<s} Ago',Updated=TO_TIMESTAMP('2023-04-20 12:09:09','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200834
;

View File

@ -89,12 +89,14 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
private static final String DATESELECTIONMODE_PREVIOUS = "01";
private static final String DATESELECTIONMODE_NEXT = "02";
private static final String DATESELECTIONMODE_CURRENT = "03";
private static final String DATESELECTIONMODE_BEFORE = "04";
private static final String DATESELECTIONMODE_AFTER = "05";
private static final String DATESELECTIONMODE_ON = "06";
private static final String DATESELECTIONMODE_BETWEEN = "07";
private static final String DATESELECTIONMODE_QUICK = "08";
private static final String DATESELECTIONMODE_AGO = "04";
private static final String DATESELECTIONMODE_BEFORE = "05";
private static final String DATESELECTIONMODE_AFTER = "06";
private static final String DATESELECTIONMODE_ON = "07";
private static final String DATESELECTIONMODE_BETWEEN = "08";
private static final String DATESELECTIONMODE_QUICK = "09";
/** UI elements */
private Button okBtn;
private Combobox modeCombobox;
private Spinner numberBox;
@ -147,6 +149,9 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
init();
}
/**
* Initialize elements
*/
private void init() {
editor.addValueChangeListener(this);
@ -301,8 +306,14 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
dateTo = dates[1];
}
updateUI();
}
} // init
/**
* Set picker selection
* @param mode
* @param unit
* @param offset
*/
private void setPickerSelection(String mode, String unit, int offset) {
for(Comboitem item : modeCombobox.getItems()) {
if(item.getValue().equals(mode))
@ -316,8 +327,11 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
numberBox.setValue(numBoxValue);
setDateTextBoxAndDisplayValue();
}
} // setPickerSelection
/**
* Update popup UI
*/
private void updateUI() {
String selectedMode = modeCombobox.getSelectedItem().getValue().toString();
@ -365,6 +379,7 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
break;
case DATESELECTIONMODE_NEXT:
case DATESELECTIONMODE_PREVIOUS:
case DATESELECTIONMODE_AGO:
tabbox.setVisible(false);
numberBox.setVisible(true);
unitCombobox.setVisible(true);
@ -383,7 +398,7 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
default:
break;
}
}
} // updateUI
@Override
public void onEvent(Event event) throws Exception {
@ -408,25 +423,32 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
if(!Util.isEmpty(dateTextBox.getValue()) || !event.getTarget().equals(dateTextBox)) {
setDateTextBoxAndDisplayValue();
}
}
} // onEvent
/**
* Calculate the values of the DateTextBox in the popup and the DisplayValue for Text and Range Picker
*/
private void setDateTextBoxAndDisplayValue() {
displayValue = "";
String dateTextBoxValue = getDateTextBoxValue();
String dateTextBoxValue = parseDateTextBoxValue();
dateTextBox.setValue(dateTextBoxValue);
if(Util.isEmpty(displayValue))
displayValue = dateTextBoxValue;
}
} // setDateTextBoxAndDisplayValue
/**
* @return date range text, for e.g "01/01/2023 - 01/31/2023"
*/
public String getDateRangeText() {
return dateTextBox.getValue();
}
} // getDateRangeText
private String getDateTextBoxValue() {
/**
* Parse the value shown in DateTextBox, set dateFrom and dateTo values
* @return String value shown in DateTextBox
*/
private String parseDateTextBoxValue() {
String returnVal = "";
Date[] dates;
@ -434,10 +456,11 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
case DATESELECTIONMODE_PREVIOUS:
case DATESELECTIONMODE_NEXT:
case DATESELECTIONMODE_CURRENT:
case DATESELECTIONMODE_AGO:
case DATESELECTIONMODE_BEFORE:
case DATESELECTIONMODE_AFTER:
case DATESELECTIONMODE_ON:
returnVal = getIntervalHumanReadable();
returnVal = getIntervalAsString();
break;
case DATESELECTIONMODE_BETWEEN:
returnVal = DisplayType.getDateFormat().format(cal.getValue()) + " - " + DisplayType.getDateFormat().format(cal2.getValue());
@ -465,8 +488,11 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
throw new AdempiereException("InvalidDateSelectionMode");
}
return returnVal;
}
} // parseDateTextBoxValue
/**
* Load the picker selection based on the default date values set with auto-detection
*/
private void loadPickerSelection() {
String detectedMode = null;
@ -505,8 +531,11 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
numberBox.setValue(numBoxValue);
updateCal1AndCal2();
setDateTextBoxAndDisplayValue();
}
} // loadPickerSelection
/**
* Update the picker calendars with current values
*/
private void updateCal1AndCal2() {
if(dateFrom == null) {
cal.setValue(dateTo);
@ -520,8 +549,13 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
cal.setValue(dateFrom);
cal2.setValue(dateTo);
}
}
} // updateCal1AndCal2
/**
* Auto-detect the date selection mode based on the default date values set
* @param today
* @return String date selection mode (value)
*/
private String autodetectMode(Timestamp today) {
Date d1 = dateFrom;
Date d2 = dateTo;
@ -550,8 +584,14 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
}
else
return DATESELECTIONMODE_BETWEEN;
}
} // autodetectMode
/**
* Auto-detect the time unit based on the default date values set, and correct the detected mode if necessary
* @param today
* @param predictedMode
* @return
*/
private String[] autodetectUnitAndCorrectMode(Timestamp today, String predictedMode) {
// use case: modes Before, After, On - unit is not needed
Date d1 = dateFrom;
@ -638,8 +678,14 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
}
return new String[] {detectedUnit, correctedMode};
}
} // autodetectUnitAndCorrectMode
/**
* Auto-detect the time offset based on the default date values set
* @param mode
* @param unit
* @return
*/
private int autodetectOffset(String mode, String unit) {
Date date = dateFrom;
Date date2 = dateTo;
@ -664,9 +710,13 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
if(mode.equalsIgnoreCase(DATESELECTIONMODE_PREVIOUS))
diff = -diff;
return (int) diff;
}
} // autodetectOffset
private String getIntervalHumanReadable() {
/**
* Get the currently selected date interval
* @return String dates separated by " - "
*/
private String getIntervalAsString() {
Timestamp ts = new Timestamp(cal.getValue().getTime());
String mode = modeCombobox.getSelectedItem().getValue().toString();
@ -703,11 +753,14 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
return displayValue;
}
if(mode.equalsIgnoreCase(DATESELECTIONMODE_PREVIOUS))
if(mode.equalsIgnoreCase(DATESELECTIONMODE_PREVIOUS)
|| mode.equalsIgnoreCase(DATESELECTIONMODE_AGO))
numBoxValue = -numBoxValue;
if(mode.equalsIgnoreCase(DATESELECTIONMODE_CURRENT))
dates = getInterval(unit, 0);
else if(mode.equalsIgnoreCase(DATESELECTIONMODE_AGO))
dates = getInterval(unit, unit, numBoxValue.intValue(), false, false, null);
else
dates = getInterval(unit, numBoxValue.intValue());
@ -719,12 +772,29 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
displayValue = datesToHumanReadable(mode, unit, numBoxValue);
return DisplayType.getDateFormat().format(dateFrom) + " - " + DisplayType.getDateFormat().format(dateTo);
}
} // getIntervalAsString
/**
* Calls {@link #getInterval(String, String, int, boolean, boolean, Date) getInterval} method
* @param timeUnit
* @param offset
* @return array of dates: {DateFrom, DateTo}
*/
private Date[] getInterval(String timeUnit, int offset) {
return getInterval(timeUnit, null, offset, false, false, null);
}
} // getInterval
/**
* Calculate time interval based on the selected parameters.
* @param timeUnit - used with the offset parameter to set an exact date-time (e.g. current date-time 1 year ago)
* @param timeUnitForRange - after an exact date-time is set with timeUnit and offset, timeUnitForRange defines what time
* range should be defined around the exact date-time ((e.g. current day/week/month/year 1 year ago))
* @param offset - used with the timeUnit parameter to set an exact date-time (e.g. current date-time 1 year ago)
* @param isToDate - if false, set date from and to to the beginning and end of the given time interval
* @param includeThis - if true, it will include the current date (e.g. return from the beginning of last month until today/until end of last month)
* @param dateFrom - define date from (default now)
* @return array of dates: {DateFrom, DateTo}
*/
private Date[] getInterval(String timeUnit, String timeUnitForRange, int offset, boolean isToDate, boolean includeThis, Date dateFrom) {
if(dateFrom == null)
@ -840,17 +910,35 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
Date date2 = cal2.getTime();
return new Date[] {date1, date2};
}
} // getInterval
/**
* Convert dates to human readable form (e.g. Last Month)
* @param mode
* @param unit
* @param offset
* @return String
*/
private String datesToHumanReadable(String mode, String unit, Integer offset) {
String msgVal = "";
String modeVal = "";
if(offset < 0)
offset = -offset;
if(mode.equalsIgnoreCase(DATESELECTIONMODE_CURRENT))
offset = -1;
String unitVal = "";
for(Comboitem item : unitCombobox.getItems()) {
if(item.getValue().equals(unit))
unitVal = item.getLabel();
}
if(DATESELECTIONMODE_AGO.equals(mode))
return Msg.getMsg(Env.getCtx(), "DatePickerAgo", new Object[] {offset, unitVal});
String msgVal = "";
String modeVal = "";
switch (unit) {
case MChart.TIMEUNIT_Day:
msgVal = "DatePickerDay";
@ -875,8 +963,14 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
modeVal = item.getLabel();
}
return Msg.getMsg(Env.getCtx(), msgVal, new Object[]{modeVal, offset});
}
} // datesToHumanReadable
/**
* Set time on dateFrom: 00:00:00; on dateTo: 23:59:99
* @param dateFrom
* @param dateTo
* @return date array {dateFrom, dateTo}
*/
private Date[] setTimesOnDates(Date dateFrom, Date dateTo) {
Calendar cal = Calendar.getInstance(Env.getLocale(Env.getCtx()));
if(dateFrom != null) {
@ -898,16 +992,28 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
dateTo = new Timestamp(cal.getTime().getTime());
}
return new Date[] {dateFrom, dateTo};
}
} // setTimesOnDates
/**
* Create a ListItem for Quick mode
* @param value
* @param timeUnit
* @param offset
* @param dateFrom
* @return ListItem
*/
private ListItem createItem(String value, String timeUnit, int offset, Date dateFrom) {
ListItem item = new ListItem(value, value);
item.setAttribute("Offset", offset);
item.setAttribute("TimeUnit", timeUnit);
item.setAttribute("DateFrom", dateFrom);
return item;
}
} // createItem
/**
* Initialize Quick mode content
* @return Div
*/
private Div getQuickModeContent() {
Calendar cNow = Calendar.getInstance(Env.getLocale(Env.getCtx()));
@ -1015,7 +1121,7 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
div.appendChild(wrapperDiv2);
return div;
}
} // getQuickModeContent
/**
* Get Display Value
@ -1023,37 +1129,34 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
*/
public String getDisplayValue() {
return this.displayValue;
}
} // getDisplayValue
/**
* Add value change listener
* @param listener
*/
public void addValueChangeListener(ValueChangeListener listener)
{
public void addValueChangeListener(ValueChangeListener listener) {
if (listener == null)
return;
if (!listeners.contains(listener))
listeners.add(listener);
}
} // addValueChangeListener
/**
* Remove value change listener
* @param listener
* @return true if the class had the specified listener
*/
public boolean removeValuechangeListener(ValueChangeListener listener)
{
public boolean removeValuechangeListener(ValueChangeListener listener) {
return listeners.remove(listener);
}
} // removeValuechangeListener
/**
* Fire value change event
* @param event
*/
protected void fireValueChange(ValueChangeEvent event)
{
protected void fireValueChange(ValueChangeEvent event) {
//copy to array to avoid concurrent modification exception
ValueChangeListener[] vcl = new ValueChangeListener[listeners.size()];
listeners.toArray(vcl);
@ -1061,7 +1164,7 @@ public class DateRangePicker extends Popup implements EventListener<Event>, Valu
{
listener.valueChange(event);
}
}
} // fireValueChange
@Override
public void valueChange(ValueChangeEvent evt) {