Merge pull request #5223 from expsa/fix_table_width_form
[UDP] update catalog button action, add "Add" custom button to window…
This commit is contained in:
commit
925d0becc6
|
|
@ -7303,6 +7303,18 @@ msgstr ""
|
|||
"<i class=\"fa fa-shopping-cart\"/>\n"
|
||||
" <span>إضافة</span>"
|
||||
|
||||
#. module: odex_takaful
|
||||
#: code:addons/odex_takaful/models/donation_details_lines.py:0
|
||||
#: code:addons/odex_takaful/models/takaful_sponorship_model.py:0
|
||||
#, python-format
|
||||
msgid "Choose Donation Items"
|
||||
msgstr "أختر بنود التبرع"
|
||||
|
||||
#. module: odex_takaful
|
||||
#: model_terms:ir.ui.view,arch_db:odex_takaful.product_template_view_kanban_odex_takaful
|
||||
msgid "<span>Amount:</span>"
|
||||
msgstr "<span>القيمة:</span>"
|
||||
|
||||
#. module: odex_takaful
|
||||
#: model_terms:ir.ui.view,arch_db:odex_takaful.family_member_form_inherit_donation_button
|
||||
msgid "Kafala Information"
|
||||
|
|
|
|||
|
|
@ -252,8 +252,10 @@ class TakafulSponsorship(models.Model):
|
|||
('donation_category', '=', 'donation')],
|
||||
'context': {
|
||||
# '_quantity_change': True,
|
||||
'sponsorship_id': self.id,
|
||||
'create': False
|
||||
'sponsorship_id': self._origin.id,
|
||||
'create': False,
|
||||
'hide_breadcrumbs': True,
|
||||
'action_code': 'donation_items'
|
||||
},
|
||||
'target': "new",
|
||||
'help': _("""<p class="o_view_nocontent_smiling_face">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
odoo.define('odex_takaful.custom_dialog', function (require) {
|
||||
"use strict";
|
||||
|
||||
const AbstractAction = require('web.AbstractAction');
|
||||
const Dialog = require('web.Dialog');
|
||||
const core = require('web.core');
|
||||
const _t = core._t;
|
||||
const ActionManager = require('web.ActionManager');
|
||||
|
||||
Dialog.include({
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
open: function() {
|
||||
var self = this;
|
||||
this.opened(function() {
|
||||
setTimeout(function () {
|
||||
var parent = self.getParent();
|
||||
|
||||
if (parent instanceof ActionManager) {
|
||||
var action = parent.getCurrentActionInDialog();
|
||||
if (action) {
|
||||
if(action.context){
|
||||
let context = action.context;
|
||||
if(context.action_code){
|
||||
if(context.action_code === 'donation_items'){
|
||||
if (self.$footer) {
|
||||
const closeBtn = $('<button/>', {
|
||||
text: _t('Add'),
|
||||
class: 'btn btn-primary btn-close-custom',
|
||||
}).on('click', () => self.close());
|
||||
self.$footer.append(closeBtn);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(context.sponsorship_id){
|
||||
$('#cspid').remove();
|
||||
$('body').append(`<input type="hidden" id="cspid" value="${context.sponsorship_id}"/>`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(self.$modal){
|
||||
self.$modal.find('.modal-header button.close').hide();
|
||||
self.$modal.find('.modal-header .modal-title').css("width","100%");
|
||||
}
|
||||
|
||||
if(self.$el){
|
||||
self.$el.find('.o_cp_top_left').hide();
|
||||
self.$el.find('.o_cp_bottom_left').hide();
|
||||
self.$el.find('.o_cp_top_right').css("width","100%");
|
||||
self.$el.find('.o_cp_bottom_right').css("width","100%");
|
||||
}
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -1,171 +1,165 @@
|
|||
// Donation Catalog Quantity Controls
|
||||
// Handles plus/minus buttons in the donation catalog popup
|
||||
odoo.define('odex_takaful.DonationQuantityWidget', function (require) {
|
||||
"use strict";
|
||||
|
||||
// Attach event handlers immediately using event delegation
|
||||
// Odoo converts 'name' attribute to 'data-name' in rendered HTML
|
||||
$(document).on('click', 'button[data-name="add_quantity_button_request"]', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
handleQuantityChange($(this), 'first_add');
|
||||
return false; // ensure Odoo's default kanban action handler does not run
|
||||
});
|
||||
|
||||
$(document).on('click', 'button[data-name="add_quantity_button_so"]', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
handleQuantityChange($(this), 'add');
|
||||
return false; // ensure Odoo's default kanban action handler does not run
|
||||
});
|
||||
|
||||
$(document).on('click', 'button[data-name="remove_quantity_button_so"]', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
handleQuantityChange($(this), 'remove');
|
||||
return false; // ensure Odoo's default kanban action handler does not run
|
||||
});
|
||||
|
||||
// Expose imperative handlers as a reliable fallback (callable from inline onclick if needed)
|
||||
window.__dc_add = function(btn) {
|
||||
return __dc_handle(btn, 'add');
|
||||
};
|
||||
window.__dc_remove = function(btn) {
|
||||
return __dc_handle(btn, 'remove');
|
||||
};
|
||||
window.__dc_first_add = function(btn) {
|
||||
return __dc_handle(btn, 'first_add');
|
||||
};
|
||||
|
||||
function __dc_handle(btn, operation) {
|
||||
try {
|
||||
const $btn = $(btn);
|
||||
handleQuantityChange($btn, operation);
|
||||
} catch (_e) {
|
||||
// no-op
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async function handleQuantityChange($button, operation) {
|
||||
|
||||
// Get the kanban record (product card) container
|
||||
const $kanbanRecord = $button.closest('.o_kanban_record');
|
||||
if (!$kanbanRecord.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get quantity display element from the button's parent container using stable custom classes
|
||||
let $container = $button.closest('.dc-qty-controls');
|
||||
if (operation === 'first_add'){
|
||||
$container = $kanbanRecord.find('.dc-qty-controls')
|
||||
}
|
||||
let $quantityDisplay = $container.find('.dc-qty-badge');
|
||||
// if (!$quantityDisplay.length) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Extract product ID from the image URL
|
||||
const $img = $kanbanRecord.find('.o_kanban_image img');
|
||||
// if (!$img.length) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
const imgSrc = $img.attr('src');
|
||||
const match = imgSrc.match(/[&?]id=(\d+)/);
|
||||
// if (!match || !match[1]) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
const productId = parseInt(match[1]);
|
||||
let currentQuantity = parseFloat($quantityDisplay.text()) || 0;
|
||||
const Widget = require('web.Widget');
|
||||
const rpc = require('web.rpc');
|
||||
const core = require('web.core');
|
||||
const QWeb = core.qweb;
|
||||
const _t = core._t;
|
||||
|
||||
|
||||
// Prevent going below zero for remove operation
|
||||
if (operation === 'remove' && currentQuantity <= 0) {
|
||||
return;
|
||||
let o_cart_kanban_donation = $('.o_cart_kanban_donation');
|
||||
if(o_cart_kanban_donation){
|
||||
$(o_cart_kanban_donation).parents('.o_act_window').find('.o_cp_top_left').remove();
|
||||
}
|
||||
|
||||
// Resolve sponsorship id from multiple sources (robust against context differences)
|
||||
let sponsorship_id;
|
||||
try {
|
||||
const stored = sessionStorage.getItem("current_action");
|
||||
if (stored) {
|
||||
const parsed = JSON.parse(stored);
|
||||
const data = JSON.parse(parsed);
|
||||
sponsorship_id = data?.context?.params?.id || data?.context?.sponsorship_id;
|
||||
|
||||
$(document).on('click', 'button[data-name="add_quantity_button_request"]', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
handleQuantityChange($(this), 'first_add');
|
||||
return false; // ensure Odoo's default kanban action handler does not run
|
||||
});
|
||||
|
||||
$(document).on('click', 'button[data-name="add_quantity_button_so"]', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
handleQuantityChange($(this), 'add');
|
||||
return false; // ensure Odoo's default kanban action handler does not run
|
||||
});
|
||||
|
||||
$(document).on('click', 'button[data-name="remove_quantity_button_so"]', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
handleQuantityChange($(this), 'remove');
|
||||
return false; // ensure Odoo's default kanban action handler does not run
|
||||
});
|
||||
|
||||
// Expose imperative handlers as a reliable fallback (callable from inline onclick if needed)
|
||||
window.__dc_add = function (btn) {
|
||||
return __dc_handle(btn, 'add');
|
||||
};
|
||||
window.__dc_remove = function (btn) {
|
||||
return __dc_handle(btn, 'remove');
|
||||
};
|
||||
window.__dc_first_add = function (btn) {
|
||||
return __dc_handle(btn, 'first_add');
|
||||
};
|
||||
|
||||
function __dc_handle(btn, operation) {
|
||||
try {
|
||||
const $btn = $(btn);
|
||||
handleQuantityChange($btn, operation);
|
||||
} catch (_e) {
|
||||
// no-op
|
||||
}
|
||||
} catch (_err) {
|
||||
// ignore, fall back to other strategies
|
||||
}
|
||||
if (!sponsorship_id) {
|
||||
const $form = $('.o_form_view');
|
||||
const resIdFromDom = $form && ($form.data('res-id') || $form.attr('data-res-id'));
|
||||
if (resIdFromDom) sponsorship_id = parseInt(resIdFromDom);
|
||||
}
|
||||
if (!sponsorship_id) {
|
||||
const hash = window.location.hash || '';
|
||||
const m = hash.match(/[&#]id=(\d+)/);
|
||||
if (m) sponsorship_id = parseInt(m[1]);
|
||||
}
|
||||
if (!sponsorship_id) {
|
||||
return;
|
||||
}
|
||||
sponsorship_id = parseInt(sponsorship_id);
|
||||
|
||||
// Disable buttons during operation
|
||||
$button.prop('disabled', true).addClass('o_btn_loading');
|
||||
$button.siblings('button').prop('disabled', true);
|
||||
|
||||
// Calculate new quantity
|
||||
let newQuantity = currentQuantity;
|
||||
if (operation === 'first_add'){
|
||||
$button.addClass('d-none');
|
||||
$kanbanRecord.find('.dc-qty-controls').removeClass("d-none");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (operation === 'add' || operation === 'first_add') {
|
||||
newQuantity = newQuantity + 1;
|
||||
}
|
||||
|
||||
if (operation === 'remove') {
|
||||
newQuantity = newQuantity - 1;
|
||||
}
|
||||
|
||||
// Update display optimistically
|
||||
$quantityDisplay.text(newQuantity.toFixed(2));
|
||||
|
||||
try {
|
||||
// Call server to update quantity
|
||||
await $.ajax({
|
||||
url: "/qtyupdatecart_so",
|
||||
method: "GET",
|
||||
dataType: 'json',
|
||||
data: {
|
||||
quantity: newQuantity,
|
||||
product_id: productId,
|
||||
sponsorship_id: sponsorship_id
|
||||
}
|
||||
}).catch(function(jqXHR) {
|
||||
// Re-throw with more details
|
||||
const info = {
|
||||
status: jqXHR?.status,
|
||||
responseText: jqXHR?.responseText,
|
||||
readyState: jqXHR?.readyState
|
||||
};
|
||||
throw info;
|
||||
});
|
||||
|
||||
|
||||
} catch (error) {
|
||||
// Revert on error
|
||||
$quantityDisplay.text(currentQuantity.toFixed(2));
|
||||
// $quantityDisplay.addClass('bg-danger').removeClass('bg-secondary');
|
||||
setTimeout(() => {
|
||||
// $quantityDisplay.removeClass('bg-danger').addClass('bg-secondary');
|
||||
}, 1000);
|
||||
} finally {
|
||||
// Re-enable buttons
|
||||
$button.prop('disabled', false).removeClass('o_btn_loading');
|
||||
$button.siblings('button').prop('disabled', false);
|
||||
}
|
||||
}
|
||||
async function handleQuantityChange($button, operation) {
|
||||
|
||||
// Get the kanban record (product card) container
|
||||
const $kanbanRecord = $button.closest('.o_kanban_record');
|
||||
if (!$kanbanRecord.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get quantity display element from the button's parent container using stable custom classes
|
||||
let $container = $button.closest('.dc-qty-controls');
|
||||
if (operation === 'first_add') {
|
||||
$container = $kanbanRecord.find('.dc-qty-controls')
|
||||
}
|
||||
let $quantityDisplay = $container.find('.dc-qty-badge');
|
||||
// if (!$quantityDisplay.length) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Extract product ID from the image URL
|
||||
const $img = $kanbanRecord.find('.o_kanban_image img');
|
||||
// if (!$img.length) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
const imgSrc = $img.attr('src');
|
||||
const match = imgSrc.match(/[&?]id=(\d+)/);
|
||||
// if (!match || !match[1]) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
const productId = parseInt(match[1]);
|
||||
let currentQuantity = parseFloat($quantityDisplay.text()) || 0;
|
||||
|
||||
|
||||
// Prevent going below zero for remove operation
|
||||
if (operation === 'remove' && currentQuantity <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Resolve sponsorship id from multiple sources (robust against context differences)
|
||||
let sponsorship_id;
|
||||
if (!sponsorship_id) {
|
||||
const $input = $('#cspid');
|
||||
if ($input) sponsorship_id = parseInt($input.val());
|
||||
}
|
||||
|
||||
if (!sponsorship_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable buttons during operation
|
||||
$button.prop('disabled', true).addClass('o_btn_loading');
|
||||
$button.siblings('button').prop('disabled', true);
|
||||
|
||||
// Calculate new quantity
|
||||
let newQuantity = currentQuantity;
|
||||
if (operation === 'first_add') {
|
||||
$button.addClass('d-none');
|
||||
$kanbanRecord.find('.dc-qty-controls').removeClass("d-none");
|
||||
}
|
||||
|
||||
if (operation === 'add' || operation === 'first_add') {
|
||||
newQuantity = newQuantity + 1;
|
||||
}
|
||||
|
||||
if (operation === 'remove') {
|
||||
newQuantity = newQuantity - 1;
|
||||
}
|
||||
|
||||
// Update display optimistically
|
||||
$quantityDisplay.text(newQuantity);
|
||||
|
||||
try {
|
||||
// Call server to update quantity
|
||||
await $.ajax({
|
||||
url: "/qtyupdatecart_so",
|
||||
method: "GET",
|
||||
dataType: 'json',
|
||||
data: {
|
||||
quantity: newQuantity,
|
||||
product_id: productId,
|
||||
sponsorship_id: sponsorship_id
|
||||
}
|
||||
}).catch(function (jqXHR) {
|
||||
// Re-throw with more details
|
||||
const info = {
|
||||
status: jqXHR?.status,
|
||||
responseText: jqXHR?.responseText,
|
||||
readyState: jqXHR?.readyState
|
||||
};
|
||||
throw info;
|
||||
});
|
||||
|
||||
|
||||
} catch (error) {
|
||||
// Revert on error
|
||||
$quantityDisplay.text(currentQuantity);
|
||||
// $quantityDisplay.addClass('bg-danger').removeClass('bg-secondary');
|
||||
setTimeout(() => {
|
||||
// $quantityDisplay.removeClass('bg-danger').addClass('bg-secondary');
|
||||
}, 1000);
|
||||
} finally {
|
||||
// Re-enable buttons
|
||||
$button.prop('disabled', false).removeClass('o_btn_loading');
|
||||
$button.siblings('button').prop('disabled', false);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
<link rel="stylesheet" type="text/scss" href="/odex_takaful/static/src/scss/donation_item_views.scss"/>
|
||||
<link rel="stylesheet" type="text/scss" href="/odex_takaful/static/src/scss/fix_table_overflow.scss"/>
|
||||
<script type="text/javascript" src="/odex_takaful/static/src/js/product_product_views.js"/>
|
||||
<script type="text/javascript" src="/odex_takaful/static/src/js/donation_catalog_button.js"/>
|
||||
<script type="text/javascript" src="/odex_takaful/static/src/js/donation_catalog_controls.js"/>
|
||||
<!-- <script type="text/javascript" src="/odex_takaful/static/src/js/catalog_kanban_dynamic_button.js"/>-->
|
||||
</xpath>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<field name="name">product.template.view.kanban.odex.takaful</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban edit="0" create="0" class="o_kanban_mobile o_cart_kanban">
|
||||
<kanban edit="0" create="0" class="o_kanban_mobile o_cart_kanban o_cart_kanban_donation">
|
||||
<field name="id" />
|
||||
<field name="name" />
|
||||
<field name="_quantity" />
|
||||
|
|
@ -17,7 +17,8 @@
|
|||
</div>
|
||||
<h5 style="margin-top: 5px;text-align: center;">
|
||||
<span>Amount:</span>
|
||||
<field name="lst_price" widget="monetary" options="{'currency_field': 'currency_id'}" />
|
||||
<field name="lst_price" widget="monetary"/>
|
||||
<svg id="Layer_1" data-name="Layer 1" viewBox="0 0 1124.14 1256.39" style="height: 11px"><defs><style>.cls-1 {fill: #231f20;}</style></defs><path class="cls-1" d="M699.62,1113.02h0c-20.06,44.48-33.32,92.75-38.4,143.37l424.51-90.24c20.06-44.47,33.31-92.75,38.4-143.37l-424.51,90.24Z"/><path class="cls-1" d="M1085.73,895.8c20.06-44.47,33.32-92.75,38.4-143.37l-330.68,70.33v-135.2l292.27-62.11c20.06-44.47,33.32-92.75,38.4-143.37l-330.68,70.27V66.13c-50.67,28.45-95.67,66.32-132.25,110.99v403.35l-132.25,28.11V0c-50.67,28.44-95.67,66.32-132.25,110.99v525.69l-295.91,62.88c-20.06,44.47-33.33,92.75-38.42,143.37l334.33-71.05v170.26l-358.3,76.14c-20.06,44.47-33.32,92.75-38.4,143.37l375.04-79.7c30.53-6.35,56.77-24.4,73.83-49.24l68.78-101.97v-.02c7.14-10.55,11.3-23.27,11.3-36.97v-149.98l132.25-28.11v270.4l424.53-90.28Z"/></svg>
|
||||
</h5>
|
||||
<div class="oe_kanban_details p-2 d-flex">
|
||||
<div class="o_kanban_record_top flex-column w-100 "
|
||||
|
|
@ -56,7 +57,6 @@
|
|||
<i class="fa fa-shopping-cart" />
|
||||
<span>Add</span>
|
||||
</button>
|
||||
|
||||
|
||||
<div class="dc-qty-controls d-none">
|
||||
<div class="input-group">
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
<i class="fa fa-minus" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-control dc-qty-badge">
|
||||
<div class="form-control dc-qty-badge" style="min-width: 40px;text-align: center;">
|
||||
<field name="_quantity" />
|
||||
</div>
|
||||
<div class="input-group-prepend">
|
||||
|
|
@ -114,6 +114,7 @@
|
|||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="odex_takaful_product_template_form_view" model="ir.ui.view">
|
||||
<field name="name">odex.takaful.product.template.form.view</field>
|
||||
<field name="model">product.template</field>
|
||||
|
|
@ -124,4 +125,5 @@
|
|||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
Loading…
Reference in New Issue