[REF] *: Replace underscore function by native JS
Replace _.isNumber(), _.filter(), _.reject(), _.unique(), _.indexOf(), _.lastIndexOf(), _.findIndex(), _.range() _.keys(), _.values(), _.str.sprintf() and some _.each() closes odoo/odoo#118003 Signed-off-by: Géry Debongnie <ged@odoo.com>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import { _t } from "web.core";
|
||||
import Widget from "web.Widget";
|
||||
import { computeScore } from "@auth_password_policy/password_policy";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
export default Widget.extend({
|
||||
tagName: "meter",
|
||||
@@ -27,7 +28,7 @@ export default Widget.extend({
|
||||
);
|
||||
this.el.setAttribute(
|
||||
"title",
|
||||
_.str.sprintf(helpMessage, String(this._required) || _t("no requirements"))
|
||||
sprintf(helpMessage, String(this._required) || _t("no requirements"))
|
||||
);
|
||||
return this._super().then(function () {});
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@ BasicModel.include({
|
||||
_fetchSpecialAttendeeStatus: function (record, fieldName) {
|
||||
var context = record.getContext({fieldName: fieldName});
|
||||
var attendeeIDs = record.data[fieldName] ? this.localData[record.data[fieldName]].res_ids : [];
|
||||
var meetingID = _.isNumber(record.res_id) ? record.res_id : false;
|
||||
var meetingID = Number.isFinite(record.res_id) ? record.res_id : false;
|
||||
return this._rpc({
|
||||
model: 'res.partner',
|
||||
method: 'get_attendee_detail',
|
||||
|
||||
@@ -7,7 +7,7 @@ import core from "web.core";
|
||||
import "@crm/js/tours/crm";
|
||||
var _t = core._t;
|
||||
|
||||
var DragOppToWonStepIndex = _.findIndex(registry.category("web_tour.tours").get("crm_tour").steps, function (step) {
|
||||
var DragOppToWonStepIndex = registry.category("web_tour.tours").get("crm_tour").steps.findIndex(step => {
|
||||
return (step.id === 'drag_opportunity_to_won_step');
|
||||
});
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
import { Component, xml } from "@odoo/owl";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
const actionRegistry = registry.category("actions");
|
||||
|
||||
class QRModalComponent extends Component {
|
||||
setup() {
|
||||
this.url = _.str.sprintf(
|
||||
this.url = sprintf(
|
||||
"/report/barcode/?barcode_type=QR&value=%s&width=256&height=256&humanreadable=1",
|
||||
this.props.action.params.url);
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ const PublicLivechat = Class.extend(Mixins.EventDispatcherMixin, {
|
||||
? [this.messaging.publicLivechatGlobal.publicLivechat.operator]
|
||||
: [];
|
||||
const sortedTypingMembers = _.sortBy(typingMembers, function (member) {
|
||||
return _.indexOf(typingPartnerIDs, member.id);
|
||||
return typingPartnerIDs.indexOf(member.id);
|
||||
});
|
||||
const displayableTypingMembers = sortedTypingMembers.slice(0, 3);
|
||||
|
||||
@@ -330,9 +330,7 @@ const PublicLivechat = Class.extend(Mixins.EventDispatcherMixin, {
|
||||
if (!_.contains(this._typingPartnerIDs, partnerID)) {
|
||||
return;
|
||||
}
|
||||
this._typingPartnerIDs = _.reject(this._typingPartnerIDs, function (id) {
|
||||
return id === partnerID;
|
||||
});
|
||||
this._typingPartnerIDs = this._typingPartnerIDs.filter((id) => id !== partnerID);
|
||||
this._warnUpdatedTypingPartners();
|
||||
},
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ const Feedback = Widget.extend({
|
||||
_onClickSend() {
|
||||
this.$(".o_livechat_rating_reason").hide();
|
||||
this._showThanksMessage();
|
||||
if (_.isNumber(this.rating)) {
|
||||
if (Number.isFinite(this.rating)) {
|
||||
this._sendFeedback(this.$("textarea").val());
|
||||
}
|
||||
},
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
import { registry } from "@web/core/registry";
|
||||
let account_tour = registry.category("web_tour.tours").get("account_tour");
|
||||
// Remove the step suggesting to change the name as it is done another way (document number)
|
||||
account_tour.steps = _.filter(account_tour.steps, step => step.trigger != "input[name=name]");
|
||||
account_tour.steps = account_tour.steps.filter(step => step.trigger != "input[name=name]");
|
||||
|
||||
// Configure the AFIP Responsibility
|
||||
let partner_step_idx = _.findIndex(account_tour.steps, step => step.trigger == 'div[name=partner_id] input');
|
||||
let partner_step_idx = account_tour.steps.findIndex(step => step.trigger == 'div[name=partner_id] input');
|
||||
account_tour.steps.splice(partner_step_idx + 2, 0, {
|
||||
// FIXME WOWL: this selector needs to work in both legacy and non-legacy views
|
||||
trigger: "div[name=l10n_ar_afip_responsibility_type_id] input",
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
import { PosGlobalState, Order, Orderline } from "@point_of_sale/js/models";
|
||||
import core from "web.core";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
patch(PosGlobalState.prototype, "l10n_fr_pos_cert.PosGlobalState", {
|
||||
@@ -13,10 +13,7 @@ patch(PosGlobalState.prototype, "l10n_fr_pos_cert.PosGlobalState", {
|
||||
if (!this.company.country) {
|
||||
this.env.services.popup.add(ErrorPopup, {
|
||||
title: _t("Missing Country"),
|
||||
body: _.str.sprintf(
|
||||
_t("The company %s doesn't have a country set."),
|
||||
this.company.name
|
||||
),
|
||||
body: sprintf(_t("The company %s doesn't have a country set."), this.company.name),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import ajax from "web.ajax";
|
||||
import core from "web.core";
|
||||
import "web.dom_ready";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
@@ -45,7 +46,7 @@ if ($('.o_unsubscribe_form').length) {
|
||||
|
||||
var unsubscribed_list = $("input[name='unsubscribed_list']").val();
|
||||
if (unsubscribed_list){
|
||||
$('#subscription_info').html(_.str.sprintf(
|
||||
$('#subscription_info').html(sprintf(
|
||||
_t("You have been <strong>successfully unsubscribed from %s</strong>."),
|
||||
_.escape(unsubscribed_list)
|
||||
));
|
||||
|
||||
@@ -268,7 +268,7 @@ export class MassMailingHtmlField extends HtmlField {
|
||||
this._themeClassNames = "";
|
||||
const displayableThemes =
|
||||
device.isMobile ?
|
||||
_.filter($themes, theme => !$(theme).data("hideFromMobile")) :
|
||||
$themes.filter(theme => !$(theme).data("hideFromMobile")) :
|
||||
$themes;
|
||||
this._themeParams = _.map(displayableThemes, (theme) => {
|
||||
const $theme = $(theme);
|
||||
|
||||
@@ -27,7 +27,7 @@ LinkDialog.include({
|
||||
this.__realMMColors = {};
|
||||
const $previewArea = $('<div/>').addClass('o_mail_snippet_general');
|
||||
$(this.editable).find('.o_layout').append($previewArea);
|
||||
_.each(['link', 'primary', 'secondary'], type => {
|
||||
['link', 'primary', 'secondary'].forEach(type => {
|
||||
const $el = $('<a href="#" class="btn btn-' + type + '"/>');
|
||||
$el.appendTo($previewArea);
|
||||
this.__realMMColors[type] = {
|
||||
@@ -62,7 +62,7 @@ LinkDialog.include({
|
||||
$preview.css('border-color', '');
|
||||
$preview.css('background-color', '');
|
||||
$preview.css('color', '');
|
||||
_.each(['link', 'primary', 'secondary'], type => {
|
||||
['link', 'primary', 'secondary'].forEach(type => {
|
||||
if ($preview.hasClass('btn-' + type) || type === 'link' && !$preview.hasClass('btn')) {
|
||||
$preview.css(this.__realMMColors[type]);
|
||||
}
|
||||
|
||||
@@ -62,10 +62,7 @@ export class Navbar extends Component {
|
||||
this.env.pos.setLoadingOrderState(true);
|
||||
const message = await this.env.pos._syncAllOrdersFromServer();
|
||||
if (message) {
|
||||
this.notification.add(
|
||||
_.str.sprintf(message),
|
||||
5000
|
||||
);
|
||||
this.notification.add(message, 5000);
|
||||
}
|
||||
} finally {
|
||||
this.env.pos.setLoadingOrderState(false);
|
||||
|
||||
@@ -12,6 +12,7 @@ import { ConnectionLostError } from "@web/core/network/rpc_service";
|
||||
import { identifyError } from "@point_of_sale/app/error_handlers/error_handlers";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { usePos } from "@point_of_sale/app/pos_hook";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
export class ClosePosPopup extends AbstractAwaitablePopup {
|
||||
static components = { SaleDetailsButton };
|
||||
@@ -51,7 +52,7 @@ export class ClosePosPopup extends AbstractAwaitablePopup {
|
||||
} else {
|
||||
await this.popup.add(ConfirmPopup, {
|
||||
title: this.env._t("Payments Difference"),
|
||||
body: _.str.sprintf(
|
||||
body: sprintf(
|
||||
this.env._t(
|
||||
"The maximum difference allowed is %s.\n\
|
||||
Please contact your manager to accept the closing difference."
|
||||
|
||||
@@ -8,6 +8,7 @@ import { PartnerLine } from "./PartnerLine";
|
||||
import { PartnerDetailsEdit } from "./PartnerDetailsEdit";
|
||||
import { usePos } from "@point_of_sale/app/pos_hook";
|
||||
import { Component, onWillUnmount, useRef } from "@odoo/owl";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
/**
|
||||
* Render this screen using `showTempScreen` to select partner.
|
||||
@@ -115,7 +116,7 @@ export class PartnerListScreen extends Component {
|
||||
const result = await this.searchPartner();
|
||||
if (result.length > 0) {
|
||||
this.notification.add(
|
||||
_.str.sprintf(
|
||||
sprintf(
|
||||
this.env._t('%s customer(s) found for "%s".'),
|
||||
result.length,
|
||||
this.state.query
|
||||
@@ -124,14 +125,10 @@ export class PartnerListScreen extends Component {
|
||||
);
|
||||
} else {
|
||||
this.notification.add(
|
||||
_.str.sprintf(
|
||||
this.env._t('No more customer found for "%s".'),
|
||||
this.state.query
|
||||
),
|
||||
sprintf(this.env._t('No more customer found for "%s".'), this.state.query),
|
||||
3000
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
_clearSearch() {
|
||||
this.searchWordInputRef.el.value = "";
|
||||
@@ -188,7 +185,7 @@ export class PartnerListScreen extends Component {
|
||||
async getNewPartners() {
|
||||
let domain = [];
|
||||
const limit = 30;
|
||||
if(this.state.query) {
|
||||
if (this.state.query) {
|
||||
domain = [
|
||||
"|",
|
||||
["name", "ilike", this.state.query + "%"],
|
||||
@@ -199,7 +196,8 @@ export class PartnerListScreen extends Component {
|
||||
const result = await this.orm.silent.call(
|
||||
"pos.session",
|
||||
"get_pos_ui_res_partner_by_params",
|
||||
[[odoo.pos_session_id], { domain, limit: limit, offset: this.state.currentOffset }]);
|
||||
[[odoo.pos_session_id], { domain, limit: limit, offset: this.state.currentOffset }]
|
||||
);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import { PaymentScreenPaymentLines } from "./PaymentScreenPaymentLines";
|
||||
import { PaymentScreenStatus } from "./PaymentScreenStatus";
|
||||
import { usePos } from "@point_of_sale/app/pos_hook";
|
||||
import { Component } from "@odoo/owl";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
export class PaymentScreen extends Component {
|
||||
static template = "PaymentScreen";
|
||||
@@ -334,7 +335,7 @@ export class PaymentScreen extends Component {
|
||||
const paymentMethod = splitPayments[0].payment_method;
|
||||
const { confirmed } = await this.popup.add(ConfirmPopup, {
|
||||
title: this.env._t("Customer Required"),
|
||||
body: _.str.sprintf(
|
||||
body: sprintf(
|
||||
this.env._t("Customer is required for %s payment method."),
|
||||
paymentMethod.name
|
||||
),
|
||||
|
||||
+4
-15
@@ -6,7 +6,7 @@ import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
export class SaveButton extends Component {
|
||||
static template = "point_of_sale.SaveButton";
|
||||
|
||||
|
||||
setup() {
|
||||
super.setup();
|
||||
this.notification = useService("pos_notification");
|
||||
@@ -14,25 +14,15 @@ export class SaveButton extends Component {
|
||||
onClick() {
|
||||
const orderline = this.env.pos.get_order().get_selected_orderline();
|
||||
if (!orderline) {
|
||||
this.notification.add(
|
||||
_.str.sprintf(
|
||||
this.env._t('You cannot save an empty order')
|
||||
),
|
||||
3000
|
||||
);
|
||||
this.notification.add(this.env._t("You cannot save an empty order"), 3000);
|
||||
return;
|
||||
}
|
||||
this._selectEmptyOrder();
|
||||
this.notification.add(
|
||||
_.str.sprintf(
|
||||
this.env._t('Order saved for later')
|
||||
),
|
||||
3000
|
||||
);
|
||||
this.notification.add(this.env._t("Order saved for later"), 3000);
|
||||
}
|
||||
_selectEmptyOrder() {
|
||||
const orders = this.env.pos.get_order_list();
|
||||
let emptyOrders = orders.filter((order) => order.is_empty());
|
||||
const emptyOrders = orders.filter((order) => order.is_empty());
|
||||
if (emptyOrders.length > 0) {
|
||||
this.env.pos.sendDraftToServer();
|
||||
this.env.pos.set_order(emptyOrders[0]);
|
||||
@@ -40,7 +30,6 @@ export class SaveButton extends Component {
|
||||
this.env.pos.add_new_order();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ProductScreen.addControlButton({
|
||||
|
||||
@@ -214,9 +214,9 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
|
||||
}
|
||||
if (newQuantity >= selectedLine.saved_quantity) {
|
||||
if (newQuantity == 0) {
|
||||
order.remove_orderline(selectedLine)
|
||||
order.remove_orderline(selectedLine);
|
||||
}
|
||||
selectedLine.set_quantity(newQuantity)
|
||||
selectedLine.set_quantity(newQuantity);
|
||||
return;
|
||||
}
|
||||
const newLine = selectedLine.clone();
|
||||
@@ -241,10 +241,7 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
|
||||
this.pos.showScreen("TicketScreen", {
|
||||
ui: { filter: "SYNCED", searchDetails },
|
||||
});
|
||||
this.notification.add(
|
||||
_.str.sprintf(this.env._t("The order has been already paid.")),
|
||||
3000
|
||||
);
|
||||
this.notification.add(this.env._t("The order has been already paid."), 3000);
|
||||
this.env.pos.removeOrder(this.env.pos.get_order(), false);
|
||||
this.env.pos.add_new_order();
|
||||
return;
|
||||
|
||||
@@ -8,6 +8,7 @@ import { ConnectionLostError, ConnectionAbortedError } from "@web/core/network/r
|
||||
import { ProductItem } from "./ProductItem";
|
||||
import { ProductsWidgetControlPanel } from "./ProductsWidgetControlPanel";
|
||||
import { Component, useState } from "@odoo/owl";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
export class ProductsWidget extends Component {
|
||||
static components = { ProductItem, ProductsWidgetControlPanel };
|
||||
@@ -88,7 +89,7 @@ export class ProductsWidget extends Component {
|
||||
const result = await this.loadProductFromDB();
|
||||
if (result.length > 0) {
|
||||
this.notification.add(
|
||||
_.str.sprintf(
|
||||
sprintf(
|
||||
this.env._t('%s product(s) found for "%s".'),
|
||||
result.length,
|
||||
this.env.pos.searchProductWord
|
||||
@@ -97,7 +98,7 @@ export class ProductsWidget extends Component {
|
||||
);
|
||||
} else {
|
||||
this.notification.add(
|
||||
_.str.sprintf(
|
||||
sprintf(
|
||||
this.env._t('No more product found for "%s".'),
|
||||
this.env.pos.searchProductWord
|
||||
),
|
||||
@@ -112,34 +113,47 @@ export class ProductsWidget extends Component {
|
||||
}
|
||||
}
|
||||
async loadProductFromDB() {
|
||||
if(!this.env.pos.searchProductWord)
|
||||
if (!this.env.pos.searchProductWord) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const limit = 30;
|
||||
let ProductIds = await this.orm.call(
|
||||
const ProductIds = await this.orm.call(
|
||||
"product.product",
|
||||
"search",
|
||||
[['&',['available_in_pos', '=', true], '|','|',
|
||||
['name', 'ilike', this.env.pos.searchProductWord],
|
||||
['default_code', 'ilike', this.env.pos.searchProductWord],
|
||||
['barcode', 'ilike', this.env.pos.searchProductWord]]],
|
||||
[
|
||||
[
|
||||
"&",
|
||||
["available_in_pos", "=", true],
|
||||
"|",
|
||||
"|",
|
||||
["name", "ilike", this.env.pos.searchProductWord],
|
||||
["default_code", "ilike", this.env.pos.searchProductWord],
|
||||
["barcode", "ilike", this.env.pos.searchProductWord],
|
||||
],
|
||||
],
|
||||
{
|
||||
offset: this.state.currentOffset,
|
||||
limit: limit,
|
||||
}
|
||||
);
|
||||
if(ProductIds.length) {
|
||||
if (ProductIds.length) {
|
||||
await this.env.pos._addProducts(ProductIds, false);
|
||||
}
|
||||
this.updateProductList();
|
||||
return ProductIds;
|
||||
} catch (error) {
|
||||
const identifiedError = identifyError(error)
|
||||
if (identifiedError instanceof ConnectionLostError || identifiedError instanceof ConnectionAbortedError) {
|
||||
const identifiedError = identifyError(error);
|
||||
if (
|
||||
identifiedError instanceof ConnectionLostError ||
|
||||
identifiedError instanceof ConnectionAbortedError
|
||||
) {
|
||||
return this.popup.add("OfflineErrorPopup", {
|
||||
title: this.env._t("Network Error"),
|
||||
body: this.env._t("Product is not loaded. Tried loading the product from the server but there is a network error."),
|
||||
body: this.env._t(
|
||||
"Product is not loaded. Tried loading the product from the server but there is a network error."
|
||||
),
|
||||
});
|
||||
} else {
|
||||
throw error;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { Component } from "@odoo/owl";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import { format } from "web.field_utils";
|
||||
import { round_precision as round_pr } from "web.utils";
|
||||
|
||||
@@ -67,9 +68,9 @@ export class OrderlineDetails extends Component {
|
||||
return this.env.pos.formatProductQty(toRefundDetail && toRefundDetail.qty);
|
||||
}
|
||||
getRefundingMessage() {
|
||||
return _.str.sprintf(this.env._t("Refunding %s in "), this.getFormattedToRefundQty());
|
||||
return sprintf(this.env._t("Refunding %s in "), this.getFormattedToRefundQty());
|
||||
}
|
||||
getToRefundMessage() {
|
||||
return _.str.sprintf(this.env._t("To Refund: %s"), this.getFormattedToRefundQty());
|
||||
return sprintf(this.env._t("To Refund: %s"), this.getFormattedToRefundQty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { ReprintReceiptButton } from "./ControlButtons/ReprintReceiptButton";
|
||||
import { SearchBar } from "../../Misc/SearchBar";
|
||||
import { usePos } from "@point_of_sale/app/pos_hook";
|
||||
import { onMounted, useState } from "@odoo/owl";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
export class TicketScreen extends IndependentToOrderScreen {
|
||||
static template = "TicketScreen";
|
||||
@@ -126,7 +127,7 @@ export class TicketScreen extends IndependentToOrderScreen {
|
||||
) {
|
||||
const { confirmed } = await this.popup.add(ConfirmPopup, {
|
||||
title: this.env._t("Existing orderlines"),
|
||||
body: _.str.sprintf(
|
||||
body: sprintf(
|
||||
this.env._t(
|
||||
"%s has a total amount of %s, are you sure you want to delete this order?"
|
||||
),
|
||||
@@ -207,7 +208,7 @@ export class TicketScreen extends IndependentToOrderScreen {
|
||||
this.numberBuffer.reset();
|
||||
this.popup.add(ErrorPopup, {
|
||||
title: this.env._t("Maximum Exceeded"),
|
||||
body: _.str.sprintf(
|
||||
body: sprintf(
|
||||
this.env._t(
|
||||
"The requested quantity to be refunded is higher than the ordered quantity. %s is requested while only %s can be refunded."
|
||||
),
|
||||
@@ -656,19 +657,28 @@ export class TicketScreen extends IndependentToOrderScreen {
|
||||
const limit = this._state.syncedOrders.nPerPage;
|
||||
const offset =
|
||||
(this._state.syncedOrders.currentPage - 1) * this._state.syncedOrders.nPerPage;
|
||||
const { ordersInfo, totalCount } = await this.orm.call("pos.order", "search_paid_order_ids", [], {
|
||||
config_id: this.env.pos.config.id,
|
||||
domain,
|
||||
limit,
|
||||
offset,
|
||||
});
|
||||
const idsNotInCache = ordersInfo.filter((orderInfo) => !(orderInfo[0] in this._state.syncedOrders.cache));
|
||||
const idsNotUpToDate = ordersInfo.filter((orderInfo) => format.datetime(moment(orderInfo[1]), {}, {}) > format.datetime(moment(this._state.syncedOrders.cacheDate), {}, { timezone: false }));
|
||||
const { ordersInfo, totalCount } = await this.orm.call(
|
||||
"pos.order",
|
||||
"search_paid_order_ids",
|
||||
[],
|
||||
{
|
||||
config_id: this.env.pos.config.id,
|
||||
domain,
|
||||
limit,
|
||||
offset,
|
||||
}
|
||||
);
|
||||
const idsNotInCache = ordersInfo.filter(
|
||||
(orderInfo) => !(orderInfo[0] in this._state.syncedOrders.cache)
|
||||
);
|
||||
const idsNotUpToDate = ordersInfo.filter(
|
||||
(orderInfo) =>
|
||||
format.datetime(moment(orderInfo[1]), {}, {}) >
|
||||
format.datetime(moment(this._state.syncedOrders.cacheDate), {}, { timezone: false })
|
||||
);
|
||||
const idsToLoad = idsNotInCache.concat(idsNotUpToDate).map((info) => info[0]);
|
||||
if (idsToLoad.length > 0) {
|
||||
const fetchedOrders = await this.orm.call("pos.order", "export_for_ui", [
|
||||
idsToLoad,
|
||||
]);
|
||||
const fetchedOrders = await this.orm.call("pos.order", "export_for_ui", [idsToLoad]);
|
||||
// Check for missing products and partners and load them in the PoS
|
||||
await this.env.pos._loadMissingProducts(fetchedOrders);
|
||||
await this.env.pos._loadMissingPartners(fetchedOrders);
|
||||
|
||||
@@ -493,9 +493,7 @@ export const PosDB = core.Class.extend({
|
||||
},
|
||||
remove_order: function (order_id) {
|
||||
var orders = this.load("orders", []);
|
||||
orders = _.filter(orders, function (order) {
|
||||
return order.id !== order_id;
|
||||
});
|
||||
orders = orders.filter((order) => order.id !== order_id);
|
||||
this.save("orders", orders);
|
||||
},
|
||||
remove_all_orders: function () {
|
||||
@@ -534,9 +532,7 @@ export const PosDB = core.Class.extend({
|
||||
},
|
||||
remove_unpaid_order: function (order) {
|
||||
var orders = this.load("unpaid_orders", []);
|
||||
orders = _.filter(orders, function (o) {
|
||||
return o.id !== order.uid;
|
||||
});
|
||||
orders = orders.filter((o) => o.id !== order.uid);
|
||||
this.save("unpaid_orders", orders);
|
||||
},
|
||||
remove_all_unpaid_orders: function () {
|
||||
@@ -591,9 +587,7 @@ export const PosDB = core.Class.extend({
|
||||
set_ids_removed_from_server: function (ids) {
|
||||
var to_remove = this.load("unpaid_orders_to_remove", []);
|
||||
|
||||
to_remove = _.filter(to_remove, function (id) {
|
||||
return !ids.includes(id);
|
||||
});
|
||||
to_remove = to_remove.filter((id) => !ids.includes(id));
|
||||
this.save("unpaid_orders_to_remove", to_remove);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -12,12 +12,32 @@ import { ProductConfiguratorPopup } from "@point_of_sale/js/Popups/ProductConfig
|
||||
import { EditListPopup } from "@point_of_sale/js/Popups/EditListPopup";
|
||||
import { markRaw, reactive } from "@odoo/owl";
|
||||
import { ConfirmPopup } from "@point_of_sale/js/Popups/ConfirmPopup";
|
||||
import { escape } from "@web/core/utils/strings";
|
||||
import { escape, sprintf } from "@web/core/utils/strings";
|
||||
import { Mutex } from "@web/core/utils/concurrency";
|
||||
import { memoize } from "@web/core/utils/functions";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { renderToString } from "@web/core/utils/render";
|
||||
|
||||
/* Returns an array containing all elements of the given
|
||||
* array corresponding to the rule function {agg} and without duplicates
|
||||
*
|
||||
* @template T
|
||||
* @template F
|
||||
* @param {T[]} array
|
||||
* @param {F} function
|
||||
* @returns {T[]}
|
||||
*/
|
||||
export function uniqueBy(array, agg) {
|
||||
const map = new Map();
|
||||
for (const item of array) {
|
||||
const key = agg(item);
|
||||
if (!map.has(key)) {
|
||||
map.set(key, item);
|
||||
}
|
||||
}
|
||||
return [...map.values()];
|
||||
}
|
||||
|
||||
var round_di = utils.round_decimals;
|
||||
var round_pr = utils.round_precision;
|
||||
const Markup = utils.Markup;
|
||||
@@ -720,7 +740,7 @@ export class PosGlobalState extends PosModel {
|
||||
const pricelistsNames = pricelistsJson.map((pricelist) => {
|
||||
return pricelist.display_name;
|
||||
});
|
||||
message = _.str.sprintf(
|
||||
message = sprintf(
|
||||
_t("%s fiscal position(s) added to the configuration."),
|
||||
pricelistsNames.join(", ")
|
||||
);
|
||||
@@ -759,7 +779,7 @@ export class PosGlobalState extends PosModel {
|
||||
const fiscalPositionNames = fiscalPositionJson.map((fp) => {
|
||||
return fp.display_name;
|
||||
});
|
||||
message = _.str.sprintf(
|
||||
message = sprintf(
|
||||
_t("%s fiscal position(s) added to the configuration."),
|
||||
fiscalPositionNames.join(", ")
|
||||
);
|
||||
@@ -1115,7 +1135,7 @@ export class PosGlobalState extends PosModel {
|
||||
this.orders.add(orders);
|
||||
}
|
||||
|
||||
report.unpaid_skipped_sessions = _.keys(skipped_sessions);
|
||||
report.unpaid_skipped_sessions = Object.keys(skipped_sessions);
|
||||
}
|
||||
|
||||
return report;
|
||||
@@ -1394,7 +1414,7 @@ export class PosGlobalState extends PosModel {
|
||||
}
|
||||
}
|
||||
}
|
||||
return _.uniq(mappedTaxes, (tax) => tax.id);
|
||||
return uniqueBy(mappedTaxes, (tax) => tax.id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1978,7 +1998,7 @@ export class Orderline extends PosModel {
|
||||
} else {
|
||||
this.pos.env.services.popup.add(ErrorPopup, {
|
||||
title: _t("Greater than allowed"),
|
||||
body: _.str.sprintf(
|
||||
body: sprintf(
|
||||
_t(
|
||||
"The requested quantity to be refunded is higher than the refundable quantity of %s."
|
||||
),
|
||||
@@ -2377,7 +2397,7 @@ export class Orderline extends PosModel {
|
||||
|
||||
var product = this.get_product();
|
||||
var taxes_ids = this.tax_ids || product.taxes_id;
|
||||
taxes_ids = _.filter(taxes_ids, (t) => t in this.pos.taxes_by_id);
|
||||
taxes_ids = taxes_ids.filter((t) => t in this.pos.taxes_by_id);
|
||||
var taxdetail = {};
|
||||
var product_taxes = this.pos.get_taxes_after_fp(taxes_ids, this.order.fiscal_position);
|
||||
|
||||
@@ -2700,7 +2720,7 @@ export class Order extends PosModel {
|
||||
this.access_token = uuidv4(); // unique uuid used to identify the authenticity of the request from the QR code.
|
||||
this.ticketCode = this._generateTicketCode(); // 5-digits alphanum code shown on the receipt
|
||||
this.uid = this.generate_unique_id();
|
||||
this.name = _.str.sprintf(_t("Order %s"), this.uid);
|
||||
this.name = sprintf(_t("Order %s"), this.uid);
|
||||
this.validation_date = undefined;
|
||||
this.fiscal_position = this.pos.fiscal_positions.find(function (fp) {
|
||||
return fp.id === self.pos.config.default_fiscal_position_id[0];
|
||||
@@ -2737,7 +2757,7 @@ export class Order extends PosModel {
|
||||
}
|
||||
this.session_id = this.pos.pos_session.id;
|
||||
this.uid = json.uid;
|
||||
this.name = _.str.sprintf(_t("Order %s"), this.uid);
|
||||
this.name = sprintf(_t("Order %s"), this.uid);
|
||||
this.validation_date = json.creation_date;
|
||||
this.server_id = json.server_id ? json.server_id : false;
|
||||
this.user_id = json.user_id;
|
||||
@@ -3139,9 +3159,7 @@ export class Order extends PosModel {
|
||||
var self = this;
|
||||
this.pricelist = pricelist;
|
||||
|
||||
var lines_to_recompute = _.filter(this.get_orderlines(), function (line) {
|
||||
return !line.price_manually_set;
|
||||
});
|
||||
var lines_to_recompute = this.get_orderlines().filter((line) => !line.price_manually_set);
|
||||
_.each(lines_to_recompute, function (line) {
|
||||
line.set_unit_price(
|
||||
line.product.get_price(self.pricelist, line.get_quantity(), line.get_price_extra())
|
||||
|
||||
@@ -13,7 +13,7 @@ function assert(condition, message) {
|
||||
|
||||
function assertProductPrice(product, pricelist_name, quantity, expected_price) {
|
||||
return function () {
|
||||
var pricelist = _.findWhere(posmodel.pricelists, { name: pricelist_name });
|
||||
var pricelist = posmodel.pricelists.find((pricelist) => pricelist.name === pricelist_name);
|
||||
var frontend_price = product.get_price(pricelist, quantity);
|
||||
frontend_price = round_di(frontend_price, posmodel.dp["Product Price"]);
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ import publicWidget from "web.public.widget";
|
||||
import time from "web.time";
|
||||
import portalComposer from "portal.composer";
|
||||
import {Markup} from "web.utils";
|
||||
import { range } from "@web/core/utils/numbers";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
var qweb = core.qweb;
|
||||
var _t = core._t;
|
||||
@@ -101,8 +103,8 @@ var PortalChatter = publicWidget.Widget.extend({
|
||||
*/
|
||||
preprocessMessages(messages) {
|
||||
_.each(messages, function (m) {
|
||||
m['author_avatar_url'] = _.str.sprintf('/web/image/%s/%s/author_avatar/50x50', 'mail.message', m.id);
|
||||
m['published_date_str'] = _.str.sprintf(_t('Published on %s'), moment(time.str_to_datetime(m.date)).format('MMMM Do YYYY, h:mm:ss a'));
|
||||
m['author_avatar_url'] = sprintf('/web/image/%s/%s/author_avatar/50x50', 'mail.message', m.id);
|
||||
m['published_date_str'] = sprintf(_t('Published on %s'), moment(time.str_to_datetime(m.date)).format('MMMM Do YYYY, h:mm:ss a'));
|
||||
m['body'] = Markup(m.body);
|
||||
});
|
||||
return messages;
|
||||
@@ -245,9 +247,7 @@ var PortalChatter = publicWidget.Widget.extend({
|
||||
}
|
||||
|
||||
var pages = [];
|
||||
_.each(_.range(pmin, pmax + 1), function (index) {
|
||||
pages.push(index);
|
||||
});
|
||||
range(pmin, pmax + 1).forEach(index => pages.push(index));
|
||||
|
||||
return {
|
||||
"page_count": pageCount,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module alias=portal.composer **/
|
||||
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import ajax from "web.ajax";
|
||||
import core from "web.core";
|
||||
import publicWidget from "web.public.widget";
|
||||
@@ -91,7 +92,7 @@ var PortalComposer = publicWidget.Widget.extend({
|
||||
'access_token': accessToken,
|
||||
},
|
||||
}).then(function () {
|
||||
self.attachments = _.reject(self.attachments, {'id': attachmentId});
|
||||
self.attachments = self.attachments.filter(attachment => attachment.id !== attachmentId);
|
||||
self._updateAttachments();
|
||||
self.$sendButton.prop('disabled', false);
|
||||
});
|
||||
@@ -124,7 +125,7 @@ var PortalComposer = publicWidget.Widget.extend({
|
||||
resolve();
|
||||
}).guardedCatch(function (error) {
|
||||
self.displayNotification({
|
||||
message: _.str.sprintf(_t("Could not save file <strong>%s</strong>"),
|
||||
message: sprintf(_t("Could not save file <strong>%s</strong>"),
|
||||
_.escape(file.name)),
|
||||
type: 'warning',
|
||||
sticky: true,
|
||||
|
||||
@@ -4,6 +4,7 @@ import core from "web.core";
|
||||
import publicWidget from "web.public.widget";
|
||||
import time from "web.time";
|
||||
import session from "web.session";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
@@ -40,9 +41,9 @@ var PortalSidebar = publicWidget.Widget.extend({
|
||||
} else if (diff > 0) {
|
||||
// Workaround: force uniqueness of these two translations. We use %1d because the string
|
||||
// with %d is already used in mail and mail's translations are not sent to the frontend.
|
||||
displayStr = _.str.sprintf(_t('Due in %1d days'), Math.abs(diff));
|
||||
displayStr = sprintf(_t('Due in %s days'), Math.abs(diff).toFixed(1));
|
||||
} else {
|
||||
displayStr = _.str.sprintf(_t('%1d days overdue'), Math.abs(diff));
|
||||
displayStr = sprintf(_t('%s days overdue'), Math.abs(diff).toFixed(1));
|
||||
}
|
||||
$(el).text(displayStr);
|
||||
});
|
||||
|
||||
@@ -136,7 +136,7 @@ PortalChatter.include({
|
||||
'avg': Math.round(result['rating_stats']['avg'] * 100) / 100,
|
||||
'percent': [],
|
||||
};
|
||||
_.each(_.sortBy(_.keys(result['rating_stats']['percent'])).reverse(), function (rating) {
|
||||
_.each(_.sortBy(Object.keys(result['rating_stats']['percent'])).reverse(), function (rating) {
|
||||
ratingData['percent'].push({
|
||||
'num': self.roundToHalf(rating),
|
||||
'percent': utils.round_precision(result['rating_stats']['percent'][rating], 0.01),
|
||||
@@ -172,7 +172,7 @@ PortalChatter.include({
|
||||
return {
|
||||
mes_index: messageIndex,
|
||||
publisher_id: this.options.partner_id,
|
||||
publisher_avatar: _.str.sprintf('/web/image/res.partner/%s/avatar_128/50x50', this.options.partner_id),
|
||||
publisher_avatar: `/web/image/res.partner/${this.options.partner_id}/avatar_128/50x50`,
|
||||
publisher_name: _t("Write your comment"),
|
||||
publisher_datetime: '',
|
||||
publisher_comment: '',
|
||||
@@ -197,7 +197,7 @@ PortalChatter.include({
|
||||
if (rawRating.publisher_id && rawRating.publisher_id.length >= 2) {
|
||||
ratingData.publisher_id = rawRating.publisher_id[0];
|
||||
ratingData.publisher_name = rawRating.publisher_id[1];
|
||||
ratingData.publisher_avatar = _.str.sprintf('/web/image/res.partner/%s/avatar_128/50x50', ratingData.publisher_id);
|
||||
ratingData.publisher_avatar = `/web/image/res.partner/${ratingData.publisher_id}/avatar_128/50x50`;
|
||||
}
|
||||
var commentData = Object.assign(this._newPublisherCommentData(messageIndex), ratingData);
|
||||
return commentData;
|
||||
|
||||
@@ -4,6 +4,7 @@ import core from "web.core";
|
||||
import rpc from "web.rpc";
|
||||
import { PaymentInterface } from "@point_of_sale/js/payment";
|
||||
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
@@ -78,7 +79,7 @@ export const PaymentAdyen = PaymentInterface.extend({
|
||||
|
||||
_adyen_get_sale_id: function () {
|
||||
var config = this.pos.config;
|
||||
return _.str.sprintf("%s (ID: %s)", config.display_name, config.id);
|
||||
return sprintf("%s (ID: %s)", config.display_name, config.id);
|
||||
},
|
||||
|
||||
_adyen_common_message_header: function () {
|
||||
@@ -192,9 +193,9 @@ export const PaymentAdyen = PaymentInterface.extend({
|
||||
return output_text.reduce(function (acc, entry) {
|
||||
var params = new URLSearchParams(entry.Text);
|
||||
if (params.get("name") && !params.get("value")) {
|
||||
return acc + _.str.sprintf("\n%s", params.get("name"));
|
||||
return acc + sprintf("\n%s", params.get("name"));
|
||||
} else if (params.get("name") && params.get("value")) {
|
||||
return acc + _.str.sprintf("\n%s: %s", params.get("name"), params.get("value"));
|
||||
return acc + sprintf("\n%s: %s", params.get("name"), params.get("value"));
|
||||
}
|
||||
|
||||
return acc;
|
||||
@@ -287,7 +288,7 @@ export const PaymentAdyen = PaymentInterface.extend({
|
||||
resolve(true);
|
||||
} else {
|
||||
var message = additional_response.get("message");
|
||||
self._show_error(_.str.sprintf(_t("Message from Adyen: %s"), message));
|
||||
self._show_error(sprintf(_t("Message from Adyen: %s"), message));
|
||||
|
||||
// this means the transaction was cancelled by pressing the cancel button on the device
|
||||
if (message.startsWith("108 ")) {
|
||||
@@ -327,7 +328,7 @@ export const PaymentAdyen = PaymentInterface.extend({
|
||||
}
|
||||
|
||||
this._show_error(
|
||||
_.str.sprintf(_t("An unexpected error occurred. Message from Adyen: %s"), msg)
|
||||
sprintf(_t("An unexpected error occurred. Message from Adyen: %s"), msg)
|
||||
);
|
||||
if (line) {
|
||||
line.set_payment_status("force_done");
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useService } from "@web/core/utils/hooks";
|
||||
import { NumberPopup } from "@point_of_sale/js/Popups/NumberPopup";
|
||||
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
|
||||
import { Component } from "@odoo/owl";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
export class DiscountButton extends Component {
|
||||
static template = "DiscountButton";
|
||||
@@ -68,7 +69,7 @@ export class DiscountButton extends Component {
|
||||
description:
|
||||
`${pc}%, ` +
|
||||
(tax_ids_array.length
|
||||
? _.str.sprintf(
|
||||
? sprintf(
|
||||
this.env._t("Tax: %s"),
|
||||
tax_ids_array
|
||||
.map((taxId) => this.env.pos.taxes_by_id[taxId].amount + "%")
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import core from "web.core";
|
||||
import { PrinterMixin, PrintResult, PrintResultGenerator } from "@point_of_sale/js/printers";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
var QWeb = core.qweb;
|
||||
var _t = core._t;
|
||||
@@ -19,15 +20,15 @@ class EpsonPrintResultGenerator extends PrintResultGenerator {
|
||||
title: _t("Connection to the printer failed"),
|
||||
body: _t(
|
||||
"Please check if the printer is still connected. \n" +
|
||||
"Some browsers don't allow HTTP calls from websites to devices in the network (for security reasons). " +
|
||||
"If it is the case, you will need to follow Odoo's documentation for " +
|
||||
"'Self-signed certificate for ePOS printers' and 'Secure connection (HTTPS)' to solve the issue"
|
||||
"Some browsers don't allow HTTP calls from websites to devices in the network (for security reasons). " +
|
||||
"If it is the case, you will need to follow Odoo's documentation for " +
|
||||
"'Self-signed certificate for ePOS printers' and 'Secure connection (HTTPS)' to solve the issue"
|
||||
),
|
||||
},
|
||||
});
|
||||
|
||||
if (window.location.protocol === "https:") {
|
||||
printRes.message.body += _.str.sprintf(
|
||||
printRes.message.body += sprintf(
|
||||
_t(
|
||||
"If you are on a secure server (HTTPS) please make sure you manually accepted the certificate by accessing %s"
|
||||
),
|
||||
@@ -39,22 +40,32 @@ class EpsonPrintResultGenerator extends PrintResultGenerator {
|
||||
}
|
||||
|
||||
IoTResultError(printerErrorCode) {
|
||||
let message = _t("The printer was successfully reached, but it wasn't able to print.") + '\n';
|
||||
let message =
|
||||
_t("The printer was successfully reached, but it wasn't able to print.") + "\n";
|
||||
if (printerErrorCode) {
|
||||
message += '\n' + _t("The following error code was given by the printer:") + '\n' + printerErrorCode;
|
||||
message +=
|
||||
"\n" +
|
||||
_t("The following error code was given by the printer:") +
|
||||
"\n" +
|
||||
printerErrorCode;
|
||||
|
||||
const extra_messages = {
|
||||
"DeviceNotFound":
|
||||
_t("Check on the printer configuration for the 'Device ID' setting. " +
|
||||
"It should be set to: ") + "\nlocal_printer",
|
||||
"EPTR_REC_EMPTY":
|
||||
_t("No paper was detected by the printer"),
|
||||
DeviceNotFound:
|
||||
_t(
|
||||
"Check on the printer configuration for the 'Device ID' setting. " +
|
||||
"It should be set to: "
|
||||
) + "\nlocal_printer",
|
||||
EPTR_REC_EMPTY: _t("No paper was detected by the printer"),
|
||||
};
|
||||
if (printerErrorCode in extra_messages) {
|
||||
message += '\n' + extra_messages[printerErrorCode];
|
||||
message += "\n" + extra_messages[printerErrorCode];
|
||||
}
|
||||
message += '\n' + _t("To find more details on the error reason, please search online for:") + '\n' +
|
||||
" Epson Server Direct Print " + printerErrorCode;
|
||||
message +=
|
||||
"\n" +
|
||||
_t("To find more details on the error reason, please search online for:") +
|
||||
"\n" +
|
||||
" Epson Server Direct Print " +
|
||||
printerErrorCode;
|
||||
} else {
|
||||
message += _t("Please check if the printer has enough paper and is ready to print.");
|
||||
}
|
||||
@@ -184,6 +195,9 @@ export const EpsonPrinter = core.Class.extend(PrinterMixin, {
|
||||
data: img,
|
||||
});
|
||||
const response = $(res).find("response");
|
||||
return {"result": response.attr("success") === "true", "printerErrorCode": response.attr("code")};
|
||||
return {
|
||||
result: response.attr("success") === "true",
|
||||
printerErrorCode: response.attr("code"),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { PartnerLine } from "@point_of_sale/js/Screens/PartnerListScreen/PartnerLine";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
patch(PartnerLine.prototype, "pos_loyalty.PartnerLine", {
|
||||
_getLoyaltyPointsRepr(loyaltyCard) {
|
||||
@@ -13,6 +14,6 @@ patch(PartnerLine.prototype, "pos_loyalty.PartnerLine", {
|
||||
if (program.portal_visible) {
|
||||
return `${balanceRepr} ${program.portal_point_name}`;
|
||||
}
|
||||
return _.str.sprintf(this.env._t("%s Points"), balanceRepr);
|
||||
return sprintf(this.env._t("%s Points"), balanceRepr);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useBarcodeReader } from "@point_of_sale/app/barcode_reader_hook";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { ConfirmPopup } from "@point_of_sale/js/Popups/ConfirmPopup";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
patch(ProductScreen.prototype, "pos_loyalty.ProductScreen", {
|
||||
setup() {
|
||||
@@ -43,7 +44,7 @@ patch(ProductScreen.prototype, "pos_loyalty.ProductScreen", {
|
||||
const reward = this.env.pos.reward_by_id[selectedLine.reward_id];
|
||||
const { confirmed } = await this.popup.add(ConfirmPopup, {
|
||||
title: this.env._t("Deactivating reward"),
|
||||
body: _.str.sprintf(
|
||||
body: sprintf(
|
||||
this.env._t(
|
||||
"Are you sure you want to remove %s from this order?\n You will still be able to claim it through the reward button."
|
||||
),
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@ import { useService } from "@web/core/utils/hooks";
|
||||
import { NumberPopup } from "@point_of_sale/js/Popups/NumberPopup";
|
||||
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
|
||||
import { Component } from "@odoo/owl";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
export class TableGuestsButton extends Component {
|
||||
static template = "TableGuestsButton";
|
||||
@@ -34,7 +35,7 @@ export class TableGuestsButton extends Component {
|
||||
if (guestCount > max_capacity) {
|
||||
await this.popup.add(ErrorPopup, {
|
||||
title: this.env._t("Blocked action"),
|
||||
body: _.str.sprintf(
|
||||
body: sprintf(
|
||||
this.env._t("You cannot put a number that exceeds %s "),
|
||||
max_capacity
|
||||
),
|
||||
|
||||
@@ -98,7 +98,7 @@ export class SaleOrderManagementScreen extends ControlButtonsMixin(IndependentTo
|
||||
await this.env.pos._loadPartners([sale_order.partner_id[0]]);
|
||||
} catch {
|
||||
const title = this.env._t("Customer loading error");
|
||||
const body = _.str.sprintf(
|
||||
const body = sprintf(
|
||||
this.env._t("There was a problem in loading the %s customer."),
|
||||
sale_order.partner_id[1]
|
||||
);
|
||||
|
||||
@@ -5,6 +5,7 @@ import core from "web.core";
|
||||
import rpc from "web.rpc";
|
||||
import { PaymentInterface } from "@point_of_sale/js/payment";
|
||||
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
const _t = core._t;
|
||||
|
||||
@@ -48,7 +49,7 @@ export const PaymentStripe = PaymentInterface.extend({
|
||||
discoverReaders: async function () {
|
||||
const discoverResult = await this.terminal.discoverReaders({});
|
||||
if (discoverResult.error) {
|
||||
this._showError(_.str.sprintf(_t("Failed to discover: %s"), discoverResult.error));
|
||||
this._showError(sprintf(_t("Failed to discover: %s"), discoverResult.error));
|
||||
} else if (discoverResult.discoveredReaders.length === 0) {
|
||||
this._showError(_t("No available Stripe readers."));
|
||||
} else {
|
||||
@@ -100,7 +101,7 @@ export const PaymentStripe = PaymentInterface.extend({
|
||||
}
|
||||
}
|
||||
this._showError(
|
||||
_.str.sprintf(
|
||||
sprintf(
|
||||
this.env._t("Stripe readers %s not listed in your account"),
|
||||
this.payment_method.stripe_serial_number
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ import concurrency from "web.concurrency";
|
||||
import core from "web.core";
|
||||
import utils from "web.utils";
|
||||
import ajax from "web.ajax";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
var _t = core._t;
|
||||
|
||||
var VariantMixin = {
|
||||
@@ -500,7 +501,7 @@ var VariantMixin = {
|
||||
}
|
||||
excludedByData.push(excludedByName);
|
||||
|
||||
$target.attr('title', _.str.sprintf(_t('Not available with %s'), excludedByData.join(', ')));
|
||||
$target.attr('title', sprintf(_t('Not available with %s'), excludedByData.join(', ')));
|
||||
$target.data('excluded-by', JSON.stringify(excludedByData));
|
||||
}
|
||||
},
|
||||
@@ -600,7 +601,7 @@ var VariantMixin = {
|
||||
if ($('.decimal_precision').length) {
|
||||
precision = parseInt($('.decimal_precision').last().data('precision'));
|
||||
}
|
||||
var formatted = _.str.sprintf('%.' + precision + 'f', price).split('.');
|
||||
var formatted = price.toFixed(precision).split(".");
|
||||
formatted[0] = utils.insert_thousand_seps(formatted[0]);
|
||||
return formatted.join(l10n.decimal_point);
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { _t } from "web.core";
|
||||
import * as spreadsheet from "@odoo/o-spreadsheet";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
const { arg, toString, toNumber } = spreadsheet.helpers;
|
||||
const { functionRegistry } = spreadsheet.registries;
|
||||
@@ -12,7 +13,7 @@ const { functionRegistry } = spreadsheet.registries;
|
||||
|
||||
function assertListsExists(listId, getters) {
|
||||
if (!getters.isExistingList(listId)) {
|
||||
throw new Error(_.str.sprintf(_t('There is no list with id "%s"'), listId));
|
||||
throw new Error(sprintf(_t('There is no list with id "%s"'), listId));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -483,7 +483,7 @@ publicWidget.registry.SurveyFormWidget = publicWidget.Widget.extend(SurveyPreloa
|
||||
}
|
||||
|
||||
var submitPromise = self._rpc({
|
||||
route: _.str.sprintf('%s/%s/%s', route, self.options.surveyToken, self.options.answerToken),
|
||||
route: `${route}/${self.options.surveyToken}/${self.options.answerToken}`,
|
||||
params: params,
|
||||
});
|
||||
this._nextScreen(submitPromise, options);
|
||||
@@ -736,7 +736,7 @@ publicWidget.registry.SurveyFormWidget = publicWidget.Widget.extend(SurveyPreloa
|
||||
break;
|
||||
}
|
||||
});
|
||||
if (_.keys(errors).length > 0) {
|
||||
if (Object.keys(errors).length > 0) {
|
||||
this._showErrors(errors);
|
||||
return false;
|
||||
}
|
||||
@@ -1170,8 +1170,8 @@ publicWidget.registry.SurveyFormWidget = publicWidget.Widget.extend(SurveyPreloa
|
||||
|
||||
_showErrors: function (errors) {
|
||||
var self = this;
|
||||
var errorKeys = _.keys(errors);
|
||||
_.each(errorKeys, function (key) {
|
||||
var errorKeys = Object.keys(errors || {});
|
||||
errorKeys.forEach(key => {
|
||||
self.$("#" + key + '>.o_survey_question_error').append($('<p>', {text: errors[key]})).addClass("slide_in");
|
||||
if (errorKeys[0] === key) {
|
||||
self._scrollToError(self.$('.js_question-wrapper#' + key));
|
||||
|
||||
@@ -44,7 +44,7 @@ publicWidget.registry.SurveySessionLeaderboard = publicWidget.Widget.extend({
|
||||
}
|
||||
|
||||
var leaderboardPromise = this._rpc({
|
||||
route: _.str.sprintf('/survey/session/leaderboard/%s', this.surveyAccessToken)
|
||||
route: `/survey/session/leaderboard/${this.surveyAccessToken}`,
|
||||
});
|
||||
|
||||
Promise.all([fadeOutPromise, leaderboardPromise]).then(function (results) {
|
||||
|
||||
@@ -250,10 +250,7 @@ publicWidget.registry.SurveySessionManage = publicWidget.Widget.extend(SurveyPre
|
||||
args: [[this.surveyId]],
|
||||
}).then(function () {
|
||||
if ($(ev.currentTarget).data('showResults')) {
|
||||
document.location = _.str.sprintf(
|
||||
'/survey/results/%s',
|
||||
self.surveyId
|
||||
);
|
||||
document.location = `/survey/results/${encodeURIComponent(self.surveyId)}`;
|
||||
} else {
|
||||
window.history.back();
|
||||
}
|
||||
@@ -359,7 +356,7 @@ publicWidget.registry.SurveySessionManage = publicWidget.Widget.extend(SurveyPre
|
||||
}
|
||||
|
||||
var nextQuestionPromise = this._rpc({
|
||||
route: _.str.sprintf('/survey/session/next_question/%s', self.surveyAccessToken),
|
||||
route: `/survey/session/next_question/${self.surveyAccessToken}`,
|
||||
params: {
|
||||
'go_back': goBack,
|
||||
}
|
||||
@@ -472,7 +469,7 @@ publicWidget.registry.SurveySessionManage = publicWidget.Widget.extend(SurveyPre
|
||||
var self = this;
|
||||
|
||||
return this._rpc({
|
||||
route: _.str.sprintf('/survey/session/results/%s', self.surveyAccessToken)
|
||||
route: `/survey/session/results/${self.surveyAccessToken}`,
|
||||
}).then(function (questionResults) {
|
||||
if (questionResults) {
|
||||
self.attendeesCount = questionResults.attendees_count;
|
||||
|
||||
@@ -116,7 +116,7 @@ export class ProfilingQwebView extends Component {
|
||||
* @returns {string}
|
||||
*/
|
||||
_formatDelay(delay) {
|
||||
return delay ? _.str.sprintf("%.1f", Math.ceil(delay * 10) / 10) : ".";
|
||||
return delay ? (Math.ceil(delay * 10) / 10).toFixed(1) : ".";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,3 +32,20 @@ export function computeVariation(value, comparisonValue) {
|
||||
export function clamp(num, min, max) {
|
||||
return Math.max(Math.min(num, max), min);
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to create flexibly-numbered lists of integers, handy for each and map loops.
|
||||
* step defaults to 1.
|
||||
* Returns a list of integers from start (inclusive) to stop (exclusive), incremented (or decremented) by step.
|
||||
* @param {number} min default 0
|
||||
* @param {number} max
|
||||
* @param {number} step default 1
|
||||
* @returns {number[]}
|
||||
*/
|
||||
export function range(start, stop, step = 1) {
|
||||
const array = [];
|
||||
for (let i = start; i < stop; i += step) {
|
||||
array.push(i);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/** @odoo-module alias=web.KeyboardNavigationMixin **/
|
||||
import BrowserDetection from "web.BrowserDetection";
|
||||
import BrowserDetection from "web.BrowserDetection";
|
||||
import core from "web.core";
|
||||
|
||||
/**
|
||||
@@ -77,7 +77,7 @@
|
||||
}
|
||||
var accesskeyElements = $(document).find('[accesskey]').filter(':visible');
|
||||
_.each(accesskeyElements, function (elem) {
|
||||
var overlay = $(_.str.sprintf("<div class='o_web_accesskey_overlay font-sans-serif'>%s</div>", $(elem).attr('accesskey').toUpperCase()));
|
||||
var overlay = $(`<div class='o_web_accesskey_overlay font-sans-serif'>${$(elem).attr('accesskey').toUpperCase()}</div>`);
|
||||
|
||||
var $overlayParent;
|
||||
if (elem.tagName.toUpperCase() === "INPUT") {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
import SearchBar from "web.SearchBar";
|
||||
import { useModel } from "web.Model";
|
||||
import { LegacyComponent } from "@web/legacy/legacy_component";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
const {
|
||||
onMounted,
|
||||
@@ -132,7 +133,7 @@
|
||||
|
||||
this.fields = this._formatFields(toRaw(this.props.fields || {}));
|
||||
|
||||
this.sprintf = _.str.sprintf;
|
||||
this.sprintf = sprintf;
|
||||
|
||||
onWillDestroy(() => {
|
||||
const content = this.props.cp_content;
|
||||
|
||||
@@ -312,7 +312,7 @@ var Dialog = Widget.extend({
|
||||
_setButtonsTo($target, buttons) {
|
||||
var self = this;
|
||||
$target.empty();
|
||||
_.each(buttons, function (buttonData) {
|
||||
buttons.forEach(buttonData => {
|
||||
var $button = dom.renderButton({
|
||||
attrs: {
|
||||
class: buttonData.classes || (buttons.length > 1 ? 'btn-secondary' : 'btn-primary'),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module alias=web.Domain **/
|
||||
|
||||
import { intersection } from "@web/core/utils/arrays";
|
||||
import collections from "web.collections";
|
||||
import pyUtils from "web.py_utils";
|
||||
var py = window.py; // look py.js
|
||||
@@ -34,7 +35,7 @@ var Domain = collections.Tree.extend({
|
||||
*/
|
||||
init: function (domain, evalContext) {
|
||||
this._super.apply(this, arguments);
|
||||
if (_.isArray(domain) || _.isString(domain)) {
|
||||
if (Array.isArray(domain) || _.isString(domain)) {
|
||||
this._parse(this.normalizeArray(_.clone(this.stringToArray(domain, evalContext))));
|
||||
} else {
|
||||
this._data = !!domain;
|
||||
@@ -57,7 +58,7 @@ var Domain = collections.Tree.extend({
|
||||
if (this._data === true || this._data === false) {
|
||||
// The domain is a always-true or a always-false domain
|
||||
return this._data;
|
||||
} else if (_.isArray(this._data)) {
|
||||
} else if (Array.isArray(this._data)) {
|
||||
// The domain is a [name, operator, value] entity
|
||||
// First check if we have the field value in the field values set
|
||||
// and if the first part of the domain contains 'parent.field'
|
||||
@@ -78,10 +79,7 @@ var Domain = collections.Tree.extend({
|
||||
fieldName in values.parent;
|
||||
}
|
||||
if (!(this._data[0] in values) && !(isParentField)) {
|
||||
throw new Error(_.str.sprintf(
|
||||
"Unknown field %s in domain",
|
||||
this._data[0]
|
||||
));
|
||||
throw new Error(`Unknown field ${this._data[0]} in domain`);
|
||||
}
|
||||
fieldValue = isParentField ? values.parent[fieldName] : values[fieldName];
|
||||
}
|
||||
@@ -102,14 +100,14 @@ var Domain = collections.Tree.extend({
|
||||
case ">=":
|
||||
return (fieldValue >= this._data[2]);
|
||||
case "in":
|
||||
return _.intersection(
|
||||
_.isArray(this._data[2]) ? this._data[2] : [this._data[2]],
|
||||
_.isArray(fieldValue) ? fieldValue : [fieldValue],
|
||||
return intersection(
|
||||
Array.isArray(this._data[2]) ? this._data[2] : [this._data[2]],
|
||||
Array.isArray(fieldValue) ? fieldValue : [fieldValue],
|
||||
).length !== 0;
|
||||
case "not in":
|
||||
return _.intersection(
|
||||
_.isArray(this._data[2]) ? this._data[2] : [this._data[2]],
|
||||
_.isArray(fieldValue) ? fieldValue : [fieldValue],
|
||||
return intersection(
|
||||
Array.isArray(this._data[2]) ? this._data[2] : [this._data[2]],
|
||||
Array.isArray(fieldValue) ? fieldValue : [fieldValue],
|
||||
).length === 0;
|
||||
case "like":
|
||||
if (fieldValue === false) {
|
||||
@@ -132,10 +130,7 @@ var Domain = collections.Tree.extend({
|
||||
}
|
||||
return new RegExp(this._data[2].replace(/%/g, '.*'), 'i').test(fieldValue);
|
||||
default:
|
||||
throw new Error(_.str.sprintf(
|
||||
"Domain %s uses an unsupported operator",
|
||||
this._data
|
||||
));
|
||||
throw new Error(`Domain ${this._data} uses an unsupported operator`);
|
||||
}
|
||||
} else { // The domain is a set of [name, operator, value] entitie(s)
|
||||
switch (this._data) {
|
||||
@@ -289,7 +284,7 @@ var Domain = collections.Tree.extend({
|
||||
normalizeArray: function (domain) {
|
||||
if (domain.length === 0) { return domain; }
|
||||
var expected = 1;
|
||||
_.each(domain, function (item) {
|
||||
domain.forEach(item => {
|
||||
if (item === "&" || item === "|") {
|
||||
expected++;
|
||||
} else if (item !== "!") {
|
||||
@@ -299,10 +294,7 @@ var Domain = collections.Tree.extend({
|
||||
if (expected < 0) {
|
||||
domain.unshift.apply(domain, _.times(Math.abs(expected), _.constant("&")));
|
||||
} else if (expected > 0) {
|
||||
throw new Error(_.str.sprintf(
|
||||
"invalid domain %s (missing %d segment(s))",
|
||||
JSON.stringify(domain), expected
|
||||
));
|
||||
throw new Error(`invalid domain ${JSON.stringify(domain)} (missing ${expected.toFixed(0)} segment(s))`);
|
||||
}
|
||||
return domain;
|
||||
},
|
||||
|
||||
@@ -305,7 +305,7 @@ var EventDispatcherMixin = Object.assign({}, ParentedMixin, {
|
||||
_.each(events, function (eventName) {
|
||||
self.__edispatcherEvents.off(eventName, func, dest);
|
||||
if (dest && dest.__eventDispatcherMixin) {
|
||||
dest.__edispatcherRegisteredEvents = _.filter(dest.__edispatcherRegisteredEvents, function (el) {
|
||||
dest.__edispatcherRegisteredEvents = dest.__edispatcherRegisteredEvents.filter(el => {
|
||||
return !(el.name === eventName && el.func === func && el.source === self);
|
||||
});
|
||||
}
|
||||
@@ -386,7 +386,7 @@ var PropertiesMixin = Object.assign({}, EventDispatcherMixin, {
|
||||
// remove this, or move it elsewhere. Also, learn OO programming.
|
||||
if (key === 'value' && self.field && self.field.type === 'float' && tmp && val){
|
||||
var digits = self.field.digits;
|
||||
if (_.isArray(digits)) {
|
||||
if (Array.isArray(digits)) {
|
||||
if (utils.float_is_zero(tmp - val, digits[1])) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ var RamStorage = Class.extend(mixins.EventDispatcherMixin, {
|
||||
* @return {string}
|
||||
*/
|
||||
key: function (index) {
|
||||
return _.keys(this.storage)[index];
|
||||
return Object.keys(this.storage)[index];
|
||||
},
|
||||
/**
|
||||
* Removes the given key from the storage
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module alias=web.time **/
|
||||
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import translation from "web.translation";
|
||||
import utils from "web.utils";
|
||||
|
||||
@@ -189,7 +190,7 @@ function auto_str_to_date (value) {
|
||||
try {
|
||||
return str_to_time(value);
|
||||
} catch {}
|
||||
throw new Error(_.str.sprintf(_t("'%s' is not a correct date, datetime nor time"), value));
|
||||
throw new Error(sprintf(_t("'%s' is not a correct date, datetime nor time"), value));
|
||||
}
|
||||
|
||||
function auto_date_to_str (value, type) {
|
||||
@@ -201,7 +202,7 @@ function auto_date_to_str (value, type) {
|
||||
case 'time':
|
||||
return time_to_str(value);
|
||||
default:
|
||||
throw new Error(_.str.sprintf(_t("'%s' is not convertible to date, datetime nor time"), type));
|
||||
throw new Error(sprintf(_t("'%s' is not convertible to date, datetime nor time"), type));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ var TranslationDataBase = Class.extend(/** @lends instance.TranslationDataBase#
|
||||
set_bundle: function(translation_bundle) {
|
||||
var self = this;
|
||||
this.multi_lang = translation_bundle.multi_lang
|
||||
var modules = _.keys(translation_bundle.modules);
|
||||
var modules = Object.keys(translation_bundle.modules);
|
||||
modules.sort();
|
||||
if (_.include(modules, "web")) {
|
||||
modules = ["web"].concat(_.without(modules, "web"));
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import translation from "web.translation";
|
||||
|
||||
import { Component } from "@odoo/owl";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
var _t = translation._t;
|
||||
var id = -1;
|
||||
@@ -633,7 +634,7 @@ const utils = {
|
||||
return sindent + node.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
} else if (typeof(node.tag) !== 'string' || node.children && !(node.children instanceof Array) || node.attrs && !(node.attrs instanceof Object)) {
|
||||
throw new Error(
|
||||
_.str.sprintf(_t("Node [%s] is not a JSONified XML node"),
|
||||
sprintf(_t("Node [%s] is not a JSONified XML node"),
|
||||
JSON.stringify(node)));
|
||||
}
|
||||
for (var attr in node.attrs) {
|
||||
|
||||
@@ -15,6 +15,7 @@ import py_utils from "web.py_utils";
|
||||
import session from "web.session";
|
||||
import field_utils from "web.field_utils";
|
||||
import utils from "web.utils";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
var _t = core._t;
|
||||
var _lt = core._lt;
|
||||
@@ -1281,7 +1282,7 @@ var FieldFloatToggle = AbstractField.extend({
|
||||
_nextValue: function () {
|
||||
var range = this.nodeOptions.range;
|
||||
var val = utils.closestNumber(this._getDisplayedValue(), range);
|
||||
var index = _.indexOf(range, val);
|
||||
var index = range.indexOf(val);
|
||||
if (index !== -1) {
|
||||
if (index + 1 < range.length) {
|
||||
return range[index + 1];
|
||||
@@ -1539,7 +1540,7 @@ var AbstractFieldBinary = AbstractField.extend({
|
||||
var file = file_node.files[0];
|
||||
if (file.size > this.max_upload_size) {
|
||||
var msg = _t("The selected file exceed the maximum file size of %s.");
|
||||
this.displayNotification({ title: _t("File upload"), message: _.str.sprintf(msg, utils.human_size(this.max_upload_size)), type: 'danger' });
|
||||
this.displayNotification({ title: _t("File upload"), message: sprintf(msg, utils.human_size(this.max_upload_size)), type: 'danger' });
|
||||
return false;
|
||||
}
|
||||
utils.getDataURLFromFile(file).then(function (data) {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* conversions.
|
||||
*/
|
||||
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import core from "web.core";
|
||||
import dom from "web.dom";
|
||||
import session from "web.session";
|
||||
@@ -175,7 +176,7 @@ function formatFloat(value, field, options) {
|
||||
} else {
|
||||
precision = 2;
|
||||
}
|
||||
var formatted = _.str.sprintf('%.' + precision + 'f', value || 0).split('.');
|
||||
var formatted = (value || 0).toFixed(precision).split(".");
|
||||
formatted[0] = utils.insert_thousand_seps(formatted[0]);
|
||||
return formatted.join(l10n.decimal_point);
|
||||
}
|
||||
@@ -210,18 +211,18 @@ function formatFloatFactor(value, field, options) {
|
||||
*/
|
||||
function formatFloatTime(value, field, options) {
|
||||
options = options || {};
|
||||
var pattern = options.noLeadingZeroHour ? '%1d:%02d' : '%02d:%02d';
|
||||
if (value < 0) {
|
||||
value = Math.abs(value);
|
||||
pattern = '-' + pattern;
|
||||
}
|
||||
var hour = Math.floor(value);
|
||||
var min = Math.round((value % 1) * 60);
|
||||
if (min === 60){
|
||||
var hour = Math.floor(Math.abs(value));
|
||||
var min = Math.round((Math.abs(value) % 1) * 60);
|
||||
if (min === 60) {
|
||||
min = 0;
|
||||
hour = hour + 1;
|
||||
}
|
||||
return _.str.sprintf(pattern, hour, min);
|
||||
|
||||
const val = options.noLeadingZeroHour
|
||||
? String(hour) + ":" + String(min).padStart(2, "0")
|
||||
: String(hour).padStart(2, "0") + ":" + String(min).padStart(2, "0");
|
||||
|
||||
return value < 0 ? "-" + val : val;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -251,7 +252,7 @@ function formatInteger(value, field, options) {
|
||||
if (options.humanReadable && options.humanReadable(value)) {
|
||||
return utils.human_number(value, options.decimals, options.minDigits, options.formatterCallback);
|
||||
}
|
||||
return utils.insert_thousand_seps(_.str.sprintf('%d', value));
|
||||
return utils.insert_thousand_seps(String(value));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -271,7 +272,7 @@ function formatInteger(value, field, options) {
|
||||
function formatMany2one(value, field, options) {
|
||||
if (!value) {
|
||||
value = '';
|
||||
} else if (_.isArray(value)) {
|
||||
} else if (Array.isArray(value)) {
|
||||
// value is a pair [id, nameget]
|
||||
value = value[1];
|
||||
} else {
|
||||
@@ -509,7 +510,7 @@ function parseDate(value, field, options) {
|
||||
return date;
|
||||
}
|
||||
}
|
||||
throw new Error(_.str.sprintf(core._t("'%s' is not a correct date"), value));
|
||||
throw new Error(sprintf(core._t("'%s' is not a correct date"), value));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -562,7 +563,7 @@ function parseDateTime(value, field, options) {
|
||||
return datetime;
|
||||
}
|
||||
}
|
||||
throw new Error(_.str.sprintf(core._t("'%s' is not a correct datetime"), value));
|
||||
throw new Error(sprintf(core._t("'%s' is not a correct datetime"), value));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -596,7 +597,7 @@ function parseNumber(value) {
|
||||
function parseFloat(value) {
|
||||
var parsed = parseNumber(value);
|
||||
if (isNaN(parsed)) {
|
||||
throw new Error(_.str.sprintf(core._t("'%s' is not a correct float"), value));
|
||||
throw new Error(sprintf(core._t("'%s' is not a correct float"), value));
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
@@ -644,7 +645,7 @@ function parseMonetary(value, field, options) {
|
||||
return parseFloat(value);
|
||||
}
|
||||
if (!value.includes(currency.symbol)) {
|
||||
throw new Error(_.str.sprintf(core._t("'%s' is not a correct monetary field"), value));
|
||||
throw new Error(sprintf(core._t("'%s' is not a correct monetary field"), value));
|
||||
}
|
||||
if (currency.position === 'before') {
|
||||
return parseFloat(value
|
||||
@@ -709,7 +710,7 @@ function parseInteger(value) {
|
||||
var parsed = parseNumber(value);
|
||||
// do not accept not numbers or float values
|
||||
if (isNaN(parsed) || parsed % 1 || parsed < -2147483648 || parsed > 2147483647) {
|
||||
throw new Error(_.str.sprintf(core._t("'%s' is not a correct integer"), value));
|
||||
throw new Error(sprintf(core._t("'%s' is not a correct integer"), value));
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
@@ -728,13 +729,13 @@ function parseInteger(value) {
|
||||
* number, the value is returned untouched.
|
||||
*/
|
||||
function parseMany2one(value) {
|
||||
if (_.isArray(value)) {
|
||||
if (Array.isArray(value)) {
|
||||
return {
|
||||
id: value[0],
|
||||
display_name: value[1],
|
||||
};
|
||||
}
|
||||
if (_.isNumber(value) || _.isString(value)) {
|
||||
if (Number.isFinite(value) || _.isString(value)) {
|
||||
return {
|
||||
id: parseInt(value, 10),
|
||||
};
|
||||
|
||||
@@ -20,8 +20,7 @@ import dom from "web.dom";
|
||||
import { FormViewDialog } from "@web/views/view_dialogs/form_view_dialog";
|
||||
import { SelectCreateDialog } from "@web/views/view_dialogs/select_create_dialog";
|
||||
import Domain from "web.Domain";
|
||||
import { sprintf } from "web.utils";
|
||||
import { escape } from "@web/core/utils/strings";
|
||||
import { escape, sprintf } from "@web/core/utils/strings";
|
||||
|
||||
var _t = core._t;
|
||||
var _lt = core._lt;
|
||||
@@ -37,7 +36,7 @@ var M2ODialog = Dialog.extend({
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this._super(parent, {
|
||||
title: _.str.sprintf(_t("New %s"), this.name),
|
||||
title: sprintf(_t("New %s"), this.name),
|
||||
size: 'medium',
|
||||
buttons: [{
|
||||
text: _t('Create'),
|
||||
@@ -423,7 +422,7 @@ var FieldMany2One = AbstractField.extend({
|
||||
domain: this.record.getDomain({fieldName: this.name}),
|
||||
context: Object.assign({}, this.record.getContext(this.recordParams), context || {}),
|
||||
dynamicFilters: dynamicFilters || [],
|
||||
title: _.str.sprintf((view === 'search' ? _t("Search: %s") : _t("Create: %s")), this.string),
|
||||
title: sprintf((view === 'search' ? _t("Search: %s") : _t("Create: %s")), this.string),
|
||||
multiSelect: false,
|
||||
noCreate: !self.can_create,
|
||||
onSelected: function (records) {
|
||||
@@ -469,7 +468,7 @@ var FieldMany2One = AbstractField.extend({
|
||||
return x[0];
|
||||
});
|
||||
dynamicFilters = [{
|
||||
description: _.str.sprintf(_t('Quick search: %s'), search_val),
|
||||
description: sprintf(_t('Quick search: %s'), search_val),
|
||||
domain: [['id', 'in', ids]],
|
||||
}];
|
||||
}
|
||||
@@ -596,7 +595,7 @@ var FieldMany2One = AbstractField.extend({
|
||||
_renderReadonly: function () {
|
||||
this.$el.html(this._renderValueLines(true));
|
||||
if (!this.noOpen && this.value) {
|
||||
this.$el.attr('href', _.str.sprintf('#id=%s&model=%s', this.value.res_id, this.field.relation));
|
||||
this.$el.attr('href', `#id=${this.value.res_id}&model=${this.field.relation}`);
|
||||
this.$el.addClass('o_form_uri');
|
||||
}
|
||||
},
|
||||
@@ -1512,9 +1511,7 @@ var FieldSelection = AbstractField.extend({
|
||||
this.values = this.record.specialData[this.name];
|
||||
this.formatType = 'many2one';
|
||||
} else {
|
||||
this.values = _.reject(this.field.selection, function (v) {
|
||||
return v[0] === false && v[1] === '';
|
||||
});
|
||||
this.values = this.field.selection.filter(v => !(v[0] === false && v[1] === ''));
|
||||
}
|
||||
this.values = [[false, this.attrs.placeholder || '']].concat(this.values);
|
||||
},
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
* element, so it can be edited later.
|
||||
*/
|
||||
|
||||
import { intersection, unique } from "@web/core/utils/arrays";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import AbstractModel from "web.AbstractModel";
|
||||
import concurrency from "web.concurrency";
|
||||
import Context from "web.Context";
|
||||
@@ -860,8 +862,8 @@ var BasicModel = AbstractModel.extend({
|
||||
record.data[field.name] = null;
|
||||
if (field.type === 'many2one') {
|
||||
if (field.value) {
|
||||
var id = _.isArray(field.value) ? field.value[0] : field.value;
|
||||
var display_name = _.isArray(field.value) ? field.value[1] : undefined;
|
||||
var id = Array.isArray(field.value) ? field.value[0] : field.value;
|
||||
var display_name = Array.isArray(field.value) ? field.value[1] : undefined;
|
||||
dataPoint = self._makeDataPoint({
|
||||
modelName: field.relation,
|
||||
data: {
|
||||
@@ -991,7 +993,7 @@ var BasicModel = AbstractModel.extend({
|
||||
if (parent.static) {
|
||||
// x2Many case: the new record has been stored in _changes, as a
|
||||
// command so we remove the command(s) related to that record
|
||||
parent._changes = _.filter(parent._changes, function (change) {
|
||||
parent._changes = parent._changes.filter( change => {
|
||||
if (change.id === elementID &&
|
||||
change.operation === 'ADD' && // For now, only an ADD command increases limits
|
||||
parent.tempLimitIncrement) {
|
||||
@@ -1072,7 +1074,7 @@ var BasicModel = AbstractModel.extend({
|
||||
}
|
||||
if (dataType === 'list') {
|
||||
data.data = _.sortBy(data.data, function (d) {
|
||||
return _.indexOf(resIDs, self.localData[d].res_id)
|
||||
return resIDs.indexOf(self.localData[d].res_id);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1247,9 +1249,7 @@ var BasicModel = AbstractModel.extend({
|
||||
list.orderedBy[0].asc = !list.orderedBy[0].asc;
|
||||
}
|
||||
} else {
|
||||
var orderedBy = _.reject(list.orderedBy, function (o) {
|
||||
return o.name === fieldName;
|
||||
});
|
||||
var orderedBy = list.orderedBy.filter(o => o.name !== fieldName);
|
||||
list.orderedBy = [{name: fieldName, asc: true}].concat(orderedBy);
|
||||
}
|
||||
|
||||
@@ -1538,7 +1538,7 @@ var BasicModel = AbstractModel.extend({
|
||||
|
||||
if (options.notifyChange === false) {
|
||||
return Promise.all(defs).then(function () {
|
||||
return Promise.resolve(_.keys(changes));
|
||||
return Promise.resolve(Object.keys(changes));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1558,7 +1558,7 @@ var BasicModel = AbstractModel.extend({
|
||||
self._performOnChange(record, onChangeFields, { viewType: options.viewType })
|
||||
.then(function (result) {
|
||||
delete record._warning;
|
||||
resolve(_.keys(changes).concat(Object.keys(result && result.value || {})));
|
||||
resolve(Object.keys(changes).concat(Object.keys(result && result.value || {})));
|
||||
}).guardedCatch(function () {
|
||||
self._visitChildren(record, function (elem) {
|
||||
Object.assign(elem, initialData[elem.id]);
|
||||
@@ -1566,13 +1566,13 @@ var BasicModel = AbstractModel.extend({
|
||||
reject();
|
||||
});
|
||||
} else {
|
||||
resolve(_.keys(changes));
|
||||
resolve(Object.keys(changes));
|
||||
}
|
||||
}).then(function (fieldNames) {
|
||||
return self._fetchSpecialData(record).then(function (fieldNames2) {
|
||||
// Return the names of the fields that changed (onchange or
|
||||
// associated special data change)
|
||||
return _.union(fieldNames, fieldNames2);
|
||||
return fieldNames.concat(fieldNames2);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1729,7 +1729,7 @@ var BasicModel = AbstractModel.extend({
|
||||
if (val) {
|
||||
// when the value isn't false, it can be either
|
||||
// an array [id, display_name] or just an id.
|
||||
var data = _.isArray(val) ?
|
||||
var data = Array.isArray(val) ?
|
||||
{id: val[0], display_name: val[1]} :
|
||||
{id: val};
|
||||
if (!oldValue || (self.localData[oldValue].res_id !== data.id)) {
|
||||
@@ -1961,7 +1961,7 @@ var BasicModel = AbstractModel.extend({
|
||||
list._forceM2MLink = true;
|
||||
// handle multiple add: command[2] may be a dict of values (1
|
||||
// record added) or an array of dict of values
|
||||
var data = _.isArray(command.ids) ? command.ids : [command.ids];
|
||||
var data = Array.isArray(command.ids) ? command.ids : [command.ids];
|
||||
|
||||
// name_create records for which there is no id (typically, could
|
||||
// be the case of a quick_create in a many2many_tags, so data.length
|
||||
@@ -2066,23 +2066,22 @@ var BasicModel = AbstractModel.extend({
|
||||
// no 'ADD' operation for that dataPoint, as it would mean
|
||||
// that the record wasn't in the relation yet
|
||||
var idsToRemove = command.ids;
|
||||
list._changes = _.reject(list._changes, function (change, index) {
|
||||
var idInCommands = _.contains(command.ids, change.id);
|
||||
|
||||
list._changes = list._changes.filter(change => {
|
||||
var idInCommands = command.ids.includes(change.id);
|
||||
if (idInCommands && change.operation === 'ADD') {
|
||||
idsToRemove = _.without(idsToRemove, change.id);
|
||||
idsToRemove = idsToRemove.filter(id => id !== change.id);
|
||||
}
|
||||
return idInCommands;
|
||||
return !idInCommands;
|
||||
});
|
||||
_.each(idsToRemove, function (id) {
|
||||
idsToRemove.forEach(id => {
|
||||
var operation = list._forceM2MUnlink ? 'FORGET': 'DELETE';
|
||||
list._changes.push({operation: operation, id: id});
|
||||
});
|
||||
break;
|
||||
case 'DELETE_ALL':
|
||||
// first remove all pending 'ADD' operations
|
||||
list._changes = _.reject(list._changes, function (change) {
|
||||
return change.operation === 'ADD';
|
||||
});
|
||||
list._changes = list._changes.filter(change => change.operation !== 'ADD');
|
||||
|
||||
// then apply 'DELETE' on existing records
|
||||
return this._applyX2ManyChange(record, fieldName, {
|
||||
@@ -2393,7 +2392,7 @@ var BasicModel = AbstractModel.extend({
|
||||
evalContext = evalContext || this._getEvalContext(element);
|
||||
evaluated[k] = new Domain(mod, evalContext).compute(evalContext);
|
||||
} catch (e) {
|
||||
throw new Error(_.str.sprintf('for modifier "%s": %s', k, e.message));
|
||||
throw new Error(sprintf('for modifier "%s": %s', k, e.message));
|
||||
}
|
||||
}
|
||||
return evaluated;
|
||||
@@ -2436,12 +2435,12 @@ var BasicModel = AbstractModel.extend({
|
||||
const referenceFieldName = record.fields[fieldName].string;
|
||||
|
||||
this.displayNotification({
|
||||
title: _.str.sprintf(
|
||||
title: sprintf(
|
||||
_t(`'%s' is unsynchronized with '%s'.`),
|
||||
referenceFieldName,
|
||||
modelFieldName,
|
||||
),
|
||||
message: _.str.sprintf(
|
||||
message: sprintf(
|
||||
_t(`If you change %s or %s, the synchronization will be reapplied and the data will be modified.`),
|
||||
modelFieldName,
|
||||
referenceFieldName,
|
||||
@@ -2512,7 +2511,7 @@ var BasicModel = AbstractModel.extend({
|
||||
return this._rpc({
|
||||
model: model,
|
||||
method: 'name_get',
|
||||
args: [_.uniq(ids)],
|
||||
args: [unique(ids)],
|
||||
context: list.context,
|
||||
})
|
||||
.then(function (name_gets) {
|
||||
@@ -2539,7 +2538,7 @@ var BasicModel = AbstractModel.extend({
|
||||
var self = this;
|
||||
options = options || {};
|
||||
var fieldNames = options.fieldNames || record.getFieldNames(options);
|
||||
fieldNames = _.uniq(fieldNames.concat(['display_name']));
|
||||
fieldNames = unique(fieldNames.concat(['display_name']));
|
||||
return this._rpc({
|
||||
model: record.model,
|
||||
method: 'read',
|
||||
@@ -2761,7 +2760,7 @@ var BasicModel = AbstractModel.extend({
|
||||
*/
|
||||
_fetchRelatedData: function (list, toFetch, fieldName) {
|
||||
var self = this;
|
||||
var ids = _.keys(toFetch);
|
||||
var ids = Object.keys(toFetch || {});
|
||||
for (var i = 0; i < ids.length; i++) {
|
||||
ids[i] = Number(ids[i]);
|
||||
}
|
||||
@@ -2772,7 +2771,7 @@ var BasicModel = AbstractModel.extend({
|
||||
}
|
||||
|
||||
var def;
|
||||
var fieldNames = _.keys(fieldInfo.relatedFields);
|
||||
var fieldNames = Object.keys(fieldInfo.relatedFields || {});
|
||||
if (fieldNames.length) {
|
||||
var field = list.fields[fieldName];
|
||||
def = this._rpc({
|
||||
@@ -2782,12 +2781,14 @@ var BasicModel = AbstractModel.extend({
|
||||
context: list.getContext({withoutRecordData: true}) || {},
|
||||
});
|
||||
} else {
|
||||
def = Promise.resolve(_.map(ids, function (id) {
|
||||
return {id:id};
|
||||
}));
|
||||
def = Promise.resolve(
|
||||
ids.map((id) => {
|
||||
return { id: id };
|
||||
})
|
||||
);
|
||||
}
|
||||
return def.then(function (result) {
|
||||
var records = _.uniq(_.flatten(_.values(toFetch)));
|
||||
var records = unique(Object.values(toFetch || {}).flat());
|
||||
self._updateRecordsData(records, fieldName, result);
|
||||
});
|
||||
},
|
||||
@@ -3121,7 +3122,7 @@ var BasicModel = AbstractModel.extend({
|
||||
_.each(list.data, function (groupIndex) {
|
||||
var group = self.localData[groupIndex];
|
||||
var nextDataToFetch = self._getDataToFetch(group, fieldName);
|
||||
_.each(_.keys(nextDataToFetch), function (id) {
|
||||
_.each(Object.keys(nextDataToFetch), function (id) {
|
||||
if (toFetch[id]) {
|
||||
toFetch[id] = toFetch[id].concat(nextDataToFetch[id]);
|
||||
} else {
|
||||
@@ -3316,9 +3317,7 @@ var BasicModel = AbstractModel.extend({
|
||||
list = this._applyX2ManyOperations(list);
|
||||
this._sortList(list);
|
||||
if (type === 'many2many' || list._forceM2MLink) {
|
||||
var relRecordCreated = _.filter(relRecordAdded, function (rec) {
|
||||
return typeof rec.res_id === 'string';
|
||||
});
|
||||
var relRecordCreated = relRecordAdded.filter(rec => typeof rec.res_id === 'string');
|
||||
var realIDs = _.difference(list.res_ids, _.pluck(relRecordCreated, 'res_id'));
|
||||
// deliberately generate a single 'replace' command instead
|
||||
// of a 'delete' and a 'link' commands with the exact diff
|
||||
@@ -3342,7 +3341,7 @@ var BasicModel = AbstractModel.extend({
|
||||
} else if (type === 'one2many') {
|
||||
var removedIds = _.difference(oldResIDs, list.res_ids);
|
||||
var addedIds = _.difference(list.res_ids, oldResIDs);
|
||||
var keptIds = _.intersection(oldResIDs, list.res_ids);
|
||||
var keptIds = intersection(oldResIDs, list.res_ids);
|
||||
|
||||
// the didChange variable keeps track of the fact that at
|
||||
// least one id was updated
|
||||
@@ -3878,7 +3877,7 @@ var BasicModel = AbstractModel.extend({
|
||||
}
|
||||
if (field.type === 'one2many' || field.type === 'many2many') {
|
||||
var ids;
|
||||
if (!context[fieldName] || _.isArray(context[fieldName])) { // no dataPoint created yet
|
||||
if (!context[fieldName] || Array.isArray(context[fieldName])) { // no dataPoint created yet
|
||||
ids = context[fieldName] ? context[fieldName].slice(0) : [];
|
||||
} else {
|
||||
relDataPoint = this._applyX2ManyOperations(this.localData[context[fieldName]]);
|
||||
@@ -3894,9 +3893,7 @@ var BasicModel = AbstractModel.extend({
|
||||
* The webClient doesn't do literal id list comparison like ids == list
|
||||
* Only relevant in o2m: m2m does create actual records in db
|
||||
*/
|
||||
ids = _.filter(ids, function (id) {
|
||||
return typeof id !== 'string';
|
||||
});
|
||||
ids = ids.filter(id => typeof id !== 'string');
|
||||
}
|
||||
context[fieldName] = ids;
|
||||
}
|
||||
@@ -3949,7 +3946,7 @@ var BasicModel = AbstractModel.extend({
|
||||
}
|
||||
if (field.type === 'one2many' || field.type === 'many2many') {
|
||||
let ids;
|
||||
if (!fieldValue || _.isArray(fieldValue)) { // no dataPoint created yet
|
||||
if (!fieldValue || Array.isArray(fieldValue)) { // no dataPoint created yet
|
||||
ids = fieldValue ? fieldValue.slice(0) : [];
|
||||
} else {
|
||||
relDataPoint = self._applyX2ManyOperations(self.localData[fieldValue]);
|
||||
@@ -3965,13 +3962,11 @@ var BasicModel = AbstractModel.extend({
|
||||
* The webClient doesn't do literal id list comparison like ids == list
|
||||
* Only relevant in o2m: m2m does create actual records in db
|
||||
*/
|
||||
ids = _.filter(ids, function (id) {
|
||||
return typeof id !== 'string';
|
||||
});
|
||||
ids = ids.filter(id => typeof id !== 'string');
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
if (field.type === "properties" && _.isArray(fieldValue)) {
|
||||
if (field.type === "properties" && Array.isArray(fieldValue)) {
|
||||
// remove deleted properties to be able
|
||||
// to filter based on empty properties field
|
||||
return fieldValue.filter(definition => !definition.definition_deleted);
|
||||
@@ -4193,7 +4188,7 @@ var BasicModel = AbstractModel.extend({
|
||||
limit: type === 'record' ? 1 : (params.limit || Number.MAX_SAFE_INTEGER),
|
||||
loadMoreOffset: 0,
|
||||
model: params.modelName,
|
||||
offset: params.offset || (type === 'record' ? _.indexOf(res_ids, res_id) : 0),
|
||||
offset: params.offset || (type === 'record' ? res_ids.indexOf(res_id) : 0),
|
||||
openGroupByDefault: params.openGroupByDefault,
|
||||
orderedBy: params.orderedBy || [],
|
||||
orderedResIDs: params.orderedResIDs,
|
||||
@@ -4265,7 +4260,7 @@ var BasicModel = AbstractModel.extend({
|
||||
|
||||
if (parentRecord && parentRecord.viewType in parentRecord.fieldsInfo) {
|
||||
var originView = parentRecord.viewType;
|
||||
fieldNames = _.union(fieldNames, Object.keys(parentRecord.fieldsInfo[originView]));
|
||||
fieldNames = fieldNames.concat(Object.keys(parentRecord.fieldsInfo[originView]));
|
||||
fieldsInfo[targetView] = _.defaults({}, fieldsInfo[targetView], parentRecord.fieldsInfo[originView]);
|
||||
fields = _.defaults({}, fields, parentRecord.fields);
|
||||
}
|
||||
@@ -4594,7 +4589,7 @@ var BasicModel = AbstractModel.extend({
|
||||
var many2ones = {};
|
||||
var r;
|
||||
commands = commands || []; // handle false value
|
||||
var isCommandList = commands.length && _.isArray(commands[0]);
|
||||
var isCommandList = commands.length && Array.isArray(commands[0]);
|
||||
if (!isCommandList) {
|
||||
commands = [[6, false, commands]];
|
||||
}
|
||||
@@ -4673,7 +4668,7 @@ var BasicModel = AbstractModel.extend({
|
||||
});
|
||||
|
||||
// fetch many2ones display_name
|
||||
_.each(_.keys(many2ones), function (name) {
|
||||
_.each(Object.keys(many2ones), function (name) {
|
||||
defs.push(self._fetchNameGets(x2manyList, name));
|
||||
});
|
||||
|
||||
@@ -4701,7 +4696,7 @@ var BasicModel = AbstractModel.extend({
|
||||
}
|
||||
var record = self.localData[dataPointID];
|
||||
var data = Object.assign({}, record.data, record._changes);
|
||||
if (_.difference(fieldNames, _.keys(data)).length) {
|
||||
if (_.difference(fieldNames, Object.keys(data)).length) {
|
||||
missingIDs.push(resId);
|
||||
}
|
||||
}
|
||||
@@ -4770,9 +4765,9 @@ var BasicModel = AbstractModel.extend({
|
||||
var groupByField = list.groupedBy[0];
|
||||
var rawGroupBy = groupByField.split(':')[0];
|
||||
var fields = _.uniq(list.getFieldNames().concat(rawGroupBy));
|
||||
var orderedBy = _.filter(list.orderedBy, function (order) {
|
||||
var orderedBy = list.orderedBy?.filter(order => {
|
||||
return order.name === rawGroupBy || list.fields[order.name].group_operator !== undefined;
|
||||
});
|
||||
}) || [];
|
||||
var openGroupsLimit = list.groupsLimit || self.OPEN_GROUP_LIMIT;
|
||||
var expand = list.openGroupByDefault && options.fetchRecordsWithGroups;
|
||||
return this._rpc({
|
||||
@@ -4924,7 +4919,7 @@ var BasicModel = AbstractModel.extend({
|
||||
if (list.res_ids.length > list.limit && list.orderedBy.length) {
|
||||
if (!list.orderedResIDs) {
|
||||
var fieldNames = _.pluck(list.orderedBy, 'name');
|
||||
def = this._readMissingFields(list, _.filter(list.res_ids, _.isNumber), fieldNames, options.withoutRecordData);
|
||||
def = this._readMissingFields(list, list.res_ids.filter(id => Number.isFinite(id)), fieldNames, options.withoutRecordData);
|
||||
}
|
||||
def.then(function () {
|
||||
self._sortList(list);
|
||||
@@ -4953,7 +4948,7 @@ var BasicModel = AbstractModel.extend({
|
||||
var fieldNames = list.getFieldNames();
|
||||
for (var i = list.offset; i < upperBound; i++) {
|
||||
var resId = currentResIDs[i];
|
||||
if (_.isNumber(resId)) {
|
||||
if (Number.isFinite(resId)) {
|
||||
resIDs.push(resId);
|
||||
}
|
||||
}
|
||||
@@ -5045,7 +5040,7 @@ var BasicModel = AbstractModel.extend({
|
||||
element.count = element.res_ids.length;
|
||||
}
|
||||
if (element.type === 'record') {
|
||||
element.offset = _.indexOf(element.res_ids, element.res_id);
|
||||
element.offset = element.res_ids.indexOf(element.res_id);
|
||||
}
|
||||
var loadOptions = _.pick(options, 'fieldNames', 'viewType');
|
||||
return this._load(element, loadOptions).then(function (result) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/** @odoo-module alias=web.viewUtils **/
|
||||
|
||||
|
||||
import { unique } from '@web/core/utils/arrays';
|
||||
import * as dom from 'web.dom';
|
||||
import * as utils from 'web.utils';
|
||||
|
||||
@@ -93,7 +94,7 @@ var viewUtils = {
|
||||
};
|
||||
if (options && options.extraClass) {
|
||||
var classes = btnOptions.attrs.class ? btnOptions.attrs.class.split(' ') : [];
|
||||
btnOptions.attrs.class = _.uniq(classes.concat(options.extraClass.split(' '))).join(' ');
|
||||
btnOptions.attrs.class = unique(classes.concat(options.extraClass.split(' '))).join(' ');
|
||||
}
|
||||
var str = (node.attrs.string || '').replace(/_/g, '');
|
||||
if (str) {
|
||||
|
||||
@@ -136,14 +136,17 @@ var ColorpickerWidget = Widget.extend({
|
||||
|
||||
// Update inputs
|
||||
_.each(this.colorComponents, function (value, color) {
|
||||
self.$(_.str.sprintf('.o_%s_input', color)).val(value);
|
||||
self.$(`.o_${color}_input`).val(value);
|
||||
});
|
||||
|
||||
// Update preview
|
||||
this.$('.o_color_preview').css('background-color', this.colorComponents.cssColor);
|
||||
|
||||
// Update picker area and picker pointer position
|
||||
this.$colorpickerArea.css('background-color', _.str.sprintf('hsl(%s, 100%%, 50%%)', this.colorComponents.hue));
|
||||
this.$colorpickerArea.css(
|
||||
"background-color",
|
||||
`hsl(${this.colorComponents.hue}, 100%, 50%)`
|
||||
);
|
||||
var top = (100 - this.colorComponents.lightness) * this.$colorpickerArea.height() / 100;
|
||||
var left = this.colorComponents.saturation * this.$colorpickerArea.width() / 100;
|
||||
this.$colorpickerPointer.css({
|
||||
|
||||
@@ -251,7 +251,7 @@ var DomainTree = DomainNode.extend({
|
||||
* false otherwise (the afterNode was not found)
|
||||
*/
|
||||
_addChild: function (domain, afterNode) {
|
||||
var i = afterNode ? _.indexOf(this.children, afterNode) : this.children.length;
|
||||
var i = afterNode ? this.children.indexOf(afterNode) : this.children.length;
|
||||
if (i < 0) return false;
|
||||
|
||||
this.children.splice(i+1, 0, instantiateNode(this, this.model, domain, this.options));
|
||||
@@ -355,7 +355,7 @@ var DomainTree = DomainNode.extend({
|
||||
* widget does not own the child)
|
||||
*/
|
||||
_removeChild: function (oldChild) {
|
||||
var i = _.indexOf(this.children, oldChild);
|
||||
var i = this.children.indexOf(oldChild);
|
||||
if (i < 0) return false;
|
||||
|
||||
this.children[i].destroy();
|
||||
@@ -708,7 +708,7 @@ var DomainLeaf = DomainNode.extend({
|
||||
// Adapt display value and operator for rendering
|
||||
this.displayValue = this.value;
|
||||
try {
|
||||
if (selectedField && !selectedField.relation && !_.isArray(this.value)) {
|
||||
if (selectedField && !selectedField.relation && !Array.isArray(this.value)) {
|
||||
this.displayValue = field_utils.format[selectedField.type](this.value, selectedField);
|
||||
}
|
||||
} catch {/**/}
|
||||
@@ -819,9 +819,9 @@ var DomainLeaf = DomainNode.extend({
|
||||
this.operator = this.operator === "not set" ? "=" : "!=";
|
||||
this.value = false;
|
||||
} else if (_.contains(["in", "not in"], this.operator)) {
|
||||
this.value = _.isArray(this.value) ? this.value : this.value ? ("" + this.value).split(",") : [];
|
||||
this.value = Array.isArray(this.value) ? this.value : this.value ? ("" + this.value).split(",") : [];
|
||||
} else {
|
||||
if (_.isArray(this.value)) {
|
||||
if (Array.isArray(this.value)) {
|
||||
this.value = this.value.join(",");
|
||||
}
|
||||
this._changeValue(this.value, true);
|
||||
@@ -868,7 +868,7 @@ var DomainLeaf = DomainNode.extend({
|
||||
// Never display "true" or "false" strings from boolean value
|
||||
if (_.isBoolean(this.value)) {
|
||||
this.value = "";
|
||||
} else if (_.isObject(this.value) && !_.isArray(this.value)) { // Can be object if parsed to x2x representation
|
||||
} else if (_.isObject(this.value) && !Array.isArray(this.value)) { // Can be object if parsed to x2x representation
|
||||
this.value = this.value.id || value || "";
|
||||
}
|
||||
}
|
||||
@@ -971,7 +971,7 @@ var DomainLeaf = DomainNode.extend({
|
||||
if (e.type === "keyup" && e.which !== $.ui.keyCode.ENTER) return;
|
||||
if (!_.contains(["not in", "in"], this.operator)) return;
|
||||
|
||||
var values = _.isArray(this.value) ? this.value.slice() : [];
|
||||
var values = Array.isArray(this.value) ? this.value.slice() : [];
|
||||
|
||||
var $input = this.$(".o_domain_leaf_value_tags input");
|
||||
var val = $input.val().trim();
|
||||
@@ -982,7 +982,7 @@ var DomainLeaf = DomainNode.extend({
|
||||
}
|
||||
},
|
||||
on_remove_tag: function (e) {
|
||||
var values = _.isArray(this.value) ? this.value.slice() : [];
|
||||
var values = Array.isArray(this.value) ? this.value.slice() : [];
|
||||
var val = this.$(e.currentTarget).data("value");
|
||||
|
||||
var index = values.indexOf(val);
|
||||
|
||||
@@ -245,7 +245,7 @@ var ModelFieldSelectorPopover = Widget.extend({
|
||||
}).bind(this));
|
||||
}
|
||||
return def.then((function () {
|
||||
return _.filter(modelFieldsCache.cache[model], function (f) {
|
||||
return modelFieldsCache.cache[model].filter(f => {
|
||||
return (!filters.searchable || f.searchable) && self.options.filter(f);
|
||||
});
|
||||
}).bind(this));
|
||||
@@ -429,7 +429,12 @@ var ModelFieldSelectorPopover = Widget.extend({
|
||||
var page = this.pages.at(-1);
|
||||
this.$(".o_field_selector_popover_header .o_field_selector_title").text(this._getTitle());
|
||||
|
||||
var lines = _.filter(page, this.options.filter);
|
||||
var lines = page.filter((item) => {
|
||||
return Object.keys(this.options.filter).every((key) => {
|
||||
return item[key] === this.options.filter[key];
|
||||
});
|
||||
});
|
||||
|
||||
if (this.searchValue) {
|
||||
lines = fuzzyLookup(this.searchValue, lines, (l) => l.string);
|
||||
}
|
||||
|
||||
@@ -27,8 +27,12 @@ export class TimezoneMismatchField extends SelectionField {
|
||||
if (userOffset && this.props.record.data[this.props.name]) {
|
||||
const offset = -new Date().getTimezoneOffset();
|
||||
let browserOffset = offset < 0 ? "-" : "+";
|
||||
browserOffset += _.str.sprintf("%02d", Math.abs(offset / 60));
|
||||
browserOffset += _.str.sprintf("%02d", Math.abs(offset % 60));
|
||||
browserOffset += Math.abs(offset / 60)
|
||||
.toFixed(0)
|
||||
.padStart(2, "0");
|
||||
browserOffset += Math.abs(offset % 60)
|
||||
.toFixed(0)
|
||||
.padStart(2, "0");
|
||||
return browserOffset !== userOffset;
|
||||
} else if (!this.props.record.data[this.props.name]) {
|
||||
return true;
|
||||
|
||||
@@ -85,10 +85,20 @@ QUnit.module('core', function () {
|
||||
return String(d.getFullYear()) + '-01-30';
|
||||
});
|
||||
|
||||
check("time.strftime('%Y-%m-%d %H:%M:%S')", function(d) {
|
||||
return _.str.sprintf('%04d-%02d-%02d %02d:%02d:%02d',
|
||||
d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate(),
|
||||
d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds());
|
||||
check("time.strftime('%Y-%m-%d %H:%M:%S')", function (d) {
|
||||
return (
|
||||
[
|
||||
String(d.getUTCFullYear()).padStart(4, "0"),
|
||||
String(d.getUTCMonth() + 1).padStart(2, "0"),
|
||||
String(d.getUTCDate()).padStart(2, "0"),
|
||||
].join("-") +
|
||||
" " +
|
||||
[
|
||||
String(d.getUTCHours()).padStart(2, "0"),
|
||||
String(d.getUTCMinutes()).padStart(2, "0"),
|
||||
String(d.getUTCSeconds()).padStart(2, "0"),
|
||||
].join(":")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -98,8 +108,11 @@ QUnit.module('core', function () {
|
||||
var check = makeTimeCheck(assert, pyUtils);
|
||||
|
||||
check("context_today().strftime('%Y-%m-%d')", function(d) {
|
||||
return String(_.str.sprintf('%04d-%02d-%02d',
|
||||
d.getFullYear(), d.getMonth() + 1, d.getDate()));
|
||||
return [
|
||||
String(d.getFullYear()).padStart(4, "0"),
|
||||
String(d.getMonth() + 1).padStart(2, "0"),
|
||||
String(d.getDate()).padStart(2, "0"),
|
||||
].join("-");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -709,8 +722,11 @@ QUnit.module('core', function () {
|
||||
});
|
||||
|
||||
var d = new Date();
|
||||
var today = _.str.sprintf("%04d-%02d-%02d",
|
||||
d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate());
|
||||
var today = [
|
||||
String(d.getUTCFullYear()).padStart(4, "0"),
|
||||
String(d.getUTCMonth() + 1).padStart(2, "0"),
|
||||
String(d.getUTCDate()).padStart(2, "0"),
|
||||
].join("-");
|
||||
assert.deepEqual(result.domain, [
|
||||
["type", "=", "contract"],
|
||||
"|", ["state", "in", ["open", "draft"]],
|
||||
@@ -777,8 +793,11 @@ QUnit.module('core', function () {
|
||||
});
|
||||
|
||||
var date = new Date();
|
||||
var today = _.str.sprintf("%04d-%02d-%02d",
|
||||
date.getFullYear(), date.getMonth() + 1, date.getDate());
|
||||
var today = [
|
||||
String(date.getFullYear()).padStart(4, "0"),
|
||||
String(date.getMonth() + 1).padStart(2, "0"),
|
||||
String(date.getDate()).padStart(2, "0"),
|
||||
].join("-");
|
||||
assert.deepEqual(result.domain, [
|
||||
['state', '!=', 'cancel'],
|
||||
['opening_date', '>', today]
|
||||
@@ -794,11 +813,17 @@ QUnit.module('core', function () {
|
||||
contexts: [],
|
||||
});
|
||||
var date = new Date();
|
||||
var today = _.str.sprintf("%04d-%02d-%02d",
|
||||
date.getFullYear(), date.getMonth() + 1, date.getDate());
|
||||
var today = [
|
||||
String(date.getFullYear()).padStart(4, "0"),
|
||||
String(date.getMonth() + 1).padStart(2, "0"),
|
||||
String(date.getDate()).padStart(2, "0"),
|
||||
].join("-");
|
||||
date.setDate(date.getDate() - 15);
|
||||
var ago_15_d = _.str.sprintf("%04d-%02d-%02d",
|
||||
date.getFullYear(), date.getMonth() + 1, date.getDate());
|
||||
var ago_15_d = [
|
||||
String(date.getFullYear()).padStart(4, "0"),
|
||||
String(date.getMonth() + 1).padStart(2, "0"),
|
||||
String(date.getDate()).padStart(2, "0"),
|
||||
].join("-");
|
||||
assert.deepEqual(result.domain, [
|
||||
['type', '=', 'in'],
|
||||
['day', '<=', today],
|
||||
|
||||
@@ -381,14 +381,14 @@ var MockServer = Class.extend({
|
||||
var v = pyUtils.py_eval(mod, {context: pyevalContext}) ? true: false;
|
||||
if (inTreeView && !inListHeader && a === 'invisible') {
|
||||
modifiers.column_invisible = v;
|
||||
} else if (v || !(a in modifiers) || !_.isArray(modifiers[a])) {
|
||||
} else if (v || !(a in modifiers) || !Array.isArray(modifiers[a])) {
|
||||
modifiers[a] = v;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
_.each(modifiersNames, function (a) {
|
||||
if (a in modifiers && (!!modifiers[a] === false || (_.isArray(modifiers[a]) && !modifiers[a].length))) {
|
||||
if (a in modifiers && (!!modifiers[a] === false || (Array.isArray(modifiers[a]) && !modifiers[a].length))) {
|
||||
delete modifiers[a];
|
||||
}
|
||||
});
|
||||
@@ -470,7 +470,7 @@ var MockServer = Class.extend({
|
||||
* @returns {Object[]} a list of records
|
||||
*/
|
||||
_getRecords: function (model, domain, { active_test = true } = {}) {
|
||||
if (!_.isArray(domain)) {
|
||||
if (!Array.isArray(domain)) {
|
||||
throw new Error("MockServer._getRecords: given domain has to be an array.");
|
||||
}
|
||||
|
||||
@@ -517,9 +517,7 @@ var MockServer = Class.extend({
|
||||
}
|
||||
return criterion;
|
||||
});
|
||||
records = _.filter(records, function (record) {
|
||||
return self._evaluateDomain(domain, record);
|
||||
});
|
||||
records = records.filter(record => self._evaluateDomain(domain, record));
|
||||
}
|
||||
|
||||
return records;
|
||||
@@ -1217,7 +1215,7 @@ var MockServer = Class.extend({
|
||||
}
|
||||
}
|
||||
var key = [model, viewID, viewType].join(',');
|
||||
var arch = self.archs[key] || _.find(self.archs, function (_v, k) {
|
||||
var arch = self.archs[key] || Object.keys(self.archs).find(k => {
|
||||
var ka = k.split(',');
|
||||
viewID = parseInt(ka[1], 10);
|
||||
return ka[0] === model && ka[2] === viewType;
|
||||
@@ -1252,7 +1250,7 @@ var MockServer = Class.extend({
|
||||
else if (!ids) {
|
||||
return []
|
||||
}
|
||||
if (!_.isArray(ids)) {
|
||||
if (!Array.isArray(ids)) {
|
||||
ids = [ids];
|
||||
}
|
||||
var records = this.data[model].records;
|
||||
@@ -1299,9 +1297,7 @@ var MockServer = Class.extend({
|
||||
var domain = (args && args[1]) || _kwargs.args || [];
|
||||
var records = this._getRecords(model, domain);
|
||||
if (str.length) {
|
||||
records = _.filter(records, function (record) {
|
||||
return record.display_name.indexOf(str) !== -1;
|
||||
});
|
||||
records = records.filter(record => record.display_name.indexOf(str) !== -1);
|
||||
}
|
||||
var result = _.map(records, function (record) {
|
||||
return [record.id, record.display_name];
|
||||
@@ -1380,7 +1376,7 @@ var MockServer = Class.extend({
|
||||
_mockRead: function (model, args, _kwargs) {
|
||||
var self = this;
|
||||
var ids = args[0];
|
||||
if (!_.isArray(ids)) {
|
||||
if (!Array.isArray(ids)) {
|
||||
ids = [ids];
|
||||
}
|
||||
var fields = args[1] && args[1].length ? _.uniq(args[1].concat(['id'])) : Object.keys(this.data[model].fields);
|
||||
@@ -1467,7 +1463,7 @@ var MockServer = Class.extend({
|
||||
|
||||
// if no fields have been given, the server picks all stored fields
|
||||
if (kwargs.fields.length === 0) {
|
||||
aggregatedFields = _.keys(this.data[model].fields);
|
||||
aggregatedFields = Object.keys(this.data[model].fields);
|
||||
}
|
||||
|
||||
var groupByFieldNames = _.map(groupBy, function (groupByField) {
|
||||
@@ -1475,7 +1471,7 @@ var MockServer = Class.extend({
|
||||
});
|
||||
|
||||
// filter out non existing fields
|
||||
aggregatedFields = _.filter(aggregatedFields, function (name) {
|
||||
aggregatedFields = aggregatedFields.filter(name => {
|
||||
return name in self.data[model].fields && !(_.contains(groupByFieldNames,name));
|
||||
});
|
||||
|
||||
@@ -1827,7 +1823,7 @@ var MockServer = Class.extend({
|
||||
var records = this._getRecords(args.model, args.domain || [], {
|
||||
active_test,
|
||||
});
|
||||
var fields = args.fields && args.fields.length ? args.fields : _.keys(this.data[args.model].fields);
|
||||
var fields = args.fields && args.fields.length ? args.fields : Object.keys(this.data[args.model].fields);
|
||||
var nbRecords = records.length;
|
||||
var offset = args.offset || 0;
|
||||
if (args.sort) {
|
||||
@@ -1870,12 +1866,10 @@ var MockServer = Class.extend({
|
||||
*/
|
||||
_mockUnlink: function (model, args) {
|
||||
var ids = args[0];
|
||||
if (!_.isArray(ids)) {
|
||||
if (!Array.isArray(ids)) {
|
||||
ids = [ids];
|
||||
}
|
||||
this.data[model].records = _.reject(this.data[model].records, function (record) {
|
||||
return _.contains(ids, record.id);
|
||||
});
|
||||
this.data[model].records = this.data[model].records.filter(record => !_.contains(ids, record.id));
|
||||
|
||||
// update value of relationnal fields pointing to the deleted records
|
||||
_.each(this.data, function (d) {
|
||||
|
||||
@@ -146,7 +146,7 @@ async function _getMockedOwlEnv(params, mockServer) {
|
||||
delete servicesToDeploy[serviceName];
|
||||
services[serviceName].start();
|
||||
} else {
|
||||
const serviceNames = _.keys(servicesToDeploy);
|
||||
const serviceNames = Object.keys(servicesToDeploy);
|
||||
if (serviceNames.length) {
|
||||
console.warn("Non loaded services:", serviceNames);
|
||||
}
|
||||
|
||||
@@ -2303,7 +2303,7 @@ QUnit.module("Fields", (hooks) => {
|
||||
if (args.method === "write") {
|
||||
saveCount++;
|
||||
const nbCommands = args.args[1].p.length;
|
||||
const nbLinkCommands = _.filter(args.args[1].p, function (command) {
|
||||
const nbLinkCommands = args.args[1].p.filter((command) => {
|
||||
return command[0] === 4;
|
||||
}).length;
|
||||
switch (saveCount) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import dom from "web.dom";
|
||||
import Dialog from "web.Dialog";
|
||||
import Widget from "web.Widget";
|
||||
import localStorage from "web.local_storage";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
@@ -283,9 +284,9 @@ var ViewEditor = Widget.extend({
|
||||
if (typeof this.viewKey === "number") {
|
||||
initResID = this.viewKey;
|
||||
} else {
|
||||
var view = _.findWhere(this.views, {xml_id: this.viewKey});
|
||||
var view = Object.values(this.views).find(view => view.xml_id === this.viewKey);
|
||||
if (!view) {
|
||||
view = _.findWhere(this.views, {key: this.viewKey});
|
||||
view = Object.values(this.views).find(view => view.key === this.viewKey);
|
||||
}
|
||||
initResID = view.id;
|
||||
}
|
||||
@@ -425,11 +426,11 @@ var ViewEditor = Widget.extend({
|
||||
this.aceEditor.setSession(editingSession);
|
||||
|
||||
if (this.currentType === 'xml') {
|
||||
this.$viewID.text(_.str.sprintf(_t("Template ID: %s"), this.views[resID].key));
|
||||
this.$viewID.text(sprintf(_t("Template ID: %s"), this.views[resID].key));
|
||||
} else if (this.currentType === 'scss') {
|
||||
this.$viewID.text(_.str.sprintf(_t("SCSS file: %s"), resID));
|
||||
this.$viewID.text(sprintf(_t("SCSS file: %s"), resID));
|
||||
} else {
|
||||
this.$viewID.text(_.str.sprintf(_t("JS file: %s"), resID));
|
||||
this.$viewID.text(sprintf(_t("JS file: %s"), resID));
|
||||
}
|
||||
const isCustomized = this._isCustomResource(resID);
|
||||
this.$lists[this.currentType].select2('val', resID);
|
||||
@@ -518,9 +519,7 @@ var ViewEditor = Widget.extend({
|
||||
|
||||
function _processViews(views) {
|
||||
// Only keep the active views and index them by ID.
|
||||
Object.assign(this.views, _.indexBy(_.filter(views, function (view) {
|
||||
return view.active;
|
||||
}), 'id'));
|
||||
Object.assign(this.views, _.indexBy(views.filter(view => view.active), 'id'));
|
||||
|
||||
// Initialize a 0 level for each view and assign them an array containing their children.
|
||||
var self = this;
|
||||
@@ -893,7 +892,7 @@ var ViewEditor = Widget.extend({
|
||||
label: bundleInfos[0],
|
||||
}).appendTo($list);
|
||||
_.each(bundleInfos[1], function (dataInfo) {
|
||||
var name = dataInfo.url.substring(_.lastIndexOf(dataInfo.url, '/') + 1, dataInfo.url.length - lettersToRemove);
|
||||
var name = dataInfo.url.substring(dataInfo.url.lastIndexOf('/') + 1, dataInfo.url.length - lettersToRemove);
|
||||
$optgroup.append($('<option/>', {
|
||||
value: dataInfo.url,
|
||||
text: name,
|
||||
|
||||
@@ -4,13 +4,14 @@ import concurrency from "web.concurrency";
|
||||
import core from "web.core";
|
||||
import Dialog from "web.Dialog";
|
||||
import dom from "web.dom";
|
||||
import {Markup, sprintf, confine} from "web.utils";
|
||||
import {Markup, confine} from "web.utils";
|
||||
import Widget from "web.Widget";
|
||||
import options from "web_editor.snippets.options";
|
||||
import {ColorPaletteWidget} from "web_editor.ColorPalette";
|
||||
import SmoothScrollOnDrag from "web.smooth_scroll_on_drag";
|
||||
import {getCSSVariableValue} from "web_editor.utils";
|
||||
import * as gridUtils from "@web_editor/js/common/grid_layout_utils";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
const QWeb = core.qweb;
|
||||
import {closestElement} from "@web_editor/js/editor/odoo-editor/src/utils/utils";
|
||||
|
||||
@@ -666,7 +667,7 @@ var SnippetEditor = Widget.extend({
|
||||
*/
|
||||
toggleTargetVisibility: async function (show) {
|
||||
show = this._toggleVisibilityStatus(show);
|
||||
var styles = _.values(this.styles);
|
||||
var styles = Object.values(this.styles);
|
||||
const proms = _.sortBy(styles, '__order').map(style => {
|
||||
return show ? style.onTargetShow() : style.onTargetHide();
|
||||
});
|
||||
@@ -2900,12 +2901,12 @@ var SnippetsMenu = Widget.extend({
|
||||
const btnRenameEl = document.createElement('we-button');
|
||||
btnRenameEl.dataset.snippetId = $snippet.data('oeSnippetId');
|
||||
btnRenameEl.classList.add('o_rename_btn', 'fa', 'fa-pencil', 'btn', 'o_we_hover_success');
|
||||
btnRenameEl.title = _.str.sprintf(_t("Rename %s"), name);
|
||||
btnRenameEl.title = sprintf(_t("Rename %s"), name);
|
||||
$snippet.append(btnRenameEl);
|
||||
const btnEl = document.createElement('we-button');
|
||||
btnEl.dataset.snippetId = $snippet.data('oeSnippetId');
|
||||
btnEl.classList.add('o_delete_btn', 'fa', 'fa-trash', 'btn', 'o_we_hover_danger');
|
||||
btnEl.title = _.str.sprintf(_t("Delete %s"), name);
|
||||
btnEl.title = sprintf(_t("Delete %s"), name);
|
||||
$snippet.append(btnEl);
|
||||
}
|
||||
})
|
||||
@@ -3728,9 +3729,9 @@ var SnippetsMenu = Widget.extend({
|
||||
var moduleID = $snippet.data('moduleId');
|
||||
var name = $snippet.attr('name');
|
||||
new Dialog(this, {
|
||||
title: _.str.sprintf(_t("Install %s"), name),
|
||||
title: sprintf(_t("Install %s"), name),
|
||||
size: 'medium',
|
||||
$content: $('<div/>', {text: _.str.sprintf(_t("Do you want to install the %s App?"), name)}).append(
|
||||
$content: $('<div/>', {text: sprintf(_t("Do you want to install the %s App?"), name)}).append(
|
||||
$('<a/>', {
|
||||
target: '_blank',
|
||||
href: '/web#id=' + moduleID + '&view_type=form&model=ir.module.module&action=base.open_module_tree',
|
||||
@@ -3817,7 +3818,7 @@ var SnippetsMenu = Widget.extend({
|
||||
new Dialog(this, {
|
||||
size: 'medium',
|
||||
title: _t('Confirmation'),
|
||||
$content: $('<div><p>' + _.str.sprintf(_t("Are you sure you want to delete the snippet: %s?"), $snippet.attr('name')) + '</p></div>'),
|
||||
$content: $('<div><p>' + sprintf(_t("Are you sure you want to delete the snippet: %s?"), $snippet.attr('name')) + '</p></div>'),
|
||||
buttons: [{
|
||||
text: _t("Yes"),
|
||||
close: true,
|
||||
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
} from "web_editor.image_processing";
|
||||
import * as OdooEditorLib from "@web_editor/js/editor/odoo-editor/src/OdooEditor";
|
||||
import {SIZES, MEDIAS_BREAKPOINTS} from "@web/core/ui/ui_service";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
var qweb = core.qweb;
|
||||
var _t = core._t;
|
||||
@@ -5771,9 +5772,9 @@ const ImageHandlerOption = SnippetOptionWidget.extend({
|
||||
1024: '1024px',
|
||||
1920: '1920px',
|
||||
};
|
||||
widths[img.naturalWidth] = _.str.sprintf(_t("%spx"), img.naturalWidth);
|
||||
widths[optimizedWidth] = _.str.sprintf(_t("%dpx (Suggested)"), optimizedWidth);
|
||||
widths[maxWidth] = _.str.sprintf(_t("%dpx (Original)"), maxWidth);
|
||||
widths[img.naturalWidth] = sprintf(_t("%spx"), img.naturalWidth);
|
||||
widths[optimizedWidth] = sprintf(_t("%dpx (Suggested)"), optimizedWidth);
|
||||
widths[maxWidth] = sprintf(_t("%dpx (Original)"), maxWidth);
|
||||
return Object.entries(widths)
|
||||
.filter(([width]) => width <= maxWidth)
|
||||
.sort(([v1], [v2]) => v1 - v2);
|
||||
@@ -7815,7 +7816,7 @@ registry.SnippetSave = SnippetOptionWidget.extend({
|
||||
reloadEditor: true,
|
||||
invalidateSnippetCache: true,
|
||||
onSuccess: async () => {
|
||||
const defaultSnippetName = _.str.sprintf(_t("Custom %s"), this.data.snippetName);
|
||||
const defaultSnippetName = sprintf(_t("Custom %s"), this.data.snippetName);
|
||||
const targetCopyEl = this.$target[0].cloneNode(true);
|
||||
delete targetCopyEl.dataset.name;
|
||||
// By the time onSuccess is called after request_save, the
|
||||
|
||||
@@ -7,6 +7,7 @@ import * as OdooEditorLib from "@web_editor/js/editor/odoo-editor/src/OdooEditor
|
||||
import Widget from "web.Widget";
|
||||
import Wysiwyg from "web_editor.wysiwyg";
|
||||
import options from "web_editor.snippets.options";
|
||||
import { range } from "@web/core/utils/numbers";
|
||||
|
||||
const COLOR_PICKER_TEMPLATE = `
|
||||
<colorpicker>
|
||||
@@ -356,7 +357,7 @@ var keyboardMap = {
|
||||
"91": "OS_KEY", // 'left command': Windows Key (Windows) or Command Key (Mac)
|
||||
"93": "CONTEXT_MENU", // 'right command'
|
||||
};
|
||||
_.each(_.range(40, 127), function (keyCode) {
|
||||
_.each(range(40, 127), function (keyCode) {
|
||||
if (!keyboardMap[keyCode]) {
|
||||
keyboardMap[keyCode] = String.fromCharCode(keyCode);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { useService } from '@web/core/utils/hooks';
|
||||
import { uploadService, AUTOCLOSE_DELAY } from '@web_editor/components/upload_progress_toast/upload_service';
|
||||
|
||||
import { useState, Component } from "@odoo/owl";
|
||||
import { sprintf } from '@web/core/utils/strings';
|
||||
|
||||
class UnsplashCredentials extends Component {
|
||||
setup() {
|
||||
@@ -224,8 +225,8 @@ patch(uploadService, 'upload_service_unsplash', {
|
||||
const file = service.addFile({
|
||||
id: service.fileId,
|
||||
name: records.length > 1 ?
|
||||
_.str.sprintf(env._t("Uploading %s '%s' images."), records.length, records[0].query) :
|
||||
_.str.sprintf(env._t("Uploading '%s' image."), records[0].query),
|
||||
sprintf(env._t("Uploading %s '%s' images."), records.length, records[0].query) :
|
||||
sprintf(env._t("Uploading '%s' image."), records[0].query),
|
||||
size: null,
|
||||
progress: 0,
|
||||
});
|
||||
|
||||
@@ -36,7 +36,7 @@ export const WebsiteAceEditor = AceEditor.extend({
|
||||
// We need to find the new ID (either because the view became
|
||||
// specific or because its parent was edited too and the view
|
||||
// got copy/unlink).
|
||||
const selectedView = _.findWhere(this.views, {id: this._getSelectedResource()});
|
||||
const selectedView = Object.values(this.views).find(view => view.id === this._getSelectedResource());
|
||||
let context;
|
||||
this.trigger_up('context_get', {
|
||||
callback: (ctx) => {
|
||||
|
||||
@@ -55,7 +55,7 @@ var Dashboard = AbstractAction.extend({
|
||||
return Promise.all([loadBundle(this), this._super()]).then(function() {
|
||||
return self.fetch_data();
|
||||
}).then(function(){
|
||||
var website = _.findWhere(self.websites, {selected: true});
|
||||
var website = self.websites.find(w => w.selected);
|
||||
self.website_id = website ? website.id : false;
|
||||
});
|
||||
},
|
||||
@@ -102,7 +102,7 @@ var Dashboard = AbstractAction.extend({
|
||||
|
||||
on_go_to_website: function (ev) {
|
||||
ev.preventDefault();
|
||||
var website = _.findWhere(this.websites, {selected: true});
|
||||
var website = this.websites.find(website => website.selected);
|
||||
window.location.replace(`/web#action=website.website_preview&website_id=${website.id}`);
|
||||
},
|
||||
|
||||
|
||||
@@ -921,7 +921,7 @@ registry.socialShare = publicWidget.Widget.extend({
|
||||
'twitter': 'https://twitter.com/intent/tweet?original_referer=' + url + '&text=' + encodeURIComponent(title + hashtags + ' - ') + url,
|
||||
'linkedin': 'https://www.linkedin.com/sharing/share-offsite/?url=' + url,
|
||||
};
|
||||
if (!_.contains(_.keys(socialNetworks), social)) {
|
||||
if (!_.contains(Object.keys(socialNetworks), social)) {
|
||||
return;
|
||||
}
|
||||
var wHeight = 500;
|
||||
|
||||
@@ -177,7 +177,7 @@ export const WebsiteRoot = publicRootData.PublicRoot.extend(KeyboardNavigationMi
|
||||
url: encodeURIComponent($target.attr('href').replace(/[&?]edit_translations[^&?]+/, '')),
|
||||
hash: encodeURIComponent(window.location.hash)
|
||||
};
|
||||
window.location.href = _.str.sprintf("/website/lang/%(lang)s?r=%(url)s%(hash)s", redirect);
|
||||
window.location.href = `/website/lang/${redirect.lang}?r=${redirect.url}${redirect.hash}`;
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
|
||||
@@ -11,6 +11,7 @@ import wLinkPopoverWidget from "@website/js/widgets/link_popover_widget";
|
||||
import wUtils from "website.utils";
|
||||
import {isImageSupportedForStyle} from "web_editor.image_processing";
|
||||
import "website.s_popup_options";
|
||||
import { range } from "@web/core/utils/numbers";
|
||||
|
||||
var _t = core._t;
|
||||
var qweb = core.qweb;
|
||||
@@ -1387,7 +1388,7 @@ options.registry.OptionsTab = options.Class.extend({
|
||||
await this._super(...arguments);
|
||||
const extraSaturationRangeEl = uiFragment.querySelector(`we-range[data-param=${this.GRAY_PARAMS.EXTRA_SATURATION}]`);
|
||||
if (extraSaturationRangeEl) {
|
||||
const baseGrays = _.range(100, 1000, 100).map(id => {
|
||||
const baseGrays = range(100, 1000, 100).map(id => {
|
||||
const gray = weUtils.getCSSVariableValue(`base-${id}`);
|
||||
const grayRGB = ColorpickerWidget.convertCSSColorToRgba(gray);
|
||||
const hsl = ColorpickerWidget.convertRgbToHsl(grayRGB.red, grayRGB.green, grayRGB.blue);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import {_t} from "web.core";
|
||||
import {Markup} from "web.utils";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
function addMedia(position = "right") {
|
||||
return {
|
||||
@@ -104,7 +105,7 @@ function changeOption(optionName, weName = '', optionTooltipLabel = '', position
|
||||
const option_block = `${noPalette} we-customizeblock-option[class='snippet-option-${optionName}']`;
|
||||
return {
|
||||
trigger: `${option_block} ${weName}, ${option_block} [title='${weName}']`,
|
||||
content: Markup(_.str.sprintf(_t("<b>Click</b> on this option to change the %s of the block."), optionTooltipLabel)),
|
||||
content: Markup(sprintf(_t("<b>Click</b> on this option to change the %s of the block."), optionTooltipLabel)),
|
||||
position: position,
|
||||
run: "click",
|
||||
};
|
||||
@@ -115,7 +116,7 @@ function selectNested(trigger, optionName, alt_trigger = null, optionTooltipLabe
|
||||
const option_block = `${noPalette} we-customizeblock-option[class='snippet-option-${optionName}']`;
|
||||
return {
|
||||
trigger: trigger,
|
||||
content: Markup(_.str.sprintf(_t("<b>Select</b> a %s."), optionTooltipLabel)),
|
||||
content: Markup(sprintf(_t("<b>Select</b> a %s."), optionTooltipLabel)),
|
||||
alt_trigger: alt_trigger == null ? undefined : `${option_block} ${alt_trigger}`,
|
||||
position: position,
|
||||
run: 'click',
|
||||
@@ -132,7 +133,7 @@ function changePaddingSize(direction) {
|
||||
}
|
||||
return {
|
||||
trigger: `iframe .oe_overlay.ui-draggable.o_we_overlay_sticky.oe_active .o_handle.${paddingDirection}`,
|
||||
content: Markup(_.str.sprintf(_t("<b>Slide</b> this button to change the %s padding"), direction)),
|
||||
content: Markup(sprintf(_t("<b>Slide</b> this button to change the %s padding"), direction)),
|
||||
consumeEvent: 'mousedown',
|
||||
position: position,
|
||||
};
|
||||
@@ -229,7 +230,7 @@ function dragNDrop(snippet, position = "bottom") {
|
||||
return {
|
||||
trigger: `#oe_snippets .oe_snippet[name="${snippet.name}"] .oe_snippet_thumbnail:not(.o_we_already_dragging)`,
|
||||
extra_trigger: ".o_website_preview.editor_enable.editor_has_snippets",
|
||||
content: Markup(_.str.sprintf(_t("Drag the <b>%s</b> building block and drop it at the bottom of the page."), snippet.name)),
|
||||
content: Markup(sprintf(_t("Drag the <b>%s</b> building block and drop it at the bottom of the page."), snippet.name)),
|
||||
position: position,
|
||||
// Normally no main snippet can be dropped in the default footer but
|
||||
// targeting it allows to force "dropping at the end of the page".
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module alias=website.utils **/
|
||||
|
||||
import { intersection } from "@web/core/utils/arrays";
|
||||
import core from "web.core";
|
||||
|
||||
const { qweb, _t } = core;
|
||||
@@ -186,7 +187,7 @@ function prompt(options, _qweb) {
|
||||
btn_secondary_title: _t('Cancel'),
|
||||
}, options || {});
|
||||
|
||||
var type = _.intersection(Object.keys(options), ['input', 'textarea', 'select']);
|
||||
var type = intersection(Object.keys(options), ['input', 'textarea', 'select']);
|
||||
type = type.length ? type[0] : 'input';
|
||||
options.field_type = type;
|
||||
options.field_name = options.field_name || options[type];
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { pick } from "@web/core/utils/objects";
|
||||
import options from "web_editor.snippets.options";
|
||||
|
||||
options.registry.facebookPage = options.Class.extend({
|
||||
@@ -19,8 +20,7 @@ options.registry.facebookPage = options.Class.extend({
|
||||
small_header: true,
|
||||
hide_cover: true,
|
||||
};
|
||||
this.fbData = _.defaults(_.pick(this.$target[0].dataset, _.keys(defaults)), defaults);
|
||||
|
||||
this.fbData = Object.assign({}, defaults, pick(this.$target[0].dataset, Object.keys(defaults)), defaults);
|
||||
if (!this.fbData.href) {
|
||||
// Fetches the default url for facebook page from website config
|
||||
var self = this;
|
||||
|
||||
@@ -312,7 +312,7 @@ options.registry.gallery = options.Class.extend({
|
||||
this.mode('reset', this.getMode());
|
||||
} else if (name === 'image_index_request') {
|
||||
var imgs = this._getImages();
|
||||
var position = _.indexOf(imgs, data.$image[0]);
|
||||
var position = imgs.indexOf(data.$image[0]);
|
||||
imgs.splice(position, 1);
|
||||
switch (data.position) {
|
||||
case 'first':
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import publicWidget from "web.public.widget";
|
||||
import dom from "web.dom";
|
||||
import concurrency from "web.concurrency";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
var _t = core._t;
|
||||
var qweb = core.qweb;
|
||||
@@ -415,9 +416,7 @@
|
||||
// filter neither on required, nor on checkbox and
|
||||
// checking the validity of the group of checkbox is
|
||||
// currently done for each checkbox of that group...
|
||||
var checkboxes = _.filter(inputs, function (input) {
|
||||
return input.required && input.type === 'checkbox';
|
||||
});
|
||||
var checkboxes = inputs.filter(input => input.required && input.type === 'checkbox');
|
||||
return !_.any(checkboxes, checkbox => checkbox.checkValidity());
|
||||
|
||||
// Special cases for dates and datetimes
|
||||
@@ -493,13 +492,13 @@
|
||||
if (datetime.isValid()) {
|
||||
return time.datetime_to_str(datetime.toDate());
|
||||
}
|
||||
throw new Error(_.str.sprintf(_t("'%s' is not a correct datetime"), value));
|
||||
throw new Error(sprintf(_t("'%s' is not a correct datetime"), value));
|
||||
case 'date':
|
||||
var date = moment(value, [date_pattern, date_pattern_wo_zero], true);
|
||||
if (date.isValid()) {
|
||||
return time.date_to_str(date.toDate());
|
||||
}
|
||||
throw new Error(_.str.sprintf(_t("'%s' is not a correct date"), value));
|
||||
throw new Error(sprintf(_t("'%s' is not a correct date"), value));
|
||||
}
|
||||
return value;
|
||||
},
|
||||
|
||||
@@ -7,6 +7,7 @@ import Dialog from "web.Dialog";
|
||||
import dom from "web.dom";
|
||||
import {generateHTMLId} from "web_editor.utils";
|
||||
import "website.editor.snippets.options";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
const qweb = core.qweb;
|
||||
const _t = core._t;
|
||||
@@ -307,9 +308,9 @@ options.registry.WebsiteFormEditor = FormEditor.extend({
|
||||
model: 'ir.model',
|
||||
method: 'get_compatible_form_models',
|
||||
});
|
||||
|
||||
|
||||
const targetModelName = this.$target[0].dataset.model_name || 'mail.mail';
|
||||
this.activeForm = _.findWhere(this.models, {model: targetModelName});
|
||||
this.activeForm = this.models.find(m => m.model === targetModelName);
|
||||
// Create the Form Action select
|
||||
this.selectActionEl = document.createElement('we-select');
|
||||
this.selectActionEl.setAttribute('string', 'Action');
|
||||
@@ -708,7 +709,7 @@ options.registry.WebsiteFormEditor = FormEditor.extend({
|
||||
oldFormInfo = FormEditorRegistry.get(oldFormKey);
|
||||
}
|
||||
this.$target.find('.s_website_form_field').remove();
|
||||
this.activeForm = _.findWhere(this.models, {id: modelId});
|
||||
this.activeForm = this.models.find(model => model.id === modelId);
|
||||
}
|
||||
const formKey = this.activeForm.website_form_key;
|
||||
const formInfo = FormEditorRegistry.get(formKey);
|
||||
@@ -1293,7 +1294,7 @@ options.registry.WebsiteFieldEditor = FieldEditor.extend({
|
||||
const list = document.createElement('we-list');
|
||||
const optionText = select ? 'Option' : type === 'selection' ? 'Radio' : 'Checkbox';
|
||||
list.setAttribute('string', `${optionText} List`);
|
||||
list.dataset.addItemTitle = _.str.sprintf(_t("Add new %s"), optionText);
|
||||
list.dataset.addItemTitle = sprintf(_t("Add new %s"), optionText);
|
||||
list.dataset.renderListItems = '';
|
||||
|
||||
list.dataset.hasDefault = ['one2many', 'many2many'].includes(type) ? 'multiple' : 'unique';
|
||||
|
||||
@@ -203,14 +203,14 @@ export class NewContentModal extends Component {
|
||||
const {id, name} = this.modulesInfo[element.moduleName];
|
||||
const dialogProps = {
|
||||
title: element.title,
|
||||
installationText: _.str.sprintf(this.newContentText.installNeeded, name),
|
||||
installationText: sprintf(this.newContentText.installNeeded, name),
|
||||
installModule: async () => {
|
||||
// Update the NewContentElement with installing icon and text.
|
||||
this.state.newContentElements = this.state.newContentElements.map(el => {
|
||||
if (el.moduleXmlId === element.moduleXmlId) {
|
||||
el.status = MODULE_STATUS.INSTALLING;
|
||||
el.icon = xml`<i class="fa fa-spin fa-circle-o-notch"/>`;
|
||||
el.title = _.str.sprintf(this.newContentText.installPleaseWait, name);
|
||||
el.title = sprintf(this.newContentText.installPleaseWait, name);
|
||||
}
|
||||
return el;
|
||||
});
|
||||
@@ -226,7 +226,7 @@ export class NewContentModal extends Component {
|
||||
if (el.moduleXmlId === element.moduleXmlId) {
|
||||
el.status = MODULE_STATUS.FAILED_TO_INSTALL;
|
||||
el.icon = xml`<i class="fa fa-exclamation-triangle"/>`;
|
||||
el.title = _.str.sprintf(this.newContentText.failed, name);
|
||||
el.title = sprintf(this.newContentText.failed, name);
|
||||
}
|
||||
return el;
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import dom from "web.dom";
|
||||
|
||||
$.fn.share = function (options) {
|
||||
@@ -32,8 +33,8 @@ $.fn.share = function (options) {
|
||||
// Note: all (non-localhost) urls in a tweet have 23 characters https://support.twitter.com/articles/78124
|
||||
var selectedText = this.getSelection('string').substring(0, option.maxLength - baseLength - 23);
|
||||
|
||||
var text = window.btoa(encodeURIComponent(_.str.sprintf(tweet, selectedText, window.location.href)));
|
||||
$popover_content.append(_.str.sprintf(
|
||||
var text = window.btoa(encodeURIComponent(sprintf(tweet, selectedText, window.location.href)));
|
||||
$popover_content.append(sprintf(
|
||||
"<a onclick=\"window.open('%s' + atob('%s'), '_%s','location=yes,height=570,width=520,scrollbars=yes,status=yes')\"><i class=\"ml4 mr4 fa fa-twitter fa-lg\"/></a>",
|
||||
option.shareLink, text, option.target));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import {_t} from "web.core";
|
||||
import publicWidget from "web.public.widget";
|
||||
import time from "web.time";
|
||||
@@ -238,7 +239,7 @@ publicWidget.registry.crmPartnerAssign = publicWidget.Widget.extend({
|
||||
const contactName = ev.currentTarget.value.trim();
|
||||
let titleEl = this.el.querySelector('.title');
|
||||
if (!titleEl.value.trim()) {
|
||||
titleEl.value = contactName ? _.str.sprintf(_t("%s's Opportunity"), contactName) : '';
|
||||
titleEl.value = contactName ? sprintf(_t("%s's Opportunity"), contactName) : '';
|
||||
}
|
||||
},
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module alias=website_event_track.website_event_track_reminder **/
|
||||
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import core from "web.core";
|
||||
var _t = core._t;
|
||||
import publicWidget from "web.public.widget";
|
||||
@@ -49,7 +50,7 @@ publicWidget.registry.websiteEventTrackReminder = publicWidget.Widget.extend({
|
||||
self.displayNotification({
|
||||
type: 'info',
|
||||
title: _t('Error'),
|
||||
message: _.str.sprintf(_t('Talk already in your Favorites')),
|
||||
message: sprintf(_t('Talk already in your Favorites')),
|
||||
});
|
||||
} else {
|
||||
self.reminderOn = reminderOnValue;
|
||||
|
||||
@@ -63,9 +63,7 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({
|
||||
maximumSelectionSize: 5,
|
||||
lastsearch: [],
|
||||
createSearchChoice: function (term) {
|
||||
if (_.filter(self.lastsearch, function (s) {
|
||||
return s.text.localeCompare(term) === 0;
|
||||
}).length === 0) {
|
||||
if (self.lastsearch.filter(s => s.text.localeCompare(term) === 0).length === 0) {
|
||||
//check Karma
|
||||
if (parseInt($('#karma').val()) >= parseInt($('#karma_edit_retag').val())) {
|
||||
return {
|
||||
|
||||
@@ -52,7 +52,7 @@ var SelectBox = publicWidget.Widget.extend({
|
||||
if (self._objectExists(term)) {
|
||||
return null;
|
||||
}
|
||||
return {id: term, text: _.str.sprintf("Create '%s'", term)};
|
||||
return { id: term, text: `Create '${term}'` };
|
||||
},
|
||||
createSearchChoicePosition: 'bottom',
|
||||
multiple: false,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import core, { _t } from 'web.core';
|
||||
import checkoutForm from 'payment.checkout_form';
|
||||
import { sprintf } from '@web/core/utils/strings';
|
||||
|
||||
checkoutForm.include({
|
||||
events: Object.assign({}, checkoutForm.prototype.events || {}, {
|
||||
@@ -45,7 +46,7 @@ checkoutForm.include({
|
||||
const $field = this.$('input[name="' + id + '"],select[name="' + id + '"]');
|
||||
$field.removeClass('is-invalid').popover('dispose');
|
||||
if (!$field.val().trim()) {
|
||||
errorFields[id] = _.str.sprintf(_t("Field '%s' is mandatory"), mandatoryFields[id]);
|
||||
errorFields[id] = sprintf(_t("Field '%s' is mandatory"), mandatoryFields[id]);
|
||||
}
|
||||
}
|
||||
if (Object.keys(errorFields).length) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { sprintf } from '@web/core/utils/strings';
|
||||
import {_t} from 'web.core';
|
||||
import publicWidget from 'web.public.widget';
|
||||
|
||||
@@ -126,7 +127,7 @@ publicWidget.registry.DonationSnippet = publicWidget.Widget.extend({
|
||||
} else if (amount < parseFloat(minAmount)) {
|
||||
const before = this.currency.position === "before" ? this.currency.symbol : "";
|
||||
const after = this.currency.position === "after" ? this.currency.symbol : "";
|
||||
errorMessage = _.str.sprintf(_t("The minimum donation amount is %s%s%s"), before, minAmount, after);
|
||||
errorMessage = sprintf(_t("The minimum donation amount is %s%s%s"), before, minAmount, after);
|
||||
}
|
||||
if (errorMessage) {
|
||||
$(ev.currentTarget).before($('<p>', {
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
import { registry } from "@web/core/registry";
|
||||
import "website_sale.tour";
|
||||
|
||||
var addCartStepIndex = _.findIndex(registry.category("web_tour.tours").get("shop_buy_product").steps, function (step) {
|
||||
return (step.id === 'add_cart_step');
|
||||
});
|
||||
var addCartStepIndex = registry.category("web_tour.tours").get("shop_buy_product").steps.findIndex(step => step.id === 'add_cart_step');
|
||||
|
||||
registry.category("web_tour.tours").get("shop_buy_product").steps.splice(addCartStepIndex + 1, 1, {
|
||||
content: "click in modal on 'Proceed to checkout' button",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { _t } from 'web.core';
|
||||
import { PortalChatter } from 'portal.chatter';
|
||||
import { sprintf } from '@web/core/utils/strings';
|
||||
|
||||
/**
|
||||
* PortalChatter
|
||||
@@ -18,7 +19,7 @@ PortalChatter.include({
|
||||
_reloadChatterContent: async function (data) {
|
||||
await this._super(...arguments);
|
||||
if (this.options.res_model === "slide.channel") {
|
||||
$('#review-tab').text(_.str.sprintf(_t('Reviews (%d)'), data.rating_count));
|
||||
$('#review-tab').text(sprintf(_t('Reviews (%d)'), data.rating_count));
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -288,7 +288,7 @@
|
||||
*/
|
||||
_getCurrentIndex: function () {
|
||||
var slide = this.get('slideEntry');
|
||||
var currentIndex = _.findIndex(this.slideEntries, function (entry) {
|
||||
var currentIndex = this.slideEntries.findIndex(entry =>{
|
||||
return entry.id === slide.id && entry.isQuiz === slide.isQuiz;
|
||||
});
|
||||
return currentIndex;
|
||||
@@ -609,11 +609,11 @@
|
||||
} else if (slideData.category === 'video' && slideData.videoSourceType === 'vimeo') {
|
||||
slideData.embedCode = Markup(slideData.embedCode);
|
||||
} else if (slideData.category === 'infographic') {
|
||||
slideData.embedUrl = _.str.sprintf('/web/image/slide.slide/%s/image_1024', slideData.id);
|
||||
slideData.embedUrl = `/web/image/slide.slide/${slideData.id}/image_1024`;
|
||||
} else if (slideData.category === 'document') {
|
||||
slideData.embedUrl = $(slideData.embedCode).attr('src');
|
||||
}
|
||||
// fill empty property to allow searching on it with _.filter(list, matcher)
|
||||
// fill empty property to allow searching on it with list.filter(matcher)
|
||||
slideData.isQuiz = !!slideData.isQuiz;
|
||||
slideData.hasQuestion = !!slideData.hasQuestion;
|
||||
// technical settings for the Fullscreen to work
|
||||
@@ -644,7 +644,7 @@
|
||||
if (this.get('slide').isQuiz){
|
||||
params.quiz = 1;
|
||||
}
|
||||
var fullscreenUrl = _.str.sprintf('%s?%s', url, $.param(params));
|
||||
var fullscreenUrl = `${url}?${$.param(params)}`;
|
||||
history.pushState(null, '', fullscreenUrl);
|
||||
},
|
||||
/**
|
||||
@@ -755,8 +755,7 @@
|
||||
_toggleSlideCompleted: async function (slide, completed = true) {
|
||||
await this._super(...arguments);
|
||||
|
||||
const slideMatch = _.matcher({id: slide.id});
|
||||
const fsSlides = _.filter(this.slides, slideMatch);
|
||||
const fsSlides = this.slides.filter(_slide => _slide.id === slide.id);
|
||||
|
||||
fsSlides.forEach(slide => slide.completed = completed);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { sprintf } from '@web/core/utils/strings';
|
||||
import { _t } from 'web.core';
|
||||
import Dialog from 'web.Dialog';
|
||||
import publicWidget from 'web.public.widget';
|
||||
@@ -111,7 +112,7 @@ var TagCourseDialog = Dialog.extend({
|
||||
},
|
||||
createSearchChoice: function (term, data) {
|
||||
var addedTags = $(this.opts.element).select2('data');
|
||||
if (_.filter(_.union(addedTags, data), function (tag) {
|
||||
if (addedTags.concat(data).filter(tag => {
|
||||
return tag.text.toLowerCase().localeCompare(term.toLowerCase()) === 0;
|
||||
}).length === 0) {
|
||||
if (this.opts.can_create) {
|
||||
@@ -119,7 +120,7 @@ var TagCourseDialog = Dialog.extend({
|
||||
id: _.uniqueId('tag_'),
|
||||
create: true,
|
||||
tag: term,
|
||||
text: _.str.sprintf(_t("Create new %s '%s'"), tag, term),
|
||||
text: sprintf(_t("Create new %s '%s'"), tag, term),
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { sprintf } from '@web/core/utils/strings';
|
||||
import {_t, qweb as QWeb} from 'web.core';
|
||||
import Dialog from 'web.Dialog';
|
||||
import publicWidget from 'web.public.widget';
|
||||
@@ -293,7 +294,7 @@ var SlideUploadDialog = Dialog.extend({
|
||||
},
|
||||
createSearchChoice: function (term, data) {
|
||||
var addedTags = $(this.opts.element).select2('data');
|
||||
if (_.filter(_.union(addedTags, data), function (tag) {
|
||||
if (addedTags.concat(data).filter(tag => {
|
||||
return tag.text.toLowerCase().localeCompare(term.toLowerCase()) === 0;
|
||||
}).length === 0) {
|
||||
if (this.opts.can_create) {
|
||||
@@ -301,7 +302,7 @@ var SlideUploadDialog = Dialog.extend({
|
||||
id: _.uniqueId('tag_'),
|
||||
create: true,
|
||||
tag: term,
|
||||
text: _.str.sprintf(_t("Create new %s '%s'"), tag, term),
|
||||
text: sprintf(_t("Create new %s '%s'"), tag, term),
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
@@ -650,23 +651,23 @@ var SlideUploadDialog = Dialog.extend({
|
||||
this.set('state', '_import');
|
||||
if (this.modulesToInstallStatus.installing) {
|
||||
this.$('#o_wslides_install_module_text')
|
||||
.text(_.str.sprintf(_t('Already installing "%s".'), this.modulesToInstallStatus.name));
|
||||
.text(sprintf(_t('Already installing "%s".'), this.modulesToInstallStatus.name));
|
||||
} else if (this.modulesToInstallStatus.failed) {
|
||||
this.$('#o_wslides_install_module_text')
|
||||
.text(_.str.sprintf(_t('Failed to install "%s".'), this.modulesToInstallStatus.name));
|
||||
.text(sprintf(_t('Failed to install "%s".'), this.modulesToInstallStatus.name));
|
||||
}
|
||||
} else {
|
||||
this.modulesToInstallStatus = Object.assign({}, this.modulesToInstall.find( function (item) { return item.id === moduleId; }));
|
||||
this.set('state', '_import');
|
||||
this.$('#o_wslides_install_module_text')
|
||||
.text(_.str.sprintf(_t('Do you want to install the "%s" app?'), this.modulesToInstallStatus.name));
|
||||
.text(sprintf(_t('Do you want to install the "%s" app?'), this.modulesToInstallStatus.name));
|
||||
}
|
||||
},
|
||||
|
||||
_onClickInstallModuleConfirm: function () {
|
||||
var self = this;
|
||||
var $el = this.$('#o_wslides_install_module_text');
|
||||
$el.text(_.str.sprintf(_t('Installing "%s".'), this.modulesToInstallStatus.name));
|
||||
$el.text(sprintf(_t('Installing "%s".'), this.modulesToInstallStatus.name));
|
||||
this.modulesToInstallStatus.installing = true;
|
||||
this._resetModalButton();
|
||||
this._rpc({
|
||||
@@ -681,7 +682,7 @@ var SlideUploadDialog = Dialog.extend({
|
||||
}
|
||||
window.location.href = redirectUrl;
|
||||
}, function () {
|
||||
$el.text(_.str.sprintf(_t('Failed to install "%s".'), self.modulesToInstallStatus.name));
|
||||
$el.text(sprintf(_t('Failed to install "%s".'), self.modulesToInstallStatus.name));
|
||||
self.modulesToInstallStatus.installing = false;
|
||||
self.modulesToInstallStatus.failed = true;
|
||||
self._resetModalButton();
|
||||
|
||||
Reference in New Issue
Block a user