summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
authorJiten (OpenERP) <jra@tinyerp.com>2011-11-22 10:48:03 +0530
committerJiten (OpenERP) <jra@tinyerp.com>2011-11-22 10:48:03 +0530
commit990ece97a5dfd2b22be25d73193452c034424cdb (patch)
treed0ebc692ed7d608d0cf4a79a5506e48e85ee4c9b /addons/web/static/src
parentaad7d22763beb1774218bd7f041a918a56237964 (diff)
parent8ca42daf0a1b0ef3505a0505328a9d785ecb564c (diff)
[MERGE] Merge from openerp-web.
bzr revid: jra@tinyerp.com-20111122051803-1ttx64ilabhxo4p1
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/css/base.css60
-rw-r--r--addons/web/static/src/js/core.js27
-rw-r--r--addons/web/static/src/js/data.js2
-rw-r--r--addons/web/static/src/js/search.js6
-rw-r--r--addons/web/static/src/js/view_form.js131
-rw-r--r--addons/web/static/src/js/view_tree.js17
-rw-r--r--addons/web/static/src/js/views.js16
-rw-r--r--addons/web/static/src/xml/base.xml18
8 files changed, 166 insertions, 111 deletions
diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css
index c061353d113..d8f31af1d35 100644
--- a/addons/web/static/src/css/base.css
+++ b/addons/web/static/src/css/base.css
@@ -809,33 +809,33 @@ label.error {
also on the first and last children of the first and last row
*/
.openerp .oe-listview table.oe-listview-content {
- -webkit-border-radius: 7px;
- -moz-border-radius: 7px;
- border-radius: 7px;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
}
.openerp .oe-listview table.oe-listview-content thead tr:first-child th:first-child {
- -webkit-border-top-left-radius: 7px;
- -moz-border-radius-topleft: 7px;
- border-top-left-radius: 7px;
+ -webkit-border-top-left-radius: 4px;
+ -moz-border-radius-topleft: 4px;
+ border-top-left-radius: 4px;
}
.openerp .oe-listview table.oe-listview-content thead tr:first-child th:last-child {
- -webkit-border-top-right-radius: 7px;
- -moz-border-radius-topright: 7px;
- border-top-right-radius: 7px;
+ -webkit-border-top-right-radius: 4px;
+ -moz-border-radius-topright: 4px;
+ border-top-right-radius: 4px;
}
.openerp .oe-listview table.oe-listview-content tfoot tr:last-child th:first-child,
.openerp .oe-listview table.oe-listview-content tfoot tr:last-child td:first-child,
.openerp .oe-listview table.oe-listview-content tbody:last-child tr:last-child th:first-child {
- -webkit-border-bottom-left-radius: 7px;
- -moz-border-radius-bottomleft: 7px;
- border-bottom-left-radius: 7px;
+ -webkit-border-bottom-left-radius: 4px;
+ -moz-border-radius-bottomleft: 4px;
+ border-bottom-left-radius: 4px;
}
.openerp .oe-listview table.oe-listview-content tfoot tr:last-child th:last-child,
.openerp .oe-listview table.oe-listview-content tfoot tr:last-child td:last-child,
.openerp .oe-listview table.oe-listview-content tbody:last-child tr:last-child td:last-child {
- -webkit-border-bottom-right-radius: 7px;
- -moz-border-radius-bottomright: 7px;
- border-bottom-right-radius: 7px;
+ -webkit-border-bottom-right-radius: 4px;
+ -moz-border-radius-bottomright: 4px;
+ border-bottom-right-radius: 4px;
}
/* Notebook */
@@ -967,20 +967,25 @@ label.error {
.openerp .oe_forms textarea {
resize:vertical;
}
-.openerp .oe_forms input[type="text"], .openerp .oe_forms input[type="password"], .openerp .oe_forms select, .openerp .oe_forms .button {
+.openerp .oe_forms input[type="text"], .openerp .oe_forms input[type="password"], .openerp .oe_forms select, .openerp .oe_forms .oe_button {
height: 22px;
}
.openerp .oe_forms input.field_datetime {
min-width: 11em;
}
-.openerp .oe_forms.oe_frame .oe_datepicker_root {
- width: 100%;
-}
-.openerp .oe_forms .button {
+.openerp .oe_forms .oe_button {
color: #4c4c4c;
white-space: nowrap;
+ min-width: 100%;
+ width: 100%;
}
-.openerp .oe_forms .button span {
+@-moz-document url-prefix() {
+ /* Strange firefox behaviour on width: 100% + white-space: nowrap */
+ .openerp .oe_forms .oe_button {
+ width: auto;
+ }
+}
+.openerp .oe_forms .oe_button span {
position: relative;
vertical-align: top;
}
@@ -989,13 +994,20 @@ label.error {
cursor: pointer;
right: 5px;
top: 3px;
+ z-index: 2;
+}
+.openerp .oe_datepicker_container {
+ position: absolute;
+ top: 0;
+ right: 0;
+ display: none;
}
.openerp .oe_datepicker_root {
position: relative;
display: inline-block;
}
-.openerp .oe_datepicker_root input[type="text"] {
- min-width: 160px;
+.openerp .oe_forms.oe_frame .oe_datepicker_root {
+ width: 100%;
}
.openerp .oe_input_icon_disabled {
position: absolute;
@@ -1003,7 +1015,7 @@ label.error {
opacity: 0.5;
filter:alpha(opacity=50);
right: 5px;
- top: 5px;
+ top: 3px;
}
.openerp img.oe_field_translate {
margin-left: -21px;
diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js
index f77f9bf1041..a9731ef5b16 100644
--- a/addons/web/static/src/js/core.js
+++ b/addons/web/static/src/js/core.js
@@ -125,7 +125,11 @@ openerp.web.callback = function(obj, method) {
callback.callback_chain.splice(i, 1);
i -= 1;
}
- r = c.callback.apply(c.self, c.args.concat(args));
+ var result = c.callback.apply(c.self, c.args.concat(args));
+ if (c.callback === method) {
+ // return the result of the original method
+ r = result;
+ }
// TODO special value to stop the chain
// openerp.web.callback_stop
}
@@ -354,6 +358,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
this.debug = (window.location.search.indexOf('?debug') !== -1);
this.session_id = false;
this.uid = false;
+ this.username = false;
this.user_context= {};
this.db = false;
this.module_list = [];
@@ -484,10 +489,13 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
var self = this;
var params = { db: db, login: login, password: password };
return this.rpc("/web/session/login", params, function(result) {
- self.session_id = result.session_id;
- self.uid = result.uid;
- self.user_context = result.context;
- self.db = result.db;
+ _.extend(self, {
+ session_id: result.session_id,
+ uid: result.uid,
+ user_context: result.context,
+ db: result.db,
+ username: result.login
+ });
self.session_save();
self.on_session_valid();
return true;
@@ -501,9 +509,12 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
var self = this;
this.session_id = this.get_cookie('session_id');
return this.rpc("/web/session/get_session_info", {}).then(function(result) {
- self.uid = result.uid;
- self.user_context = result.context;
- self.db = result.db;
+ _.extend(self, {
+ uid: result.uid,
+ user_context: result.context,
+ db: result.db,
+ username: result.login
+ });
if (self.uid)
self.on_session_valid();
else
diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js
index e783f374dce..69d8fd9ddfd 100644
--- a/addons/web/static/src/js/data.js
+++ b/addons/web/static/src/js/data.js
@@ -316,7 +316,7 @@ openerp.web.DataSet = openerp.web.Widget.extend( /** @lends openerp.web.DataSet
def.reject();
} else {
fields = fields || false;
- return this.read_ids([this.ids[this.index]], fields).then(function(records) {
+ this.read_ids([this.ids[this.index]], fields).then(function(records) {
def.resolve(records[0]);
}, function() {
def.reject.apply(def, arguments);
diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js
index c82584e87f8..f95801975b5 100644
--- a/addons/web/static/src/js/search.js
+++ b/addons/web/static/src/js/search.js
@@ -41,7 +41,11 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search
if (this.headless) {
this.ready.resolve();
} else {
- this.rpc("/web/searchview/load", {"model": this.model, "view_id":this.view_id}, this.on_loaded);
+ this.rpc("/web/searchview/load", {
+ model: this.model,
+ view_id: this.view_id,
+ context: this.dataset.get_context()
+ }, this.on_loaded);
}
return this.ready.promise();
},
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index 6cc46246651..8b84404f87a 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -140,7 +140,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
// null index means we should start a new record
promise = this.on_button_new();
} else {
- promise = this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded);
+ promise = this.dataset.read_index(_.keys(this.fields_view.fields)).pipe(this.on_record_loaded);
}
this.$element.show();
if (this.sidebar) {
@@ -155,6 +155,8 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
}
},
on_record_loaded: function(record) {
+ var self = this,
+ deferred_stack = $.Deferred.queue();
if (!record) {
throw("Form: No record received");
}
@@ -172,33 +174,41 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
this.$form_header.find('.oe_form_on_readonly').toggle(this.readonly);
this.$form_header.find('.oe_form_on_editable').toggle(!this.readonly);
this.datarecord = record;
- for (var f in this.fields) {
- var field = this.fields[f];
- field.dirty = false;
- field.set_value(this.datarecord[f] || false);
- field.validate();
- }
- if (!record.id) {
- // New record: Second pass in order to trigger the onchanges
- this.show_invalid = false;
- for (var f in record) {
- var field = this.fields[f];
- if (field) {
- field.dirty = true;
- this.do_onchange(field);
+
+ _(this.fields).each(function (field, f) {
+ field.reset();
+ var result = field.set_value(self.datarecord[f] || false);
+ if (result && _.isFunction(result.promise)) {
+ deferred_stack.push(result);
+ }
+ $.when(result).then(function() {
+ field.validate();
+ });
+ });
+ deferred_stack.push('force resolution if no fields');
+ return deferred_stack.then(function() {
+ if (!record.id) {
+ // New record: Second pass in order to trigger the onchanges
+ self.show_invalid = false;
+ for (var f in record) {
+ var field = self.fields[f];
+ if (field) {
+ field.dirty = true;
+ self.do_onchange(field);
+ }
}
}
- }
- this.on_form_changed();
- this.initial_mutating_lock.resolve();
- this.show_invalid = true;
- this.do_update_pager(record.id == null);
- if (this.sidebar) {
- this.sidebar.attachments.do_update();
- }
- if (this.default_focus_field && !this.embedded_view) {
- this.default_focus_field.focus();
- }
+ self.on_form_changed();
+ self.initial_mutating_lock.resolve();
+ self.show_invalid = true;
+ self.do_update_pager(record.id == null);
+ if (self.sidebar) {
+ self.sidebar.attachments.do_update();
+ }
+ if (self.default_focus_field && !self.embedded_view) {
+ self.default_focus_field.focus();
+ }
+ });
},
on_form_changed: function() {
for (var w in this.widgets) {
@@ -354,12 +364,13 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
var keys = _.keys(self.fields_view.fields);
$.when(self.do_set_editable()).then(function() {
if (keys.length) {
- self.dataset.default_get(keys).then(self.on_record_loaded).then(function() {
+ self.dataset.default_get(keys).pipe(self.on_record_loaded).then(function() {
def.resolve();
});
} else {
- self.on_record_loaded({});
- def.resolve();
+ self.on_record_loaded({}).then(function() {
+ def.resolve();
+ });
}
});
}
@@ -427,7 +438,10 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
if (!first_invalid_field) {
first_invalid_field = f;
}
- } else if (f.is_dirty()) {
+ } else if (f.name !== 'id' && !f.readonly && (!self.datarecord.id || f.is_dirty())) {
+ // Special case 'id' field, do not save this field
+ // on 'create' : save all non readonly fields
+ // on 'edit' : save non readonly modified fields
values[f.name] = f.get_value();
}
}
@@ -476,8 +490,8 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
// should not happen in the server, but may happen for internal purpose
return $.Deferred().reject();
} else {
- this.reload();
- return $.when(r).then(success);
+ return $.when(this.reload()).pipe(function () {
+ return $.when(r).then(success); }, null);
}
},
/**
@@ -524,7 +538,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
if (self.dataset.index == null || self.dataset.index < 0) {
return $.when(self.on_button_new());
} else {
- return self.dataset.read_index(_.keys(self.fields_view.fields), self.on_record_loaded);
+ return self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_record_loaded);
}
};
this.reload_lock = this.reload_lock.pipe(act, act);
@@ -1180,8 +1194,7 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f
this.nolabel = (this.field.nolabel || node.attrs.nolabel) === '1';
this.readonly = this.modifiers['readonly'] === true;
this.required = this.modifiers['required'] === true;
- this.invalid = false;
- this.dirty = false;
+ this.invalid = this.dirty = false;
this.classname = 'oe_form_field_' + this.type;
},
@@ -1251,6 +1264,9 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f
this.invalid = false;
},
focus: function() {
+ },
+ reset: function() {
+ this.dirty = false;
}
});
@@ -1340,7 +1356,6 @@ openerp.web.form.FieldFloat = openerp.web.form.FieldChar.extend({
if (value === false || value === undefined) {
// As in GTK client, floats default to 0
value = 0;
- this.dirty = true;
}
this._super.apply(this, [value]);
}
@@ -1350,54 +1365,58 @@ openerp.web.DateTimeWidget = openerp.web.Widget.extend({
template: "web.datetimepicker",
jqueryui_object: 'datetimepicker',
type_of_date: "datetime",
+ init: function(parent) {
+ this._super(parent);
+ this.name = parent.name;
+ },
start: function() {
var self = this;
- this.$element.find('input').change(this.on_change);
+ this.$input = this.$element.find('input.oe_datepicker_master');
+ this.$input_picker = this.$element.find('input.oe_datepicker_container');
+ this.$input.change(this.on_change);
this.picker({
onSelect: this.on_picker_select,
changeMonth: true,
changeYear: true,
showWeek: true,
- showButtonPanel: false
+ showButtonPanel: true
});
this.$element.find('img.oe_datepicker_trigger').click(function() {
if (!self.readonly) {
self.picker('setDate', self.value ? openerp.web.auto_str_to_date(self.value) : new Date());
- self.$element.find('.oe_datepicker').toggle();
+ self.$input_picker.show();
+ self.picker('show');
+ self.$input_picker.hide();
}
});
- this.$element.find('.ui-datepicker-inline').removeClass('ui-widget-content ui-corner-all');
- this.$element.find('button.oe_datepicker_close').click(function() {
- self.$element.find('.oe_datepicker').hide();
- });
this.set_readonly(false);
this.value = false;
},
picker: function() {
- return $.fn[this.jqueryui_object].apply(this.$element.find('.oe_datepicker_container'), arguments);
+ return $.fn[this.jqueryui_object].apply(this.$input_picker, arguments);
},
on_picker_select: function(text, instance) {
var date = this.picker('getDate');
- this.$element.find('input').val(date ? this.format_client(date) : '').change();
+ this.$input.val(date ? this.format_client(date) : '').change();
},
set_value: function(value) {
this.value = value;
- this.$element.find('input').val(value ? this.format_client(value) : '');
+ this.$input.val(value ? this.format_client(value) : '');
},
get_value: function() {
return this.value;
},
set_value_from_ui: function() {
- var value = this.$element.find('input').val() || false;
+ var value = this.$input.val() || false;
this.value = this.parse_client(value);
},
set_readonly: function(readonly) {
this.readonly = readonly;
- this.$element.find('input').attr('disabled', this.readonly);
+ this.$input.attr('disabled', this.readonly);
this.$element.find('img.oe_datepicker_trigger').toggleClass('oe_input_icon_disabled', readonly);
},
is_valid: function(required) {
- var value = this.$element.find('input').val();
+ var value = this.$input.val();
if (value === "") {
return !required;
} else {
@@ -1410,7 +1429,7 @@ openerp.web.DateTimeWidget = openerp.web.Widget.extend({
}
},
focus: function() {
- this.$element.find('input').focus();
+ this.$input.focus();
},
parse_client: function(v) {
return openerp.web.parse_value(v, {"widget": this.type_of_date});
@@ -1427,11 +1446,7 @@ openerp.web.DateTimeWidget = openerp.web.Widget.extend({
openerp.web.DateWidget = openerp.web.DateTimeWidget.extend({
jqueryui_object: 'datepicker',
- type_of_date: "date",
- on_picker_select: function(text, instance) {
- this._super(text, instance);
- this.$element.find('.oe_datepicker').hide();
- }
+ type_of_date: "date"
});
openerp.web.form.FieldDatetime = openerp.web.form.Field.extend({
@@ -2109,7 +2124,7 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({
},
reload_current_view: function() {
var self = this;
- self.is_loaded = self.is_loaded.pipe(function() {
+ return self.is_loaded = self.is_loaded.pipe(function() {
var view = self.viewmanager.views[self.viewmanager.active_view].controller;
if(self.viewmanager.active_view === "list") {
return view.reload_content();
@@ -2182,8 +2197,8 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({
if (this.dataset.index === null && this.dataset.ids.length > 0) {
this.dataset.index = 0;
}
- self.reload_current_view();
- this.is_setted.resolve();
+ self.is_setted.resolve();
+ return self.reload_current_view();
},
get_value: function() {
var self = this;
diff --git a/addons/web/static/src/js/view_tree.js b/addons/web/static/src/js/view_tree.js
index 5143adb3838..34d47b92813 100644
--- a/addons/web/static/src/js/view_tree.js
+++ b/addons/web/static/src/js/view_tree.js
@@ -42,7 +42,8 @@ openerp.web.TreeView = openerp.web.View.extend(/** @lends openerp.web.TreeView#
model: this.model,
view_id: this.view_id,
view_type: "tree",
- toolbar: this.view_manager ? !!this.view_manager.sidebar : false
+ toolbar: this.view_manager ? !!this.view_manager.sidebar : false,
+ context: this.dataset.get_context()
}, this.on_loaded);
},
/**
@@ -214,17 +215,23 @@ openerp.web.TreeView = openerp.web.View.extend(/** @lends openerp.web.TreeView#
// Get details in listview
activate: function(id) {
var self = this;
+ var local_context = {
+ active_model: self.dataset.model,
+ active_id: id,
+ active_ids: [id]};
this.rpc('/web/treeview/action', {
id: id,
model: this.dataset.model,
context: new openerp.web.CompoundContext(
- this.dataset.get_context(), {
- active_model: this.dataset.model,
- active_id: id,
- active_ids: [id]})
+ this.dataset.get_context(), local_context)
}, function (actions) {
if (!actions.length) { return; }
var action = actions[0][2];
+ var c = new openerp.web.CompoundContext(local_context);
+ if (action.context) {
+ c.add(action.context);
+ }
+ action.context = c;
self.do_action(action);
});
},
diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js
index d348b2d7240..90060f47fc1 100644
--- a/addons/web/static/src/js/views.js
+++ b/addons/web/static/src/js/views.js
@@ -143,7 +143,7 @@ session.web.ActionManager = session.web.Widget.extend({
var ClientWidget = session.web.client_actions.get_object(action.tag);
(this.client_widget = new ClientWidget(this, action.params)).appendTo(this);
},
- ir_actions_report_xml: function(action) {
+ ir_actions_report_xml: function(action, on_closed) {
var self = this;
$.blockUI();
self.rpc("/web/session/eval_domain_and_context", {
@@ -155,8 +155,14 @@ session.web.ActionManager = session.web.Widget.extend({
self.session.get_file({
url: '/web/report',
data: {action: JSON.stringify(action)},
- complete: $.unblockUI
- });
+ complete: $.unblockUI,
+ success: function(){
+ if (!self.dialog && on_closed) {
+ on_closed();
+ }
+ self.dialog_stop();
+ }
+ })
});
},
ir_actions_act_url: function (action) {
@@ -210,7 +216,7 @@ session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.View
sidebar_id : self.element_id + '_sidebar_' + view.view_type,
action : self.action,
action_views_ids : views_ids
- }, self.flags, view.options || {})
+ }, self.flags, self.flags[view.view_type] || {}, view.options || {})
});
views_ids[view.view_type] = view.view_id;
});
@@ -882,7 +888,7 @@ session.web.View = session.web.Widget.extend(/** @lends session.web.View# */{
}
};
var context = new session.web.CompoundContext(dataset.get_context(), action_data.context || {});
-
+
var handler = function (r) {
var action = r.result;
if (action && action.constructor == Object) {
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 92a3e5ffc43..fb7ccdf7d8e 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -714,7 +714,7 @@
</t>
<t t-name="Widget">
Unhandled widget
- <t t-raw="console.log('Unhandled widget', widget)"/>
+ <t t-js="dict">console.warn('Unhandled widget', dict.widget);</t>
</t>
<t t-name="WidgetFrame">
<table border="0" width="100%" cellpadding="0" cellspacing="0" class="oe_frame oe_forms">
@@ -907,13 +907,13 @@
</t>
<t t-name="web.datetimepicker">
<div class="oe_datepicker_root">
- <input type="text" size="1" style="width: 100%"/>
+ <input type="text" size="1" style="width: 100%"
+ t-att-name="widget.name"
+ t-attf-class="oe_datepicker_master field_#{widget.type_of_date}"
+ />
<img class="oe_input_icon oe_datepicker_trigger" src="/web/static/src/img/ui/field_calendar.png"
title="Select date" width="16" height="16" border="0"/>
- <div class="oe_datepicker ui-widget-content ui-corner-all" style="display: none; position: absolute; z-index: 1;">
- <div class="oe_datepicker_container"/>
- <button type="button" class="oe_datepicker_close ui-state-default ui-priority-primary ui-corner-all" style="float: right;">Done</button>
- </div>
+ <input type="text" size="1" class="oe_datepicker_container" disabled="disabled"/>
</div>
</t>
<t t-name="FieldSelection">
@@ -1081,7 +1081,7 @@
</table>
</t>
<t t-name="WidgetButton">
- <button type="button" style="width: 100%" class="button">
+ <button type="button" class="oe_button">
<img t-if="widget.node.attrs.icon" t-att-src="'/web/static/src/img/icons/' + widget.node.attrs.icon + '.png'" width="16" height="16"/>
<span t-if="widget.string"><t t-esc="widget.string"/></span>
</button>
@@ -1163,8 +1163,8 @@
t-att-title="attrs.help"
t-att-class="classes.join(' ')"
t-att-autofocus="attrs.default_focus === '1' ? 'autofocus' : undefined">
- <img t-if="attrs.icon" t-att-src="'/web/static/src/img/icons/' + attrs.icon + '.png'" width="16" height="16"/>
- <br t-if="attrs.icon and attrs.string"/>
+ <img t-att-src="'/web/static/src/img/icons/' + (attrs.icon || 'gtk-home') + '.png'" width="16" height="16"/>
+ <br t-if="attrs.string"/>
<t t-esc="attrs.string"/>
</button>
<span t-name="SearchView.filters" class="filter_label_group"