.openerp.ui-dialog .ui-dialog-buttonpane button {
margin-left: 8px;
}
+.openerp.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
+ float: left;
+}
.openerp.ui-dialog .ui-dialog-titlebar-close {
padding: 0;
}
.openerp .oe_avatar {
margin: 0 16px 0 0;
}
-.openerp .oe_avatar img {
+.openerp .oe_avatar > img {
height: 50px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
.openerp .oe_webclient .oe_star_on {
color: gold;
}
+.openerp .oe_tags .text-wrap {
+ width: 100% !important;
+}
+.openerp .oe_tags .text-wrap textarea {
+ width: 100% !important;
+}
+.openerp .oe_tags .oe_tag {
+ border-radius: 2px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ -ms-box-sizing: border-box;
+ box-sizing: border-box;
+ position: relative;
+ float: left;
+ border: 1px solid #9daccc;
+ background: #e2e6f0;
+ color: black;
+ padding: 0px 3px 0px 3px;
+ margin: 0 2px 2px 0;
+ height: 16px;
+ font: 11px "lucida grande", tahoma, verdana, arial, sans-serif;
+}
+.openerp .oe_tags .text-core .text-wrap .text-dropdown .text-list .text-suggestion em {
+ font-style: italic;
+ text-decoration: none;
+}
.openerp.oe_tooltip {
font-size: 12px;
}
display: inline-block;
float: right;
}
-.openerp .oe_form footer {
+.openerp .oe_form div.oe_chatter {
min-width: 650px;
max-width: 860px;
margin: 0 auto;
padding-top: 4px;
width: auto;
}
-.openerp .oe_form .oe_form_field_many2manytags .text-wrap {
- width: 100% !important;
-}
-.openerp .oe_form .oe_form_field_many2manytags .text-wrap textarea {
- width: 100% !important;
-}
-.openerp .oe_form .oe_form_field_many2manytags .oe_form_field_many2manytags_box {
- border-radius: 2px;
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- -ms-box-sizing: border-box;
- box-sizing: border-box;
- position: relative;
- float: left;
- border: 1px solid #9daccc;
- background: #e2e6f0;
- color: black;
- padding: 0px 3px 0px 3px;
- margin: 0 2px 2px 0;
- height: 16px;
- font: 11px "lucida grande", tahoma, verdana, arial, sans-serif;
-}
-.openerp .oe_form .oe_form_field_many2manytags .text-core .text-wrap .text-dropdown .text-list .text-suggestion em {
- font-style: italic;
- text-decoration: none;
-}
.openerp .oe_form .oe_datepicker_container {
display: none;
}
}
.openerp .oe_form .oe_form_field_image .oe_form_field_image_controls {
position: absolute;
+ white-space: nowrap;
top: 1px;
padding: 3px 0 0 0;
margin: 0 1px;
@include radius(0 0 2px 2px)
button
margin-left: 8px
+ .ui-dialog-buttonset
+ float: left
.ui-dialog-titlebar-close
padding: 0
.ui-icon-closethick
margin: 4px
.oe_avatar
margin: 0 16px 0 0
- img
+ > img
height: 50px
@include radius(3px)
@include box-shadow(0 1px 3px rgba(0, 0, 0, 0.3))
text-decoration: none
.oe_star_on
color: gold
-
- //.oe_edit_only
+ // }}}
+ // Tags (for many2many tags, among others) {{{
+ .oe_tags
+ .text-wrap
+ width: 100% !important
+ textarea
+ width: 100% !important
+ .oe_tag
+ border-radius: 2px
+ @include box-sizing(border)
+ position: relative
+ float: left
+ border: 1px solid #9DACCC
+ background: #E2E6F0
+ color: black
+ padding: 0px 3px 0px 3px
+ margin: 0 2px 2px 0
+ height: 16px
+ font: 11px "lucida grande", tahoma, verdana, arial, sans-serif
+ .text-core .text-wrap .text-dropdown .text-list .text-suggestion em
+ font-style: italic
+ text-decoration: none
// }}}
// Tooltips {{{
&.oe_tooltip
text-shadow: 0 1px 1px rgba(0,0,0,0.2)
@include radius(4px)
@include box-shadow(inset 0 1px 1px rgba(0, 0, 0, 0.2))
- .oe_menu_counter
+ .oe_menu_counter
float: right
background: #8a89ba
color: #eee
color: $colour4
text-shadow: 0 1px 1px white
@include box-shadow(0 1px 1px rgba(0, 0, 0, 0.2))
- .oe_menu_counter
+ .oe_menu_counter
background: #eee
color: #8a89ba
.oe_menu_toggler:before
margin: 0 0 0 4px
padding: 0
-
+
// }}}
// Views Common {{{
.oe_view_nocontent
display: none !important
.oe_form .oe_form_field_date
width: auto
- .oe_form_nosheet
+ .oe_form_nosheet
margin-left: 10px
margin-right: 10px
.oe_form_nosheet > header
margin-right: -10px
// }}}
// FormView.custom tags and classes {{{
- .oe_form
+ .oe_form
header
position: relative
border-bottom: 1px solid #cacaca
@include vertical-gradient(#fcfcfc, #dedede)
padding: 0 8px
- line-height: 30px
+ line-height: 30px
ul
display: inline-block
float: right
- footer
+ div.oe_chatter
min-width: 650px
max-width: $sheet-max-width
margin: 0 auto
vertical-align: top
margin-left: 8px
li
- border-right: none
+ border-right: none
padding: 0
margin: 0
- float: left
+ float: left
vertical-align: top
- height: 30px
+ height: 30px
padding: 0 0 0 12px
&:first-child
border-left: 1px solid #cacaca
.oe_form_sheetbg
background: url(/web/static/src/img/form_sheetbg.png)
padding: 8px 0
- border-bottom: 1px solid #ddd
+ border-bottom: 1px solid #ddd
.oe_form_sheet_width
min-width: 650px
max-width: $sheet-max-width
.oe_form_field_boolean
padding-top: 4px
width: auto
- .oe_form_field_many2manytags
- .text-wrap
- width: 100% !important
- textarea
- width: 100% !important
- .oe_form_field_many2manytags_box
- border-radius: 2px
- @include box-sizing(border)
- position: relative
- float: left
- border: 1px solid #9DACCC
- background: #E2E6F0
- color: black
- padding: 0px 3px 0px 3px
- margin: 0 2px 2px 0
- height: 16px
- font: 11px "lucida grande", tahoma, verdana, arial, sans-serif
- .text-core .text-wrap .text-dropdown .text-list .text-suggestion em
- font-style: italic
- text-decoration: none
.oe_datepicker_container
display: none
.oe_datepicker_root
vertical-align: top
.oe_form_field_image_controls
position: absolute
+ white-space: nowrap
top: 1px
padding: 3px 0 0 0
margin: 0 1px
this.dialog_options = {
modal: true,
destroy_on_close: true,
- width: 580,
+ width: 700,
min_width: 0,
max_width: '95%',
height: 'auto',
if (this.dialog_options.autoOpen) {
this.open();
} else {
- instance.web.dialog(this.$element, this.get_options());
+ test = instance.web.dialog(this.$element, this.get_options());
}
},
get_options: function(options) {
_.each(this.getChildren(), function(el) {
el.destroy();
});
- if (! this.isDestroyed()) {
- this.$element.dialog('destroy');
- }
+ if (! this.isDestroyed()) {
+ this.$element.dialog('destroy');
+ }
this._super();
}
});
dialog.$element.html(QWeb.render('CrashManager.error', {session: instance.connection, error: error}));
},
on_javascript_exception: function(exception) {
- this.on_traceback({
- type: _t("Client Error"),
- message: exception,
- data: {debug: ""}
- });
+ this.on_traceback({
+ type: _t("Client Error"),
+ message: exception,
+ data: {debug: ""}
+ });
},
});
{text: _t("Change password"), click: function(){ self.change_password(); }},
{text: _t("Cancel"), click: function(){ $(this).dialog('destroy'); }},
{text: _t("Save"), click: function(){
- var inner_viewmanager = action_manager.inner_viewmanager;
- inner_viewmanager.views[inner_viewmanager.active_view].controller.do_save()
+ var inner_widget = action_manager.inner_widget;
+ inner_widget.views[inner_widget.active_view].controller.do_save()
.then(function() {
self.dialog.destroy();
// needs to refresh interface in case language changed
if (options.needaction) {
action.context.search_default_needaction_pending = true;
}
+ self.action_manager.clear_breadcrumbs();
self.action_manager.do_action(action);
});
},
this.main_view_id = this.parent.fields_view.view_id;
this.action_manager = new instance.web.ActionManager(this);
$.when(this.action_manager.do_action(action)).then(function() {
- var viewmanager = self.action_manager.inner_viewmanager,
+ var viewmanager = self.action_manager.inner_widget,
controller = viewmanager.views[viewmanager.active_view].controller;
self.action_manager.appendTo(self.view_edit_dialog.$element);
self.action_manager.renderElement(self.view_edit_dialog);
} else {
$.when(self.do_save_view(view_values)).then(function() {
self.create_view_dialog.close();
- var controller = self.action_manager.inner_viewmanager.views[self.action_manager.inner_viewmanager.active_view].controller;
+ var controller = self.action_manager.inner_widget.views[self.action_manager.inner_widget.active_view].controller;
controller.reload_content();
});
}
do_delete_view: function() {
var self = this;
if (confirm(_t("Do you really want to remove this view?"))) {
- var controller = this.action_manager.inner_viewmanager.views[this.action_manager.inner_viewmanager.active_view].controller;
+ var controller = this.action_manager.inner_widget.views[this.action_manager.inner_widget.active_view].controller;
this.dataset.unlink([this.main_view_id]).then(function() {
controller.reload_content();
self.main_view_id = self.parent.fields_view.view_id;
action_manager.do_action(action);
}},
{text: _t("Close"), click: function(){
- self.action_manager.inner_viewmanager.views[self.action_manager.inner_viewmanager.active_view].controller.reload_content();
+ self.action_manager.inner_widget.views[self.action_manager.inner_widget.active_view].controller.reload_content();
self.edit_xml_dialog.close();
}}
]
};
var action_manager = new instance.web.ActionManager(self);
$.when(action_manager.do_action(action)).then(function() {
- var controller = action_manager.dialog_viewmanager.views['form'].controller;
+ var controller = action_manager.dialog_widget.views['form'].controller;
controller.on_button_cancel.add_last(function(){
action_manager.destroy()
});
/**
* Interface implemented by the form view or any other object
* able to provide the features necessary for the fields to work.
- *
+ *
* Properties:
* - display_invalid_fields : if true, all fields where is_valid() return true should
* be displayed as invalid.
on_record_loaded: function(record) {
var self = this, set_values = [];
if (!record) {
+ this.set({ 'title' : undefined });
this.do_warn("Form", "The record could not be found in the database.", true);
return $.Deferred().reject();
}
this.datarecord = record;
+ this.set({ 'title' : record.id ? record.name : "New record" });
if (this.qweb) {
this.kill_current_form();
this.on_form_changed();
}
if (!_.isEmpty(result.warning)) {
- instance.web.dialog($(QWeb.render("CrashManager.warning", result.warning)), {
+ instance.web.dialog($(QWeb.render("CrashManager.warning", result.warning)), {
title:result.warning.title,
modal: true,
buttons: [
/**
* Default rendering engine for the form view.
- *
+ *
* It is necessary to set the view using set_view() before usage.
*/
instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInterface.extend({
page_attrs.__page = $new_page;
page_attrs.__ic = ic;
pages.push(page_attrs);
-
+
$new_page.children().each(function() {
self.process($(this));
});
}
});
});
-
+
this.handle_common_properties($new_notebook, $notebook);
return $new_notebook;
},
if (! v_context) {
v_context = (this.field || {}).context || {};
}
-
+
if (v_context.__ref || true) { //TODO: remove true
var fields_values = this._build_eval_context(blacklist);
v_context = new instance.web.CompoundContext(v_context).set_eval_context(fields_values);
/**
* Interface to be implemented by fields.
- *
+ *
* Properties:
* - readonly: boolean. If set to true the field should appear in readonly mode.
* - force_readonly: boolean, When it is true, the field should always appear
* in read only mode, no matter what the value of the "readonly" property can be.
* Events:
* - changed_value: triggered to inform the view to check on_changes
- *
+ *
*/
instance.web.form.FieldInterface = {
/**
init: function(field_manager, node) {},
/**
* Called by the form view to indicate the value of the field.
- *
+ *
* set_value() may return an object that can be passed to $.when() that represents the moment when
* the field has finished all operations necessary before the user can effectively use the widget.
- *
+ *
* Multiple calls to set_value() can occur at any time and must be handled correctly by the implementation,
* regardless of any asynchronous operation currently running and the status of any promise that a
* previous call to set_value() could have returned.
- *
+ *
* set_value() must be able, at any moment, to handle the syntax returned by the "read" method of the
* osv class in the OpenERP server as well as the syntax used by the set_value() (see below). It must
* also be able to handle any other format commonly used in the _defaults key on the models in the addons
set_value: function(value_) {},
/**
* Get the current value of the widget.
- *
+ *
* Must always return a syntaxically correct value to be passed to the "write" method of the osv class in
* the OpenERP server, although it is not assumed to respect the constraints applied to the field.
* For example if the field is marqued as "required", a call to get_value() can return false.
- *
+ *
* get_value() can also be called *before* a call to set_value() and, in that case, is supposed to
* return a defaut value according to the type of field.
- *
+ *
* This method is always assumed to perform synchronously, it can not return a promise.
- *
+ *
* If there was no user interaction to modify the value of the field, it is always assumed that
* get_value() return the same semantic value than the one passed in the last call to set_value(),
* altough the syntax can be different. This can be the case for type of fields that have a different
/**
* Abstract class for classes implementing FieldInterface.
- *
+ *
* Properties:
* - effective_readonly: when it is true, the widget is displayed as readonly. Vary depending
* the values of the "readonly" property and the "force_readonly" property on the field manager.
* - value: useful property to hold the value of the field. By default, set_value() and get_value()
* set and retrieve the value property. Changing the value property also triggers automatically
* a 'changed_value' event that inform the view to trigger on_changes.
- *
+ *
*/
instance.web.form.AbstractField = instance.web.form.FormWidget.extend(instance.web.form.FieldInterface, {
/**
this.string = this.node.attrs.string || this.field.string || this.name;
this.set({'value': false});
this.set({required: this.modifiers['required'] === true});
-
+
// some events to make the property "effective_readonly" sync automatically with "readonly" and
// "force_readonly"
this.set({"readonly": this.modifiers['readonly'] === true});
this.on("change:readonly", this, test_effective_readonly);
this.on("change:force_readonly", this, test_effective_readonly);
_.bind(test_effective_readonly, this)();
-
+
this.on("change:value", this, function() {
if (! this._inhibit_on_change)
this.trigger('changed_value');
});
instance.web.form.FieldID = instance.web.form.FieldChar.extend({
-
+
});
instance.web.form.FieldEmail = instance.web.form.FieldChar.extend({
} else {
var self = this;
var option = _(this.values)
- .detect(function (record) { return record[0] === self.get('value'); });
+ .detect(function (record) { return record[0] === self.get('value'); });
this.$element.text(option ? option[1] : this.values[0][1]);
}
},
render_editable: function() {
var self = this;
this.$input = this.$element.find("input");
-
+
self.$input.tipsy({
title: function() {
return "No element was selected, you should create or select one from the dropdown list.";
trigger:'manual',
fade: true,
});
-
+
this.$drop_down = this.$element.find(".oe_m2o_drop_down_button");
this.$follow_button = $(".oe_m2o_cm_button", this.$element);
-
+
this.$follow_button.click(function() {
if (!self.get('value')) {
self.focus();
},
load_views: function() {
var self = this;
-
+
var modes = this.node.attrs.mode;
modes = !!modes ? modes.split(",") : ["tree"];
var views = [];
$("textarea", self.$element).css("padding-left", "3px");
self.tags.addTags(_.map(data, function(el) {return {name: el[1], id:el[0]};}));
} else {
- self.$element.html(QWeb.render("FieldMany2ManyTags.box", {elements: data}));
+ self.$element.html(QWeb.render("FieldMany2ManyTag", {elements: data}));
}
};
if (! self.get('values') || self.get('values').length > 0) {
this.dataset.on_unlink.add_last(function(ids) {
self.dataset_changed();
});
-
+
this.is_setted.then(function() {
self.load_view();
});
});
instance.web.form.Many2ManyQuickCreate = instance.web.Widget.extend({
template: 'Many2ManyKanban.quick_create',
-
+
/**
* close_btn: If true, the widget will display a "Close" button able to trigger
* a "close" event.
this.selection = [];
// get fold information from widget
var fold = ((this.node.attrs || {}).statusbar_fold || true);
- // build final domain: if fold option required, add the
+ // build final domain: if fold option required, add the
if (fold == true) {
var domain = new instance.web.CompoundDomain(['|'], ['&'], self.build_domain(), [['fold', '=', false]], [['id', '=', self.selected_value]]);
} else {
var shown = _.map(((this.node.attrs || {}).statusbar_visible || "").split(","),
function(x) { return _.str.trim(x); });
shown = _.select(shown, function(x) { return x.length > 0; });
-
+
if (shown.length == 0) {
this.to_show = this.selection;
} else {
init: function(parent) {
this._super(parent);
this.inner_action = null;
- this.inner_viewmanager = null;
+ this.inner_widget = null;
this.dialog = null;
- this.dialog_viewmanager = null;
- this.client_widget = null;
+ this.dialog_widget = null;
+ this.breadcrumbs = [];
+ },
+ start: function() {
+ this._super.apply(this, arguments);
+ this.$element.on('click', '.oe_breadcrumb_item', this.on_breadcrumb_clicked);
},
dialog_stop: function () {
if (this.dialog) {
- this.dialog_viewmanager.destroy();
- this.dialog_viewmanager = null;
+ this.dialog_widget.destroy();
+ this.dialog_widget = null;
this.dialog.destroy();
this.dialog = null;
}
},
- content_stop: function () {
- if (this.inner_viewmanager) {
- this.inner_viewmanager.destroy();
- this.inner_viewmanager = null;
+ /**
+ * Add a new item to the breadcrumb
+ *
+ * If the title of an item is an array, the multiple title mode is in use.
+ * (eg: a widget with multiple views might need to display a title for each view)
+ * In multiple title mode, the show() callback can check the index it receives
+ * in order to detect which of its titles has been clicked on by the user.
+ *
+ * @param {Object} item breadcrumb item
+ * @param {Object} item.widget widget containing the view(s) to be added to the breadcrumb added
+ * @param {Function} [item.show] triggered whenever the widget should be shown back
+ * @param {Function} [item.hide] triggered whenever the widget should be shown hidden
+ * @param {Function} [item.destroy] triggered whenever the widget should be destroyed
+ * @param {String|Array} [item.title] title(s) of the view(s) to be displayed in the breadcrumb
+ * @param {Function} [item.get_title] should return the title(s) of the view(s) to be displayed in the breadcrumb
+ */
+ push_breadcrumb: function(item) {
+ var last = this.breadcrumbs.slice(-1)[0];
+ if (last) {
+ last.hide();
+ }
+ var item = _.extend({
+ show: function(index) {
+ this.widget.$element.show();
+ },
+ hide: function() {
+ this.widget.$element.hide();
+ },
+ destroy: function() {
+ this.widget.destroy();
+ },
+ get_title: function() {
+ return this.title || this.widget.get('title');
+ }
+ }, item);
+ item.id = _.uniqueId('breadcrumb_');
+ this.breadcrumbs.push(item);
+ },
+ on_breadcrumb_clicked: function(ev) {
+ var $e = $(ev.target);
+ var id = $e.data('id');
+ var item;
+ for (var i = this.breadcrumbs.length - 1; i >= 0; i--) {
+ var it = this.breadcrumbs[i];
+ if (it.id == id) {
+ item = it;
+ break;
+ }
+ this.remove_breadcrumb(i);
+ }
+ var index = $e.parent().find('.oe_breadcrumb_item[data-id=' + $e.data('id') + ']').index($e);
+ item.show(index, $e);
+ this.inner_widget = item.widget;
+ },
+ clear_breadcrumbs: function() {
+ while (this.breadcrumbs.length) {
+ this.remove_breadcrumb(0);
}
- if (this.client_widget) {
- this.client_widget.destroy();
- this.client_widget = null;
+ },
+ remove_breadcrumb: function(index) {
+ var item = this.breadcrumbs.splice(index, 1)[0];
+ if (item) {
+ var dups = _.filter(this.breadcrumbs, function(it) {
+ return item.widget === it.widget;
+ });
+ if (!dups.length) {
+ item.destroy();
+ }
}
},
+ get_title: function() {
+ var titles = [];
+ for (var i = 0; i < this.breadcrumbs.length; i += 1) {
+ var item = this.breadcrumbs[i];
+ var tit = item.get_title();
+ if (!_.isArray(tit)) {
+ tit = [tit];
+ }
+ for (var j = 0; j < tit.length; j += 1) {
+ var label = _.escape(tit[j]);
+ if (i === this.breadcrumbs.length - 1 && j === tit.length - 1) {
+ titles.push(label);
+ } else {
+ titles.push(_.str.sprintf('<a href="#" class="oe_breadcrumb_item" data-id="%s">%s</a>', item.id, label));
+ }
+ }
+ }
+ return titles.join(' / ');
+ },
do_push_state: function(state) {
if (this.getParent() && this.getParent().do_push_state) {
if (this.inner_action) {
var self = this,
action_loaded;
if (state.action_id) {
- var run_action = (!this.inner_viewmanager) || this.inner_viewmanager.action.id !== state.action_id;
+ var run_action = (!this.inner_widget || !this.inner_widget.action) || this.inner_widget.action.id !== state.action_id;
if (run_action) {
this.null_action();
action_loaded = this.do_action(state.action_id);
}
$.when(action_loaded || null).then(function() {
- if (self.inner_viewmanager) {
- self.inner_viewmanager.do_load_state(state, warm);
+ if (self.inner_widget && self.inner_widget.do_load_state) {
+ self.inner_widget.do_load_state(state, warm);
}
});
},
},
null_action: function() {
this.dialog_stop();
- this.content_stop();
+ this.clear_breadcrumbs();
},
ir_actions_act_window: function (action, on_close) {
var self = this;
}
if (action.target === 'new') {
if (this.dialog === null) {
- this.dialog = new instance.web.Dialog(this, { width: '80%' });
+ // These buttons will be overwrited by <footer> if any
+ this.dialog = new instance.web.Dialog(this, {
+ buttons: { "Close": function() { $(this).dialog("close"); }}
+ });
if(on_close)
this.dialog.on_close.add(on_close);
} else {
- this.dialog_viewmanager.destroy();
+ this.dialog_widget.destroy();
}
this.dialog.dialog_title = action.name;
- this.dialog_viewmanager = new instance.web.ViewManagerAction(this.dialog, action);
- this.dialog_viewmanager.appendTo(this.dialog.$element);
- this.dialog_viewmanager.$element.addClass("oe_view_manager_" + (action.target || 'current'));
+ this.dialog_widget = new instance.web.ViewManagerAction(this, action);
+ this.dialog_widget.appendTo(this.dialog.$element);
this.dialog.open();
} else {
this.dialog_stop();
- this.content_stop();
if(action.menu_id) {
return this.getParent().do_action(action, function () {
instance.webclient.menu.open_menu(action.menu_id);
});
}
this.inner_action = action;
- this.inner_viewmanager = new instance.web.ViewManagerAction(this, action);
- this.inner_viewmanager.appendTo(this.$element);
- this.inner_viewmanager.$element.addClass("oe_view_manager_" + (action.target || 'current'));
+ var inner_widget = this.inner_widget = new instance.web.ViewManagerAction(this, action);
+ inner_widget.add_breadcrumb();
+ this.inner_widget.appendTo(this.$element);
}
},
ir_actions_act_window_close: function (action, on_closed) {
});
},
ir_actions_client: function (action) {
- this.content_stop();
this.dialog_stop();
var ClientWidget = instance.web.client_actions.get_object(action.tag);
- (this.client_widget = new ClientWidget(this, action.params)).appendTo(this.$element);
+ this.inner_widget = new ClientWidget(this, action.params);
+ this.push_breadcrumb({
+ widget: this.inner_widget,
+ title: action.name
+ });
+ this.inner_widget.appendTo(this.$element);
},
ir_actions_report_xml: function(action, on_closed) {
var self = this;
this.active_view = view_type;
if (!view.controller) {
- // Lazy loading of views
- var controllerclass = this.registry.get_object(view_type);
- var options = _.clone(view.options);
- if (view_type === "form" && this.action) {
- switch (this.action.target) {
- case 'new':
- case 'inline':
- options.initial_mode = 'edit';
- break;
- }
- }
- var controller = new controllerclass(this, this.dataset, view.view_id, options);
- if (view.embedded_view) {
- controller.set_embedded_view(view.embedded_view);
- }
- controller.do_switch_view.add_last(_.bind(this.switch_view, this));
- controller.do_prev_view.add_last(this.on_prev_view);
- var container = this.$element.find(".oe_view_manager_view_" + view_type);
- view_promise = controller.appendTo(container);
- this.views[view_type].controller = controller;
- this.views[view_type].deferred.resolve(view_type);
- $.when(view_promise).then(function() {
- self.on_controller_inited(view_type, controller);
- if (self.searchview
- && self.flags.auto_search
- && view.controller.searchable !== false) {
- self.searchview.ready.then(self.searchview.do_search);
- }
- });
+ view_promise = this.do_create_view(view_type);
} else if (this.searchview
&& self.flags.auto_search
&& view.controller.searchable !== false) {
container.hide();
controller.do_hide();
}
+ if (self.$element.parent('.ui-dialog-content') && self.$element.find('footer')) {
+ self.$element.parent('.ui-dialog-content').parent().find('div.ui-dialog-buttonset').hide()
+ self.$element.find('footer').appendTo(
+ self.$element.parent('.ui-dialog-content').parent().find('div.ui-dialog-buttonpane')
+ );
+ }
}
});
-
- self.$element.find('.oe_view_title_text:first').text(
- self.display_title());
});
return view_promise;
},
+ do_create_view: function(view_type) {
+ // Lazy loading of views
+ var self = this;
+ var view = this.views[view_type];
+ var controllerclass = this.registry.get_object(view_type);
+ var options = _.clone(view.options);
+ if (view_type === "form" && this.action) {
+ switch (this.action.target) {
+ case 'new':
+ case 'inline':
+ options.initial_mode = 'edit';
+ break;
+ }
+ }
+ var controller = new controllerclass(this, this.dataset, view.view_id, options);
+
+ controller.on("change:title", this, function() {
+ if (self.active_view === view_type) {
+ self.set_title(controller.get('title'));
+ }
+ });
+
+ if (view.embedded_view) {
+ controller.set_embedded_view(view.embedded_view);
+ }
+ controller.do_switch_view.add_last(_.bind(this.switch_view, this));
+
+ controller.do_prev_view.add_last(this.on_prev_view);
+ var container = this.$element.find(".oe_view_manager_view_" + view_type);
+ var view_promise = controller.appendTo(container);
+ this.views[view_type].controller = controller;
+ this.views[view_type].deferred.resolve(view_type);
+ return $.when(view_promise).then(function() {
+ self.on_controller_inited(view_type, controller);
+ if (self.searchview
+ && self.flags.auto_search
+ && view.controller.searchable !== false) {
+ self.searchview.ready.then(self.searchview.do_search);
+ }
+ });
+ },
+ set_title: function(title) {
+ this.$element.find('.oe_view_title_text:first').text(title);
+ },
+ add_breadcrumb: function() {
+ var self = this;
+ var views = [this.active_view || this.views_src[0].view_type];
+ this.on_mode_switch.add(function(mode) {
+ var last = views.slice(-1)[0];
+ if (mode !== last) {
+ if (mode !== 'form') {
+ views.length = 0;
+ }
+ views.push(mode);
+ }
+ });
+ this.getParent().push_breadcrumb({
+ widget: this,
+ show: function(index, $e) {
+ var view_to_select = views[index];
+ self.$element.show();
+ if (self.active_view !== view_to_select) {
+ self.on_mode_switch(view_to_select);
+ }
+ },
+ get_title: function() {
+ return _.map(views, function(v) {
+ return self.views[v].controller.get('title');
+ });
+ }
+ });
+ },
/**
* Method used internally when a view asks to switch view. This method is meant
* to be extended by child classes to change the default behavior, which simply
*/
on_action_executed: function () {
},
- display_title: function () {
- var view = this.views[this.active_view];
- if (view) {
- // ick
- return view.controller.fields_view.arch.attrs.string;
- }
- return '';
- }
});
instance.web.ViewManagerAction = instance.web.ViewManager.extend({
if (this.session.hidden_menutips) {
return;
}
- this.session.hidden_menutips = {}
+ this.session.hidden_menutips = {};
},
/**
* Initializes the ViewManagerAction: sets up the searchview (if the
var manager_ready = $.when(searchview_loaded, main_view_loaded);
this.$element.find('.oe_debug_view').change(this.on_debug_changed);
+ this.$element.addClass("oe_view_manager_" + (this.action.target || 'current'));
if (this.action.help && !this.flags.low_profile) {
var Users = new instance.web.DataSet(self, 'res.users'),
view: controller,
view_manager: self
}));
- if (!self.action.name && fvg) {
- self.$element.find('.oe_view_title_text').text(fvg.arch.attrs.string || fvg.name);
- }
-
+ self.set_title();
});
},
+ do_create_view: function(view_type) {
+ var r = this._super.apply(this, arguments);
+ var view = this.views[view_type].controller;
+ view.set({ 'title': this.action.name });
+ return r;
+ },
+ set_title: function(title) {
+ this.$element.find('.oe_breadcrumb_title:first').html(this.getParent().get_title());
+ },
do_push_state: function(state) {
if (this.getParent() && this.getParent().do_push_state) {
state["view_type"] = this.active_view;
self.views[self.active_view].controller.do_load_state(state, warm);
});
},
- display_title: function () {
- return this.action.name;
- }
});
instance.web.Sidebar = instance.web.Widget.extend({
<tr class="oe_header_row oe_header_row_top">
<td colspan="2">
<h2 class="oe_view_title" t-if="widget.flags.display_title !== false">
- <span class="oe_view_title_text"><t t-esc="widget.display_title()"/></span>
+ <span class="oe_view_title_text oe_breadcrumb_title"/>
</h2>
</td>
<td colspan="2">
</t>
</span>
</t>
+<!-- Collection of m2m tags -->
<t t-name="FieldMany2ManyTags">
- <div class="oe_form_field oe_form_field_many2manytags" t-att-style="widget.node.attrs.style">
+ <div class="oe_form_field oe_tags" t-att-style="widget.node.attrs.style">
<t t-if="! widget.get('effective_readonly')">
<textarea rows="1" style="width: 100%"
t-att-placeholder="widget.node.attrs.placeholder"></textarea>
</t>
</div>
</t>
-<t t-name="FieldMany2ManyTags.box">
+<!-- Individual m2m tag element -->
+<t t-name="FieldMany2ManyTag">
<t t-set="i" t-value="0"/>
<t t-foreach="elements" t-as="el">
- <span class="oe_form_field_many2manytags_box" t-att-data-index="i">
+ <span class="oe_tag" t-att-data-index="i">
<t t-esc="el[1]"/>
</span>
<t t-set="i" t-value="i + 1"/>
}
});
}
- if (am.inner_viewmanager) {
- am.inner_viewmanager.on_mode_switch.add(function(mode) {
+ if (am.inner_widget) {
+ am.inner_widget.on_mode_switch.add(function(mode) {
var new_views = [];
_.each(action_orig.views, function(view) {
new_views[view[1] === mode ? 'unshift' : 'push'](view);
new_views.unshift([false, mode]);
}
action_orig.views = new_views;
- action_orig.res_id = am.inner_viewmanager.dataset.ids[am.inner_viewmanager.dataset.index];
+ action_orig.res_id = am.inner_widget.dataset.ids[am.inner_widget.dataset.index];
self.do_action(action_orig);
});
}
buttons : [
{text: _t("Cancel"), click: function() { $(this).dialog('destroy'); }},
{text: _t("Save"), click: function() {
- var form_view = action_manager.inner_viewmanager.views.form.controller;
+ var form_view = action_manager.inner_widget.views.form.controller;
form_view.do_save(function() {
self.initialize_process_view();