mirror of
https://github.com/OCA/web.git
synced 2025-02-22 13:21:25 +02:00
[MIG] web_widget_float_formula: Migration to 12.0
This commit is contained in:
@@ -1,111 +1,200 @@
|
||||
/**
|
||||
* Copyright GRAP
|
||||
* Copyright 2016 LasLabs Inc.
|
||||
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
**/
|
||||
|
||||
* Copyright 2014-2015 GRAP
|
||||
* Copyright 2016 LasLabs Inc.
|
||||
* Copyright 2020 Brainbean Apps (https://brainbeanapps.com)
|
||||
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
*/
|
||||
odoo.define('web_widget_float_formula', function(require) {
|
||||
"use strict";
|
||||
|
||||
var form_view = require('web.FormView');
|
||||
form_view.include({
|
||||
// Ensure that formula is computed even if user saves right away and
|
||||
// clean up '_formula_text' value to avoid bugs in tree view
|
||||
_process_save: function(save_obj) {
|
||||
for (var f in this.fields) {
|
||||
if (!this.fields.hasOwnProperty(f)) { continue; }
|
||||
f = this.fields[f];
|
||||
if (f.hasOwnProperty('_formula_text') && f.$el.find('input').length > 0) {
|
||||
f._compute_result();
|
||||
f._clean_formula_text();
|
||||
var field_utils = require('web.field_utils');
|
||||
var pyUtils = require('web.py_utils');
|
||||
var NumericField = require('web.basic_fields').NumericField;
|
||||
var FieldMonetary = require('web.basic_fields').FieldMonetary;
|
||||
|
||||
var FormulaFieldMixin = {
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Unaltered formula that user has entered.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_formula: '',
|
||||
|
||||
/**
|
||||
* Value of the field that was concealed during formula reveal.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_concealedValue: '',
|
||||
|
||||
/**
|
||||
* Returns formula prefix character
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_getFormulaPrefix: function () {
|
||||
return '=';
|
||||
},
|
||||
|
||||
/**
|
||||
* Process formula if one is detected.
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
* @param {any} value
|
||||
* @param {Object} [options]
|
||||
*/
|
||||
_setValue: function (value, options) {
|
||||
this._formula = '';
|
||||
if (!!value && this._isFormula(value)) {
|
||||
try {
|
||||
var evaluated_value = this._evaluateFormula(value);
|
||||
this._formula = value;
|
||||
|
||||
value = this._formatValue(evaluated_value);
|
||||
this.$input.val(value);
|
||||
} catch (err) {
|
||||
this._formula = '';
|
||||
} finally {
|
||||
this._concealedValue = '';
|
||||
}
|
||||
}
|
||||
|
||||
return this._super(save_obj);
|
||||
return this._super(value, options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if provided value is a formula.
|
||||
*
|
||||
* @private
|
||||
* @param {any} value
|
||||
*/
|
||||
_isFormula: function(value) {
|
||||
value = value.toString().replace(/\s+/gm, '');
|
||||
return value.startsWith(this._getFormulaPrefix())
|
||||
|| this._getOperatorsRegExp().test(value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns regular expression that matches all supported operators
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_getOperatorsRegExp: function () {
|
||||
return /((?:\+)|(?:\-)|(?:\*)|(?:\/)|(?:\()|(?:\))|(?:\%))/;
|
||||
},
|
||||
|
||||
/**
|
||||
* Evaluate formula.
|
||||
*
|
||||
* @private
|
||||
* @param {any} formula
|
||||
*/
|
||||
_evaluateFormula: function(formula) {
|
||||
return pyUtils.py_eval(this._preparseFormula(formula));
|
||||
},
|
||||
|
||||
/**
|
||||
* Pre-parses and sanitizes formula
|
||||
*
|
||||
* @private
|
||||
* @param {string} formula
|
||||
*/
|
||||
_preparseFormula: function(formula) {
|
||||
formula = formula.toString().replace(/\s+/gm, '');
|
||||
var prefix = this._getFormulaPrefix();
|
||||
if (formula.startsWith(prefix)) {
|
||||
formula = formula.substring(prefix.length);
|
||||
}
|
||||
var operatorsRegExp = this._getOperatorsRegExp();
|
||||
return formula.split(operatorsRegExp).reduce((tokens, token) => {
|
||||
if (token === '') {
|
||||
return tokens;
|
||||
}
|
||||
if (!operatorsRegExp.test(token)) {
|
||||
token = field_utils.parse.float(token);
|
||||
}
|
||||
tokens.push(token);
|
||||
return tokens;
|
||||
}, []).join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Reveals formula
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_revealFormula: function () {
|
||||
if (!!this._formula) {
|
||||
this._concealedValue = this.$input.val();
|
||||
this.$input.val(this._formula);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Conceals formula
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_concealFormula: function () {
|
||||
var value = this.$input.val();
|
||||
if (!!value && this._isFormula(value)) {
|
||||
if (value !== this._formula) {
|
||||
this.commitChanges();
|
||||
} else if (!!this._concealedValue) {
|
||||
this.$input.val(this._concealedValue);
|
||||
this._concealedValue = '';
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles 'focus' event
|
||||
*
|
||||
* @private
|
||||
* @param {FocusEvent} event
|
||||
*/
|
||||
_onFocusFormulaField: function(event) {
|
||||
if (this.$input === undefined || this.mode !== 'edit') {
|
||||
return;
|
||||
}
|
||||
this._revealFormula();
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles 'blur' event
|
||||
*
|
||||
* @private
|
||||
* @param {FocusEvent} event
|
||||
*/
|
||||
_onBlurFormulaField: function(event) {
|
||||
if (this.$input === undefined || this.mode !== 'edit') {
|
||||
return;
|
||||
}
|
||||
this._concealFormula();
|
||||
},
|
||||
};
|
||||
|
||||
NumericField.include({
|
||||
...FormulaFieldMixin,
|
||||
events: _.extend({}, NumericField.prototype.events, {
|
||||
'focus': '_onFocusFormulaField',
|
||||
'blur': '_onBlurFormulaField',
|
||||
}),
|
||||
});
|
||||
|
||||
var core = require('web.core');
|
||||
core.bus.on('web_client_ready', null, function () {
|
||||
// Import localization values used to eval formula
|
||||
var translation_params = core._t.database.parameters;
|
||||
var decimal_point = translation_params.decimal_point;
|
||||
var thousands_sep = translation_params.thousands_sep;
|
||||
|
||||
var field_float = require('web.form_widgets').FieldFloat;
|
||||
field_float.include({
|
||||
start: function() {
|
||||
this._super();
|
||||
this.on('blurred', this, this._compute_result);
|
||||
this.on('focused', this, this._display_formula);
|
||||
return this;
|
||||
},
|
||||
|
||||
initialize_content: function() {
|
||||
this._clean_formula_text();
|
||||
return this._super();
|
||||
},
|
||||
|
||||
_formula_text: '',
|
||||
|
||||
_clean_formula_text: function() {
|
||||
this._formula_text = '';
|
||||
},
|
||||
|
||||
_process_formula: function(formula) {
|
||||
try{
|
||||
formula = formula.toString();
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
var clean_formula = formula.toString().replace(/^\s+|\s+$/g, '');
|
||||
if (clean_formula[0] == '=') {
|
||||
clean_formula = clean_formula.substring(1);
|
||||
var myreg = new RegExp('[0-9]|\\s|\\.|,|\\(|\\)|\\+|\\-|\\*|\\/', 'g');
|
||||
if (clean_formula.replace(myreg, '') === '') {
|
||||
return clean_formula;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_eval_formula: function(formula) {
|
||||
var value;
|
||||
formula = formula.replace(thousands_sep, '').replace(decimal_point, '.');
|
||||
try {
|
||||
value = eval(formula);
|
||||
}
|
||||
catch(e) {}
|
||||
|
||||
if (typeof value != 'undefined') {
|
||||
return value;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_compute_result: function() {
|
||||
this._clean_formula_text();
|
||||
|
||||
var input = this.$input.val();
|
||||
|
||||
var formula = this._process_formula(input);
|
||||
if (formula !== false) {
|
||||
var value = this._eval_formula(formula);
|
||||
if (value !== false) {
|
||||
this._formula_text = "=" + formula;
|
||||
this.set_value(value);
|
||||
// Force rendering to avoid format loss if there's no change
|
||||
this.render_value();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Display the formula stored in the field to allow modification
|
||||
_display_formula: function() {
|
||||
if (this._formula_text !== '') {
|
||||
this.$input.val(this._formula_text);
|
||||
}
|
||||
},
|
||||
});
|
||||
FieldMonetary.include({
|
||||
...FormulaFieldMixin,
|
||||
events: _.extend({}, FieldMonetary.prototype.events, {
|
||||
'focusin': '_onFocusFormulaField',
|
||||
'focusout': '_onBlurFormulaField',
|
||||
}),
|
||||
});
|
||||
|
||||
return {
|
||||
FormulaFieldMixin: FormulaFieldMixin,
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user