mirror of
https://github.com/discourse/discourse.git
synced 2024-11-23 15:05:24 +08:00
DEV: Add optional timezone support to date-time-input-range (#17654)
This allows consumers to pass in, and receive, timestamps for a different timezone. Previously, attempting this would lead to very strange behavior which would become worse the further the input timestamp's timezone was from the browser's timezone. The default behavior is unchanged - the browser's timezone will be assumed.
This commit is contained in:
parent
91b6b5eee7
commit
17e733b6a8
|
@ -52,7 +52,9 @@ export default Component.extend({
|
|||
this._picker = picker;
|
||||
|
||||
if (this._picker && this.date) {
|
||||
this._picker.setDate(moment(this.date).toDate(), true);
|
||||
const parsedDate =
|
||||
this.date instanceof moment ? this.date : moment(this.date);
|
||||
this._picker.setDate(parsedDate.toDate(), true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -62,11 +64,18 @@ export default Component.extend({
|
|||
this._super(...arguments);
|
||||
|
||||
if (this._picker && this.date) {
|
||||
this._picker.setDate(moment(this.date).toDate(), true);
|
||||
const parsedDate =
|
||||
this.date instanceof moment ? this.date : moment(this.date);
|
||||
this._picker.setDate(parsedDate.toDate(), true);
|
||||
}
|
||||
|
||||
if (this._picker && this.relativeDate) {
|
||||
this._picker.setMinDate(moment(this.relativeDate).toDate(), true);
|
||||
const parsedRelativeDate =
|
||||
this.relativeDate instanceof moment
|
||||
? this.relativeDate
|
||||
: moment(this.relativeDate);
|
||||
|
||||
this._picker.setMinDate(parsedRelativeDate.toDate(), true);
|
||||
}
|
||||
|
||||
if (this._picker && !this.date) {
|
||||
|
|
|
@ -23,7 +23,7 @@ export default Component.extend({
|
|||
const diff = {};
|
||||
|
||||
if (options.prop === "from") {
|
||||
if (value && value.isAfter(this.to)) {
|
||||
if (this.to && value?.isAfter(this.to)) {
|
||||
diff[options.prop] = value;
|
||||
diff["to"] = value.clone().add(1, "hour");
|
||||
} else {
|
||||
|
|
|
@ -28,16 +28,19 @@ export default Component.extend({
|
|||
? this.date
|
||||
: this.relativeDate
|
||||
? this.relativeDate
|
||||
: moment();
|
||||
: moment.tz(this.resolvedTimezone);
|
||||
|
||||
this.onChange(
|
||||
moment({
|
||||
year: date.year(),
|
||||
month: date.month(),
|
||||
day: date.date(),
|
||||
hours: time.hours,
|
||||
minutes: time.minutes,
|
||||
})
|
||||
moment.tz(
|
||||
{
|
||||
year: date.year(),
|
||||
month: date.month(),
|
||||
day: date.date(),
|
||||
hours: time.hours,
|
||||
minutes: time.minutes,
|
||||
},
|
||||
this.resolvedTimezone
|
||||
)
|
||||
);
|
||||
}
|
||||
},
|
||||
|
@ -49,15 +52,22 @@ export default Component.extend({
|
|||
return;
|
||||
}
|
||||
|
||||
this.onChange &&
|
||||
this.onChange(
|
||||
moment({
|
||||
this.onChange?.(
|
||||
moment.tz(
|
||||
{
|
||||
year: date.year(),
|
||||
month: date.month(),
|
||||
day: date.date(),
|
||||
hours: this.hours || 0,
|
||||
minutes: this.minutes || 0,
|
||||
})
|
||||
);
|
||||
},
|
||||
this.resolvedTimezone
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
@computed
|
||||
get resolvedTimezone() {
|
||||
return this.timezone || moment.tz.guess();
|
||||
},
|
||||
});
|
||||
|
|
|
@ -66,7 +66,7 @@ export default Component.extend({
|
|||
minimumTime: computed("relativeDate", "date", function () {
|
||||
if (this.relativeDate) {
|
||||
if (this.date) {
|
||||
if (this.date.diff(this.relativeDate, "minutes") > 1440) {
|
||||
if (!this.date.isSame(this.relativeDate, "day")) {
|
||||
return 0;
|
||||
} else {
|
||||
return this.relativeDate.hours() * 60 + this.relativeDate.minutes();
|
||||
|
@ -116,11 +116,18 @@ export default Component.extend({
|
|||
let name = convertMinutesToString(option);
|
||||
let label;
|
||||
|
||||
if (this.minimumTime) {
|
||||
const diff = option - this.minimumTime;
|
||||
label = htmlSafe(
|
||||
`${name} <small>(${convertMinutesToDurationString(diff)})</small>`
|
||||
);
|
||||
if (this.date && this.relativeDate) {
|
||||
const diff = this.date
|
||||
.clone()
|
||||
.startOf("day")
|
||||
.add(option, "minutes")
|
||||
.diff(this.relativeDate, "minutes");
|
||||
|
||||
if (diff < 1440) {
|
||||
label = htmlSafe(
|
||||
`${name} <small>(${convertMinutesToDurationString(diff)})</small>`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<DateTimeInput @date={{this.from}} @onChange={{action "onChangeRanges" (hash prop="from")}} @showTime={{this.showFromTime}} @class="from" @placeholder={{i18n "dates.from_placeholder"}} />
|
||||
<DateTimeInput @date={{this.from}} @onChange={{action "onChangeRanges" (hash prop="from")}} @showTime={{this.showFromTime}} @class="from" @placeholder={{i18n "dates.from_placeholder"}} @timezone={{@timezone}}/>
|
||||
|
||||
<DateTimeInput @date={{this.to}} @relativeDate={{this.from}} @onChange={{action "onChangeRanges" (hash prop="to")}} @timeFirst={{this.toTimeFirst}} @showTime={{this.showToTime}} @clearable={{this.clearable}} @class="to" @placeholder={{i18n "dates.to_placeholder"}} />
|
||||
<DateTimeInput @date={{this.to}} @relativeDate={{this.from}} @onChange={{action "onChangeRanges" (hash prop="to")}} @timeFirst={{this.toTimeFirst}} @showTime={{this.showToTime}} @clearable={{this.clearable}} @class="to" @placeholder={{i18n "dates.to_placeholder"}} @timezone={{@timezone}} />
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { module, test } from "qunit";
|
||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||
import { render } from "@ember/test-helpers";
|
||||
import { fillIn, render } from "@ember/test-helpers";
|
||||
import { query } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { hbs } from "ember-cli-htmlbars";
|
||||
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||
|
||||
function fromDateInput() {
|
||||
return query(".from.d-date-time-input .date-picker");
|
||||
|
@ -26,15 +27,52 @@ module("Integration | Component | date-time-input-range", function (hooks) {
|
|||
setupRenderingTest(hooks);
|
||||
|
||||
test("default", async function (assert) {
|
||||
this.setProperties({ from: DEFAULT_DATE_TIME, to: null });
|
||||
this.setProperties({ state: { from: DEFAULT_DATE_TIME, to: null } });
|
||||
|
||||
await render(
|
||||
hbs`<DateTimeInputRange @from={{this.from}} @to={{this.to}} />`
|
||||
hbs`<DateTimeInputRange @from={{this.state.from}} @to={{this.state.to}} @onChange={{action (mut this.state)}} />`
|
||||
);
|
||||
|
||||
assert.strictEqual(fromDateInput().value, "2019-01-29");
|
||||
assert.strictEqual(fromTimeInput().dataset.name, "14:45");
|
||||
assert.strictEqual(toDateInput().value, "");
|
||||
assert.strictEqual(toTimeInput().dataset.name, "--:--");
|
||||
|
||||
await fillIn(toDateInput(), "2019-01-29");
|
||||
const toTimeSelectKit = selectKit(".to .d-time-input .select-kit");
|
||||
await toTimeSelectKit.expand();
|
||||
let rows = toTimeSelectKit.rows();
|
||||
assert.equal(rows[0].dataset.name, "14:45");
|
||||
assert.equal(rows[rows.length - 1].dataset.name, "23:45");
|
||||
await toTimeSelectKit.collapse();
|
||||
|
||||
await fillIn(toDateInput(), "2019-01-30");
|
||||
await toTimeSelectKit.expand();
|
||||
rows = toTimeSelectKit.rows();
|
||||
|
||||
assert.equal(rows[0].dataset.name, "00:00");
|
||||
assert.equal(rows[rows.length - 1].dataset.name, "23:45");
|
||||
});
|
||||
|
||||
test("timezone support", async function (assert) {
|
||||
this.setProperties({
|
||||
state: { from: moment.tz(DEFAULT_DATE_TIME, "Europe/Paris"), to: null },
|
||||
});
|
||||
|
||||
await render(
|
||||
hbs`<DateTimeInputRange @from={{this.state.from}} @to={{this.state.to}} @onChange={{action (mut this.state)}} @timezone="Europe/Paris" />`
|
||||
);
|
||||
|
||||
assert.strictEqual(fromDateInput().value, "2019-01-29");
|
||||
assert.strictEqual(fromTimeInput().dataset.name, "15:45");
|
||||
assert.strictEqual(toDateInput().value, "");
|
||||
assert.strictEqual(toTimeInput().dataset.name, "--:--");
|
||||
|
||||
await fillIn(toDateInput(), "2019-01-29");
|
||||
const toTimeSelectKit = selectKit(".to .d-time-input .select-kit");
|
||||
await toTimeSelectKit.expand();
|
||||
await toTimeSelectKit.selectRowByName("19:15");
|
||||
|
||||
assert.equal(this.state.to.toString(), "Tue Jan 29 2019 19:15:00 GMT+0100");
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue
Block a user