Merge lp:~gkliska/server-env-tools/server-env-tools-61 into lp:~server-env-tools-core-editors/server-env-tools/6.1

Proposed by Goran Kliska
Status: Needs review
Proposed branch: lp:~gkliska/server-env-tools/server-env-tools-61
Merge into: lp:~server-env-tools-core-editors/server-env-tools/6.1
Diff against target: 303 lines (+284/-0)
3 files modified
web_base/__init__.py (+22/-0)
web_base/__openerp__.py (+69/-0)
web_base/static/src/js/view_form_base.js (+193/-0)
To merge this branch: bzr merge lp:~gkliska/server-env-tools/server-env-tools-61
Reviewer Review Type Date Requested Status
Pedro Manuel Baeza Abstain
Review via email: mp+204699@code.launchpad.net

Description of the change

New web module for 6.1 web client.
1.Fixing wishlist: Fields with attribute readonly=True do not preserve on_change values
         https://bugs.launchpad.net/openerp-web/+bug/378824 Reported by Ferdinand on 2009-05-20
         If field is (readonly and required and dirty) then it is "readonly_writable". 3 LOC
2.Allowing parent.field for in attrs
         Example: <field name="amount" attrs="{'readonly':[('*parent.*entry_type','!=','amount')],'required':[('*parent.*entry_type','!=','amount')]}"/>

To post a comment you must log in.
Revision history for this message
Pedro Manuel Baeza (pedro.baeza) wrote :

Don't you think this is better as a bugfix in OCB branch?

Regards.

review: Needs Information
Revision history for this message
Goran Kliska (gkliska) wrote :

@Pedro
Yes,
but I did it in a few hours using Chrome debugger (first time with OpenERP) and patching web client directly.
This is my first web module and I wrote it without basic knowledge about OE web client.
Results of my tests are: 1. It is not throwing errors, 2. It's working on my test case (one2many form view),
but I don't know will it produce some unwanted side effects.
After all, this "wishlist" is from 2009 - for sure it must be more than 3LOC patch.

IMO My proposal needs review from someone with deeper understanding of web client before it can be considered OCB quality.
I am puzzled in L:193 with how deep this.view.widget_parent.widget_parent.... must go to reliably find parent data set.

In my TODO list regarding this is:
  1. Make attrs="{'readonly':[('product_id.uom_alternatives','!=',True)]} possible.
     I don't know (yet) how to prefill fields with something like this this.view.fields[product_id][uom_alternatives]
  2. Duplicate this funcionality for v8

I didn't know that OCB is mandatory for OCA modules.
All I know - No more dummy fields in my modules.

BRGDS

Revision history for this message
Pedro Manuel Baeza (pedro.baeza) wrote :

