mirror of
https://gitlab.com/flectra-hq/flectra.git
synced 2026-10-25 23:40:05 -05:00
[PATCH] Upstream patch - 17052022
This commit is contained in:
1 parent
6e25da8ac4
commit
c56aea7c82
10 files changed
+124
-16
No files matched your search
@@ -65,7 +65,7 @@ class OAuthLogin(Home):
|
||||
redirect_uri=return_url,
|
||||
scope=provider['scope'],
|
||||
state=json.dumps(state),
|
||||
nonce=base64.urlsafe_b64encode(os.urandom(16)),
|
||||
# nonce=base64.urlsafe_b64encode(os.urandom(16)),
|
||||
)
|
||||
provider['auth_link'] = "%s?%s" % (provider['auth_endpoint'], werkzeug.urls.url_encode(params))
|
||||
return providers
|
||||
|
||||
@@ -12,15 +12,6 @@ flectra.define('hr_holidays.dashboard.view_custo', function(require) {
|
||||
var _t = core._t;
|
||||
var QWeb = core.qweb;
|
||||
|
||||
var TimeOffCalendarModel = CalendarModel.extend({
|
||||
|
||||
_getFilterDomain: function() {
|
||||
const company_domain = [['user_id.company_id', 'in', this.data.context.allowed_company_ids]];
|
||||
return this._super().concat(company_domain);
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
var TimeOffCalendarPopover = CalendarPopover.extend({
|
||||
template: 'hr_holidays.calendar.popover',
|
||||
|
||||
@@ -175,7 +166,6 @@ flectra.define('hr_holidays.dashboard.view_custo', function(require) {
|
||||
config: _.extend({}, CalendarView.prototype.config, {
|
||||
Controller: TimeOffCalendarController,
|
||||
Renderer: TimeOffCalendarRenderer,
|
||||
Model: TimeOffCalendarModel,
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -648,7 +648,7 @@
|
||||
'search_default_managed_people': 1,
|
||||
'hide_employee_name': 1}
|
||||
</field>
|
||||
<field name="domain">[]</field>
|
||||
<field name="domain">[('employee_id.company_id', 'in', allowed_company_ids)]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Meet the time off dashboard.
|
||||
|
||||
@@ -1809,10 +1809,11 @@ class SaleOrderLine(models.Model):
|
||||
|
||||
Lines cannot be deleted if the order is confirmed; downpayment
|
||||
lines who have not yet been invoiced bypass that exception.
|
||||
Also, allow deleting UX lines (notes/sections).
|
||||
:rtype: recordset sale.order.line
|
||||
:returns: set of lines that cannot be deleted
|
||||
"""
|
||||
return self.filtered(lambda line: line.state in ('sale', 'done') and (line.invoice_lines or not line.is_downpayment))
|
||||
return self.filtered(lambda line: line.state in ('sale', 'done') and (line.invoice_lines or not line.is_downpayment) and not line.display_type)
|
||||
|
||||
def unlink(self):
|
||||
if self._check_line_unlink():
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_sale_order_template,sale.order.template,model_sale_order_template,sales_team.group_sale_salesman,1,0,0,0
|
||||
access_sale_order_template_manager,sale.order.template,model_sale_order_template,sales_team.group_sale_manager,1,1,1,1
|
||||
access_sale_order_template_system,sale.order.template,model_sale_order_template,base.group_system,1,0,0,0
|
||||
access_sale_order_template_line,sale.order.template.line,model_sale_order_template_line,sales_team.group_sale_salesman,1,0,0,0
|
||||
access_sale_order_template_line_manager,sale.order.template.line,model_sale_order_template_line,sales_team.group_sale_manager,1,1,1,1
|
||||
access_sale_order_template_option,sale.order.template.option,model_sale_order_template_option,sales_team.group_sale_salesman,1,0,0,0
|
||||
|
||||
|
@@ -24,7 +24,7 @@
|
||||
<div class="py-3 m-0 p-0 text-right">
|
||||
<div class="o_survey_progress_wrapper d-inline-block pr-5 text-left">
|
||||
<t t-call="survey.survey_progression"
|
||||
t-if="survey and survey.questions_layout != 'one_page' and answer and answer.state == 'in_progress' and (not question or not question.is_page)">
|
||||
t-if="survey and survey.questions_layout != 'one_page' and answer and answer.state == 'in_progress' and (not question or not question.is_page) and not survey_form_readonly">
|
||||
<t t-if="survey.questions_layout == 'page_per_section'">
|
||||
<t t-set="page_ids" t-value="survey.page_ids.ids"/>
|
||||
<t t-set="page_number" t-value="page_ids.index(page.id) + (1 if survey.progression_mode == 'number' else 0)"/>
|
||||
|
||||
@@ -2674,8 +2674,20 @@ var BooleanToggle = FieldBoolean.extend({
|
||||
*/
|
||||
_onClick: function (event) {
|
||||
event.stopPropagation();
|
||||
this._setValue(!this.value);
|
||||
if (!this.$input.prop('disabled')) {
|
||||
this._setValue(!this.value);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The boolean_toggle should only be disabled when there is a readonly modifier
|
||||
* not when the view is in readonly mode
|
||||
*/
|
||||
_render: function() {
|
||||
this._super.apply(this, arguments);
|
||||
const isReadonly = this.record.evalModifiers(this.attrs.modifiers).readonly || false;
|
||||
this.$input.prop('disabled', isReadonly);
|
||||
}
|
||||
});
|
||||
|
||||
var StatInfo = AbstractField.extend({
|
||||
|
||||
@@ -367,6 +367,63 @@ QUnit.module('basic_fields', {
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('boolean toggle widget is not disabled in readonly mode', async function (assert) {
|
||||
assert.expect(3);
|
||||
|
||||
const form = await createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<form><field name="bar" widget="boolean_toggle"/></form>',
|
||||
res_id: 5,
|
||||
});
|
||||
|
||||
assert.containsOnce(form, ".custom-checkbox.o_boolean_toggle", "Boolean toggle widget applied to boolean field");
|
||||
assert.notOk(form.$('.o_boolean_toggle input')[0].checked);
|
||||
await testUtils.dom.click(form.$('.o_boolean_toggle'));
|
||||
assert.ok(form.$('.o_boolean_toggle input')[0].checked);
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('boolean toggle widget is disabled with a readonly attribute', async function (assert) {
|
||||
assert.expect(3);
|
||||
|
||||
const form = await createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<form><field name="bar" widget="boolean_toggle" readonly="1"/></form>',
|
||||
res_id: 5,
|
||||
});
|
||||
|
||||
assert.containsOnce(form, ".custom-checkbox.o_boolean_toggle", "Boolean toggle widget applied to boolean field");
|
||||
await testUtils.dom.click(form.$buttons.find('.o_form_button_edit'));
|
||||
assert.notOk(form.$('.o_boolean_toggle input')[0].checked);
|
||||
await testUtils.dom.click(form.$('.o_boolean_toggle'));
|
||||
assert.notOk(form.$('.o_boolean_toggle input')[0].checked);
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('boolean toggle widget is enabled in edit mode', async function (assert) {
|
||||
assert.expect(3);
|
||||
|
||||
const form = await createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<form><field name="bar" widget="boolean_toggle"/></form>',
|
||||
res_id: 5,
|
||||
});
|
||||
|
||||
assert.containsOnce(form, ".custom-checkbox.o_boolean_toggle", "Boolean toggle widget applied to boolean field");
|
||||
await testUtils.dom.click(form.$buttons.find('.o_form_button_edit'));
|
||||
|
||||
assert.notOk(form.$('.o_boolean_toggle input')[0].checked);
|
||||
await testUtils.dom.click(form.$('.o_boolean_toggle'));
|
||||
assert.ok(form.$('.o_boolean_toggle input')[0].checked);
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.module('FieldToggleButton');
|
||||
|
||||
QUnit.test('use toggle_button in list view', async function (assert) {
|
||||
|
||||
@@ -538,7 +538,7 @@ publicWidget.registry.WebsiteSale = publicWidget.Widget.extend(VariantMixin, {
|
||||
|
||||
params.product_custom_attribute_values = JSON.stringify(params.product_custom_attribute_values);
|
||||
params.no_variant_attribute_values = JSON.stringify(params.no_variant_attribute_values);
|
||||
|
||||
|
||||
if (this.isBuyNow) {
|
||||
params.express = true;
|
||||
}
|
||||
|
||||
@@ -48,11 +48,29 @@ publicWidget.registry.productsSearchBar = publicWidget.Widget.extend({
|
||||
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
destroy() {
|
||||
this._super(...arguments);
|
||||
this._render(null);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_adaptToScrollingParent() {
|
||||
const bcr = this.el.getBoundingClientRect();
|
||||
this.$menu[0].style.setProperty('position', 'fixed', 'important');
|
||||
this.$menu[0].style.setProperty('top', `${bcr.bottom}px`, 'important');
|
||||
this.$menu[0].style.setProperty('left', `${bcr.left}px`, 'important');
|
||||
this.$menu[0].style.setProperty('max-width', `${bcr.width}px`, 'important');
|
||||
this.$menu[0].style.setProperty('max-height', `${document.body.clientHeight - bcr.bottom - 16}px`, 'important');
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@@ -75,6 +93,13 @@ publicWidget.registry.productsSearchBar = publicWidget.Widget.extend({
|
||||
* @private
|
||||
*/
|
||||
_render: function (res) {
|
||||
if (this._scrollingParentEl) {
|
||||
this._scrollingParentEl.removeEventListener('scroll', this._menuScrollAndResizeHandler);
|
||||
window.removeEventListener('resize', this._menuScrollAndResizeHandler);
|
||||
delete this._scrollingParentEl;
|
||||
delete this._menuScrollAndResizeHandler;
|
||||
}
|
||||
|
||||
var $prevMenu = this.$menu;
|
||||
this.$el.toggleClass('dropdown show', !!res);
|
||||
if (res) {
|
||||
@@ -86,8 +111,30 @@ publicWidget.registry.productsSearchBar = publicWidget.Widget.extend({
|
||||
widget: this,
|
||||
}));
|
||||
this.$menu.css('min-width', this.autocompleteMinWidth);
|
||||
|
||||
// Handle the case where the searchbar is in a mega menu by making
|
||||
// it position:fixed and forcing its size. Note: this could be the
|
||||
// default behavior or at least needed in more cases than the mega
|
||||
// menu only (all scrolling parents). But as a stable fix, it was
|
||||
// easier to fix that case only as a first step, especially since
|
||||
// this cannot generically work on all scrolling parent.
|
||||
const megaMenuEl = this.el.closest('.o_mega_menu');
|
||||
if (megaMenuEl) {
|
||||
const navbarEl = this.el.closest('.navbar');
|
||||
const navbarTogglerEl = navbarEl ? navbarEl.querySelector('.navbar-toggler') : null;
|
||||
if (navbarTogglerEl && navbarTogglerEl.clientWidth < 1) {
|
||||
this._scrollingParentEl = megaMenuEl;
|
||||
this._menuScrollAndResizeHandler = () => this._adaptToScrollingParent();
|
||||
this._scrollingParentEl.addEventListener('scroll', this._menuScrollAndResizeHandler);
|
||||
window.addEventListener('resize', this._menuScrollAndResizeHandler);
|
||||
|
||||
this._adaptToScrollingParent();
|
||||
}
|
||||
}
|
||||
|
||||
this.$el.append(this.$menu);
|
||||
}
|
||||
|
||||
if ($prevMenu) {
|
||||
$prevMenu.remove();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user