diff options
Diffstat (limited to 'addons/web/static/src')
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; } } } |
