mirror of
https://gitlab.com/flectra-hq/flectra.git
synced 2025-02-25 18:55:21 -06:00
[PATCH] Upstream patch - 28062023
This commit is contained in:
@@ -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, {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user