This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.
osr-discourse-src/app/assets/javascripts/discourse/app/components/time-shortcut-picker.js

283 lines
6.9 KiB
JavaScript

import { laterToday, now, parseCustomDatetime } from "discourse/lib/time-utils";
import {
TIME_SHORTCUT_TYPES,
defaultTimeShortcuts,
formatTime,
hideDynamicTimeShortcuts,
specialShortcutOptions,
} from "discourse/lib/time-shortcut";
import discourseComputed, {
observes,
on,
} from "discourse-common/utils/decorators";
import Component from "@ember/component";
import I18n from "I18n";
import { action } from "@ember/object";
import { and, equal } from "@ember/object/computed";
const BINDINGS = {
"l t": {
handler: "selectShortcut",
args: [TIME_SHORTCUT_TYPES.LATER_TODAY],
},
"l w": {
handler: "selectShortcut",
args: [TIME_SHORTCUT_TYPES.LATER_THIS_WEEK],
},
"n d": {
handler: "selectShortcut",
args: [TIME_SHORTCUT_TYPES.TOMORROW],
},
"n b w": {
handler: "selectShortcut",
args: [TIME_SHORTCUT_TYPES.START_OF_NEXT_BUSINESS_WEEK],
},
"n m": {
handler: "selectShortcut",
args: [TIME_SHORTCUT_TYPES.NEXT_MONTH],
},
"c r": { handler: "selectShortcut", args: [TIME_SHORTCUT_TYPES.CUSTOM] },
"n r": { handler: "selectShortcut", args: [TIME_SHORTCUT_TYPES.NONE] },
};
export default Component.extend({
tagName: "",
userTimezone: null,
onTimeSelected: null,
selectedShortcut: null,
selectedTime: null,
selectedDate: null,
selectedDatetime: null,
prefilledDatetime: null,
hiddenOptions: null,
customOptions: null,
lastCustomDate: null,
lastCustomTime: null,
parsedLastCustomDatetime: null,
customDate: null,
customTime: null,
_itsatrap: null,
@on("init")
_setupPicker() {
this.setProperties({
userTimezone: this.currentUser.timezone,
hiddenOptions: this.hiddenOptions || [],
customOptions: this.customOptions || [],
customLabels: this.customLabels || {},
});
if (this.prefilledDatetime) {
this.parsePrefilledDatetime();
}
this._bindKeyboardShortcuts();
},
@observes("prefilledDatetime")
prefilledDatetimeChanged() {
if (this.prefilledDatetime) {
this.parsePrefilledDatetime();
} else {
this.setProperties({
customDate: null,
customTime: null,
selectedShortcut: null,
});
}
},
willDestroyElement() {
this._super(...arguments);
this._itsatrap.unbind(Object.keys(BINDINGS));
},
parsePrefilledDatetime() {
let parsedDatetime = parseCustomDatetime(
this.prefilledDatetime,
null,
this.userTimezone
);
if (parsedDatetime.isSame(laterToday())) {
return this.set("selectedShortcut", TIME_SHORTCUT_TYPES.LATER_TODAY);
}
this.setProperties({
customDate: parsedDatetime.format("YYYY-MM-DD"),
customTime: parsedDatetime.format("HH:mm"),
selectedShortcut: TIME_SHORTCUT_TYPES.CUSTOM,
});
},
_loadLastUsedCustomDatetime() {
const lastTime = this.keyValueStore.lastCustomTime;
const lastDate = this.keyValueStore.lastCustomDate;
if (lastTime && lastDate) {
let parsed = parseCustomDatetime(lastDate, lastTime, this.userTimezone);
if (!parsed.isValid() || parsed < now(this.userTimezone)) {
return;
}
this.setProperties({
lastCustomDate: lastDate,
lastCustomTime: lastTime,
parsedLastCustomDatetime: parsed,
});
}
},
_bindKeyboardShortcuts() {
Object.keys(BINDINGS).forEach((shortcut) => {
this._itsatrap.bind(shortcut, () => {
let binding = BINDINGS[shortcut];
this.send(binding.handler, ...binding.args);
return false;
});
});
},
customDatetimeSelected: equal("selectedShortcut", TIME_SHORTCUT_TYPES.CUSTOM),
relativeTimeSelected: equal("selectedShortcut", TIME_SHORTCUT_TYPES.RELATIVE),
customDatetimeFilled: and("customDate", "customTime"),
@observes("customDate", "customTime")
customDatetimeChanged() {
if (!this.customDatetimeFilled) {
return;
}
this.selectShortcut(TIME_SHORTCUT_TYPES.CUSTOM);
},
@discourseComputed(
"timeShortcuts",
"hiddenOptions",
"customLabels",
"userTimezone"
)
options(timeShortcuts, hiddenOptions, customLabels, userTimezone) {
this._loadLastUsedCustomDatetime();
let options;
if (timeShortcuts && timeShortcuts.length) {
options = timeShortcuts;
} else {
options = defaultTimeShortcuts(userTimezone);
}
options = hideDynamicTimeShortcuts(
options,
userTimezone,
this.siteSettings
);
let specialOptions = specialShortcutOptions();
if (this.lastCustomDate && this.lastCustomTime) {
let lastCustom = specialOptions.findBy(
"id",
TIME_SHORTCUT_TYPES.LAST_CUSTOM
);
lastCustom.time = this.parsedLastCustomDatetime;
lastCustom.timeFormatKey = "dates.long_no_year";
lastCustom.hidden = false;
}
options = options.concat(specialOptions);
if (hiddenOptions.length > 0) {
options.forEach((opt) => {
if (hiddenOptions.includes(opt.id)) {
opt.hidden = true;
}
});
}
this._applyCustomLabels(options, customLabels);
options.forEach((o) => (o.timeFormatted = formatTime(o)));
return options;
},
@action
relativeTimeChanged(relativeTimeMins) {
let dateTime = now(this.userTimezone).add(relativeTimeMins, "minutes");
this.set("selectedDatetime", dateTime);
if (this.onTimeSelected) {
this.onTimeSelected(TIME_SHORTCUT_TYPES.RELATIVE, dateTime);
}
},
@action
selectShortcut(type) {
if (this.options.filterBy("hidden").mapBy("id").includes(type)) {
return;
}
let dateTime = null;
if (type === TIME_SHORTCUT_TYPES.CUSTOM) {
const defaultCustomDateTime = this._defaultCustomDateTime();
this.set(
"customDate",
this.customDate || defaultCustomDateTime.format("YYYY-MM-DD")
);
this.set(
"customTime",
this.customTime || defaultCustomDateTime.format("HH:mm")
);
const customDatetime = parseCustomDatetime(
this.customDate,
this.customTime,
this.userTimezone
);
if (customDatetime.isValid() && this.customDate) {
dateTime = customDatetime;
this.keyValueStore.lastCustomTime = this.customTime;
this.keyValueStore.lastCustomDate = this.customDate;
}
} else {
dateTime = this.options.findBy("id", type).time;
}
this.setProperties({
selectedShortcut: type,
selectedDatetime: dateTime,
});
if (this.onTimeSelected) {
this.onTimeSelected(type, dateTime);
}
},
_applyCustomLabels(options, customLabels) {
options.forEach((option) => {
if (customLabels[option.id]) {
option.label = customLabels[option.id];
}
});
},
_formatTime(options) {
options.forEach((option) => {
if (option.time && option.timeFormatKey) {
option.timeFormatted = option.time.format(I18n.t(option.timeFormatKey));
}
});
},
_defaultCustomDateTime() {
return moment.tz(this.userTimezone).add(1, "hour");
},
});