You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openmeetings.apache.org by so...@apache.org on 2021/06/15 16:21:03 UTC

[openmeetings] branch OPENMEETINGS-2624-datetime created (now 8688850)

This is an automated email from the ASF dual-hosted git repository.

solomax pushed a change to branch OPENMEETINGS-2624-datetime
in repository https://gitbox.apache.org/repos/asf/openmeetings.git.


      at 8688850  [OPENMEETINGS-2624] datetimes should work with custom locales/formats

This branch includes the following new commits:

     new 8688850  [OPENMEETINGS-2624] datetimes should work with custom locales/formats

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[openmeetings] 01/01: [OPENMEETINGS-2624] datetimes should work with custom locales/formats

Posted by so...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

solomax pushed a commit to branch OPENMEETINGS-2624-datetime
in repository https://gitbox.apache.org/repos/asf/openmeetings.git

commit 8688850272965d7d9ac7ad37de80abe9b6be7bc8
Author: Maxim Solodovnik <so...@gmail.com>
AuthorDate: Tue Jun 15 23:19:52 2021 +0700

    [OPENMEETINGS-2624] datetimes should work with custom locales/formats
---
 .../web/common/AbstractOmDateTimePicker.java       |  89 ------------
 .../openmeetings/web/common/GeneralUserForm.java   |   1 +
 .../openmeetings/web/common/InvitationForm.java    |   1 +
 .../common/datetime/AbstractOmDateTimePicker.html  |  27 ++++
 .../common/datetime/AbstractOmDateTimePicker.java  | 153 +++++++++++++++++++++
 .../common/{ => datetime}/AjaxOmDatePicker.java    |  41 ++++--
 .../common/{ => datetime}/OmDateTimePicker.java    |  32 ++---
 .../web/common/datetime/datepicker-functions.js    |  16 +++
 .../openmeetings/web/user/MessageDialog.java       |   2 +-
 .../web/user/calendar/AppointmentDialog.java       |   2 +-
 .../org/apache/openmeetings/util/TestDateTime.java |   2 +-
 pom.xml                                            |   4 +-
 12 files changed, 248 insertions(+), 122 deletions(-)

diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/AbstractOmDateTimePicker.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/AbstractOmDateTimePicker.java
deleted file mode 100644
index 2d0bd5a..0000000
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/AbstractOmDateTimePicker.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License") +  you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.openmeetings.web.common;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Locale;
-
-import org.apache.openmeetings.web.app.WebSession;
-import org.apache.wicket.model.IModel;
-
-import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.datetime.AbstractDateTimePickerWithIcon;
-import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.datetime.DatetimePickerConfig;
-import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.datetime.DatetimePickerIconConfig;
-import de.agilecoders.wicket.extensions.markup.html.bootstrap.icon.FontAwesome5IconType;
-
-public abstract class AbstractOmDateTimePicker<T> extends AbstractDateTimePickerWithIcon<T> {
-	private static final long serialVersionUID = 1L;
-	private static final String DEFAULT_DATE_FORMAT = "yyyy/MM/dd";
-	private static final String DEFAULT_DATE_TIME_FORMAT = DEFAULT_DATE_FORMAT + " HH:mm:ss";
-
-	protected AbstractOmDateTimePicker(String id, IModel<T> model) {
-		this(id, model, getDateTimeFormat());
-	}
-
-	protected AbstractOmDateTimePicker(String id, IModel<T> model, String format) {
-		super(id, model, new DatetimePickerConfig()
-				//.useLocale(WebSession.get().getLocale().toLanguageTag())
-				.withFormat(patch(format))
-				.with(new DatetimePickerIconConfig()
-						.useDateIcon(FontAwesome5IconType.calendar_s)
-						.useTimeIcon(FontAwesome5IconType.clock_s)
-						.useUpIcon(FontAwesome5IconType.arrow_up_s)
-						.useDownIcon(FontAwesome5IconType.arrow_down_s)
-						.usePreviousIcon(FontAwesome5IconType.arrow_left_s)
-						.useNextIcon(FontAwesome5IconType.arrow_right_s)
-						.useTodayIcon(FontAwesome5IconType.calendar_check_s)
-						.useClearIcon(FontAwesome5IconType.eraser_s)
-						.useCloseIcon(FontAwesome5IconType.times_s))
-				);
-		setRenderBodyOnly(false);
-	}
-
-	public static String patch(String format) {
-		// in Java free text is escaped with single-quotes
-		// moment.js uses []
-		return format.replaceAll("[']{1}([^']*)[']{1}", "\\[$1\\]");
-	}
-
-	public static String getDateTimeFormat() {
-		return getDateTimeFormat(WebSession.get().getLocale());
-	}
-
-	public static String getDateTimeFormat(Locale loc) {
-		DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, loc);
-		if (fmt instanceof SimpleDateFormat) {
-			return ((SimpleDateFormat)fmt).toPattern();
-		}
-		return DEFAULT_DATE_TIME_FORMAT;
-	}
-
-	public static String getDateFormat() {
-		return getDateFormat(WebSession.get().getLocale());
-	}
-
-	public static String getDateFormat(Locale loc) {
-		DateFormat fmt = DateFormat.getDateInstance(DateFormat.SHORT, loc);
-		if (fmt instanceof SimpleDateFormat) {
-			return ((SimpleDateFormat)fmt).toPattern();
-		}
-		return DEFAULT_DATE_FORMAT;
-	}
-}
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/GeneralUserForm.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/GeneralUserForm.java
index c8d6488..75c1811 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/GeneralUserForm.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/GeneralUserForm.java
@@ -33,6 +33,7 @@ import org.apache.openmeetings.db.entity.user.Group;
 import org.apache.openmeetings.db.entity.user.GroupUser;
 import org.apache.openmeetings.db.entity.user.User;
 import org.apache.openmeetings.db.entity.user.User.Salutation;
+import org.apache.openmeetings.web.common.datetime.AjaxOmDatePicker;
 import org.apache.openmeetings.web.util.CountryDropDown;
 import org.apache.openmeetings.web.util.RestrictiveChoiceProvider;
 import org.apache.wicket.extensions.validation.validator.RfcCompliantEmailAddressValidator;
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/InvitationForm.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/InvitationForm.java
index fd8bd00..e5c3763 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/InvitationForm.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/InvitationForm.java
@@ -40,6 +40,7 @@ import org.apache.openmeetings.db.entity.user.User.Type;
 import org.apache.openmeetings.service.room.InvitationManager;
 import org.apache.openmeetings.util.crypt.CryptProvider;
 import org.apache.openmeetings.web.app.WebSession;
