[FIX] web: avoid week number calculation errors

When opening the calendar view in, for example, the timesheets app, the first
day of the week used for the number calculation is provided by the localization
service, which in turn requests it from the database. Because the first day of
the week is stored as a number between 1 and 7 in the res.lang model and a
value between 0 and 6 is expected by the DateEnv, offset errors can occur.

The error is fixed in various components (for example, the CalendarDatePicker
and CalendarCommonRenderer) but not in others (CalendarYearRenderer). Instead
of patching each component separately, a better solution is to require the
CalendarModel to expose a 0 to 6 firstDayOfWeek value as part of its public
interface.

opw-3389617

closes odoo/odoo#142056

X-original-commit: aea22a46515304df41dfaf427f5955824fe342f5
Signed-off-by: Michaël Mattiello (mcm) <mcm@odoo.com>
This commit is contained in:
Tom De Caluwé
2023-11-28 21:20:48 +00:00
committed by Michael (mcm)
parent daa1b46608
commit 48634a2adf
3 changed files with 124 additions and 7 deletions
@@ -91,7 +91,7 @@ export class CalendarCommonRenderer extends Component {
eventResize: this.onEventResize,
eventResizeStart: this.onEventResizeStart,
events: (_, successCb) => successCb(this.mapRecordsToEvents()),
firstDay: this.props.model.firstDayOfWeek % 7,
firstDay: this.props.model.firstDayOfWeek,
header: false,
height: "parent",
locale: luxon.Settings.defaultLocale,
@@ -29,7 +29,7 @@ export class CalendarModel extends Model {
...params,
activeFields,
fields,
firstDayOfWeek: localization.weekStart,
firstDayOfWeek: (localization.weekStart || 0) % 7,
formViewId: params.formViewId || formViewIdFromConfig,
};
@@ -361,8 +361,8 @@ export class CalendarModel extends Model {
}
if (["week", "month"].includes(scale)) {
const weekday = start.weekday < firstDayOfWeek ? firstDayOfWeek - 7 : firstDayOfWeek;
start = start.set({ weekday });
const currentWeekOffset = (start.weekday - firstDayOfWeek + 7) % 7;
start = start.minus({ days: currentWeekOffset });
end = start.plus({ weeks: scale === "week" ? 1 : 6, days: -1 });
}
@@ -43,6 +43,7 @@ import { dialogService } from "@web/core/dialog/dialog_service";
import { localization } from "@web/core/l10n/localization";
import { registry } from "@web/core/registry";
import { userService } from "@web/core/user_service";
import { CalendarYearRenderer } from "@web/views/calendar/calendar_year/calendar_year_renderer";
import { actionService } from "@web/webclient/actions/action_service";
import { getTimePickers } from "../../core/datetime/datetime_test_helpers";
import { CalendarController } from "@web/views/calendar/calendar_controller";
@@ -2670,7 +2671,6 @@ QUnit.module("Views", ({ beforeEach }) => {
</calendar>
`,
});
const colorClass = Array.from(findEvent(target, 1).classList).find((className) =>
className.startsWith("o_calendar_color_")
);
@@ -4121,7 +4121,7 @@ QUnit.module("Views", ({ beforeEach }) => {
});
QUnit.test(`Monday week start week mode`, async (assert) => {
assert.expect(3);
assert.expect(4);
patchDate(2019, 8, 15, 8, 0, 0); // 2019-09-15 08:00:00
// the week start depends on the locale
@@ -4162,10 +4162,15 @@ QUnit.module("Views", ({ beforeEach }) => {
"Sun 15",
"The last day of the week should be Sunday the 15th"
);
assert.strictEqual(
target.querySelector(".fc-head .fc-week-number").textContent,
"Week 37",
"The number of the week should be correct"
);
});
QUnit.test(`Saturday week start week mode`, async (assert) => {
assert.expect(3);
assert.expect(4);
patchDate(2019, 8, 12, 8, 0, 0); // 2019-09-12 08:00:00
@@ -4207,6 +4212,118 @@ QUnit.module("Views", ({ beforeEach }) => {
"Fri 13",
"The last day of the week should be Friday the 13th"
);
assert.strictEqual(
target.querySelector(".fc-head .fc-week-number").textContent,
"Week 36",
"The number of the week should be correct"
);
});
QUnit.test(`Monday week start year mode`, async (assert) => {
assert.expect(4);
patchDate(2019, 8, 15, 8, 0, 0); // 2019-09-15 08:00:00
// the week start depends on the locale
patchWithCleanup(localization, { weekStart: 1 });
patchWithCleanup(CalendarYearRenderer.prototype, {
get options() {
return { ...super.options, weekNumbers: true };
},
});
await makeView({
type: "calendar",
resModel: "event",
serverData,
arch: `
<calendar date_start="start" date_stop="stop" mode="year" />
`,
mockRPC(route, { method, model, kwargs }) {
if (model === "event" && method === "search_read") {
assert.deepEqual(
kwargs.domain,
[
["start", "<=", "2019-12-31 22:59:59"],
["stop", ">=", "2018-12-31 23:00:00"],
],
"The domain to search events in should be correct"
);
}
},
});
const weekRow = target.querySelector(".fc-day-top.fc-today").closest("tr");
const weekDays = weekRow.querySelectorAll(".fc-day-top");
assert.strictEqual(
weekDays[0].textContent,
"9",
"The first day of the week should be Monday the 9th"
);
assert.strictEqual(
weekDays[weekDays.length - 1].textContent,
"15",
"The last day of the week should be Sunday the 15th"
);
assert.strictEqual(
weekRow.querySelector(".fc-week-number").textContent,
"37",
"The number of the week should be correct"
);
});
QUnit.test(`Sunday week start year mode`, async (assert) => {
assert.expect(4);
patchDate(2019, 8, 15, 8, 0, 0); // 2019-09-15 08:00:00
// the week start depends on the locale
// the localization presents a python-like 1 to 7 weekStart value
patchWithCleanup(localization, { weekStart: 7 });
patchWithCleanup(CalendarYearRenderer.prototype, {
get options() {
return { ...super.options, weekNumbers: true };
},
});
await makeView({
type: "calendar",
resModel: "event",
serverData,
arch: `
<calendar date_start="start" date_stop="stop" mode="year" />
`,
mockRPC(route, { method, model, kwargs }) {
if (model === "event" && method === "search_read") {
assert.deepEqual(
kwargs.domain,
[
["start", "<=", "2019-12-31 22:59:59"],
["stop", ">=", "2018-12-31 23:00:00"],
],
"The domain to search events in should be correct"
);
}
},
});
const weekRow = target.querySelector(".fc-day-top.fc-today").closest("tr");
const weekDays = weekRow.querySelectorAll(".fc-day-top");
assert.strictEqual(
weekDays[0].textContent,
"15",
"The first day of the week should be Sunday the 15th"
);
assert.strictEqual(
weekDays[weekDays.length - 1].textContent,
"21",
"The last day of the week should be Saturday the 21st"
);
assert.strictEqual(
weekRow.querySelector(".fc-week-number").textContent,
"38",
"The number of the week should be correct"
);
});
QUnit.test(