diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/product_matrix/static | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/product_matrix/static')
| -rw-r--r-- | addons/product_matrix/static/img/matrix_mycompany_tshirt.jpeg | bin | 0 -> 111742 bytes | |||
| -rw-r--r-- | addons/product_matrix/static/src/js/section_and_note_widget.js | 139 | ||||
| -rw-r--r-- | addons/product_matrix/static/src/scss/product_matrix.scss | 61 | ||||
| -rw-r--r-- | addons/product_matrix/static/src/xml/product_matrix.xml | 53 |
4 files changed, 253 insertions, 0 deletions
diff --git a/addons/product_matrix/static/img/matrix_mycompany_tshirt.jpeg b/addons/product_matrix/static/img/matrix_mycompany_tshirt.jpeg Binary files differnew file mode 100644 index 00000000..b600989d --- /dev/null +++ b/addons/product_matrix/static/img/matrix_mycompany_tshirt.jpeg diff --git a/addons/product_matrix/static/src/js/section_and_note_widget.js b/addons/product_matrix/static/src/js/section_and_note_widget.js new file mode 100644 index 00000000..650efbf2 --- /dev/null +++ b/addons/product_matrix/static/src/js/section_and_note_widget.js @@ -0,0 +1,139 @@ +odoo.define('product_matrix.section_and_note_widget', function (require) { + +var Dialog = require('web.Dialog'); +var core = require('web.core'); +var _t = core._t; +var qweb = core.qweb; +var fieldRegistry = require('web.field_registry'); +require('account.section_and_note_backend'); + +var SectionAndNoteFieldOne2Many = fieldRegistry.get('section_and_note_one2many'); + +SectionAndNoteFieldOne2Many.include({ + custom_events: _.extend({}, SectionAndNoteFieldOne2Many.prototype.custom_events, { + open_matrix: '_openMatrix', + }), + + /** + * Sends the matrix modifications to the server + * Through a change on an invisible non stored field. + * + * @param {List} list of changes in the matrix, to be applied to the order. + * {integer} quantity: float + * {List} ptav_ids: product.template.attribute.value ids + * + * @private + */ + _applyGrid: function (changes, productTemplateId) { + // the getParent is to trigger the event on the form Controller instead of the one2many. + // If not, the one2many crashes on reset because it tries to find an operation in the event + // even if there isn't any. + // the only solution would be to use a custom event catched on a new controller + // on the so/po form (as a js_class). + this.trigger_up('field_changed', { + dataPointID: this.dataPointID, + changes: { + grid: JSON.stringify({changes: changes, product_template_id: productTemplateId}), + grid_update: true // to say that the changes to grid have to be applied to the SO. + }, + viewType: 'form', + }); + }, + + /** + * Catches the event asking for matrix opening + * + * @param {OdooEvent} ev various values needed to open the matrix + * {integer} data.product_template_id product.template id + * {list} data.editedCellAttributes list of product.template.attribute.value ids + * {bool} data.edit whether the line source should be deleted or not. + * + * @private + */ + _openMatrix: function (ev) { + ev.stopPropagation(); + var self = this; + var dataPointId = ev.data.dataPointId; + var productTemplateId = ev.data.product_template_id; + var editedCellAttributes = ev.data.editedCellAttributes; + if (!ev.data.edit) { + // remove the line used to open the matrix + this._setValue({operation: 'DELETE', ids: [dataPointId]}); + } + // the getParent is to trigger the event on the form Controller instead of the one2many. + // If not, the one2many crashes on reset because it tries to find an operation in the event + // even if there isn't any. + // the only solution would be to use a custom event catched on a new controller + // on the so/po form (as a js_class). + this.trigger_up('field_changed', { + dataPointID: this.dataPointID, + changes: { + grid_product_tmpl_id: {id: productTemplateId} + }, + viewType: 'form', + onSuccess: function () { + const gridInfo = self.recordData.grid; + self._openMatrixConfigurator(gridInfo, productTemplateId, editedCellAttributes); + } + }); + }, + + /** + * Triggers Matrix Dialog opening + * + * @param {String} jsonInfo matrix dialog content + * @param {integer} productTemplateId product.template id + * @param {editedCellAttributes} list of product.template.attribute.value ids + * used to focus on the matrix cell representing the edited line. + * + * @private + */ + _openMatrixConfigurator: function (jsonInfo, productTemplateId, editedCellAttributes) { + var self = this; + var infos = JSON.parse(jsonInfo); + var MatrixDialog = new Dialog(this, { + title: _t('Choose Product Variants'), + size: 'extra-large', // adapt size depending on matrix size? + $content: $(qweb.render( + 'product_matrix.matrix', { + header: infos.header, + rows: infos.matrix, + } + )), + buttons: [ + {text: _t('Confirm'), classes: 'btn-primary', close: true, click: function (result) { + var $inputs = this.$('.o_matrix_input'); + var matrixChanges = []; + _.each($inputs, function (matrixInput) { + if (matrixInput.value && matrixInput.value !== matrixInput.attributes.value.nodeValue) { + matrixChanges.push({ + qty: parseFloat(matrixInput.value), + ptav_ids: matrixInput.attributes.ptav_ids.nodeValue.split(",").map(function (id) { + return parseInt(id); + }), + }); + } + }); + if (matrixChanges.length > 0) { + self._applyGrid(matrixChanges, productTemplateId); + } + }}, + {text: _t('Close'), close: true}, + ], + }).open(); + + MatrixDialog.opened(function () { + if (editedCellAttributes.length > 0) { + var str = editedCellAttributes.toString(); + MatrixDialog.$content.find('.o_matrix_input').filter((k, v) => v.attributes.ptav_ids.nodeValue === str)[0].focus(); + } else { + MatrixDialog.$content.find('.o_matrix_input:first()').focus(); + } + }); + }, + +}); + +return SectionAndNoteFieldOne2Many; + +}); diff --git a/addons/product_matrix/static/src/scss/product_matrix.scss b/addons/product_matrix/static/src/scss/product_matrix.scss new file mode 100644 index 00000000..ead8137d --- /dev/null +++ b/addons/product_matrix/static/src/scss/product_matrix.scss @@ -0,0 +1,61 @@ +.o_web_client .o_matrix_input_table { + cursor: default; + + table { + margin-bottom: 0; + table-layout: fixed; + min-width: 100%; + width: auto; + max-width: none; + } + th, td { + border: 0 !important; + vertical-align: middle; + width: 5em; + } + .o_matrix_title_header { + width: 10em; + } + thead { + color: $o-main-text-color; + background-color: $o-brand-lightsecondary; + th { + text-align: center; + white-space: pre-line; + } + } + tbody { + background-color: $o-view-background-color; + text-align: right; + tr { + border-top: 1px solid $o-form-lightsecondary; + border-bottom: 1px solid $o-form-lightsecondary; + } + .o_matrix_input { + text-align: right; + border: none; + } + } + .o_matrix_text_muted{ + color: lighten($o-main-text-color, 15%); + font-style: italic; + } + + // ensure white background completely surrounds nocontent bubble + .o_matrix_nocontent_container { + overflow: auto; + + .oe_view_nocontent_img_link { + padding:10px; + } + } +} + +.o_product_variant_matrix { + .form-control { + &:focus { + box-shadow: none; + border: 1px solid $gray-400; + } + } +} diff --git a/addons/product_matrix/static/src/xml/product_matrix.xml b/addons/product_matrix/static/src/xml/product_matrix.xml new file mode 100644 index 00000000..09fc7ba0 --- /dev/null +++ b/addons/product_matrix/static/src/xml/product_matrix.xml @@ -0,0 +1,53 @@ +<template> + <div t-name="product_matrix.matrix"> + <table class="o_matrix_input_table o_product_variant_matrix table table-sm table-striped table-bordered"> + <thead> + <tr> + <t t-foreach="header" t-as="column_header"> + <th t-attf-class="o_matrix_title_header {{column_header_first?'text-left':'text-center'}}"> + <span t-esc="column_header.name"/> + <t t-call="product_matrix.extra_price"> + <t t-set="price" t-value="column_header.price"/> + </t> + </th> + </t> + </tr> + </thead> + <tbody> + <tr t-foreach="rows" t-as="row"> + <t t-foreach="row" t-as="cell"> + <td t-if="cell.name" class="text-left"> + <strong t-esc="cell.name"/> + <t t-call="product_matrix.extra_price"> + <t t-set="price" t-value="cell.price"/> + </t> + </td> + <td t-else=""> + <div t-if="cell.is_possible_combination" class="input-group"> + <input type="number" + class="o_matrix_input" + t-att-ptav_ids="cell.ptav_ids" + t-att-value="cell.qty"/> + </div> + <span t-else="" class="o_matrix_cell o_matrix_text_muted o_matrix_nocontent_container"> Not available </span> + </td> + </t> + </tr> + </tbody> + </table> + </div> + <span t-name="product_matrix.extra_price" t-if="price" class="badge badge-pill badge-secondary"> + <!-- + price_extra is displayed as catalog price instead of + price after pricelist because it is impossible to + compute. Indeed, the pricelist rule might depend on the + selected variant, so the price_extra will be different + depending on the selected combination. The price of an + attribute is therefore variable and it's not very + accurate to display it. + --> + <span class="variant_price_extra" style="white-space: nowrap;"> + <t t-raw="price"/> + </span> + </span> +</template> |