+import org.apache.openmeetings.web.common.datetime.OmDateTimePicker;
 import org.apache.openmeetings.web.util.UserMultiChoice;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior;
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/datetime/AbstractOmDateTimePicker.html b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/datetime/AbstractOmDateTimePicker.html
new file mode 100644
index 0000000..5d3d67b
--- /dev/null
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/datetime/AbstractOmDateTimePicker.html
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+
+-->
+<!DOCTYPE html>
+<html xmlns:wicket="http://wicket.apache.org">
+<wicket:panel>
+	<span wicket:id="picker"></span>
+	<input type="hidden" wicket:id="date" />
+</wicket:panel>
+</html>
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/datetime/AbstractOmDateTimePicker.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/datetime/AbstractOmDateTimePicker.java
new file mode 100644
index 0000000..c2c382e
--- /dev/null
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/datetime/AbstractOmDateTimePicker.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") +  you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openmeetings.web.common.datetime;
+
+import java.io.Serializable;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+import org.apache.openmeetings.web.app.WebSession;
+import org.apache.wicket.Session;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.JavaScriptHeaderItem;
+import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
+import org.apache.wicket.markup.html.form.FormComponent;
+import org.apache.wicket.markup.html.form.FormComponentPanel;
+import org.apache.wicket.markup.html.form.HiddenField;
+import org.apache.wicket.model.ChainingModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.request.resource.JavaScriptResourceReference;
+import org.apache.wicket.request.resource.ResourceReference;
+
+import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.datetime.AbstractDateTimePickerWithIcon;
+import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.datetime.DatetimePickerConfig;
+import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.datetime.DatetimePickerIconConfig;
+import de.agilecoders.wicket.extensions.markup.html.bootstrap.icon.FontAwesome5IconType;
+
+public abstract class AbstractOmDateTimePicker<T extends Serializable> extends FormComponentPanel<T> {
+	private static final long serialVersionUID = 1L;
+	private static final String DEFAULT_DATE_FORMAT = "yyyy/MM/dd";
+	private static final String DEFAULT_DATE_TIME_FORMAT = DEFAULT_DATE_FORMAT + " HH:mm:ss";
+	private static final ResourceReference FUNCJS = new JavaScriptResourceReference(AbstractOmDateTimePicker.class, "datepicker-functions.js");
+	private final boolean dateOnly;
+	private final HiddenField<T> date;
+	private AbstractDateTimePickerWithIcon<T> picker;
+	private String markupId;
+
+	AbstractOmDateTimePicker(String id, IModel<T> model, boolean dateOnly) {
+		super(id, model);
+		this.dateOnly = dateOnly;
+		date = newHidden("date", new ChainingModel<>(model));
+	}
+
+	@Override
+	protected void onInitialize() {
+		super.onInitialize();
+		final String format = dateOnly ? getDateFormat() : getDateTimeFormat();
+		DatetimePickerConfig config = new DatetimePickerConfig()
+				.useLocale(WebSession.get().getLocale().toLanguageTag())
+				.withFormat(patch(format))
+				.withKeepInvalid(true)
+				.with(new DatetimePickerIconConfig().useDateIcon(FontAwesome5IconType.calendar_s)
+						.useTimeIcon(FontAwesome5IconType.clock_s).useUpIcon(FontAwesome5IconType.arrow_up_s)
+						.useDownIcon(FontAwesome5IconType.arrow_down_s)
+						.usePreviousIcon(FontAwesome5IconType.arrow_left_s)
+						.useNextIcon(FontAwesome5IconType.arrow_right_s)
+						.useTodayIcon(FontAwesome5IconType.calendar_check_s).useClearIcon(FontAwesome5IconType.eraser_s)
+						.useCloseIcon(FontAwesome5IconType.times_s));
+		picker = new AbstractDateTimePickerWithIcon<>("picker", new Model<>(getModelObject()), config) {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			protected FormComponent<T> newInput(String wicketId, String dateFormat) {
+				FormComponent<T> input = AbstractOmDateTimePicker.this.newInput(wicketId, dateFormat);
+				markupId = input.getMarkupId();
+				return input;
+			}
+		};
+		date.setOutputMarkupId(true);
+		add(date, picker.setRenderBodyOnly(false));
+	}
+
+	@Override
+	public void convertInput() {
+		date.convertInput();
+		if (date.isValid()) {
+			setConvertedInput(date.getConvertedInput());
+		} else {
+			date.getFeedbackMessages().forEach(msg -> getFeedbackMessages().add(msg));
+			date.getFeedbackMessages().clear();
+		}
+	}
+
+	protected abstract FormComponent<T> newInput(String wicketId, String dateFormat);
+
+	protected abstract HiddenField<T> newHidden(String wicketId, IModel<T> model);
+
+	@Override
+	public void renderHead(IHeaderResponse response) {
+		super.renderHead(response);
+		response.render(JavaScriptHeaderItem.forReference(FUNCJS));
+		response.render(new OnDomReadyHeaderItem("$('#" + markupId + "').on('change.datetimepicker', function (e) {omDateTimeInputHasChanged(e, '" + date.getMarkupId() + "', " + dateOnly + ");});"));
+	}
+
+	@Override
+	public boolean processChildren() {
+		return false;
+	}
+
+	public static String patch(String format) {
+		// in Java free text is escaped with single-quotes
+		// moment.js uses []
+		return format.replaceAll("[']{1}([^']*)[']{1}", "\\[$1\\]");
+	}
+
+	public static String getDateTimeFormat() {
+		return getDateTimeFormat(WebSession.get().getLocale());
+	}
+
+	@Override
+	public FormComponent<T> setLabel(IModel<String> labelModel) {
+		date.setLabel(labelModel);
+		return this;
+	}
+
+	@Override
+	protected void onModelChanged() {
+		picker.setModelObject(getModelObject());
+	}
+
+	public static String getDateTimeFormat(Locale loc) {
+		DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, loc);
+		if (fmt instanceof SimpleDateFormat) {
+			return ((SimpleDateFormat)fmt).toPattern();
+		}
+		return DEFAULT_DATE_TIME_FORMAT;
+	}
+
+	public static String getDateFormat() {
+		DateFormat fmt = DateFormat.getDateInstance(DateFormat.SHORT, Session.get().getLocale());
+		if (fmt instanceof SimpleDateFormat) {
+			return ((SimpleDateFormat)fmt).toPattern();
+		}
+		return DEFAULT_DATE_FORMAT;
+	}
+}
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/AjaxOmDatePicker.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/datetime/AjaxOmDatePicker.java
similarity index 58%
rename from openmeetings-web/src/main/java/org/apache/openmeetings/web/common/AjaxOmDatePicker.java
rename to openmeetings-web/src/main/java/org/apache/openmeetings/web/common/datetime/AjaxOmDatePicker.java
index 0fd162f..893723c 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/AjaxOmDatePicker.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/datetime/AjaxOmDatePicker.java
@@ -16,35 +16,56 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.openmeetings.web.common;
+package org.apache.openmeetings.web.common.datetime;
 
 import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.Locale;
 
