[PATCH] Upstream patch - 18012022

This commit is contained in:
Parthiv Patel committed 2022-01-18 15:56:27 +00:00
1 parent a6d4ddf2ea
commit 02e4797361
290 files changed
+4422 -1070

No files matched your search

+15 -8
View File
@@ -128,9 +128,8 @@ def redirect_with_hash(*args, **kw):
return http.redirect_with_hash(*args, **kw)
def abort_and_redirect(url):
r = request.httprequest
response = werkzeug.utils.redirect(url, 302)
response = r.app.get_response(r, response, explicit_session=False)
response = http.root.get_response(request.httprequest, response, explicit_session=False)
werkzeug.exceptions.abort(response)
def ensure_db(redirect='/web/database/selector'):
@@ -647,6 +646,10 @@ class HomeStaticTemplateHelpers(object):
def get_qweb_templates(cls, addons, db=None, debug=False):
return cls(addons, db, debug=debug)._get_qweb_templates()[0]
# Shared parameters for all login/signup flows
SIGN_UP_REQUEST_PARAMS = {'db', 'login', 'debug', 'token', 'message', 'error', 'scope', 'mode',
'redirect', 'redirect_hostname', 'email', 'name', 'partner_id',
'password', 'confirm_password', 'city', 'country_id', 'lang'}
class GroupsTreeNode:
"""
@@ -934,7 +937,7 @@ class Home(http.Controller):
if not request.uid:
request.uid = flectra.SUPERUSER_ID
values = request.params.copy()
values = {k: v for k, v in request.params.items() if k in SIGN_UP_REQUEST_PARAMS}
try:
values['databases'] = http.db_list()
except flectra.exceptions.AccessDenied:
@@ -1102,7 +1105,7 @@ class Proxy(http.Controller):
from werkzeug.wrappers import BaseResponse
base_url = request.httprequest.base_url
query_string = request.httprequest.query_string
client = Client(request.httprequest.app, BaseResponse)
client = Client(http.root, BaseResponse)
headers = {'X-Openerp-Session-Id': request.session.sid}
return client.post('/' + path, base_url=base_url, query_string=query_string,
headers=headers, data=data)
@@ -2067,9 +2070,10 @@ class ReportController(http.Controller):
# Misc. route utils
#------------------------------------------------------
@http.route(['/report/barcode', '/report/barcode/<type>/<path:value>'], type='http', auth="public")
def report_barcode(self, type, value, width=600, height=100, humanreadable=0, quiet=1, mask=None):
def report_barcode(self, type, value, **kwargs):
"""Contoller able to render barcode images thanks to reportlab.
Samples:
Samples::
<img t-att-src="'/report/barcode/QR/%s' % o.name"/>
<img t-att-src="'/report/barcode/?type=%s&amp;value=%s&amp;width=%s&amp;height=%s' %
('QR', o.name, 200, 200)"/>
@@ -2077,6 +2081,8 @@ class ReportController(http.Controller):
:param type: Accepted types: 'Codabar', 'Code11', 'Code128', 'EAN13', 'EAN8', 'Extended39',
'Extended93', 'FIM', 'I2of5', 'MSI', 'POSTNET', 'QR', 'Standard39', 'Standard93',
'UPCA', 'USPS_4State'
:param width: Pixel width of the barcode
:param height: Pixel height of the barcode
:param humanreadable: Accepted values: 0 (default) or 1. 1 will insert the readable value
at the bottom of the output image
:param quiet: Accepted values: 0 (default) or 1. 1 will display white
@@ -2084,10 +2090,11 @@ class ReportController(http.Controller):
:param mask: The mask code to be used when rendering this QR-code.
Masks allow adding elements on top of the generated image,
such as the Swiss cross in the center of QR-bill codes.
:param barLevel: QR code Error Correction Levels. Default is 'L'.
ref: https://hg.reportlab.com/hg-public/reportlab/file/830157489e00/src/reportlab/graphics/barcode/qr.py#l101
"""
try:
barcode = request.env['ir.actions.report'].barcode(type, value, width=width,
height=height, humanreadable=humanreadable, quiet=quiet, mask=mask)
barcode = request.env['ir.actions.report'].barcode(type, value, **kwargs)
except (ValueError, AttributeError):
raise werkzeug.exceptions.HTTPException(description='Cannot convert into barcode.')
+37 -6
View File
@@ -359,6 +359,7 @@
* the list of variables so it does not get replaced by a lookup in the context
*/
function compileExprToArray(expr, scope) {
const localVars = new Set();
scope = Object.create(scope);
const tokens = tokenize(expr);
let i = 0;
@@ -407,12 +408,14 @@
if (tokens[j].type === "SYMBOL" && tokens[j].originalValue) {
tokens[j].value = tokens[j].originalValue;
scope[tokens[j].value] = { id: tokens[j].value, expr: tokens[j].value };
localVars.add(tokens[j].value);
}
j--;
}
}
else {
scope[token.value] = { id: token.value, expr: token.value };
localVars.add(token.value);
}
}
if (isVar) {
@@ -427,6 +430,13 @@
}
i++;
}
// Mark all variables that have been used locally.
// This assumes the expression has only one scope (incorrect but "good enough for now")
for (const token of tokens) {
if (token.type === "SYMBOL" && localVars.has(token.value)) {
token.isLocal = true;
}
}
return tokens;
}
function compileExpr(expr, scope) {
@@ -577,8 +587,24 @@
const tokens = compileExprToArray(expr, this.variables);
const done = new Set();
return tokens
.map((tok) => {
if (tok.varName) {
.map((tok, i) => {
// "this" in captured expressions should be the current component
if (tok.value === "this") {
if (!done.has("this")) {
done.add("this");
this.addLine(`const this_${argId} = utils.getComponent(context);`);
}
tok.value = `this_${argId}`;
}
// Variables that should be looked up in the scope. isLocal is for arrow
// function arguments that should stay untouched (eg "ev => ev" should
// not become "const ev_1 = scope['ev']; ev_1 => ev_1")
if (tok.varName &&
!tok.isLocal &&
// HACK: for backwards compatibility, we don't capture bare methods
// this allows them to be called with the rendering context/scope
// as their this value.
(!tokens[i + 1] || tokens[i + 1].type !== "LEFT_PAREN")) {
if (!done.has(tok.varName)) {
done.add(tok.varName);
this.addLine(`const ${tok.varName}_${argId} = ${tok.value};`);
@@ -3176,7 +3202,12 @@ See https://github.com/flectra/owl/blob/master/doc/reference/config.md#mode for
else if (!name.startsWith("t-")) {
if (name !== "class" && name !== "style") {
// this is a prop!
props[name] = ctx.formatExpression(value) || "undefined";
if (value.includes("=>")) {
props[name] = ctx.captureExpression(value);
}
else {
props[name] = ctx.formatExpression(value) || "undefined";
}
}
}
}
@@ -5546,9 +5577,9 @@ See https://github.com/flectra/owl/blob/master/doc/reference/config.md#mode for
Object.defineProperty(exports, '__esModule', { value: true });
__info__.version = '1.4.8';
__info__.date = '2021-11-03T12:45:36.455Z';
__info__.hash = '307b936';
__info__.version = '1.4.10';
__info__.date = '2021-12-07T14:32:29.551Z';
__info__.hash = 'bc04f72';
__info__.url = 'https://github.com/flectra/owl';
Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

@@ -3083,7 +3083,7 @@ var JournalDashboardGraph = AbstractField.extend({
var labels = this.data[0].values.map(function (pt) {
return pt.x;
});
var borderColor = this.data[0].is_sample_data ? '#dddddd' : '#2496f6';
var borderColor = this.data[0].is_sample_data ? '#dddddd' : '#009EFB';
var backgroundColor = this.data[0].is_sample_data ? '#ebebeb' : '#dcd0d9';
return {
type: 'line',
@@ -432,8 +432,9 @@ DebugManager.include({
var self = this;
var dialog = new Dialog(this, { title: _t("Fields View Get") });
dialog.opened().then(function () {
const arch = self._controller.renderer.arch || self._controller.renderer.props.arch;
$('<pre>').text(utils.json_node_to_xml(
self._controller.renderer.arch, true)
arch, true)
).appendTo(dialog.$el);
});
dialog.open();
@@ -1014,6 +1014,7 @@ var BasicModel = AbstractModel.extend({
var params = {
model: modelName,
ids: resIDs,
context: data.getContext(),
};
if (options.offset) {
params.offset = options.offset;
@@ -1037,6 +1038,7 @@ var BasicModel = AbstractModel.extend({
model: modelName,
method: 'read',
args: [resIDs, [field]],
context: data.getContext(),
}).then(function (records) {
if (data.data.length) {
var dataType = self.localData[data.data[0]].type;
@@ -5123,6 +5125,7 @@ var BasicModel = AbstractModel.extend({
var fieldsInfo = view ? view.fieldsInfo : fieldInfo.fieldsInfo;
var fields = view ? view.fields : fieldInfo.relatedFields;
var viewType = view ? view.type : fieldInfo.viewType;
var id2Values = new Map(values.map((value) => [value.id, value]))
_.each(records, function (record) {
var x2mList = self.localData[record.data[fieldName]];
@@ -5130,7 +5133,7 @@ var BasicModel = AbstractModel.extend({
_.each(x2mList.res_ids, function (res_id) {
var dataPoint = self._makeDataPoint({
modelName: field.relation,
data: _.findWhere(values, {id: res_id}),
data: id2Values.get(res_id),
fields: fields,
fieldsInfo: fieldsInfo,
parentID: x2mList.id,
@@ -49,6 +49,9 @@ var FORMAT_OPTIONS = {
var NO_DATA = [_t('No data')];
NO_DATA.isNoData = true;
var FAKE_DATA = [""];
FAKE_DATA.isFakeData = true;
// hide top legend when too many items for device size
var MAX_LEGEND_LENGTH = 4 * (Math.max(1, config.device.size_class));
@@ -720,7 +723,7 @@ return AbstractRenderer.extend({
* @returns {string}
*/
_relabelling: function (label, originIndex) {
if (label.isNoData) {
if (label.isNoData || label.isFakeData) {
return label[0];
}
var i = this.state.comparisonFieldIndex;
@@ -873,7 +876,7 @@ return AbstractRenderer.extend({
dataset.pointBackgroundColor = dataset.borderColor;
dataset.pointBorderColor = 'rgba(0,0,0,0.2)';
});
if (data.datasets.length === 1) {
if (data.datasets.length === 1 && data.datasets[0].originIndex === 0) {
const dataset = data.datasets[0];
dataset.fill = 'origin';
dataset.backgroundColor = hexToRGBA(COLORS[0], 0.4);
@@ -882,7 +885,7 @@ return AbstractRenderer.extend({
// center the points in the chart (without that code they are put on the left and the graph seems empty)
data.labels = data.labels.length > 1 ?
data.labels :
Array.prototype.concat.apply([], [[['']], data.labels, [['']]]);
Array.prototype.concat.apply([], [[FAKE_DATA], data.labels, [FAKE_DATA]]);
// prepare options
var options = this._prepareOptions(data.datasets.length);
@@ -219,6 +219,10 @@
}
}
}
.oe_kanban_content {
overflow-wrap: break-word;
}
}
// ------- Compatibility of old (<= v10) Generic layouts -------
+10
View File
@@ -169,6 +169,16 @@
-moz-transform: scale(0.9999); // Smooth the caret on firefox
}
//-------------------------------------------------------------------
// Cursor
//-------------------------------------------------------------------
@mixin o-grab-cursor() {
// Use a custom cursor for the open hand icon as "grab" is not properly
// working on Chrome Linux (at least)
cursor: url(/web/static/src/img/openhand.cur), grab;
}
// ------------------------------------------------------------------
// Hovering effects
// ------------------------------------------------------------------
+3 -3
View File
@@ -1540,7 +1540,7 @@
<t t-set="fileupload_action" t-translation="off">/web/binary/upload_attachment</t>
<t t-set="multi_upload" t-value="true"/>
<input type="hidden" name="model" t-att-value="widget.model"/>
<input type="hidden" name="id" value="0"/>
<input type="hidden" name="id" t-att-value="widget.res_id or 0"/>
</t>
</div>
</div>
@@ -1738,7 +1738,7 @@
<a role="menuitem" href="#" data-menu="support" class="dropdown-item">Support</a>
<div role="separator" class="dropdown-divider"/>
<a role="menuitem" href="#" data-menu="settings" class="dropdown-item">Preferences</a>
<a role="menuitem" href="#" data-menu="account" class="dropdown-item">My flectrahq.com account</a>
<a role="menuitem" href="#" data-menu="account" class="dropdown-item">My Flectrahq.com account</a>
<a role="menuitem" href="#" data-menu="logout" class="dropdown-item">Log out</a>
</t>
@@ -1858,7 +1858,7 @@
<t t-name="web.IframeWrapper">
<div class="o_preview_iframe_wrapper">
<i class="o_iframe_wrapper_spinner fa fa-spinner fa-spin fa-4x" style="color: #2496f6; z-index: 2"/>
<i class="o_iframe_wrapper_spinner fa fa-spinner fa-spin fa-4x" style="color: #009EFB; z-index: 2"/>
<!--suppress CheckTagEmptyBody -->
<iframe src="about:blank" class="o_preview_iframe" style="display:none"></iframe>
</div>
@@ -80,6 +80,41 @@ flectra.define('web.basic_model_tests', function (require) {
}, function () {
QUnit.module('BasicModel');
QUnit.test('context is given when using a resequence', async function (assert) {
assert.expect(2);
delete this.params["res_id"];
this.data.product.fields.sequence = {string: "Sequence", type: "integer"};
const model = await createModel({
Model: BasicModel,
data: this.data,
mockRPC: function (route, args) {
if (route === '/web/dataset/resequence') {
assert.deepEqual(args.context, { active_field: 2 },
"context should be correct after a resequence");
}
else if (args.method === "read") {
assert.deepEqual(args.kwargs.context, { active_field: 2 },
"context should be correct after a 'read' RPC");
}
return this._super.apply(this, arguments);
},
});
const params = _.extend(this.params, {
context: { active_field: 2 },
groupedBy: ['product_id'],
fieldNames: ['foo'],
});
model.load(params)
.then(function (stateID) {
return model.resequence('product', [41, 37], stateID);
})
.then(function () {
model.destroy();
});
});
QUnit.test('can process x2many commands', async function (assert) {
assert.expect(6);
@@ -423,6 +423,76 @@ QUnit.module('Views', {
graph.destroy();
});
QUnit.test('fake data in line chart', async function (assert) {
assert.expect(1);
const unpatchDate = patchDate(2020, 4, 19, 1, 0, 0);
this.data.foo.records = [];
var graph = await createView({
View: GraphView,
model: "foo",
data: this.data,
context: { search_default_date_filter: 1, },
arch: '<graph type="line">' +
'<field name="date"/>' +
'</graph>',
archs: {
'foo,false,search': `
<search>
<filter name="date_filter" domain="[]" date="date" default_period="third_quarter"/>
</search>
`,
},
});
await cpHelpers.toggleComparisonMenu(graph);
await cpHelpers.toggleMenuItem(graph, 'Date: Previous period');
assert.checkLabels(graph, [[''], ['']]);
unpatchDate();
graph.destroy();
});
QUnit.test('no filling color for period of comparison', async function (assert) {
assert.expect(1);
const unpatchDate = patchDate(2020, 4, 19, 1, 0, 0);
this.data.foo.records.forEach((r) => {
if (r.date) {
r.date = r.date.replace(/\d\d\d\d/, "2019");
}
});
var graph = await createView({
View: GraphView,
model: "foo",
data: this.data,
context: { search_default_date_filter: 1, },
arch: '<graph type="line">' +
'<field name="product_id"/>' +
'</graph>',
archs: {
'foo,false,search': `
<search>
<filter name="date_filter" domain="[]" date="date" default_period="this_year"/>
</search>
`,
},
});
await cpHelpers.toggleComparisonMenu(graph);
await cpHelpers.toggleMenuItem(graph, 'Date: Previous period');
assert.checkDatasets(graph, ["data", "backgroundColor"], { data: [4, 2] });
unpatchDate();
graph.destroy();
});
QUnit.test('no content helper after update', async function (assert) {
assert.expect(6);
@@ -6896,6 +6896,7 @@ QUnit.module('Views', {
if (route === '/web/dataset/resequence') {
if (moves === 0) {
assert.deepEqual(args, {
context: {},
model: "foo",
ids: [4, 3],
offset: 13,
@@ -6904,6 +6905,7 @@ QUnit.module('Views', {
}
if (moves === 1) {
assert.deepEqual(args, {
context: {},
model: "foo",
ids: [4, 2],
offset: 12,
@@ -6912,6 +6914,7 @@ QUnit.module('Views', {
}
if (moves === 2) {
assert.deepEqual(args, {
context: {},
model: "foo",
ids: [2, 4],
offset: 12,
@@ -6920,6 +6923,7 @@ QUnit.module('Views', {
}
if (moves === 3) {
assert.deepEqual(args, {
context: {},
model: "foo",
ids: [4, 2],
offset: 12,
+1 -1
View File
@@ -533,7 +533,7 @@
</t>
</t>
<t t-if="company.external_report_layout_id" t-call="{{company.external_report_layout_id.key}}"><t t-raw="0"/></t>
<t t-if="company.external_report_layout_id" t-call="{{company.external_report_layout_id.sudo().key}}"><t t-raw="0"/></t>
<t t-else="else" t-call="web.external_layout_standard"><t t-raw="0"/></t>
</template>