[REF] *:Replace moment usages with luxon

luxon and moment are both used in the solution,
but these two libraries facilitate the manipulation
of dates. It was decided to replace all uses of
moment with luxon so we can then remove
moment.js from the code and lighten the assets.

task-3391739

closes odoo/odoo#128752

Signed-off-by: Bruno Boi (boi) <boi@odoo.com>
This commit is contained in:
Pierre Pulinckx (pipu)
2023-07-31 19:02:45 +02:00
parent f97e704fb4
commit 3bc94e52ce
12 changed files with 40 additions and 33 deletions
@@ -6,6 +6,8 @@ import { registry } from "@web/core/registry";
import { registerCleanup } from "@web/../tests/helpers/cleanup";
import { makeMockServer } from "@web/../tests/helpers/mock_server";
import core from "@web/legacy/js/services/core";
import { serializeDateTime, serializeDate } from "@web/core/l10n/dates";
const { DateTime } = luxon;
const modelDefinitionsPromise = new Promise((resolve) => {
QUnit.begin(() => resolve(getModelDefinitions()));
@@ -56,8 +58,8 @@ async function getModelDefinitions() {
if (["date", "datetime"].includes(field.type) && !field.default) {
const defaultFieldValue =
field.type === "date"
? () => moment.utc().format("YYYY-MM-DD")
: () => moment.utc().format("YYYY-MM-DD HH:mm:ss");
? () => serializeDate(DateTime.utc())
: () => serializeDateTime(DateTime.utc());
field.default = defaultFieldValue;
} else if (fname === "active" && !("default" in field)) {
// records are active by default.
@@ -2,8 +2,8 @@
import { ActivityMenu } from "@mail/core/web/activity_menu";
import { patch } from "@web/core/utils/patch";
import fieldUtils from "@web/legacy/js/fields/field_utils";
import time from "@web/legacy/js/core/time";
import { deserializeDateTime, formatDateTime } from "@web/core/l10n/dates";
import { localization } from "@web/core/l10n/localization";
patch(ActivityMenu.prototype, "calendar", {
async fetchSystrayActivities() {
@@ -12,11 +12,8 @@ patch(ActivityMenu.prototype, "calendar", {
if (group.type === "meeting") {
for (const meeting of group.meetings) {
if (meeting.start) {
meeting.formattedStart = moment(
fieldUtils.parse.datetime(meeting.start, false, { isUTC: true })
)
.local()
.format(time.getLangTimeFormat());
const date = deserializeDateTime(meeting.start);
meeting.formattedStart = formatDateTime(date, { format: localization.timeFormat });
}
}
}
@@ -7,6 +7,7 @@ import { datetime_to_str } from "@web/legacy/js/core/time";
import { assignDefined } from "@mail/utils/common/misc";
import { formatDate } from "@web/core/l10n/dates";
import { Command } from "@mail/../tests/helpers/command";
const { DateTime } = luxon;
patch(MockServer.prototype, "mail/models/discuss_channel", {
async _performRPC(route, args) {
@@ -953,7 +954,7 @@ patch(MockServer.prototype, "mail/models/discuss_channel", {
*/
_mockDiscussChannelWriteImage128(id) {
this.pyEnv["discuss.channel"].write([id], {
avatarCacheKey: moment.utc().format("YYYYMMDDHHmmss"),
avatarCacheKey: DateTime.utc().toFormat("yyyyMMddHHmmss"),
});
const channel = this.pyEnv["discuss.channel"].searchRead([["id", "=", id]])[0];
this.pyEnv["bus.bus"]._sendone(channel, "mail.record/insert", {
@@ -3,7 +3,7 @@
import { sortBy } from "@web/core/utils/arrays";
import { patch } from "@web/core/utils/patch";
import { MockServer } from "@web/../tests/helpers/mock_server";
import { serializeDate } from "@web/core/l10n/dates";
import { serializeDate, deserializeDate } from "@web/core/l10n/dates";
const { DateTime} = luxon;
@@ -140,7 +140,7 @@ patch(MockServer.prototype, "mail/models/mail_activity", {
group.activity_type_id = group.activity_type_id[0];
let minDate;
activites.forEach(function (activity) {
if (!minDate || moment(activity.date_deadline) < moment(minDate)) {
if (!minDate || deserializeDate(activity.date_deadline) < deserializeDate(minDate)) {
minDate = activity.date_deadline;
}
});
@@ -149,7 +149,7 @@ patch(MockServer.prototype, "mail/models/mail_activity", {
let state;
if (group.date_deadline === serializeDate(DateTime.now())) {
state = "today";
} else if (moment(group.date_deadline) > moment()) {
} else if (deserializeDate(group.date_deadline) > DateTime.now()) {
state = "planned";
} else {
state = "overdue";
@@ -183,7 +183,7 @@ patch(MockServer.prototype, "mail/models/mail_activity", {
}),
activity_res_ids: sortBy(
records.map((x) => x.id),
(id) => moment(resIdToDeadline[id])
(id) => deserializeDate(resIdToDeadline[id])
),
grouped_activities: groupedActivities,
};
@@ -3,7 +3,7 @@
import { Order } from "@point_of_sale/app/store/models";
import { registry } from "@web/core/registry";
import { useService } from "@web/core/utils/hooks";
import { deserializeDateTime } from "@web/core/l10n/dates";
import { deserializeDateTime, deserializeDate } from "@web/core/l10n/dates";
import { parseFloat } from "@web/views/fields/parsers";
import { _lt } from "@web/core/l10n/translation";
@@ -333,7 +333,7 @@ export class TicketScreen extends Component {
return this._getOrderList().filter(predicate);
}
getDate(order) {
return moment(order.validation_date).format("YYYY-MM-DD hh:mm A");
return deserializeDate(order.validation_date).toFormat("yyyy-MM-dd HH:mm a");
}
getTotal(order) {
return this.env.utils.formatCurrency(order.get_total_with_tax());
@@ -580,7 +580,7 @@ export class TicketScreen extends Component {
modelField: "pos_reference",
},
DATE: {
repr: (order) => moment(order.creation_date).format("YYYY-MM-DD hh:mm A"),
repr: (order) => deserializeDate(order.creation_date).toFormat("yyyy-MM-dd HH:mm a"),
displayName: this.env._t("Date"),
modelField: "date_order",
},
@@ -4,7 +4,7 @@ import { formatFloat } from "@web/views/fields/formatters";
import { uuidv4 } from "@point_of_sale/utils";
// FIXME POSREF - unify use of native parseFloat and web's parseFloat. We probably don't need the native version.
import { parseFloat as oParseFloat } from "@web/views/fields/parsers";
import { formatDate, formatDateTime, serializeDateTime } from "@web/core/l10n/dates";
import { formatDate, formatDateTime, serializeDateTime, deserializeDate } from "@web/core/l10n/dates";
import {
roundDecimals as round_di,
roundPrecision as round_pr,
@@ -227,8 +227,8 @@ export class Product extends PosModel {
const categories = this.parent_category_ids.concat(this.categ.id);
return (
(!item.categ_id || categories.includes(item.categ_id[0])) &&
(!item.date_start || moment.utc(item.date_start).isSameOrBefore(date)) &&
(!item.date_end || moment.utc(item.date_end).isSameOrAfter(date))
(!item.date_start || deserializeDate(item.date_start) <= date) &&
(!item.date_end || deserializeDate(item.date_end) >= date)
);
}
// Port of _get_product_price on product.pricelist.
@@ -242,7 +242,7 @@ export class Product extends PosModel {
// and were automatically sorted based on their _order by the
// ORM. After that they are added in this order to the pricelists.
get_price(pricelist, quantity, price_extra = 0, recurring = false) {
var date = moment();
const date = DateTime.now();
// In case of nested pricelists, it is necessary that all pricelists are made available in
// the POS. Display a basic alert to the user in the case where there is a pricelist item
@@ -1,6 +1,7 @@
/** @odoo-module */
import { Component, useState } from "@odoo/owl";
import { useService } from "@web/core/utils/hooks";
import { deserializeDateTime } from "@web/core/l10n/dates";
/**
* @props {models.Order} order
@@ -29,7 +30,7 @@ export class SaleOrderRow extends Component {
return this.order.name;
}
get date() {
return moment(this.order.date_order).format("YYYY-MM-DD hh:mm A");
return deserializeDateTime(this.order.date_order).toFormat("yyyy-MM-dd HH:mm a");
}
get partner() {
const partner = this.order.partner_id;
@@ -1,7 +1,7 @@
/** @odoo-module **/
import time from '@web/legacy/js/core/time';
import publicWidget from '@web/legacy/js/public/public_widget';
import { parseDate } from '@web/core/l10n/dates';
publicWidget.registry.ProjectRatingImage = publicWidget.Widget.extend({
selector: '.o_portal_project_rating .o_rating_image',
@@ -18,8 +18,8 @@ publicWidget.registry.ProjectRatingImage = publicWidget.Widget.extend({
var $elem = $(this);
var id = $elem.data('id');
var ratingDate = $elem.data('rating-date');
var baseDate = time.auto_str_to_date(ratingDate);
var duration = moment(baseDate).fromNow();
var baseDate = parseDate(ratingDate);
var duration = baseDate.toRelative();
var $rating = $('#rating_' + id);
$rating.find('.rating_timeduration').text(duration);
return $rating.html();
@@ -89,7 +89,7 @@ QUnit.module("test_mail", {}, function () {
});
var activityDateFormat = function (date) {
return date.toLocaleDateString(moment().locale(), { day: "numeric", month: "short" });
return DateTime.now().toLocaleString({ day: "numeric", month: "short" });
};
QUnit.test("activity view: simple activity rendering", async function (assert) {
+2
View File
@@ -297,6 +297,7 @@ export function formatDateTime(value, options = {}) {
/**
* Formats the given DateTime to the server date format.
* @param {DateTime} value
* @returns {string}
*/
export function serializeDate(value) {
if (!dateCache.has(value)) {
@@ -308,6 +309,7 @@ export function serializeDate(value) {
/**
* Formats the given DateTime to the server datetime format.
* @param {DateTime} value
* @returns {string}
*/
export function serializeDateTime(value) {
if (!dateTimeCache.has(value)) {
@@ -49,6 +49,7 @@ var _t = core._t;
const _lt = core._lt;
const preserveCursor = OdooEditorLib.preserveCursor;
const descendants = OdooEditorLib.descendants;
const { DateTime } = luxon;
/**
* @param {HTMLElement} el
@@ -1849,7 +1850,7 @@ const DatetimePickerUserValueWidget = InputUserValueWidget.extend({
*/
init: function () {
this._super(...arguments);
this._value = moment().unix().toString();
this._value = DateTime.now().toUnixInteger().toString();
this.__libInput = 0;
},
/**
@@ -4,6 +4,8 @@ import { sprintf } from "@web/core/utils/strings";
import {_t} from "@web/legacy/js/services/core";
import publicWidget from "@web/legacy/js/public/public_widget";
import time from "@web/legacy/js/core/time";
import { parseDate, formatDate } from "@web/core/l10n/dates";
const { DateTime } = luxon;
publicWidget.registry.crmPartnerAssign = publicWidget.Widget.extend({
selector: '#wrapwrap:has(.interested_partner_assign_form, .desinterested_partner_assign_form, .opp-stage-button, .new_opp_form)',
@@ -252,9 +254,10 @@ publicWidget.registry.crmPartnerAssign = publicWidget.Widget.extend({
$('.edit_opp_form .activity_summary').val($selected.attr('activity_summary'));
}
if ($selected.attr('delay_count')) {
var now = moment();
var date = now.add(parseInt($selected.attr('delay_count')), $selected.attr('delay_unit'));
$('.edit_opp_form .activity_date_deadline').val(date.format(time.getLangDateFormat()));
const value = +$selected.attr('delay_count');
const unit = $selected.attr('delay_unit');
const date = DateTime.now().plus({ [unit]: value});
$('.edit_opp_form .activity_date_deadline').val( formatDate(date) );
}
},
/**
@@ -277,9 +280,9 @@ publicWidget.registry.crmPartnerAssign = publicWidget.Widget.extend({
_parse_date: function (value) {
console.log(value);
var date = moment(value, time.getLangDateFormat(), true);
if (date.isValid() && date.year() >= 1900) {
return time.date_to_str(date.toDate());
var date = parseDate(value);
if (date.isValid && date.year >= 1900) {
return formatDate(date);
}
else {
return false;