-import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
 import org.apache.wicket.core.request.handler.IPartialPageRequestHandler;
 import org.apache.wicket.extensions.markup.html.form.datetime.LocalDateTextField;
 import org.apache.wicket.markup.html.form.FormComponent;
+import org.apache.wicket.markup.html.form.HiddenField;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.util.convert.IConverter;
+import org.apache.wicket.util.convert.converter.LocalDateConverter;
 
 public class AjaxOmDatePicker extends AbstractOmDateTimePicker<LocalDate> {
 	private static final long serialVersionUID = 1L;
 
 	public AjaxOmDatePicker(String id) {
-		super(id, null, getDateFormat());
+		super(id, null, true);
 	}
 
 	@Override
-	protected FormComponent<LocalDate> newInput(String wicketId, String dateFormat) {
-		LocalDateTextField input = new LocalDateTextField(wicketId, getModel(), dateFormat);
-		input.add(new OnChangeAjaxBehavior() {
+	protected HiddenField<LocalDate> newHidden(String wicketId, IModel<LocalDate> model) {
+		final IConverter<?> converter = new LocalDateConverter() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public DateTimeFormatter getDateTimeFormatter(Locale locale) {
+				return DateTimeFormatter.ISO_LOCAL_DATE;
+			}
+		};
+		HiddenField<LocalDate> date = new HiddenField<>(wicketId, model, LocalDate.class) {
 			private static final long serialVersionUID = 1L;
 
 			@Override
-			protected void onUpdate(AjaxRequestTarget target) {
-				onValueChanged(target);
+			protected IConverter<?> createConverter(Class<?> clazz) {
+				if (LocalDate.class.isAssignableFrom(clazz)) {
+					return converter;
+				}
+				return null;
 			}
-		});
-		return input;
+		};
+		date.add(OnChangeAjaxBehavior.onChange(this::onValueChanged));
+		return date;
+	}
+
+	@Override
+	protected FormComponent<LocalDate> newInput(String wicketId, String dateFormat) {
+		return new LocalDateTextField(wicketId, getModel(), dateFormat);
 	}
 
 	protected void onValueChanged(IPartialPageRequestHandler target) {
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/OmDateTimePicker.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/datetime/OmDateTimePicker.java
similarity index 77%
rename from openmeetings-web/src/main/java/org/apache/openmeetings/web/common/OmDateTimePicker.java
rename to openmeetings-web/src/main/java/org/apache/openmeetings/web/common/datetime/OmDateTimePicker.java
index d1bd393..5085f90 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/OmDateTimePicker.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/datetime/OmDateTimePicker.java
@@ -16,46 +16,37 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.openmeetings.web.common;
+package org.apache.openmeetings.web.common.datetime;
 
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.time.format.DateTimeFormatterBuilder;
 import java.util.Locale;
 
 import org.apache.wicket.extensions.markup.html.form.datetime.LocalDateTimeTextField;
 import org.apache.wicket.markup.html.form.FormComponent;
+import org.apache.wicket.markup.html.form.HiddenField;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.util.convert.IConverter;
 import org.apache.wicket.util.convert.converter.LocalDateTimeConverter;
 
 public class OmDateTimePicker extends AbstractOmDateTimePicker<LocalDateTime> {
 	private static final long serialVersionUID = 1L;
-	private final LocalDateTimeConverter converter;
 
 	public OmDateTimePicker(String id, IModel<LocalDateTime> model) {
-		this(id, model, getDateTimeFormat());
+		super(id, model, false);
 	}
 
-	private OmDateTimePicker(String id, IModel<LocalDateTime> model, final String pattern) {
-		super(id, model, pattern);
-		this.converter = new LocalDateTimeConverter() {
+	@Override
+	protected HiddenField<LocalDateTime> newHidden(String wicketId, IModel<LocalDateTime> model) {
+		final IConverter<?> converter = new LocalDateTimeConverter() {
 			private static final long serialVersionUID = 1L;
 
 			@Override
-			public DateTimeFormatter getDateTimeFormatter(Locale locale)
-			{
-				return new DateTimeFormatterBuilder()
-						.parseCaseInsensitive()
-						.appendPattern(pattern)
-						.toFormatter(Locale.ENGLISH);
+			public DateTimeFormatter getDateTimeFormatter(Locale locale) {
+				return DateTimeFormatter.ISO_LOCAL_DATE_TIME;
 			}
 		};
-	}
-
-	@Override
-	protected FormComponent<LocalDateTime> newInput(String wicketId, String dateFormat) {
-		return new LocalDateTimeTextField(wicketId, getModel(), dateFormat) {
+		return new HiddenField<>(wicketId, model, LocalDateTime.class) {
 			private static final long serialVersionUID = 1L;
 
 			@Override
@@ -67,4 +58,9 @@ public class OmDateTimePicker extends AbstractOmDateTimePicker<LocalDateTime> {
 			}
 		};
 	}
+
+	@Override
+	protected FormComponent<LocalDateTime> newInput(String wicketId, String dateFormat) {
+		return new LocalDateTimeTextField(wicketId, getModel(), dateFormat);
+	}
 }
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/datetime/datepicker-functions.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/datetime/datepicker-functions.js
new file mode 100644
index 0000000..c1e8282
--- /dev/null
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/datetime/datepicker-functions.js
@@ -0,0 +1,16 @@
+/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
+function omDateTimeInputHasChanged(e, hiddenId, dateOnly) {
+	const fmt = dateOnly ? 'YYYY-MM-DD' : 'YYYY-MM-DDTHH:mm:ss';
+	let val = e.target.value
+		, date = e.date;
+	if (!date) {
+		const mmnt = $(e.target).datetimepicker('date');
+		if (moment.isMoment(mmnt)) {
+			date = moment(val, mmnt.creationData().format);
+		}
+	}
+	if (date) {
+		val = date.isValid() ? date.clone().locale('en').format(fmt) : date.creationData().input;
+	}
+	$('#' + hiddenId).val(val).trigger('change');
+}
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/MessageDialog.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/MessageDialog.java
index be37b7b..fd33168 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/MessageDialog.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/MessageDialog.java
@@ -53,8 +53,8 @@ import org.apache.openmeetings.db.manager.IInvitationManager;
 import org.apache.openmeetings.util.CalendarHelper;
 import org.apache.openmeetings.web.app.Application;
 import org.apache.openmeetings.web.app.WebSession;
-import org.apache.openmeetings.web.common.OmDateTimePicker;
 import org.apache.openmeetings.web.common.OmModalCloseButton;
+import org.apache.openmeetings.web.common.datetime.OmDateTimePicker;
 import org.apache.openmeetings.web.user.calendar.AppointmentDialog;
 import org.apache.openmeetings.web.util.CalendarWebHelper;
 import org.apache.openmeetings.web.util.RoomTypeDropDown;
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/calendar/AppointmentDialog.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/calendar/AppointmentDialog.java
index faea5c5..1c661d9 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/calendar/AppointmentDialog.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/calendar/AppointmentDialog.java
@@ -51,8 +51,8 @@ import org.apache.openmeetings.db.util.FormatHelper;
 import org.apache.openmeetings.service.calendar.caldav.AppointmentManager;
 import org.apache.openmeetings.web.app.WebSession;
 import org.apache.openmeetings.web.common.GroupChoiceProvider;
-import org.apache.openmeetings.web.common.OmDateTimePicker;
 import org.apache.openmeetings.web.common.OmModalCloseButton;
+import org.apache.openmeetings.web.common.datetime.OmDateTimePicker;
 import org.apache.openmeetings.web.pages.MainPage;
 import org.apache.openmeetings.web.user.OmWysiwygToolbar;
 import org.apache.openmeetings.web.user.rooms.RoomEnterBehavior;
diff --git a/openmeetings-web/src/test/java/org/apache/openmeetings/util/TestDateTime.java b/openmeetings-web/src/test/java/org/apache/openmeetings/util/TestDateTime.java
index 8cd53d6..926c59a 100644
--- a/openmeetings-web/src/test/java/org/apache/openmeetings/util/TestDateTime.java
+++ b/openmeetings-web/src/test/java/org/apache/openmeetings/util/TestDateTime.java
@@ -29,7 +29,7 @@ import java.util.Calendar;
 import java.util.Date;
 import java.util.Locale;
 
-import org.apache.openmeetings.web.common.AbstractOmDateTimePicker;
+import org.apache.openmeetings.web.common.datetime.AbstractOmDateTimePicker;
 import org.junit.jupiter.api.Test;
 
 class TestDateTime {
diff --git a/pom.xml b/pom.xml
index 08fbb99..f175a8e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,7 +57,7 @@
 		<maven-project-info-reports-plugin.version>3.1.2</maven-project-info-reports-plugin.version>
 		<maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
 		<maven-assembly-plugin.version>3.3.0</maven-assembly-plugin.version>
-		<maven-dependency-plugin.version>3.1.2</maven-dependency-plugin.version>
+		<maven-dependency-plugin.version>3.2.0</maven-dependency-plugin.version>
 		<maven-bundle-plugin.version>5.1.1</maven-bundle-plugin.version>
 		<maven-war-plugin.version>3.3.1</maven-war-plugin.version>
 		<maven-clean-plugin.version>3.1.0</maven-clean-plugin.version>
@@ -81,7 +81,7 @@
 		<wicket.version>9.3.0</wicket.version>
 		<wicket-jquery-ui.version>9.3.1</wicket-jquery-ui.version>
 		<wicketstuff.version>9.3.0</wicketstuff.version>
-		<wicket-bootstrap.version>5.0.4</wicket-bootstrap.version>
+		<wicket-bootstrap.version>5.0.5-SNAPSHOT</wicket-bootstrap.version>
 		<font-awesome.version>5.15.2</font-awesome.version>
 		<spring.version>5.3.8</spring.version>
 		<tomcat.version>9.0.46</tomcat.version>