Added Gruntfile with jshint and corrected most js errors
[odoo/odoo.git] / addons / web / static / src / js / data_export.js
1 openerp.web.data_export = function(instance) {
2 var QWeb = instance.web.qweb,
3       _t = instance.web._t;
4 instance.web.DataExport = instance.web.Dialog.extend({
5     template: 'ExportTreeView',
6     dialog_title: {toString: function () { return _t("Export Data"); }},
7     events: {
8         'click #add_field': function () {
9             var self = this;
10             this.$('#field-tree-structure tr.ui-selected')
11                 .removeClass('ui-selected')
12                 .find('a').each(function () {
13                     var id = $(this).attr('id').split('-')[1];
14                     var string = $(this).attr('string');
15                     self.add_field(id, string);
16                 });
17         },
18         'click #remove_field': function () {
19             this.$('#fields_list option:selected').remove();
20         },
21         'click #remove_all_field': function () {
22             this.$('#fields_list').empty();
23         },
24         'click #export_new_list': 'on_show_save_list',
25     },
26     init: function(parent, dataset) {
27         var self = this;
28         var options = {
29             buttons: [
30                 {text: _t("Close"), click: function () { self.close(); }},
31                 {text: _t("Export To File"), click: function () { self.on_click_export_data(); }}
32             ],
33             close: function () { self.close();}
34         };
35         this._super(parent, options);
36         this.records = {};
37         this.dataset = dataset;
38         this.exports = new instance.web.DataSetSearch(
39             this, 'ir.exports', this.dataset.get_context());
40     },
41     start: function() {
42         var self = this;
43         this._super.apply(this, arguments);
44         self.$el.removeClass('ui-dialog-content ui-widget-content');
45
46         var got_fields = new $.Deferred();
47         this.$el.find('#import_compat').change(function() {
48             self.$el.find('#fields_list').empty();
49             self.$el.find('#field-tree-structure').remove();
50             var import_comp = self.$el.find("#import_compat").val();
51             self.rpc("/web/export/get_fields", {
52                 model: self.dataset.model,
53                 import_compat: !!import_comp,
54             }).done(function (records) {
55                 got_fields.resolve();
56                 self.on_show_data(records);
57             });
58         }).change();
59
60         return $.when(
61             got_fields,
62             this.rpc('/web/export/formats', {}).done(this.do_setup_export_formats),
63             this.show_exports_list());
64     },
65     do_setup_export_formats: function (formats) {
66         var $fmts = this.$el.find('#export_format');
67         _(formats).each(function (format) {
68             var opt = new Option(format.label, format.tag);
69             if (format.error) {
70                 opt.disabled = true;
71                 opt.replaceChild(
72                     document.createTextNode(
73                         _.str.sprintf("%s — %s", format.label, format.error)),
74                     opt.childNodes[0])
75             }
76             $fmts.append(opt);
77         });
78     },
79     show_exports_list: function() {
80         var self = this;
81         if (self.$el.find('#saved_export_list').is(':hidden')) {
82             self.$el.find('#ExistsExportList').show();
83             return $.when();
84         }
85         return this.exports.read_slice(['name'], {
86             domain: [['resource', '=', this.dataset.model]]
87         }).done(function (export_list) {
88             if (!export_list.length) {
89                 return;
90             }
91             self.$el.find('#ExistsExportList').append(QWeb.render('Exists.ExportList', {'existing_exports': export_list}));
92             self.$el.find('#saved_export_list').change(function() {
93                 self.$el.find('#fields_list option').remove();
94                 var export_id = self.$el.find('#saved_export_list option:selected').val();
95                 if (export_id) {
96                     self.rpc('/web/export/namelist', {'model': self.dataset.model, export_id: parseInt(export_id, 10)}).done(self.do_load_export_field);
97                 }
98             });
99             self.$el.find('#delete_export_list').click(function() {
100                 var select_exp = self.$el.find('#saved_export_list option:selected');
101                 if (select_exp.val()) {
102                     self.exports.unlink([parseInt(select_exp.val(), 10)]);
103                     select_exp.remove();
104                     if (self.$el.find('#saved_export_list option').length <= 1) {
105                         self.$el.find('#ExistsExportList').hide();
106                     }
107                 }
108             });
109         });
110     },
111     do_load_export_field: function(field_list) {
112         var export_node = this.$el.find("#fields_list");
113         _(field_list).each(function (field) {
114             export_node.append(new Option(field.label, field.name));
115         });
116     },
117     on_show_save_list: function() {
118         var self = this;
119         var current_node = self.$el.find("#savenewlist");
120         if (!(current_node.find("label")).length) {
121             current_node.append(QWeb.render('ExportNewList'));
122             current_node.find("#add_export_list").click(function() {
123                 var value = current_node.find("#savelist_name").val();
124                 if (value) {
125                     self.do_save_export_list(value);
126                 } else {
127                     alert(_t("Please enter save field list name"));
128                 }
129             });
130         } else {
131             if (current_node.is(':hidden')) {
132                 current_node.show();
133                 current_node.find("#savelist_name").val("");
134             } else {
135                current_node.hide();
136             }
137         }
138     },
139     do_save_export_list: function(value) {
140         var self = this;
141         var fields = self.get_fields();
142         if (!fields.length) {
143             return;
144         }
145         this.exports.create({
146             name: value,
147             resource: this.dataset.model,
148             export_fields: _(fields).map(function (field) {
149                 return [0, 0, {name: field}];
150             })
151         }, function (export_list_id) {
152             if (!export_list_id.result) {
153                 return;
154             }
155             self.$el.find("#saved_export_list").append(
156                     new Option(value, export_list_id.result));
157             if (self.$el.find("#saved_export_list").is(":hidden")) {
158                 self.show_exports_list();
159             }
160         });
161         this.on_show_save_list();
162         this.$el.find("#fields_list option").remove();
163     },
164     on_click: function(id, record) {
165         var self = this;
166         if (!record['children']) {
167             return;
168         }
169         var model = record['params']['model'],
170             prefix = record['params']['prefix'],
171             name = record['params']['name'],
172             exclude_fields = [];
173         if (record['relation_field']) {
174             exclude_fields.push(record['relation_field']);
175         }
176
177         if (!record.loaded) {
178             var import_comp = self.$el.find("#import_compat").val();
179             self.rpc("/web/export/get_fields", {
180                 model: model,
181                 prefix: prefix,
182                 parent_name: name,
183                 import_compat: Boolean(import_comp),
184                 parent_field_type : record['field_type'],
185                 exclude: exclude_fields
186             }).done(function(results) {
187                 record.loaded = true;
188                 self.on_show_data(results, record.id);
189             });
190         } else {
191             self.showcontent(record.id);
192         }
193     },
194     on_show_data: function(result, after) {
195         var self = this;
196
197         if (after) {
198             var current_tr = self.$el.find("tr[id='treerow-" + after + "']");
199             current_tr.addClass('open');
200             current_tr.find('img').attr('src','/web/static/src/img/collapse.gif');
201             current_tr.after(QWeb.render('ExportTreeView-Secondary.children', {'fields': result}));
202         } else {
203             self.$el.find('#left_field_panel').append(QWeb.render('ExportTreeView-Secondary', {'fields': result}));
204         }
205         _.each(result, function(record) {
206             self.records[record.id] = record.value;
207             if (record.required) {
208                 var required_fld = self.$el.find("tr[id='treerow-" + record.id + "']").find('#tree-column');
209                 required_fld.addClass("oe_export_requiredfield");
210             }
211             self.$el.find("img[id='parentimg-" + record.id +"']").click(function() {
212                 self.on_click(this.id, record);
213             });
214
215             self.$el.find("tr[id='treerow-" + record.id + "']").click(function(e) {
216                 if (e.shiftKey) {
217                     var frst_click, scnd_click = '';
218                     if (self.row_index === 0) {
219                         self.row_index = this.rowIndex;
220                         frst_click = self.$el.find("tr[id^='treerow-']")[self.row_index-1];
221                         $(frst_click).addClass("ui-selected");
222                     } else {
223                         var i;
224                         if (this.rowIndex >=self.row_index) {
225                             for (i = (self.row_index-1); i < this.rowIndex; i++) {
226                                 scnd_click = self.$el.find("tr[id^='treerow-']")[i];
227                                 if (!$(scnd_click).find('#tree-column').hasClass("oe_export_readonlyfield")) {
228                                     $(scnd_click).addClass("ui-selected");
229                                 }
230                             }
231                         } else {
232                             for (i = (self.row_index-1); i >= (this.rowIndex-1); i--) {
233                                 scnd_click = self.$el.find("tr[id^='treerow-']")[i];
234                                 if (!$(scnd_click).find('#tree-column').hasClass("oe_export_readonlyfield")) {
235                                     $(scnd_click).addClass("ui-selected");
236                                 }
237                             }
238                         }
239                     }
240                 }
241                 self.row_index = this.rowIndex;
242
243                 self.$el.find("tr[id='treerow-" + record.id + "']").keyup(function() {
244                     self.row_index = 0;
245                 });
246                 var o2m_selection = self.$el.find("tr[id='treerow-" + record.id + "']").find('#tree-column');
247                 if ($(o2m_selection).hasClass("oe_export_readonlyfield")) {
248                     return false;
249                 }
250                 if (e.ctrlKey) {
251                     if ($(this).hasClass('ui-selected')) {
252                         $(this).removeClass('ui-selected').find('a').blur();
253                     } else {
254                         $(this).addClass('ui-selected').find('a').focus();
255                     }
256                 } else if (!e.shiftKey) {
257                     self.$el.find("tr.ui-selected")
258                             .removeClass("ui-selected").find('a').blur();
259                     $(this).addClass("ui-selected").find('a').focus();
260                 }
261                 return false;
262             });
263
264             self.$el.find("tr[id='treerow-" + record.id + "']").keydown(function(e) {
265                 var keyCode = e.keyCode || e.which;
266                 var arrow = {left: 37, up: 38, right: 39, down: 40 };
267                 var elem;
268                 switch (keyCode) {
269                     case arrow.left:
270                         if ($(this).hasClass('open')) {
271                             self.on_click(this.id, record);
272                         }
273                         break;
274                     case arrow.right:
275                         if (!$(this).hasClass('open')) {
276                             self.on_click(this.id, record);
277                         }
278                         break;
279                     case arrow.up:
280                         elem = this;
281                         $(elem).removeClass("ui-selected");
282                         while (!$(elem).prev().is(":visible")) {
283                             elem = $(elem).prev();
284                         }
285                         if (!$(elem).prev().find('#tree-column').hasClass("oe_export_readonlyfield")) {
286                             $(elem).prev().addClass("ui-selected");
287                         }
288                         $(elem).prev().find('a').focus();
289                         break;
290                     case arrow.down:
291                         elem = this;
292                         $(elem).removeClass("ui-selected");
293                         while(!$(elem).next().is(":visible")) {
294                             elem = $(elem).next();
295                         }
296                         if (!$(elem).next().find('#tree-column').hasClass("oe_export_readonlyfield")) {
297                             $(elem).next().addClass("ui-selected");
298                         }
299                         $(elem).next().find('a').focus();
300                         break;
301                 }
302             });
303             self.$el.find("tr[id='treerow-" + record.id + "']").dblclick(function() {
304                 var $o2m_selection = self.$el.find("tr[id^='treerow-" + record.id + "']").find('#tree-column');
305                 if (!$o2m_selection.hasClass("oe_export_readonlyfield")) {
306                    self.add_field(record.id, $(this).find("a").attr("string"));
307                 }
308             });
309         });
310         self.$el.find('#fields_list').mouseover(function(event) {
311             if (event.relatedTarget) {
312                 if (event.relatedTarget.attributes['id'] && event.relatedTarget.attributes['string']) {
313                     var field_id = event.relatedTarget.attributes["id"]["value"];
314                     if (field_id && field_id.split("-")[0] === 'export') {
315                         if (!self.$el.find("tr[id='treerow-" + field_id.split("-")[1] + "']").find('#tree-column').hasClass("oe_export_readonlyfield")) {
316                             self.add_field(field_id.split("-")[1], event.relatedTarget.attributes["string"]["value"]);
317                         }
318                     }
319                 }
320             }
321         });
322     },
323     showcontent: function(id) {
324         // show & hide the contents
325         var $this = this.$el.find("tr[id='treerow-" + id + "']");
326         var is_open = $this.hasClass('open');
327         $this.toggleClass('open');
328
329         var first_child = $this.find('img');
330         if (is_open) {
331             first_child.attr('src', '/web/static/src/img/expand.gif');
332         } else {
333             first_child.attr('src', '/web/static/src/img/collapse.gif');
334         }
335         var child_field = this.$el.find("tr[id^='treerow-" + id +"/']");
336         var child_len = (id.split("/")).length + 1;
337         for (var i = 0; i < child_field.length; i++) {
338             var $child = $(child_field[i]);
339             if (is_open) {
340                 $child.hide();
341             } else if (child_len == (child_field[i].id.split("/")).length) {
342                 if ($child.hasClass('open')) {
343                     $child.removeClass('open');
344                     $child.find('img').attr('src', '/web/static/src/img/expand.gif');
345                 }
346                 $child.show();
347             }
348         }
349     },
350     add_field: function(field_id, string) {
351         var field_list = this.$el.find('#fields_list');
352         if (this.$el.find("#fields_list option[value='" + field_id + "']")
353                 && !this.$el.find("#fields_list option[value='" + field_id + "']").length) {
354             field_list.append(new Option(string, field_id));
355         }
356     },
357     get_fields: function() {
358         var export_fields = this.$("#fields_list option").map(function() {
359             return $(this).val();
360         }).get();
361         if (!export_fields.length) {
362             alert(_t("Please select fields to save export list..."));
363         }
364         return export_fields;
365     },
366     on_click_export_data: function() {
367         var self = this;
368         var exported_fields = this.$el.find('#fields_list option').map(function () {
369             // DOM property is textContent, but IE8 only knows innerText
370             return {name: self.records[this.value] || this.value,
371                     label: this.textContent || this.innerText};
372         }).get();
373
374         if (_.isEmpty(exported_fields)) {
375             alert(_t("Please select fields to export..."));
376             return;
377         }
378         exported_fields.unshift({name: 'id', label: 'External ID'});
379
380         var export_format = this.$el.find("#export_format").val();
381         var ids_to_export = this.$('#export_selection_only').prop('checked')
382                 ? this.getParent().get_selected_ids()
383                 : this.dataset.ids;
384
385         instance.web.blockUI();
386         this.session.get_file({
387             url: '/web/export/' + export_format,
388             data: {data: JSON.stringify({
389                 model: this.dataset.model,
390                 fields: exported_fields,
391                 ids: ids_to_export,
392                 domain: this.dataset.domain,
393                 import_compat: !!this.$el.find("#import_compat").val(),
394             })},
395             complete: instance.web.unblockUI,
396         });
397     },
398     close: function() {
399         this.$el.remove();
400         this._super();
401     }
402 });
403
404 };