[REF] web: Remove underscore.js

Underscore.js has been removed from legacy qweb engine
and from web manifest.py
range and uniqueId functions has been added to qweb
engine to replace usages of them in xml templates.
Underscore usages has been remove from xml templates.
taskId : 3246238

closes odoo/odoo#123018

Signed-off-by: Julien Mougenot (jum) <jum@odoo.com>
This commit is contained in:
Pulinckx Pierre (PIPU)
2023-06-05 13:31:35 +02:00
parent 4e3f84f394
commit f2a8e6bd51
11 changed files with 52 additions and 42 deletions
+5 -5
View File
@@ -1277,7 +1277,7 @@ export class PosGlobalState extends PosModel {
taxes = [...taxes].sort(function (tax1, tax2) {
return tax1.sequence - tax2.sequence;
});
_(taxes).each(function (tax) {
taxes.forEach((tax) => {
if (tax.amount_type === "group") {
all_taxes = _collect_taxes(tax.children_tax_ids, all_taxes);
} else {
@@ -1328,7 +1328,7 @@ export class PosGlobalState extends PosModel {
var cached_tax_amounts = {};
if (handle_price_include) {
_(taxes.reverse()).each(function (tax) {
taxes.reverse().forEach(function (tax) {
if (tax.include_base_amount) {
base = recompute_base(
base,
@@ -1378,7 +1378,7 @@ export class PosGlobalState extends PosModel {
var taxes_vals = [];
i = 0;
var cumulated_tax_included_amount = 0;
_(taxes.reverse()).each(function (tax) {
taxes.reverse().forEach(function (tax) {
if (tax.price_include || tax.is_base_affected) {
var tax_base_amount = base;
} else {
@@ -2458,7 +2458,7 @@ export class Orderline extends PosModel {
qty,
this.pos.currency.rounding
);
_(all_taxes.taxes).each(function (tax) {
all_taxes.taxes.forEach(function (tax) {
taxtotal += tax.amount;
taxdetail[tax.id] = tax.amount;
});
@@ -2481,7 +2481,7 @@ export class Orderline extends PosModel {
var mapped_included_taxes = [];
var new_included_taxes = [];
var self = this;
_(taxes).each(function (tax) {
taxes.forEach((tax) => {
var line_taxes = self.pos.get_taxes_after_fp([tax.id], order.fiscal_position);
if (line_taxes.length && line_taxes[0].price_include) {
new_included_taxes = new_included_taxes.concat(line_taxes);
@@ -8,13 +8,13 @@
t-att-style="inline_mode ? 'display:inline' : ''"
t-attf-aria-label="#{Math.round(val * 100) / 100} stars on 5"
t-attf-title="#{Math.round(val * 100) / 100} stars on 5">
<t t-foreach="_.range(0, val_integer)" t-as="num">
<t t-foreach="range(0, val_integer)" t-as="num">
<i class="fa fa-star" role="img"></i>
</t>
<t t-if="val_decimal">
<i class="fa fa-star-half-o" role="img"></i>
</t>
<t t-foreach="_.range(0, empty_star)" t-as="num">
<t t-foreach="range(0, empty_star)" t-as="num">
<i class="fa fa-star text-black-25" role="img"></i>
</t>
</div>
@@ -74,13 +74,13 @@
<t t-set="empty_star" t-value="5 - (val_integer+Math.ceil(val_decimal))"/>
<div class="stars enabled">
<t t-foreach="_.range(0, val_integer)" t-as="num">
<t t-foreach="range(0, val_integer)" t-as="num">
<i class="fa fa-star" role="img" aria-label="Full star"></i>
</t>
<t t-if="val_decimal">
<i class="fa fa-star-half-o" role="img" aria-label="Half a star"></i>
</t>
<t t-foreach="_.range(0, empty_star)" t-as="num">
<t t-foreach="range(0, empty_star)" t-as="num">
<i class="fa fa-star-o text-black-25" role="img" aria-label="Empty star"></i>
</t>
</div>
-6
View File
@@ -76,8 +76,6 @@ This module provides the core of the Odoo Web Client.
'web/static/src/session.js',
'web/static/src/legacy/js/core/cookie_utils.js',
'web/static/lib/underscore/underscore.js',
'web/static/lib/underscore.string/lib/underscore.string.js',
'web/static/lib/moment/moment.js',
'web/static/lib/luxon/luxon.js',
'web/static/lib/owl/owl.js',
@@ -123,7 +121,6 @@ This module provides the core of the Odoo Web Client.
'web/static/src/legacy/js/libs/download.js',
'web/static/src/legacy/js/libs/jquery.js',
'web/static/src/legacy/js/libs/moment.js',
'web/static/src/legacy/js/libs/underscore.js',
'web/static/src/legacy/js/libs/pdfjs.js',
'web/static/src/legacy/js/libs/zoomodoo.js',
'web/static/src/legacy/js/libs/jSignatureCustom.js',
@@ -307,8 +304,6 @@ This module provides the core of the Odoo Web Client.
('include', 'web.assets_frontend_minimal'),
'web/static/lib/underscore/underscore.js',
'web/static/lib/underscore.string/lib/underscore.string.js',
'web/static/lib/moment/moment.js',
'web/static/lib/owl/owl.js',
'web/static/lib/owl/odoo_module.js',
@@ -354,7 +349,6 @@ This module provides the core of the Odoo Web Client.
'web/static/src/legacy/js/libs/download.js',
'web/static/src/legacy/js/libs/jquery.js',
'web/static/src/legacy/js/libs/moment.js',
'web/static/src/legacy/js/libs/underscore.js',
'web/static/src/legacy/js/libs/pdfjs.js',
'web/static/src/legacy/js/libs/zoomodoo.js',
'web/static/src/legacy/js/libs/jSignatureCustom.js',
+26 -17
View File
@@ -326,15 +326,14 @@ datetime.timedelta = py.type('timedelta', null, {
ss = s;
});
});
var s = _.str.sprintf("%d:%02d:%02d", hh, mm, ss);
var s = `${hh.toFixed(0)}:${mm.toFixed(0).padStart(2,"0")}:${ss.toFixed(0).padStart(2,"0")}`
if (this.days) {
s = _.str.sprintf("%d day%s, %s",
this.days,
(this.days != 1 && this.days != -1) ? 's' : '',
s);
s = `${this.days.toFixed(0)} day${
this.days != 1 && this.days != -1 ? "s" : ""
}, ${s}`;
}
if (this.microseconds) {
s = _.str.sprintf("%s.%06d", s, this.microseconds);
s = `${s}.${this.microseconds.toFixed(0).padStart(6, "0")}`;
}
return py.str.fromJSON(s);
},
@@ -545,12 +544,18 @@ datetime.datetime = py.type('datetime', null, {
return py.str.fromJSON(args.format.toJSON()
.replace(/%([A-Za-z])/g, function (m, c) {
switch (c) {
case 'Y': return _.str.sprintf('%04d', self.year);
case 'm': return _.str.sprintf('%02d', self.month);
case 'd': return _.str.sprintf('%02d', self.day);
case 'H': return _.str.sprintf('%02d', self.hour);
case 'M': return _.str.sprintf('%02d', self.minute);
case 'S': return _.str.sprintf('%02d', self.second);
case "Y":
return self.year.toFixed(0).padStart(4, "0");
case "m":
return self.month.toFixed(0).padStart(2, "0");
case "d":
return self.day.toFixed(0).padStart(2, "0");
case "H":
return self.hour.toFixed(0).padStart(2, "0");
case "M":
return self.minute.toFixed(0).padStart(2, "0");
case "S":
return self.second.toFixed(0).padStart(2, "0");
}
throw new Error('ValueError: No known conversion for ' + m);
}));
@@ -635,8 +640,8 @@ datetime.date = py.type('date', null, {
.replace(/%([A-Za-z])/g, function (m, c) {
switch (c) {
case 'Y': return self.year;
case 'm': return _.str.sprintf('%02d', self.month);
case 'd': return _.str.sprintf('%02d', self.day);
case 'm': return self.month.toFixed(0).padStart(2, "0");
case 'd': return self.day.toFixed(0).padStart(2, "0");
}
throw new Error('ValueError: No known conversion for ' + m);
}));
@@ -786,9 +791,13 @@ time.strftime = py.PY_def.fromJSON(function () {
return py.PY_call(py.PY_getAttr(d, 'strftime'), [args.format]);
});
var args = _.map(('year month day hour minute second '
+ 'years months weeks days hours minutes seconds '
+ 'weekday leapdays yearday nlyearday').split(' '), function (arg) {
var args = (
'year month day hour minute second '+
'years months weeks days hours minutes seconds '+
'weekday leapdays yearday nlyearday'
)
.split(" ")
.map( (arg) => {
switch (arg) {
case 'years':case 'months':case 'days':case 'leapdays':case 'weeks':
case 'hours':case 'minutes':case 'seconds':
@@ -106,7 +106,7 @@ function wrap_context(context) {
function eval_contexts(contexts, evaluation_context) {
evaluation_context = Object.assign(pycontext(), evaluation_context || {});
return _(contexts).reduce(function (result_context, ctx) {
return contexts.reduce((result_context, ctx) => {
// __eval_context evaluations can lead to some of `contexts`'s
// values being null, skip them as well as empty contexts
if (Object.keys(ctx || {}).length === 0) { return result_context; }
@@ -143,7 +143,7 @@ function eval_domains(domains, evaluation_context) {
domains[0].length === 1 &&
(domains[0][0] === "|" || domains[0][0] === "!")
);
_(domains).each(function (domain) {
(domains || []).forEach(function (domain) {
if (typeof domain === "string") {
// wrap raw strings in domain
domain = { __ref: 'domain', __debug: domain };
@@ -189,7 +189,7 @@ function get_normalized_domain(domain_array) {
function eval_groupbys(contexts, evaluation_context) {
evaluation_context = Object.assign(pycontext(), evaluation_context || {});
var result_group = [];
_(contexts).each(function (ctx) {
(contexts || []).forEach(function (ctx) {
if (typeof ctx === "string") {
// wrap raw strings in context
ctx = { __ref: 'context', __debug: ctx };
+5 -1
View File
@@ -1,5 +1,7 @@
/** @odoo-module alias=web.QWeb **/
import { uniqueId } from "@web/core/utils/functions";
import { range } from "@web/core/utils/numbers";
import translation from "web.translation";
var _t = translation._t;
@@ -18,7 +20,9 @@ function QWeb(debug, default_dict, enableTranslation) {
}
var qweb = new QWeb2.Engine();
qweb.default_dict = Object.assign({}, default_dict || {}, {
'_' : _,
// '_' : _,
'uniqueId': uniqueId,
'range' : range,
'JSON': JSON,
'_t' : translation._t,
'__debug__': debug,
+1 -1
View File
@@ -114,7 +114,7 @@ $.fn.extend({
events = events.split(' ');
return this.each(function () {
var el = this;
_.each(events, function (evNameNamespaced) {
events.forEach((evNameNamespaced) => {
var evName = evNameNamespaced.split('.')[0];
var handler = $._data(el, 'events')[evName].pop();
$._data(el, 'events')[evName].unshift(handler);
@@ -155,6 +155,9 @@ var ModelFieldSelector = Widget.extend({
this.$value.html(core.qweb.render(this.template + ".value", {
chain: this.popover.chain,
pages: this.popover.pages,
findByName : (array, name) => {
return (array || []).find((arr) => arr.name === name)
}
}));
// Toggle the warning message
+2 -2
View File
@@ -478,7 +478,7 @@
<t t-esc="fieldName"/>
</t>
<t t-else="">
<t t-set="fieldInfo" t-value="_.findWhere(pages[fieldName_index], {'name': fieldName})"/>
<t t-set="fieldInfo" t-value="findByName(pages[fieldName_index], fieldName)"/>
<t t-esc="fieldInfo &amp;&amp; fieldInfo.string || '?'"/>
</t>
</span>
@@ -504,7 +504,7 @@
<t t-name="web.datepicker">
<t t-set="placeholder" t-value="widget.getParent().node and widget.getParent().node.attrs.placeholder"/>
<t t-set="datepickerID" t-value="_.uniqueId('datepicker')"/>
<t t-set="datepickerID" t-value="uniqueId('datepicker')"/>
<div class="o_datepicker" aria-atomic="true" t-att-id="datepickerID" data-target-input="nearest">
<input type="text"
class="o_datepicker_input o_input datetimepicker-input"
+1 -1
View File
@@ -8,7 +8,7 @@
t-attf-class="modal o_legacy_dialog #{ technical ? ' o_technical_modal' : '' } #{ fullscreen ? ' o_modal_full': '' }"
tabindex="-1"
data-bs-backdrop="static"
t-att-id="_.uniqueId('modal_')"
t-att-id="uniqueId('modal_')"
aria-hidden="true"
>
<div class="modal-dialog">
@@ -278,10 +278,10 @@
if (!self.check_error_fields({})) {
if (this.fileInputError) {
const errorMessage = this.fileInputError.type === "number"
? _.str.sprintf(_t(
? sprintf(_t(
"Please fill in the form correctly. You uploaded too many files. (Maximum %s files)"
), this.fileInputError.limit)
: _.str.sprintf(_t(
: sprintf(_t(
"Please fill in the form correctly. The file \"%s\" is too big. (Maximum %s MB)"
), this.fileInputError.fileName, this.fileInputError.limit);
this.update_status("error", errorMessage);