summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/fields/relational_fields.js64
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js6
-rw-r--r--addons/web/static/src/js/views/field_manager_mixin.js15
-rw-r--r--addons/web/static/src/js/views/form/form_controller.js13
-rw-r--r--addons/web/static/src/js/views/form/form_renderer.js9
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_record.js24
-rw-r--r--addons/web/static/src/js/views/pivot/pivot_model.js26
-rw-r--r--addons/web/static/src/scss/fontawesome_overriden.scss68
-rw-r--r--addons/web/static/src/scss/form_view.scss3
-rw-r--r--addons/web/static/src/scss/kanban_view.scss2
-rw-r--r--addons/web/static/src/scss/search_view_mobile.scss3
11 files changed, 170 insertions, 63 deletions
diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js
index 15b7975aa42..ef916d31ff7 100644
--- a/addons/web/static/src/js/fields/relational_fields.js
+++ b/addons/web/static/src/js/fields/relational_fields.js
@@ -21,6 +21,7 @@ var dialogs = require('web.view_dialogs');
var core = require('web.core');
var data = require('web.data');
var Dialog = require('web.Dialog');
+var KanbanRecord = require('web.KanbanRecord');
var KanbanRenderer = require('web.KanbanRenderer');
var ListRenderer = require('web.ListRenderer');
var Pager = require('web.Pager');
@@ -1407,6 +1408,59 @@ var FieldX2Many = AbstractField.extend({
},
});
+var One2ManyKanbanRecord = KanbanRecord.extend({
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * Apply same logic as in the ListRenderer: buttons with type="object"
+ * are disabled for no saved yet records, as calling the python method
+ * with no id would make no sense.
+ *
+ * To avoid to expose this logic inside all Kanban views, we define
+ * a specific KanbanRecord Class for the One2many case.
+ *
+ * This could be refactored to prevent from duplicating this logic in
+ * list and kanban views.
+ *
+ * @private
+ */
+ _postProcessObjectButtons: function () {
+ var self = this;
+ // if the res_id is defined, it's already correctly handled by the Kanban record global event click
+ if (!this.state.res_id) {
+ this.$('.oe_kanban_action[data-type=object]').each(function (index, button) {
+ var $button = $(button);
+ if ($button.attr('warn')) {
+ $button.on('click', function (e) {
+ e.stopPropagation();
+ self.do_warn(_t('Warning'), _t('Please click on the "save" button first.'));
+ });
+ } else {
+ $button.attr('disabled', 'disabled');
+ }
+ });
+ }
+ },
+ /**
+ * @override
+ * @private
+ */
+ _render: function () {
+ var self = this;
+ return this._super.apply(this, arguments).then(function () {
+ self._postProcessObjectButtons();
+ });
+ },
+});
+
+var One2ManyKanbanRenderer = KanbanRenderer.extend({
+ config: _.extend({}, KanbanRenderer.prototype.config, {
+ KanbanRecord: One2ManyKanbanRecord,
+ }),
+});
+
var FieldOne2Many = FieldX2Many.extend({
className: 'o_field_one2many',
supportedFieldTypes: ['one2many'],
@@ -1461,6 +1515,16 @@ var FieldOne2Many = FieldX2Many.extend({
//--------------------------------------------------------------------------
/**
+ * @override
+ * @private
+ */
+ _getRenderer: function () {
+ if (this.view.arch.tag === 'kanban') {
+ return One2ManyKanbanRenderer;
+ }
+ return this._super.apply(this, arguments);
+ },
+ /**
* Overrides to only render the buttons if the 'create' action is available.
*
* @override
diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js
index 95b6d439ec1..de7fd93d59b 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -3647,6 +3647,7 @@ var BasicModel = AbstractModel.extend({
var res_id, value;
var res_ids = params.res_ids || [];
var data = params.data || (type === 'record' ? {} : []);
+ var context = params.context;
if (type === 'record') {
res_id = params.res_id || (params.data && params.data.id);
if (res_id) {
@@ -3654,6 +3655,9 @@ var BasicModel = AbstractModel.extend({
} else {
res_id = _.uniqueId('virtual_');
}
+ // it doesn't make sense for a record datapoint to have those keys
+ // besides, it will mess up x2m and actions down the line
+ context = _.omit(context, ['orderedBy', 'group_by']);
} else {
var isValueArray = params.value instanceof Array;
res_id = isValueArray ? params.value[0] : undefined;
@@ -3671,7 +3675,7 @@ var BasicModel = AbstractModel.extend({
_domains: {},
_rawChanges: {},
aggregateValues: params.aggregateValues || {},
- context: params.context,
+ context: context,
count: params.count || res_ids.length,
data: data,
domain: params.domain || [],
diff --git a/addons/web/static/src/js/views/field_manager_mixin.js b/addons/web/static/src/js/views/field_manager_mixin.js
index 99aabc6e66d..b02743593a6 100644
--- a/addons/web/static/src/js/views/field_manager_mixin.js
+++ b/addons/web/static/src/js/views/field_manager_mixin.js
@@ -52,6 +52,8 @@ var FieldManagerMixin = {
if (event.data.force_save) {
return self.model.save(dataPointID).then(function () {
return self._confirmSave(dataPointID);
+ }, function /* on_failure */ () {
+ return self._rejectSave(dataPointID);
});
} else if (options.notifyChange !== false) {
return self._confirmChange(dataPointID, result, event);
@@ -84,6 +86,19 @@ var FieldManagerMixin = {
_confirmSave: function (id) {
return Promise.resolve();
},
+ /**
+ * This method will be called whenever a save has been triggered by a change
+ * and has failed. For example, when a statusbar button is clicked in a
+ * readonly form view.
+ *
+ * @abstract
+ * @private
+ * @param {string} id The basicModel ID for the saved record
+ * @returns {Deferred}
+ */
+ _rejectSave: function (id) {
+ return Promise.resolve();
+ },
//--------------------------------------------------------------------------
// Handlers
diff --git a/addons/web/static/src/js/views/form/form_controller.js b/addons/web/static/src/js/views/form/form_controller.js
index 5616a5099bc..9997e144ca3 100644
--- a/addons/web/static/src/js/views/form/form_controller.js
+++ b/addons/web/static/src/js/views/form/form_controller.js
@@ -375,6 +375,19 @@ var FormController = BasicController.extend({
this._super(state);
},
/**
+ * Overrides to reload the form when saving failed in readonly (e.g. after
+ * a change on a widget like priority or statusbar).
+ *
+ * @override
+ * @private
+ */
+ _rejectSave: function () {
+ if (this.mode === 'readonly') {
+ return this.reload();
+ }
+ return this._super.apply(this, arguments);
+ },
+ /**
* Calls unfreezeOrder when changing the mode.
* Also, when there is a change of mode, the tracking of last activated
* field is reset, so that the following field activation process starts
diff --git a/addons/web/static/src/js/views/form/form_renderer.js b/addons/web/static/src/js/views/form/form_renderer.js
index 97ab575cbc3..98f971a0c05 100644
--- a/addons/web/static/src/js/views/form/form_renderer.js
+++ b/addons/web/static/src/js/views/form/form_renderer.js
@@ -390,7 +390,7 @@ var FormRenderer = BasicRenderer.extend({
var visible_buttons = buttons_partition[1];
// Get the unfolded buttons according to window size
- var nb_buttons = [2, 2, 4, 6][config.device.size_class] || 7;
+ var nb_buttons = self._renderButtonBoxNbButtons();
var unfolded_buttons = visible_buttons.slice(0, nb_buttons).concat(invisible_buttons);
// Get the folded buttons
@@ -432,6 +432,13 @@ var FormRenderer = BasicRenderer.extend({
return $result;
},
/**
+ * @private
+ * @returns {integer}
+ */
+ _renderButtonBoxNbButtons: function () {
+ return [2, 2, 4, 6][config.device.size_class] || 7;
+ },
+ /**
* @private
* @param {Object} node
* @returns {jQueryElement}
diff --git a/addons/web/static/src/js/views/kanban/kanban_record.js b/addons/web/static/src/js/views/kanban/kanban_record.js
index 116de142b0c..212a19a2eae 100644
--- a/addons/web/static/src/js/views/kanban/kanban_record.js
+++ b/addons/web/static/src/js/views/kanban/kanban_record.js
@@ -182,24 +182,30 @@ var KanbanRecord = Widget.extend({
*/
_getImageURL: function (model, field, id, cache, options) {
options = options || {};
+ id = (_.isArray(id) ? id[0] : id) || false;
+ field = options.preview_image || field;
+ var isCurrentRecord = this.modelName === model && this.recordData.id === id;
var url;
- if (this.record[field] && this.record[field].raw_value && !utils.is_bin_size(this.record[field].raw_value)) {
+ if (isCurrentRecord && this.record[field] && this.record[field].raw_value && !utils.is_bin_size(this.record[field].raw_value)) {
// Use magic-word technique for detecting image type
url = 'data:image/' + this.file_type_magic_word[this.record[field].raw_value[0]] + ';base64,' + this.record[field].raw_value;
- } else if (this.record[field] && ! this.record[field].raw_value) {
+ } else if (!model || !field || !id || (isCurrentRecord && this.record[field] && !this.record[field].raw_value)) {
url = "/web/static/src/img/placeholder.png";
} else {
- if (_.isArray(id)) { id = id[0]; }
- if (!id) { id = undefined; }
- if (options.preview_image)
- field = options.preview_image;
- var unique = this.record.__last_update && this.record.__last_update.value.replace(/[^0-9]/g, '');
var session = this.getSession();
- url = session.url('/web/image', { model: model, field: field, id: id, unique: unique });
+ var params = {
+ model: model,
+ field: field,
+ id: id
+ };
+ if (isCurrentRecord) {
+ params.unique = this.record.__last_update && this.record.__last_update.value.replace(/[^0-9]/g, '');
+ }
if (cache !== undefined) {
// Set the cache duration in seconds.
- url += '&cache=' + parseInt(cache, 10);
+ params.cache = parseInt(cache, 10);
}
+ url = session.url('/web/image', params);
}
return url;
},
diff --git a/addons/web/static/src/js/views/pivot/pivot_model.js b/addons/web/static/src/js/views/pivot/pivot_model.js
index 989eaa448a9..e28a5baed61 100644
--- a/addons/web/static/src/js/views/pivot/pivot_model.js
+++ b/addons/web/static/src/js/views/pivot/pivot_model.js
@@ -316,12 +316,18 @@ var PivotModel = AbstractModel.extend({
return {
has_data: false,
colGroupBys: this.data.main_col.root.groupbys,
+ // colGroupBys: this.data.main_col.groupbys,
+ // colGroupBys: this.data.colGroupBys,
rowGroupBys: this.data.main_row.root.groupbys,
+ // rowGroupBys: this.data.main_row.groupbys,
+ // rowGroupBys: this.data.groupedBy,
measures: this.data.measures,
};
}
return {
colGroupBys: this.data.main_col.root.groupbys,
+ // colGroupBys: this.data.main_col.groupbys,
+ // colGroupBys: this.data.colGroupBys,
context: this.data.context,
domain: this.data.domain,
compare: this.data.compare,
@@ -332,6 +338,8 @@ var PivotModel = AbstractModel.extend({
measures: this.data.measures,
rows: !isRaw && this._computeRows(),
rowGroupBys: this.data.main_row.root.groupbys,
+ // rowGroupBys: this.data.main_row.groupbys,
+ // rowGroupBys: this.data.groupedBy,
sortedColumn: this.data.sorted_column,
};
},
@@ -440,12 +448,10 @@ var PivotModel = AbstractModel.extend({
// if we don't have the key 'groupBy' in params. In that case,
// we want to have the full open state for the groupbys.
self._updateTree(old_row.root, self.data.main_row.root);
- self._updateMainGroupBys(old_row, self.data.main_row);
}
if (!('pivot_column_groupby' in (params.context || {}))) {
self._updateTree(old_col.root, self.data.main_col.root);
- self._updateMainGroupBys(old_col, self.data.main_col);
}
});
},
@@ -985,7 +991,8 @@ var PivotModel = AbstractModel.extend({
});
var index = 0;
- var rowGroupBys = !_.isEmpty(this.data.groupedBy) ? this.data.groupedBy : this.initialRowGroupBys;
+ var rowGroupBys = !_.isEmpty(this.data.groupedBy) ? this.data.groupedBy : this.initialRowGroupBys.slice();
+ this.data.groupedBy = rowGroupBys;
var colGroupBys = this.data.colGroupBys;
var dataPoint, row, col, attrs, cell_value;
var main_row_header, main_col_header;
@@ -1118,19 +1125,6 @@ var PivotModel = AbstractModel.extend({
}
},
/**
- * Updates the groupBys that the main[row | col] holds
- *
- * @private
- * @param {Object} old: The main abstract header before reload
- * @param {Object} main: The main abstract header after reload
- *
- */
- _updateMainGroupBys: function (old, main) {
- var new_groupby_length = this._getHeaderDepth(main.root) - 1;
- var new_groupby_list = old.root.groupbys.slice(0, new_groupby_length);
- main.root.groupbys = new_groupby_list;
- },
- /**
* @param {Object} old_tree
* @param {Object} new_tree
*/
diff --git a/addons/web/static/src/scss/fontawesome_overriden.scss b/addons/web/static/src/scss/fontawesome_overriden.scss
index 5fde7a750cd..a234dbc9f81 100644
--- a/addons/web/static/src/scss/fontawesome_overriden.scss
+++ b/addons/web/static/src/scss/fontawesome_overriden.scss
@@ -1,36 +1,38 @@
// This is rtl language specific fix
// It will override the font awesome symbols and flip them 180 degree
-.fa {
- &.fa-align-right,
- &.fa-align-left,
- &.fa-chevron-right,
- &.fa-chevron-left,
- &.fa-arrow-right,
- &.fa-arrow-left,
- &.fa-hand-o-right,
- &.fa-hand-o-left,
- &.fa-arrow-circle-right,
- &.fa-arrow-circle-left,
- &.fa-caret-right,
- &.fa-caret-left,
- &.fa-rotate-right,
- &.fa-rotate-left,
- &.fa-angle-double-right,
- &.fa-angle-double-left,
- &.fa-angle-right,
- &.fa-angle-left,
- &.fa-quote-right,
- &.fa-quote-left,
- &.fa-chevron-circle-right,
- &.fa-chevron-circle-left,
- &.fa-long-arrow-right,
- &.fa-long-arrow-left,
- &.fa-toggle-right,
- &.fa-toggle-left,
- &.fa-caret-square-o-right,
- &.fa-arrow-circle-o-left,
- &.fa-arrow-circle-o-right,
- &.fa-caret-square-o-left {
- transform: rotate(180deg);
+.o_rtl {
+ .fa {
+ &.fa-align-right,
+ &.fa-align-left,
+ &.fa-chevron-right,
+ &.fa-chevron-left,
+ &.fa-arrow-right,
+ &.fa-arrow-left,
+ &.fa-hand-o-right,
+ &.fa-hand-o-left,
+ &.fa-arrow-circle-right,
+ &.fa-arrow-circle-left,
+ &.fa-caret-right,
+ &.fa-caret-left,
+ &.fa-rotate-right,
+ &.fa-rotate-left,
+ &.fa-angle-double-right,
+ &.fa-angle-double-left,
+ &.fa-angle-right,
+ &.fa-angle-left,
+ &.fa-quote-right,
+ &.fa-quote-left,
+ &.fa-chevron-circle-right,
+ &.fa-chevron-circle-left,
+ &.fa-long-arrow-right,
+ &.fa-long-arrow-left,
+ &.fa-toggle-right,
+ &.fa-toggle-left,
+ &.fa-caret-square-o-right,
+ &.fa-arrow-circle-o-left,
+ &.fa-arrow-circle-o-right,
+ &.fa-caret-square-o-left {
+ transform: rotate(180deg);
+ }
}
-}
+} \ No newline at end of file
diff --git a/addons/web/static/src/scss/form_view.scss b/addons/web/static/src/scss/form_view.scss
index 812e6cbd6cc..99430bd0eed 100644
--- a/addons/web/static/src/scss/form_view.scss
+++ b/addons/web/static/src/scss/form_view.scss
@@ -570,6 +570,9 @@
&.o_form_readonly .o_field_widget .o_list_view .o_row_handle {
display: none; // Hide the handler in non-edit mode
}
+ .o_field_widget.o_readonly_modifier .o_list_view .o_row_handle {
+ display: none; // Hide the handler on readonly fields
+ }
// Attachments
.oe_attachment {
diff --git a/addons/web/static/src/scss/kanban_view.scss b/addons/web/static/src/scss/kanban_view.scss
index b9abdb14d48..c1b05807ddf 100644
--- a/addons/web/static/src/scss/kanban_view.scss
+++ b/addons/web/static/src/scss/kanban_view.scss
@@ -101,7 +101,7 @@
.oe_kanban_bottom_left, .oe_kanban_bottom_right {
display: flex;
align-items: center;
- height: 20px;
+ min-height: 20px;
}
.oe_kanban_bottom_left {
flex: 1 1 auto;
diff --git a/addons/web/static/src/scss/search_view_mobile.scss b/addons/web/static/src/scss/search_view_mobile.scss
index c3c264649ea..dd72aaae83b 100644
--- a/addons/web/static/src/scss/search_view_mobile.scss
+++ b/addons/web/static/src/scss/search_view_mobile.scss
@@ -7,7 +7,7 @@
padding: 0;
width: 100%;
background-color: white;
- z-index: 1000;
+ z-index: $zindex-modal;
overflow: auto;
.o_mobile_search_header {
height: 46px;
@@ -89,7 +89,6 @@
right: 0;
padding: 15px;
font-size: 17px;
- z-index: 1000;
}
}
}