[PATCH] Upstream patch - 28062023

This commit is contained in:
Parthiv Patel
2023-06-28 08:34:50 +00:00
parent 7d49809c13
commit 0e4b1a5afe
6 changed files with 145 additions and 11 deletions

View File

@@ -663,7 +663,7 @@
<field name="amount_type">percent</field>
<field name="sequence" eval="0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="type_tax_use">none</field>
<field name="active" eval="False"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {

View File

@@ -776,7 +776,7 @@
<field name="amount_type">percent</field>
<field name="sequence" eval="0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="type_tax_use">none</field>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,

View File

@@ -802,17 +802,22 @@ var DateTimePicker = function ($, moment) {
//public
DateTimePicker.prototype.getMoment = function getMoment(d) {
DateTimePicker.prototype.getMoment = function getMoment(d, f) { // FLECTRA FIX: give optional format
var returnMoment = void 0;
// FLECTRA FIX: default to original `parseFormats` attribute
if (!f) {
f = this.parseFormats;
}
if (d === undefined || d === null) {
returnMoment = moment(); //TODO should this use format? and locale?
} else if (this._hasTimeZone()) {
// There is a string to parse and a default time zone
// parse with the tz function which takes a default time zone if it is not in the format string
returnMoment = moment.tz(d, this.parseFormats, this._options.locale, this._options.useStrict, this._options.timeZone);
returnMoment = moment.tz(d, f, this._options.locale, this._options.useStrict, this._options.timeZone); // FLECTRA FIX: use format argument
} else {
returnMoment = moment(d, this.parseFormats, this._options.locale, this._options.useStrict);
returnMoment = moment(d, f, this._options.locale, this._options.useStrict); // FLECTRA FIX: use format argument
}
if (this._hasTimeZone()) {
@@ -2434,7 +2439,7 @@ var TempusDominusBootstrap4 = function ($) {
break;
case 'selectHour':
{
var hour = parseInt($(e.target).text(), 10);
var hour = this.getMoment($(e.target).text(), this.use24Hours ? 'HH' : 'hh').hour(); // FLECTRA FIX: use moment format to get the proper value (not necessarily latn numbers)
if (!this.use24Hours) {
if (lastPicked.hours() >= 12) {
@@ -2456,7 +2461,7 @@ var TempusDominusBootstrap4 = function ($) {
break;
}
case 'selectMinute':
this._setValue(lastPicked.clone().minutes(parseInt($(e.target).text(), 10)), this._getLastPickedDateIndex());
this._setValue(lastPicked.clone().minutes(this.getMoment($(e.target).text(), 'mm').minute()), this._getLastPickedDateIndex()); // FLECTRA FIX: use moment format to get the proper value (not necessarily latn numbers)
if (!this._isEnabled('a') && !this._isEnabled('s') && !this._options.keepOpen && !this._options.inline) {
this.hide();
} else {
@@ -2464,7 +2469,7 @@ var TempusDominusBootstrap4 = function ($) {
}
break;
case 'selectSecond':
this._setValue(lastPicked.clone().seconds(parseInt($(e.target).text(), 10)), this._getLastPickedDateIndex());
this._setValue(lastPicked.clone().seconds(this.getMoment($(e.target).text(), 'ss').second()), this._getLastPickedDateIndex()); // FLECTRA FIX: use moment format to get the proper value (not necessarily latn numbers)
if (!this._isEnabled('a') && !this._options.keepOpen && !this._options.inline) {
this.hide();
} else {

View File

@@ -4886,6 +4886,75 @@ QUnit.module('basic_fields', {
form.destroy();
});
QUnit.test("datetime field: use picker with arabic numbering system", async function (assert) {
assert.expect(2);
const symbols = [
["1", "١"],
["2", "٢"],
["3", "٣"],
["4", "٤"],
["5", "٥"],
["6", "٦"],
["7", "٧"],
["8", "٨"],
["9", "٩"],
["0", "٠"],
];
const symbolMap = Object.fromEntries(symbols);
const numberMap = Object.fromEntries(symbols.map(([latn, arab]) => [arab, latn]));
const originalLocale = moment.locale();
moment.defineLocale("TEST_ar", {
preparse:
(string) => string
.replace(/\u200f/g, "")
.replace(/[١٢٣٤٥٦٧٨٩٠]/g, (match) => numberMap[match])
.replace(/،/g, ","),
postformat:
(string) => string
.replace(/\d/g, (match) => symbolMap[match])
.replace(/,/g, "،"),
});
const form = await createView({
View: FormView,
model: "partner",
data: this.data,
arch: /* xml */ `
<form string="Partners">
<field name="datetime" />
</form>
`,
res_id: 1,
viewOptions: {
mode: "edit",
},
});
const getInput = () => form.el.querySelector("[name=datetime] input")
const click = (el) => testUtils.dom.click($(el));
assert.strictEqual(getInput().value, "٠٢/٠٨/٢٠١٧ ١٠:٠٠:٠٠");
await click(getInput());
await click(document.querySelector("[data-action=togglePicker]"));
await click(document.querySelector("[data-action=showMinutes]"));
await click(document.querySelectorAll("[data-action=selectMinute]")[9]);
await click(document.querySelector("[data-action=showSeconds]"));
await click(document.querySelectorAll("[data-action=selectSecond]")[3]);
assert.strictEqual(getInput().value, "٠٢/٠٨/٢٠١٧ ١٠:٤٥:١٥");
moment.locale(originalLocale);
moment.updateLocale("TEST_ar", null);
form.destroy();
})
QUnit.module('RemainingDays');
QUnit.test('remaining_days widget on a date field in list view', async function (assert) {

View File

@@ -32,12 +32,15 @@ class Website(models.Model):
def _compute_app_icon(self):
""" Computes a squared image based on the favicon to be used as mobile webapp icon.
App Icon should be in PNG format and size of at least 512x512.
If the favicon is an SVG image, it will be skipped and the app_icon will be set to False.
"""
for website in self:
if not website.favicon:
image = ImageProcess(website.favicon) if website.favicon else None
if not (image and image.image):
website.app_icon = False
continue
image = ImageProcess(website.favicon)
w, h = image.image.size
square_size = w if w > h else h
image.crop_resize(square_size, square_size)

View File

@@ -3,7 +3,10 @@
from flectra.tests import tagged
from flectra.tests.common import TransactionCase
from flectra import tools
from io import BytesIO
from PIL import Image
import base64
@tagged('post_install','-at_install')
class TestWebsite(TransactionCase):
@@ -19,3 +22,57 @@ class TestWebsite(TransactionCase):
self.assertEqual(website2.events_app_name, 'Foo Events')
website2.write({'name': 'Bar'})
self.assertEqual(website2.events_app_name, 'Foo Events')
def test_compute_app_icon(self):
# Generate image data for JPEG
jpeg_image = Image.new('RGB', (60, 30), color=(73, 109, 137))
jpeg_io = BytesIO()
jpeg_image.save(jpeg_io, format='JPEG')
jpeg_image_data = jpeg_io.getvalue()
# Generate image data for JPG
jpg_image = Image.new('RGB', (60, 30), color=(73, 109, 137))
jpg_io = BytesIO()
jpg_image.save(jpg_io, format='JPEG')
jpg_image_data = jpg_io.getvalue()
# Generate image data for PNG
png_image = Image.new('RGB', (60, 30), color=(73, 109, 137))
png_io = BytesIO()
png_image.save(png_io, format='PNG')
png_image_data = png_io.getvalue()
# Generate image data for SVG
svg_image_data = b"""<svg xmlns="http://www.w3.org/2000/svg" width="60" height="30" version="1.1">
<rect width="100%" height="100%" fill="rgb(73, 109, 137)"/>
</svg>
"""
# Image data and their respective expected types
image_data = {
'png': png_image_data,
'jpg': jpg_image_data,
'jpeg': jpeg_image_data,
'svg': svg_image_data
}
for expected_type, image_data in image_data.items():
# Create a website record
website = self.env['website'].create({
'name': 'Test Website',
'favicon': base64.b64encode(image_data)
})
# Call the method to compute app_icon
website._compute_app_icon()
if expected_type in ['jpeg', 'png', 'jpg']:
# Check if app_icon is set
self.assertTrue(website.app_icon)
# Check if app_icon is a valid image
image = tools.base64_to_image(website.app_icon)
self.assertEqual(image.format.lower(), 'png')
else:
# For SVG images, ensure that the app_icon is not set
self.assertFalse(website.app_icon)