From e1245b4cb001e18b9c98905ebd78dc21e5a694d2 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 12 Apr 2024 09:40:39 +0100 Subject: [PATCH] Improve handling of time-only fields and fix issue where time-only values were not displayed properly --- .../src/Form/Core/DatePicker/DateInput.svelte | 16 ++------------ .../Form/Core/DatePicker/DatePicker.svelte | 21 ++++++++----------- packages/bbui/src/helpers.js | 18 ++++++++++++++-- .../src/components/grid/cells/DateCell.svelte | 16 +++++++------- 4 files changed, 34 insertions(+), 37 deletions(-) diff --git a/packages/bbui/src/Form/Core/DatePicker/DateInput.svelte b/packages/bbui/src/Form/Core/DatePicker/DateInput.svelte index d3bb04a30b..9fe5c234f9 100644 --- a/packages/bbui/src/Form/Core/DatePicker/DateInput.svelte +++ b/packages/bbui/src/Form/Core/DatePicker/DateInput.svelte @@ -1,5 +1,6 @@ diff --git a/packages/bbui/src/Form/Core/DatePicker/DatePicker.svelte b/packages/bbui/src/Form/Core/DatePicker/DatePicker.svelte index 2686766784..a29746ee75 100644 --- a/packages/bbui/src/Form/Core/DatePicker/DatePicker.svelte +++ b/packages/bbui/src/Form/Core/DatePicker/DatePicker.svelte @@ -7,7 +7,7 @@ import { createEventDispatcher, onMount } from "svelte" import TimePicker from "./TimePicker.svelte" import Calendar from "./Calendar.svelte" - import DateTimeInput from "./DateInput.svelte" + import DateInput from "./DateInput.svelte" import ActionButton from "../../../ActionButton/ActionButton.svelte" import { parseDate } from "../../../helpers" @@ -68,9 +68,13 @@ } let newValue = date.toISOString() - // If time only set date component to 2000-01-01 - if (timeOnly) { - newValue = `2000-01-01T${newValue.split("T")[1]}` + // Time only fields always ignore timezones, otherwise they make no sense. + // For non-timezone-aware fields, create an ISO 8601 timestamp of the exact + // time picked, without timezone + const offsetForTimezone = (enableTime && ignoreTimezones) || timeOnly + if (offsetForTimezone) { + const offset = new Date().getTimezoneOffset() * 60000 + newValue = new Date(date.valueOf() - offset).toISOString().slice(0, -1) } // For date-only fields, construct a manual timestamp string without a time @@ -82,13 +86,6 @@ newValue = `${year}-${month}-${day}T00:00:00.000` } - // For non-timezone-aware fields, create an ISO 8601 timestamp of the exact - // time picked, without timezone - else if (enableTime && ignoreTimezones) { - const offset = new Date().getTimezoneOffset() * 60000 - newValue = new Date(date.valueOf() - offset).toISOString().slice(0, -1) - } - dispatch("change", newValue) } @@ -106,7 +103,7 @@ }) - { }) } -export const parseDate = (value, { timeOnly, dateOnly } = {}) => { +export const parseDate = (value, { dateOnly } = {}) => { // If empty then invalid if (!value) { return null @@ -125,7 +125,8 @@ export const parseDate = (value, { timeOnly, dateOnly } = {}) => { // Certain string values need transformed if (typeof value === "string") { - if (timeOnly || !isNaN(new Date(`0-${value}`))) { + // Check for time only values + if (!isNaN(new Date(`0-${value}`))) { value = `0-${value}` } @@ -146,3 +147,16 @@ export const parseDate = (value, { timeOnly, dateOnly } = {}) => { // millisecond. return dayjs(Math.floor(parsedDate.valueOf() / 1000) * 1000) } + +export const getDateDisplayValue = (value, { enableTime, timeOnly }) => { + if (!value?.isValid()) { + return "" + } + if (timeOnly) { + return value.format("HH:mm") + } else if (!enableTime) { + return value.format("MMMM D YYYY") + } else { + return value.format("MMMM D YYYY, HH:mm") + } +} diff --git a/packages/frontend-core/src/components/grid/cells/DateCell.svelte b/packages/frontend-core/src/components/grid/cells/DateCell.svelte index da3dd0b374..019a0db9c2 100644 --- a/packages/frontend-core/src/components/grid/cells/DateCell.svelte +++ b/packages/frontend-core/src/components/grid/cells/DateCell.svelte @@ -14,17 +14,15 @@ $: timeOnly = schema?.timeOnly $: dateOnly = schema?.dateOnly - $: format = timeOnly - ? "HH:mm:ss" - : dateOnly - ? "MMM D YYYY" - : "MMM D YYYY, HH:mm" $: editable = focused && !readonly - $: displayValue = getDisplayValue(value, timeOnly, dateOnly, format) + $: displayValue = getDisplayValue(value, timeOnly, dateOnly) - const getDisplayValue = (value, timeOnly, dateOnly, format) => { - const parsedDate = Helpers.parseDate(value, { timeOnly, dateOnly }) - return parsedDate?.format(format) || "" + const getDisplayValue = (value, timeOnly, dateOnly) => { + const parsedDate = Helpers.parseDate(value, { dateOnly }) + return Helpers.getDateDisplayValue(parsedDate, { + enableTime: !dateOnly, + timeOnly, + }) } // Ensure we close flatpickr when unselected