DEV: make API of future-date-input more customizable and aligned with the API of time-shortcut-picker (#16502)

This commit is contained in:
Andrei Prigorshnev 2022-04-27 16:41:15 +04:00 committed by GitHub
parent 3e23bd4745
commit c9b2374299
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 422 additions and 420 deletions

View File

@ -12,7 +12,6 @@
{{future-date-input
class="silence-until"
label="admin.user.silence_duration"
includeFarFuture=true
clearable=false
input=silenceUntil
onChangeInput=(action (mut silenceUntil))

View File

@ -13,7 +13,6 @@
{{future-date-input
class="suspend-until"
label="admin.user.suspend_duration"
includeFarFuture=true
clearable=false
input=suspendUntil
onChangeInput=(action (mut suspendUntil))

View File

@ -1,9 +1,16 @@
import Component from "@ember/component";
import { action } from "@ember/object";
import { and, empty, equal } from "@ember/object/computed";
import buildTimeframes from "discourse/lib/timeframes-builder";
import I18n from "I18n";
import { FORMAT } from "select-kit/components/future-date-input-selector";
import discourseComputed from "discourse-common/utils/decorators";
import {
TIME_SHORTCUT_TYPES,
extendedDefaultTimeShortcuts,
formatTime,
hideDynamicTimeShortcuts,
timeShortcuts,
} from "discourse/lib/time-shortcut";
export default Component.extend({
selection: null,
@ -24,12 +31,12 @@ export default Component.extend({
if (this.input) {
const dateTime = moment(this.input);
const closestTimeframe = this.findClosestTimeframe(dateTime);
if (closestTimeframe) {
this.set("selection", closestTimeframe.id);
const closestShortcut = this._findClosestShortcut(dateTime);
if (closestShortcut) {
this.set("selection", closestShortcut.id);
} else {
this.setProperties({
selection: "custom",
selection: TIME_SHORTCUT_TYPES.CUSTOM,
_date: dateTime.format("YYYY-MM-DD"),
_time: dateTime.format("HH:mm"),
});
@ -45,6 +52,36 @@ export default Component.extend({
}
},
@discourseComputed("customShortcuts")
shortcuts(customShortcuts) {
let shortcuts;
if (customShortcuts && customShortcuts.length) {
shortcuts = customShortcuts;
} else {
shortcuts = extendedDefaultTimeShortcuts(this.userTimezone);
}
const shortcutsFactory = timeShortcuts(this.userTimezone);
if (this.includeDateTime) {
shortcuts.push(shortcutsFactory.custom());
}
if (this.includeNow) {
shortcuts.push(shortcutsFactory.now());
}
shortcuts = hideDynamicTimeShortcuts(shortcuts, this.userTimezone);
return shortcuts.map((s) => {
return {
id: s.id,
name: I18n.t(s.label),
time: s.time,
timeFormatted: formatTime(s),
icon: s.icon,
};
});
},
@action
onChangeDate(date) {
if (!date) {
@ -73,15 +110,8 @@ export default Component.extend({
}
},
findClosestTimeframe(dateTime) {
const options = {
includeWeekend: this.includeWeekend,
includeFarFuture: this.includeFarFuture,
includeDateTime: this.includeDateTime,
canScheduleNow: this.includeNow || false,
};
return buildTimeframes(this.userTimezone, options).find((tf) => {
_findClosestShortcut(dateTime) {
return this.shortcuts.find((tf) => {
if (tf.time) {
const diff = tf.time.diff(dateTime);
return 0 <= diff && diff < 60 * 1000;

View File

@ -1,7 +1,4 @@
import {
LATER_TODAY_CUTOFF_HOUR,
MOMENT_FRIDAY,
MOMENT_THURSDAY,
START_OF_DAY_HOUR,
laterToday,
now,
@ -10,6 +7,8 @@ import {
import {
TIME_SHORTCUT_TYPES,
defaultTimeShortcuts,
formatTime,
hideDynamicTimeShortcuts,
specialShortcutOptions,
} from "discourse/lib/time-shortcut";
import discourseComputed, {
@ -183,7 +182,7 @@ export default Component.extend({
} else {
options = defaultTimeShortcuts(userTimezone);
}
this._hideDynamicOptions(options);
options = hideDynamicTimeShortcuts(options, userTimezone);
let specialOptions = specialShortcutOptions();
if (this.lastCustomDate && this.lastCustomTime) {
@ -206,7 +205,7 @@ export default Component.extend({
}
this._applyCustomLabels(options, customLabels);
this._formatTime(options);
options.forEach((o) => (o.timeFormatted = formatTime(o)));
return options;
},
@ -271,23 +270,4 @@ export default Component.extend({
}
});
},
_hideDynamicOptions(options) {
if (now(this.userTimezone).hour() >= LATER_TODAY_CUTOFF_HOUR) {
this._hideOption(options, TIME_SHORTCUT_TYPES.LATER_TODAY);
}
if (now(this.userTimezone).day() >= MOMENT_THURSDAY) {
this._hideOption(options, TIME_SHORTCUT_TYPES.LATER_THIS_WEEK);
}
if (now(this.userTimezone).day() >= MOMENT_FRIDAY) {
this._hideOption(options, TIME_SHORTCUT_TYPES.THIS_WEEKEND);
}
},
_hideOption(options, optionId) {
const option = options.findBy("id", optionId);
option.hidden = true;
},
});

View File

@ -12,6 +12,7 @@ import Invite from "discourse/models/invite";
import I18n from "I18n";
import { FORMAT } from "select-kit/components/future-date-input-selector";
import { sanitize } from "discourse/lib/text";
import { timeShortcuts } from "discourse/lib/time-shortcut";
export default Controller.extend(
ModalFunctionality,
@ -177,6 +178,24 @@ export default Controller.extend(
return staff || groups.any((g) => g.owner);
},
@discourseComputed
timeShortcuts() {
const timezone = this.currentUser.resolvedTimezone(this.currentUser);
const shortcuts = timeShortcuts(timezone);
return [
shortcuts.laterToday(),
shortcuts.tomorrow(),
shortcuts.laterThisWeek(),
shortcuts.monday(),
shortcuts.twoWeeks(),
shortcuts.nextMonth(),
shortcuts.twoMonths(),
shortcuts.threeMonths(),
shortcuts.fourMonths(),
shortcuts.sixMonths(),
];
},
@action
copied() {
this.save({ sendEmail: false, copy: true });

View File

@ -7,6 +7,7 @@ import { action } from "@ember/object";
import discourseComputed from "discourse-common/utils/decorators";
import { equal, or } from "@ember/object/computed";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { timeShortcuts } from "discourse/lib/time-shortcut";
export default Controller.extend(ModalFunctionality, {
selectedSlowMode: null,
@ -107,6 +108,24 @@ export default Controller.extend(ModalFunctionality, {
: "topic.slow_mode_update.enable";
},
@discourseComputed
timeShortcuts() {
const timezone = this.currentUser.resolvedTimezone(this.currentUser);
const shortcuts = timeShortcuts(timezone);
return [
shortcuts.laterToday(),
shortcuts.tomorrow(),
shortcuts.laterThisWeek(),
shortcuts.monday(),
shortcuts.twoWeeks(),
shortcuts.nextMonth(),
shortcuts.twoMonths(),
shortcuts.threeMonths(),
shortcuts.fourMonths(),
shortcuts.sixMonths(),
];
},
_setFromSeconds(seconds) {
this.setProperties(fromSeconds(seconds));
},

View File

@ -3,11 +3,35 @@ import I18n from "I18n";
import ModalFunctionality from "discourse/mixins/modal-functionality";
import User from "discourse/models/user";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { timeShortcuts } from "discourse/lib/time-shortcut";
import discourseComputed from "discourse-common/utils/decorators";
export default Controller.extend(ModalFunctionality, {
loading: false,
ignoredUntil: null,
ignoredUsername: null,
@discourseComputed
timeShortcuts() {
const timezone = this.currentUser.resolvedTimezone(this.currentUser);
const shortcuts = timeShortcuts(timezone);
return [
shortcuts.laterToday(),
shortcuts.tomorrow(),
shortcuts.laterThisWeek(),
shortcuts.thisWeekend(),
shortcuts.monday(),
shortcuts.twoWeeks(),
shortcuts.nextMonth(),
shortcuts.twoMonths(),
shortcuts.threeMonths(),
shortcuts.fourMonths(),
shortcuts.sixMonths(),
shortcuts.oneYear(),
shortcuts.forever(),
];
},
actions: {
ignore() {
if (!this.ignoredUntil || !this.ignoredUsername) {

View File

@ -2,10 +2,34 @@ import Controller from "@ember/controller";
import I18n from "I18n";
import ModalFunctionality from "discourse/mixins/modal-functionality";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { timeShortcuts } from "discourse/lib/time-shortcut";
import discourseComputed from "discourse-common/utils/decorators";
export default Controller.extend(ModalFunctionality, {
loading: false,
ignoredUntil: null,
@discourseComputed
timeShortcuts() {
const timezone = this.currentUser.resolvedTimezone(this.currentUser);
const shortcuts = timeShortcuts(timezone);
return [
shortcuts.laterToday(),
shortcuts.tomorrow(),
shortcuts.laterThisWeek(),
shortcuts.thisWeekend(),
shortcuts.monday(),
shortcuts.twoWeeks(),
shortcuts.nextMonth(),
shortcuts.twoMonths(),
shortcuts.threeMonths(),
shortcuts.fourMonths(),
shortcuts.sixMonths(),
shortcuts.oneYear(),
shortcuts.forever(),
];
},
actions: {
ignore() {
if (!this.ignoredUntil) {

View File

@ -1,6 +1,10 @@
import {
LATER_TODAY_CUTOFF_HOUR,
MOMENT_FRIDAY,
MOMENT_MONDAY,
MOMENT_SATURDAY,
MOMENT_SUNDAY,
MOMENT_THURSDAY,
fourMonths,
laterThisWeek,
laterToday,
@ -16,6 +20,7 @@ import {
twoMonths,
twoWeeks,
} from "discourse/lib/time-utils";
import I18n from "I18n";
export const TIME_SHORTCUT_TYPES = {
LATER_TODAY: "later_today",
@ -46,6 +51,24 @@ export function defaultTimeShortcuts(timezone) {
];
}
export function extendedDefaultTimeShortcuts(timezone) {
const shortcuts = timeShortcuts(timezone);
return [
shortcuts.laterToday(),
shortcuts.tomorrow(),
shortcuts.laterThisWeek(),
shortcuts.monday(),
shortcuts.twoWeeks(),
shortcuts.nextMonth(),
shortcuts.twoMonths(),
shortcuts.threeMonths(),
shortcuts.fourMonths(),
shortcuts.sixMonths(),
shortcuts.oneYear(),
shortcuts.forever(),
];
}
export function specialShortcutOptions() {
const shortcuts = timeShortcuts();
return [shortcuts.lastCustom(), shortcuts.custom(), shortcuts.none()];
@ -210,3 +233,33 @@ export function timeShortcuts(timezone) {
},
};
}
export function hideDynamicTimeShortcuts(shortcuts, timezone) {
const shortcutsToHide = new Set();
const _now = now(timezone);
if (_now.hour() >= LATER_TODAY_CUTOFF_HOUR) {
shortcutsToHide.add(TIME_SHORTCUT_TYPES.LATER_TODAY);
}
if (_now.day === MOMENT_SUNDAY || _now.day() >= MOMENT_THURSDAY) {
shortcutsToHide.add(TIME_SHORTCUT_TYPES.LATER_THIS_WEEK);
}
if (
_now.day() === MOMENT_FRIDAY ||
_now.day() === MOMENT_SATURDAY ||
_now.day() === MOMENT_SUNDAY
) {
shortcutsToHide.add(TIME_SHORTCUT_TYPES.THIS_WEEKEND);
}
return shortcuts.filter((s) => !shortcutsToHide.has(s.id));
}
export function formatTime(shortcut) {
if (!shortcut.time || !shortcut.timeFormatKey) {
return null;
}
return shortcut.time.format(I18n.t(shortcut.timeFormatKey));
}

View File

@ -5,6 +5,8 @@ export const LATER_TODAY_CUTOFF_HOUR = 17;
export const LATER_TODAY_MAX_HOUR = 18;
export const MOMENT_SUNDAY = 0;
export const MOMENT_MONDAY = 1;
export const MOMENT_TUESDAY = 2;
export const MOMENT_WEDNESDAY = 3;
export const MOMENT_THURSDAY = 4;
export const MOMENT_FRIDAY = 5;
export const MOMENT_SATURDAY = 6;

View File

@ -1,89 +0,0 @@
import {
TIME_SHORTCUT_TYPES,
timeShortcuts,
} from "discourse/lib/time-shortcut";
import I18n from "I18n";
export default function buildTimeframes(timezone, options = {}) {
const timeframes = allTimeframes(timezone);
formatTime(timeframes);
processDynamicTimeframes(timeframes, options, timezone);
return timeframes.filter((t) => !t.hidden);
}
function allTimeframes(timezone) {
const shortcuts = timeShortcuts(timezone);
return [
shortcuts.now(),
shortcuts.laterToday(),
shortcuts.tomorrow(),
shortcuts.laterThisWeek(),
shortcuts.thisWeekend(),
shortcuts.monday(),
shortcuts.twoWeeks(),
shortcuts.nextMonth(),
shortcuts.twoMonths(),
shortcuts.threeMonths(),
shortcuts.fourMonths(),
shortcuts.sixMonths(),
shortcuts.oneYear(),
shortcuts.forever(),
shortcuts.custom(),
];
}
function processDynamicTimeframes(timeframes, options, timezone) {
const now = moment.tz(timezone);
if (
!options.includeWeekend ||
now.day() === 0 ||
now.day() === 5 ||
now.day() === 6
) {
hideTimeframe(timeframes, TIME_SHORTCUT_TYPES.THIS_WEEKEND);
}
if (now.day() === 0) {
hideTimeframe(timeframes, TIME_SHORTCUT_TYPES.START_OF_NEXT_BUSINESS_WEEK);
}
if (now.date() === moment.tz(timezone).endOf("month").date()) {
hideTimeframe(timeframes, TIME_SHORTCUT_TYPES.NEXT_MONTH);
}
if (24 - now.hour() <= 6) {
hideTimeframe(timeframes, TIME_SHORTCUT_TYPES.LATER_TODAY);
}
if (now.day() === 0 || now.day() >= 4) {
hideTimeframe(timeframes, TIME_SHORTCUT_TYPES.LATER_THIS_WEEK);
}
if (!options.includeFarFuture) {
hideTimeframe(timeframes, TIME_SHORTCUT_TYPES.ONE_YEAR);
hideTimeframe(timeframes, TIME_SHORTCUT_TYPES.FOREVER);
}
if (!options.includeDateTime) {
hideTimeframe(timeframes, TIME_SHORTCUT_TYPES.CUSTOM);
}
if (!options.canScheduleNow) {
hideTimeframe(timeframes, TIME_SHORTCUT_TYPES.NOW);
}
}
function hideTimeframe(timeframes, timeframeId) {
const timeframe = timeframes.findBy("id", timeframeId);
timeframe.hidden = true;
}
function formatTime(options) {
options.forEach((option) => {
if (option.time && option.timeFormatKey) {
option.timeFormatted = option.time.format(I18n.t(option.timeFormatKey));
}
});
}

View File

@ -4,12 +4,8 @@
{{#if displayLabelIcon}}{{d-icon displayLabelIcon}}{{/if}}{{displayLabel}}
</label>
{{future-date-input-selector
statusType=statusType
value=(readonly selection)
includeDateTime=includeDateTime
includeWeekend=includeWeekend
includeFarFuture=includeFarFuture
includeNow=includeNow
content=shortcuts
clearable=clearable
onChangeInput=onChangeInput
onChange=(action (mut selection))

View File

@ -124,8 +124,7 @@
{{future-date-input
displayLabelIcon="far-clock"
displayLabel=(i18n "user.invited.invite.expires_at")
statusType="close"
includeDateTime=true
customShortcuts=timeShortcuts
clearable=true
input=buffered.expires_at
onChangeInput=(action (mut buffered.expires_at))

View File

@ -31,7 +31,7 @@
class="enabled-until"
label="topic.slow_mode_update.enabled_until"
labelClasses="slow-mode-label"
includeFarFuture=false
customShortcuts=timeShortcuts
clearable=true
input=model.slow_mode_enabled_until
onChangeInput=(action (mut model.slow_mode_enabled_until))

View File

@ -43,7 +43,6 @@
<p class="with-validation">
{{future-date-input
class="pin-until"
includeFarFuture=true
clearable=true
input=model.pinnedInCategoryUntil
onChangeInput=(action (mut model.pinnedInCategoryUntil))
@ -57,7 +56,6 @@
{{d-icon "far-clock"}}
{{future-date-input
class="pin-until"
includeFarFuture=true
clearable=true
input=model.pinnedInCategoryUntil
onChangeInput=(action (mut model.pinnedInCategoryUntil))
@ -93,7 +91,6 @@
<p class="with-validation">
{{future-date-input
class="pin-until"
includeFarFuture=true
clearable=true
input=model.pinnedGloballyUntil
onChangeInput=(action (mut model.pinnedGloballyUntil))
@ -107,7 +104,6 @@
{{d-icon "far-clock"}}
{{future-date-input
class="pin-until"
includeFarFuture=true
clearable=true
input=model.pinnedGloballyUntil
onChangeInput=(action (mut model.pinnedGloballyUntil))

View File

@ -13,9 +13,8 @@
{{future-date-input
label="user.user_notifications.ignore_duration_when"
input=(readonly ignoredUntil)
includeWeekend=true
customShortcuts=timeShortcuts
includeDateTime=false
includeFarFuture=true
onChangeInput=(action (mut ignoredUntil))
}}
<p>{{i18n "user.user_notifications.ignore_duration_note"}}</p>

View File

@ -2,9 +2,8 @@
{{future-date-input
label="user.user_notifications.ignore_duration_when"
input=ignoredUntil
includeWeekend=true
customShortcuts=timeShortcuts
includeDateTime=false
includeFarFuture=true
onChangeInput=(action (mut ignoredUntil))
}}
<p>{{i18n "user.user_notifications.ignore_duration_note"}}</p>

View File

@ -1,82 +0,0 @@
import selectKit from "discourse/tests/helpers/select-kit-helper";
import componentTest, {
setupRenderingTest,
} from "discourse/tests/helpers/component-test";
import {
discourseModule,
exists,
queryAll,
} from "discourse/tests/helpers/qunit-helpers";
import hbs from "htmlbars-inline-precompile";
import I18n from "I18n";
discourseModule(
"Unit | Lib | select-kit/future-date-input-selector",
function (hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function () {
this.set("subject", selectKit());
});
hooks.afterEach(function () {
if (this.clock) {
this.clock.restore();
}
});
componentTest("rendering and expanding", {
template: hbs`
{{future-date-input-selector
options=(hash
none="time_shortcut.select_timeframe"
)
}}
`,
async test(assert) {
assert.ok(
exists(".future-date-input-selector"),
"Selector is rendered"
);
assert.ok(
this.subject.header().label() ===
I18n.t("time_shortcut.select_timeframe"),
"Default text is rendered"
);
await this.subject.expand();
assert.ok(
exists(".select-kit-collection"),
"List of options is rendered"
);
},
});
componentTest("shows 'Custom date and time' if it's enabled", {
template: hbs`
{{future-date-input-selector
includeDateTime=true
}}
`,
async test(assert) {
await this.subject.expand();
const options = getOptions();
const customDateAndTime = I18n.t("time_shortcut.custom");
assert.ok(options.includes(customDateAndTime));
},
});
function getOptions() {
return Array.from(
queryAll(`.select-kit-collection .select-kit-row`).map(
(_, span) => span.dataset.name
)
);
}
}
);

View File

@ -0,0 +1,136 @@
import selectKit from "discourse/tests/helpers/select-kit-helper";
import componentTest, {
setupRenderingTest,
} from "discourse/tests/helpers/component-test";
import {
discourseModule,
exists,
fakeTime,
queryAll,
} from "discourse/tests/helpers/qunit-helpers";
import hbs from "htmlbars-inline-precompile";
import I18n from "I18n";
discourseModule("Unit | Lib | select-kit/future-date-input", function (hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function () {
this.set("subject", selectKit());
});
hooks.afterEach(function () {
if (this.clock) {
this.clock.restore();
}
});
componentTest("rendering and expanding", {
template: hbs`
{{future-date-input
options=(hash
none="time_shortcut.select_timeframe"
)
}}
`,
async test(assert) {
assert.ok(exists(".future-date-input-selector"), "Selector is rendered");
assert.ok(
this.subject.header().label() ===
I18n.t("time_shortcut.select_timeframe"),
"Default text is rendered"
);
await this.subject.expand();
assert.ok(
exists(".select-kit-collection"),
"List of options is rendered"
);
},
});
componentTest("renders default options", {
template: hbs`{{future-date-input}}`,
beforeEach() {
const monday = "2100-12-13T08:00:00";
this.clock = fakeTime(monday, this.currentUser._timezone, true);
},
async test(assert) {
await this.subject.expand();
const options = getOptions();
const expected = [
I18n.t("time_shortcut.later_today"),
I18n.t("time_shortcut.tomorrow"),
I18n.t("time_shortcut.later_this_week"),
I18n.t("time_shortcut.start_of_next_business_week_alt"),
I18n.t("time_shortcut.two_weeks"),
I18n.t("time_shortcut.next_month"),
I18n.t("time_shortcut.two_months"),
I18n.t("time_shortcut.three_months"),
I18n.t("time_shortcut.four_months"),
I18n.t("time_shortcut.six_months"),
I18n.t("time_shortcut.one_year"),
I18n.t("time_shortcut.forever"),
I18n.t("time_shortcut.custom"),
];
assert.deepEqual(options, expected);
},
});
componentTest("shows 'Custom date and time' by default", {
template: hbs`{{future-date-input}}`,
async test(assert) {
await this.subject.expand();
const options = getOptions();
const customDateAndTime = I18n.t("time_shortcut.custom");
assert.ok(options.includes(customDateAndTime));
},
});
componentTest("doesn't show 'Custom date and time' if disabled", {
template: hbs`
{{future-date-input
includeDateTime=false
}}
`,
async test(assert) {
await this.subject.expand();
const options = getOptions();
const customDateAndTime = I18n.t("time_shortcut.custom");
assert.notOk(options.includes(customDateAndTime));
},
});
componentTest("shows the now option if enabled", {
template: hbs`
{{future-date-input
includeNow=true
}}
`,
async test(assert) {
await this.subject.expand();
const options = getOptions();
const now = I18n.t("time_shortcut.now");
assert.ok(options.includes(now));
},
});
function getOptions() {
return Array.from(
queryAll(`.select-kit-collection .select-kit-row`).map(
(_, span) => span.dataset.name
)
);
}
});

View File

@ -0,0 +1,92 @@
import { module, test } from "qunit";
import { fakeTime } from "discourse/tests/helpers/qunit-helpers";
import {
defaultTimeShortcuts,
hideDynamicTimeShortcuts,
} from "discourse/lib/time-shortcut";
module(
"Unit | Lib | time-shortcut | hideDynamicTimeShortcuts",
function (hooks) {
hooks.afterEach(function () {
if (this.clock) {
this.clock.restore();
}
});
test("hides 'Later Today' at the end of the day", function (assert) {
const timezone = moment.tz.guess();
const shortcuts = defaultTimeShortcuts(timezone);
this.clock = fakeTime("2100-04-19 08:00:00", timezone, true); // morning
let result = hideDynamicTimeShortcuts(shortcuts, timezone).mapBy("id");
assert.ok(
result.includes("later_today"),
"shows later_today in the morning"
);
this.clock = fakeTime("2100-04-19 18:00:00", timezone, true); // evening
result = hideDynamicTimeShortcuts(shortcuts, timezone).mapBy("id");
assert.notOk(result.includes("doesn't show later_today in the evening"));
});
test("hides 'Later This Week' starting from Thursday", function (assert) {
const timezone = moment.tz.guess();
const shortcuts = defaultTimeShortcuts(timezone);
this.clock = fakeTime("2100-04-21 18:00:00", timezone, true); // Wednesday
let result = hideDynamicTimeShortcuts(shortcuts, timezone).mapBy("id");
assert.ok(
result.includes("later_this_week"),
"shows later_this_week on Wednesdays"
);
this.clock = fakeTime("2100-04-22 18:00:00", timezone, true); // Thursday
result = hideDynamicTimeShortcuts(shortcuts, timezone).mapBy("id");
assert.notOk(
result.includes("later_this_week"),
"doesn't show later_this_week on Thursdays"
);
this.clock = fakeTime("2100-04-23 18:00:00", timezone, true); // Friday
result = hideDynamicTimeShortcuts(shortcuts, timezone).mapBy("id");
assert.notOk(
result.includes("later_this_week"),
"doesn't show later_this_week on Fridays"
);
});
test("hides 'This Weekend' on Fridays, Saturdays and Sundays", function (assert) {
const timezone = moment.tz.guess();
const shortcuts = defaultTimeShortcuts(timezone);
this.clock = fakeTime("2100-04-22 18:00:00", timezone, true); // Thursday
let result = hideDynamicTimeShortcuts(shortcuts, timezone).mapBy("id");
assert.ok(
result.includes("this_weekend"),
"shows this_weekend on Thursdays"
);
this.clock = fakeTime("2100-04-23 18:00:00", timezone, true); // Friday
result = hideDynamicTimeShortcuts(shortcuts, timezone).mapBy("id");
assert.notOk(
result.includes("this_weekend"),
"doesn't show this_weekend on Fridays"
);
this.clock = fakeTime("2100-04-24 18:00:00", timezone, true); // Saturday
result = hideDynamicTimeShortcuts(shortcuts, timezone).mapBy("id");
assert.notOk(
result.includes("this_weekend"),
"doesn't show this_weekend on Saturdays"
);
this.clock = fakeTime("2100-04-25 18:00:00", timezone, true); // Sunday
result = hideDynamicTimeShortcuts(shortcuts, timezone).mapBy("id");
assert.notOk(
result.includes("this_weekend"),
"doesn't show this_weekend on Sundays"
);
});
}
);

View File

@ -1,169 +0,0 @@
import { module, test } from "qunit";
import { fakeTime } from "discourse/tests/helpers/qunit-helpers";
import buildTimeframes from "discourse/lib/timeframes-builder";
module("Unit | Lib | timeframes-builder", function (hooks) {
hooks.afterEach(function () {
if (this.clock) {
this.clock.restore();
}
});
test("default options", function (assert) {
const timezone = moment.tz.guess();
this.clock = fakeTime("2100-06-07T08:00:00", timezone, true); // Monday
const expected = [
"later_today",
"tomorrow",
"later_this_week",
"start_of_next_business_week",
"two_weeks",
"next_month",
"two_months",
"three_months",
"four_months",
"six_months",
];
assert.deepEqual(buildTimeframes(timezone).mapBy("id"), expected);
});
test("doesn't output 'Next Week' on Sundays", function (assert) {
const timezone = moment.tz.guess();
this.clock = fakeTime("2100-06-13T08:00:00", timezone, true); // Sunday
assert.ok(
!buildTimeframes(timezone)
.mapBy("id")
.includes("start_of_next_business_week")
);
});
test("outputs 'This Weekend' if it's enabled", function (assert) {
const timezone = moment.tz.guess();
this.clock = fakeTime("2100-06-07T08:00:00", timezone, true); // Monday
assert.ok(
buildTimeframes(timezone, { includeWeekend: true })
.mapBy("id")
.includes("this_weekend")
);
});
test("doesn't output 'This Weekend' on Fridays", function (assert) {
const timezone = moment.tz.guess();
this.clock = fakeTime("2100-04-23 18:00:00", timezone, true); // Friday
assert.ok(
!buildTimeframes(timezone, { includeWeekend: true })
.mapBy("id")
.includes("this_weekend")
);
});
test("doesn't show 'This Weekend' on Sundays", function (assert) {
/*
We need this test to avoid regressions.
We tend to write such conditions and think that
they mean the beginning of work week
(Monday, Tuesday and Wednesday in this specific case):
if (date.day <= 3) {
...
}
In fact, Sunday will pass this check too, because
in moment.js 0 stands for Sunday.
*/
const timezone = moment.tz.guess();
this.clock = fakeTime("2100-04-25 18:00:00", timezone, true); // Sunday
assert.ok(
!buildTimeframes(timezone, { includeWeekend: true })
.mapBy("id")
.includes("this_weekend")
);
});
test("outputs 'Later This Week' instead of 'Later Today' at the end of the day", function (assert) {
const timezone = moment.tz.guess();
this.clock = fakeTime("2100-04-19 18:00:00", timezone, true); // Monday evening
const timeframes = buildTimeframes(timezone).mapBy("id");
assert.notOk(timeframes.includes("later_today"));
assert.ok(timeframes.includes("later_this_week"));
});
test("doesn't output 'Later This Week' on Thursdays", function (assert) {
const timezone = moment.tz.guess();
this.clock = fakeTime("2100-04-22 18:00:00", timezone, true); // Thursday evening
const timeframes = buildTimeframes(timezone).mapBy("id");
assert.notOk(timeframes.includes("later_this_week"));
});
test("doesn't output 'Later This Week' on Sundays", function (assert) {
/*
We need this test to avoid regressions.
We tend to write such conditions and think that
they mean the beginning of business week
(Monday, Tuesday and Wednesday in this specific case):
if (date.day < 3) {
...
}
In fact, Sunday will pass this check too, because
in moment.js 0 stands for Sunday.
*/
const timezone = moment.tz.guess();
this.clock = fakeTime("2100-04-25 18:00:00", timezone, true); // Sunday evening
const timeframes = buildTimeframes(timezone).mapBy("id");
assert.notOk(timeframes.includes("later_this_week"));
});
test("doesn't output 'Next Month' on the last day of the month", function (assert) {
const timezone = moment.tz.guess();
this.clock = fakeTime("2100-04-30 18:00:00", timezone, true); // The last day of April
const timeframes = buildTimeframes(timezone).mapBy("id");
assert.notOk(timeframes.includes("next_month"));
});
test("shows far future options if enabled", function (assert) {
const timezone = moment.tz.guess();
this.clock = fakeTime("2100-06-07T08:00:00", timezone, true); // Monday
const timeframes = buildTimeframes(timezone, {
includeFarFuture: true,
}).mapBy("id");
assert.ok(timeframes.includes("one_year"));
assert.ok(timeframes.includes("forever"));
});
test("shows the pick-date-and-time option if enabled", function (assert) {
const timezone = moment.tz.guess();
this.clock = fakeTime("2100-06-07T08:00:00", timezone, true); // Monday
const timeframes = buildTimeframes(timezone, {
includeDateTime: true,
}).mapBy("id");
assert.ok(timeframes.includes("custom"));
});
test("shows the now option if enabled", function (assert) {
const timezone = moment.tz.guess();
this.clock = fakeTime("2100-06-07T08:00:00", timezone, true); // Monday
const timeframes = buildTimeframes(timezone, {
canScheduleNow: true,
}).mapBy("id");
assert.ok(timeframes.includes("now"));
});
});

View File

@ -1,9 +1,6 @@
import ComboBoxComponent from "select-kit/components/combo-box";
import { computed } from "@ember/object";
import { equal } from "@ember/object/computed";
import { isEmpty } from "@ember/utils";
import buildTimeframes from "discourse/lib/timeframes-builder";
import I18n from "I18n";
export const FORMAT = "YYYY-MM-DD HH:mmZ";
@ -28,25 +25,6 @@ export default ComboBoxComponent.extend({
return "future-date-input-selector/future-date-input-selector-row";
},
content: computed("statusType", function () {
const opts = {
includeWeekend: this.includeWeekend,
includeFarFuture: this.includeFarFuture,
includeDateTime: this.includeDateTime,
canScheduleNow: this.includeNow || false,
};
return buildTimeframes(this.userTimezone, opts).map((tf) => {
return {
id: tf.id,
name: I18n.t(tf.label),
time: tf.time,
timeFormatted: tf.timeFormatted,
icon: tf.icon,
};
});
}),
actions: {
onChange(value) {
if (value !== "custom" && !isEmpty(value)) {

View File

@ -21,7 +21,6 @@
{{#styleguide-example title="future-date-input"}}
{{future-date-input
displayLabelIcon="far-clock"
includeDateTime=true
clearable=true
}}
{{/styleguide-example}}

View File

@ -58,7 +58,6 @@
{{#styleguide-example title="future-date-input-selector"}}
{{future-date-input-selector
statusType="open"
input=dummy.topicTimerUpdateDate
includeWeekend=true
includeForever=true