summaryrefslogtreecommitdiff
path: root/addons/web
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web')
-rw-r--r--addons/web/controllers/main.py33
-rw-r--r--addons/web/static/src/js/views/list/list_controller.js5
-rw-r--r--addons/web/static/src/js/widgets/data_export.js65
-rw-r--r--addons/web/static/src/scss/data_export.scss20
-rw-r--r--addons/web/static/src/xml/base.xml50
5 files changed, 97 insertions, 76 deletions
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index cd0f2ff0873..bf27842d55e 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -1238,8 +1238,8 @@ class Export(http.Controller):
:rtype: [(str, str)]
"""
return [
- {'tag': 'csv', 'label': 'CSV'},
{'tag': 'xls', 'label': 'Excel', 'error': None if xlwt else "XLWT 1.3.0 required"},
+ {'tag': 'csv', 'label': 'CSV'},
]
def fields_get(self, model):
@@ -1250,24 +1250,29 @@ class Export(http.Controller):
@http.route('/web/export/get_fields', type='json', auth="user")
def get_fields(self, model, prefix='', parent_name= '',
import_compat=True, parent_field_type=None,
- exclude=None):
+ parent_field=None, exclude=None):
- if import_compat and parent_field_type == "many2one":
- fields = {}
+ if import_compat and parent_field_type in ['many2one', 'many2many']:
+ fields = self.fields_get(model)
+ fields = {k: v for k, v in fields.items() if k in ['id', 'name']}
else:
fields = self.fields_get(model)
- if import_compat:
- fields.pop('id', None)
- else:
+ if not import_compat:
fields['.id'] = fields.pop('id', {'string': 'ID'})
+ else:
+ fields['id']['string'] = _('External ID')
+
+ if parent_field:
+ parent_field['string'] = _('External ID')
+ fields['id'] = parent_field
fields_sequence = sorted(fields.items(),
- key=lambda field: odoo.tools.ustr(field[1].get('string', '')))
+ key=lambda field: (field[0] not in ['id', '.id', 'display_name', 'name'], odoo.tools.ustr(field[1].get('string', ''))))
records = []
for field_name, field in fields_sequence:
- if import_compat:
+ if import_compat and not field_name == 'id':
if exclude and field_name in exclude:
continue
if field.get('readonly'):
@@ -1279,6 +1284,9 @@ class Export(http.Controller):
continue
id = prefix + (prefix and '/'or '') + field_name
+ if field_name == 'name' and import_compat and parent_field_type in ['many2one', 'many2many']:
+ # Add name field when expand m2o and m2m fields in import-compatible mode
+ id = prefix
name = parent_name + (parent_name and '/' or '') + field['string']
record = {'id': id, 'string': name,
'value': id, 'children': False,
@@ -1290,11 +1298,8 @@ class Export(http.Controller):
if len(name.split('/')) < 3 and 'relation' in field:
ref = field.pop('relation')
record['value'] += '/id'
- record['params'] = {'model': ref, 'prefix': id, 'name': name}
-
- if not import_compat or field['type'] == 'one2many':
- # m2m field in import_compat is childless
- record['children'] = True
+ record['params'] = {'model': ref, 'prefix': id, 'name': name, 'parent_field': field}
+ record['children'] = True
return records
diff --git a/addons/web/static/src/js/views/list/list_controller.js b/addons/web/static/src/js/views/list/list_controller.js
index a210c07a885..ce0554a8fe6 100644
--- a/addons/web/static/src/js/views/list/list_controller.js
+++ b/addons/web/static/src/js/views/list/list_controller.js
@@ -446,7 +446,10 @@ var ListController = BasicController.extend({
*/
_onExportData: function () {
var record = this.model.get(this.handle);
- new DataExport(this, record).open();
+ var defaultExportFields = _.map(this.renderer.columns, function (field) {
+ return field.attrs.name;
+ });
+ new DataExport(this, record, defaultExportFields).open();
},
/**
* Called when the renderer displays an editable row and the user tries to
diff --git a/addons/web/static/src/js/widgets/data_export.js b/addons/web/static/src/js/widgets/data_export.js
index 8a09f7fa034..30e17604077 100644
--- a/addons/web/static/src/js/widgets/data_export.js
+++ b/addons/web/static/src/js/widgets/data_export.js
@@ -14,7 +14,7 @@ var _t = core._t;
var DataExport = Dialog.extend({
template: 'ExportDialog',
events: {
- 'click .o_expand_parent': function(e) {
+ 'click .o_expand': function(e) {
this.on_expand_action(this.records[$(e.target).closest('.o_export_tree_item').data('id')]);
},
'click .o_export_tree_item': function(e) {
@@ -56,10 +56,19 @@ var DataExport = Dialog.extend({
}
}
},
- 'dblclick .o_export_tree_item': function(e) {
- var $elem = $(e.currentTarget);
- $elem.removeClass('o_selected');
- this.add_field($elem.data('id'), $elem.find('.o_tree_column').first().text());
+ 'dblclick .o_export_tree_item:not(.haschild)': function(e) {
+ var self = this;
+ function addElement(el) {
+ self.add_field(el.getAttribute('data-id'), el.querySelector('.o_tree_column').textContent);
+ }
+ var target = e.currentTarget;
+ target.classList.remove('o_selected');
+ // Add parent fields to export
+ [].reverse.call($(target).parents('.o_export_tree_item')).each(function () {
+ addElement(this);
+ });
+ // add field itself
+ addElement(target);
},
'keydown .o_export_tree_item': function(e) {
e.stopPropagation();
@@ -195,7 +204,7 @@ var DataExport = Dialog.extend({
});
},
},
- init: function(parent, record) {
+ init: function(parent, record, defaultExportFields) {
var options = {
title: _t("Export Data"),
buttons: [
@@ -206,6 +215,7 @@ var DataExport = Dialog.extend({
this._super(parent, options);
this.records = {};
this.record = record;
+ this.defaultExportFields = defaultExportFields;
this.exports = new data.DataSetSearch(this, 'ir.exports', this.record.getContext());
this.row_index = 0;
@@ -228,13 +238,14 @@ var DataExport = Dialog.extend({
var got_fields = new $.Deferred();
this.$import_compat_radios.change(function(e) {
+ self.isCompatibleMode = !!$(e.target).val();
self.$('.o_field_tree_structure').remove();
self._rpc({
route: '/web/export/get_fields',
params: {
model: self.record.model,
- import_compat: !!$(e.target).val(),
+ import_compat: self.isCompatibleMode,
},
})
.done(function (records) {
@@ -250,6 +261,15 @@ var DataExport = Dialog.extend({
.remove();
got_fields.resolve();
self.on_show_data(records);
+ // In compatible mode add ID field as first field to export
+ if (self.isCompatibleMode) {
+ self.$('.o_fields_list').prepend(new Option(_('External ID'), 'id'));
+ }
+ _.each(records, function (record) {
+ if (_.contains(self.defaultExportFields, record.id)) {
+ self.add_field(record.id, record.string);
+ }
+ });
});
}).eq(0).change();
waitFor.push(got_fields);
@@ -262,10 +282,15 @@ var DataExport = Dialog.extend({
self.ids_to_export = false;
self.domain = domain;
}
- self.on_show_domain();
}));
- waitFor.push(this.show_exports_list());
+ waitFor.push(this.show_exports_list().then(function () {
+ _.each(self.records, function (record, key) {
+ if (_.contains(self.defaultExportFields, key)) {
+ self.add_field(key, record.string);
+ }
+ });
+ }));
return $.when.apply($, waitFor);
@@ -274,14 +299,15 @@ var DataExport = Dialog.extend({
_.each(formats, function(format, i) {
var $radio = $('<input/>', {type: 'radio', value: format.tag, name: 'o_export_format_name'});
- var $label = $('<label/>', {html: format.label});
+ var $label = $('<span/>', {html: format.label});
if (format.error) {
$radio.prop('disabled', true);
$label.html(_.str.sprintf("%s — %s", format.label, format.error));
}
- $fmts.append($("<div/>").append($radio, $label));
+ var $radioButton = $('<label/>').append($radio, $label);
+ $fmts.append($("<div class='radio'></div>").append($radioButton));
});
self.$export_format_inputs = $fmts.find('input');
@@ -366,7 +392,8 @@ var DataExport = Dialog.extend({
parent_name: name,
import_compat: !!this.$import_compat_radios.filter(':checked').val(),
parent_field_type : record['field_type'],
- exclude: exclude_fields
+ parent_field: record['params']['parent_field'],
+ exclude: exclude_fields,
},
})
.done(function(results) {
@@ -377,17 +404,13 @@ var DataExport = Dialog.extend({
this.show_content(record.id);
}
},
- on_show_domain: function() {
- this.$('p').first()
- .after(QWeb.render('Export.DomainMessage', {record: this}));
- },
on_show_data: function(records, expansion) {
var self = this;
if(expansion) {
this.$('.o_export_tree_item[data-id="' + expansion + '"]')
.addClass('open')
.find('.o_expand_parent')
- .toggleClass('fa-plus fa-minus')
+ .toggleClass('fa-chevron-right fa-chevron-down')
.next()
.after(QWeb.render('Export.TreeItems', {'fields': records, 'debug': this.getSession().debug}));
} else {
@@ -409,7 +432,7 @@ var DataExport = Dialog.extend({
$this.toggleClass('open');
var is_open = $this.hasClass('open');
- $this.children('.o_expand_parent').toggleClass('fa-minus', !!is_open).toggleClass('fa-plus', !is_open);
+ $this.children('.o_expand_parent').toggleClass('fa-chevron-down', !!is_open).toggleClass('fa-chevron-right', !is_open);
var $child_field = $this.find('.o_export_tree_item');
var child_len = (id.split("/")).length + 1;
@@ -420,7 +443,7 @@ var DataExport = Dialog.extend({
} else if(child_len === $child_field.eq(i).data('id').split("/").length) {
if ($child.hasClass('open')) {
$child.removeClass('open');
- $child.children('.o_expand_parent').removeClass('fa-minus').addClass('fa-plus');
+ $child.children('.o_expand_parent').removeClass('fa-chevron-down').addClass('fa-chevron-right');
}
$child.show();
}
@@ -455,7 +478,9 @@ var DataExport = Dialog.extend({
Dialog.alert(this, _t("Please select fields to export..."));
return;
}
- exported_fields.unshift({name: 'id', label: _t('External ID')});
+ if (!this.isCompatibleMode) {
+ exported_fields.unshift({name: 'id', label: _t('External ID')});
+ }
var export_format = this.$export_format_inputs.filter(':checked').val();
diff --git a/addons/web/static/src/scss/data_export.scss b/addons/web/static/src/scss/data_export.scss
index aa690cfdb74..17cec27d3a5 100644
--- a/addons/web/static/src/scss/data_export.scss
+++ b/addons/web/static/src/scss/data_export.scss
@@ -8,25 +8,6 @@
@include o-flex(0, 0, auto);
}
- label {
- vertical-align: top;
- font-weight: normal;
- }
-
- .o_import_compat, .o_export_format {
- display: inline-block;
-
- > div {
- margin-left: 5px;
- @include o-inline-flex-display;
- @include o-align-items(center);
-
- > label, > input {
- margin: 0 0 0 5px;
- }
- }
- }
-
.o_export_panel {
@include o-flex(1, 1, auto);
position: relative;
@@ -77,6 +58,7 @@
.o_expand_parent {
@include o-position-absolute($top: 4px, $left: 5px);
+ font-size: 10px;
}
.o_tree_column {
display: block;
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 758f5bcd416..4c081b679dd 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -1281,21 +1281,26 @@
</div>
<div t-name="ExportDialog" class="o_export">
- <p role="status">
- This wizard will export all data that matches the current search criteria to a CSV file.
- You can export all data or only the fields that can be reimported after modification.
- </p>
-
<div class="row">
<div class="col-md-6">
- <label>Export Type :</label>
+ <strong>What do you want to do?</strong>
<div class="o_import_compat">
- <div><input type="radio" name="o_import_compat_name" value="yes" checked="checked"/><label>Import-Compatible Export</label></div>
- <div><input type="radio" name="o_import_compat_name" value=""/><label>Export all Data</label></div>
+ <div class="radio">
+ <label>
+ <input type="radio" name="o_import_compat_name" value="" checked="checked"/>
+ Use data in a spreadsheet (export all data)
+ </label>
+ </div>
+ <div class="radio">
+ <label>
+ <input type="radio" name="o_import_compat_name" value="yes"/>
+ Update data (import-compatible export)
+ </label>
+ </div>
</div>
</div>
<div class="col-md-6">
- <label>Export Formats :</label>
+ <strong>Export Format:</strong>
<div class="o_export_format"/>
</div>
</div>
@@ -1323,19 +1328,20 @@
</div>
</div>
</div>
-<p t-name="Export.DomainMessage">
- <strong t-if="!record.ids_to_export" role="alert">Please pay attention that all records matching your search filter will be exported. Not only the selected ids.</strong>
- <strong t-if="record.ids_to_export" role="alert">Please note that only the selected ids will be exported.</strong>
-</p>
-<div t-name="Export.TreeItems"
- t-foreach="fields" t-as="field"
- t-att-data-id="field.id"
- class="o_export_tree_item"
- tabindex="-1" role="treeitem"> <!-- tabindex make the div focusable -->
- <span t-if="field.children &amp;&amp; (field.id).split('/').length != 3"
- class="o_expand_parent fa fa-plus" role="img" aria-label="Expand parents" title="Expand parents"/>
- <span class="o_tree_column" t-att-title="debug and field.id or None"><t t-esc="field.string"/></span>
-</div>
+<t t-name="Export.TreeItems">
+ <t t-foreach="fields" t-as="field">
+ <t t-set="has_child" t-value="field.children &amp;&amp; (field.id).split('/').length != 3" />
+ <div t-att-data-id="field.id" t-attf-class="o_export_tree_item #{has_child ? 'haschild' : ''}" tabindex="-1" role="treeitem"> <!-- tabindex make the div focusable -->
+ <t t-if="has_child">
+ <span class="o_expand o_expand_parent fa fa-chevron-right" role="img" aria-label="Expand parents" title="Expand parents"/>
+ <span class="o_tree_column o_expand" t-att-title="debug and field.id or None"><t t-esc="field.string"/></span>
+ </t>
+ <t t-else="">
+ <span class="o_tree_column" t-att-title="debug and field.id or None"><t t-esc="field.string"/></span>
+ </t>
+ </div>
+ </t>
+</t>
<t t-name="Export.SaveList">
<label>Save as:</label> <input type="text"/><button type="button" class="btn btn-sm btn-default">Ok</button>
</t>