import moment from '@baserow/modules/core/moment' import { getCellTimezoneAbbr, getDateHumanReadableFormat, getDateMomentFormat, getFieldTimezone, getTimeHumanReadableFormat, getTimeMomentFormat, } from '@baserow/modules/database/utils/date' const DATE_PICKER_FORMAT = 'YYYY-MM-DD' /** * Mixin that introduces methods for the date field. This can both be used for a row * and grid view field. */ export default { data() { return { date: '', pickerDate: '', time: '', momentDate: null, } }, computed: { /** * We need to watch the value and the date/time formats. This can easily be done * with a computed property. */ valueAndFormats() { return `${this.value}|${this.field.date_format}|${this.field.date_time_format}|${this.field.date_force_timezone}` }, fieldDateFormat() { return getDateMomentFormat(this.field.date_format) }, }, watch: { /** * When the value or one of the date formats changes we need to update the date * and time data with the correct values. This is because the date and time data * are directly visible to the user and not the value like most other fields. */ valueAndFormats() { if (!this.editing) { this.setDateAndTime(this.field, this.value) } }, }, created() { this.setDateAndTime(this.field, this.value) }, methods: { updateFormattedDateValue() { this.pickerDate = this.momentDate.format(DATE_PICKER_FORMAT) this.date = this.momentDate.format(this.fieldDateFormat) }, updateFormattedTimeValue() { const timeFormat = getTimeMomentFormat(this.field.date_time_format) this.time = this.momentDate.format(timeFormat) }, /** * When the date part is updated we also need to update the copy data which * contains the whole date(time) in the correct format. The copy contains the * value that is actually going to be saved. */ updateDate(field, value) { const dateFormats = [DATE_PICKER_FORMAT, this.fieldDateFormat] const newDate = moment.utc(value, dateFormats, true) const timezone = getFieldTimezone(field) // default to now if no time is set const now = moment.utc() if (timezone !== null) { newDate.tz(timezone, true) now.tz(timezone) } if (newDate.isValid()) { const momentDate = this.momentDate || now newDate.set({ hour: momentDate.hour(), minute: momentDate.minute(), second: momentDate.second(), }) // needed again to be able to format correctly the moment date // composed by the date and time parts separately if (timezone !== null) { newDate.tz(timezone) } this.updateCopy(field, newDate) this.updateFormattedDateValue() } else { this.updateCopy(field, null) } }, /** * When the time part is updated we also need to update the copy data which * contains the whole date(time) in the correct format. The copy contains the * value that is actually going to be saved. */ updateTime(field, value) { const newTime = moment.utc(value, ['hh:mm a', 'HH:mm'], true) const timezone = getFieldTimezone(field) if (timezone !== null) { newTime.tz(timezone, true) } if (newTime.isValid()) { if (this.momentDate !== null) { newTime.set({ year: this.momentDate.year(), month: this.momentDate.month(), date: this.momentDate.date(), }) // needed again to be able to format correctly the moment date // composed by the date and time parts separately if (timezone !== null) { newTime.tz(timezone) } } this.updateCopy(field, newTime) this.updateFormattedTimeValue() } else { this.time = value } }, /** * When the user uses the datepicker to choose a date, we also need to update * date data and the copy so that the correct date is visible for the user. */ chooseDate(field, value) { this.updateDate(field, moment.utc(value).format(DATE_PICKER_FORMAT)) }, /** * When the user uses the time context to choose a time, we also need to update * time data and the copy so that the correct time is visible for the user. */ chooseTime(field, value) { this.updateTime(field, value) this.time = value }, /** * A helper method that allows updating the copy data by only changing certain * properties of a datetime. For example only the month could be updated. */ updateCopy(field, newMomentDate) { if (newMomentDate === null) { this.copy = null this.momentDate = null } else { this.momentDate = newMomentDate this.copy = field.date_include_time ? this.momentDate.format() : this.momentDate.format('YYYY-MM-DD') } }, /** * Updates the date and time data by converting the value to the correct formats. */ setDateAndTime(field, value) { if (value === null) { this.momentDate = null this.date = this.time = this.pickerDate = '' } else { const timezone = getFieldTimezone(field) this.momentDate = moment.utc(value, moment.ISO_8601, true) if (timezone) { this.momentDate.tz(timezone) } this.updateFormattedDateValue() this.updateFormattedTimeValue() } }, getCellTimezoneAbbr(field, value, force) { return getCellTimezoneAbbr(field, value, { force }) }, /** * Returns a human readable date placeholder of the format for the input. */ getDatePlaceholder(field) { return this.$t( 'humanDateFormat.' + getDateHumanReadableFormat(field.date_format) ) }, /** * Returns a human readable time placeholder of the format for the input. */ getTimePlaceholder(field) { return getTimeHumanReadableFormat(field.date_time_format) }, /** * When the user focuses on one of the inputs the related context menu must * also be opened. */ focus(context, event) { context.toggle(event.currentTarget, 'bottom', 'left', 0) }, /** * When the user blurs one of the inputs the related context menu must also be * hidden. */ blur(context, event) { context.hide() }, }, }