FEATURE: Bookmark reminder type changes and bugfixes (#9329)
New Reminder Types ------------------------------------- * Add a "later this week" reminder which is today + 2 days, will not show if we are on the days Thu-Sun * Add a "start of next business week" reminder which is 8am Monday Bugfixes and Tweaks -------------------------------------- * Move dates out of translation for reminder types and yield HTML for tap-tile for more customizable content and styling * Make sure double clicking the bookmark icon in quick access takes users to the new bookmarks-with-reminders page * Sane default to 8am (start of day) for custom reminder with no time
This commit is contained in:
parent
393215266f
commit
d261a809e2
|
@ -3,7 +3,6 @@ import { Promise } from "rsvp";
|
||||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
import { htmlSafe } from "@ember/template";
|
|
||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
|
|
||||||
const START_OF_DAY_HOUR = 8;
|
const START_OF_DAY_HOUR = 8;
|
||||||
|
@ -17,7 +16,9 @@ const REMINDER_TYPES = {
|
||||||
NEXT_MONTH: "next_month",
|
NEXT_MONTH: "next_month",
|
||||||
CUSTOM: "custom",
|
CUSTOM: "custom",
|
||||||
LAST_CUSTOM: "last_custom",
|
LAST_CUSTOM: "last_custom",
|
||||||
NONE: "none"
|
NONE: "none",
|
||||||
|
START_OF_NEXT_BUSINESS_WEEK: "start_of_next_business_week",
|
||||||
|
LATER_THIS_WEEK: "later_this_week"
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Controller.extend(ModalFunctionality, {
|
export default Controller.extend(ModalFunctionality, {
|
||||||
|
@ -115,60 +116,48 @@ export default Controller.extend(ModalFunctionality, {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@discourseComputed()
|
||||||
|
showLaterThisWeek() {
|
||||||
|
return this.now().day() < 4; // 4 is Thursday
|
||||||
|
},
|
||||||
|
|
||||||
@discourseComputed("parsedLastCustomReminderDatetime")
|
@discourseComputed("parsedLastCustomReminderDatetime")
|
||||||
lastCustomFormatted(parsedLastCustomReminderDatetime) {
|
lastCustomFormatted(parsedLastCustomReminderDatetime) {
|
||||||
return htmlSafe(
|
return parsedLastCustomReminderDatetime.format(
|
||||||
I18n.t("bookmarks.reminders.last_custom", {
|
I18n.t("dates.long_no_year")
|
||||||
date: parsedLastCustomReminderDatetime.format(
|
|
||||||
I18n.t("dates.long_no_year")
|
|
||||||
)
|
|
||||||
})
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@discourseComputed()
|
||||||
|
startNextBusinessWeekFormatted() {
|
||||||
|
return this.nextWeek()
|
||||||
|
.day("Monday")
|
||||||
|
.format(I18n.t("dates.long_no_year"));
|
||||||
|
},
|
||||||
|
|
||||||
@discourseComputed()
|
@discourseComputed()
|
||||||
laterTodayFormatted() {
|
laterTodayFormatted() {
|
||||||
return htmlSafe(
|
return this.laterToday().format(I18n.t("dates.time"));
|
||||||
I18n.t("bookmarks.reminders.later_today", {
|
|
||||||
date: this.laterToday().format(I18n.t("dates.time"))
|
|
||||||
})
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed()
|
@discourseComputed()
|
||||||
tomorrowFormatted() {
|
tomorrowFormatted() {
|
||||||
return htmlSafe(
|
return this.tomorrow().format(I18n.t("dates.time_short_day"));
|
||||||
I18n.t("bookmarks.reminders.tomorrow", {
|
|
||||||
date: this.tomorrow().format(I18n.t("dates.time_short_day"))
|
|
||||||
})
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
@discourseComputed()
|
|
||||||
nextBusinessDayFormatted() {
|
|
||||||
return htmlSafe(
|
|
||||||
I18n.t("bookmarks.reminders.next_business_day", {
|
|
||||||
date: this.nextBusinessDay().format(I18n.t("dates.time_short_day"))
|
|
||||||
})
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed()
|
@discourseComputed()
|
||||||
nextWeekFormatted() {
|
nextWeekFormatted() {
|
||||||
return htmlSafe(
|
return this.nextWeek().format(I18n.t("dates.long_no_year"));
|
||||||
I18n.t("bookmarks.reminders.next_week", {
|
},
|
||||||
date: this.nextWeek().format(I18n.t("dates.long_no_year"))
|
|
||||||
})
|
@discourseComputed()
|
||||||
);
|
laterThisWeekFormatted() {
|
||||||
|
return this.laterThisWeek().format(I18n.t("dates.time_short_day"));
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed()
|
@discourseComputed()
|
||||||
nextMonthFormatted() {
|
nextMonthFormatted() {
|
||||||
return htmlSafe(
|
return this.nextMonth().format(I18n.t("dates.long_no_year"));
|
||||||
I18n.t("bookmarks.reminders.next_month", {
|
|
||||||
date: this.nextMonth().format(I18n.t("dates.long_no_year"))
|
|
||||||
})
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed()
|
@discourseComputed()
|
||||||
|
@ -237,9 +226,17 @@ export default Controller.extend(ModalFunctionality, {
|
||||||
return this.tomorrow();
|
return this.tomorrow();
|
||||||
case REMINDER_TYPES.NEXT_WEEK:
|
case REMINDER_TYPES.NEXT_WEEK:
|
||||||
return this.nextWeek();
|
return this.nextWeek();
|
||||||
|
case REMINDER_TYPES.START_OF_NEXT_BUSINESS_WEEK:
|
||||||
|
return this.nextWeek().day("Monday");
|
||||||
|
case REMINDER_TYPES.LATER_THIS_WEEK:
|
||||||
|
return this.laterThisWeek();
|
||||||
case REMINDER_TYPES.NEXT_MONTH:
|
case REMINDER_TYPES.NEXT_MONTH:
|
||||||
return this.nextMonth();
|
return this.nextMonth();
|
||||||
case REMINDER_TYPES.CUSTOM:
|
case REMINDER_TYPES.CUSTOM:
|
||||||
|
this.set(
|
||||||
|
"customReminderTime",
|
||||||
|
this.customReminderTime || `0${START_OF_DAY_HOUR}:00`
|
||||||
|
);
|
||||||
const customDateTime = this.parseCustomDateTime(
|
const customDateTime = this.parseCustomDateTime(
|
||||||
this.customReminderDate,
|
this.customReminderDate,
|
||||||
this.customReminderTime
|
this.customReminderTime
|
||||||
|
@ -265,23 +262,6 @@ export default Controller.extend(ModalFunctionality, {
|
||||||
return this.startOfDay(this.now().add(1, "month"));
|
return this.startOfDay(this.now().add(1, "month"));
|
||||||
},
|
},
|
||||||
|
|
||||||
nextBusinessDay() {
|
|
||||||
const currentDay = this.now().isoWeekday(); // 1=Mon, 7=Sun
|
|
||||||
let next = null;
|
|
||||||
|
|
||||||
// friday
|
|
||||||
if (currentDay === 5) {
|
|
||||||
next = this.now().add(3, "days");
|
|
||||||
// saturday
|
|
||||||
} else if (currentDay === 6) {
|
|
||||||
next = this.now().add(2, "days");
|
|
||||||
} else {
|
|
||||||
next = this.now().add(1, "day");
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.startOfDay(next);
|
|
||||||
},
|
|
||||||
|
|
||||||
tomorrow() {
|
tomorrow() {
|
||||||
return this.startOfDay(this.now().add(1, "day"));
|
return this.startOfDay(this.now().add(1, "day"));
|
||||||
},
|
},
|
||||||
|
@ -301,6 +281,13 @@ export default Controller.extend(ModalFunctionality, {
|
||||||
: later.add(30, "minutes").startOf("hour");
|
: later.add(30, "minutes").startOf("hour");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
laterThisWeek() {
|
||||||
|
if (!this.showLaterThisWeek) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return this.startOfDay(this.now().add(2, "days"));
|
||||||
|
},
|
||||||
|
|
||||||
handleSaveError(e) {
|
handleSaveError(e) {
|
||||||
this.isSavingBookmarkManually = false;
|
this.isSavingBookmarkManually = false;
|
||||||
if (typeof e === "string") {
|
if (typeof e === "string") {
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
{{d-icon icon}}
|
{{d-icon icon}}
|
||||||
{{text}}
|
{{ yield }}
|
||||||
|
|
|
@ -21,21 +21,51 @@
|
||||||
{{#if userHasTimezoneSet}}
|
{{#if userHasTimezoneSet}}
|
||||||
{{#tap-tile-grid activeTile=selectedReminderType as |grid|}}
|
{{#tap-tile-grid activeTile=selectedReminderType as |grid|}}
|
||||||
{{#if showAtDesktop}}
|
{{#if showAtDesktop}}
|
||||||
{{tap-tile icon="desktop" text=(i18n "bookmarks.reminders.at_desktop") tileId=reminderTypes.AT_DESKTOP activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
{{#tap-tile icon="desktop" tileId=reminderTypes.AT_DESKTOP activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
||||||
|
{{i18n "bookmarks.reminders.at_desktop"}}
|
||||||
|
{{/tap-tile}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if showLaterToday}}
|
{{#if showLaterToday}}
|
||||||
{{tap-tile icon="far-moon" text=laterTodayFormatted tileId=reminderTypes.LATER_TODAY activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
{{#tap-tile icon="far-moon" tileId=reminderTypes.LATER_TODAY activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
||||||
|
{{i18n "bookmarks.reminders.later_today"}}<br>
|
||||||
|
{{laterTodayFormatted}}
|
||||||
|
{{/tap-tile}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{tap-tile icon="briefcase" text=nextBusinessDayFormatted tileId=reminderTypes.NEXT_BUSINESS_DAY activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
{{#tap-tile icon="far-sun" tileId=reminderTypes.TOMORROW activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
||||||
{{tap-tile icon="far-sun" text=tomorrowFormatted tileId=reminderTypes.TOMORROW activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
{{i18n "bookmarks.reminders.tomorrow"}}<br>
|
||||||
{{tap-tile icon="far-clock" text=nextWeekFormatted tileId=reminderTypes.NEXT_WEEK activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
{{tomorrowFormatted}}
|
||||||
{{tap-tile icon="far-calendar-plus" text=nextMonthFormatted tileId=reminderTypes.NEXT_MONTH activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
{{/tap-tile}}
|
||||||
{{tap-tile icon="calendar-alt" text=(I18n "bookmarks.reminders.custom") tileId=reminderTypes.CUSTOM activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
{{#if showLaterThisWeek}}
|
||||||
|
{{#tap-tile icon="angle-double-right" tileId=reminderTypes.LATER_THIS_WEEK activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
||||||
|
{{i18n "bookmarks.reminders.later_this_week"}}<br>
|
||||||
|
{{laterThisWeekFormatted}}
|
||||||
|
{{/tap-tile}}
|
||||||
|
{{/if}}
|
||||||
|
{{#tap-tile icon="briefcase" tileId=reminderTypes.START_OF_NEXT_BUSINESS_WEEK activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
||||||
|
{{i18n "bookmarks.reminders.start_of_next_business_week"}}<br>
|
||||||
|
{{startNextBusinessWeekFormatted}}
|
||||||
|
{{/tap-tile}}
|
||||||
|
{{#tap-tile icon="far-clock" tileId=reminderTypes.NEXT_WEEK activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
||||||
|
{{i18n "bookmarks.reminders.next_week"}}<br>
|
||||||
|
{{nextWeekFormatted}}
|
||||||
|
{{/tap-tile}}
|
||||||
|
{{#tap-tile icon="far-calendar-plus" tileId=reminderTypes.NEXT_MONTH activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
||||||
|
{{i18n "bookmarks.reminders.next_month"}}<br>
|
||||||
|
{{nextMonthFormatted}}
|
||||||
|
{{/tap-tile}}
|
||||||
|
{{#tap-tile icon="calendar-alt" tileId=reminderTypes.CUSTOM activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
||||||
|
{{i18n "bookmarks.reminders.custom"}}
|
||||||
|
{{/tap-tile}}
|
||||||
{{#if showLastCustom}}
|
{{#if showLastCustom}}
|
||||||
{{tap-tile icon="undo" text=lastCustomFormatted tileId=reminderTypes.LAST_CUSTOM activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
{{#tap-tile icon="undo" tileId=reminderTypes.LAST_CUSTOM activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
||||||
|
{{i18n "bookmarks.reminders.last_custom"}}<br>
|
||||||
|
{{lastCustomFormatted}}
|
||||||
|
{{/tap-tile}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{tap-tile icon="ban" text=(I18n "bookmarks.reminders.none") tileId=reminderTypes.NONE activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
{{#tap-tile icon="ban" tileId=reminderTypes.NONE activeTile=grid.activeTile onChange=(action "selectReminderType")}}
|
||||||
|
{{i18n "bookmarks.reminders.none"}}
|
||||||
|
{{/tap-tile}}
|
||||||
{{/tap-tile-grid}}
|
{{/tap-tile-grid}}
|
||||||
{{#if customDateTimeSelected}}
|
{{#if customDateTimeSelected}}
|
||||||
<div class="control-group custom-date-time-wrap">
|
<div class="control-group custom-date-time-wrap">
|
||||||
|
|
|
@ -56,13 +56,16 @@ createWidget("user-menu-links", {
|
||||||
},
|
},
|
||||||
|
|
||||||
bookmarksGlyph() {
|
bookmarksGlyph() {
|
||||||
|
let path = this.siteSettings.enable_bookmarks_with_reminders
|
||||||
|
? "bookmarks-with-reminders"
|
||||||
|
: "bookmarks";
|
||||||
return {
|
return {
|
||||||
action: UserMenuAction.QUICK_ACCESS,
|
action: UserMenuAction.QUICK_ACCESS,
|
||||||
actionParam: QuickAccess.BOOKMARKS,
|
actionParam: QuickAccess.BOOKMARKS,
|
||||||
label: "user.bookmarks",
|
label: "user.bookmarks",
|
||||||
className: "user-bookmarks-link",
|
className: "user-bookmarks-link",
|
||||||
icon: "bookmark",
|
icon: "bookmark",
|
||||||
href: `${this.attrs.path}/activity/bookmarks`
|
href: `${this.attrs.path}/activity/${path}`
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,9 @@ class Bookmark < ActiveRecord::Base
|
||||||
tomorrow: 3,
|
tomorrow: 3,
|
||||||
next_week: 4,
|
next_week: 4,
|
||||||
next_month: 5,
|
next_month: 5,
|
||||||
custom: 6
|
custom: 6,
|
||||||
|
start_of_next_business_week: 7,
|
||||||
|
later_this_week: 8
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -316,13 +316,15 @@ en:
|
||||||
list_permission_denied: "You do not have permission to view this user's bookmarks."
|
list_permission_denied: "You do not have permission to view this user's bookmarks."
|
||||||
reminders:
|
reminders:
|
||||||
at_desktop: "Next time I'm at my desktop"
|
at_desktop: "Next time I'm at my desktop"
|
||||||
later_today: "Later today <br/>{{date}}"
|
later_today: "Later today"
|
||||||
next_business_day: "Next business day <br/>{{date}}"
|
next_business_day: "Next business day"
|
||||||
tomorrow: "Tomorrow <br/>{{date}}"
|
tomorrow: "Tomorrow"
|
||||||
next_week: "Next week <br/>{{date}}"
|
next_week: "Next week"
|
||||||
next_month: "Next month <br/>{{date}}"
|
later_this_week: "Later this week"
|
||||||
|
start_of_next_business_week: "Next Monday"
|
||||||
|
next_month: "Next month"
|
||||||
custom: "Custom date and time"
|
custom: "Custom date and time"
|
||||||
last_custom: "Last <br/>{{date}}"
|
last_custom: "Last"
|
||||||
none: "No reminder needed"
|
none: "No reminder needed"
|
||||||
|
|
||||||
drafts:
|
drafts:
|
||||||
|
|
|
@ -6,6 +6,7 @@ moduleFor("controller:bookmark", {
|
||||||
beforeEach() {
|
beforeEach() {
|
||||||
logIn();
|
logIn();
|
||||||
BookmarkController = this.subject({ currentUser: User.current() });
|
BookmarkController = this.subject({ currentUser: User.current() });
|
||||||
|
BookmarkController.onShow();
|
||||||
},
|
},
|
||||||
|
|
||||||
afterEach() {
|
afterEach() {
|
||||||
|
@ -58,54 +59,34 @@ QUnit.test("nextMonth gets next month correctly", function(assert) {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test(
|
QUnit.test("laterThisWeek gets 2 days from now", function(assert) {
|
||||||
"nextBusinessDay gets next business day of monday correctly if today is friday",
|
mockMomentTz("2019-12-10T08:00:00");
|
||||||
function(assert) {
|
|
||||||
mockMomentTz("2019-12-13T08:00:00");
|
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
BookmarkController.nextBusinessDay().format("YYYY-MM-DD"),
|
BookmarkController.laterThisWeek().format("YYYY-MM-DD"),
|
||||||
"2019-12-16"
|
"2019-12-12"
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
QUnit.test(
|
QUnit.test("laterThisWeek returns null if we are at Thursday already", function(
|
||||||
"nextBusinessDay gets next business day of monday correctly if today is saturday",
|
assert
|
||||||
function(assert) {
|
) {
|
||||||
mockMomentTz("2019-12-14T08:00:00");
|
mockMomentTz("2019-12-12T08:00:00");
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(BookmarkController.laterThisWeek(), null);
|
||||||
BookmarkController.nextBusinessDay().format("YYYY-MM-DD"),
|
});
|
||||||
"2019-12-16"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
QUnit.test(
|
QUnit.test("showLaterThisWeek returns true if < Thursday", function(assert) {
|
||||||
"nextBusinessDay gets next business day of monday correctly if today is sunday",
|
mockMomentTz("2019-12-10T08:00:00");
|
||||||
function(assert) {
|
|
||||||
mockMomentTz("2019-12-15T08:00:00");
|
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(BookmarkController.showLaterThisWeek, true);
|
||||||
BookmarkController.nextBusinessDay().format("YYYY-MM-DD"),
|
});
|
||||||
"2019-12-16"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
QUnit.test(
|
QUnit.test("showLaterThisWeek returns false if > Thursday", function(assert) {
|
||||||
"nextBusinessDay gets next business day of thursday correctly if today is wednesday",
|
mockMomentTz("2019-12-12T08:00:00");
|
||||||
function(assert) {
|
|
||||||
mockMomentTz("2019-12-11T08:00:00");
|
|
||||||
|
|
||||||
assert.equal(
|
|
||||||
BookmarkController.nextBusinessDay().format("YYYY-MM-DD"),
|
|
||||||
"2019-12-12"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
assert.equal(BookmarkController.showLaterThisWeek, false);
|
||||||
|
});
|
||||||
QUnit.test("tomorrow gets tomorrow correctly", function(assert) {
|
QUnit.test("tomorrow gets tomorrow correctly", function(assert) {
|
||||||
mockMomentTz("2019-12-11T08:00:00");
|
mockMomentTz("2019-12-11T08:00:00");
|
||||||
|
|
||||||
|
@ -154,6 +135,27 @@ QUnit.test(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
QUnit.test(
|
||||||
|
"reminderAt - custom - defaults to 8:00am if the time is not selected",
|
||||||
|
function(assert) {
|
||||||
|
BookmarkController.customReminderDate = "2028-12-12";
|
||||||
|
BookmarkController.selectedReminderType =
|
||||||
|
BookmarkController.reminderTypes.CUSTOM;
|
||||||
|
const reminderAt = BookmarkController.reminderAt();
|
||||||
|
assert.equal(BookmarkController.customReminderTime, "08:00");
|
||||||
|
assert.equal(
|
||||||
|
reminderAt.toString(),
|
||||||
|
moment
|
||||||
|
.tz(
|
||||||
|
"2028-12-12 08:00",
|
||||||
|
BookmarkController.currentUser.resolvedTimezone()
|
||||||
|
)
|
||||||
|
.toString(),
|
||||||
|
"the custom date and time are parsed correctly with default time"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
QUnit.test(
|
QUnit.test(
|
||||||
"loadLastUsedCustomReminderDatetime fills the custom reminder date + time if present in localStorage",
|
"loadLastUsedCustomReminderDatetime fills the custom reminder date + time if present in localStorage",
|
||||||
function(assert) {
|
function(assert) {
|
||||||
|
|
Loading…
Reference in New Issue