tryton-sao 8.0.2 → 8.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG +10 -0
- package/dist/tryton-sao.css +5 -0
- package/dist/tryton-sao.js +72 -34
- package/package.json +1 -1
- package/src/common.js +29 -1
- package/src/rpc.js +5 -7
- package/src/sao.js +1 -1
- package/src/sao.less +5 -0
- package/src/session.js +19 -16
- package/src/view/form.js +2 -3
- package/src/view/list_form.js +1 -0
- package/src/view/tree.js +1 -1
- package/src/wizard.js +14 -5
- package/tests/sao.js +34 -0
package/CHANGELOG
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
|
|
2
|
+
Version 8.0.4 - 2026-06-02
|
|
3
|
+
--------------------------
|
|
4
|
+
* Bug fixes (see mercurial logs for details)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Version 8.0.3 - 2026-05-20
|
|
8
|
+
--------------------------
|
|
9
|
+
* Bug fixes (see mercurial logs for details)
|
|
10
|
+
|
|
11
|
+
|
|
2
12
|
Version 8.0.2 - 2026-05-02
|
|
3
13
|
--------------------------
|
|
4
14
|
* Bug fixes (see mercurial logs for details)
|
package/dist/tryton-sao.css
CHANGED
|
@@ -10077,6 +10077,10 @@ img.icon {
|
|
|
10077
10077
|
height: 1.42857143em;
|
|
10078
10078
|
display: block;
|
|
10079
10079
|
}
|
|
10080
|
+
[dir="rtl"] .treeview > table.tree img.column-affix,
|
|
10081
|
+
[dir="rtl"] .treeview > table.tree a.column-affix > img {
|
|
10082
|
+
transform: scaleX(-1);
|
|
10083
|
+
}
|
|
10080
10084
|
.treeview > table.tree tr.more-row {
|
|
10081
10085
|
text-align: center;
|
|
10082
10086
|
}
|
|
@@ -10196,6 +10200,7 @@ img.icon {
|
|
|
10196
10200
|
}
|
|
10197
10201
|
[dir="rtl"] .treeview .expander > img {
|
|
10198
10202
|
float: right;
|
|
10203
|
+
transform: scaleX(-1);
|
|
10199
10204
|
}
|
|
10200
10205
|
.treeview label {
|
|
10201
10206
|
font-weight: normal;
|
package/dist/tryton-sao.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
/* eslint-disable no-redeclare */
|
|
5
5
|
var Sao = {
|
|
6
|
-
__version__: '8.0.
|
|
6
|
+
__version__: '8.0.4',
|
|
7
7
|
};
|
|
8
8
|
/* eslint-enable no-redeclare */
|
|
9
9
|
|
|
@@ -1490,11 +1490,6 @@ var Sao = {
|
|
|
1490
1490
|
};
|
|
1491
1491
|
|
|
1492
1492
|
var ajax_error = function(query, status_, error) {
|
|
1493
|
-
if (!process_exception) {
|
|
1494
|
-
console.debug(`RPC error calling ${args}: ${status_}: ${error}.`);
|
|
1495
|
-
dfd.reject();
|
|
1496
|
-
return;
|
|
1497
|
-
}
|
|
1498
1493
|
if (query.status == 503) {
|
|
1499
1494
|
this.retries++;
|
|
1500
1495
|
if (this.retries < 5) {
|
|
@@ -1520,8 +1515,7 @@ var Sao = {
|
|
|
1520
1515
|
}
|
|
1521
1516
|
return;
|
|
1522
1517
|
}
|
|
1523
|
-
}
|
|
1524
|
-
if (query.status == 401) {
|
|
1518
|
+
} else if (query.status == 401) {
|
|
1525
1519
|
//Try to relog
|
|
1526
1520
|
Sao.Session.renew(session).then(function() {
|
|
1527
1521
|
if (async) {
|
|
@@ -1531,6 +1525,10 @@ var Sao = {
|
|
|
1531
1525
|
dfd.resolve();
|
|
1532
1526
|
}
|
|
1533
1527
|
}, dfd.reject);
|
|
1528
|
+
} else if (!process_exception) {
|
|
1529
|
+
console.debug(`RPC error calling ${args}: ${status_}: ${error}.`);
|
|
1530
|
+
dfd.reject();
|
|
1531
|
+
return;
|
|
1534
1532
|
} else {
|
|
1535
1533
|
var err_msg = `[${query.status}] ${error}`;
|
|
1536
1534
|
Sao.common.message.run(
|
|
@@ -2761,7 +2759,7 @@ var Sao = {
|
|
|
2761
2759
|
'contentType': 'application/json',
|
|
2762
2760
|
'data': JSON.stringify(args),
|
|
2763
2761
|
'dataType': 'json',
|
|
2764
|
-
'url':
|
|
2762
|
+
'url': (this.database || '.') + '/rpc/#' + args.method,
|
|
2765
2763
|
'type': 'post',
|
|
2766
2764
|
});
|
|
2767
2765
|
},
|
|
@@ -2859,15 +2857,16 @@ var Sao = {
|
|
|
2859
2857
|
|
|
2860
2858
|
Sao.Session.server_version = function() {
|
|
2861
2859
|
var timeoutID = Sao.common.processing.show();
|
|
2862
|
-
|
|
2863
|
-
'contentType': 'application/json',
|
|
2864
|
-
'data': JSON.stringify({
|
|
2860
|
+
let args = {
|
|
2865
2861
|
'id': 0,
|
|
2866
2862
|
'method': 'common.server.version',
|
|
2867
2863
|
'params': []
|
|
2868
|
-
}
|
|
2864
|
+
};
|
|
2865
|
+
return jQuery.ajax({
|
|
2866
|
+
'contentType': 'application/json',
|
|
2867
|
+
'data': JSON.stringify(args),
|
|
2869
2868
|
'dataType': 'json',
|
|
2870
|
-
'url': 'rpc
|
|
2869
|
+
'url': 'rpc/#' + args.method,
|
|
2871
2870
|
'type': 'post',
|
|
2872
2871
|
'complete': [function() {
|
|
2873
2872
|
Sao.common.processing.hide(timeoutID);
|
|
@@ -3272,15 +3271,16 @@ var Sao = {
|
|
|
3272
3271
|
|
|
3273
3272
|
Sao.DB.list = function() {
|
|
3274
3273
|
var timeoutID = Sao.common.processing.show();
|
|
3275
|
-
|
|
3276
|
-
'contentType': 'application/json',
|
|
3277
|
-
'data': JSON.stringify({
|
|
3274
|
+
let args = {
|
|
3278
3275
|
'id': 0,
|
|
3279
3276
|
'method': 'common.db.list',
|
|
3280
3277
|
'params': []
|
|
3281
|
-
}
|
|
3278
|
+
};
|
|
3279
|
+
return jQuery.ajax({
|
|
3280
|
+
'contentType': 'application/json',
|
|
3281
|
+
'data': JSON.stringify(args),
|
|
3282
3282
|
'dataType': 'json',
|
|
3283
|
-
'url': 'rpc
|
|
3283
|
+
'url': 'rpc/#' + args.method,
|
|
3284
3284
|
'type': 'post',
|
|
3285
3285
|
'complete': [function() {
|
|
3286
3286
|
Sao.common.processing.hide(timeoutID);
|
|
@@ -3294,15 +3294,16 @@ var Sao = {
|
|
|
3294
3294
|
|
|
3295
3295
|
Sao.Authentication.services = function() {
|
|
3296
3296
|
var timeoutID = Sao.common.processing.show();
|
|
3297
|
-
|
|
3298
|
-
'contentType': 'application/json',
|
|
3299
|
-
'data': JSON.stringify({
|
|
3297
|
+
let args = {
|
|
3300
3298
|
'id': 0,
|
|
3301
3299
|
'method': 'common.authentication.services',
|
|
3302
3300
|
'params': []
|
|
3303
|
-
}
|
|
3301
|
+
}
|
|
3302
|
+
return jQuery.ajax({
|
|
3303
|
+
'contentType': 'application/json',
|
|
3304
|
+
'data': JSON.stringify(args),
|
|
3304
3305
|
'dataType': 'json',
|
|
3305
|
-
'url': 'rpc
|
|
3306
|
+
'url': 'rpc/#' + args.method,
|
|
3306
3307
|
'type': 'post',
|
|
3307
3308
|
'complete': [function() {
|
|
3308
3309
|
Sao.common.processing.hide(timeoutID);
|
|
@@ -4962,7 +4963,9 @@ var Sao = {
|
|
|
4962
4963
|
};
|
|
4963
4964
|
|
|
4964
4965
|
var complete_datetime = function() {
|
|
4965
|
-
return [Sao.Date(), Sao.DateTime(
|
|
4966
|
+
return [Sao.Date(), Sao.DateTime(
|
|
4967
|
+
undefined, undefined, undefined,
|
|
4968
|
+
0, 0, 0, 0, true)];
|
|
4966
4969
|
};
|
|
4967
4970
|
|
|
4968
4971
|
var complete_date = function() {
|
|
@@ -5269,6 +5272,32 @@ var Sao = {
|
|
|
5269
5272
|
]);
|
|
5270
5273
|
return;
|
|
5271
5274
|
}
|
|
5275
|
+
if ((typeof value == 'string') &&
|
|
5276
|
+
['datetime', 'timestamp'].includes(field.type) &&
|
|
5277
|
+
(operator == '=')) {
|
|
5278
|
+
let ctx, format_, parsed_date;
|
|
5279
|
+
if (this.context && Object.keys(this.context).length) {
|
|
5280
|
+
ctx = this.context;
|
|
5281
|
+
} else {
|
|
5282
|
+
ctx = {};
|
|
5283
|
+
}
|
|
5284
|
+
format_ = Sao.common.date_format(ctx.date_format);
|
|
5285
|
+
parsed_date = Sao.common.parse_date(format_, value);
|
|
5286
|
+
if (parsed_date &&
|
|
5287
|
+
(Sao.common.format_date(format_, parsed_date) == value)) {
|
|
5288
|
+
let date = Sao.DateTime.combine(parsed_date, Sao.Time());
|
|
5289
|
+
let next_day = Sao.DateTime(
|
|
5290
|
+
date.year(), date.month(), date.date(),
|
|
5291
|
+
date.hour(), date.minute(), date.second(),
|
|
5292
|
+
date.millisecond())
|
|
5293
|
+
next_day.add(1, 'day');
|
|
5294
|
+
result.push(this._clausify([
|
|
5295
|
+
[field_name, '>=', date],
|
|
5296
|
+
[field_name, '<', next_day]
|
|
5297
|
+
]));
|
|
5298
|
+
return;
|
|
5299
|
+
}
|
|
5300
|
+
}
|
|
5272
5301
|
}
|
|
5273
5302
|
if (['many2one', 'one2many', 'many2many', 'one2one',
|
|
5274
5303
|
'many2many', 'one2one'].includes(field.type) && value) {
|
|
@@ -19155,9 +19184,8 @@ function eval_pyson(value){
|
|
|
19155
19184
|
if (record) {
|
|
19156
19185
|
var fields = this.screen.current_view.get_fields();
|
|
19157
19186
|
if (!record.validate(fields)) {
|
|
19158
|
-
this.screen.display(true);
|
|
19159
|
-
prm
|
|
19160
|
-
return;
|
|
19187
|
+
this.screen.display(true).always(() => prm.reject());
|
|
19188
|
+
return prm;
|
|
19161
19189
|
}
|
|
19162
19190
|
if (this.screen.pre_validate) {
|
|
19163
19191
|
return record.pre_validate().then(
|
|
@@ -23901,7 +23929,7 @@ function eval_pyson(value){
|
|
|
23901
23929
|
fields, false, false)) {
|
|
23902
23930
|
var value = cell.prop('checked');
|
|
23903
23931
|
this.field.set_client(record, value);
|
|
23904
|
-
if (record !== current_record) {
|
|
23932
|
+
if ((!this.group.parent) & (record !== current_record)) {
|
|
23905
23933
|
// we can not rely on editable tree handler to save the row
|
|
23906
23934
|
record.save();
|
|
23907
23935
|
}
|
|
@@ -25452,6 +25480,7 @@ function eval_pyson(value){
|
|
|
25452
25480
|
},
|
|
25453
25481
|
button_clicked: function(event) {
|
|
25454
25482
|
if (Sao.common.compare(this.screen.selected_records, [this.record])) {
|
|
25483
|
+
event.stopPropagation();
|
|
25455
25484
|
Sao.View.ListGroupViewForm._super.button_clicked.call(this, event);
|
|
25456
25485
|
}
|
|
25457
25486
|
}
|
|
@@ -28826,6 +28855,7 @@ function eval_pyson(value){
|
|
|
28826
28855
|
if (this.__processing || this.__waiting_response) {
|
|
28827
28856
|
return jQuery.when();
|
|
28828
28857
|
}
|
|
28858
|
+
this.__processing = true;
|
|
28829
28859
|
var process = function() {
|
|
28830
28860
|
if (this.state == this.end_state) {
|
|
28831
28861
|
return this.end();
|
|
@@ -28884,8 +28914,8 @@ function eval_pyson(value){
|
|
|
28884
28914
|
} else {
|
|
28885
28915
|
prms.push(execute_actions());
|
|
28886
28916
|
}
|
|
28887
|
-
|
|
28888
|
-
|
|
28917
|
+
return jQuery.when.apply(jQuery, prms).then(
|
|
28918
|
+
() => this.__processing = false);
|
|
28889
28919
|
}, result => {
|
|
28890
28920
|
if (!result || !this.screen) {
|
|
28891
28921
|
this.state = this.end_state;
|
|
@@ -29008,11 +29038,14 @@ function eval_pyson(value){
|
|
|
29008
29038
|
this.footer.empty();
|
|
29009
29039
|
},
|
|
29010
29040
|
_get_button: function(definition) {
|
|
29041
|
+
let state = this.state;
|
|
29011
29042
|
var button = Sao.Wizard.Form._super._get_button.call(this,
|
|
29012
29043
|
definition);
|
|
29013
29044
|
this.footer.append(button.el);
|
|
29014
29045
|
button.el.click(() => {
|
|
29015
|
-
this.
|
|
29046
|
+
if (this.state === state) {
|
|
29047
|
+
this.response(definition);
|
|
29048
|
+
}
|
|
29016
29049
|
});
|
|
29017
29050
|
return button;
|
|
29018
29051
|
},
|
|
@@ -29060,19 +29093,24 @@ function eval_pyson(value){
|
|
|
29060
29093
|
this.footer.empty();
|
|
29061
29094
|
},
|
|
29062
29095
|
_get_button: function(definition) {
|
|
29096
|
+
let state = this.state;
|
|
29063
29097
|
var button = Sao.Wizard.Dialog._super._get_button.call(this,
|
|
29064
29098
|
definition);
|
|
29065
29099
|
this.footer.append(button.el);
|
|
29066
29100
|
if (definition['default']) {
|
|
29067
29101
|
this.content.unbind('submit');
|
|
29068
29102
|
this.content.submit(e => {
|
|
29069
|
-
this.response(definition);
|
|
29070
29103
|
e.preventDefault();
|
|
29104
|
+
if (this.state === state) {
|
|
29105
|
+
this.response(definition);
|
|
29106
|
+
}
|
|
29071
29107
|
});
|
|
29072
29108
|
button.el.attr('type', 'submit');
|
|
29073
29109
|
} else {
|
|
29074
29110
|
button.el.click(() => {
|
|
29075
|
-
this.
|
|
29111
|
+
if (this.state === state) {
|
|
29112
|
+
this.response(definition);
|
|
29113
|
+
}
|
|
29076
29114
|
});
|
|
29077
29115
|
}
|
|
29078
29116
|
return button;
|
package/package.json
CHANGED
package/src/common.js
CHANGED
|
@@ -1644,7 +1644,9 @@
|
|
|
1644
1644
|
};
|
|
1645
1645
|
|
|
1646
1646
|
var complete_datetime = function() {
|
|
1647
|
-
return [Sao.Date(), Sao.DateTime(
|
|
1647
|
+
return [Sao.Date(), Sao.DateTime(
|
|
1648
|
+
undefined, undefined, undefined,
|
|
1649
|
+
0, 0, 0, 0, true)];
|
|
1648
1650
|
};
|
|
1649
1651
|
|
|
1650
1652
|
var complete_date = function() {
|
|
@@ -1951,6 +1953,32 @@
|
|
|
1951
1953
|
]);
|
|
1952
1954
|
return;
|
|
1953
1955
|
}
|
|
1956
|
+
if ((typeof value == 'string') &&
|
|
1957
|
+
['datetime', 'timestamp'].includes(field.type) &&
|
|
1958
|
+
(operator == '=')) {
|
|
1959
|
+
let ctx, format_, parsed_date;
|
|
1960
|
+
if (this.context && Object.keys(this.context).length) {
|
|
1961
|
+
ctx = this.context;
|
|
1962
|
+
} else {
|
|
1963
|
+
ctx = {};
|
|
1964
|
+
}
|
|
1965
|
+
format_ = Sao.common.date_format(ctx.date_format);
|
|
1966
|
+
parsed_date = Sao.common.parse_date(format_, value);
|
|
1967
|
+
if (parsed_date &&
|
|
1968
|
+
(Sao.common.format_date(format_, parsed_date) == value)) {
|
|
1969
|
+
let date = Sao.DateTime.combine(parsed_date, Sao.Time());
|
|
1970
|
+
let next_day = Sao.DateTime(
|
|
1971
|
+
date.year(), date.month(), date.date(),
|
|
1972
|
+
date.hour(), date.minute(), date.second(),
|
|
1973
|
+
date.millisecond())
|
|
1974
|
+
next_day.add(1, 'day');
|
|
1975
|
+
result.push(this._clausify([
|
|
1976
|
+
[field_name, '>=', date],
|
|
1977
|
+
[field_name, '<', next_day]
|
|
1978
|
+
]));
|
|
1979
|
+
return;
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1954
1982
|
}
|
|
1955
1983
|
if (['many2one', 'one2many', 'many2many', 'one2one',
|
|
1956
1984
|
'many2many', 'one2one'].includes(field.type) && value) {
|
package/src/rpc.js
CHANGED
|
@@ -119,11 +119,6 @@
|
|
|
119
119
|
};
|
|
120
120
|
|
|
121
121
|
var ajax_error = function(query, status_, error) {
|
|
122
|
-
if (!process_exception) {
|
|
123
|
-
console.debug(`RPC error calling ${args}: ${status_}: ${error}.`);
|
|
124
|
-
dfd.reject();
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
122
|
if (query.status == 503) {
|
|
128
123
|
this.retries++;
|
|
129
124
|
if (this.retries < 5) {
|
|
@@ -149,8 +144,7 @@
|
|
|
149
144
|
}
|
|
150
145
|
return;
|
|
151
146
|
}
|
|
152
|
-
}
|
|
153
|
-
if (query.status == 401) {
|
|
147
|
+
} else if (query.status == 401) {
|
|
154
148
|
//Try to relog
|
|
155
149
|
Sao.Session.renew(session).then(function() {
|
|
156
150
|
if (async) {
|
|
@@ -160,6 +154,10 @@
|
|
|
160
154
|
dfd.resolve();
|
|
161
155
|
}
|
|
162
156
|
}, dfd.reject);
|
|
157
|
+
} else if (!process_exception) {
|
|
158
|
+
console.debug(`RPC error calling ${args}: ${status_}: ${error}.`);
|
|
159
|
+
dfd.reject();
|
|
160
|
+
return;
|
|
163
161
|
} else {
|
|
164
162
|
var err_msg = `[${query.status}] ${error}`;
|
|
165
163
|
Sao.common.message.run(
|
package/src/sao.js
CHANGED
package/src/sao.less
CHANGED
|
@@ -1025,6 +1025,10 @@ img.icon {
|
|
|
1025
1025
|
width: unit(@line-height-base, em);
|
|
1026
1026
|
height: unit(@line-height-base, em);
|
|
1027
1027
|
display: block;
|
|
1028
|
+
|
|
1029
|
+
[dir="rtl"] & {
|
|
1030
|
+
transform: scaleX(-1);
|
|
1031
|
+
}
|
|
1028
1032
|
}
|
|
1029
1033
|
|
|
1030
1034
|
tr.more-row {
|
|
@@ -1118,6 +1122,7 @@ img.icon {
|
|
|
1118
1122
|
float: left;
|
|
1119
1123
|
[dir="rtl"] & {
|
|
1120
1124
|
float: right;
|
|
1125
|
+
transform: scaleX(-1);
|
|
1121
1126
|
}
|
|
1122
1127
|
width: unit(@line-height-base, em);
|
|
1123
1128
|
height: unit(@line-height-base, em);
|
package/src/session.js
CHANGED
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
'contentType': 'application/json',
|
|
84
84
|
'data': JSON.stringify(args),
|
|
85
85
|
'dataType': 'json',
|
|
86
|
-
'url':
|
|
86
|
+
'url': (this.database || '.') + '/rpc/#' + args.method,
|
|
87
87
|
'type': 'post',
|
|
88
88
|
});
|
|
89
89
|
},
|
|
@@ -181,15 +181,16 @@
|
|
|
181
181
|
|
|
182
182
|
Sao.Session.server_version = function() {
|
|
183
183
|
var timeoutID = Sao.common.processing.show();
|
|
184
|
-
|
|
185
|
-
'contentType': 'application/json',
|
|
186
|
-
'data': JSON.stringify({
|
|
184
|
+
let args = {
|
|
187
185
|
'id': 0,
|
|
188
186
|
'method': 'common.server.version',
|
|
189
187
|
'params': []
|
|
190
|
-
}
|
|
188
|
+
};
|
|
189
|
+
return jQuery.ajax({
|
|
190
|
+
'contentType': 'application/json',
|
|
191
|
+
'data': JSON.stringify(args),
|
|
191
192
|
'dataType': 'json',
|
|
192
|
-
'url': 'rpc
|
|
193
|
+
'url': 'rpc/#' + args.method,
|
|
193
194
|
'type': 'post',
|
|
194
195
|
'complete': [function() {
|
|
195
196
|
Sao.common.processing.hide(timeoutID);
|
|
@@ -594,15 +595,16 @@
|
|
|
594
595
|
|
|
595
596
|
Sao.DB.list = function() {
|
|
596
597
|
var timeoutID = Sao.common.processing.show();
|
|
597
|
-
|
|
598
|
-
'contentType': 'application/json',
|
|
599
|
-
'data': JSON.stringify({
|
|
598
|
+
let args = {
|
|
600
599
|
'id': 0,
|
|
601
600
|
'method': 'common.db.list',
|
|
602
601
|
'params': []
|
|
603
|
-
}
|
|
602
|
+
};
|
|
603
|
+
return jQuery.ajax({
|
|
604
|
+
'contentType': 'application/json',
|
|
605
|
+
'data': JSON.stringify(args),
|
|
604
606
|
'dataType': 'json',
|
|
605
|
-
'url': 'rpc
|
|
607
|
+
'url': 'rpc/#' + args.method,
|
|
606
608
|
'type': 'post',
|
|
607
609
|
'complete': [function() {
|
|
608
610
|
Sao.common.processing.hide(timeoutID);
|
|
@@ -616,15 +618,16 @@
|
|
|
616
618
|
|
|
617
619
|
Sao.Authentication.services = function() {
|
|
618
620
|
var timeoutID = Sao.common.processing.show();
|
|
619
|
-
|
|
620
|
-
'contentType': 'application/json',
|
|
621
|
-
'data': JSON.stringify({
|
|
621
|
+
let args = {
|
|
622
622
|
'id': 0,
|
|
623
623
|
'method': 'common.authentication.services',
|
|
624
624
|
'params': []
|
|
625
|
-
}
|
|
625
|
+
}
|
|
626
|
+
return jQuery.ajax({
|
|
627
|
+
'contentType': 'application/json',
|
|
628
|
+
'data': JSON.stringify(args),
|
|
626
629
|
'dataType': 'json',
|
|
627
|
-
'url': 'rpc
|
|
630
|
+
'url': 'rpc/#' + args.method,
|
|
628
631
|
'type': 'post',
|
|
629
632
|
'complete': [function() {
|
|
630
633
|
Sao.common.processing.hide(timeoutID);
|
package/src/view/form.js
CHANGED
|
@@ -3959,9 +3959,8 @@ function eval_pyson(value){
|
|
|
3959
3959
|
if (record) {
|
|
3960
3960
|
var fields = this.screen.current_view.get_fields();
|
|
3961
3961
|
if (!record.validate(fields)) {
|
|
3962
|
-
this.screen.display(true);
|
|
3963
|
-
prm
|
|
3964
|
-
return;
|
|
3962
|
+
this.screen.display(true).always(() => prm.reject());
|
|
3963
|
+
return prm;
|
|
3965
3964
|
}
|
|
3966
3965
|
if (this.screen.pre_validate) {
|
|
3967
3966
|
return record.pre_validate().then(
|
package/src/view/list_form.js
CHANGED
package/src/view/tree.js
CHANGED
|
@@ -2791,7 +2791,7 @@
|
|
|
2791
2791
|
fields, false, false)) {
|
|
2792
2792
|
var value = cell.prop('checked');
|
|
2793
2793
|
this.field.set_client(record, value);
|
|
2794
|
-
if (record !== current_record) {
|
|
2794
|
+
if ((!this.group.parent) & (record !== current_record)) {
|
|
2795
2795
|
// we can not rely on editable tree handler to save the row
|
|
2796
2796
|
record.save();
|
|
2797
2797
|
}
|
package/src/wizard.js
CHANGED
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
if (this.__processing || this.__waiting_response) {
|
|
56
56
|
return jQuery.when();
|
|
57
57
|
}
|
|
58
|
+
this.__processing = true;
|
|
58
59
|
var process = function() {
|
|
59
60
|
if (this.state == this.end_state) {
|
|
60
61
|
return this.end();
|
|
@@ -113,8 +114,8 @@
|
|
|
113
114
|
} else {
|
|
114
115
|
prms.push(execute_actions());
|
|
115
116
|
}
|
|
116
|
-
|
|
117
|
-
|
|
117
|
+
return jQuery.when.apply(jQuery, prms).then(
|
|
118
|
+
() => this.__processing = false);
|
|
118
119
|
}, result => {
|
|
119
120
|
if (!result || !this.screen) {
|
|
120
121
|
this.state = this.end_state;
|
|
@@ -237,11 +238,14 @@
|
|
|
237
238
|
this.footer.empty();
|
|
238
239
|
},
|
|
239
240
|
_get_button: function(definition) {
|
|
241
|
+
let state = this.state;
|
|
240
242
|
var button = Sao.Wizard.Form._super._get_button.call(this,
|
|
241
243
|
definition);
|
|
242
244
|
this.footer.append(button.el);
|
|
243
245
|
button.el.click(() => {
|
|
244
|
-
this.
|
|
246
|
+
if (this.state === state) {
|
|
247
|
+
this.response(definition);
|
|
248
|
+
}
|
|
245
249
|
});
|
|
246
250
|
return button;
|
|
247
251
|
},
|
|
@@ -289,19 +293,24 @@
|
|
|
289
293
|
this.footer.empty();
|
|
290
294
|
},
|
|
291
295
|
_get_button: function(definition) {
|
|
296
|
+
let state = this.state;
|
|
292
297
|
var button = Sao.Wizard.Dialog._super._get_button.call(this,
|
|
293
298
|
definition);
|
|
294
299
|
this.footer.append(button.el);
|
|
295
300
|
if (definition['default']) {
|
|
296
301
|
this.content.unbind('submit');
|
|
297
302
|
this.content.submit(e => {
|
|
298
|
-
this.response(definition);
|
|
299
303
|
e.preventDefault();
|
|
304
|
+
if (this.state === state) {
|
|
305
|
+
this.response(definition);
|
|
306
|
+
}
|
|
300
307
|
});
|
|
301
308
|
button.el.attr('type', 'submit');
|
|
302
309
|
} else {
|
|
303
310
|
button.el.click(() => {
|
|
304
|
-
this.
|
|
311
|
+
if (this.state === state) {
|
|
312
|
+
this.response(definition);
|
|
313
|
+
}
|
|
305
314
|
});
|
|
306
315
|
}
|
|
307
316
|
return button;
|
package/tests/sao.js
CHANGED
|
@@ -1933,6 +1933,12 @@
|
|
|
1933
1933
|
'name': 'integer',
|
|
1934
1934
|
'type': 'integer'
|
|
1935
1935
|
},
|
|
1936
|
+
'timestamp': {
|
|
1937
|
+
'name': 'timestamp',
|
|
1938
|
+
'string': 'Timestamp',
|
|
1939
|
+
'type': 'timestamp',
|
|
1940
|
+
'format': '"%H:%M:%S"',
|
|
1941
|
+
},
|
|
1936
1942
|
'selection': {
|
|
1937
1943
|
'string': 'Selection',
|
|
1938
1944
|
'name': 'selection',
|
|
@@ -2033,6 +2039,7 @@
|
|
|
2033
2039
|
c(['integer', '>=', 3]),
|
|
2034
2040
|
c(['integer', '<=', 5])
|
|
2035
2041
|
]]],
|
|
2042
|
+
[[c(['Timestamp', null, null])], [c(['timestamp', '=', null])]],
|
|
2036
2043
|
[[c(['Reference', null, 'foo'])],
|
|
2037
2044
|
[c(['reference', 'ilike', '%foo%'])]],
|
|
2038
2045
|
[[c(['Reference', null, 'Spam'])],
|
|
@@ -2073,6 +2080,33 @@
|
|
|
2073
2080
|
QUnit.assert.deepEqual(parser.parse_clause(value), result,
|
|
2074
2081
|
'parse_clause(' + JSON.stringify(value) + ')');
|
|
2075
2082
|
});
|
|
2083
|
+
|
|
2084
|
+
let clause = parser.parse_clause([c(
|
|
2085
|
+
['Timestamp', '=', Sao.common.format_date('%x', Sao.Date(2002, 12, 4))])]);
|
|
2086
|
+
QUnit.assert.strictEqual(clause[0].length, 2);
|
|
2087
|
+
let [ , operator, value] = clause[0][0];
|
|
2088
|
+
QUnit.assert.strictEqual(operator, '>=');
|
|
2089
|
+
QUnit.assert.ok(value.isSame(Sao.Date(2002, 12, 4)));
|
|
2090
|
+
[ , operator, value] = clause[0][1];
|
|
2091
|
+
QUnit.assert.strictEqual(operator, '<');
|
|
2092
|
+
QUnit.assert.ok(value.isSame(Sao.Date(2002, 12, 5)));
|
|
2093
|
+
|
|
2094
|
+
clause = parser.parse_clause([c(
|
|
2095
|
+
['Timestamp', '=',
|
|
2096
|
+
Sao.common.format_datetime('%x %X', Sao.DateTime(2002, 12, 4, 12, 30))])]);
|
|
2097
|
+
[ , operator, value] = clause[0];
|
|
2098
|
+
QUnit.assert.strictEqual(operator, '=');
|
|
2099
|
+
QUnit.assert.ok(value.isSame(Sao.DateTime(2002, 12, 4, 12, 30)));
|
|
2100
|
+
|
|
2101
|
+
clause = parser.parse_clause([c(
|
|
2102
|
+
['Timestamp', null, [
|
|
2103
|
+
`${Sao.common.format_date('%x', Sao.Date(2002, 12, 4))}`,
|
|
2104
|
+
`${Sao.common.format_date('%x', Sao.Date(2002, 12, 5))}`,
|
|
2105
|
+
]])]);
|
|
2106
|
+
[ , operator, value] = clause[0];
|
|
2107
|
+
QUnit.assert.strictEqual(operator, 'in');
|
|
2108
|
+
QUnit.assert.ok(value[0].isSame(Sao.DateTime(2002, 12, 4)));
|
|
2109
|
+
QUnit.assert.ok(value[1].isSame(Sao.DateTime(2002, 12, 5)));
|
|
2076
2110
|
});
|
|
2077
2111
|
|
|
2078
2112
|
QUnit.test('DomainParser.format_value', function() {
|