FIX: Bookmark reminders and improvements changes (#9213)
* Cosmetic fixes for the bookmark modal * Do not show "later today" when the later time will be > 5pm * When a custom reminder time is selected, store it in localStorage. The next time the modal is opened, if the last datetime is > now, then a new tile with "Last" will be shown that lets the user reselect that same time. * Also add an explicit "No Reminder" option that is selected by default
This commit is contained in:
parent
a6e9057609
commit
4cce564b35
|
@ -7,6 +7,7 @@ import { htmlSafe } from "@ember/template";
|
|||
import { ajax } from "discourse/lib/ajax";
|
||||
|
||||
const START_OF_DAY_HOUR = 8;
|
||||
const LATER_TODAY_CUTOFF_HOUR = 17;
|
||||
const REMINDER_TYPES = {
|
||||
AT_DESKTOP: "at_desktop",
|
||||
LATER_TODAY: "later_today",
|
||||
|
@ -14,7 +15,9 @@ const REMINDER_TYPES = {
|
|||
TOMORROW: "tomorrow",
|
||||
NEXT_WEEK: "next_week",
|
||||
NEXT_MONTH: "next_month",
|
||||
CUSTOM: "custom"
|
||||
CUSTOM: "custom",
|
||||
LAST_CUSTOM: "last_custom",
|
||||
NONE: "none"
|
||||
};
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
|
@ -27,17 +30,42 @@ export default Controller.extend(ModalFunctionality, {
|
|||
onCloseWithoutSaving: null,
|
||||
customReminderDate: null,
|
||||
customReminderTime: null,
|
||||
lastCustomReminderDate: null,
|
||||
lastCustomReminderTime: null,
|
||||
|
||||
onShow() {
|
||||
this.setProperties({
|
||||
errorMessage: null,
|
||||
name: null,
|
||||
selectedReminderType: null,
|
||||
selectedReminderType: REMINDER_TYPES.NONE,
|
||||
closeWithoutSaving: false,
|
||||
isSavingBookmarkManually: false,
|
||||
customReminderDate: null,
|
||||
customReminderTime: null
|
||||
customReminderTime: null,
|
||||
lastCustomReminderDate: null,
|
||||
lastCustomReminderTime: null
|
||||
});
|
||||
|
||||
this.loadLastUsedCustomReminderDatetime();
|
||||
},
|
||||
|
||||
loadLastUsedCustomReminderDatetime() {
|
||||
let lastTime = localStorage.lastCustomBookmarkReminderTime;
|
||||
let lastDate = localStorage.lastCustomBookmarkReminderDate;
|
||||
|
||||
if (lastTime && lastDate) {
|
||||
let parsed = this.parseCustomDateTime(lastDate, lastTime);
|
||||
|
||||
if (parsed < this.now()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setProperties({
|
||||
lastCustomReminderDate: lastDate,
|
||||
lastCustomReminderTime: lastTime,
|
||||
parsedLastCustomReminderDatetime: parsed
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// we always want to save the bookmark unless the user specifically
|
||||
|
@ -71,9 +99,29 @@ export default Controller.extend(ModalFunctionality, {
|
|||
return REMINDER_TYPES;
|
||||
},
|
||||
|
||||
@discourseComputed()
|
||||
showLastCustom() {
|
||||
return this.lastCustomReminderTime && this.lastCustomReminderDate;
|
||||
},
|
||||
|
||||
@discourseComputed()
|
||||
showLaterToday() {
|
||||
return !this.laterToday().isSame(this.tomorrow(), "date");
|
||||
let later = this.laterToday();
|
||||
return (
|
||||
!later.isSame(this.tomorrow(), "date") &&
|
||||
later.hour() <= LATER_TODAY_CUTOFF_HOUR
|
||||
);
|
||||
},
|
||||
|
||||
@discourseComputed("parsedLastCustomReminderDatetime")
|
||||
lastCustomFormatted(parsedLastCustomReminderDatetime) {
|
||||
return htmlSafe(
|
||||
I18n.t("bookmarks.reminders.last_custom", {
|
||||
date: parsedLastCustomReminderDatetime.format(
|
||||
I18n.t("dates.long_no_year")
|
||||
)
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
@discourseComputed()
|
||||
|
@ -130,12 +178,26 @@ export default Controller.extend(ModalFunctionality, {
|
|||
const reminderAt = this.reminderAt();
|
||||
const reminderAtISO = reminderAt ? reminderAt.toISOString() : null;
|
||||
|
||||
if (!reminderAt && this.selectedReminderType === REMINDER_TYPES.CUSTOM) {
|
||||
return Promise.reject(I18n.t("bookmarks.invalid_custom_datetime"));
|
||||
if (this.selectedReminderType === REMINDER_TYPES.CUSTOM) {
|
||||
if (!reminderAt) {
|
||||
return Promise.reject(I18n.t("bookmarks.invalid_custom_datetime"));
|
||||
}
|
||||
|
||||
localStorage.lastCustomBookmarkReminderTime = this.customReminderTime;
|
||||
localStorage.lastCustomBookmarkReminderDate = this.customReminderDate;
|
||||
}
|
||||
|
||||
let reminderType;
|
||||
if (this.selectedReminderType === REMINDER_TYPES.NONE) {
|
||||
reminderType = null;
|
||||
} else if (this.selectedReminderType === REMINDER_TYPES.LAST_CUSTOM) {
|
||||
reminderType = REMINDER_TYPES.CUSTOM;
|
||||
} else {
|
||||
reminderType = this.selectedReminderType;
|
||||
}
|
||||
|
||||
const data = {
|
||||
reminder_type: this.selectedReminderType,
|
||||
reminder_type: reminderType,
|
||||
reminder_at: reminderAtISO,
|
||||
name: this.name,
|
||||
post_id: this.model.postId
|
||||
|
@ -148,6 +210,10 @@ export default Controller.extend(ModalFunctionality, {
|
|||
});
|
||||
},
|
||||
|
||||
parseCustomDateTime(date, time) {
|
||||
return moment.tz(date + " " + time, this.userTimezone());
|
||||
},
|
||||
|
||||
reminderAt() {
|
||||
if (!this.selectedReminderType) {
|
||||
return;
|
||||
|
@ -167,9 +233,9 @@ export default Controller.extend(ModalFunctionality, {
|
|||
case REMINDER_TYPES.NEXT_MONTH:
|
||||
return this.nextMonth();
|
||||
case REMINDER_TYPES.CUSTOM:
|
||||
const customDateTime = moment.tz(
|
||||
this.customReminderDate + " " + this.customReminderTime,
|
||||
this.userTimezone()
|
||||
const customDateTime = this.parseCustomDateTime(
|
||||
this.customReminderDate,
|
||||
this.customReminderTime
|
||||
);
|
||||
if (!customDateTime.isValid()) {
|
||||
this.setProperties({
|
||||
|
@ -179,6 +245,8 @@ export default Controller.extend(ModalFunctionality, {
|
|||
return;
|
||||
}
|
||||
return customDateTime;
|
||||
case REMINDER_TYPES.LAST_CUSTOM:
|
||||
return this.parsedLastCustomReminderDatetime;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -9,10 +9,6 @@
|
|||
{{/if}}
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="name">
|
||||
{{i18n 'post.bookmarks.name'}}
|
||||
</label>
|
||||
|
||||
{{input value=name name="name" class="bookmark-name" enter=(action "saveAndClose") placeholder=(i18n "post.bookmarks.name_placeholder")}}
|
||||
</div>
|
||||
|
||||
|
@ -36,6 +32,10 @@
|
|||
{{tap-tile icon="far-clock" text=nextWeekFormatted tileId=reminderTypes.NEXT_WEEK activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
||||
{{tap-tile icon="far-calendar-plus" text=nextMonthFormatted tileId=reminderTypes.NEXT_MONTH activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
||||
{{tap-tile icon="calendar-alt" text=(I18n "bookmarks.reminders.custom") tileId=reminderTypes.CUSTOM activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
||||
{{#if showLastCustom}}
|
||||
{{tap-tile icon="undo" text=lastCustomFormatted tileId=reminderTypes.LAST_CUSTOM activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
||||
{{/if}}
|
||||
{{tap-tile icon="ban" text=(I18n "bookmarks.reminders.none") tileId=reminderTypes.NONE activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
||||
{{/tap-tile-grid}}
|
||||
{{#if customDateTimeSelected}}
|
||||
<div class="control-group">
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
$horizontal-tile-padding: 5px;
|
||||
|
||||
.tap-tile {
|
||||
color: $primary-high;
|
||||
padding: 10px $horizontal-tile-padding;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
|
@ -321,6 +321,8 @@ en:
|
|||
next_week: "Next week <br/>{{date}}"
|
||||
next_month: "Next month <br/>{{date}}"
|
||||
custom: "Custom date and time"
|
||||
last_custom: "Last <br/>{{date}}"
|
||||
none: "No reminder needed"
|
||||
|
||||
drafts:
|
||||
resume: "Resume"
|
||||
|
@ -2676,8 +2678,8 @@ en:
|
|||
create: "Create bookmark"
|
||||
created: "Created"
|
||||
name: "Name"
|
||||
name_placeholder: "Name the bookmark to help jog your memory"
|
||||
set_reminder: "Set a reminder"
|
||||
name_placeholder: "What is this bookmark for?"
|
||||
set_reminder: "Remind me"
|
||||
actions:
|
||||
delete_bookmark:
|
||||
name: "Delete bookmark"
|
||||
|
|
|
@ -19,22 +19,27 @@ function mockMomentTz(dateString) {
|
|||
QUnit.test("showLaterToday when later today is tomorrow do not show", function(
|
||||
assert
|
||||
) {
|
||||
mockMomentTz("2019-12-11T13:00:00Z");
|
||||
mockMomentTz("2019-12-11T22:00:00");
|
||||
|
||||
assert.equal(BookmarkController.get("showLaterToday"), false);
|
||||
});
|
||||
|
||||
QUnit.test("showLaterToday when later today is after 5pm", function(assert) {
|
||||
mockMomentTz("2019-12-11T15:00:00");
|
||||
assert.equal(BookmarkController.get("showLaterToday"), false);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"showLaterToday when later today is before the end of the day, show",
|
||||
function(assert) {
|
||||
mockMomentTz("2019-12-11T08:00:00Z");
|
||||
mockMomentTz("2019-12-11T10:00:00");
|
||||
|
||||
assert.equal(BookmarkController.get("showLaterToday"), true);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("nextWeek gets next week correctly", function(assert) {
|
||||
mockMomentTz("2019-12-11T08:00:00Z");
|
||||
mockMomentTz("2019-12-11T08:00:00");
|
||||
|
||||
assert.equal(
|
||||
BookmarkController.nextWeek().format("YYYY-MM-DD"),
|
||||
|
@ -43,7 +48,7 @@ QUnit.test("nextWeek gets next week correctly", function(assert) {
|
|||
});
|
||||
|
||||
QUnit.test("nextMonth gets next month correctly", function(assert) {
|
||||
mockMomentTz("2019-12-11T08:00:00Z");
|
||||
mockMomentTz("2019-12-11T08:00:00");
|
||||
|
||||
assert.equal(
|
||||
BookmarkController.nextMonth().format("YYYY-MM-DD"),
|
||||
|
@ -54,7 +59,7 @@ QUnit.test("nextMonth gets next month correctly", function(assert) {
|
|||
QUnit.test(
|
||||
"nextBusinessDay gets next business day of monday correctly if today is friday",
|
||||
function(assert) {
|
||||
mockMomentTz("2019-12-13T08:00:00Z");
|
||||
mockMomentTz("2019-12-13T08:00:00");
|
||||
|
||||
assert.equal(
|
||||
BookmarkController.nextBusinessDay().format("YYYY-MM-DD"),
|
||||
|
@ -66,7 +71,7 @@ QUnit.test(
|
|||
QUnit.test(
|
||||
"nextBusinessDay gets next business day of monday correctly if today is saturday",
|
||||
function(assert) {
|
||||
mockMomentTz("2019-12-14T08:00:00Z");
|
||||
mockMomentTz("2019-12-14T08:00:00");
|
||||
|
||||
assert.equal(
|
||||
BookmarkController.nextBusinessDay().format("YYYY-MM-DD"),
|
||||
|
@ -78,7 +83,7 @@ QUnit.test(
|
|||
QUnit.test(
|
||||
"nextBusinessDay gets next business day of monday correctly if today is sunday",
|
||||
function(assert) {
|
||||
mockMomentTz("2019-12-15T08:00:00Z");
|
||||
mockMomentTz("2019-12-15T08:00:00");
|
||||
|
||||
assert.equal(
|
||||
BookmarkController.nextBusinessDay().format("YYYY-MM-DD"),
|
||||
|
@ -90,7 +95,7 @@ QUnit.test(
|
|||
QUnit.test(
|
||||
"nextBusinessDay gets next business day of thursday correctly if today is wednesday",
|
||||
function(assert) {
|
||||
mockMomentTz("2019-12-11T08:00:00Z");
|
||||
mockMomentTz("2019-12-11T08:00:00");
|
||||
|
||||
assert.equal(
|
||||
BookmarkController.nextBusinessDay().format("YYYY-MM-DD"),
|
||||
|
@ -100,7 +105,7 @@ QUnit.test(
|
|||
);
|
||||
|
||||
QUnit.test("tomorrow gets tomorrow correctly", function(assert) {
|
||||
mockMomentTz("2019-12-11T08:00:00Z");
|
||||
mockMomentTz("2019-12-11T08:00:00");
|
||||
|
||||
assert.equal(
|
||||
BookmarkController.tomorrow().format("YYYY-MM-DD"),
|
||||
|
@ -112,7 +117,7 @@ QUnit.test(
|
|||
"startOfDay changes the time of the provided date to 8:00am correctly",
|
||||
function(assert) {
|
||||
let dt = moment.tz(
|
||||
"2019-12-11T11:37:16Z",
|
||||
"2019-12-11T11:37:16",
|
||||
BookmarkController.currentUser.timezone
|
||||
);
|
||||
|
||||
|
@ -126,11 +131,11 @@ QUnit.test(
|
|||
QUnit.test(
|
||||
"laterToday gets 3 hours from now and if before half-past, it sets the time to half-past",
|
||||
function(assert) {
|
||||
mockMomentTz("2019-12-11T08:13:00Z");
|
||||
mockMomentTz("2019-12-11T08:13:00");
|
||||
|
||||
assert.equal(
|
||||
BookmarkController.laterToday().format("YYYY-MM-DD HH:mm:ss"),
|
||||
"2019-12-11 21:30:00"
|
||||
"2019-12-11 11:30:00"
|
||||
);
|
||||
}
|
||||
);
|
||||
|
@ -138,11 +143,39 @@ QUnit.test(
|
|||
QUnit.test(
|
||||
"laterToday gets 3 hours from now and if after half-past, it rounds up to the next hour",
|
||||
function(assert) {
|
||||
mockMomentTz("2019-12-11T08:43:00Z");
|
||||
mockMomentTz("2019-12-11T08:43:00");
|
||||
|
||||
assert.equal(
|
||||
BookmarkController.laterToday().format("YYYY-MM-DD HH:mm:ss"),
|
||||
"2019-12-11 22:00:00"
|
||||
"2019-12-11 12:00:00"
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"loadLastUsedCustomReminderDatetime fills the custom reminder date + time if present in localStorage",
|
||||
function(assert) {
|
||||
mockMomentTz("2019-12-11T08:00:00");
|
||||
localStorage.lastCustomBookmarkReminderDate = "2019-12-12";
|
||||
localStorage.lastCustomBookmarkReminderTime = "08:00";
|
||||
|
||||
BookmarkController.loadLastUsedCustomReminderDatetime();
|
||||
|
||||
assert.equal(BookmarkController.lastCustomReminderDate, "2019-12-12");
|
||||
assert.equal(BookmarkController.lastCustomReminderTime, "08:00");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"loadLastUsedCustomReminderDatetime does not fills the custom reminder date + time if the datetime in localStorage is < now",
|
||||
function(assert) {
|
||||
mockMomentTz("2019-12-11T08:00:00");
|
||||
localStorage.lastCustomBookmarkReminderDate = "2019-12-11";
|
||||
localStorage.lastCustomBookmarkReminderTime = "07:00";
|
||||
|
||||
BookmarkController.loadLastUsedCustomReminderDatetime();
|
||||
|
||||
assert.equal(BookmarkController.lastCustomReminderDate, null);
|
||||
assert.equal(BookmarkController.lastCustomReminderTime, null);
|
||||
}
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue