summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
authorKishan Gajjar <kig@odoo.com>2019-01-24 10:29:28 +0000
committerXavier Morel <xmo@odoo.com>2019-08-12 13:38:31 +0000
commit22b598bc1b8331907ba0ce77739b64c48d6fcbbd (patch)
tree527b726ebfccb01fc7677107d3081523faeee031 /addons/web/static/src
parentb6193a6b8d569d9d3a9fb4abe1590012782d03c2 (diff)
[IMP] web: export improvements
* remove center buttons, corresponding features either moved to fields list (handle / bin on exported, etc...) or removed entirely (e.g. clear) * replace XLS to XLSX format, increases rows# to 1048579 * add FAYT filtering of available fields * sort available fields alphabetically (CI) always * change export templates UI: remove buttons TaskID: 1910953 closes odoo/odoo#32339 Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/widgets/data_export.js257
-rw-r--r--addons/web/static/src/scss/data_export.scss118
-rw-r--r--addons/web/static/src/xml/base.xml113
3 files changed, 239 insertions, 249 deletions
diff --git a/addons/web/static/src/js/widgets/data_export.js b/addons/web/static/src/js/widgets/data_export.js
index 9031dd43232..975cc99e35c 100644
--- a/addons/web/static/src/js/widgets/data_export.js
+++ b/addons/web/static/src/js/widgets/data_export.js
@@ -19,15 +19,14 @@ var DataExport = Dialog.extend({
'click .o_add_field': '_onClickAddField',
'click .o_delete_exported_list': '_onClickDeleteExportListBtn',
'click .o_expand': '_onClickExpand',
- 'click .o_move_down': '_onClickMovedown',
- 'click .o_move_up': '_onClickMoveup',
- 'click .o_remove_all_field': '_onClickRemoveAllFields',
'click .o_remove_field': '_onClickRemoveField',
- 'click .o_toggle_save_list': '_onClickSaveList',
- 'click .o_save_list > button': '_onClickSaveListBtn',
+ 'click .o_save_list .o_save_list_btn': '_onClickSaveListBtn',
+ 'click .o_save_list .o_cancel_list_btn': '_resetTemplateField',
'click .o_export_tree_item': '_onClickTreeItem',
'dblclick .o_export_tree_item:not(.haschild)': '_onDblclickTreeItem',
- 'keydown .o_export_tree_item': '_onKeydownTreeItem'
+ 'keydown .o_export_tree_item': '_onKeydownTreeItem',
+ 'keydown .o_save_list_name': '_onKeydownSaveList',
+ 'input .o_export_search_input': '_onSearchInput',
},
/**
* @constructor
@@ -39,7 +38,7 @@ var DataExport = Dialog.extend({
var options = {
title: _t("Export Data"),
buttons: [
- {text: _t("Export To File"), click: this._exportData, classes: 'btn-primary'},
+ {text: _t("Export"), click: this._exportData, classes: 'btn-primary'},
{text: _t("Close"), close: true},
],
};
@@ -65,7 +64,6 @@ var DataExport = Dialog.extend({
this.$modal.find('.modal-content').css('height', '100%');
this.$fieldsList = this.$('.o_fields_list');
- this.$importCompatRadios = this.$('.o_import_compat input');
proms.push(this._rpc({route: '/web/export/formats'}).then(doSetupExportFormats));
proms.push(this._onChangeCompatibleInput());
@@ -81,29 +79,37 @@ var DataExport = Dialog.extend({
}));
proms.push(this._showExportsList().then(function () {
- _.each(self.records, function (record, key) {
- if (_.contains(self.defaultExportFields, key)) {
- self._addField(key, record.string);
- }
+ _.each(self.defaultExportFields, function (field) {
+ var record = self.records[field];
+ self._addField(record.id, record.string);
});
}));
+ // Bind sortable events after Dialog is open
+ this.opened().then(function () {
+ self.$('.o_fields_list').sortable({
+ axis: 'y',
+ handle: '.o_short_field',
+ forcePlaceholderSize: true,
+ placeholder: 'o-field-placeholder',
+ update: self.proxy('_resetTemplateField'),
+ });
+ });
return Promise.all(proms);
function doSetupExportFormats(formats) {
var $fmts = self.$('.o_export_format');
_.each(formats, function (format) {
- var $radio = $('<input/>', {type: 'radio', value: format.tag, name: 'o_export_format_name'});
- var $label = $('<span/>', {html: format.label});
+ var $radio = $('<input/>', {type: 'radio', value: format.tag, name: 'o_export_format_name', class: 'form-check-input', id: 'o_radio' + format.label});
+ var $label = $('<label/>', {html: format.label, class: 'form-check-label', for: 'o_radio' + format.label});
if (format.error) {
$radio.prop('disabled', true);
$label.html(_.str.sprintf("%s — %s", format.label, format.error));
}
- var $radioButton = $('<label/>').append($radio, $label);
- $fmts.append($("<div class='radio'></div>").append($radioButton));
+ $fmts.append($("<div class='radio form-check form-check-inline pl-4'></div>").append($radio, $label));
});
self.$exportFormatInputs = $fmts.find('input');
@@ -124,22 +130,27 @@ var DataExport = Dialog.extend({
*/
_addField: function (fieldID, label) {
var $fieldList = this.$('.o_fields_list');
- fieldID = this.records[fieldID].value || fieldID;
- if ($fieldList.find('option[value="' + fieldID + '"]').length === 0) {
- $fieldList.append(new Option(label, fieldID));
+ if (!$fieldList.find(".o_export_field[data-field_id='" + fieldID + "']").length) {
+ $fieldList.append(
+ $('<li>', {'class': 'o_export_field', 'data-field_id': fieldID}).append(
+ $('<span>', {'class': "fa fa-arrows o_short_field mx-1"}),
+ label,
+ $('<span>', {'class': 'fa fa-trash m-1 pull-right o_remove_field', 'title': _t("Remove field")})
+ )
+ );
}
},
+
/**
* Submit the user data and export the file
*
* @private
*/
_exportData: function () {
- var self = this;
- var exportedFields = this.$('.o_fields_list option').map(function () {
+ var exportedFields = this.$('.o_export_field').map(function () {
return {
- name: (self.records[this.value] || this).value,
- label: this.textContent || this.innerText, // DOM property is textContent, but IE8 only knows innerText
+ name: $(this).data('field_id'),
+ label: this.textContent
};
}).get();
@@ -147,7 +158,7 @@ var DataExport = Dialog.extend({
Dialog.alert(this, _t("Please select fields to export..."));
return;
}
- if (!this.isCompatibleMode) {
+ if (this.isCompatibleMode) {
exportedFields.unshift({ name: 'id', label: _t('External ID') });
}
@@ -163,7 +174,7 @@ var DataExport = Dialog.extend({
ids: this.idsToExport,
domain: this.domain,
context: pyUtils.eval('contexts', [this.record.getContext()]),
- import_compat: !!this.$importCompatRadios.filter(':checked').val(),
+ import_compat: this.isCompatibleMode,
})
},
complete: framework.unblockUI,
@@ -175,8 +186,8 @@ var DataExport = Dialog.extend({
* @returns {string[]} exportFields
*/
_getFields: function () {
- var exportFields = this.$('.o_fields_list option').map(function () {
- return $(this).val();
+ var exportFields = this.$('.o_export_field').map(function () {
+ return $(this).data('field_id');
}).get();
if (exportFields.length === 0) {
Dialog.alert(this, _t("Please select fields to save export list..."));
@@ -211,7 +222,7 @@ var DataExport = Dialog.extend({
model: model,
prefix: prefix,
parent_name: name,
- import_compat: !!this.$importCompatRadios.filter(':checked').val(),
+ import_compat: this.isCompatibleMode,
parent_field_type: record.field_type,
parent_field: record.params.parent_field,
exclude: excludeFields,
@@ -254,6 +265,31 @@ var DataExport = Dialog.extend({
var $el = $(el);
$el.find('.o_tree_column').first().toggleClass('o_required', !!self.records[$el.data('id')].required);
});
+ this.$('#o-export-search-filter').val('');
+ },
+ /**
+ * @private
+ */
+ _addNewTemplate: function () {
+ this.$('.o_exported_lists').addClass('d-none');
+
+ this.$(".o_save_list")
+ .show()
+ .find(".o_save_list_name")
+ .val("")
+ .focus();
+ },
+ /**
+ * @private
+ */
+ _resetTemplateField: function () {
+ this.$('.o_exported_lists_select').val("");
+ this.$('.o_delete_exported_list').addClass('d-none');
+ this.$('.o_exported_lists').removeClass('d-none');
+
+ this.$(".o_save_list")
+ .hide()
+ .find(".o_save_list_name").val("");
},
/**
* If relational fields info is already fetched then this method is
@@ -283,6 +319,7 @@ var DataExport = Dialog.extend({
$child.show();
}
}
+ this.$('#o-export-search-filter').val('');
},
/**
* Fetches the saved export list for the current model
@@ -303,9 +340,6 @@ var DataExport = Dialog.extend({
fields: ['name'],
domain: [['resource', '=', this.record.model]]
}).then(function (exportList) {
- if (!exportList.length) {
- return;
- }
self.$('.o_exported_lists').append(QWeb.render('Export.SavedList', {
existing_exports: exportList,
}));
@@ -323,9 +357,10 @@ var DataExport = Dialog.extend({
*/
_onChangeExportList: function () {
var self = this;
- this.$fieldsList.empty();
var exportID = this.$('.o_exported_lists_select option:selected').val();
- if (exportID) {
+ this.$('.o_delete_exported_list').toggleClass('d-none', !exportID);
+ if (exportID && exportID !== 'new_template') {
+ this.$('.o_fields_list').empty();
this._rpc({
route: '/web/export/namelist',
params: {
@@ -334,9 +369,11 @@ var DataExport = Dialog.extend({
},
}).then(function (fieldList) {
_.each(fieldList, function (field) {
- self.$fieldsList.append(new Option(field.label, field.name));
+ self._addField(field.name, field.label);
});
});
+ } else if (exportID === 'new_template') {
+ self._addNewTemplate();
}
},
/**
@@ -345,10 +382,10 @@ var DataExport = Dialog.extend({
*/
_onChangeCompatibleInput: function () {
var self = this;
- this.isCompatibleMode = this.$('.o_import_compat input[value="yes"]').is(':checked');
+ this.isCompatibleMode = this.$('.o_import_compat input').is(':checked');
this.$('.o_field_tree_structure').remove();
-
+ this._resetTemplateField();
return this._rpc({
route: '/web/export/get_fields',
params: {
@@ -357,40 +394,33 @@ var DataExport = Dialog.extend({
},
}).then(function (records) {
var compatibleFields = _.map(records, function (record) { return record.id; });
- self.$fieldsList
- .find('option')
- .filter(function () {
- var optionField = $(this).attr('value');
- if (compatibleFields.indexOf(optionField) === -1) {
- return true;
- }
- })
- .remove();
self._onShowData(records);
- // In compatible mode add ID field as first field to export
- if (self.isCompatibleMode) {
- self.$('.o_fields_list').prepend(new Option(_t("External ID"), 'id'));
- }
- _.each(records, function (record) {
- if (_.contains(self.defaultExportFields, record.id)) {
- self._addField(record.id, record.string);
- }
+ self.$('.o_fields_list').empty();
+
+ _.chain(self.$fieldsList.find('.o_export_field'))
+ .map(function (field) { return $(field).data('field_id'); })
+ .union(self.defaultExportFields)
+ .intersection(compatibleFields)
+ .each(function (field) {
+ var record = _.find(records, function (rec) {
+ return rec.id === field;
+ });
+ self._addField(record.id, record.string);
});
+ self.$('#o-export-search-filter').val('');
});
},
/**
* Add a field to export list
*
* @private
+ * @param {Event} ev
*/
- _onClickAddField: function () {
- var self = this;
- this.$('.o_field_tree_structure .o_selected')
- .removeClass('o_selected')
- .each(function () {
- var $this = $(this);
- self._addField($this.data('id'), $this.children('.o_tree_column').text());
- });
+ _onClickAddField: function(ev) {
+ ev.stopPropagation();
+ var $field = $(ev.currentTarget);
+ this._resetTemplateField();
+ this._addField($field.closest('.o_export_tree_item').data('id'), $field.closest('.o_tree_column').text());
},
/**
* Delete selected export list item from the saved export list
@@ -405,7 +435,6 @@ var DataExport = Dialog.extend({
if (selectExp.val()) {
self.exports.unlink([parseInt(selectExp.val(), 10)]);
selectExp.remove();
- self.$fieldsList.empty();
if (self.$('.o_exported_lists_select option').length <= 1) {
self.$('.o_exported_lists').hide();
}
@@ -422,59 +451,14 @@ var DataExport = Dialog.extend({
this._onExpandAction(this.records[$(ev.target).closest('.o_export_tree_item').data('id')]);
},
/**
- * @private
- */
- _onClickMovedown: function () {
- var $selectedRows = this.$fieldsList.find('option:selected');
- var $nextRow = $selectedRows.last().next();
- if ($nextRow.length) {
- $nextRow.after($selectedRows.detach());
- }
- },
- /**
- * @private
- */
- _onClickMoveup: function () {
- var $selectedRows = this.$fieldsList.find('option:selected');
- var $prevRow = $selectedRows.first().prev();
- if ($prevRow.length) {
- $prevRow.before($selectedRows.detach());
- }
- },
- /**
- * Remove all fields from export field list
- *
- * @private
- */
- _onClickRemoveAllFields: function () {
- this.$fieldsList.empty();
- },
- /**
* Remove selected field from export field list
*
* @private
- */
- _onClickRemoveField: function () {
- this.$fieldsList.find('option:selected').remove();
- },
- /**
- * @private
* @param {Event} ev
*/
- _onClickSaveList: function (ev) {
- ev.preventDefault();
-
- var $saveList = this.$('.o_save_list');
- if ($saveList.is(':empty')) {
- $saveList.append(QWeb.render('Export.SaveList'));
- } else {
- if ($saveList.is(':hidden')) {
- $saveList.show();
- $saveList.find('.o_export_list_input').val('');
- } else {
- $saveList.hide();
- }
- }
+ _onClickRemoveField: function (ev) {
+ $(ev.currentTarget).closest('.o_export_field').remove();
+ this._resetTemplateField();
},
/**
* This method will create a record in 'ir.exports' model with list of
@@ -514,11 +498,13 @@ var DataExport = Dialog.extend({
self._showExportsList();
}
$select.append(new Option(value, exportListID));
+ self.$('.o_exported_lists').removeClass('d-none');
+ $select.val(exportListID);
});
},
/**
* @private
- * @param {Event} ev
+ * @param ev
*/
_onClickTreeItem: function (ev) {
ev.stopPropagation();
@@ -546,7 +532,7 @@ var DataExport = Dialog.extend({
} else if (ev.shiftKey) {
$elem.addClass('o_selected').focus();
} else {
- this.$('.o_selected').removeClass('o_selected')
+ this.$('.o_selected').removeClass('o_selected');
$elem.addClass('o_selected').focus();
}
@@ -567,6 +553,7 @@ var DataExport = Dialog.extend({
*/
_onDblclickTreeItem: function (ev) {
var self = this;
+ this._resetTemplateField();
function addElement(el) {
self._addField(el.getAttribute('data-id'), el.querySelector('.o_tree_column').textContent);
}
@@ -580,10 +567,19 @@ var DataExport = Dialog.extend({
addElement(target);
},
/**
+ * @private
+ * @param ev
+ */
+ _onKeydownSaveList: function (ev) {
+ if (ev.keyCode === $.ui.keyCode.ENTER) {
+ this._onClickSaveListBtn();
+ }
+ },
+ /**
* Handles the keyboard navigation for the fields
*
* @private
- * @param {Event} ev
+ * @param ev
*/
_onKeydownTreeItem: function (ev) {
ev.stopPropagation();
@@ -636,6 +632,41 @@ var DataExport = Dialog.extend({
break;
}
},
+ /**
+ * Search fields from a field list.
+ *
+ * @private
+ */
+ _onSearchInput: function (ev) {
+ var searchText = $(ev.currentTarget).val().trim().toUpperCase();
+ if (!searchText) {
+ this.$('.o_no_match').remove();
+ this.$(".o_export_tree_item").show();
+ this.$(".o_export_tree_item.haschild:not(.show) .o_export_tree_item").hide();
+ return;
+ }
+
+ var matchItems = this.$(".o_tree_column").filter(function () {
+ return this.innerText.toUpperCase().indexOf(searchText) >= 0;
+ }).parent();
+ this.$(".o_export_tree_item").hide();
+ if (matchItems.length) {
+ this.$('.o_no_match').remove();
+ _.each(matchItems, function (col) {
+ var $col = $(col);
+ $col.show();
+ $col.parents('.haschild.show').show();
+ if (!$col.parent().hasClass('show') && !$col.parent().hasClass('o_field_tree_structure')) {
+ $col.hide();
+ }
+ });
+ } else if (!this.$('.o_no_match').length) {
+ this.$(".o_field_tree_structure").append($("<h3/>", {
+ class: 'text-center text-muted mt-5 o_no_match',
+ text: _t("No match found.")
+ }));
+ }
+ },
});
return DataExport;
diff --git a/addons/web/static/src/scss/data_export.scss b/addons/web/static/src/scss/data_export.scss
index c03d13b355b..f52bcf10383 100644
--- a/addons/web/static/src/scss/data_export.scss
+++ b/addons/web/static/src/scss/data_export.scss
@@ -1,90 +1,52 @@
.o_web_client .o_export {
- flex: 1 1 auto;
- display: flex;
- flex-flow: column nowrap;
- min-height: 0;
-
- > p, > .row {
- flex: 0 0 auto;
+ padding: 20px;
+ .o-export-panel {
+ height: 100%;
}
-
- .o_export_panel {
- flex: 1 1 auto;
- position: relative;
- min-height: 0;
-
- > div {
- height: 100%;
- display: flex;
- flex-flow: column nowrap;
- justify-content: center;
-
- &.o_left_panel { // Needed because of chrome
- @include o-position-absolute($top: 0, $bottom: 0, $left: 0, $right: 57%);
+ .o_left_panel {
+ padding-right: 10px;
+ flex-flow: column nowrap;
+ height: 100%;
+ .o_left_field_panel {
+ flex: 1;
+ overflow: auto;
+ }
+ .o_export_tree_item {
+ cursor: pointer;
+ position: relative;
+ padding-left: 20px;
+ &.o_selected > .o_tree_column {
+ background-color: $o-brand-odoo;
+ color: white;
}
- &.o_center_panel { // Needed because of chrome
- @include o-position-absolute($top: 0, $bottom: 0, $left: 43%, $right: 43%);
+ .o_expand_parent {
+ @include o-position-absolute($top: 4px, $left: 5px);
+ font-size: 10px;
}
- &.o_right_panel { // Needed because of chrome
- @include o-position-absolute($top: 0, $bottom: 0, $left: 57%, $right: 0);
+ .o_required {
+ border-bottom: 2px solid $o-main-text-color;
}
+ }
+ }
- > h4, > div {
- flex: 0 0 auto;
+ .o_right_panel {
+ padding-left: 10px;
+ flex-flow: column nowrap;
+ height: 100%;
+ .o_save_list {
+ display: none;
+ }
+ .o_right_field_panel {
+ flex: 1;
+ overflow: auto;
+ .o_short_field {
+ cursor: ns-resize;
}
-
- > button {
- flex: 0 0 auto;
- margin-top: 10px;
+ .o-field-placeholder {
+ border: 1px dashed $o-brand-primary;
}
-
- .o_left_field_panel, .o_fields_list {
- border: 1px solid $o-brand-lightsecondary;
- overflow: auto;
- flex: 1 1 auto;
- min-height: 0;
- }
-
- .o_export_tree_item {
+ .o_remove_field {
cursor: pointer;
- position: relative;
- padding-left: 20px;
- user-select: none;
-
- &.o_selected > .o_tree_column {
- background-color: $o-brand-odoo;
- color: white;
- }
-
- .o_expand_parent {
- @include o-position-absolute($top: 4px, $left: 5px);
- font-size: 10px;
- }
- .o_tree_column {
- display: block;
-
- &.o_required {
- border-bottom: 2px solid $o-main-text-color;
- }
- }
-
- &:focus {
- outline: none;
- }
- }
-
- .o_save_list, .o_exported_lists {
- display: flex;
- align-items: baseline;
-
- > label, > button {
- margin: 0 0 5px;
- flex: 0 0 auto;
- }
- > input, > select {
- width: 0;
- flex: 1 0 auto;
- }
}
}
}
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index c342c24441f..1b319f6b3e5 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -1279,79 +1279,76 @@
</div>
<div t-name="ExportDialog" class="o_export">
- <div class="row">
- <div class="col-lg-6">
- <strong>What do you want to do?</strong>
- <div class="o_import_compat">
- <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 class="row o-export-panel no-gutters">
+ <div class="col-6 d-flex o_left_panel">
+ <div class="form-check o_import_compat">
+ <input class="form-check-input" id="o-update-data" type="checkbox"/>
+ <label class="form-check-label" for="o-update-data">
+ I want to update data (import-compatible export)
+ </label>
</div>
+ <div class="mt-3">
+ <h4>Available fields</h4>
+ </div>
+ <div class="input-group mb-3">
+ <input type="search" class="form-control o_export_search_input" id="o-export-search-filter" placeholder="Search" />
+ </div>
+ <div class="border o_left_field_panel"/>
</div>
- <div class="col-lg-6">
- <strong>Export Format:</strong>
- <div class="o_export_format"/>
- </div>
- </div>
-
- <div class="o_export_panel">
- <div class="o_left_panel">
- <h4>Available fields</h4>
- <div class="o_left_field_panel"/>
- </div>
- <div class="o_center_panel">
- <button type="button" class="btn btn-secondary o_add_field">Add</button>
- <button type="button" class="btn btn-secondary o_remove_field">Remove</button>
- <button type="button" class="btn btn-secondary o_remove_all_field">Remove All</button>
- <button type="button" class="btn btn-secondary o_move_up">Move Up</button>
- <button type="button" class="btn btn-secondary o_move_down">Move Down</button>
- </div>
- <div class="o_right_panel">
- <h4>
- <a href="#" class="float-right o_toggle_save_list">Save fields list</a>
- Fields to export
- </h4>
- <div class="o_save_list"/>
+ <div class="col-6 d-flex o_right_panel">
+ <div class="o_export_format">
+ <strong>Export Format:</strong>
+ </div>
+ <div class="mt-3">
+ <h4>Fields to export</h4>
+ </div>
+ <div class="o_save_list">
+ <t t-call="Export.SaveList"/>
+ </div>
<div class="o_exported_lists"/>
- <select class="o_fields_list" multiple="multiple"></select>
+ <div class="border o_right_field_panel">
+ <ul class="o_fields_list list-unstyled"/>
+ </div>
</div>
</div>
</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-att-data-id="field.id" t-attf-class="o_export_tree_item #{has_child ? 'haschild o_expand' : ''}" tabindex="-1" role="treeitem"> <!-- tabindex make the div focusable -->
+ <span t-if="has_child" class="o_expand_parent fa fa-chevron-right" role="img" aria-label="Show sub-fields" title="Show sub-fields"/>
+ <div t-attf-class="o_tree_column" t-att-title="debug and field.id or None">
+ <t t-esc="field.string"/>
+ <span title="Select field" class="fa fa-plus pull-right m-1 o_add_field"/>
+ </div>
</div>
</t>
</t>
<t t-name="Export.SaveList">
- <label>Save as:</label> <input type="text"/><button type="button" class="btn btn-secondary">Ok</button>
+ <div class="input-group mb-3">
+ <label class="pt-2 font-weight-bold">Save as : </label>
+ <input class="form-control ml-4 o_save_list_name"
+ placeholder="New template"/>
+ <button type="button" class="btn btn-secondary ml-1 o_save_list_btn"><i class="fa fa-floppy-o"/></button>
+ <button type="button" class="btn btn-secondary ml-1 o_cancel_list_btn"><i class="fa fa-times"/></button>
+ </div>
</t>
<t t-name="Export.SavedList">
- <label>Saved exports: </label>
- <select class="o_exported_lists_select">
- <option></option>
- <t t-foreach="existing_exports" t-as="export">
- <option t-att-value="export.id"><t t-esc="export.name"/></option>
- </t>
- </select>
- <button type="button" class="btn btn-secondary o_delete_exported_list">Delete</button>
+ <div class="input-group mb-3">
+ <label class="pt-2 mb-0 font-weight-bold">Template: </label>
+ <select class="form-control ml-4 o_exported_lists_select">
+ <option></option>
+ <option class="font-italic" value="new_template">New template</option>
+ <t t-foreach="existing_exports" t-as="export">
+ <option t-att-value="export.id">
+ <t t-esc="export.name"/>
+ </option>
+ </t>
+ </select>
+ <button type="button" class="btn btn-secondary d-none ml-1 o_delete_exported_list">
+ <i class="fa fa-trash"/>
+ </button>
+ </div>
</t>
<t t-name="Throbber">