aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/main/java
diff options
context:
space:
mode:
authorDenis <denis@vaadin.com>2017-01-19 10:01:03 +0200
committerGitHub <noreply@github.com>2017-01-19 10:01:03 +0200
commitf42b9657b818da483b839d3b43b4cf55552ef034 (patch)
treedd65e611eb326469b4dbeb84eefc2c69b57f3e5f /server/src/main/java
parentdafc8310259a2e79bb203c7f786c9aba5354937b (diff)
downloadvaadin-framework-f42b9657b818da483b839d3b43b4cf55552ef034.tar.gz
vaadin-framework-f42b9657b818da483b839d3b43b4cf55552ef034.zip
Introduce DateTimeFile and InlineDateTimeField. (#8218)
* Introduce DateTimeFile and InlineDateTimeField. Fixes #8132 * Correct and provide declarative tests. * Provide a date converter and UI tests.
Diffstat (limited to 'server/src/main/java')
-rw-r--r--server/src/main/java/com/vaadin/data/converter/LocalDateTimeToDateConverter.java74
-rw-r--r--server/src/main/java/com/vaadin/data/validator/DateTimeRangeValidator.java51
-rw-r--r--server/src/main/java/com/vaadin/ui/AbstractLocalDateField.java4
-rw-r--r--server/src/main/java/com/vaadin/ui/AbstractLocalDateTimeField.java118
-rw-r--r--server/src/main/java/com/vaadin/ui/DateTimeField.java139
-rw-r--r--server/src/main/java/com/vaadin/ui/InlineDateTimeField.java71
-rw-r--r--server/src/main/java/com/vaadin/ui/declarative/DesignFormatter.java4
-rw-r--r--server/src/main/java/com/vaadin/ui/declarative/converters/DesignLocalDateTimeConverter.java68
8 files changed, 524 insertions, 5 deletions
diff --git a/server/src/main/java/com/vaadin/data/converter/LocalDateTimeToDateConverter.java b/server/src/main/java/com/vaadin/data/converter/LocalDateTimeToDateConverter.java
new file mode 100644
index 0000000000..e427d956e3
--- /dev/null
+++ b/server/src/main/java/com/vaadin/data/converter/LocalDateTimeToDateConverter.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed 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 com.vaadin.data.converter;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.Date;
+import java.util.Objects;
+
+import com.vaadin.data.Converter;
+import com.vaadin.data.Result;
+import com.vaadin.data.ValueContext;
+import com.vaadin.ui.DateTimeField;
+import com.vaadin.ui.InlineDateTimeField;
+
+/**
+ * A converter that converts between <code>LocalDateTime</code> and
+ * <code>Date</code>. This is used when a {@link DateTimeField} or
+ * {@link InlineDateTimeField} is bound to a {@link Date} property.
+ *
+ * @author Vaadin Ltd
+ */
+public class LocalDateTimeToDateConverter
+ implements Converter<LocalDateTime, Date> {
+
+ private ZoneOffset zoneOffset;
+
+ /**
+ * Creates a new converter using the given time zone.
+ *
+ * @param zoneOffset
+ * the time zone offset to use, not <code>null</code>
+ */
+ public LocalDateTimeToDateConverter(ZoneOffset zoneOffset) {
+ this.zoneOffset = Objects.requireNonNull(zoneOffset,
+ "Zone offset cannot be null");
+ }
+
+ @Override
+ public Result<Date> convertToModel(LocalDateTime localDate,
+ ValueContext context) {
+ if (localDate == null) {
+ return Result.ok(null);
+ }
+
+ return Result.ok(Date.from(localDate.toInstant(zoneOffset)));
+ }
+
+ @Override
+ public LocalDateTime convertToPresentation(Date date,
+ ValueContext context) {
+ if (date == null) {
+ return null;
+ }
+
+ return Instant.ofEpochMilli(date.getTime()).atZone(zoneOffset)
+ .toLocalDateTime();
+ }
+
+}
diff --git a/server/src/main/java/com/vaadin/data/validator/DateTimeRangeValidator.java b/server/src/main/java/com/vaadin/data/validator/DateTimeRangeValidator.java
new file mode 100644
index 0000000000..9096a8cc70
--- /dev/null
+++ b/server/src/main/java/com/vaadin/data/validator/DateTimeRangeValidator.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed 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 com.vaadin.data.validator;
+
+import java.time.LocalDateTime;
+import java.util.Comparator;
+
+/**
+ * Validator for validating that a {@link LocalDateTime} is inside a given
+ * range.
+ *
+ * @author Vaadin Ltd.
+ * @since 8.0
+ */
+public class DateTimeRangeValidator extends RangeValidator<LocalDateTime> {
+
+ /**
+ * Creates a validator for checking that a {@link LocalDateTime} is within a
+ * given range.
+ * <p>
+ * By default the range is inclusive i.e. both minValue and maxValue are
+ * valid values. Use {@link #setMinValueIncluded(boolean)} or
+ * {@link #setMaxValueIncluded(boolean)} to change it.
+ * </p>
+ *
+ * @param errorMessage
+ * the message to display in case the value does not validate.
+ * @param minValue
+ * The minimum value to accept or null for no limit
+ * @param maxValue
+ * The maximum value to accept or null for no limit
+ */
+ public DateTimeRangeValidator(String errorMessage, LocalDateTime minValue,
+ LocalDateTime maxValue) {
+ super(errorMessage, Comparator.naturalOrder(), minValue, maxValue);
+ }
+
+}
diff --git a/server/src/main/java/com/vaadin/ui/AbstractLocalDateField.java b/server/src/main/java/com/vaadin/ui/AbstractLocalDateField.java
index ab99fe0f28..7754757429 100644
--- a/server/src/main/java/com/vaadin/ui/AbstractLocalDateField.java
+++ b/server/src/main/java/com/vaadin/ui/AbstractLocalDateField.java
@@ -27,7 +27,11 @@ import com.vaadin.shared.ui.datefield.AbstractTextualDateFieldState;
import com.vaadin.shared.ui.datefield.DateResolution;
/**
+ * Abstract DateField class for {@link LocalDate} type.
+ *
* @author Vaadin Ltd
+ *
+ * @since 8.0
*
*/
public abstract class AbstractLocalDateField
diff --git a/server/src/main/java/com/vaadin/ui/AbstractLocalDateTimeField.java b/server/src/main/java/com/vaadin/ui/AbstractLocalDateTimeField.java
index 9be77444c6..65da2a2b8b 100644
--- a/server/src/main/java/com/vaadin/ui/AbstractLocalDateTimeField.java
+++ b/server/src/main/java/com/vaadin/ui/AbstractLocalDateTimeField.java
@@ -15,14 +15,24 @@
*/
package com.vaadin.ui;
+import java.time.Instant;
import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.time.temporal.ChronoUnit;
+import java.util.Date;
+import java.util.Map;
+import com.vaadin.data.validator.DateTimeRangeValidator;
+import com.vaadin.data.validator.RangeValidator;
+import com.vaadin.shared.ui.datefield.AbstractTextualDateFieldState;
import com.vaadin.shared.ui.datefield.DateTimeResolution;
-import com.vaadin.shared.ui.datefield.LocalDateTimeFieldState;
/**
+ * Abstract DateField class for {@link LocalDateTime} type.
+ *
* @author Vaadin Ltd
*
+ * @since 8.0
*/
public abstract class AbstractLocalDateTimeField
extends AbstractDateField<LocalDateTime, DateTimeResolution> {
@@ -45,14 +55,112 @@ public abstract class AbstractLocalDateTimeField
super(caption, DateTimeResolution.MINUTE);
}
+ /**
+ * Constructs a new <code>AbstractLocalDateTimeField</code> with the given
+ * caption and initial text contents.
+ *
+ * @param caption
+ * the caption <code>String</code> for the editor.
+ * @param value
+ * the LocalDateTime value.
+ */
+ public AbstractLocalDateTimeField(String caption, LocalDateTime value) {
+ super(caption, value, DateTimeResolution.MINUTE);
+ }
+
+ @Override
+ protected AbstractTextualDateFieldState getState() {
+ return (AbstractTextualDateFieldState) super.getState();
+ }
+
+ @Override
+ protected AbstractTextualDateFieldState getState(boolean markAsDirty) {
+ return (AbstractTextualDateFieldState) super.getState(markAsDirty);
+ }
+
@Override
- protected LocalDateTimeFieldState getState() {
- return (LocalDateTimeFieldState) super.getState();
+ protected int getDatePart(LocalDateTime date,
+ DateTimeResolution resolution) {
+ LocalDateTime value = date;
+ if (value == null) {
+ value = LocalDateTime.of(1, 1, 1, 0, 0);
+ }
+ switch (resolution) {
+ case DAY:
+ return value.getDayOfMonth();
+ case MONTH:
+ return value.getMonthValue();
+ case YEAR:
+ return value.getYear();
+ case HOUR:
+ return value.getHour();
+ case MINUTE:
+ return value.getMinute();
+ case SECOND:
+ return value.getSecond();
+ default:
+ assert false : "Unexpected resolution argument " + resolution;
+ return -1;
+ }
}
@Override
- protected LocalDateTimeFieldState getState(boolean markAsDirty) {
- return (LocalDateTimeFieldState) super.getState(markAsDirty);
+ protected RangeValidator<LocalDateTime> getRangeValidator() {
+ return new DateTimeRangeValidator(getDateOutOfRangeMessage(),
+ getDate(getRangeStart(), getResolution()),
+ getDate(getRangeEnd(), getResolution()));
+ }
+
+ @Override
+ protected LocalDateTime buildDate(
+ Map<DateTimeResolution, Integer> resolutionValues) {
+ return LocalDateTime.of(resolutionValues.get(DateTimeResolution.YEAR),
+ resolutionValues.getOrDefault(DateTimeResolution.MONTH, 1),
+ resolutionValues.getOrDefault(DateTimeResolution.DAY, 1),
+ resolutionValues.getOrDefault(DateTimeResolution.HOUR, 0),
+ resolutionValues.getOrDefault(DateTimeResolution.MINUTE, 0),
+ resolutionValues.getOrDefault(DateTimeResolution.SECOND, 0));
+ }
+
+ @Override
+ protected LocalDateTime convertFromDate(Date date) {
+ if (date == null) {
+ return null;
+ }
+ return Instant.ofEpochMilli(date.getTime()).atZone(ZoneOffset.UTC)
+ .toLocalDateTime();
+ }
+
+ @Override
+ protected Date convertToDate(LocalDateTime date) {
+ if (date == null) {
+ return null;
+ }
+ return Date.from(date.toInstant(ZoneOffset.UTC));
+ }
+
+ private LocalDateTime getDate(LocalDateTime date,
+ DateTimeResolution forResolution) {
+ if (date == null) {
+ return null;
+ }
+ switch (forResolution) {
+ case YEAR:
+ return date.withDayOfYear(1).toLocalDate().atStartOfDay();
+ case MONTH:
+ return date.withDayOfMonth(1).toLocalDate().atStartOfDay();
+ case DAY:
+ return date.toLocalDate().atStartOfDay();
+ case HOUR:
+ return date.truncatedTo(ChronoUnit.HOURS);
+ case MINUTE:
+ return date.truncatedTo(ChronoUnit.MINUTES);
+ case SECOND:
+ return date.truncatedTo(ChronoUnit.SECONDS);
+ default:
+ assert false : "Unexpected resolution argument " + forResolution;
+ return null;
+ }
}
}
diff --git a/server/src/main/java/com/vaadin/ui/DateTimeField.java b/server/src/main/java/com/vaadin/ui/DateTimeField.java
new file mode 100644
index 0000000000..cde5633846
--- /dev/null
+++ b/server/src/main/java/com/vaadin/ui/DateTimeField.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed 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 com.vaadin.ui;
+
+import java.time.LocalDateTime;
+
+import com.vaadin.shared.ui.datefield.LocalDateTimeFieldState;
+
+/**
+ * A date time entry component, which displays the actual date selector as a
+ * popup.
+ *
+ * @see AbstractLocalDateTimeField
+ * @see InlineDateTimeField
+ * @author Vaadin Ltd.
+ * @since 8.0
+ */
+public class DateTimeField extends AbstractLocalDateTimeField {
+
+ /**
+ * Constructs an empty <code>DateTimeField</code> with no caption.
+ */
+ public DateTimeField() {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>DateTimeField</code> with the given caption and
+ * initial text contents.
+ *
+ * @param caption
+ * the caption <code>String</code> for the editor.
+ * @param value
+ * the LocalDateTime value.
+ */
+ public DateTimeField(String caption, LocalDateTime value) {
+ super(caption, value);
+ }
+
+ /**
+ * Constructs an empty <code>DateTimeField</code> with caption.
+ *
+ * @param caption
+ * the caption of the datefield.
+ */
+ public DateTimeField(String caption) {
+ super(caption);
+ }
+
+ /**
+ * Returns the current placeholder text.
+ *
+ * @see #setPlaceholder(String)
+ * @return the placeholder text
+ */
+ public String getPlaceholder() {
+ return getState(false).placeholder;
+ }
+
+ /**
+ * Sets the placeholder text. The placeholder is text that is displayed when
+ * the field would otherwise be empty, to prompt the user for input.
+ *
+ * @param placeholder
+ * the placeholder text to set
+ */
+ public void setPlaceholder(String placeholder) {
+ getState().placeholder = placeholder;
+ }
+
+ @Override
+ protected LocalDateTimeFieldState getState() {
+ return (LocalDateTimeFieldState) super.getState();
+ }
+
+ @Override
+ protected LocalDateTimeFieldState getState(boolean markAsDirty) {
+ return (LocalDateTimeFieldState) super.getState(markAsDirty);
+ }
+
+ /**
+ * Checks whether the text field is enabled (default) or not.
+ *
+ * @see #setTextFieldEnabled(boolean)
+ *
+ * @return <b>true</b> if the text field is enabled, <b>false</b> otherwise.
+ */
+ public boolean isTextFieldEnabled() {
+ return getState(false).textFieldEnabled;
+ }
+
+ /**
+ * Enables or disables the text field. By default the text field is enabled.
+ * Disabling it causes only the button for date selection to be active, thus
+ * preventing the user from entering invalid dates.
+ *
+ * See {@link http://dev.vaadin.com/ticket/6790}.
+ *
+ * @param state
+ * <b>true</b> to enable text field, <b>false</b> to disable it.
+ */
+ public void setTextFieldEnabled(boolean state) {
+ getState().textFieldEnabled = state;
+ }
+
+ /**
+ * Set a description that explains the usage of the Widget for users of
+ * assistive devices.
+ *
+ * @param description
+ * String with the description
+ */
+ public void setAssistiveText(String description) {
+ getState().descriptionForAssistiveDevices = description;
+ }
+
+ /**
+ * Get the description that explains the usage of the Widget for users of
+ * assistive devices.
+ *
+ * @return String with the description
+ */
+ public String getAssistiveText() {
+ return getState(false).descriptionForAssistiveDevices;
+ }
+}
diff --git a/server/src/main/java/com/vaadin/ui/InlineDateTimeField.java b/server/src/main/java/com/vaadin/ui/InlineDateTimeField.java
new file mode 100644
index 0000000000..2c4cf290b3
--- /dev/null
+++ b/server/src/main/java/com/vaadin/ui/InlineDateTimeField.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed 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 com.vaadin.ui;
+
+import java.time.LocalDateTime;
+
+import com.vaadin.shared.ui.datefield.InlineDateTimeFieldState;
+
+/**
+ * A date time entry component, which displays the actual date selector inline.
+ *
+ * @see AbstractLocalDateTimeField
+ * @see DateTimeField
+ * @author Vaadin Ltd.
+ * @since 8.0
+ */
+public class InlineDateTimeField extends AbstractLocalDateTimeField {
+
+ /**
+ * Constructs an empty <code>InlineDateTimeField</code> with no caption.
+ */
+ public InlineDateTimeField() {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>InlineDateTimeField</code> with the given caption
+ * and initial text contents.
+ *
+ * @param caption
+ * the caption <code>String</code> for the editor.
+ * @param value
+ * the LocalDate value.
+ */
+ public InlineDateTimeField(String caption, LocalDateTime value) {
+ super(caption, value);
+ }
+
+ /**
+ * Constructs an empty <code>InlineDateTimeField</code> with caption.
+ *
+ * @param caption
+ * the caption of the datefield.
+ */
+ public InlineDateTimeField(String caption) {
+ super(caption);
+ }
+
+ @Override
+ protected InlineDateTimeFieldState getState() {
+ return (InlineDateTimeFieldState) super.getState();
+ }
+
+ @Override
+ protected InlineDateTimeFieldState getState(boolean markAsDirty) {
+ return (InlineDateTimeFieldState) super.getState(markAsDirty);
+ }
+}
diff --git a/server/src/main/java/com/vaadin/ui/declarative/DesignFormatter.java b/server/src/main/java/com/vaadin/ui/declarative/DesignFormatter.java
index 6e9ff8f9bb..0f40be795b 100644
--- a/server/src/main/java/com/vaadin/ui/declarative/DesignFormatter.java
+++ b/server/src/main/java/com/vaadin/ui/declarative/DesignFormatter.java
@@ -21,6 +21,7 @@ import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.time.LocalDate;
+import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Date;
import java.util.Locale;
@@ -42,6 +43,7 @@ import com.vaadin.server.Resource;
import com.vaadin.ui.declarative.converters.DesignDateConverter;
import com.vaadin.ui.declarative.converters.DesignEnumConverter;
import com.vaadin.ui.declarative.converters.DesignLocalDateConverter;
+import com.vaadin.ui.declarative.converters.DesignLocalDateTimeConverter;
import com.vaadin.ui.declarative.converters.DesignObjectConverter;
import com.vaadin.ui.declarative.converters.DesignResourceConverter;
import com.vaadin.ui.declarative.converters.DesignShortcutActionConverter;
@@ -178,6 +180,8 @@ public class DesignFormatter implements Serializable {
converterMap.put(Date.class, new DesignDateConverter());
converterMap.put(LocalDate.class, new DesignLocalDateConverter());
+ converterMap.put(LocalDateTime.class,
+ new DesignLocalDateTimeConverter());
converterMap.put(ShortcutAction.class,
new DesignShortcutActionConverter());
converterMap.put(Resource.class, new DesignResourceConverter());
diff --git a/server/src/main/java/com/vaadin/ui/declarative/converters/DesignLocalDateTimeConverter.java b/server/src/main/java/com/vaadin/ui/declarative/converters/DesignLocalDateTimeConverter.java
new file mode 100644
index 0000000000..bfc177ca0c
--- /dev/null
+++ b/server/src/main/java/com/vaadin/ui/declarative/converters/DesignLocalDateTimeConverter.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed 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 com.vaadin.ui.declarative.converters;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.util.Locale;
+
+import com.vaadin.data.Converter;
+import com.vaadin.data.Result;
+import com.vaadin.data.ValueContext;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+
+/**
+ * A {@link LocalDate} converter to be used by {@link DesignAttributeHandler}.
+ * Provides ISO-compliant way of storing date and time.
+ *
+ * @since 8.0
+ * @author Vaadin Ltd
+ */
+public class DesignLocalDateTimeConverter
+ implements Converter<String, LocalDateTime> {
+
+ @Override
+ public Result<LocalDateTime> convertToModel(String value,
+ ValueContext context) {
+ for (String pattern : new String[] { "yyyy-MM-dd HH:mm:ssZ",
+ "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH",
+ "yyyy-MM-dd", "yyyy-MM", "yyyy" }) {
+ try {
+ Locale effectiveLocale = context.getLocale()
+ .orElse(Locale.ENGLISH);
+ LocalDateTime date = DateTimeFormatter
+ .ofPattern(pattern, effectiveLocale)
+ .parse(value, LocalDateTime::from);
+ return Result.ok(date);
+ } catch (DateTimeParseException ignored) {
+ // not parseable, ignore and try another format
+ }
+ }
+ return Result.error("Could not parse date value: " + value);
+ }
+
+ @Override
+ public String convertToPresentation(LocalDateTime value,
+ ValueContext context) {
+ return DateTimeFormatter
+ .ofPattern("yyyy-MM-dd HH:mm:ss",
+ context.getLocale().orElse(Locale.ENGLISH))
+ .format(value);
+ }
+
+}