DEV: Remove user options from current user serializer (#19089)

User options were serialized at the root level of CurrentUserSerializer,
but UserSerializer has a user_option field. This inconsistency caused
issues in the past because user_option fields had to be duplicated on
the frontend.
This commit is contained in:
Bianca Nenciu 2022-12-05 18:25:30 +02:00 committed by GitHub
parent 68c4f16a73
commit 7d7551adfc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
68 changed files with 368 additions and 324 deletions

View File

@ -31,7 +31,7 @@ export default Route.extend({
model, model,
parentController, parentController,
allThemes: parentController.get("model"), allThemes: parentController.get("model"),
colorSchemeId: model.get("color_scheme_id"), colorSchemeId: model.get("user_option.color_scheme_id"),
colorSchemes: parentController.get("model.extras.color_schemes"), colorSchemes: parentController.get("model.extras.color_schemes"),
editingName: false, editingName: false,
}); });

View File

@ -41,7 +41,7 @@ export default class BookmarkIcon extends Component {
if (!isEmpty(this.bookmark.reminder_at)) { if (!isEmpty(this.bookmark.reminder_at)) {
const formattedTime = formattedReminderTime( const formattedTime = formattedReminderTime(
this.bookmark.reminder_at, this.bookmark.reminder_at,
this.currentUser.timezone this.currentUser.user_option.timezone
); );
return I18n.t("bookmarks.created_with_reminder_generic", { return I18n.t("bookmarks.created_with_reminder_generic", {
date: formattedTime, date: formattedTime,

View File

@ -57,7 +57,7 @@ export default Component.extend({
postDetectedLocalTime: null, postDetectedLocalTime: null,
postDetectedLocalTimezone: null, postDetectedLocalTimezone: null,
prefilledDatetime: null, prefilledDatetime: null,
userTimezone: this.currentUser.timezone, userTimezone: this.currentUser.user_option.timezone,
showOptions: false, showOptions: false,
_itsatrap: new ItsATrap(), _itsatrap: new ItsATrap(),
autoDeletePreference: this.model.autoDeletePreference || 0, autoDeletePreference: this.model.autoDeletePreference || 0,
@ -154,7 +154,7 @@ export default Component.extend({
} }
this.currentUser.set( this.currentUser.set(
"bookmark_auto_delete_preference", "user_option.bookmark_auto_delete_preference",
this.autoDeletePreference this.autoDeletePreference
); );

View File

@ -84,7 +84,7 @@ export default Component.extend({
@discourseComputed() @discourseComputed()
timeOptions() { timeOptions() {
const timezone = this.currentUser.timezone; const timezone = this.currentUser.user_option.timezone;
const shortcuts = timeShortcuts(timezone); const shortcuts = timeShortcuts(timezone);
return [ return [

View File

@ -28,7 +28,7 @@ export default Component.extend({
init() { init() {
this._super(...arguments); this._super(...arguments);
this.userTimezone = this.currentUser.timezone; this.userTimezone = this.currentUser.user_option.timezone;
}, },
didReceiveAttrs() { didReceiveAttrs() {

View File

@ -424,7 +424,7 @@ export default Component.extend(KeyEnterEscape, {
embedQuoteButton(canCreatePost, canReplyAsNewTopic) { embedQuoteButton(canCreatePost, canReplyAsNewTopic) {
return ( return (
(canCreatePost || canReplyAsNewTopic) && (canCreatePost || canReplyAsNewTopic) &&
this.currentUser?.get("enable_quoting") this.currentUser?.get("user_option.enable_quoting")
); );
}, },

View File

@ -68,7 +68,7 @@ export default Component.extend({
@on("init") @on("init")
_setupPicker() { _setupPicker() {
this.setProperties({ this.setProperties({
userTimezone: this.currentUser.timezone, userTimezone: this.currentUser.user_option.timezone,
hiddenOptions: this.hiddenOptions || [], hiddenOptions: this.hiddenOptions || [],
customOptions: this.customOptions || [], customOptions: this.customOptions || [],
customLabels: this.customLabels || {}, customLabels: this.customLabels || {},

View File

@ -56,7 +56,7 @@ export default Component.extend({
canInviteTo: alias("topic.details.can_invite_to"), canInviteTo: alias("topic.details.can_invite_to"),
canDefer: alias("currentUser.enable_defer"), canDefer: alias("currentUser.user_option.enable_defer"),
inviteDisabled: or("topic.archived", "topic.closed", "topic.deleted"), inviteDisabled: or("topic.archived", "topic.closed", "topic.deleted"),

View File

@ -92,7 +92,7 @@ export default Component.extend(CardContentsBase, CanCheckEmails, CleansUp, {
if (!this.showUserLocalTime) { if (!this.showUserLocalTime) {
return; return;
} }
return user.timezone; return user.get("user_option.timezone");
}, },
@discourseComputed("userTimezone") @discourseComputed("userTimezone")

View File

@ -83,7 +83,7 @@ const CORE_TOP_TABS = [
} }
get shouldDisplay() { get shouldDisplay() {
return !this.currentUser.likes_notifications_disabled; return !this.currentUser.user_option.likes_notifications_disabled;
} }
get count() { get count() {

View File

@ -14,7 +14,7 @@ export default class UserStatusMessage extends Component {
return until( return until(
this.status.ends_at, this.status.ends_at,
this.currentUser.timezone, this.currentUser.user_option.timezone,
this.currentUser.locale this.currentUser.locale
); );
} }

View File

@ -192,7 +192,7 @@ export default Controller.extend(
@discourseComputed @discourseComputed
timeShortcuts() { timeShortcuts() {
const timezone = this.currentUser.timezone; const timezone = this.currentUser.user_option.timezone;
const shortcuts = timeShortcuts(timezone); const shortcuts = timeShortcuts(timezone);
return [ return [
shortcuts.laterToday(), shortcuts.laterToday(),

View File

@ -22,7 +22,7 @@ const controllerOpts = {
canStar: alias("currentUser.id"), canStar: alias("currentUser.id"),
showTopicPostBadges: not("new"), showTopicPostBadges: not("new"),
redirectedReason: alias("currentUser.redirected_to_top.reason"), redirectedReason: alias("currentUser.user_option.redirected_to_top.reason"),
expandGloballyPinned: false, expandGloballyPinned: false,
expandAllPinned: false, expandAllPinned: false,

View File

@ -10,10 +10,10 @@ export default Controller.extend(ModalFunctionality, {
@action @action
downloadCalendar() { downloadCalendar() {
if (this.remember) { if (this.remember) {
this.currentUser.setProperties({ this.currentUser.user_option.set(
default_calendar: this.selectedCalendar, "default_calendar",
user_option: { default_calendar: this.selectedCalendar }, this.selectedCalendar
}); );
this.currentUser.save(["default_calendar"]); this.currentUser.save(["default_calendar"]);
} }
if (this.selectedCalendar === "ics") { if (this.selectedCalendar === "ics") {

View File

@ -110,7 +110,7 @@ export default Controller.extend(ModalFunctionality, {
@discourseComputed @discourseComputed
timeShortcuts() { timeShortcuts() {
const timezone = this.currentUser.timezone; const timezone = this.currentUser.user_option.timezone;
const shortcuts = timeShortcuts(timezone); const shortcuts = timeShortcuts(timezone);
const nextWeek = shortcuts.monday(); const nextWeek = shortcuts.monday();

View File

@ -13,7 +13,7 @@ export default Controller.extend(ModalFunctionality, {
@discourseComputed @discourseComputed
timeShortcuts() { timeShortcuts() {
const timezone = this.currentUser.timezone; const timezone = this.currentUser.user_option.timezone;
const shortcuts = timeShortcuts(timezone); const shortcuts = timeShortcuts(timezone);
return [ return [
shortcuts.laterToday(), shortcuts.laterToday(),

View File

@ -11,7 +11,7 @@ export default Controller.extend(ModalFunctionality, {
@discourseComputed @discourseComputed
timeShortcuts() { timeShortcuts() {
const timezone = this.currentUser.timezone; const timezone = this.currentUser.user_option.timezone;
const shortcuts = timeShortcuts(timezone); const shortcuts = timeShortcuts(timezone);
return [ return [
shortcuts.laterToday(), shortcuts.laterToday(),

View File

@ -51,7 +51,7 @@ export default Controller.extend({
}); });
}, },
@discourseComputed("model.default_calendar") @discourseComputed("model.user_option.default_calendar")
canChangeDefaultCalendar(defaultCalendar) { canChangeDefaultCalendar(defaultCalendar) {
return defaultCalendar !== "none_selected"; return defaultCalendar !== "none_selected";
}, },
@ -125,12 +125,6 @@ export default Controller.extend({
return model return model
.save(this.saveAttrNames) .save(this.saveAttrNames)
.then(() => { .then(() => {
// update the timezone in memory so we can use the new
// one if we change routes without reloading the user
if (this.currentUser.id === this.model.id) {
this.currentUser.timezone = this.model.user_option.timezone;
}
cookAsync(model.get("bio_raw")) cookAsync(model.get("bio_raw"))
.then(() => { .then(() => {
model.set("bio_cooked"); model.set("bio_cooked");

View File

@ -62,7 +62,7 @@ addBulkButton("deletePostTiming", "defer", {
icon: "circle", icon: "circle",
class: "btn-default", class: "btn-default",
buttonVisible() { buttonVisible() {
return this.currentUser.enable_defer; return this.currentUser.user_option.enable_defer;
}, },
}); });
addBulkButton("unlistTopics", "unlist_topics", { addBulkButton("unlistTopics", "unlist_topics", {

View File

@ -837,7 +837,7 @@ export default Controller.extend(bufferedProperty("model"), {
bookmarkable_id: post.id, bookmarkable_id: post.id,
bookmarkable_type: "Post", bookmarkable_type: "Post",
auto_delete_preference: auto_delete_preference:
this.currentUser.bookmark_auto_delete_preference, this.currentUser.user_option.bookmark_auto_delete_preference,
}), }),
post post
); );
@ -1350,7 +1350,7 @@ export default Controller.extend(bufferedProperty("model"), {
bookmarkable_id: this.model.id, bookmarkable_id: this.model.id,
bookmarkable_type: "Topic", bookmarkable_type: "Topic",
auto_delete_preference: auto_delete_preference:
this.currentUser.bookmark_auto_delete_preference, this.currentUser.user_option.bookmark_auto_delete_preference,
}) })
); );
} }
@ -1781,7 +1781,7 @@ export default Controller.extend(bufferedProperty("model"), {
if ( if (
this.siteSettings.automatically_unpin_topics && this.siteSettings.automatically_unpin_topics &&
this.currentUser && this.currentUser &&
this.currentUser.automatically_unpin_topics this.currentUser.user_option.automatically_unpin_topics
) { ) {
// automatically unpin topics when the user reaches the bottom // automatically unpin topics when the user reaches the bottom
const max = Math.max(...postNumbers); const max = Math.max(...postNumbers);

View File

@ -84,7 +84,7 @@ export default Controller.extend(ModalFunctionality, {
}, },
_buildTimeShortcuts() { _buildTimeShortcuts() {
const timezone = this.currentUser.timezone; const timezone = this.currentUser.user_option.timezone;
const shortcuts = timeShortcuts(timezone); const shortcuts = timeShortcuts(timezone);
return [shortcuts.oneHour(), shortcuts.twoHours(), shortcuts.tomorrow()]; return [shortcuts.oneHour(), shortcuts.twoHours(), shortcuts.tomorrow()];
}, },

View File

@ -54,7 +54,9 @@ export function isValidLink(link) {
export function shouldOpenInNewTab(href) { export function shouldOpenInNewTab(href) {
const isInternal = DiscourseURL.isInternal(href); const isInternal = DiscourseURL.isInternal(href);
const openExternalInNewTab = User.currentProp("external_links_in_new_tab"); const openExternalInNewTab = User.currentProp(
"user_option.external_links_in_new_tab"
);
return !isInternal && openExternalInNewTab; return !isInternal && openExternalInNewTab;
} }

View File

@ -8,7 +8,7 @@ export function downloadCalendar(title, dates) {
const formattedDates = formatDates(dates); const formattedDates = formatDates(dates);
title = title.trim(); title = title.trim();
switch (currentUser.default_calendar) { switch (currentUser.user_option.default_calendar) {
case "none_selected": case "none_selected":
_displayModal(title, formattedDates); _displayModal(title, formattedDates);
break; break;

View File

@ -10,7 +10,9 @@ export function addFeaturedLinkMetaDecorator(decorator) {
export function extractLinkMeta(topic) { export function extractLinkMeta(topic) {
const href = topic.get("featured_link"); const href = topic.get("featured_link");
const target = User.currentProp("external_links_in_new_tab") ? "_blank" : ""; const target = User.currentProp("user_option.external_links_in_new_tab")
? "_blank"
: "";
const domain = topic.get("featured_link_root_domain"); const domain = topic.get("featured_link_root_domain");
let allowList = topic.siteSettings.exclude_rel_nofollow_domains; let allowList = topic.siteSettings.exclude_rel_nofollow_domains;
let rel = "nofollow ugc"; let rel = "nofollow ugc";

View File

@ -130,7 +130,10 @@ const Bookmark = RestModel.extend({
@discourseComputed("reminder_at", "currentUser") @discourseComputed("reminder_at", "currentUser")
formattedReminder(bookmarkReminderAt, currentUser) { formattedReminder(bookmarkReminderAt, currentUser) {
return capitalize( return capitalize(
formattedReminderTime(bookmarkReminderAt, currentUser.timezone) formattedReminderTime(
bookmarkReminderAt,
currentUser.user_option.timezone
)
); );
}, },

View File

@ -1,4 +1,5 @@
import EmberObject, { computed, get, getProperties } from "@ember/object"; import EmberObject, { computed, get, getProperties } from "@ember/object";
import { camelize } from "@ember/string";
import cookie, { removeCookie } from "discourse/lib/cookie"; import cookie, { removeCookie } from "discourse/lib/cookie";
import { defaultHomepage, escapeExpression } from "discourse/lib/utilities"; import { defaultHomepage, escapeExpression } from "discourse/lib/utilities";
import { import {
@ -130,15 +131,65 @@ export function addSaveableUserOptionField(fieldName) {
userOptionFields.push(fieldName); userOptionFields.push(fieldName);
} }
function userOption(userOptionKey) {
return computed(`user_option.${userOptionKey}`, {
get(key) {
deprecated(
`Getting ${key} property of user object is deprecated. Use user_option object instead`,
{
id: "discourse.user.userOptions",
since: "2.9.0.beta12",
dropFrom: "3.0.0.beta1",
}
);
return this.get(`user_option.${key}`);
},
set(key, value) {
deprecated(
`Setting ${key} property of user object is deprecated. Use user_option object instead`,
{
id: "discourse.user.userOptions",
since: "2.9.0.beta12",
dropFrom: "3.0.0.beta1",
}
);
if (!this.user_option) {
this.set("user_option", {});
}
return this.set(`user_option.${key}`, value);
},
});
}
const User = RestModel.extend({ const User = RestModel.extend({
mailing_list_mode: userOption("mailing_list_mode"),
external_links_in_new_tab: userOption("external_links_in_new_tab"),
enable_quoting: userOption("enable_quoting"),
dynamic_favicon: userOption("dynamic_favicon"),
automatically_unpin_topics: userOption("automatically_unpin_topics"),
likes_notifications_disabled: userOption("likes_notifications_disabled"),
hide_profile_and_presence: userOption("hide_profile_and_presence"),
title_count_mode: userOption("title_count_mode"),
enable_defer: userOption("enable_defer"),
timezone: userOption("timezone"),
skip_new_user_tips: userOption("skip_new_user_tips"),
default_calendar: userOption("default_calendar"),
bookmark_auto_delete_preference: userOption(
"bookmark_auto_delete_preference"
),
seen_popups: userOption("seen_popups"),
should_be_redirected_to_top: userOption("should_be_redirected_to_top"),
redirected_to_top: userOption("redirected_to_top"),
treat_as_new_topic_start_date: userOption("treat_as_new_topic_start_date"),
hasPMs: gt("private_messages_stats.all", 0), hasPMs: gt("private_messages_stats.all", 0),
hasStartedPMs: gt("private_messages_stats.mine", 0), hasStartedPMs: gt("private_messages_stats.mine", 0),
hasUnreadPMs: gt("private_messages_stats.unread", 0), hasUnreadPMs: gt("private_messages_stats.unread", 0),
redirected_to_top: {
reason: null,
},
@discourseComputed("can_be_deleted", "post_count") @discourseComputed("can_be_deleted", "post_count")
canBeDeleted(canBeDeleted, postCount) { canBeDeleted(canBeDeleted, postCount) {
const maxPostCount = this.siteSettings.delete_all_posts_max; const maxPostCount = this.siteSettings.delete_all_posts_max;
@ -376,20 +427,15 @@ const User = RestModel.extend({
userFields.filter((uf) => !fields || fields.includes(uf)) userFields.filter((uf) => !fields || fields.includes(uf))
); );
let filteredUserOptionFields = []; const filteredUserOptionFields = fields
if (fields) { ? userOptionFields.filter((uo) => fields.includes(uo))
filteredUserOptionFields = userOptionFields.filter((uo) => : userOptionFields;
fields.includes(uo)
);
} else {
filteredUserOptionFields = userOptionFields;
}
filteredUserOptionFields.forEach((s) => { filteredUserOptionFields.forEach((s) => {
data[s] = this.get(`user_option.${s}`); data[s] = this.get(`user_option.${s}`);
}); });
let updatedState = {}; const updatedState = {};
["muted", "regular", "watched", "tracked", "watched_first_post"].forEach( ["muted", "regular", "watched", "tracked", "watched_first_post"].forEach(
(categoryNotificationLevel) => { (categoryNotificationLevel) => {
@ -397,23 +443,17 @@ const User = RestModel.extend({
fields === undefined || fields === undefined ||
fields.includes(`${categoryNotificationLevel}_category_ids`) fields.includes(`${categoryNotificationLevel}_category_ids`)
) { ) {
let prop = const categories = this.get(
categoryNotificationLevel === "watched_first_post" `${camelize(categoryNotificationLevel)}Categories`
? "watchedFirstPostCategories" );
: `${categoryNotificationLevel}Categories`;
let cats = this.get(prop); if (categories) {
const ids = categories.map((c) => c.get("id"));
if (cats) { updatedState[`${categoryNotificationLevel}_category_ids`] = ids;
let cat_ids = cats.map((c) => c.get("id")); // HACK: Empty arrays are not sent in the request, we use [-1],
updatedState[`${categoryNotificationLevel}_category_ids`] = cat_ids; // an invalid category ID, that will be ignored by the server.
data[`${categoryNotificationLevel}_category_ids`] =
// HACK: denote lack of categories ids.length === 0 ? [-1] : ids;
if (cats.length === 0) {
cat_ids = [-1];
}
data[`${categoryNotificationLevel}_category_ids`] = cat_ids;
} }
} }
} }
@ -436,10 +476,6 @@ const User = RestModel.extend({
} }
}); });
return this._saveUserData(data, updatedState);
},
_saveUserData(data, updatedState) {
// TODO: We can remove this when migrated fully to rest model. // TODO: We can remove this when migrated fully to rest model.
this.set("isSaving", true); this.set("isSaving", true);
return ajax(userPath(`${this.username_lower}.json`), { return ajax(userPath(`${this.username_lower}.json`), {
@ -449,19 +485,6 @@ const User = RestModel.extend({
.then((result) => { .then((result) => {
this.setProperties(updatedState); this.setProperties(updatedState);
this.setProperties(getProperties(result.user, "bio_excerpt")); this.setProperties(getProperties(result.user, "bio_excerpt"));
if (User.current() === this && result.user.user_option) {
this.setProperties(
getProperties(
result.user.user_option,
"enable_quoting",
"enable_defer",
"external_links_in_new_tab",
"dynamic_favicon",
"seen_popups",
"skip_new_user_tips"
)
);
}
return result; return result;
}) })
.finally(() => { .finally(() => {
@ -1060,9 +1083,17 @@ const User = RestModel.extend({
); );
}, },
// obsolete, just call "user.timezone" instead
resolvedTimezone() { resolvedTimezone() {
return this.timezone; deprecated(
"user.resolvedTimezone() has been deprecated. Use user.user_option.timezone instead",
{
id: "discourse.user.resolved-timezone",
since: "2.9.0.beta12",
dropFrom: "3.0.0.beta1",
}
);
return this.user_option.timezone;
}, },
calculateMutedIds(notificationLevel, id, type) { calculateMutedIds(notificationLevel, id, type) {
@ -1199,12 +1230,10 @@ const User = RestModel.extend({
if (!this.user_option) { if (!this.user_option) {
this.set("user_option", {}); this.set("user_option", {});
} }
this.set("seen_popups", seenUserTips);
this.set("user_option.seen_popups", seenUserTips); this.set("user_option.seen_popups", seenUserTips);
if (userTipId) { if (userTipId) {
return this.save(["seen_popups"]); return this.save(["seen_popups"]);
} else { } else {
this.set("skip_new_user_tips", true);
this.set("user_option.skip_new_user_tips", true); this.set("user_option.skip_new_user_tips", true);
return this.save(["seen_popups", "skip_new_user_tips"]); return this.save(["seen_popups", "skip_new_user_tips"]);
} }
@ -1233,8 +1262,8 @@ User.reopenClass(Singleton, {
} }
} }
if (!userJson.timezone) { if (!userJson.user_option.timezone) {
userJson.timezone = moment.tz.guess(); userJson.user_option.timezone = moment.tz.guess();
this._saveTimezone(userJson); this._saveTimezone(userJson);
} }
@ -1319,7 +1348,7 @@ User.reopenClass(Singleton, {
ajax(userPath(user.username + ".json"), { ajax(userPath(user.username + ".json"), {
type: "PUT", type: "PUT",
dataType: "json", dataType: "json",
data: { timezone: user.timezone }, data: { timezone: user.user_option.timezone },
}); });
}, },
}); });

View File

@ -59,8 +59,16 @@ export default {
buildTopicRoute("top", { buildTopicRoute("top", {
actions: { actions: {
willTransition() { willTransition() {
User.currentProp("should_be_redirected_to_top", false); User.currentProp(
User.currentProp("redirected_to_top.reason", null); "user_option.should_be_redirected_to_top",
false
);
if (User.currentProp("user_option.redirected_to_top")) {
User.currentProp(
"user_option.redirected_to_top.reason",
null
);
}
return this._super(...arguments); return this._super(...arguments);
}, },
}, },

View File

@ -25,10 +25,11 @@ export default DiscourseRoute.extend(OpenComposer, {
if ( if (
(url === "/" || url === "/latest" || url === "/categories") && (url === "/" || url === "/latest" || url === "/categories") &&
!transition.targetName.includes("discovery.top") && !transition.targetName.includes("discovery.top") &&
User.currentProp("should_be_redirected_to_top") User.currentProp("user_option.should_be_redirected_to_top")
) { ) {
User.currentProp("should_be_redirected_to_top", false); User.currentProp("user_option.should_be_redirected_to_top", false);
const period = User.currentProp("redirected_to_top.period") || "all"; const period =
User.currentProp("user_option.redirected_to_top.period") || "all";
this.replaceWith("discovery.top", { this.replaceWith("discovery.top", {
queryParams: { queryParams: {
period, period,

View File

@ -73,7 +73,7 @@ export default Service.extend({
_displayCount() { _displayCount() {
return this.currentUser && return this.currentUser &&
this.currentUser.title_count_mode === "notifications" this.currentUser.user_option.title_count_mode === "notifications"
? this.notificationCount ? this.notificationCount
: this.contextCount; : this.contextCount;
}, },
@ -82,12 +82,13 @@ export default Service.extend({
let title = this._title || this.siteSettings.title; let title = this._title || this.siteSettings.title;
let displayCount = this._displayCount(); let displayCount = this._displayCount();
let dynamicFavicon = this.currentUser && this.currentUser.dynamic_favicon; let dynamicFavicon = this.currentUser?.user_option.dynamic_favicon;
if (this.currentUser && this.currentUser.isInDoNotDisturb()) { if (this.currentUser?.isInDoNotDisturb()) {
document.title = title; document.title = title;
return; return;
} }
if (displayCount > 0 && !dynamicFavicon) { if (displayCount > 0 && !dynamicFavicon) {
title = `(${displayCount}) ${title}`; title = `(${displayCount}) ${title}`;
} }
@ -96,7 +97,7 @@ export default Service.extend({
}, },
_renderFavicon() { _renderFavicon() {
if (this.currentUser && this.currentUser.dynamic_favicon) { if (this.currentUser?.user_option.dynamic_favicon) {
let url = this.siteSettings.site_favicon_url; let url = this.siteSettings.site_favicon_url;
// Since the favicon is cached on the browser for a really long time, we // Since the favicon is cached on the browser for a really long time, we

View File

@ -353,7 +353,7 @@ registerButton(
if (attrs.bookmarkReminderAt) { if (attrs.bookmarkReminderAt) {
let formattedReminder = formattedReminderTime( let formattedReminder = formattedReminderTime(
attrs.bookmarkReminderAt, attrs.bookmarkReminderAt,
currentUser.timezone currentUser.user_option.timezone
); );
title = "bookmarks.created_with_reminder"; title = "bookmarks.created_with_reminder";
titleOptions.date = formattedReminder; titleOptions.date = formattedReminder;

View File

@ -8,7 +8,7 @@ export default createWidget("user-status-bubble", {
let title = attrs.description; let title = attrs.description;
if (attrs.ends_at) { if (attrs.ends_at) {
const until = moment const until = moment
.tz(attrs.ends_at, this.currentUser.timezone) .tz(attrs.ends_at, this.currentUser.user_option.timezone)
.format(I18n.t("dates.long_date_without_year")); .format(I18n.t("dates.long_date_without_year"));
title += `\n${I18n.t("until")} ${until}`; title += `\n${I18n.t("until")} ${until}`;
} }

View File

@ -13,7 +13,7 @@ acceptance("Admin - Silence User", function (needs) {
needs.user(); needs.user();
needs.hooks.beforeEach(() => { needs.hooks.beforeEach(() => {
const timezone = loggedInUser().timezone; const timezone = loggedInUser().user_option.timezone;
clock = fakeTime("2100-05-03T08:00:00", timezone, true); // Monday morning clock = fakeTime("2100-05-03T08:00:00", timezone, true); // Monday morning
}); });

View File

@ -112,7 +112,7 @@ acceptance("Admin - Suspend User - timeframe choosing", function (needs) {
needs.user(); needs.user();
needs.hooks.beforeEach(() => { needs.hooks.beforeEach(() => {
const timezone = loggedInUser().timezone; const timezone = loggedInUser().user_option.timezone;
clock = fakeTime("2100-05-03T08:00:00", timezone, true); // Monday morning clock = fakeTime("2100-05-03T08:00:00", timezone, true); // Monday morning
}); });

View File

@ -170,7 +170,10 @@ acceptance("Bookmarking", function (needs) {
await selectKit(".bookmark-option-selector").selectRowByValue(1); await selectKit(".bookmark-option-selector").selectRowByValue(1);
await click("#save-bookmark"); await click("#save-bookmark");
assert.equal(User.current().bookmark_auto_delete_preference, "1"); assert.equal(
User.currentProp("user_option.bookmark_auto_delete_preference"),
"1"
);
await openEditBookmarkModal(); await openEditBookmarkModal();
@ -243,7 +246,7 @@ acceptance("Bookmarking", function (needs) {
test("Editing a bookmark", async function (assert) { test("Editing a bookmark", async function (assert) {
await visit("/t/internationalization-localization/280"); await visit("/t/internationalization-localization/280");
let now = moment.tz(loggedInUser().timezone); let now = moment.tz(loggedInUser().user_option.timezone);
let tomorrow = now.add(1, "day").format("YYYY-MM-DD"); let tomorrow = now.add(1, "day").format("YYYY-MM-DD");
await openBookmarkModal(); await openBookmarkModal();
await fillIn("input#bookmark-name", "Test name"); await fillIn("input#bookmark-name", "Test name");
@ -269,7 +272,7 @@ acceptance("Bookmarking", function (needs) {
test("Using a post date for the reminder date", async function (assert) { test("Using a post date for the reminder date", async function (assert) {
await visit("/t/internationalization-localization/280"); await visit("/t/internationalization-localization/280");
let postDate = moment.tz("2036-01-15", loggedInUser().timezone); let postDate = moment.tz("2036-01-15", loggedInUser().user_option.timezone);
let postDateFormatted = postDate.format("YYYY-MM-DD"); let postDateFormatted = postDate.format("YYYY-MM-DD");
await openBookmarkModal(); await openBookmarkModal();
await fillIn("input#bookmark-name", "Test name"); await fillIn("input#bookmark-name", "Test name");

View File

@ -126,7 +126,7 @@ acceptance("Composer - editor mentions", function (needs) {
}); });
test("shows status on search results when mentioning a user", async function (assert) { test("shows status on search results when mentioning a user", async function (assert) {
const timezone = loggedInUser().timezone; const timezone = loggedInUser().user_option.timezone;
const now = moment(status.ends_at).add(-1, "hour").format(); const now = moment(status.ends_at).add(-1, "hour").format();
clock = fakeTime(now, timezone, true); clock = fakeTime(now, timezone, true);

View File

@ -191,7 +191,7 @@ acceptance(
}); });
needs.hooks.beforeEach(() => { needs.hooks.beforeEach(() => {
const timezone = loggedInUser().timezone; const timezone = loggedInUser().user_option.timezone;
clock = fakeTime("2100-05-03T08:00:00", timezone, true); // Monday morning clock = fakeTime("2100-05-03T08:00:00", timezone, true); // Monday morning
}); });

View File

@ -19,11 +19,13 @@ acceptance("Redirect to Top", function (needs) {
test("redirects categories to weekly top", async function (assert) { test("redirects categories to weekly top", async function (assert) {
updateCurrentUser({ updateCurrentUser({
user_option: {
should_be_redirected_to_top: true, should_be_redirected_to_top: true,
redirected_to_top: { redirected_to_top: {
period: "weekly", period: "weekly",
reason: "Welcome back!", reason: "Welcome back!",
}, },
},
}); });
await visit("/categories"); await visit("/categories");
@ -36,11 +38,13 @@ acceptance("Redirect to Top", function (needs) {
test("redirects latest to monthly top", async function (assert) { test("redirects latest to monthly top", async function (assert) {
updateCurrentUser({ updateCurrentUser({
user_option: {
should_be_redirected_to_top: true, should_be_redirected_to_top: true,
redirected_to_top: { redirected_to_top: {
period: "monthly", period: "monthly",
reason: "Welcome back!", reason: "Welcome back!",
}, },
},
}); });
await visit("/latest"); await visit("/latest");
@ -53,11 +57,13 @@ acceptance("Redirect to Top", function (needs) {
test("redirects root to All top", async function (assert) { test("redirects root to All top", async function (assert) {
updateCurrentUser({ updateCurrentUser({
user_option: {
should_be_redirected_to_top: true, should_be_redirected_to_top: true,
redirected_to_top: { redirected_to_top: {
period: null, period: null,
reason: "Welcome back!", reason: "Welcome back!",
}, },
},
}); });
await visit("/"); await visit("/");

View File

@ -23,7 +23,10 @@ acceptance("Topic - Bulk Actions", function (needs) {
}); });
test("bulk select - modal", async function (assert) { test("bulk select - modal", async function (assert) {
updateCurrentUser({ moderator: true, enable_defer: true }); updateCurrentUser({
moderator: true,
user_option: { enable_defer: true },
});
await visit("/latest"); await visit("/latest");
await click("button.bulk-select"); await click("button.bulk-select");
@ -168,7 +171,13 @@ acceptance("Topic - Bulk Actions", function (needs) {
}); });
test("TL4 users can bulk select", async function (assert) { test("TL4 users can bulk select", async function (assert) {
updateCurrentUser({ moderator: false, admin: false, trust_level: 4 }); updateCurrentUser({
moderator: false,
admin: false,
trust_level: 4,
user_option: { enable_defer: false },
});
await visit("/latest"); await visit("/latest");
await click("button.bulk-select"); await click("button.bulk-select");

View File

@ -31,7 +31,7 @@ acceptance("Topic - Edit timer", function (needs) {
}); });
needs.hooks.beforeEach(() => { needs.hooks.beforeEach(() => {
const timezone = loggedInUser().timezone; const timezone = loggedInUser().user_option.timezone;
const tuesday = "2100-06-15T08:00:00"; const tuesday = "2100-06-15T08:00:00";
clock = fakeTime(tuesday, timezone, true); clock = fakeTime(tuesday, timezone, true);
}); });

View File

@ -29,7 +29,7 @@ acceptance("Topic - Set Slow Mode", function (needs) {
}); });
needs.hooks.beforeEach(() => { needs.hooks.beforeEach(() => {
const timezone = loggedInUser().timezone; const timezone = loggedInUser().user_option.timezone;
clock = fakeTime("2100-05-03T08:00:00", timezone, true); // Monday morning clock = fakeTime("2100-05-03T08:00:00", timezone, true); // Monday morning
}); });

View File

@ -12,11 +12,6 @@ import { cloneJSON } from "discourse-common/lib/object";
acceptance("User Card - Show Local Time", function (needs) { acceptance("User Card - Show Local Time", function (needs) {
needs.user(); needs.user();
needs.settings({ display_local_time_in_user_card: true }); needs.settings({ display_local_time_in_user_card: true });
needs.pretender((server, helper) => {
const cardResponse = cloneJSON(userFixtures["/u/charlie/card.json"]);
delete cardResponse.user.timezone;
server.get("/u/charlie/card.json", () => helper.response(cardResponse));
});
test("user card local time - does not update timezone for another user", async function (assert) { test("user card local time - does not update timezone for another user", async function (assert) {
User.current().timezone = "Australia/Brisbane"; User.current().timezone = "Australia/Brisbane";

View File

@ -116,7 +116,7 @@ acceptance("User Notifications - Users - Ignore User", function (needs) {
needs.user(); needs.user();
needs.hooks.beforeEach(() => { needs.hooks.beforeEach(() => {
const timezone = loggedInUser().timezone; const timezone = loggedInUser().user_option.timezone;
clock = fakeTime("2100-05-03T08:00:00", timezone, true); // Monday morning clock = fakeTime("2100-05-03T08:00:00", timezone, true); // Monday morning
}); });

View File

@ -5,6 +5,8 @@ import {
} from "discourse/tests/helpers/qunit-helpers"; } from "discourse/tests/helpers/qunit-helpers";
import { click, visit } from "@ember/test-helpers"; import { click, visit } from "@ember/test-helpers";
import { test } from "qunit"; import { test } from "qunit";
import { cloneJSON } from "discourse-common/lib/object";
import userFixtures from "discourse/tests/fixtures/user-fixtures";
acceptance("User - Preferences - Profile - Featured topic", function (needs) { acceptance("User - Preferences - Profile - Featured topic", function (needs) {
needs.user(); needs.user();
@ -65,7 +67,15 @@ acceptance("User - Preferences - Profile - Featured topic", function (needs) {
acceptance( acceptance(
"User - Preferences - Profile - No default calendar set", "User - Preferences - Profile - No default calendar set",
function (needs) { function (needs) {
needs.user({ default_calendar: "none_selected" }); needs.user();
needs.pretender((server, helper) => {
server.get("/u/eviltrout.json", () => {
const cloned = cloneJSON(userFixtures["/u/eviltrout.json"]);
cloned.user.user_option.default_calendar = "none_selected";
return helper.response(200, cloned);
});
});
test("default calendar option is not visible", async function (assert) { test("default calendar option is not visible", async function (assert) {
await visit("/u/eviltrout/preferences/profile"); await visit("/u/eviltrout/preferences/profile");
@ -81,7 +91,15 @@ acceptance(
acceptance( acceptance(
"User - Preferences - Profile - Default calendar set", "User - Preferences - Profile - Default calendar set",
function (needs) { function (needs) {
needs.user({ default_calendar: "google" }); needs.user();
needs.pretender((server, helper) => {
server.get("/u/eviltrout.json", () => {
const cloned = cloneJSON(userFixtures["/u/eviltrout.json"]);
cloned.user.user_option.default_calendar = "google";
return helper.response(200, cloned);
});
});
test("default calendar can be changed", async function (assert) { test("default calendar can be changed", async function (assert) {
await visit("/u/eviltrout/preferences/profile"); await visit("/u/eviltrout/preferences/profile");

View File

@ -189,6 +189,8 @@ acceptance("User Preferences - Tracking", function (needs) {
await click(".save-changes"); await click(".save-changes");
assert.deepEqual(putRequestData, { assert.deepEqual(putRequestData, {
auto_track_topics_after_msecs: "60000",
new_topic_duration_minutes: "1440",
"regular_category_ids[]": ["-1"], "regular_category_ids[]": ["-1"],
"tracked_category_ids[]": ["4"], "tracked_category_ids[]": ["4"],
"watched_category_ids[]": ["3"], "watched_category_ids[]": ["3"],
@ -211,6 +213,8 @@ acceptance("User Preferences - Tracking", function (needs) {
await click(".save-changes"); await click(".save-changes");
assert.deepEqual(putRequestData, { assert.deepEqual(putRequestData, {
auto_track_topics_after_msecs: "60000",
new_topic_duration_minutes: "1440",
"muted_category_ids[]": ["-1"], "muted_category_ids[]": ["-1"],
"tracked_category_ids[]": ["4"], "tracked_category_ids[]": ["4"],
"watched_category_ids[]": ["3"], "watched_category_ids[]": ["3"],

View File

@ -26,7 +26,7 @@ acceptance("User Status", function (needs) {
const userId = 1; const userId = 1;
const userTimezone = "UTC"; const userTimezone = "UTC";
needs.user({ id: userId, timezone: userTimezone }); needs.user({ id: userId, "user_option.timezone": userTimezone });
needs.pretender((server, helper) => { needs.pretender((server, helper) => {
server.put("/user-status.json", () => { server.put("/user-status.json", () => {

View File

@ -1,6 +1,5 @@
import I18n from "I18n"; import I18n from "I18n";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import User from "discourse/models/user";
import selectKit from "discourse/tests/helpers/select-kit-helper"; import selectKit from "discourse/tests/helpers/select-kit-helper";
import sinon from "sinon"; import sinon from "sinon";
import userFixtures from "discourse/tests/fixtures/user-fixtures"; import userFixtures from "discourse/tests/fixtures/user-fixtures";
@ -167,21 +166,33 @@ acceptance("User - Saving user options", function (needs) {
disable_mailing_list_mode: false, disable_mailing_list_mode: false,
}); });
let putRequestData;
needs.pretender((server, helper) => { needs.pretender((server, helper) => {
server.put("/u/eviltrout.json", () => { server.put("/u/eviltrout.json", (request) => {
return helper.response(200, { user: {} }); putRequestData = helper.parsePostData(request.requestBody);
return helper.response({ user: {} });
}); });
}); });
needs.hooks.afterEach(() => {
putRequestData = null;
});
test("saving user options", async function (assert) { test("saving user options", async function (assert) {
const spy = sinon.spy(User.current(), "_saveUserData");
await visit("/u/eviltrout/preferences/emails"); await visit("/u/eviltrout/preferences/emails");
await click(".pref-mailing-list-mode input[type='checkbox']"); await click(".pref-mailing-list-mode input[type='checkbox']");
await click(".save-changes"); await click(".save-changes");
assert.ok( assert.deepEqual(
spy.calledWithMatch({ mailing_list_mode: true }), putRequestData,
{
digest_after_minutes: "10080",
email_digests: "true",
email_level: "1",
email_messages_level: "0",
mailing_list_mode: "true",
},
"sends a PUT request to update the specified user option" "sends a PUT request to update the specified user option"
); );
@ -189,8 +200,15 @@ acceptance("User - Saving user options", function (needs) {
await selectKit("#user-email-messages-level").selectRowByValue(2); // never option await selectKit("#user-email-messages-level").selectRowByValue(2); // never option
await click(".save-changes"); await click(".save-changes");
assert.ok( assert.deepEqual(
spy.calledWithMatch({ email_messages_level: 2 }), putRequestData,
{
digest_after_minutes: "10080",
email_digests: "true",
email_level: "1",
email_messages_level: "2",
mailing_list_mode: "true",
},
"is able to save a different user_option on a subsequent request" "is able to save a different user_option on a subsequent request"
); );
}); });

View File

@ -18,21 +18,14 @@ export default {
title: "co-founder", title: "co-founder",
reply_count: 859, reply_count: 859,
topic_count: 36, topic_count: 36,
enable_quoting: true,
external_links_in_new_tab: false,
dynamic_favicon: true,
trust_level: 4, trust_level: 4,
can_edit: true, can_edit: true,
can_invite_to_forum: true, can_invite_to_forum: true,
can_send_private_messages: true, can_send_private_messages: true,
should_be_redirected_to_top: false,
custom_fields: {}, custom_fields: {},
muted_category_ids: [], muted_category_ids: [],
dismissed_banner_key: null, dismissed_banner_key: null,
akismet_review_count: 0, akismet_review_count: 0,
title_count_mode: "notifications",
timezone: "Australia/Brisbane",
skip_new_user_tips: false,
can_review: true, can_review: true,
ignored_users: [], ignored_users: [],
groups: [ groups: [
@ -48,7 +41,16 @@ export default {
name: "trust_level_1", name: "trust_level_1",
display_name: "trust_level_1", display_name: "trust_level_1",
} }
] ],
user_option: {
external_links_in_new_tab: false,
enable_quoting: true,
dynamic_favicon: true,
title_count_mode: "notifications",
timezone: "Australia/Brisbane",
skip_new_user_tips: false,
should_be_redirected_to_top: false,
},
}, },
}, },
}; };

View File

@ -107,6 +107,18 @@ export default {
user: { user: {
user_option: { user_option: {
text_size_seq: 1, text_size_seq: 1,
email_digests: true,
email_messages_level: 0,
email_level: 1,
digest_after_minutes: 10080,
mailing_list_mode: false,
auto_track_topics_after_msecs: 60000,
new_topic_duration_minutes: 1440,
external_links_in_new_tab: false,
dynamic_favicon: true,
skip_new_user_tips: false,
enable_quoting: true,
timezone: "Australia/Brisbane",
}, },
id: 19, id: 19,
username: "eviltrout", username: "eviltrout",
@ -166,17 +178,6 @@ export default {
can_be_deleted: false, can_be_deleted: false,
can_delete_all_posts: false, can_delete_all_posts: false,
locale: "", locale: "",
email_digests: true,
email_messages_level: 0,
email_level: 1,
digest_after_minutes: 10080,
mailing_list_mode: false,
auto_track_topics_after_msecs: 60000,
new_topic_duration_minutes: 1440,
external_links_in_new_tab: false,
dynamic_favicon: true,
skip_new_user_tips: false,
enable_quoting: true,
muted_category_ids: [], muted_category_ids: [],
regular_category_ids: [4], regular_category_ids: [4],
tracked_category_ids: [], tracked_category_ids: [],
@ -294,7 +295,6 @@ export default {
day_6_start_time: 480, day_6_start_time: 480,
day_6_end_time: 1020, day_6_end_time: 1020,
}, },
timezone: "Australia/Brisbane",
has_topic_draft: true, has_topic_draft: true,
}, },
}, },
@ -2722,10 +2722,10 @@ export default {
hide_profile_and_presence: false, hide_profile_and_presence: false,
text_size: "normal", text_size: "normal",
text_size_seq: 0, text_size_seq: 0,
},
timezone: "America/Los_Angeles", timezone: "America/Los_Angeles",
}, },
}, },
},
"/u/charlie/card.json": { "/u/charlie/card.json": {
user_badges: [ user_badges: [
{ {
@ -3253,6 +3253,18 @@ export default {
user: { user: {
user_option: { user_option: {
text_size_seq: 1, text_size_seq: 1,
email_digests: true,
email_messages_level: 0,
email_level: 1,
digest_after_minutes: 10080,
mailing_list_mode: false,
auto_track_topics_after_msecs: 60000,
new_topic_duration_minutes: 1440,
external_links_in_new_tab: false,
dynamic_favicon: true,
skip_new_user_tips: false,
enable_quoting: true,
timezone: "Australia/Brisbane",
}, },
id: 4432, id: 4432,
username: "e.il.rout", username: "e.il.rout",
@ -3312,17 +3324,6 @@ export default {
can_be_deleted: false, can_be_deleted: false,
can_delete_all_posts: false, can_delete_all_posts: false,
locale: "", locale: "",
email_digests: true,
email_messages_level: 0,
email_level: 1,
digest_after_minutes: 10080,
mailing_list_mode: false,
auto_track_topics_after_msecs: 60000,
new_topic_duration_minutes: 1440,
external_links_in_new_tab: false,
dynamic_favicon: true,
skip_new_user_tips: false,
enable_quoting: true,
muted_category_ids: [], muted_category_ids: [],
regular_category_ids: [], regular_category_ids: [],
tracked_category_ids: [], tracked_category_ids: [],
@ -3439,7 +3440,6 @@ export default {
day_6_start_time: 480, day_6_start_time: 480,
day_6_end_time: 1020, day_6_end_time: 1020,
}, },
timezone: "Australia/Brisbane",
}, },
}, },
"/u/staged.json": { "/u/staged.json": {
@ -3470,6 +3470,18 @@ export default {
user: { user: {
user_option: { user_option: {
text_size_seq: 1, text_size_seq: 1,
email_digests: false,
email_messages_level: 0,
email_level: 1,
digest_after_minutes: 10080,
mailing_list_mode: false,
auto_track_topics_after_msecs: 60000,
new_topic_duration_minutes: 1440,
external_links_in_new_tab: false,
dynamic_favicon: true,
skip_new_user_tips: false,
enable_quoting: true,
timezone: "Australia/Brisbane",
}, },
id: 20, id: 20,
username: "staged", username: "staged",
@ -3509,17 +3521,6 @@ export default {
can_be_deleted: true, can_be_deleted: true,
can_delete_all_posts: true, can_delete_all_posts: true,
locale: "", locale: "",
email_digests: false,
email_messages_level: 0,
email_level: 1,
digest_after_minutes: 10080,
mailing_list_mode: false,
auto_track_topics_after_msecs: 60000,
new_topic_duration_minutes: 1440,
external_links_in_new_tab: false,
dynamic_favicon: true,
skip_new_user_tips: false,
enable_quoting: true,
muted_category_ids: [], muted_category_ids: [],
regular_category_ids: [], regular_category_ids: [],
tracked_category_ids: [], tracked_category_ids: [],
@ -3562,7 +3563,6 @@ export default {
day_6_start_time: 480, day_6_start_time: 480,
day_6_end_time: 1020, day_6_end_time: 1020,
}, },
timezone: "Australia/Brisbane",
}, },
}, },
"/u/recent-searches": { "/u/recent-searches": {

View File

@ -24,7 +24,6 @@ export function setupRenderingTest(hooks) {
const currentUser = User.create({ const currentUser = User.create({
username: "eviltrout", username: "eviltrout",
timezone: "Australia/Brisbane",
name: "Robin Ward", name: "Robin Ward",
admin: false, admin: false,
moderator: false, moderator: false,
@ -42,6 +41,9 @@ export function setupRenderingTest(hooks) {
display_name: "trust_level_1", display_name: "trust_level_1",
}, },
], ],
user_option: {
timezone: "Australia/Brisbane",
},
}); });
this.currentUser = currentUser; this.currentUser = currentUser;
this.owner.unregister("service:current-user"); this.owner.unregister("service:current-user");

View File

@ -14,7 +14,7 @@ module("Integration | Component | bookmark-icon", function (hooks) {
test("with reminder", async function (assert) { test("with reminder", async function (assert) {
this.setProperties({ this.setProperties({
bookmark: Bookmark.create({ bookmark: Bookmark.create({
reminder_at: tomorrow(this.currentUser.timezone), reminder_at: tomorrow(this.currentUser.user_option.timezone),
name: "some name", name: "some name",
}), }),
}); });
@ -29,7 +29,7 @@ module("Integration | Component | bookmark-icon", function (hooks) {
I18n.t("bookmarks.created_with_reminder_generic", { I18n.t("bookmarks.created_with_reminder_generic", {
date: formattedReminderTime( date: formattedReminderTime(
this.bookmark.reminder_at, this.bookmark.reminder_at,
this.currentUser.timezone this.currentUser.user_option.timezone
), ),
name: "some name", name: "some name",
}) })

View File

@ -23,7 +23,7 @@ module("Integration | Component | d-document", function (hooks) {
const titleBefore = document.title; const titleBefore = document.title;
try { try {
this.currentUser.redesigned_user_menu_enabled = true; this.currentUser.redesigned_user_menu_enabled = true;
this.currentUser.title_count_mode = "notifications"; this.currentUser.user_option.title_count_mode = "notifications";
await render(hbs`<DDocument />`); await render(hbs`<DDocument />`);
assert.strictEqual( assert.strictEqual(
getTitleCount(), getTitleCount(),
@ -51,7 +51,7 @@ module("Integration | Component | d-document", function (hooks) {
const titleBefore = document.title; const titleBefore = document.title;
try { try {
this.currentUser.redesigned_user_menu_enabled = false; this.currentUser.redesigned_user_menu_enabled = false;
this.currentUser.title_count_mode = "notifications"; this.currentUser.user_option.title_count_mode = "notifications";
await render(hbs`<DDocument />`); await render(hbs`<DDocument />`);
assert.strictEqual( assert.strictEqual(
getTitleCount(), getTitleCount(),

View File

@ -58,7 +58,11 @@ module(
test("renders default options", async function (assert) { test("renders default options", async function (assert) {
const monday = "2100-12-13T08:00:00"; const monday = "2100-12-13T08:00:00";
this.clock = fakeTime(monday, this.currentUser.timezone, true); this.clock = fakeTime(
monday,
this.currentUser.user_option.timezone,
true
);
await render(hbs`<FutureDateInput />`); await render(hbs`<FutureDateInput />`);

View File

@ -29,7 +29,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("shows default options", async function (assert) { test("shows default options", async function (assert) {
this.siteSettings.suggest_weekends_in_date_pickers = true; this.siteSettings.suggest_weekends_in_date_pickers = true;
const tuesday = "2100-06-08T08:00:00"; const tuesday = "2100-06-08T08:00:00";
this.clock = fakeTime(tuesday, this.currentUser.timezone, true); this.clock = fakeTime(tuesday, this.currentUser.user_option.timezone, true);
await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`); await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`);
@ -55,7 +55,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("show 'Later This Week' if today is < Thursday", async function (assert) { test("show 'Later This Week' if today is < Thursday", async function (assert) {
const monday = "2100-06-07T08:00:00"; const monday = "2100-06-07T08:00:00";
this.clock = fakeTime(monday, this.currentUser.timezone, true); this.clock = fakeTime(monday, this.currentUser.user_option.timezone, true);
await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`); await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`);
@ -64,7 +64,11 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("does not show 'Later This Week' if today is >= Thursday", async function (assert) { test("does not show 'Later This Week' if today is >= Thursday", async function (assert) {
const thursday = "2100-06-10T08:00:00"; const thursday = "2100-06-10T08:00:00";
this.clock = fakeTime(thursday, this.currentUser.timezone, true); this.clock = fakeTime(
thursday,
this.currentUser.user_option.timezone,
true
);
await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`); await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`);
@ -77,7 +81,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("does not show 'Later Today' if 'Later Today' is tomorrow", async function (assert) { test("does not show 'Later Today' if 'Later Today' is tomorrow", async function (assert) {
this.clock = fakeTime( this.clock = fakeTime(
"2100-12-11T22:00:00", // + 3 hours is tomorrow "2100-12-11T22:00:00", // + 3 hours is tomorrow
this.currentUser.timezone, this.currentUser.user_option.timezone,
true true
); );
@ -92,7 +96,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("shows 'Later Today' if it is before 5pm", async function (assert) { test("shows 'Later Today' if it is before 5pm", async function (assert) {
this.clock = fakeTime( this.clock = fakeTime(
"2100-12-11T16:50:00", "2100-12-11T16:50:00",
this.currentUser.timezone, this.currentUser.user_option.timezone,
true true
); );
@ -104,7 +108,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("does not show 'Later Today' if it is after 5pm", async function (assert) { test("does not show 'Later Today' if it is after 5pm", async function (assert) {
this.clock = fakeTime( this.clock = fakeTime(
"2100-12-11T17:00:00", "2100-12-11T17:00:00",
this.currentUser.timezone, this.currentUser.user_option.timezone,
true true
); );
@ -119,7 +123,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("default custom date time is in one hour from now", async function (assert) { test("default custom date time is in one hour from now", async function (assert) {
this.clock = fakeTime( this.clock = fakeTime(
"2100-12-11T17:00:00", "2100-12-11T17:00:00",
this.currentUser.timezone, this.currentUser.user_option.timezone,
true true
); );
@ -132,7 +136,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("shows 'Next Monday' instead of 'Monday' on Sundays", async function (assert) { test("shows 'Next Monday' instead of 'Monday' on Sundays", async function (assert) {
const sunday = "2100-01-24T08:00:00"; const sunday = "2100-01-24T08:00:00";
this.clock = fakeTime(sunday, this.currentUser.timezone, true); this.clock = fakeTime(sunday, this.currentUser.user_option.timezone, true);
await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`); await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`);
@ -150,7 +154,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("shows 'Next Monday' instead of 'Monday' on Mondays", async function (assert) { test("shows 'Next Monday' instead of 'Monday' on Mondays", async function (assert) {
const monday = "2100-01-25T08:00:00"; const monday = "2100-01-25T08:00:00";
this.clock = fakeTime(monday, this.currentUser.timezone, true); this.clock = fakeTime(monday, this.currentUser.user_option.timezone, true);
await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`); await render(hbs`<TimeShortcutPicker @_itsatrap={{this.itsatrap}} />`);
@ -169,7 +173,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("the 'Next Month' option points to the first day of the next month", async function (assert) { test("the 'Next Month' option points to the first day of the next month", async function (assert) {
this.clock = fakeTime( this.clock = fakeTime(
"2100-01-01T08:00:00", "2100-01-01T08:00:00",
this.currentUser.timezone, this.currentUser.user_option.timezone,
true true
); );

View File

@ -64,7 +64,7 @@ module("Integration | Component | user-menu", function (hooks) {
}); });
test("likes tab is hidden if current user's like notifications frequency is 'never'", async function (assert) { test("likes tab is hidden if current user's like notifications frequency is 'never'", async function (assert) {
this.currentUser.set("likes_notifications_disabled", true); this.currentUser.set("user_option.likes_notifications_disabled", true);
this.currentUser.set("can_send_private_messages", true); this.currentUser.set("can_send_private_messages", true);
await render(template); await render(template);
assert.ok(!exists("#user-menu-button-likes")); assert.ok(!exists("#user-menu-button-likes"));

View File

@ -12,7 +12,7 @@ module("Integration | Component | user-status-message", function (hooks) {
setupRenderingTest(hooks); setupRenderingTest(hooks);
hooks.beforeEach(function () { hooks.beforeEach(function () {
this.currentUser.timezone = "UTC"; this.currentUser.user_option.timezone = "UTC";
}); });
hooks.afterEach(function () { hooks.afterEach(function () {
@ -49,7 +49,7 @@ module("Integration | Component | user-status-message", function (hooks) {
test("it shows the until TIME on the tooltip if status will expire today", async function (assert) { test("it shows the until TIME on the tooltip if status will expire today", async function (assert) {
this.clock = fakeTime( this.clock = fakeTime(
"2100-02-01T08:00:00.000Z", "2100-02-01T08:00:00.000Z",
this.currentUser.timezone, this.currentUser.user_option.timezone,
true true
); );
this.set("status", { this.set("status", {
@ -72,7 +72,7 @@ module("Integration | Component | user-status-message", function (hooks) {
test("it shows the until DATE on the tooltip if status will expire tomorrow", async function (assert) { test("it shows the until DATE on the tooltip if status will expire tomorrow", async function (assert) {
this.clock = fakeTime( this.clock = fakeTime(
"2100-02-01T08:00:00.000Z", "2100-02-01T08:00:00.000Z",
this.currentUser.timezone, this.currentUser.user_option.timezone,
true true
); );
this.set("status", { this.set("status", {
@ -95,7 +95,7 @@ module("Integration | Component | user-status-message", function (hooks) {
test("it doesn't show until datetime on the tooltip if status doesn't have expiration date", async function (assert) { test("it doesn't show until datetime on the tooltip if status doesn't have expiration date", async function (assert) {
this.clock = fakeTime( this.clock = fakeTime(
"2100-02-01T08:00:00.000Z", "2100-02-01T08:00:00.000Z",
this.currentUser.timezone, this.currentUser.user_option.timezone,
true true
); );
this.set("status", { this.set("status", {

View File

@ -137,7 +137,7 @@ module("Unit | Utility | click-track", function (hooks) {
skip("tracks external URLs when opening in another window", async function (assert) { skip("tracks external URLs when opening in another window", async function (assert) {
assert.expect(3); assert.expect(3);
User.currentProp("external_links_in_new_tab", true); User.currentProp("user_option.external_links_in_new_tab", true);
const done = assert.async(); const done = assert.async();
pretender.post("/clicks/track", (request) => { pretender.post("/clicks/track", (request) => {
@ -171,7 +171,7 @@ module("Unit | Utility | click-track", function (hooks) {
}); });
test("does not track clicks links in quotes", async function (assert) { test("does not track clicks links in quotes", async function (assert) {
User.currentProp("external_links_in_new_tab", true); User.currentProp("user_option.external_links_in_new_tab", true);
assert.notOk(track(generateClickEventOn(".quote a:last-child"))); assert.notOk(track(generateClickEventOn(".quote a:last-child")));
assert.ok(window.open.calledWith("https://google.com/", "_blank")); assert.ok(window.open.calledWith("https://google.com/", "_blank"));
}); });

View File

@ -94,14 +94,14 @@ module("Unit | Model | user", function (hooks) {
test("createCurrent() guesses timezone if user doesn't have it set", async function (assert) { test("createCurrent() guesses timezone if user doesn't have it set", async function (assert) {
PreloadStore.store("currentUser", { PreloadStore.store("currentUser", {
username: "eviltrout", username: "eviltrout",
timezone: null, user_option: { timezone: null },
}); });
const expectedTimezone = "Africa/Casablanca"; const expectedTimezone = "Africa/Casablanca";
sinon.stub(moment.tz, "guess").returns(expectedTimezone); sinon.stub(moment.tz, "guess").returns(expectedTimezone);
const currentUser = User.createCurrent(); const currentUser = User.createCurrent();
assert.deepEqual(currentUser.timezone, expectedTimezone); assert.deepEqual(currentUser.user_option.timezone, expectedTimezone);
await settled(); // `User` sends a request to save the timezone await settled(); // `User` sends a request to save the timezone
}); });
@ -110,7 +110,7 @@ module("Unit | Model | user", function (hooks) {
const timezone = "Africa/Casablanca"; const timezone = "Africa/Casablanca";
PreloadStore.store("currentUser", { PreloadStore.store("currentUser", {
username: "eviltrout", username: "eviltrout",
timezone, user_option: { timezone },
}); });
const spyMomentGuess = sinon.spy(moment.tz, "guess"); const spyMomentGuess = sinon.spy(moment.tz, "guess");

View File

@ -34,7 +34,7 @@ module("Unit | Service | document-title", function (hooks) {
test("it displays notification counts for logged in users", function (assert) { test("it displays notification counts for logged in users", function (assert) {
this.documentTitle.currentUser = currentUser(); this.documentTitle.currentUser = currentUser();
this.documentTitle.currentUser.dynamic_favicon = false; this.documentTitle.currentUser.user_option.dynamic_favicon = false;
this.documentTitle.setTitle("test notifications"); this.documentTitle.setTitle("test notifications");
this.documentTitle.updateNotificationCount(5); this.documentTitle.updateNotificationCount(5);
assert.strictEqual(document.title, "test notifications"); assert.strictEqual(document.title, "test notifications");
@ -52,7 +52,7 @@ module("Unit | Service | document-title", function (hooks) {
date.setHours(date.getHours() + 1); date.setHours(date.getHours() + 1);
this.documentTitle.currentUser.do_not_disturb_until = date.toUTCString(); this.documentTitle.currentUser.do_not_disturb_until = date.toUTCString();
this.documentTitle.currentUser.dynamic_favicon = false; this.documentTitle.currentUser.user_option.dynamic_favicon = false;
this.documentTitle.setTitle("test notifications"); this.documentTitle.setTitle("test notifications");
this.documentTitle.updateNotificationCount(5); this.documentTitle.updateNotificationCount(5);
assert.strictEqual(document.title, "test notifications"); assert.strictEqual(document.title, "test notifications");

View File

@ -18,7 +18,7 @@ export default ComboBoxComponent.extend({
init() { init() {
this._super(...arguments); this._super(...arguments);
this.userTimezone = this.currentUser.timezone; this.userTimezone = this.currentUser.user_option.timezone;
}, },
modifyComponentForRow() { modifyComponentForRow() {

View File

@ -61,7 +61,7 @@ export default Component.extend({
if ( if (
this.currentUser && this.currentUser &&
this.currentUser.mailing_list_mode && this.currentUser.user_option.mailing_list_mode &&
level > NotificationLevels.MUTED level > NotificationLevels.MUTED
) { ) {
return I18n.t("topic.notifications.reasons.mailing_list_mode"); return I18n.t("topic.notifications.reasons.mailing_list_mode");

View File

@ -0,0 +1,33 @@
# frozen_string_literal: true
class CurrentUserOptionSerializer < ApplicationSerializer
attributes :mailing_list_mode,
:external_links_in_new_tab,
:enable_quoting,
:dynamic_favicon,
:automatically_unpin_topics,
:likes_notifications_disabled,
:hide_profile_and_presence,
:title_count_mode,
:enable_defer,
:timezone,
:skip_new_user_tips,
:default_calendar,
:bookmark_auto_delete_preference,
:seen_popups,
:should_be_redirected_to_top,
:redirected_to_top,
:treat_as_new_topic_start_date,
def likes_notifications_disabled
object.likes_notifications_disabled?
end
def include_redirected_to_top?
object.redirected_to_top.present?
end
def include_seen_popups?
SiteSetting.enable_user_tips
end
end

View File

@ -17,10 +17,6 @@ class CurrentUserSerializer < BasicUserSerializer
:whisperer?, :whisperer?,
:title, :title,
:any_posts, :any_posts,
:enable_quoting,
:enable_defer,
:external_links_in_new_tab,
:dynamic_favicon,
:trust_level, :trust_level,
:can_send_private_email_messages, :can_send_private_email_messages,
:can_send_private_messages, :can_send_private_messages,
@ -28,8 +24,6 @@ class CurrentUserSerializer < BasicUserSerializer
:can_invite_to_forum, :can_invite_to_forum,
:no_password, :no_password,
:can_delete_account, :can_delete_account,
:should_be_redirected_to_top,
:redirected_to_top,
:custom_fields, :custom_fields,
:muted_category_ids, :muted_category_ids,
:indirectly_muted_category_ids, :indirectly_muted_category_ids,
@ -48,9 +42,6 @@ class CurrentUserSerializer < BasicUserSerializer
:unseen_reviewable_count, :unseen_reviewable_count,
:new_personal_messages_notifications_count, :new_personal_messages_notifications_count,
:read_faq?, :read_faq?,
:automatically_unpin_topics,
:mailing_list_mode,
:treat_as_new_topic_start_date,
:previous_visit_at, :previous_visit_at,
:seen_notification_id, :seen_notification_id,
:primary_group_id, :primary_group_id,
@ -61,25 +52,17 @@ class CurrentUserSerializer < BasicUserSerializer
:external_id, :external_id,
:associated_account_ids, :associated_account_ids,
:top_category_ids, :top_category_ids,
:hide_profile_and_presence,
:groups, :groups,
:second_factor_enabled, :second_factor_enabled,
:ignored_users, :ignored_users,
:title_count_mode,
:timezone,
:featured_topic, :featured_topic,
:skip_new_user_tips,
:seen_popups,
:do_not_disturb_until, :do_not_disturb_until,
:has_topic_draft, :has_topic_draft,
:can_review, :can_review,
:draft_count, :draft_count,
:default_calendar,
:bookmark_auto_delete_preference,
:pending_posts_count, :pending_posts_count,
:status, :status,
:sidebar_category_ids, :sidebar_category_ids,
:likes_notifications_disabled,
:grouped_unread_notifications, :grouped_unread_notifications,
:redesigned_user_menu_enabled, :redesigned_user_menu_enabled,
:redesigned_user_page_nav_enabled, :redesigned_user_page_nav_enabled,
@ -89,6 +72,8 @@ class CurrentUserSerializer < BasicUserSerializer
delegate :user_stat, to: :object, private: true delegate :user_stat, to: :object, private: true
delegate :any_posts, :draft_count, :pending_posts_count, :read_faq?, to: :user_stat delegate :any_posts, :draft_count, :pending_posts_count, :read_faq?, to: :user_stat
has_one :user_option, embed: :object, serializer: CurrentUserOptionSerializer
def groups def groups
owned_group_ids = GroupUser.where(user_id: id, owner: true).pluck(:group_id).to_set owned_group_ids = GroupUser.where(user_id: id, owner: true).pluck(:group_id).to_set
@ -115,54 +100,6 @@ class CurrentUserSerializer < BasicUserSerializer
scope.can_create_group? scope.can_create_group?
end end
def hide_profile_and_presence
object.user_option.hide_profile_and_presence
end
def enable_quoting
object.user_option.enable_quoting
end
def enable_defer
object.user_option.enable_defer
end
def external_links_in_new_tab
object.user_option.external_links_in_new_tab
end
def dynamic_favicon
object.user_option.dynamic_favicon
end
def title_count_mode
object.user_option.title_count_mode
end
def automatically_unpin_topics
object.user_option.automatically_unpin_topics
end
def should_be_redirected_to_top
object.user_option.should_be_redirected_to_top
end
def redirected_to_top
object.user_option.redirected_to_top
end
def timezone
object.user_option.timezone
end
def default_calendar
object.user_option.default_calendar
end
def bookmark_auto_delete_preference
object.user_option.bookmark_auto_delete_preference
end
def sidebar_list_destination def sidebar_list_destination
object.user_option.sidebar_list_none_selected? ? SiteSetting.default_sidebar_list_destination : object.user_option.sidebar_list_destination object.user_option.sidebar_list_none_selected? ? SiteSetting.default_sidebar_list_destination : object.user_option.sidebar_list_destination
end end
@ -203,10 +140,6 @@ class CurrentUserSerializer < BasicUserSerializer
true true
end end
def include_redirected_to_top?
object.user_option.redirected_to_top.present?
end
def custom_fields def custom_fields
fields = nil fields = nil
if SiteSetting.public_user_custom_fields.present? if SiteSetting.public_user_custom_fields.present?
@ -278,26 +211,6 @@ class CurrentUserSerializer < BasicUserSerializer
scope.can_see_review_queue? scope.can_see_review_queue?
end end
def mailing_list_mode
object.user_option.mailing_list_mode
end
def treat_as_new_topic_start_date
object.user_option.treat_as_new_topic_start_date
end
def skip_new_user_tips
object.user_option.skip_new_user_tips
end
def seen_popups
object.user_option.seen_popups
end
def include_seen_popups?
SiteSetting.enable_user_tips
end
def include_primary_group_id? def include_primary_group_id?
object.primary_group_id.present? object.primary_group_id.present?
end end
@ -364,10 +277,6 @@ class CurrentUserSerializer < BasicUserSerializer
object.redesigned_user_menu_enabled? object.redesigned_user_menu_enabled?
end end
def likes_notifications_disabled
object.user_option&.likes_notifications_disabled?
end
def include_all_unread_notifications_count? def include_all_unread_notifications_count?
redesigned_user_menu_enabled redesigned_user_menu_enabled
end end

View File

@ -7,9 +7,7 @@ import User from "discourse/models/user";
registerUnbound("format-chat-date", function (message, details, mode) { registerUnbound("format-chat-date", function (message, details, mode) {
let currentUser = User.current(); let currentUser = User.current();
let tz = currentUser let tz = currentUser ? currentUser.user_option.timezone : moment.tz.guess();
? currentUser.resolvedTimezone(currentUser)
: moment.tz.guess();
let date = moment(new Date(message.created_at), tz); let date = moment(new Date(message.created_at), tz);

View File

@ -66,8 +66,7 @@ export default {
api.decorateCookedElement( api.decorateCookedElement(
(elem) => { (elem) => {
const currentUser = getOwner(this).lookup("service:current-user"); const currentUser = getOwner(this).lookup("service:current-user");
const currentUserTimezone = const currentUserTimezone = currentUser?.user_option?.timezone;
currentUser?.resolvedTimezone(currentUser);
const chatTranscriptElements = const chatTranscriptElements =
elem.querySelectorAll(".chat-transcript"); elem.querySelectorAll(".chat-transcript");

View File

@ -383,7 +383,7 @@ export default {
if (status.ends_at) { if (status.ends_at) {
const untilFormatted = until( const untilFormatted = until(
status.ends_at, status.ends_at,
this.chatService.currentUser.timezone, this.chatService.currentUser.user_option.timezone,
this.chatService.currentUser.locale this.chatService.currentUser.locale
); );
title += ` ${untilFormatted}`; title += ` ${untilFormatted}`;

View File

@ -13,7 +13,7 @@ import { cloneJSON } from "discourse-common/lib/object";
acceptance( acceptance(
"Local Dates - Download calendar without default calendar option set", "Local Dates - Download calendar without default calendar option set",
function (needs) { function (needs) {
needs.user({ default_calendar: "none_selected" }); needs.user({ "user_option.default_calendar": "none_selected" });
needs.settings({ discourse_local_dates_enabled: true }); needs.settings({ discourse_local_dates_enabled: true });
needs.pretender((server, helper) => { needs.pretender((server, helper) => {
const response = cloneJSON(fixturesByUrl["/t/281.json"]); const response = cloneJSON(fixturesByUrl["/t/281.json"]);
@ -43,7 +43,7 @@ acceptance(
acceptance( acceptance(
"Local Dates - Download calendar is not available for dates in the past", "Local Dates - Download calendar is not available for dates in the past",
function (needs) { function (needs) {
needs.user({ default_calendar: "none_selected" }); needs.user({ "user_option.default_calendar": "none_selected" });
needs.settings({ discourse_local_dates_enabled: true }); needs.settings({ discourse_local_dates_enabled: true });
needs.pretender((server, helper) => { needs.pretender((server, helper) => {
const response = cloneJSON(fixturesByUrl["/t/281.json"]); const response = cloneJSON(fixturesByUrl["/t/281.json"]);
@ -69,7 +69,7 @@ acceptance(
acceptance( acceptance(
"Local Dates - Download calendar with default calendar option set", "Local Dates - Download calendar with default calendar option set",
function (needs) { function (needs) {
needs.user({ default_calendar: "google" }); needs.user({ "user_option.default_calendar": "google" });
needs.settings({ discourse_local_dates_enabled: true }); needs.settings({ discourse_local_dates_enabled: true });
needs.pretender((server, helper) => { needs.pretender((server, helper) => {
const response = cloneJSON(fixturesByUrl["/t/281.json"]); const response = cloneJSON(fixturesByUrl["/t/281.json"]);

View File

@ -11,7 +11,7 @@ export default class ComposerPresenceManager extends Service {
notifyState(intent, id) { notifyState(intent, id) {
if ( if (
this.siteSettings.allow_users_to_hide_profile && this.siteSettings.allow_users_to_hide_profile &&
this.currentUser.hide_profile_and_presence this.currentUser.user_option.hide_profile_and_presence
) { ) {
return; return;
} }

View File

@ -331,16 +331,16 @@ RSpec.describe CurrentUserSerializer do
describe "#likes_notifications_disabled" do describe "#likes_notifications_disabled" do
it "is true if the user disables likes notifications" do it "is true if the user disables likes notifications" do
user.user_option.update!(like_notification_frequency: UserOption.like_notification_frequency_type[:never]) user.user_option.update!(like_notification_frequency: UserOption.like_notification_frequency_type[:never])
expect(serializer.as_json[:likes_notifications_disabled]).to eq(true) expect(serializer.as_json[:user_option][:likes_notifications_disabled]).to eq(true)
end end
it "is false if the user doesn't disable likes notifications" do it "is false if the user doesn't disable likes notifications" do
user.user_option.update!(like_notification_frequency: UserOption.like_notification_frequency_type[:always]) user.user_option.update!(like_notification_frequency: UserOption.like_notification_frequency_type[:always])
expect(serializer.as_json[:likes_notifications_disabled]).to eq(false) expect(serializer.as_json[:user_option][:likes_notifications_disabled]).to eq(false)
user.user_option.update!(like_notification_frequency: UserOption.like_notification_frequency_type[:first_time_and_daily]) user.user_option.update!(like_notification_frequency: UserOption.like_notification_frequency_type[:first_time_and_daily])
expect(serializer.as_json[:likes_notifications_disabled]).to eq(false) expect(serializer.as_json[:user_option][:likes_notifications_disabled]).to eq(false)
user.user_option.update!(like_notification_frequency: UserOption.like_notification_frequency_type[:first_time]) user.user_option.update!(like_notification_frequency: UserOption.like_notification_frequency_type[:first_time])
expect(serializer.as_json[:likes_notifications_disabled]).to eq(false) expect(serializer.as_json[:user_option][:likes_notifications_disabled]).to eq(false)
end end
end end