OK then, I let then the review to someone with JS skills (it's one of my pendings).

Regards.

review: Abstain
Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

> I didn't know that OCB is mandatory for OCA modules.

They shouldn't require OCB. If you see incompatibilities in modules with the OpenERP branches (not OCB), please report them as bugs.

Regarding your proposal, I can't help.

Unmerged revisions

44. By Slobodni programi

New module web_base

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'web_base'
=== added file 'web_base/__init__.py'
--- web_base/__init__.py 1970-01-01 00:00:00 +0000
+++ web_base/__init__.py 2014-02-04 14:41:41 +0000
@@ -0,0 +1,22 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# OpenERP, Open Source Management Solution
5# Copyright (C) 2014 Decodio ERP/Slobodni Programi d.o.o. (<http://slobodni-programi.com>).
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
023
=== added file 'web_base/__openerp__.py'
--- web_base/__openerp__.py 1970-01-01 00:00:00 +0000
+++ web_base/__openerp__.py 2014-02-04 14:41:41 +0000
@@ -0,0 +1,69 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# OpenERP, Open Source Management Solution
5# Copyright (C) 2014 Decodio / Slobodni Programi d.o.o. (<http://slobodni-programi.com>).
6# Author: Goran Kliska
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23
24{
25 'name': 'Web Base',
26 'version': '6.3.1.0',
27 'category': 'Borg/Base',
28 'complexity': "normal",
29 "depends": [
30 # 'base_base',
31 'web',
32 ],
33 "js": [
34 'static/src/js/view_form_base.js',
35 # 'static/src/js/view_list_base.js',
36 ],
37 'qweb': [
38 # 'static/xml/*.xml',
39 ],
40 'css': [
41 # 'static/css/*.css',
42 ],
43 'author': 'Decodio - Slobodni programi d.o.o.',
44 'website': 'http://slobodni-programi.com',
45 'installable' : True,
46 'active' : False,
47 # 'auto_install': True,
48 'description':
49 """
50 1. Fixing Wishlist: Fields with attribute readonly=True do not preserve on_change values
51 https://bugs.launchpad.net/openerp-web/+bug/378824 Reported by Ferdinand on 2009-05-20
52 If field is (readonly and required and dirty) then it is "readonly_writable". 3 LOC
53 Example:
54 <field name="uom_id" on_change="onchange_product_uom( ...
55 <field name="base_uom_qty" readonly="1" required="1"/>
56 Method onchange_product_uom(...) is calculating and changing value of
57 "base_uom_qty" field and making it "dirty".
58 Field is readonly and required and it will be saved in the client dataset
59 and sent to orm create and write methods.
60 It is good practice to recalculate all important fields again in create and write methods.
61
62 2. Allowing parent.field for in attrs
63 Example: <field name="amount" attrs="{'readonly':[('parent.entry_type','!=','amount')],'required':[('parent.entry_type','!=','amount')]}"/>
64 """,
65 'data': [],
66 'demo_xml': [],
67 'images': [],
68}
69# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
070
=== added directory 'web_base/static'
=== added directory 'web_base/static/src'
=== added directory 'web_base/static/src/js'
=== added file 'web_base/static/src/js/view_form_base.js'
--- web_base/static/src/js/view_form_base.js 1970-01-01 00:00:00 +0000
+++ web_base/static/src/js/view_form_base.js 2014-02-04 14:41:41 +0000
@@ -0,0 +1,193 @@
1openerp.web_base = function(openerp) {
2var QWeb = openerp.web.qweb,
3 _t = openerp.web._t,
4 _lt = openerp.web._lt;
5
6openerp.web.form.Field = openerp.web.form.Field.extend({
7
8 is_dirty: function() {
9 // DECODIO KGB START Save readony required dirty
10 //return this.dirty && !this.readonly;
11 return this.dirty && ( !this.readonly || (this.required && this.readonly));
12 }
13});
14
15
16openerp.web.FormView = openerp.web.FormView.extend({
17 do_save: function(success, prepend_on_create) {
18 var self = this;
19 return this.mutating_mutex.exec(function() { return self.is_initialized.pipe(function() {
20 try {
21 var form_invalid = false,
22 values = {},
23 first_invalid_field = null;
24 for (var f in self.fields) {
25 f = self.fields[f];
26 if (!f.is_valid()) {
27 form_invalid = true;
28 if (!first_invalid_field) {
29 first_invalid_field = f;
30 }
31 } else if (f.name !== 'id' && !f.readonly && (!self.datarecord.id || f.is_dirty())) {
32 // Special case 'id' field, do not save this field
33 // on 'create' : save all non readonly fields
34 // on 'edit' : save non readonly modified fields
35 values[f.name] = f.get_value();
36 // DECODIO KGB START Save readony required dirty
37 } else if (f.name !== 'id' && f.readonly && f.required && f.is_dirty()) {
38 values[f.name] = f.get_value();
39 // DECODIO KGB END Save readony required dirty
40 }
41 f.update_dom(true);
42 }
43 if (form_invalid) {
44 first_invalid_field.focus();
45 self.on_invalid();
46 return $.Deferred().reject();
47 } else {
48 var save_deferral;
49 if (!self.datarecord.id) {
50 //console.log("FormView(", self, ") : About to create", values);
51 save_deferral = self.dataset.create(values).pipe(function(r) {
52 return self.on_created(r, undefined, prepend_on_create);
53 }, null);
54 } else if (_.isEmpty(values) && ! self.force_dirty) {
55 //console.log("FormView(", self, ") : Nothing to save");
56 save_deferral = $.Deferred().resolve({}).promise();
57 } else {
58 self.force_dirty = false;
59 //console.log("FormView(", self, ") : About to save", values);
60 save_deferral = self.dataset.write(self.datarecord.id, values, {}).pipe(function(r) {
61 return self.on_saved(r);
62 }, null);
63 }
64 return save_deferral.then(success);
65 }
66 } catch (e) {
67 console.error(e);
68 return $.Deferred().reject();
69 }
70 });});
71 },
72
73});
74
75openerp.web.form.Widget = openerp.web.form.Widget.extend({
76
77 process_modifiers: function() {
78 var compute_domain = openerp.web.form.compute_domain;
79 /** DECODIO START KGB allow parent.field in attribs */
80 // trying to find (guesswork) parent fields values
81 var parent_fields;
82 var i=0;
83 tmp_parent = this.view.widget_parent;
84 while (i<10) {
85 if (tmp_parent && tmp_parent.model){
86 if (tmp_parent.model !== this.view.model) {
87 parent_fields = tmp_parent.fields;
88 break;
89 }
90 }
91 if (tmp_parent.widget_parent){
92 tmp_parent = tmp_parent.widget_parent;
93 } else {
94 parent_fields = false;
95 break;
96 }
97 i++;
98 }
99 for (var a in this.modifiers) {
100 //this[a] = compute_domain(this.modifiers[a], this.view.fields);
101 this[a] = compute_domain(this.modifiers[a], this.view.fields, parent_fields);
102 }
103 }
104});
105
106
107/** DECODIO KGB allow parent.field in attribs */
108openerp.web.form.compute_domain = function(expr, fields, parent_fields) {
109 var stack = [];
110 for (var i = expr.length - 1; i >= 0; i--) {
111 var ex = expr[i];
112 if (ex.length == 1) {
113 var top = stack.pop();
114 switch (ex) {
115 case '|':
116 stack.push(stack.pop() || top);
117 continue;
118 case '&':
119 stack.push(stack.pop() && top);
120 continue;
121 case '!':
122 stack.push(!top);
123 continue;
124 default:
125 throw new Error(_.str.sprintf(
126 _t("Unknown operator %s in domain %s"),
127 ex, JSON.stringify(expr)));
128 }
129 }
130
131 var field = fields[ex[0]];
132 /** DECODIO START KGB allow parent.field in attribs */
133 var parent_field;
134 var splitted;
135 if (parent_fields && !field ) {
136 splitted = ex[0].split('.');
137 if (splitted.length > 1 && splitted[0] === "parent") {
138 parent_field = parent_fields[splitted[1]];
139 }
140 }
141 if ((!field) && (!parent_field)) {
142 throw new Error(_.str.sprintf(
143 _t("Unknown field %s in domain %s"),
144 ex[0], JSON.stringify(expr)));
145 }
146 if (field) {
147 var field_value = field.get_value ? fields[ex[0]].get_value() : fields[ex[0]].value;
148 }
149 if (parent_field) {
150 var field_value = parent_field.get_value ? parent_fields[splitted[1]].get_value() : parent_fields[splitted[1]].value;
151 }
152 /** DECODIO END KGB allow parent.field in attribs */
153 var op = ex[1];
154 var val = ex[2];
155
156 switch (op.toLowerCase()) {
157 case '=':
158 case '==':
159 stack.push(field_value == val);
160 break;
161 case '!=':
162 case '<>':
163 stack.push(field_value != val);
164 break;
165 case '<':
166 stack.push(field_value < val);
167 break;
168 case '>':
169 stack.push(field_value > val);
170 break;
171 case '<=':
172 stack.push(field_value <= val);
173 break;
174 case '>=':
175 stack.push(field_value >= val);
176 break;
177 case 'in':
178 if (!_.isArray(val)) val = [val];
179 stack.push(_(val).contains(field_value));
180 break;
181 case 'not in':
182 if (!_.isArray(val)) val = [val];
183 stack.push(!_(val).contains(field_value));
184 break;
185 default:
186 console.warn(
187 _t("Unsupported operator %s in domain %s"),
188 op, JSON.stringify(expr));
189 }
190 }
191 return _.all(stack, _.identity);
192};
193};
0\ No newline at end of file194\ No newline at end of file

Subscribers

People subscribed via source and target branches