diff --git a/CHANGELOG b/CHANGELOG index 6d733cb0e1..c2c3d86adc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +* Add URL for the current export +* Add option to export listed records * Set treeview header sticky on top * Add noreferrer noopener to external URL (issue9089) * Manage readonly dates in calendar view diff --git a/src/screen.js b/src/screen.js index d57ace7679..49f0862f98 100644 --- a/src/screen.js +++ b/src/screen.js @@ -999,14 +999,7 @@ } var domain = this.search_domain(search_string, true); - if (this.context_domain) { - var decoder = new Sao.PYSON.Decoder(this.context); - domain = ['AND', domain, decoder.decode(this.context_domain)]; - } - var tab_domain = this.screen_container.get_tab_domain(); - if (!jQuery.isEmptyObject(tab_domain)) { - domain = ['AND', domain, tab_domain]; - } + var context = this.context; if (this.screen_container.but_active.hasClass('active')) { context.active_test = false; @@ -1058,8 +1051,9 @@ }.bind(this)); }.bind(this)); }, - search_domain: function(search_string, set_text) { + search_domain: function(search_string, set_text, with_tab) { set_text = set_text || false; + with_tab = with_tab === undefined ? true : with_tab; var domain = []; // Test first parent to avoid calling unnecessary domain_parser @@ -1104,11 +1098,21 @@ domain = this.current_view.current_domain(); } } + if (this.context_domain) { + var decoder = new Sao.PYSON.Decoder(this.context); + domain = ['AND', domain, decoder.decode(this.context_domain)]; + } + if (with_tab) { + var tab_domain = this.screen_container.get_tab_domain(); + if (!jQuery.isEmptyObject(tab_domain)) { + domain = ['AND', domain, tab_domain]; + } + } return domain; }, count_tab_domain: function() { var screen_domain = this.search_domain( - this.screen_container.get_text()); + this.screen_container.get_text(), false, false); this.screen_container.tab_domain.forEach(function(tab_domain, i) { if (tab_domain[2]) { var domain = ['AND', tab_domain[1], screen_domain]; diff --git a/src/tab.js b/src/tab.js index 0a52b70c3b..f81be05a45 100644 --- a/src/tab.js +++ b/src/tab.js @@ -1279,11 +1279,7 @@ this.modified_save().then(function() { new Sao.Window.Export( this.title.text(), this.screen, - this.screen.current_view.selected_records.map(function(r) { - return r.id; - }), - this.screen.current_view.get_fields(), - this.screen.context); + this.screen.current_view.get_fields()); }.bind(this)); }, do_export: function(export_) { diff --git a/src/window.js b/src/window.js index 842308d672..914e5ae16c 100644 --- a/src/window.js +++ b/src/window.js @@ -1003,31 +1003,27 @@ .appendTo(column_fields_selected.find('.panel')); this.chooser_form = jQuery('
', { - 'class': 'row form-inline' + 'class': 'form-inline' }).appendTo(this.dialog.body); var row_csv_param = jQuery('', { - 'class': 'row' - }).appendTo(this.dialog.body); - - var expander_icon = jQuery('', { - 'class': 'caret', - }).css('cursor', 'pointer').html(' '); + }).on('click', function(){ + this.expander_csv.collapse('toggle'); + }.bind(this)).appendTo(this.dialog.body); var csv_param_label = jQuery('', { 'text': Sao.i18n.gettext('CSV Parameters') - }).css('cursor', 'pointer'); + }).css('cursor', 'pointer') + .appendTo(row_csv_param); - jQuery('', { - 'class': 'col-md-12' - }).append(csv_param_label).append(expander_icon) - .on('click', function(){ - this.expander_csv.collapse('toggle'); - }.bind(this)).appendTo(row_csv_param); + var expander_icon = jQuery('', { + 'class': 'caret', + }).css('cursor', 'pointer').html(' ') + .appendTo(row_csv_param); this.expander_csv = jQuery('', { 'id': 'expander_csv', - 'class': 'collapse col-md-12 form-inline' + 'class': 'collapse form-inline' }).appendTo(row_csv_param); var delimiter_label = jQuery('', { @@ -1413,12 +1409,10 @@ }); Sao.Window.Export = Sao.class_(Sao.Window.CSV, { - init: function(name, screen, ids, names, context) { + init: function(name, screen, names) { this.name = name; - this.ids = ids; this.screen = screen; this.session = Sao.Session.current_session; - this.context = context; Sao.Window.Export._super.init.call(this, Sao.i18n.gettext('CSV Export: %1',name)); var fields = this.screen.model.fields; @@ -1446,6 +1440,15 @@ }.bind(this)).append(' '+Sao.i18n.gettext('Save Export')) .appendTo(this.column_buttons); + this.button_url = jQuery('', { + 'class': 'btn btn-default btn-block', + 'target': '_blank', + 'rel': 'noreferrer noopener', + }).append(Sao.common.ICONFACTORY.get_icon_img('tryton-public') + ).append(' ' + Sao.i18n.gettext("URL Export")) + .appendTo(this.column_buttons); + this.dialog.body.on('change click', this.set_url.bind(this)); + jQuery('', { 'class': 'btn btn-default btn-block', 'type': 'button' @@ -1469,6 +1472,44 @@ }).css('cursor', 'pointer') .appendTo(predefined_exports_column); + this.selected_records = jQuery('', { + 'class': 'form-control', + 'id': 'input-records', + }).append(jQuery('', { + 'val': true, + }).html(Sao.i18n.gettext("Selected Records"))) + .append(jQuery('', { + 'val': false, + }).html(Sao.i18n.gettext("Listed Records"))); + + this.ignore_search_limit = jQuery('', { + 'type': 'checkbox', + }); + + this.selected_records.change(function() { + this.ignore_search_limit.parents('.form-group').first().toggle( + !JSON.parse(this.selected_records.val())); + }.bind(this)); + + jQuery('', { + 'class': 'form-group', + }).appendTo(this.chooser_form) + .append(jQuery('', { + 'text': Sao.i18n.gettext("Export:"), + 'class': 'control-label', + 'for': 'input-records', + })).append(this.selected_records); + + jQuery('', { + 'class': 'form-group', + }).appendTo(this.chooser_form) + .append(jQuery('', { + 'class': 'checkbox', + }).append(jQuery('', { + 'text': ' ' + Sao.i18n.gettext("Ignore search limit") + }).prepend(this.ignore_search_limit))) + .hide(); + this.el_csv_locale = jQuery('', { 'type': 'checkbox', 'checked': 'checked', @@ -1492,6 +1533,11 @@ 'text': ' '+Sao.i18n.gettext('Add Field Names') }).prepend(this.el_add_field_names)).appendTo(this.expander_csv); this.expander_csv.append(' '); + + this.set_url(); + }, + get context() { + return this.screen.context; }, view_populate: function(parent_node, parent_view) { var names = Object.keys(parent_node).sort(function(a, b) { @@ -1775,11 +1821,39 @@ fields.push(field.getAttribute('path')); fields2.push(field.innerText); }); - Sao.rpc({ - 'method': 'model.' + this.screen.model_name + - '.export_data', - 'params': [this.ids, fields, this.context] - }, this.session).then(function(data) { + + var prm; + if (JSON.parse(this.selected_records.val())) { + var ids = this.screen.current_view.selected_records.map(function(r) { + return r.id; + }); + prm = Sao.rpc({ + 'method': ( + 'model.' + this.screen.model_name + + '.export_data'), + 'params': [ids, fields, this.context] + }, this.session); + } else { + var domain = this.screen.search_domain( + this.screen.screen_container.get_text()); + var offset, limit; + if (this.ignore_search_limit.prop('checked')) { + offset = 0; + limit = null; + } else { + offset = this.screen.offset; + limit = this.screen.limit; + } + prm = Sao.rpc({ + 'method': ( + 'model.' + this.screen.model_name + + '.export_data_domain'), + 'params': [ + domain, fields, offset, limit, this.screen.order, + this.context], + }, this.session); + } + prm.then(function(data) { this.export_csv(fields2, data).then(function() { this.destroy(); }.bind(this)); @@ -1808,6 +1882,58 @@ Sao.i18n.ngettext('%1 record saved', '%1 records saved', data.length)); }, + set_url: function() { + var path = [this.session.database, 'data', this.screen.model_name]; + var query_string = []; + var domain; + if (JSON.parse(this.selected_records.val())) { + domain = this.screen.current_view.selected_records.map(function(r) { + return r.id; + }); + } else { + domain = this.screen.search_domain( + this.screen.screen_container.get_text()); + if (!this.ignore_search_limit.prop('checked')) { + query_string.push(['s', this.screen.limit.toString()]); + query_string.push( + ['p', Math.floor( + this.screen.offset / this.screen.limit).toString()]); + } + if (this.screen.order) { + this.screen.order.forEach(function(expr) { + query_string.push(['o', expr.map(function(e) { + return e; + }).join(',')]); + }); + } + } + query_string.splice( + 0, 0, ['d', JSON.stringify(Sao.rpc.prepareObject(domain))]); + + this.fields_selected.children('li').each(function(i, field) { + query_string.push(['f', field.getAttribute('path')]); + }); + + var encoding = this.el_csv_encoding.val(); + if (encoding) { + query_string.push(['enc', encoding]); + } + + query_string.push(['dl', this.el_csv_delimiter.val()]); + query_string.push(['qc', this.el_csv_quotechar.val()]); + + if (!this.el_add_field_names.is(':checked')) { + query_string.push(['h', '0']); + } + if (this.el_csv_locale.prop('checked')) { + query_string.push(['loc', '1']); + } + + query_string = query_string.map(function(param) { + return param.map(encodeURIComponent).join('='); + }).join('&'); + this.button_url.attr('href', '/' + path.join('/') + '?' + query_string); + }, }); Sao.Window.Export.format_row = function(line, locale_format) {