diff --git a/addons/web/i18n/zh_CN.po b/addons/web/i18n/zh_CN.po index d90ed916ffd..09a7d041b88 100644 --- a/addons/web/i18n/zh_CN.po +++ b/addons/web/i18n/zh_CN.po @@ -14,7 +14,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-11-06 05:12+0000\n" +"X-Launchpad-Export-Date: 2012-11-07 04:55+0000\n" "X-Generator: Launchpad (build 16232)\n" #. openerp-web diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index c97b59ec6fe..94d02758ad0 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -659,7 +659,7 @@ cursor: pointer; } .openerp .oe_dropdown_toggle { - color: rgba(0, 0, 0, 0.5); + color: rgba(0, 0, 0, 0.3); font-weight: normal; } .openerp .oe_dropdown_hover:hover .oe_dropdown_menu, .openerp .oe_dropdown_menu.oe_opened { @@ -2565,7 +2565,7 @@ background-color: #eeeeee; } .openerp .oe_list_editable .oe_list_content td.oe_list_field_cell { - padding: 4px 6px 3px 6px; + padding: 4px 6px 3px; } .openerp .oe_list.oe_list_editable.oe_editing .oe_edition .oe_list_field_cell:not(.oe_readonly) { color: transparent; @@ -2646,6 +2646,9 @@ margin: 0 !important; padding: 0; } +.openerp .oe_list .oe_form .oe_form_field_boolean { + padding: 1px 6px 3px; +} .openerp .oe_list .oe_list_content .oe_group_header { background-color: #fcfcfc; background-image: -webkit-gradient(linear, left top, left bottom, from(#fcfcfc), to(#dedede)); diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass index 18451352370..f911929e159 100644 --- a/addons/web/static/src/css/base.sass +++ b/addons/web/static/src/css/base.sass @@ -569,7 +569,7 @@ $sheet-padding: 16px position: relative cursor: pointer .oe_dropdown_toggle - color: rgba(0,0,0,0.5) + color: rgba(0,0,0,0.3) font-weight: normal .oe_dropdown_hover:hover .oe_dropdown_menu, .oe_dropdown_menu.oe_opened display: block @@ -2030,10 +2030,8 @@ $sheet-padding: 16px background-color: #eee $row-height: 27px - .oe_list_editable - .oe_list_content - td.oe_list_field_cell - padding: 4px 6px 3px 6px + .oe_list_editable .oe_list_content td.oe_list_field_cell + padding: 4px 6px 3px .oe_list.oe_list_editable.oe_editing .oe_edition .oe_list_field_cell:not(.oe_readonly) * @@ -2106,6 +2104,10 @@ $sheet-padding: 16px position: absolute margin: 0 !important // dammit padding: 0 + .oe_form_field_boolean + // use padding similar to actual cell to correctly position the + // checkbox + padding: 1px 6px 3px .oe_list_content .oe_group_header @include vertical-gradient(#fcfcfc, #dedede) diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index b2ded00c105..d005c79e9b2 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -1656,11 +1656,20 @@ instance.web.search.Advanced = instance.web.search.Input.extend({ }); }, append_proposition: function () { + var self = this; return (new instance.web.search.ExtendedSearchProposition(this, this.fields)) - .appendTo(this.$('ul')); + .appendTo(this.$('ul')).then(function () { + self.$('button.oe_apply').prop('disabled', false); + }); + }, + remove_proposition: function (prop) { + // removing last proposition, disable apply button + if (this.getChildren().length <= 1) { + this.$('button.oe_apply').prop('disabled', true); + } + prop.destroy(); }, commit_search: function () { - var self = this; // Get domain sections from all propositions var children = this.getChildren(); var propositions = _.invoke(children, 'get_proposition'); @@ -1694,7 +1703,7 @@ instance.web.search.ExtendedSearchProposition = instance.web.Widget.extend(/** @ 'change .searchview_extended_prop_field': 'changed', 'click .searchview_extended_delete_prop': function (e) { e.stopPropagation(); - this.destroy(); + this.getParent().remove_proposition(this); } }, /** @@ -1714,7 +1723,7 @@ instance.web.search.ExtendedSearchProposition = instance.web.Widget.extend(/** @ this.value = null; }, start: function () { - this.changed(); + return this._super().then(this.proxy('changed')); }, changed: function() { var nval = this.$(".searchview_extended_prop_field").val(); diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 07c237ae0d8..e3b4b98a364 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -2216,6 +2216,13 @@ instance.web.form.FieldChar = instance.web.form.AbstractField.extend(instance.we }, focus: function() { this.$('input:first').focus(); + }, + set_dimensions: function (height, width) { + this._super(height, width); + this.$('input').css({ + height: height, + width: width + }); } }); @@ -2502,7 +2509,7 @@ instance.web.form.FieldText = instance.web.form.AbstractField.extend(instance.we this.$textarea.focus(); }, set_dimensions: function (height, width) { - this._super(); + this._super(height, width); this.$textarea.css({ width: width, minHeight: height @@ -2664,6 +2671,13 @@ instance.web.form.FieldSelection = instance.web.form.AbstractField.extend(instan }, focus: function() { this.$el.find('select:first').focus(); + }, + set_dimensions: function (height, width) { + this._super(height, width); + this.$('select').css({ + height: height, + width: width + }); } }); @@ -3146,6 +3160,62 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc this.ed_def.reject(); return instance.web.form.CompletionFieldMixin._search_create_popup.apply(this, arguments); }, + set_dimensions: function (height, width) { + this._super(height, width); + this.$input.css('height', height); + } +}); + +instance.web.form.Many2OneButton = instance.web.form.AbstractField.extend({ + template: 'Many2OneButton', + init: function(field_manager, node) { + this._super.apply(this, arguments); + }, + start: function() { + this._super.apply(this, arguments); + this.set_button(); + }, + set_button: function() { + var self = this; + if (this.$button) { + this.$button.remove(); + } + var options = {}; + try { + options = py.eval(this.node.attrs.options); + } catch (e) {} + if (options.label) { + this.string = this.get('value') ? _t(options.label.edit) : _t(options.label.create); + } else { + this.string = ''; + } + this.node.attrs.icon = this.get('value') ? '/web/static/src/img/icons/gtk-yes.png' : '/web/static/src/img/icons/gtk-no.png'; + this.$button = $(QWeb.render('WidgetButton', {'widget': this})); + this.$el.append(this.$button); + this.$button.on('click', self.on_click); + }, + on_click: function(ev) { + var self = this; + this.popup = new instance.web.form.FormOpenPopup(this); + this.popup.show_element( + this.field.relation, + this.get('value'), + this.build_context(), + {title: this.string} + ); + this.popup.on('create_completed write_completed', self, function(r) { + self.set_value(r); + }); + }, + set_value: function(value_) { + var self = this; + if (value_ instanceof Array) { + value_ = value_[0]; + } + value_ = value_ || false; + this.set('value', value_); + this.set_button(); + }, }); /* @@ -3922,6 +3992,8 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in var dataset = new instance.web.DataSetStatic(this, this.field.relation, self.build_context()); var values = self.get("value") var handle_names = function(data) { + if (self.isDestroyed()) + return; var indexed = {}; _.each(data, function(el) { indexed[el[0]] = el; @@ -4420,6 +4492,7 @@ instance.web.form.AbstractFormPopup = instance.web.Widget.extend({ this.destroy(); }, destroy: function () { + this.trigger('closed'); this.$el.dialog('close'); this._super(); }, @@ -4823,6 +4896,7 @@ instance.web.form.FieldBinaryFile = instance.web.form.FieldBinary.extend({ instance.web.form.FieldBinaryImage = instance.web.form.FieldBinary.extend({ template: 'FieldBinaryImage', + placeholder: "/web/static/src/img/placeholder.png", render_value: function() { var self = this; var url; @@ -4836,7 +4910,7 @@ instance.web.form.FieldBinaryImage = instance.web.form.FieldBinary.extend({ url = '/web/binary/image?session_id=' + this.session.session_id + '&model=' + this.view.dataset.model +'&id=' + id + '&field=' + field + '&t=' + (new Date().getTime()); } else { - url = "/web/static/src/img/placeholder.png"; + url = this.placeholder; } var $img = $(QWeb.render("FieldBinaryImage-img", { widget: this, url: url })); this.$el.find('> img').remove(); @@ -4849,10 +4923,10 @@ instance.web.form.FieldBinaryImage = instance.web.form.FieldBinary.extend({ $img.css("margin-left", "" + (self.options.size[0] - $img.width()) / 2 + "px"); $img.css("margin-top", "" + (self.options.size[1] - $img.height()) / 2 + "px"); }); - }, - on_file_change: function() { - this.render_value(); - this._super.apply(this, arguments); + $img.on('error', function() { + $img.attr('src', self.placeholder); + instance.webclient.notification.warn(_t("Image"), _t("Could not display the selected image.")); + }); }, on_file_uploaded_and_valid: function(size, name, content_type, file_base64) { this.internal_set_value(file_base64); @@ -5132,6 +5206,7 @@ instance.web.form.widgets = new instance.web.Registry({ 'datetime' : 'instance.web.form.FieldDatetime', 'selection' : 'instance.web.form.FieldSelection', 'many2one' : 'instance.web.form.FieldMany2One', + 'many2onebutton' : 'instance.web.form.Many2OneButton', 'many2many' : 'instance.web.form.FieldMany2Many', 'many2many_tags' : 'instance.web.form.FieldMany2ManyTags', 'many2many_kanban' : 'instance.web.form.FieldMany2ManyKanban', diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index ab50ae933d9..e59fb3c4d84 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -2012,6 +2012,7 @@ instance.web.list.columns = new instance.web.Registry({ 'field.progressbar': 'instance.web.list.ProgressBar', 'field.handle': 'instance.web.list.Handle', 'button': 'instance.web.list.Button', + 'field.many2onebutton': 'instance.web.list.Many2OneButton', }); instance.web.list.columns.for_ = function (id, field, node) { var description = _.extend({tag: node.tag}, field, node.attrs); @@ -2199,5 +2200,11 @@ instance.web.list.Handle = instance.web.list.Column.extend({ return '
'; } }); +instance.web.list.Many2OneButton = instance.web.list.Column.extend({ + _format: function (row_data, options) { + this.has_value = !!row_data[this.id].value; + return QWeb.render('Many2OneButton.cell', {'widget': this}); + }, +}); }; // vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/web/static/src/js/view_tree.js b/addons/web/static/src/js/view_tree.js index 05760420ba8..3f1dfabe80a 100644 --- a/addons/web/static/src/js/view_tree.js +++ b/addons/web/static/src/js/view_tree.js @@ -45,7 +45,7 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie view_type: "tree", toolbar: this.view_manager ? !!this.view_manager.sidebar : false, context: this.dataset.get_context() - }).then(this.on_loaded); + }, this.on_loaded); }, /** * Returns the list of fields needed to correctly read objects. @@ -63,12 +63,6 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie } return fields; }, - store_record:function(records){ - var self = this; - _(records).each(function (record) { - self.records[record.id] = record; - }); - }, on_loaded: function (fields_view) { var self = this; var has_toolbar = !!fields_view.arch.attrs.toolbar; @@ -93,19 +87,17 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie this.$el.addClass(this.fields_view.arch.attrs['class']); this.dataset.read_slice(this.fields_list()).then(function(records) { - self.store_record(records); if (!has_toolbar) { // WARNING: will do a second read on the same ids, but only on // first load so not very important - self.render_data({'null':records}) - self.getdata(_.pluck(records,"id")); + self.getdata(null, _(records).pluck('id')); return; } var $select = self.$el.find('select') .change(function () { var $option = $(this).find(':selected'); - self.getdata($option.val()); + self.getdata($option.val(), $option.data('children')); }); _(records).each(function (record) { self.records[record.id] = record; @@ -120,12 +112,7 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie $select.change(); } }); - this.$el.find("#tree_view_expand").click(function(){ - self.expand_all(); - }); - this.$el.find("#tree_view_collapse").click(function(){ - self.collpase_all(); - }); + // TODO store open nodes in url ?... this.do_push_state({}); @@ -141,22 +128,6 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie return [color, py.parse(py.tokenize(expr)), expr]; }).value(); }, - expand_all: function(){ - var self = this; - var tr = this.$el.find(".oe-treeview-table tbody tr[id^='treerow_']"); - _.each(tr,function(rec){ - self.showcontent($(rec).attr('data-id'),true); - }); - }, - collpase_all: function(){ - var self = this; - var root_tr = this.$el.find(".oe-treeview-table tbody tr[data-level='"+1+"']"); - _.each(root_tr,function(rec){ - if($(rec).hasClass('oe_open')){ - self.showcontent($(rec).attr('data-id'),false); - } - }); - }, /** * Returns the color for the provided record in the current view (from the * ``@colors`` attribute) @@ -193,44 +164,50 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie }); this.$el.delegate('.treeview-tr', 'click', function () { - var $this = $(this), + var is_loaded = 0, + $this = $(this), record_id = $this.data('id'), - bool = $this.parent().hasClass('oe_open'); - self.showcontent(record_id, !bool); + record = self.records[record_id], + children_ids = record[self.children_field]; + + _(children_ids).each(function(childid) { + if (self.$el.find('#treerow_' + childid).length) { + if (self.$el.find('#treerow_' + childid).is(':hidden')) { + is_loaded = -1; + } else { + is_loaded++; + } + } + }); + if (is_loaded === 0) { + if (!$this.parent().hasClass('oe_open')) { + self.getdata(record_id, children_ids); + } + } else { + self.showcontent(record_id, is_loaded < 0); + } }); }, // get child data of selected value - getdata: function (id) { + getdata: function (id, children_ids) { var self = this; - var parent_child ={}; - id = _.isArray(id)?id:parseInt(id); - var ir_model_data = new instance.web.Model(this.model,self.dataset.get_context() || {},[['id','child_of',id]]).query(); - ir_model_data._execute().then(function(records){ - self.store_record(records); - _.each(records,function(rec){ - if(rec[self.children_field].length === 0)return; - parent_child[rec.id] = []; - _.each(rec[self.children_field],function(key){ - parent_child[rec.id].push(self.records[key]); - }); - }) - self.render_data(parent_child); - }); - }, - render_data: function(groupby){ - var self = this; - _.each(_.keys(groupby),function(key){ - var $curr_node = self.$el.find('#treerow_' + key); - var record = groupby[key]; + + self.dataset.read_ids(children_ids, this.fields_list()).then(function(records) { + _(records).each(function (record) { + self.records[record.id] = record; + }); + + var $curr_node = self.$el.find('#treerow_' + id); var children_rows = QWeb.render('TreeView.rows', { - 'records': record, + 'records': records, 'children_field': self.children_field, 'fields_view': self.fields_view.arch.children, 'fields': self.fields, - 'level': ($curr_node.data('level') || 0) + 1, + 'level': $curr_node.data('level') || 0, 'render': instance.web.format_value, 'color_for': self.color_for }); + if ($curr_node.length) { $curr_node.addClass('oe_open'); $curr_node.after(children_rows); @@ -238,10 +215,8 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie self.$el.find('tbody').html(children_rows); } }); - self.collpase_all(); }, - // Get details in listview activate: function(id) { var self = this; @@ -284,5 +259,13 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie }, this); }, + do_show: function () { + this.$el.show(); + }, + + do_hide: function () { + this.$el.hide(); + this.hidden = true; + } }); }; diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 275d31a9fde..215374cb6fb 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -567,16 +567,14 @@ -
- - - -
- + +
@@ -588,11 +586,11 @@ + t-att-data-id="record.id" t-att-data-level="level + 1"> - +
+ t-if="!field.attrs.modifiers.tree_invisible" + class="treeview-header">
+ + + + + +
diff --git a/addons/web_kanban/static/src/css/kanban.css b/addons/web_kanban/static/src/css/kanban.css index 837d11949bc..f968364c987 100644 --- a/addons/web_kanban/static/src/css/kanban.css +++ b/addons/web_kanban/static/src/css/kanban.css @@ -144,8 +144,13 @@ margin-left: 4px; cursor: pointer; position: relative; +} +.openerp .oe_kanban_view .oe_kanban_add { top: -8px; } +.openerp .oe_kanban_view .oe_kanban_header .oe_dropdown_toggle { + top: -2px; +} .openerp .oe_kanban_view .oe_kanban_card, .openerp .oe_kanban_view .oe_dropdown_toggle { cursor: pointer; display: inline-block; @@ -481,7 +486,6 @@ } .openerp .oe_kanban_view .oe_dropdown_kanban { float: right; - clear: both; cursor: pointer; margin-top: -6px; } diff --git a/addons/web_kanban/static/src/css/kanban.sass b/addons/web_kanban/static/src/css/kanban.sass index aea5d6bc8c0..459fc56092d 100644 --- a/addons/web_kanban/static/src/css/kanban.sass +++ b/addons/web_kanban/static/src/css/kanban.sass @@ -168,7 +168,10 @@ margin-left: 4px cursor: pointer position: relative + .oe_kanban_add top: -8px + .oe_kanban_header .oe_dropdown_toggle + top: -2px .oe_kanban_card, .oe_dropdown_toggle cursor: pointer display: inline-block @@ -414,7 +417,6 @@ // KanbanDropDown {{{ .oe_dropdown_kanban float: right - clear: both cursor: pointer margin-top: -6px &:hover