DEV: improve timezone API on the client (#16660)

This commit is contained in:
Andrei Prigorshnev 2022-05-13 13:21:56 +04:00 committed by GitHub
parent 6bea6cba5d
commit 7412f665e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 87 additions and 144 deletions

View File

@ -55,7 +55,7 @@ export default Component.extend({
postDetectedLocalTime: null,
postDetectedLocalTimezone: null,
prefilledDatetime: null,
userTimezone: this.currentUser.resolvedTimezone(this.currentUser),
userTimezone: this.currentUser.timezone,
showOptions: false,
_itsatrap: new ItsATrap(),
autoDeletePreference: this.model.autoDeletePreference || 0,

View File

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

View File

@ -27,7 +27,7 @@ export default Component.extend({
init() {
this._super(...arguments);
this.userTimezone = this.currentUser.resolvedTimezone(this.currentUser);
this.userTimezone = this.currentUser.timezone;
if (this.input) {
const dateTime = moment(this.input);

View File

@ -76,7 +76,7 @@ export default Component.extend({
_setupPicker() {
this.setProperties({
customTime: this.defaultCustomReminderTime,
userTimezone: this.currentUser.resolvedTimezone(this.currentUser),
userTimezone: this.currentUser.timezone,
hiddenOptions: this.hiddenOptions || [],
customOptions: this.customOptions || [],
customLabels: this.customLabels || {},

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -126,7 +126,7 @@ export default Controller.extend({
// 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.changeTimezone(this.model.user_option.timezone);
this.currentUser.timezone = this.model.user_option.timezone;
}
cookAsync(model.get("bio_raw"))

View File

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

View File

@ -670,11 +670,6 @@ const User = RestModel.extend({
json.user.card_badge = Badge.create(json.user.card_badge);
}
if (!json.user._timezone) {
json.user._timezone = json.user.timezone;
delete json.user.timezone;
}
user.setProperties(json.user);
return user;
});
@ -961,34 +956,9 @@ const User = RestModel.extend({
);
},
resolvedTimezone(currentUser) {
if (this.hasSavedTimezone()) {
return this._timezone;
}
// only change the timezone and save it if we are
// looking at our own user
if (currentUser.id === this.id) {
this.changeTimezone(moment.tz.guess());
ajax(userPath(this.username + ".json"), {
type: "PUT",
dataType: "json",
data: { timezone: this._timezone },
});
}
return this._timezone;
},
changeTimezone(tz) {
this._timezone = tz;
},
hasSavedTimezone() {
if (this._timezone) {
return true;
}
return false;
// obsolete, just call "user.timezone" instead
resolvedTimezone() {
return this.timezone;
},
calculateMutedIds(notificationLevel, id, type) {
@ -1040,17 +1010,6 @@ const User = RestModel.extend({
});
User.reopenClass(Singleton, {
munge(json) {
// timezone should not be directly accessed, use
// resolvedTimezone() and changeTimezone(tz)
if (!json._timezone) {
json._timezone = json.timezone;
delete json.timezone;
}
return json;
},
// Find a `User` for a given username.
findByUsername(username, options) {
const user = User.create({ username });
@ -1059,22 +1018,26 @@ User.reopenClass(Singleton, {
// TODO: Use app.register and junk Singleton
createCurrent() {
let userJson = PreloadStore.get("currentUser");
if (userJson && userJson.primary_group_id) {
const primaryGroup = userJson.groups.find(
(group) => group.id === userJson.primary_group_id
);
if (primaryGroup) {
userJson.primary_group_name = primaryGroup.name;
}
}
const userJson = PreloadStore.get("currentUser");
if (userJson) {
userJson = User.munge(userJson);
if (userJson.primary_group_id) {
const primaryGroup = userJson.groups.find(
(group) => group.id === userJson.primary_group_id
);
if (primaryGroup) {
userJson.primary_group_name = primaryGroup.name;
}
}
if (!userJson.timezone) {
userJson.timezone = moment.tz.guess();
this._saveTimezone(userJson);
}
const store = getOwner(this).lookup("service:store");
return store.createRecord("user", userJson);
}
return null;
},
@ -1145,6 +1108,14 @@ User.reopenClass(Singleton, {
type: "POST",
});
},
_saveTimezone(user) {
ajax(userPath(user.username + ".json"), {
type: "PUT",
dataType: "json",
data: { timezone: user.timezone },
});
},
});
if (typeof Discourse !== "undefined") {

View File

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

View File

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

View File

@ -241,7 +241,7 @@ acceptance("Bookmarking", function (needs) {
test("Editing a bookmark", async function (assert) {
await visit("/t/internationalization-localization/280");
let now = moment.tz(loggedInUser().resolvedTimezone(loggedInUser()));
let now = moment.tz(loggedInUser().timezone);
let tomorrow = now.add(1, "day").format("YYYY-MM-DD");
await openBookmarkModal();
await fillIn("input#bookmark-name", "Test name");
@ -267,10 +267,7 @@ acceptance("Bookmarking", function (needs) {
test("Using a post date for the reminder date", async function (assert) {
await visit("/t/internationalization-localization/280");
let postDate = moment.tz(
"2036-01-15",
loggedInUser().resolvedTimezone(loggedInUser())
);
let postDate = moment.tz("2036-01-15", loggedInUser().timezone);
let postDateFormatted = postDate.format("YYYY-MM-DD");
await openBookmarkModal();
await fillIn("input#bookmark-name", "Test name");

View File

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

View File

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

View File

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

View File

@ -19,7 +19,7 @@ acceptance("User Card - Show Local Time", function (needs) {
});
test("user card local time - does not update timezone for another user", async function (assert) {
User.current().changeTimezone("Australia/Brisbane");
User.current().timezone = "Australia/Brisbane";
await visit("/t/internationalization-localization/280");
await click('a[data-user-card="charlie"]');

View File

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

View File

@ -56,7 +56,7 @@ discourseModule("Unit | Lib | select-kit/future-date-input", function (hooks) {
beforeEach() {
const monday = "2100-12-13T08:00:00";
this.clock = fakeTime(monday, this.currentUser._timezone, true);
this.clock = fakeTime(monday, this.currentUser.timezone, true);
},
async test(assert) {

View File

@ -40,7 +40,7 @@ discourseModule(
beforeEach() {
this.siteSettings.suggest_weekends_in_date_pickers = true;
const tuesday = "2100-06-08T08:00:00";
this.clock = fakeTime(tuesday, this.currentUser._timezone, true);
this.clock = fakeTime(tuesday, this.currentUser.timezone, true);
},
async test(assert) {
@ -70,7 +70,7 @@ discourseModule(
beforeEach() {
const monday = "2100-06-07T08:00:00";
this.clock = fakeTime(monday, this.currentUser._timezone, true);
this.clock = fakeTime(monday, this.currentUser.timezone, true);
},
test(assert) {
@ -86,7 +86,7 @@ discourseModule(
beforeEach() {
const thursday = "2100-06-10T08:00:00";
this.clock = fakeTime(thursday, this.currentUser._timezone, true);
this.clock = fakeTime(thursday, this.currentUser.timezone, true);
},
test(assert) {
@ -103,7 +103,7 @@ discourseModule(
beforeEach() {
this.clock = fakeTime(
"2100-12-11T22:00:00", // + 3 hours is tomorrow
this.currentUser._timezone,
this.currentUser.timezone,
true
);
},
@ -122,7 +122,7 @@ discourseModule(
beforeEach() {
this.clock = fakeTime(
"2100-12-11T16:50:00",
this.currentUser._timezone,
this.currentUser.timezone,
true
);
},
@ -138,7 +138,7 @@ discourseModule(
beforeEach() {
this.clock = fakeTime(
"2100-12-11T17:00:00",
this.currentUser._timezone,
this.currentUser.timezone,
true
);
},
@ -165,7 +165,7 @@ discourseModule(
beforeEach() {
const sunday = "2100-01-24T08:00:00";
this.clock = fakeTime(sunday, this.currentUser._timezone, true);
this.clock = fakeTime(sunday, this.currentUser.timezone, true);
},
async test(assert) {
@ -188,7 +188,7 @@ discourseModule(
beforeEach() {
const monday = "2100-01-25T08:00:00";
this.clock = fakeTime(monday, this.currentUser._timezone, true);
this.clock = fakeTime(monday, this.currentUser.timezone, true);
},
async test(assert) {
@ -214,7 +214,7 @@ discourseModule(
beforeEach() {
this.clock = fakeTime(
"2100-01-01T08:00:00",
this.currentUser._timezone,
this.currentUser.timezone,
true
);
},

View File

@ -1,8 +1,8 @@
import * as ajaxlib from "discourse/lib/ajax";
import { module, test } from "qunit";
import sinon from "sinon";
import Group from "discourse/models/group";
import User from "discourse/models/user";
import PreloadStore from "discourse/lib/preload-store";
import sinon from "sinon";
module("Unit | Model | user", function () {
test("staff", function (assert) {
@ -70,58 +70,36 @@ module("Unit | Model | user", function () {
);
});
test("resolvedTimezone", function (assert) {
const tz = "Australia/Brisbane";
let user = User.create({ timezone: tz, username: "chuck", id: 111 });
sinon.stub(moment.tz, "guess").returns("America/Chicago");
sinon.stub(ajaxlib.ajax);
let spy = sinon.spy(ajaxlib, "ajax");
assert.strictEqual(
user.resolvedTimezone(user),
tz,
"if the user already has a timezone return it"
);
assert.ok(
spy.notCalled,
"if the user already has a timezone do not call AJAX update"
);
user = User.create({ username: "chuck", id: 111 });
assert.strictEqual(
user.resolvedTimezone(user),
"America/Chicago",
"if the user has no timezone guess it with moment"
);
assert.ok(
spy.calledWith("/u/chuck.json", {
type: "PUT",
dataType: "json",
data: { timezone: "America/Chicago" },
}),
"if the user has no timezone save it with an AJAX update"
);
let otherUser = User.create({ username: "howardhamlin", id: 999 });
assert.strictEqual(
otherUser.resolvedTimezone(user),
undefined,
"if the user has no timezone and the user is not the current user, do NOT guess with moment"
);
assert.notOk(
spy.calledWith("/u/howardhamlin.json", {
type: "PUT",
dataType: "json",
data: { timezone: "America/Chicago" },
}),
"if the user has no timezone, and the user is not the current user, do NOT save it with an AJAX update"
);
});
test("muted ids", function (assert) {
let user = User.create({ username: "chuck", muted_category_ids: [] });
assert.deepEqual(user.calculateMutedIds(0, 1, "muted_category_ids"), [1]);
assert.deepEqual(user.calculateMutedIds(1, 1, "muted_category_ids"), []);
});
test("createCurrent() guesses timezone if user doesn't have it set", function (assert) {
PreloadStore.store("currentUser", {
username: "eviltrout",
timezone: null,
});
const expectedTimezone = "Africa/Casablanca";
sinon.stub(moment.tz, "guess").returns(expectedTimezone);
const currentUser = User.createCurrent();
assert.deepEqual(currentUser.timezone, expectedTimezone);
});
test("createCurrent() doesn't guess timezone if user has it already set", function (assert) {
const timezone = "Africa/Casablanca";
PreloadStore.store("currentUser", {
username: "eviltrout",
timezone,
});
const spyMomentGuess = sinon.spy(moment.tz, "guess");
User.createCurrent();
assert.ok(spyMomentGuess.notCalled);
});
});

View File

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