summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorqsm-odoo <qsm@odoo.com>2015-06-16 11:38:20 +0200
committerqsm-odoo <qsm@odoo.com>2015-06-17 09:49:46 +0200
commit46bf047e86c2a5dd93aae3b6ac77873aa6180a1e (patch)
tree9fa2fd229f0c577c7342b91f39b957bea09277e6
parentd6d3d0983fa936be90f05a6ebacb83d632414c75 (diff)
[IMP] web, web_*, mail, board : New modals and dialogs
-rw-r--r--addons/board/static/src/js/dashboard.js11
-rw-r--r--addons/mail/static/src/js/mail.js17
-rw-r--r--addons/mail/static/src/js/many2many_tags_email.js15
-rw-r--r--addons/web/static/src/css/base.css58
-rw-r--r--addons/web/static/src/css/base.sass50
-rw-r--r--addons/web/static/src/js/action_manager.js32
-rw-r--r--addons/web/static/src/js/framework/crash_manager.js30
-rw-r--r--addons/web/static/src/js/framework/data.js4
-rw-r--r--addons/web/static/src/js/framework/dialog.js273
-rw-r--r--addons/web/static/src/js/view_manager.js2
-rw-r--r--addons/web/static/src/js/views/form_common.js359
-rw-r--r--addons/web/static/src/js/views/form_relational_widgets.js142
-rw-r--r--addons/web/static/src/js/views/form_view.js16
-rw-r--r--addons/web/static/src/js/views/form_widgets.js36
-rw-r--r--addons/web/static/src/js/widgets/change_password.js10
-rw-r--r--addons/web/static/src/js/widgets/data_export.js2
-rw-r--r--addons/web/static/src/js/widgets/database_manager.js6
-rw-r--r--addons/web/static/src/js/widgets/debug_manager.js9
-rw-r--r--addons/web/static/src/js/widgets/sidebar.js2
-rw-r--r--addons/web/static/src/js/widgets/user_menu.js5
-rw-r--r--addons/web/static/src/less/modal.less51
-rw-r--r--addons/web/static/src/xml/base.xml81
-rw-r--r--addons/web/static/test/menu.js4
-rw-r--r--addons/web/views/webclient_templates.xml1
-rw-r--r--addons/web_calendar/static/src/js/web_calendar.js60
-rw-r--r--addons/web_calendar/static/src/js/widgets.js65
-rw-r--r--addons/web_calendar/static/src/less/web_calendar.less147
-rw-r--r--addons/web_diagram/static/src/js/diagram.js97
-rw-r--r--addons/web_gantt/static/src/js/gantt.js28
-rw-r--r--addons/web_view_editor/static/src/js/view_editor.js4
30 files changed, 777 insertions, 840 deletions
diff --git a/addons/board/static/src/js/dashboard.js b/addons/board/static/src/js/dashboard.js
index 72c4eee1eca..568a6e2babd 100644
--- a/addons/board/static/src/js/dashboard.js
+++ b/addons/board/static/src/js/dashboard.js
@@ -90,13 +90,14 @@ var DashBoard = form_common.FormWidget.extend({
var qdict = {
current_layout : this.$el.find('.oe_dashboard').attr('data-layout')
};
- var $dialog = new Dialog(this, {
- title: _t("Edit Layout"),
- }, QWeb.render('DashBoard.layouts', qdict)).open();
- $dialog.$el.find('li').click(function() {
+ var dialog = new Dialog(this, {
+ title: _t("Edit Layout"),
+ $content: QWeb.render('DashBoard.layouts', qdict)
+ }).open();
+ dialog.$el.find('li').click(function() {
var layout = $(this).attr('data-layout');
self.do_change_layout(layout);
- $dialog.$dialog_box.modal('hide');
+ dialog.close();
});
},
do_change_layout: function(new_layout) {
diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js
index e29feecf414..21ac9d5e171 100644
--- a/addons/mail/static/src/js/mail.js
+++ b/addons/mail/static/src/js/mail.js
@@ -1266,18 +1266,17 @@ var ComposeMessage = Attachment.extend ({
var partner_id = partner_info.partner_id;
var parsed_email = mail_utils.parse_email(partner_name);
- var pop = new form_common.FormOpenPopup(this);
- pop.show_element(
- 'res.partner',
- partner_id,
- { 'force_email': true,
+ var pop = new form_common.FormViewDialog(this, {
+ res_model: 'res.partner',
+ res_id: partner_id,
+ context: {
+ 'force_email': true,
'ref': "compound_context",
'default_name': parsed_email[0],
'default_email': parsed_email[1],
- }, {
- title: _t("Please complete partner's informations"),
- }
- );
+ },
+ title: _t("Please complete partner's informations"),
+ }).open();
pop.on('closed', self, function () {
deferred.resolve();
});
diff --git a/addons/mail/static/src/js/many2many_tags_email.js b/addons/mail/static/src/js/many2many_tags_email.js
index 604c1662579..2250935e1da 100644
--- a/addons/mail/static/src/js/many2many_tags_email.js
+++ b/addons/mail/static/src/js/many2many_tags_email.js
@@ -61,15 +61,12 @@ var FieldMany2ManyTagsEmail = form_relational.FieldMany2ManyTags.extend({
// unvalid partner
_.each(record_ids, function (id) {
- var pop = new form_common.FormOpenPopup(self);
- pop.show_element(
- 'res.partner',
- id,
- self.build_context(),
- {
- title: _t("Please complete partner's informations and Email"),
- }
- );
+ var pop = new form_common.FormViewDialog(self, {
+ res_model: 'res.partner',
+ res_id: id,
+ context: self.build_context(),
+ title: _t("Please complete partner's informations and Email"),
+ }).open();
pop.on('write_completed', self, function () {
this.values.push(id);
this.values_checking = _.without(this.values_checking, id);
diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css
index 81a1460b0bd..440c83cd14b 100644
--- a/addons/web/static/src/css/base.css
+++ b/addons/web/static/src/css/base.css
@@ -1105,21 +1105,6 @@
.openerp .oe-control-panel .oe-pager-buttons {
min-height: 30px;
}
-.openerp .o-modal-header > div {
- margin-left: 45%;
-}
-.openerp .oe_popup_form {
- display: none;
-}
-.openerp .oe_popup_form .oe_formview .oe_form_pager {
- display: none !important;
-}
-.openerp .oe_popup_form table label {
- font-weight: normal;
-}
-.openerp .oe_popup_list_pager {
- float: right;
-}
.openerp .oe_searchview {
cursor: text;
position: relative;
@@ -3189,49 +3174,6 @@ body.oe_single_form .oe_single_form_container {
background-image: url("/web/static/lib/jquery.ui/images/ui-icons_ffffff_256x240.png");
}
-.modal .modal-header button.close {
- border: none;
- background: none;
- padding: 1px;
- height: 18px;
- font-size: 20px;
-}
-.modal .modal-body {
- overflow: auto;
- padding: 0;
-}
-.modal .modal-body .oe_application {
- width: 100%;
-}
-.modal .modal-body .oe_popup_list {
- display: none;
- min-height: 150px;
-}
-.modal .modal-body .oe-view-manager {
- min-height: 150px;
-}
-.modal .modal-body .oe_form_sheetbg .oe_form_sheet {
- padding: 0;
-}
-.modal .modal-footer {
- text-align: left;
-}
-.modal .oe_button {
- margin: 0 4px 0 0;
-}
-.modal .oe_act_window.modal-body {
- padding: 0;
-}
-.modal .oe-view-manager-content {
- position: static !important;
-}
-
-@media (min-width: 768px) {
- .modal .modal-body {
- max-height: -webkit-calc(100vh - 170px);
- max-height: calc(100vh - 170px);
- }
-}
.ui-datepicker {
z-index: 1500 !important;
}
diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass
index 1f7a0c1560f..4ecea186b4b 100644
--- a/addons/web/static/src/css/base.sass
+++ b/addons/web/static/src/css/base.sass
@@ -954,21 +954,6 @@ $sheet-padding: 16px
min-height: 30px
// }}}
- // FormPopup {{{
- .o-modal-header
- > div
- margin-left: 45%
- .oe_popup_form
- display: none
- .oe_formview .oe_form_pager
- display: none !important
- // Customize label weight for popup wizard appear from another wizard according bootstrap3
- table label
- font-weight: normal
- // End of customize
- .oe_popup_list_pager
- float: right
- // }}}
// SearchView {{{
.oe_searchview
cursor: text
@@ -2628,41 +2613,6 @@ body.oe_single_form
background-image: url("/web/static/lib/jquery.ui/images/ui-icons_ffffff_256x240.png")
// End jquery-ui override}}}
-// Customized modal according bootstrap3
-.modal
- .modal-header button.close
- border: none
- background: none
- padding: 1px
- height: 18px
- font-size: 20px
- .modal-body
- overflow: auto
- padding: 0
- .oe_application
- width: 100%
- .oe_popup_list
- display: none
- min-height: 150px
- .oe-view-manager
- min-height: 150px
- .oe_form_sheetbg
- .oe_form_sheet
- padding: 0
- .modal-footer
- text-align: left
- .oe_button
- margin: 0 4px 0 0
- .oe_act_window.modal-body
- padding: 0
- .oe-view-manager-content
- position: static !important
-
-@media (min-width: 768px)
- .modal .modal-body
- max-height: -webkit-calc(100vh - 170px)
- max-height: calc(100vh - 170px)
-
.ui-datepicker
z-index: 1500 !important
diff --git a/addons/web/static/src/js/action_manager.js b/addons/web/static/src/js/action_manager.js
index 6700932b4bc..68a81a9dc68 100644
--- a/addons/web/static/src/js/action_manager.js
+++ b/addons/web/static/src/js/action_manager.js
@@ -529,14 +529,13 @@ var ActionManager = Widget.extend({
* @return {*}
*/
ir_actions_common: function(executor, options) {
- var widget;
if (executor.action.target === 'new') {
var pre_dialog = (this.dialog && !this.dialog.isDestroyed()) ? this.dialog : null;
if (pre_dialog){
// prevent previous dialog to consider itself closed,
// right now, as we're opening a new one (prevents
// reload of original form view)
- pre_dialog.off('closing', null, pre_dialog.on_close);
+ pre_dialog.off('closed', null, pre_dialog.on_close);
}
if (this.dialog_widget && !this.dialog_widget.isDestroyed()) {
this.dialog_widget.destroy();
@@ -547,6 +546,7 @@ var ActionManager = Widget.extend({
this.dialog = new Dialog(this, {
title: executor.action.name,
dialogClass: executor.klass,
+ buttons: []
});
// chain on_close triggers with previous dialog, if any
@@ -560,34 +560,32 @@ var ActionManager = Widget.extend({
pre_dialog.on_close();
}
};
- this.dialog.on("closing", null, this.dialog.on_close);
- widget = executor.widget();
- if (widget instanceof ViewManager) {
- _.extend(widget.flags, {
- $buttons: this.dialog.$buttons,
+ this.dialog.on("closed", null, this.dialog.on_close);
+ this.dialog_widget = executor.widget();
+ if (this.dialog_widget instanceof ViewManager) {
+ _.extend(this.dialog_widget.flags, {
+ $buttons: this.dialog.$footer,
footer_to_buttons: true,
});
- if (widget.action.view_mode === 'form') {
- widget.flags.headless = true;
+ if (this.dialog_widget.action.view_mode === 'form') {
+ this.dialog_widget.flags.headless = true;
}
}
- if (widget.need_control_panel) {
+ if (this.dialog_widget.need_control_panel) {
// Set a fake bus to Dialogs needing a ControlPanel as they should not
// communicate with the main ControlPanel
- widget.set_cp_bus(new core.Bus());
+ this.dialog_widget.set_cp_bus(new core.Bus());
}
- this.dialog_widget = widget;
this.dialog_widget.setParent(this.dialog);
- var initialized = this.dialog_widget.appendTo(this.dialog.$el);
this.dialog.open();
- return $.when(initialized);
+
+ return this.dialog_widget.appendTo(this.dialog.$el);
}
if (this.inner_widget && this.webclient.has_uncommitted_changes()) {
return $.Deferred().reject();
}
- widget = executor.widget();
this.dialog_stop(executor.action);
- return this.push_action(widget, executor.action, options);
+ return this.push_action(executor.widget(), executor.action, options);
},
ir_actions_act_window: function (action, options) {
var self = this;
@@ -596,7 +594,7 @@ var ActionManager = Widget.extend({
return new ViewManager(self, null, null, null, action);
},
action: action,
- klass: 'oe_act_window',
+ klass: 'o_act_window',
}, options);
},
ir_actions_client: function (action, options) {
diff --git a/addons/web/static/src/js/framework/crash_manager.js b/addons/web/static/src/js/framework/crash_manager.js
index 303cd66a4a3..4ab40f456bc 100644
--- a/addons/web/static/src/js/framework/crash_manager.js
+++ b/addons/web/static/src/js/framework/crash_manager.js
@@ -118,23 +118,17 @@ var CrashManager = core.Class.extend({
size: 'medium',
title: "Odoo " + (_.str.capitalize(error.type) || _t("Warning")),
subtitle: error.data.title,
- buttons: [
- {text: _t("Ok"), click: function() { this.parents('.modal').modal('hide'); }}
- ],
- }, $('<div>' + QWeb.render('CrashManager.warning', {error: error}) + '</div>')).open();
+ $content: $('<div>').html(QWeb.render('CrashManager.warning', {error: error}))
+ }).open();
},
show_error: function(error) {
if (!this.active) {
return;
}
- var buttons = {};
- buttons[_t("Ok")] = function() {
- this.parents('.modal').modal('hide');
- };
new Dialog(this, {
title: "Odoo " + _.str.capitalize(error.type),
- buttons: buttons
- }, QWeb.render('CrashManager.error', {session: session, error: error})).open();
+ $content: QWeb.render('CrashManager.error', {session: session, error: error})
+ }).open();
},
show_message: function(exception) {
this.show_error({
@@ -181,16 +175,14 @@ var RedirectWarningHandler = Dialog.extend(ExceptionHandler, {
size: 'medium',
title: "Odoo " + (_.str.capitalize(error.type) || "Warning"),
buttons: [
- {text: error.data.arguments[2],
- oe_link_class : 'oe_highlight',
- post_text : _t("or"),
- click: function() {
- window.location.href='#action='+error.data.arguments[1];
- self.destroy();
- }},
- {text: _t("Cancel"), oe_link_class: 'oe_link', click: function() { self.$el.parents('.modal').modal('hide'); self.destroy();}}
+ {text: error.data.arguments[2], classes : "btn-primary", click: function() {
+ window.location.href = '#action='+error.data.arguments[1];
+ self.destroy();
+ }},
+ {text: _t("Cancel"), click: function() { self.destroy(); }, close: true}
],
- }, QWeb.render('CrashManager.warning', {error: error})).open();
+ $content: QWeb.render('CrashManager.warning', {error: error})
+ }).open();
}
});
diff --git a/addons/web/static/src/js/framework/data.js b/addons/web/static/src/js/framework/data.js
index efbce3a5056..597af06118d 100644
--- a/addons/web/static/src/js/framework/data.js
+++ b/addons/web/static/src/js/framework/data.js
@@ -542,8 +542,8 @@ var DataSet = Class.extend(mixins.PropertiesMixin, {
/**
* @param name
*/
- name_create: function(name) {
- return this._model.call('name_create', [name], {context: this.get_context()});
+ name_create: function(name, context) {
+ return this._model.call('name_create', [name], {context: this.get_context(context)});
},
exec_workflow: function (id, signal) {
return this._model.exec_workflow(id, signal);
diff --git a/addons/web/static/src/js/framework/dialog.js b/addons/web/static/src/js/framework/dialog.js
index 81d8860d4c3..45a00bcaa60 100644
--- a/addons/web/static/src/js/framework/dialog.js
+++ b/addons/web/static/src/js/framework/dialog.js
@@ -5,190 +5,167 @@ var core = require('web.core');
var Widget = require('web.Widget');
var QWeb = core.qweb;
-var opened_modals = [];
+var _t = core._t;
/**
A useful class to handle dialogs.
Attributes:
- - $buttons: A jQuery element targeting a dom part where buttons can be added. It always exists
+ - $footer: A jQuery element targeting a dom part where buttons can be added. It always exists
during the lifecycle of the dialog.
*/
var Dialog = Widget.extend({
- dialog_title: "",
/**
Constructor.
@param {Widget} parent
- @param {dictionary} options A dictionary that will be forwarded to jQueryUI Dialog. Additionaly, that
- dictionary can contain the following keys:
+ @param {dictionary} options
+ - title
+ - subtitle
- size: one of the following: 'large', 'medium', 'small'
- - dialogClass: class to add to the body of dialog
- - buttons: Deprecated. The buttons key is not propagated to jQueryUI Dialog. It must be a dictionary (key = button
- label, value = click handler) or a list of dictionaries (each element in the dictionary is send to the
- corresponding method of a jQuery element targeting the <button> tag). It is deprecated because all dialogs
- in OpenERP must be personalized in some way (button in red, link instead of button, ...) and this
- feature does not allow that kind of personalization.
- - destroy_on_close: Default true. If true and the dialog is closed, it is automatically destroyed.
- @param {jQuery object} content Some content to replace this.$el .
+ - dialogClass: class to add to the modal-body
+ - buttons: It must be a list of dictionaries -> text, classes, close, click, disabled
+ -> If no buttons, a "ok" primary button is added with close = true
+ -> By default: close = false and classes = 'btn-primary' if only one button and 'btn-default' if many buttons
+ - $content: Some content to replace this.$el .
*/
- init: function (parent, options, content) {
+ init: function (parent, options) {
this._super(parent);
- this.content_to_set = content;
- this.dialog_options = {
- destroy_on_close: true,
- size: 'large', //'medium', 'small'
- buttons: null,
- };
- if (options) {
- _.extend(this.dialog_options, options);
+
+ options = _.defaults(options || {}, {
+ title: _t('Odoo'), subtitle: '',
+ size: 'large',
+ dialogClass: '',
+ $content: false,
+ buttons: [{text: _t("Ok"), close: true}]
+ });
+
+ this.$content = options.$content;
+
+ this.title = options.title;
+ this.subtitle = options.subtitle;
+ this.$modal = $(QWeb.render('Dialog', {title: this.title, subtitle: this.subtitle}));
+
+ switch(options.size) {
+ case 'large':
+ this.$modal.find('.modal-dialog').addClass('modal-lg');
+ break;
+ case 'small':
+ this.$modal.find('.modal-dialog').addClass('modal-sm');
+ break;
}
- this.on("closing", this, this._closing);
- this.$buttons = $('<div class="modal-footer"><span class="oe_dialog_custom_buttons"/></div>');
+
+ this.dialogClass = options.dialogClass;
+ this.$footer = this.$modal.find(".modal-footer");
+
+ this.set_buttons(options.buttons);
+
+ this.$modal.on('hidden.bs.modal', _.bind(this.destroy, this));
},
+
renderElement: function() {
- if (this.content_to_set) {
- this.setElement(this.content_to_set);
- } else if (this.template) {
- this._super();
+ this._super();
+ if(this.$content) {
+ this.setElement(this.$content);
}
},
- /**
- Opens the popup. Inits the dialog if it is not already inited.
- @return this
- */
- open: function() {
- if (!this.dialog_inited) {
- this.init_dialog();
- }
- this.$buttons.insertAfter(this.$dialog_box.find(".modal-body"));
- $('.tooltip').remove(); //remove open tooltip if any to prevent them staying when modal is opened
- //add to list of currently opened modal
- opened_modals.push(this.$dialog_box);
- return this;
- },
- _add_buttons: function(buttons) {
+ set_buttons: function(buttons) {
var self = this;
- var $customButons = this.$buttons.find('.oe_dialog_custom_buttons').empty();
- _.each(buttons, function(fn, text) {
- // buttons can be object or array
- var pre_text = fn.pre_text || "";
- var post_text = fn.post_text || "";
- var oe_link_class = fn.oe_link_class;
- if (!_.isFunction(fn)) {
- text = fn.text;
- fn = fn.click;
- }
- var $but = $(QWeb.render('WidgetButton', { widget : { pre_text: pre_text, post_text: post_text, string: text, node: { attrs: {'class': oe_link_class} }}}));
- $customButons.append($but);
- $but.filter('button').on('click', function(ev) {
- fn.call(self.$el, ev);
+
+ self.$footer.empty();
+
+ _.each(buttons, function(b) {
+ var text = b.text || "";
+ var classes = b.classes || ((buttons.length === 1)? "btn-primary" : "btn-default");
+
+ var $b = $(QWeb.render('WidgetButton', { widget : { string: text, node: { attrs: {'class': classes} }}}));
+ $b.prop('disabled', b.disabled);
+ $b.on('click', function(e) {
+ if(b.click) {
+ b.click.call(self, e);
+ }
+ if(b.close) {
+ self.close();
+ }
});
+ self.$footer.append($b);
});
},
- /**
- Initializes the popup.
-
- @return The result returned by start().
- */
- init_dialog: function() {
- var self = this;
- var options = _.extend({}, this.dialog_options);
- options.title = options.title || this.dialog_title;
- if (options.buttons) {
- this._add_buttons(options.buttons);
- delete(options.buttons);
- }
- this.renderElement();
- this.$dialog_box = $(QWeb.render('Dialog', options)).appendTo("body");
- this.$el.modal({
- 'backdrop': false,
- 'keyboard': true,
- });
- if (options.size !== 'large'){
- var dialog_class_size = this.$dialog_box.find('.modal-lg').removeClass('modal-lg');
- if (options.size === 'small'){
- dialog_class_size.addClass('modal-sm');
- }
+
+ set_title: function(title, subtitle) {
+ this.title = title || "";
+ if(subtitle !== undefined) {
+ this.subtitle = subtitle || "";
}
- this.$el.appendTo(this.$dialog_box.find(".modal-body"));
- var $dialog_content = this.$dialog_box.find('.modal-content');
- if (options.dialogClass){
- $dialog_content.find(".modal-body").addClass(options.dialogClass);
- }
- $dialog_content.openerpClass();
+ var $title = this.$modal.find('.modal-title').first();
+ var $subtitle = $title.find('.o_subtitle').detach();
+ $title.html(this.title);
+ $subtitle.html(this.subtitle).appendTo($title);
- this.$dialog_box.on('hidden.bs.modal', this, function() {
- self.close();
- });
- this.$dialog_box.modal('show');
+ return this;
+ },
+
+ open: function() {
+ $('.tooltip').remove(); // remove open tooltip if any to prevent them staying when modal is opened
- this.dialog_inited = true;
- var res = this.start();
- return res;
+ var self = this;
+ this.replace(this.$modal.find(".modal-body")).then(function() {
+ self.$el.addClass('modal-body ' + self.dialogClass);
+ self.$modal.modal('show');
+ });
+
+ return self;
},
- /**
- Closes (hide) the popup, if destroy_on_close was passed to the constructor, it will be destroyed instead.
- */
- close: function(reason) {
- if (this.dialog_inited && !this.__tmp_dialog_hiding) {
- $('.tooltip').remove(); //remove open tooltip if any to prevent them staying when modal has disappeared
- if (this.$el.is(":data(bs.modal)")) { // may have been destroyed by closing signal
- this.__tmp_dialog_hiding = true;
- this.$dialog_box.modal('hide');
- this.__tmp_dialog_hiding = undefined;
- }
- this.trigger("closing", reason);
- }
+
+ close: function() {
+ this.$modal.modal('hide');
},
- _closing: function() {
- if (this.__tmp_dialog_destroying)
+
+ destroy: function() {
+ if(this.isDestroyed())
return;
- if (this.dialog_options.destroy_on_close) {
- this.__tmp_dialog_closing = true;
- this.destroy();
- this.__tmp_dialog_closing = undefined;
- }
- },
- /**
- Destroys the popup, also closes it.
- */
- destroy: function (reason) {
- this.$buttons.remove();
- _.each(this.getChildren(), function(el) {
- el.destroy();
- });
- if (! this.__tmp_dialog_closing) {
- this.__tmp_dialog_destroying = true;
- this.close(reason);
- this.__tmp_dialog_destroying = undefined;
- }
- if (this.dialog_inited && !this.isDestroyed() && this.$el.is(":data(bs.modal)")) {
- //we need this to put the instruction to remove modal from DOM at the end
- //of the queue, otherwise it might already have been removed before the modal-backdrop
- //is removed when pressing escape key
- var $element = this.$dialog_box;
- setTimeout(function () {
- //remove modal from list of opened modal since we just destroy it
- var modal_list_index = $.inArray($element, opened_modals);
- if (modal_list_index > -1){
- opened_modals.splice(modal_list_index,1)[0].remove();
- }
- if (opened_modals.length > 0){
- //we still have other opened modal so we should focus it
- opened_modals[opened_modals.length-1].focus();
- //keep class modal-open (deleted by bootstrap hide fnct) on body
- //to allow scrolling inside the modal
- $('body').addClass('modal-open');
- }
- },0);
- }
+
+ this.trigger("closed");
+
this._super();
+
+ $('.tooltip').remove(); //remove open tooltip if any to prevent them staying when modal has disappeared
+ this.$modal.modal('hide');
+ this.$modal.remove();
+
+ setTimeout(function () { // Keep class modal-open (deleted by bootstrap hide fnct) on body to allow scrolling inside the modal
+ var modals = $('body > .modal');
+ if(modals.length) {
+ modals.last().focus();
+ $('body').addClass('modal-open');
+ }
+ }, 0);
}
});
+
+// static method to open simple confirm dialog
+Dialog.confirm = function (owner, message, confirm_callback) {
+ var buttons = [
+ {
+ text: _t("Ok"),
+ classes: 'btn-primary',
+ close: true,
+ click: confirm_callback
+ },
+ {text: _t("Cancel"), close: true}
+ ];
+ return new Dialog(owner, {
+ size: 'medium',
+ buttons: buttons,
+ $content: $('<div>', {
+ text: message,
+ }),
+ }).open();
+}
+
return Dialog;
});
diff --git a/addons/web/static/src/js/view_manager.js b/addons/web/static/src/js/view_manager.js
index d5ca65b5d61..19c645d314d 100644
--- a/addons/web/static/src/js/view_manager.js
+++ b/addons/web/static/src/js/view_manager.js
@@ -180,7 +180,7 @@ var ViewManager = Widget.extend(ControlPanelMixin, {
if (view.type === "form" && ((this.action && (this.action.target === 'new' || this.action.target === 'inline')) ||
(view_options && view_options.mode === 'edit'))) {
- options.initial_mode = 'edit';
+ options.initial_mode = options.initial_mode || 'edit';
}
var controller = new View(this, this.dataset, view.view_id, options);
var $container = view.$container;
diff --git a/addons/web/static/src/js/views/form_common.js b/addons/web/static/src/js/views/form_common.js
index e365e61a0b8..7786a516894 100644
--- a/addons/web/static/src/js/views/form_common.js
+++ b/addons/web/static/src/js/views/form_common.js
@@ -115,7 +115,6 @@ var DefaultFieldManager = Widget.extend({
},
});
-
/**
* A mixin to apply on any FormWidget that has to completely re-render when its readonly state
* switch.
@@ -273,22 +272,19 @@ var CompletionFieldMixin = {
// all search/create popup handling
_search_create_popup: function(view, ids, context) {
var self = this;
- var pop = new SelectCreatePopup(this);
- pop.select_element(
- self.field.relation,
- {
- title: (view === 'search' ? _t("Search: ") : _t("Create: ")) + this.string,
- initial_ids: ids ? _.map(ids, function(x) {return x[0];}) : undefined,
- initial_view: view,
- disable_multiple_selection: true
- },
- self.build_domain(),
- new data.CompoundContext(self.build_context(), context || {})
- );
- pop.on("elements_selected", self, function(element_ids) {
- self.add_id(element_ids[0]);
- self.focus();
- });
+ new SelectCreateDialog(this, {
+ res_model: self.field.relation,
+ domain: self.build_domain(),
+ context: new data.CompoundContext(self.build_context(), context || {}),
+ title: (view === 'search' ? _t("Search: ") : _t("Create: ")) + this.string,
+ initial_ids: ids ? _.map(ids, function(x) {return x[0];}) : undefined,
+ initial_view: view,
+ disable_multiple_selection: true,
+ on_selected: function(element_ids) {
+ self.add_id(element_ids[0]);
+ self.focus();
+ }
+ }).open();
},
/**
* To implement.
@@ -305,8 +301,6 @@ var CompletionFieldMixin = {
},
};
-
-
/**
* Must be applied over an class already possessing the PropertiesMixin.
*
@@ -389,7 +383,6 @@ var NotebookInvisibilityChanger = InvisibilityChanger.extend({
},
});
-
/**
Base class for all fields, custom widgets and buttons to be displayed in the form view.
@@ -779,10 +772,9 @@ var AbstractField = FormWidget.extend(FieldInterface, {
});
/**
- * Class with everything which is common between FormOpenPopup and SelectCreatePopup.
+ * Class with everything which is common between FormViewDialog and SelectCreateDialog.
*/
-var AbstractFormPopup = Widget.extend({
- template: "AbstractFormPopup.render",
+var ViewDialog = Dialog.extend({ // FIXME should use ViewManager
/**
* options:
* -readonly: only applicable when not in creation mode, default to false
@@ -795,18 +787,27 @@ var AbstractFormPopup = Widget.extend({
* - child_name
* - form_view_options
*/
- init_popup: function(model, row_id, domain, context, options) {
- this.row_id = row_id;
- this.model = model;
- this.domain = domain || [];
- this.context = context || {};
- this.options = options;
- _.defaults(this.options, {});
+ init: function(parent, options) {
+ options = options || {};
+ options.dialogClass = options.dialogClass || '';
+ options.dialogClass += ' o_act_window';
+
+ this._super(parent, _.clone(options));
+
+ this.res_model = options.res_model || null;
+ this.res_id = options.res_id || null;
+ this.domain = options.domain || [];
+ this.context = options.context || {};
+ this.options = _.extend(this.options || {}, options || {});
+
+ this.on('closed', this, this.select);
+ this.on_selected = options.on_selected || (function() {});
},
+
init_dataset: function() {
var self = this;
this.created_elements = [];
- this.dataset = new data.ProxyDataSet(this, this.model, this.context);
+ this.dataset = new data.ProxyDataSet(this, this.res_model, this.context);
this.dataset.read_function = this.options.read_function;
this.dataset.create_function = function(data, options, sup) {
var fct = self.options.create_function || sup;
@@ -824,114 +825,102 @@ var AbstractFormPopup = Widget.extend({
this.dataset.parent_view = this.options.parent_view;
this.dataset.child_name = this.options.child_name;
},
- display_popup: function() {
+
+ select: function() {
+ if (this.created_elements.length > 0) {
+ this.on_selected(this.created_elements);
+ this.created_elements = [];
+ }
+ }
+});
+
+/**
+ * Create and edit dialog (displays a form view record and leave once saved)
+ */
+var FormViewDialog = ViewDialog.extend({
+ init: function(parent, options) {
var self = this;
- this.renderElement();
- var dialog = new Dialog(this, {
- dialogClass: 'oe_act_window',
- title: this.options.title || "",
- }, this.$el).open();
- dialog.on('closing', this, function (e){
- self.check_exit(true);
- });
- this.$buttonpane = dialog.$buttons;
- this.start();
+
+ var multi_select = options.res_id === null && ! options.disable_multiple_selection;
+ var readonly = options.res_id !== null && options.readonly;
+
+ if(!options || !options.buttons) {
+ options = options || {};
+ options.buttons = [
+ {text: (readonly ? _t("Close") : _t("Discard")), classes: "btn-default o_form_button_cancel", close: true, click: function() {
+ self.view_form.trigger('on_button_cancel');
+ }}
+ ];
+
+ if(!readonly) {
+ options.buttons.splice(0, 0, {text: _t("Save") + ((multi_select)? _t(" & Close") : ""), classes: "btn-primary", click: function() {
+ $.when(self.view_form.save()).done(function() {
+ self.view_form.reload_mutex.exec(function() {
+ self.trigger('record_saved');
+ self.close();
+ });
+ });
+ }
+ });
+
+ if(multi_select) {
+ options.buttons.splice(1, 0, {text: _t("Save & New"), classes: "btn-primary", click: function() {
+ $.when(self.view_form.save()).done(function() {
+ self.view_form.reload_mutex.exec(function() {
+ self.view_form.on_button_new();
+ });
+ });
+ }});
+ }
+ }
+ }
+
+ this._super(parent, options);
},
- setup_form_view: function() {
+
+ open: function() {
var self = this;
- if (this.row_id) {
- this.dataset.ids = [this.row_id];
- this.dataset.index = 0;
+ self._super();
+ self.init_dataset();
+
+ if (self.res_id) {
+ self.dataset.ids = [self.res_id];
+ self.dataset.index = 0;
} else {
- this.dataset.index = null;
+ self.dataset.index = null;
}
var options = _.clone(self.options.form_view_options) || {};
- if (this.row_id !== null) {
- options.initial_mode = this.options.readonly ? "view" : "edit";
+ if (self.res_id !== null) {
+ options.initial_mode = self.options.readonly ? "view" : "edit";
}
_.extend(options, {
- $buttons: this.$buttonpane,
+ $buttons: self.$buttons,
});
var FormView = core.view_registry.get('form');
- this.view_form = new FormView(this, this.dataset, this.options.view_id || false, options);
- if (this.options.alternative_form_view) {
- this.view_form.set_embedded_view(this.options.alternative_form_view);
+ self.view_form = new FormView(self, self.dataset, self.options.view_id || false, options);
+ if (self.options.alternative_form_view) {
+ self.view_form.set_embedded_view(self.options.alternative_form_view);
}
- this.view_form.appendTo(this.$(".oe_popup_form").show());
- this.view_form.on("form_view_loaded", self, function() {
- var multi_select = self.row_id === null && ! self.options.disable_multiple_selection;
- self.$buttonpane.html(QWeb.render("AbstractFormPopup.buttons", {
- multi_select: multi_select,
- readonly: self.row_id !== null && self.options.readonly,
- }));
- var $snbutton = self.$buttonpane.find(".oe_abstractformpopup-form-save-new");
- $snbutton.click(function() {
- $.when(self.view_form.save()).done(function() {
- self.view_form.reload_mutex.exec(function() {
- self.view_form.on_button_new();
- });
- });
- });
- var $sbutton = self.$buttonpane.find(".oe_abstractformpopup-form-save");
- $sbutton.click(function() {
- $.when(self.view_form.save()).done(function() {
- self.view_form.reload_mutex.exec(function() {
- self.check_exit();
- });
- });
- });
- var $cbutton = self.$buttonpane.find(".oe_abstractformpopup-form-close");
- $cbutton.click(function() {
- self.view_form.trigger('on_button_cancel');
- self.check_exit();
+
+ self.$el.hide();
+ self.view_form.appendTo(self.$el);
+ self.view_form.on("form_view_loaded", self, function() {
+ self.view_form.do_show().then(function() {
+ self.$el.show();
});
- self.view_form.do_show();
});
- },
- select_elements: function(element_ids) {
- this.trigger("elements_selected", element_ids);
- },
- check_exit: function(no_destroy) {
- if (this.created_elements.length > 0) {
- this.select_elements(this.created_elements);
- this.created_elements = [];
- }
- this.trigger('closed');
- this.destroy();
- },
- destroy: function () {
- this.trigger('closed');
- if (this.$el.is(":data(bs.modal)")) {
- this.$el.parents('.modal').modal('hide');
- }
- this._super();
- },
-});
-/**
- * Class to display a popup containing a form view.
- */
-var FormOpenPopup = AbstractFormPopup.extend({
- show_element: function(model, row_id, context, options) {
- this.init_popup(model, row_id, [], context, options);
- _.defaults(this.options, {
- });
- this.display_popup();
- },
- start: function() {
- this._super();
- this.init_dataset();
- this.setup_form_view();
+ return this;
},
});
var SelectCreateListView = ListView.extend({
do_add_record: function () {
- this.popup.new_object();
+ this.popup.create_edit_record();
},
select_record: function(index) {
- this.popup.select_elements([this.dataset.ids[index]]);
- this.popup.destroy();
+ this.popup.on_selected([this.dataset.ids[index]]);
+ this.popup.close();
},
do_select: function(ids, records) {
this._super(ids, records);
@@ -940,10 +929,9 @@ var SelectCreateListView = ListView.extend({
});
/**
- * Class to display a popup to display a list to search a row. It also allows
- * to switch to a form view to create a new row.
+ * Search dialog (displays a list of records and permits to create a new one by switching to a form view)
*/
-var SelectCreatePopup = AbstractFormPopup.extend({
+var SelectCreateDialog = ViewDialog.extend({
/**
* options:
* - initial_ids
@@ -951,15 +939,15 @@ var SelectCreatePopup = AbstractFormPopup.extend({
* - disable_multiple_selection
* - list_view_options
*/
- select_element: function(model, options, domain, context) {
- this.init_popup(model, null, domain, context, options);
- _.defaults(this.options, {
- initial_view: "search",
- });
+ init: function(parent, options) {
+ this._super(parent, options);
+
+ _.defaults(this.options, { initial_view: "search" });
this.initial_ids = this.options.initial_ids;
- this.display_popup();
},
- start: function() {
+
+ open: function() {
+ this._super();
this.init_dataset();
if (this.options.initial_view == "search") {
var context = pyeval.sync_eval_domains_and_contexts({
@@ -973,19 +961,21 @@ var SelectCreatePopup = AbstractFormPopup.extend({
search_defaults[match[1]] = value_;
}
});
- this.setup_search_view(search_defaults);
+ this.setup(search_defaults);
} else { // "form"
- this.new_object();
+ this.create_edit_record();
}
+ return this;
},
- setup_search_view: function(search_defaults) {
+
+ setup: function(search_defaults) {
var self = this;
if (this.searchview) {
this.searchview.destroy();
}
- var $buttons = this.$('.o-search-options');
- this.searchview = new SearchView(this,
- this.dataset, false, search_defaults, {$buttons: $buttons});
+ var $header = $('<div/>').addClass('o_modal_header').appendTo(this.$el);
+ var $buttons = $('<div/>').addClass('o_search_options').appendTo($header);
+ this.searchview = new SearchView(this, this.dataset, false, search_defaults, {$buttons: $buttons});
this.searchview.on('search_data', self, function(domains, contexts, groupbys) {
if (self.initial_ids) {
self.do_search(domains.concat([[["id", "in", self.initial_ids]], self.domain]),
@@ -995,22 +985,22 @@ var SelectCreatePopup = AbstractFormPopup.extend({
self.do_search(domains.concat([self.domain]), contexts.concat(self.context), groupbys);
}
});
- this.searchview.appendTo(this.$(".o-popup-search")).done(function() {
+ this.searchview.prependTo($header).done(function() {
self.searchview.toggle_visibility(true);
self.view_list = new SelectCreateListView(self,
- self.dataset, false,
- _.extend({'deletable': false,
- 'selectable': !self.options.disable_multiple_selection,
- 'import_enabled': false,
- '$buttons': self.$buttonpane,
- 'disable_editable_mode': true,
- '$pager': self.$('.oe_popup_list_pager'),
- }, self.options.list_view_options || {}));
+ self.dataset, false,
+ _.extend({'deletable': false,
+ 'selectable': !self.options.disable_multiple_selection,
+ 'import_enabled': false,
+ '$buttons': self.$footer,
+ 'disable_editable_mode': true,
+ '$pager': self.$('.o_popup_list_pager'),
+ }, self.options.list_view_options || {}));
self.view_list.on('edit:before', self, function (e) {
e.cancel = true;
});
self.view_list.popup = self;
- self.view_list.appendTo(self.$(".oe_popup_list").show()).then(function() {
+ self.view_list.appendTo(self.$el).then(function() {
self.view_list.do_show();
}).then(function() {
if (self.options.initial_facet) {
@@ -1020,23 +1010,22 @@ var SelectCreatePopup = AbstractFormPopup.extend({
}
self.searchview.do_search();
});
- self.view_list.on("list_view_loaded", self, function() {
- self.$buttonpane.html(QWeb.render("SelectCreatePopup.search.buttons", {widget:self}));
- var $cbutton = self.$buttonpane.find(".oe_selectcreatepopup-search-close");
- $cbutton.click(function() {
- self.destroy();
- });
- var $sbutton = self.$buttonpane.find(".oe_selectcreatepopup-search-select");
- $sbutton.click(function() {
- self.select_elements(self.selected_ids);
- self.destroy();
- });
- $cbutton = self.$buttonpane.find(".oe_selectcreatepopup-search-create");
- $cbutton.click(function() {
- self.new_object();
- });
- });
- });
+
+ var buttons = [
+ {text: _t("Cancel"), classes: "btn-default o_form_button_cancel", close: true}
+ ];
+ if(!self.options.no_create) {
+ buttons.splice(0, 0, {text: _t("Create"), classes: "btn-primary", click: function() {
+ self.create_edit_record();
+ }});
+ }
+ if(!self.options.disable_multiple_selection) {
+ buttons.splice(0, 0, {text: _t("Select"), classes: "btn-primary o_selectcreatepopup_search_select", disabled: true, close: true, click: function() {
+ self.on_selected(self.selected_ids);
+ }});
+ }
+ self.set_buttons(buttons);
+ });
},
do_search: function(domains, contexts, groupbys) {
var results = pyeval.sync_eval_domains_and_contexts({
@@ -1047,43 +1036,35 @@ var SelectCreatePopup = AbstractFormPopup.extend({
this.view_list.do_search(results.domain, results.context, results.group_by);
},
on_click_element: function(ids) {
- var self = this;
this.selected_ids = ids || [];
- if(this.selected_ids.length > 0) {
- self.$buttonpane.find(".oe_selectcreatepopup-search-select").removeAttr('disabled');
- } else {
- self.$buttonpane.find(".oe_selectcreatepopup-search-select").attr('disabled', "disabled");
- }
+ this.$footer.find(".o_selectcreatepopup_search_select").prop('disabled', this.selected_ids.length <= 0);
},
- new_object: function() {
- if (this.searchview) {
- this.searchview.toggle_visibility(false);
- }
- if (this.view_list) {
- this.view_list.do_hide();
- this.view_list.$el.parent().hide();
- }
- this.setup_form_view();
+ create_edit_record: function() {
+ new FormViewDialog(this.getParent(), this.options).open();
+ this.close();
},
});
-var DomainEditorPopup = SelectCreatePopup.extend({
- select_element: function (model, options, domain, context) {
+var DomainEditorDialog = SelectCreateDialog.extend({
+ init: function(parent, options) {
if (options.readonly) {
- return this._super(model, options, domain, context);
+ this._super(parent, options);
+ return;
}
- options.initial_facet = {
+ options = _.defaults(options, {initial_facet: {
category: _t("Custom Filter"),
icon: 'fa-star',
field: {
- get_context: function () { return context; },
+ get_context: function () { return options.context; },
get_groupby: function () { return []; },
- get_domain: function () { return domain; },
+ get_domain: function () { return options.default_domain; },
},
values: [{label: _t("Selected domain"), value: null}],
- };
- this._super(model, options, [], context);
+ }});
+
+ this._super(parent, options);
},
+
get_domain: function (selected_ids) {
var group_domain = [],
domain;
@@ -1125,11 +1106,11 @@ return {
commands: commands,
AbstractField: AbstractField,
- // popup dialogs
- AbstractFormPopup: AbstractFormPopup,
- FormOpenPopup: FormOpenPopup,
- SelectCreatePopup: SelectCreatePopup,
- DomainEditorPopup: DomainEditorPopup,
+ // Dialogs
+ ViewDialog: ViewDialog,
+ FormViewDialog: FormViewDialog,
+ SelectCreateDialog: SelectCreateDialog,
+ DomainEditorDialog: DomainEditorDialog,
};
}); \ No newline at end of file
diff --git a/addons/web/static/src/js/views/form_relational_widgets.js b/addons/web/static/src/js/views/form_relational_widgets.js
index df8e0150aa1..f2e3d77fff4 100644
--- a/addons/web/static/src/js/views/form_relational_widgets.js
+++ b/addons/web/static/src/js/views/form_relational_widgets.js
@@ -144,20 +144,17 @@ var FieldMany2One = common.AbstractField.extend(common.CompletionFieldMixin, com
self.focus();
return;
}
- var pop = new common.FormOpenPopup(self);
var context = self.build_context().eval();
var model_obj = new Model(self.field.relation);
model_obj.call('get_formview_id', [self.get("value"), context]).then(function(view_id){
- pop.show_element(
- self.field.relation,
- self.get("value"),
- self.build_context(),
- {
- title: _t("Open: ") + self.string,
- view_id: view_id,
- readonly: !self.can_write
- }
- );
+ var pop = new common.FormViewDialog(self, {
+ res_model: self.field.relation,
+ res_id: self.get("value"),
+ context: self.build_context(),
+ title: _t("Open: ") + self.string,
+ view_id: view_id,
+ readonly: !self.can_write
+ }).open();
pop.on('write_completed', self, function(){
self.display_value = {};
self.display_value_backup = {};
@@ -261,7 +258,7 @@ var FieldMany2One = common.AbstractField.extend(common.CompletionFieldMixin, com
// autocomplete open
if (ignore_blur) { $(this).focus(); return; }
if (_(self.getChildren()).any(function (child) {
- return child instanceof common.AbstractFormPopup;
+ return child instanceof common.ViewDialog;
})) { return; }
self.trigger('blurred');
}
@@ -997,35 +994,34 @@ var One2ManyListView = ListView.extend({
this._super.apply(this, arguments);
} else {
var self = this;
- var pop = new common.SelectCreatePopup(this);
- pop.select_element(
- self.o2m.field.relation,
- {
- title: _t("Create: ") + self.o2m.string,
- initial_view: "form",
- alternative_form_view: self.o2m.field.views ? self.o2m.field.views.form : undefined,
- create_function: function(data, options) {
- return self.o2m.data_create(data, options);
- },
- read_function: function(ids, fields, options) {
- return self.o2m.data_read(ids, fields, options);
- },
- parent_view: self.o2m.view,
- child_name: self.o2m.name,
- form_view_options: {'not_interactible_on_create':true}
+ new common.SelectCreateDialog(this, {
+ res_model: self.o2m.field.relation,
+ domain: self.o2m.build_domain(),
+ context: self.o2m.build_context(),
+ title: _t("Create: ") + self.o2m.string,
+ initial_view: "form",
+ alternative_form_view: self.o2m.field.views ? self.o2m.field.views.form : undefined,
+ create_function: function(data, options) {
+ return self.o2m.data_create(data, options);
},
- self.o2m.build_domain(),
- self.o2m.build_context()
- );
- pop.on("elements_selected", self, function() {
- self.o2m.reload_current_view();
- });
+ read_function: function(ids, fields, options) {
+ return self.o2m.data_read(ids, fields, options);
+ },
+ parent_view: self.o2m.view,
+ child_name: self.o2m.name,
+ form_view_options: {'not_interactible_on_create':true},
+ on_selected: function() {
+ self.o2m.reload_current_view();
+ }
+ }).open();
}
},
do_activate_record: function(index, id) {
var self = this;
- var pop = new common.FormOpenPopup(self);
- pop.show_element(self.o2m.field.relation, id, self.o2m.build_context(), {
+ new common.FormViewDialog(self, {
+ res_model: self.o2m.field.relation,
+ res_id: id,
+ context: self.o2m.build_context(),
title: _t("Open: ") + self.o2m.string,
write_function: function(id, data) {
return self.o2m.data_update(id, data, {}).done(function() {
@@ -1040,7 +1036,7 @@ var One2ManyListView = ListView.extend({
},
form_view_options: {'not_interactible_on_create':true},
readonly: !this.is_action_enabled('edit') || self.o2m.get("effective_readonly")
- });
+ }).open();
},
do_button_action: function (name, id, callback) {
if (!_.isNumber(id)) {
@@ -1201,8 +1197,11 @@ var One2ManyViewManager = ViewManager.extend({
}
var self = this;
var id = self.o2m.dataset.index !== null ? self.o2m.dataset.ids[self.o2m.dataset.index] : null;
- var pop = new common.FormOpenPopup(this);
- pop.show_element(self.o2m.field.relation, id, self.o2m.build_context(), {
+ var pop = new common.FormViewDialog(this, {
+ res_model: self.o2m.field.relation,
+ res_id: id,
+ context: self.o2m.build_context(),
+
title: _t("Open: ") + self.o2m.string,
create_function: function(data, options) {
return self.o2m.data_create(data, options);
@@ -1220,7 +1219,7 @@ var One2ManyViewManager = ViewManager.extend({
},
form_view_options: {'not_interactible_on_create':true},
readonly: self.o2m.get("effective_readonly")
- });
+ }).open();
pop.on("elements_selected", self, function() {
self.o2m.reload_current_view();
});
@@ -1466,30 +1465,30 @@ var Many2ManyListView = ListView.extend(/** @lends instance.web.form.Many2ManyLi
}));
},
do_add_record: function () {
- var pop = new common.SelectCreatePopup(this);
- pop.select_element(
- this.model,
- {
- title: _t("Add: ") + this.m2m_field.string,
- alternative_form_view: this.m2m_field.field.views ? this.m2m_field.field.views.form : undefined,
- no_create: this.m2m_field.options.no_create,
- },
- new data.CompoundDomain(this.m2m_field.build_domain(), ["!", ["id", "in", this.m2m_field.dataset.ids]]),
- this.m2m_field.build_context()
- );
var self = this;
- pop.on("elements_selected", self, function(element_ids) {
- return self.dataset.o2m.data_link_multi(element_ids);
- });
+
+ new common.SelectCreateDialog(this, {
+ res_model: this.model,
+ domain: new data.CompoundDomain(this.m2m_field.build_domain(), ["!", ["id", "in", this.m2m_field.dataset.ids]]),
+ context: this.m2m_field.build_context(),
+ title: _t("Add: ") + this.m2m_field.string,
+ alternative_form_view: this.m2m_field.field.views ? this.m2m_field.field.views.form : undefined,
+ no_create: this.m2m_field.options.no_create,
+ on_selected: function(element_ids) {
+ return self.dataset.o2m.data_link_multi(element_ids);
+ }
+ }).open();
},
do_activate_record: function(index, id) {
var self = this;
- var pop = new common.FormOpenPopup(this);
- pop.show_element(this.dataset.model, id, this.m2m_field.build_context(), {
+ var pop = new common.FormViewDialog(this, {
+ res_model: this.dataset.model,
+ res_id: id,
+ context: this.m2m_field.build_context(),
title: _t("Open: ") + this.m2m_field.string,
alternative_form_view: this.m2m_field.field.views ? this.m2m_field.field.views.form : undefined,
readonly: this.getParent().get("effective_readonly")
- });
+ }).open();
pop.on('write_completed', self, function () {
self.dataset.evict_record(id);
self.reload_content();
@@ -1579,22 +1578,21 @@ var FieldMany2ManyKanban = AbstractManyField.extend(common.CompletionFieldMixin,
var self = this;
var pop;
if (this.dataset.index === null) {
- pop = new common.SelectCreatePopup(this);
- pop.select_element(
- this.field.relation,
- {
- title: _t("Add: ") + this.string
- },
- new data.CompoundDomain(this.build_domain(), ["!", ["id", "in", this.dataset.ids]]),
- this.build_context()
- );
- pop.on("elements_selected", self, function(element_ids) {
- return self.data_link_multi(element_ids);
- });
+ new common.SelectCreateDialog(this, {
+ res_model: this.field.relation,
+ domain: new data.CompoundDomain(this.build_domain(), ["!", ["id", "in", this.dataset.ids]]),
+ context: this.build_context(),
+ title: _t("Add: ") + this.string,
+ on_selected: function(element_ids) {
+ return self.data_link_multi(element_ids);
+ }
+ }).open();
} else {
var id = self.dataset.ids[self.dataset.index];
- pop = new common.FormOpenPopup(this);
- pop.show_element(self.field.relation, id, self.build_context(), {
+ pop = new common.FormViewDialog(this, {
+ res_model: self.field.relation,
+ res_id: id,
+ context: self.build_context(),
title: _t("Open: ") + self.string,
write_function: function(id, data, options) {
return self.data_update(id, data, {}).done(function() {
@@ -1605,7 +1603,7 @@ var FieldMany2ManyKanban = AbstractManyField.extend(common.CompletionFieldMixin,
parent_view: self.view,
child_name: self.name,
readonly: self.get("effective_readonly")
- });
+ }).open();
}
},
add_id: function(id) {
diff --git a/addons/web/static/src/js/views/form_view.js b/addons/web/static/src/js/views/form_view.js
index df570967f94..35aa0223a13 100644
--- a/addons/web/static/src/js/views/form_view.js
+++ b/addons/web/static/src/js/views/form_view.js
@@ -583,10 +583,8 @@ var FormView = View.extend(common.FieldManagerMixin, {
new Dialog(this, {
size: 'medium',
title:result.warning.title,
- buttons: [
- {text: _t("Ok"), click: function() { this.parents('.modal').modal('hide'); }}
- ]
- }, QWeb.render("CrashManager.warning", result.warning)).open();
+ $content: QWeb.render("CrashManager.warning", result.warning)
+ }).open();
}
return $.Deferred().resolve();
@@ -1081,12 +1079,8 @@ var FormView = View.extend(common.FieldManagerMixin, {
.value();
var d = new Dialog(this, {
title: _t("Set Default"),
- args: {
- fields: fields,
- conditions: conditions
- },
buttons: [
- {text: _t("Close"), click: function () { d.close(); }},
+ {text: _t("Close"), close: true},
{text: _t("Save default"), click: function () {
var $defaults = d.$el.find('#formview_default_fields');
var field_to_set = $defaults.val();
@@ -1108,6 +1102,10 @@ var FormView = View.extend(common.FieldManagerMixin, {
}}
]
});
+ d.args = {
+ fields: fields,
+ conditions: conditions
+ };
d.template = 'FormView.set_default';
d.open();
},
diff --git a/addons/web/static/src/js/views/form_widgets.js b/addons/web/static/src/js/views/form_widgets.js
index 2358ea88dec..49d909af041 100644
--- a/addons/web/static/src/js/views/form_widgets.js
+++ b/addons/web/static/src/js/views/form_widgets.js
@@ -62,10 +62,7 @@ var WidgetButton = common.FormWidget.extend({
var dialog = new Dialog(this, {
title: _t('Confirm'),
buttons: [
- {text: _t("Cancel"), click: function() {
- this.parents('.modal').modal('hide');
- }
- },
+ {text: _t("Cancel"), close: true},
{text: _t("Ok"), click: function() {
var self2 = this;
self.on_confirmed().always(function() {
@@ -74,8 +71,9 @@ var WidgetButton = common.FormWidget.extend({
}
}
],
- }, $('<div/>').text(self.node.attrs.confirm)).open();
- dialog.on("closing", null, function() {def.resolve();});
+ $content: $('<div/>').text(self.node.attrs.confirm)
+ }).open();
+ dialog.on("closed", null, function() {def.resolve();});
return def.promise();
} else {
return self.on_confirmed();
@@ -439,22 +437,20 @@ var FieldCharDomain = common.AbstractField.extend(common.ReinitializeFieldMixin,
on_click: function(event) {
event.preventDefault();
var self = this;
- var model = this.options.model || this.field_manager.get_field_value(this.options.model_field);
- var options = {
- title: this.get('effective_readonly') ? 'Selected records' : 'Select records...',
- readonly: this.get('effective_readonly'),
- disable_multiple_selection: this.get('effective_readonly'),
- no_create: this.get('effective_readonly'),
- };
- var domain = this.get('value');
- var popup = new common.DomainEditorPopup(this);
- popup.select_element(model, options, domain, {});
- popup.on("elements_selected", self, function(selected_ids) {
- if (!self.get('effective_readonly')) {
- self.set_value(popup.get_domain(selected_ids));
+ new common.DomainEditorDialog(this, {
+ model: this.options.model || this.field_manager.get_field_value(this.options.model_field),
+ domain: this.get('value'),
+ title: this.get('effective_readonly') ? 'Selected records' : 'Select records...',
+ readonly: this.get('effective_readonly'),
+ disable_multiple_selection: this.get('effective_readonly'),
+ no_create: this.get('effective_readonly'),
+ on_selected: function(selected_ids) {
+ if (!self.get('effective_readonly')) {
+ self.set_value(popup.get_domain(selected_ids));
+ }
}
- });
+ }).open();
},
});
diff --git a/addons/web/static/src/js/widgets/change_password.js b/addons/web/static/src/js/widgets/change_password.js
index 0ddfb20c4df..cded9dc9a4d 100644
--- a/addons/web/static/src/js/widgets/change_password.js
+++ b/addons/web/static/src/js/widgets/change_password.js
@@ -7,11 +7,11 @@ var Widget = require('web.Widget');
var _t = core._t;
-var ChangePassword = Widget.extend({
+var ChangePassword = Widget.extend({ // FIXME
template: "ChangePassword",
start: function() {
var self = this;
- this.getParent().dialog_title = _t("Change Password");
+ this.getParent().set_title(_t("Change Password"));
var $button = self.$el.find('.oe_form_button');
$button.appendTo(this.getParent().$buttons);
$button.eq(2).click(function(){
@@ -34,10 +34,8 @@ var ChangePassword = Widget.extend({
return new Dialog(this, {
size: 'medium',
title: error.title,
- buttons: [
- {text: _t("Ok"), click: function() { this.parents('.modal').modal('hide'); }}
- ]
- }, $('<div>').html(error.error)).open();
+ $content: $('<div>').html(error.error)
+ }).open();
},
});
diff --git a/addons/web/static/src/js/widgets/data_export.js b/addons/web/static/src/js/widgets/data_export.js
index 946862d7102..57159732ad6 100644
--- a/addons/web/static/src/js/widgets/data_export.js
+++ b/addons/web/static/src/js/widgets/data_export.js
@@ -12,7 +12,6 @@ var _t = core._t;
var DataExport = Dialog.extend({
template: 'ExportTreeView',
- dialog_title: {toString: function () { return _t("Export Data"); }},
events: {
'click #add_field': function () {
var self = this;
@@ -48,6 +47,7 @@ var DataExport = Dialog.extend({
this.dataset = dataset;
this.exports = new data.DataSetSearch(
this, 'ir.exports', this.dataset.get_context());
+ this.set_title(_t("Export Data"));
},
start: function() {
var self = this;
diff --git a/addons/web/static/src/js/widgets/database_manager.js b/addons/web/static/src/js/widgets/database_manager.js
index 180d42b59b6..cbffa5117dc 100644
--- a/addons/web/static/src/js/widgets/database_manager.js
+++ b/addons/web/static/src/js/widgets/database_manager.js
@@ -99,10 +99,8 @@ var DataBaseManager = Widget.extend({
return new Dialog(this, {
size: 'medium',
title: error.title,
- buttons: [
- {text: _t("Ok"), click: function() { this.parents('.modal').modal('hide'); }}
- ]
- }, $('<div>').html(error.error)).open();
+ $content: $('<div>').html(error.error)
+ }).open();
},
do_create: function(form) {
var fields = $(form).serializeArray();
diff --git a/addons/web/static/src/js/widgets/debug_manager.js b/addons/web/static/src/js/widgets/debug_manager.js
index 01db3ff71ef..b529e155fd9 100644
--- a/addons/web/static/src/js/widgets/debug_manager.js
+++ b/addons/web/static/src/js/widgets/debug_manager.js
@@ -131,12 +131,9 @@ if (core.debug) {
});
});
new Dialog(self, {
- title: _.str.sprintf(_t("Model %s fields"),
- self.dataset.model),
- buttons: {
- Ok: function() { this.parents('.modal').modal('hide');}
- },
- }, $root).open();
+ title: _.str.sprintf(_t("Model %s fields"), self.dataset.model),
+ $content: $root
+ }).open();
});
},
fvg: function() {
diff --git a/addons/web/static/src/js/widgets/sidebar.js b/addons/web/static/src/js/widgets/sidebar.js
index 5dc6c147f39..9f7c46bf48d 100644
--- a/addons/web/static/src/js/widgets/sidebar.js
+++ b/addons/web/static/src/js/widgets/sidebar.js
@@ -121,7 +121,7 @@ var Sidebar = Widget.extend({
domain = $.Deferred().resolve(undefined);
}
if (ids.length === 0) {
- new Dialog(this, { title: _t("Warning"), size: 'medium',}, $("<div />").text(_t("You must choose at least one record."))).open();
+ new Dialog(this, {title: _t("Warning"), size: 'medium', $content: $("<div/>").html(_t("You must choose at least one record."))}).open();
return false;
}
var dataset = self.getParent().dataset;
diff --git a/addons/web/static/src/js/widgets/user_menu.js b/addons/web/static/src/js/widgets/user_menu.js
index dba1704c719..3d360c1eae6 100644
--- a/addons/web/static/src/js/widgets/user_menu.js
+++ b/addons/web/static/src/js/widgets/user_menu.js
@@ -101,9 +101,10 @@ var SystrayMenu = Widget.extend({
});
new Dialog(this, {
size: 'medium',
- dialogClass: 'oe_act_window',
+ dialogClass: 'o_act_window',
title: _t("About"),
- }, $help).open();
+ $content: $help
+ }).open();
});
},
});
diff --git a/addons/web/static/src/less/modal.less b/addons/web/static/src/less/modal.less
new file mode 100644
index 00000000000..784fb47aaf8
--- /dev/null
+++ b/addons/web/static/src/less/modal.less
@@ -0,0 +1,51 @@
+.modal {
+
+ .modal-content {
+ border-radius: 0;
+
+ .modal-body {
+ &.o_act_window {
+ padding: 0;
+ }
+
+ .o_modal_header {
+ .o-webclient-padding(@top: 10px, @bottom: 10px);
+
+ .o_popup_list_pager { // FIXME : should check where it is used (o_modal_header ~= control panel)
+ float: right;
+ }
+ }
+
+ .oe-view-manager-content {
+ position: static; // Reset position for view managers in modals (default value: absolute)
+ }
+ }
+
+ .modal-footer {
+ text-align: left;
+ }
+ }
+
+
+ @media (min-width: @screen-sm-min) {
+ .modal-dialog {
+ height: 100%;
+ padding: 30px 0;
+ margin: 0 auto;
+
+ .modal-content {
+ max-height: 100%;
+ .o-flex-display();
+ .o-flex-flow(column, nowrap);
+
+ .modal-header, .modal-footer {
+ .o-flex(0, 0, auto);
+ }
+
+ .modal-body {
+ overflow: auto;
+ }
+ }
+ }
+ }
+}
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 52a7c8130a6..814ef171032 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -25,38 +25,30 @@
</t>
<t t-name="Dialog">
<div class="modal" tabindex="-1" data-backdrop="static" role="dialog" aria-hidden="true">
- <div class="modal-dialog modal-lg">
- <div class="modal-content">
+ <div class="modal-dialog">
+ <div class="modal-content openerp">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
- <h3 class="modal-title"><t t-raw="title"/><span class="text-muted"><t t-esc="subtitle"/></span></h3>
- </div>
- <div class="modal-body">
+ <h4 class="modal-title"><t t-raw="title"/><span class="o_subtitle text-muted"><t t-esc="subtitle"/></span></h4>
</div>
+ <div class="modal-body"/>
+ <div class="modal-footer"/>
</div>
</div>
</div>
</t>
<t t-name="CrashManager.warning">
- <table cellspacing="0" cellpadding="0" border="0" class="oe_dialog_warning">
- <tr>
- <td>
- <p>
- <t t-js="d">
- var message = d.message ? d.message : d.error.data.message;
- d.html_error = context.engine.tools.html_escape(message)
- .replace(/\n/g, '<br/>');
- </t>
- <t t-raw="html_error"/>
- </p>
- </td>
- </tr>
- </table>
+ <div class="o_dialog_warning">
+ <t t-js="d">
+ var message = d.message ? d.message : d.error.data.message;
+ d.html_error = context.engine.tools.html_escape(message).replace(/\n/g, '<br/>');
+ </t>
+ <t t-raw="html_error"/>
+ </div>
</t>
<t t-name="CrashManager.error">
- <div class="oe_error_detail">
+ <div class="o_error_detail">
<pre><t t-esc="error.message"/></pre>
- <hr/>
<pre><t t-esc="error.data.debug"/></pre>
</div>
</t>
@@ -330,7 +322,6 @@
<tr>
<td colspan="2" align="right">
<button class='oe_button oe_form_button'>Change Password</button>
- <span class="oe_fade oe_form_button"> or </span>
<button type="button" class="oe_button oe_form_button_cancel oe_form_button oe_link" href="javascript:void(0)"><span>Cancel</span></button>
</td>
</tr>
@@ -815,7 +806,7 @@
<span class="oe_form_pager_state"></span>
</t>
<form t-name="FormView.set_default">
- <t t-set="args" t-value="widget.dialog_options.args"/>
+ <t t-set="args" t-value="widget.args"/>
<table style="width: 100%">
<tr>
<td>
@@ -1497,8 +1488,7 @@
</div>
</t>
<t t-name="WidgetButton">
- <span t-if="widget.pre_text"> <t t-esc="widget.pre_text"/> </span>
- <button type="button" t-att-class="widget.is_stat_button ? 'oe_stat_button btn btn-default' : 'oe_button oe_form_button ' + (widget.node.attrs.class ? widget.node.attrs.class : '')"
+ <button type="button" t-attf-class="btn btn-sm #{widget.node.attrs.class or ''}"
t-att-style="widget.node.attrs.style"
t-att-tabindex="widget.node.attrs.tabindex"
t-att-autofocus="widget.node.attrs.autofocus"
@@ -1508,7 +1498,6 @@
<span t-if="widget.string and !widget.is_stat_button"><t t-esc="widget.string"/></span>
<div t-if="widget.string and widget.is_stat_button"><t t-esc="widget.string"/></div>
</button>
- <span t-if="widget.post_text"> <t t-esc="widget.post_text"/> </span>
</t>
<t t-name="WidgetButton.tooltip" t-extend="WidgetLabel.tooltip">
<t t-jquery="div.oe_tooltip_string" t-operation="replace">
@@ -1542,51 +1531,13 @@
</t>
</t>
-<t t-name="AbstractFormPopup.render">
- <div>
- <div class="o-modal-header">
- <div class="o-popup-search"/>
- <div class="o-search-options oe-search-options"/>
- <div class="oe_popup_list_pager"/>
- </div>
- <div class="oe_popup_list"/>
- <div class="oe_popup_form"/>
- </div>
-</t>
-<t t-name="SelectCreatePopup.search.buttons">
- <t t-if="! widget.options.disable_multiple_selection">
- <button type="button" class="oe_button oe_selectcreatepopup-search-select oe_highlight" disabled="disabled">Select</button>
- </t>
- <t t-if="!widget.options.no_create">
- <button type="button" class="oe_button oe_selectcreatepopup-search-create">Create</button>
- or </t><a class="oe_selectcreatepopup-search-close oe_bold oe_form_button_cancel" href="javascript:void(0)">Cancel</a>
-</t>
-<t t-name="AbstractFormPopup.buttons">
- <t t-if="! readonly">
- <t t-if="! multi_select">
- <button type="button" class="oe_button oe_abstractformpopup-form-save oe_highlight">Save</button>
- </t>
- <t t-if="multi_select">
- <button type="button" class="oe_button oe_abstractformpopup-form-save oe_highlight">Save &amp; Close</button>
- <button type="button" class="oe_button oe_abstractformpopup-form-save-new oe_highlight">Save &amp; New</button>
- </t>
- or
- </t>
- <a class="oe_abstractformpopup-form-close oe_bold oe_form_button_cancel" href="javascript:void(0)">
- <t t-if="! readonly">
- Discard
- </t>
- <t t-if="readonly">
- Close
- </t>
- </a>
-</t>
<t t-name="One2Many.formview" t-extend="FormView">
<t t-jquery=".oe_form_buttons" t-operation="inner">
<button type="button" class="oe_button oe_form_button_create">Add</button>
</t>
</t>
+
<t t-name="One2Many.listview" t-extend="ListView">
<t t-jquery="thead > tr:first">
this.removeAttr('t-if');
diff --git a/addons/web/static/test/menu.js b/addons/web/static/test/menu.js
index 78c006fa8ba..8f183481bb5 100644
--- a/addons/web/static/test/menu.js
+++ b/addons/web/static/test/menu.js
@@ -249,10 +249,10 @@ Tour.register({
{
title: "Select next action",
onload: function () {
- if ($(".oe_error_detail").size()) {
+ if ($(".o_error_detail").size()) {
console.log("Tour 'test_menu' has detected an error.");
}
- if ($(".oe_dialog_warning").size()) {
+ if ($(".o_dialog_warning").size()) {
console.log("Tour 'test_menu' has detected a warning.");
}
diff --git a/addons/web/views/webclient_templates.xml b/addons/web/views/webclient_templates.xml
index 2cc1f28641a..690b56b044c 100644
--- a/addons/web/views/webclient_templates.xml
+++ b/addons/web/views/webclient_templates.xml
@@ -75,6 +75,7 @@
<link rel="stylesheet" href='/website/static/src/less/import_bootstrap.less'/>
<link rel="stylesheet" href="/web/static/src/less/enterprise_compatibility.less"/>
<link rel="stylesheet" href="/web/static/src/less/utils.less"/>
+ <link rel="stylesheet" href="/web/static/src/less/modal.less"/>
<script src="/web/static/lib/bootstrap/js/affix.js"></script>
<script src="/web/static/lib/bootstrap/js/alert.js"></script>
<script src="/web/static/lib/bootstrap/js/button.js"></script>
diff --git a/addons/web_calendar/static/src/js/web_calendar.js b/addons/web_calendar/static/src/js/web_calendar.js
index 088d7cdbedf..d2a57bab06a 100644
--- a/addons/web_calendar/static/src/js/web_calendar.js
+++ b/addons/web_calendar/static/src/js/web_calendar.js
@@ -375,9 +375,9 @@ var CalendarView = View.extend({
get_quick_create_class: function () {
return widgets.QuickCreate;
},
- open_quick_create: function(data_template) {
+ open_quick_create: function(data_template) { // FIXME
if (!isNullOrUndef(this.quick)) {
- return this.quick.trigger('close');
+ return this.quick.close();
}
var QuickCreate = this.get_quick_create_class();
@@ -385,14 +385,16 @@ var CalendarView = View.extend({
this.quick = new QuickCreate(this, this.dataset, true, this.options, data_template);
this.quick.on('added', this, this.quick_created)
.on('slowadded', this, this.slow_created)
- .on('close', this, function() {
- this.quick.destroy();
+ .on('closed', this, function() {
delete this.quick;
this.$calendar.fullCalendar('unselect');
});
- this.quick.replace(this.$el.find('.oe_calendar_qc_placeholder'));
- if (!this.options.disable_quick_create) {
+
+ if(!this.options.disable_quick_create) {
+ this.quick.open();
this.quick.focus();
+ } else {
+ this.quick.start();
}
},
@@ -874,38 +876,26 @@ var CalendarView = View.extend({
}
}
else {
- var pop = new form_common.FormOpenPopup(this);
- var id_cast = parseInt(id).toString() == id ? parseInt(id) : id;
- pop.show_element(this.dataset.model, id_cast, this.dataset.get_context(), {
- title: _.str.sprintf(_t("View: %s"),title),
+ var dialog = new form_common.FormViewDialog(this, {
+ res_model: this.dataset.model,
+ res_id: parseInt(id).toString() == id ? parseInt(id) : id,
+ context: this.dataset.get_context(),
+ title: title,
view_id: +this.open_popup_action,
- res_id: id_cast,
- target: 'new',
- readonly:true
- });
-
- var form_controller = pop.view_form;
- form_controller.on("load_record", self, function(){
- var button_delete = _.str.sprintf("<button class='oe_button oe_bold delme'><span> %s </span></button>",_t("Delete"));
- var button_edit = _.str.sprintf("<button class='oe_button oe_bold editme oe_highlight'><span> %s </span></button>",_t("Edit Event"));
-
- pop.$el.closest(".modal").find(".modal-footer").prepend(button_delete);
- pop.$el.closest(".modal").find(".modal-footer").prepend(button_edit);
-
- $('.delme').click(
- function() {
- $('.oe_form_button_cancel').trigger('click');
- self.remove_event(id);
- }
- );
- $('.editme').click(
- function() {
- $('.oe_form_button_cancel').trigger('click');
+ readonly: true,
+ buttons: [
+ {text: _t("Edit"), classes: 'btn-primary', close: true, click: function() {
self.dataset.index = self.dataset.get_id_index(id);
self.do_switch_view('form', null, { mode: "edit" });
- }
- );
- });
+ }},
+
+ {text: _t("Delete"), close: true, click: function() {
+ self.remove_event(id);
+ }},
+
+ {text: _t("Close"), close: true}
+ ]
+ }).open();
}
return false;
},
diff --git a/addons/web_calendar/static/src/js/widgets.js b/addons/web_calendar/static/src/js/widgets.js
index 24189868bb7..09165d4d9dd 100644
--- a/addons/web_calendar/static/src/js/widgets.js
+++ b/addons/web_calendar/static/src/js/widgets.js
@@ -19,9 +19,8 @@ var QWeb = core.qweb;
* @class
* @type {*}
*/
-var QuickCreate = Widget.extend({
+var QuickCreate = Dialog.extend({
init: function(parent, dataset, buttons, options, data_template) {
- this._super(parent);
this.dataset = dataset;
this._buttons = buttons || false;
this.options = options;
@@ -29,6 +28,23 @@ var QuickCreate = Widget.extend({
// Can hold data pre-set from where you clicked on agenda
this.data_template = data_template || {};
this.$input = $();
+
+ var self = this;
+ this._super(parent, {
+ title: this.get_title(),
+ size: 'small',
+ buttons: this._buttons ? [
+ {text: _t("Create event"), classes: 'btn-primary', click: function (e) {
+ if (!self.quick_add()) {
+ self.focus();
+ }
+ }},
+ {text: _t("Edit event"), click: function (e) {
+ self.slow_add();
+ }}
+ ] : [],
+ $content: QWeb.render('CalendarView.quick_create', {widged: this})
+ });
},
get_title: function () {
var parent = this.getParent();
@@ -47,38 +63,22 @@ var QuickCreate = Widget.extend({
this.slow_create();
return;
}
- self.on('added', self, function() {
- self.trigger('close');
+ this.on('added', this, function() {
+ self.close();
});
- this.$dialog = new Dialog(this, {
- title: this.get_title(),
- size: 'small',
- buttons: this._buttons ? [
- {text: _t("Create event"), oe_link_class: 'oe_highlight', click: function (e) {
- if (!self.quick_add()) {
- self.focus();
- }
- }},
- {text: _t("Edit event"), oe_link_class: 'oe_link', click: function (e) {
- self.slow_add();
- }}
- ] : []
- }, QWeb.render('CalendarView.quick_create', {widget: this}))
- .on('closed', self, function() {
- self.trigger('close');
- })
- .open();
- this.$input = this.$dialog.$('input').keyup(function enterHandler (e) {
- if(e.keyCode == $.ui.keyCode.ENTER){
+ this.$input = this.$('input').keyup(function enterHandler (e) {
+ if(e.keyCode == $.ui.keyCode.ENTER) {
self.$input.off('keyup', enterHandler);
if (!self.quick_add()){
self.$input.on('keyup', enterHandler);
}
} else if (e.keyCode == $.ui.keyCode.ESCAPE && self._buttons) {
- self.trigger('close');
+ self.close();
}
});
+
+ return this._super();
},
focus: function() {
this.$input.focus();
@@ -140,9 +140,10 @@ var QuickCreate = Widget.extend({
});
var pop_infos = self.get_form_popup_infos();
- var pop = new form_common.FormOpenPopup(this);
var context = new data.CompoundContext(this.dataset.context, defaults);
- pop.show_element(this.dataset.model, null, this.dataset.get_context(defaults), {
+ var pop = new form_common.FormViewDialog(this, {
+ res_model: this.dataset.model,
+ context: this.dataset.get_context(defaults),
title: this.get_title(),
disable_multiple_selection: true,
view_id: pop_infos.view_id,
@@ -162,12 +163,9 @@ var QuickCreate = Widget.extend({
throw new Error(r);
}
});
- },
- });
+ }
+ }).open();
pop.on('closed', self, function() {
- // ``self.trigger('close')`` would itself destroy all child element including
- // the slow create popup, which would then re-trigger recursively the 'closed' signal.
- // Thus, here, we use a deferred and its state to cut the endless recurrence.
if (def.state() === "pending") {
def.resolve();
}
@@ -181,7 +179,8 @@ var QuickCreate = Widget.extend({
var parent = self.getParent();
parent.$calendar.fullCalendar('refetchEvents');
}
- self.trigger('close');
+ self.close();
+ self.trigger("closed");
});
return def;
},
diff --git a/addons/web_calendar/static/src/less/web_calendar.less b/addons/web_calendar/static/src/less/web_calendar.less
new file mode 100644
index 00000000000..a5c0da53d35
--- /dev/null
+++ b/addons/web_calendar/static/src/less/web_calendar.less
@@ -0,0 +1,147 @@
+
+.o_calendar_container {
+ @nb-calendar-colors: 24;
+
+ .calendar_color_loop(@index) when (@index < @nb-calendar-colors+1) {
+ .o_calendar_color_@{index} {
+ color: #0D0D0D;
+ background-color: spin(rgb(255, 192, 192), 360/(@nb-calendar-colors+1) * @index);
+ border-color: spin(rgb(255, 192, 192), 360/(@nb-calendar-colors+1) * @index);
+ opacity: 0.7;
+ }
+ .calendar_color_loop(@index + 1);
+ }
+ .calendar_color_loop(1);
+
+ .underline_color_loop(@index) when (@index < @nb-calendar-colors+1) {
+ .o_underline_color_@{index} {
+ border-bottom: 4px solid spin(rgba(255, 192, 192, 0.7), 360/(@nb-calendar-colors+1) * @index);
+ }
+ .underline_color_loop(@index + 1);
+ }
+ .underline_color_loop(1);
+
+ .o_calendar_view {
+ padding: 8px;
+
+ .o_calendar_widget {
+ background-color: @odoo-view-background-color;
+ * {
+ z-index: 0; // FIXME
+ }
+ .fc-week-number, .fc-widget-header {
+ background-color: lighten(@odoo-brand-secondary, 30%);
+ }
+ .o_attendee_head {
+ float: right;
+ margin-left: 1px;
+ width: 18px;
+ height: 18px;
+ }
+ }
+ }
+
+ .o_calendar_sidebar_container {
+ padding: 8px;
+ padding-left: 0;
+
+ .ui-datepicker {
+ width: 100%;
+ font-size: 8pt;
+ font-family: Roboto, "Nimbus Sans L";
+
+ .ui-widget-header {
+ background: none;
+ background-color: lighten(@odoo-brand-secondary, 30%);
+
+ .ui-corner-all {
+ position: static;
+ cursor: pointer;
+ text-align: center;
+ &:hover {
+ color: @odoo-view-background-color;
+ background: none;
+ background-color: @odoo-brand-secondary;
+ border: none;
+ text-decoration: none;
+ }
+ .ui-icon {
+ display: none;
+ }
+ }
+ .ui-datepicker-prev {
+ float: left;
+ &::after {
+ font-family: FontAwesome;
+ content: "";
+ }
+ }
+ .ui-datepicker-next {
+ float: right;
+ &::before {
+ font-family: FontAwesome;
+ content: "";
+ }
+ }
+ }
+ table {
+ td {
+ padding: 0 2px 2px 0;
+ background-color: @odoo-view-background-color;
+ a {
+ border: none;
+ background: none;
+ background-color: lighten(@odoo-brand-secondary, 40%);
+ }
+ }
+ .ui-state-default {
+ color: @odoo-brand-primary;
+ &:hover {
+ background: none;
+ background-color: fade(@odoo-brand-primary, 50%);
+ border-color: @odoo-brand-primary;
+ color: @odoo-view-background-color;
+ };
+ }
+ .ui-state-active {
+ background: none;
+ background-color: @odoo-brand-primary;
+ color: @odoo-view-background-color;
+ }
+ }
+ }
+ .o_calendar_filter {
+ padding: 8px;
+ background: @odoo-view-background-color;
+ }
+ .o_cal_avatar {
+ height: 24px;
+ width: 24px;
+ }
+ }
+}
+
+.o_calendar_invitation {
+ display: inline-block;
+ width: 10px;
+ height: 10px;
+ border-radius: 5px;
+
+ &.accepted {
+ background-color: @brand-success; // FIXME brand-success in green badge ...
+ }
+
+ &.needsAction {
+ background-color: @odoo-brand-secondary;
+ }
+}
+
+.o-dashboard {
+ .o_calendar_container .o_calendar_sidebar_container {
+ display: none;
+ }
+
+ .o_calendar_container .o_calendar_view {
+ width: 100%;
+ }
+}
diff --git a/addons/web_diagram/static/src/js/diagram.js b/addons/web_diagram/static/src/js/diagram.js
index 285991e29b2..8fdcf077b38 100644
--- a/addons/web_diagram/static/src/js/diagram.js
+++ b/addons/web_diagram/static/src/js/diagram.js
@@ -241,54 +241,45 @@ var DiagramView = View.extend({
edit_node: function(node_id){
var self = this;
var title = _t('Activity');
- var pop = new form_common.FormOpenPopup(self);
-
- pop.show_element(
- self.node,
- node_id,
- self.context || self.dataset.context,
- {
- title: _t("Open: ") + title
- }
- );
+ var pop = new form_common.FormViewDialog(self, {
+ res_model: self.node,
+ res_id: node_id,
+ context: self.context || self.dataset.context,
+ title: _t("Open: ") + title
+ }).open();
pop.on('write_completed', self, function() {
self.dataset.read_index(_.keys(self.fields_view.fields)).then(self.on_diagram_loaded);
- });
+ });
var form_fields = [self.parent_field];
var form_controller = pop.view_form;
- form_controller.on("load_record", self, function(){
+ form_controller.on("load_record", self, function(){
_.each(form_fields, function(fld) {
if (!(fld in form_controller.fields)) { return; }
var field = form_controller.fields[fld];
field.$input.prop('disabled', true);
field.$drop_down.unbind();
});
- });
-
-
+ });
},
// Creates a popup to add a node to the diagram
add_node: function(){
var self = this;
var title = _t('Activity');
- var pop = new form_common.SelectCreatePopup(self);
- pop.select_element(
- self.node,
- {
- title: _t("Create:") + title,
- initial_view: 'form',
- disable_multiple_selection: true
- },
- self.dataset.domain,
- self.context || self.dataset.context
- );
- pop.on("elements_selected", self, function(element_ids) {
- self.dataset.read_index(_.keys(self.fields_view.fields)).then(self.on_diagram_loaded);
- });
+ var pop = new form_common.SelectCreateDialog(self, {
+ res_model: self.node,
+ domain: self.dataset.domain,
+ context: self.context || self.dataset.context,
+ title: _t("Create:") + title,
+ initial_view: 'form',
+ disable_multiple_selection: true,
+ on_selected: function(element_ids) {
+ self.dataset.read_index(_.keys(self.fields_view.fields)).then(self.on_diagram_loaded);
+ }
+ }).open();
var form_controller = pop.view_form;
var form_fields = [this.parent_field];
@@ -307,15 +298,12 @@ var DiagramView = View.extend({
edit_connector: function(connector_id){
var self = this;
var title = _t('Transition');
- var pop = new form_common.FormOpenPopup(self);
- pop.show_element(
- self.connector,
- parseInt(connector_id,10), //FIXME Isn't connector_id supposed to be an int ?
- self.context || self.dataset.context,
- {
- title: _t("Open: ") + title
- }
- );
+ var pop = new form_common.FormViewDialog(self, {
+ res_model: self.connector,
+ res_id: parseInt(connector_id, 10), //FIXME Isn't connector_id supposed to be an int ?
+ context: self.context || self.dataset.context,
+ title: _t("Open: ") + title
+ }).open();
pop.on('write_completed', self, function() {
self.dataset.read_index(_.keys(self.fields_view.fields)).then(self.on_diagram_loaded);
});
@@ -326,21 +314,18 @@ var DiagramView = View.extend({
add_connector: function(node_source_id, node_dest_id, dummy_cuteedge){
var self = this;
var title = _t('Transition');
- var pop = new form_common.SelectCreatePopup(self);
-
- pop.select_element(
- self.connector,
- {
- title: _t("Create:") + title,
- initial_view: 'form',
- disable_multiple_selection: true
- },
- this.dataset.domain,
- this.context || this.dataset.context
- );
- pop.on("elements_selected", self, function(element_ids) {
- self.dataset.read_index(_.keys(self.fields_view.fields)).then(self.on_diagram_loaded);
- });
+ var pop = new form_common.SelectCreateDialog(self, {
+ res_model: self.connector,
+ domain: this.dataset.domain,
+ context: this.context || this.dataset.context,
+ title: _t("Create:") + title,
+ initial_view: 'form',
+ disable_multiple_selection: true,
+ on_selected: function(element_ids) {
+ self.dataset.read_index(_.keys(self.fields_view.fields)).then(self.on_diagram_loaded);
+ }
+ }).open();
+
// We want to destroy the dummy edge after a creation cancel. This destroys it even if we save the changes.
// This is not a problem since the diagram is completely redrawn on saved changes.
pop.$el.parents('.modal').on('hidden.bs.modal', function (e){
@@ -350,14 +335,12 @@ var DiagramView = View.extend({
});
var form_controller = pop.view_form;
-
-
- form_controller.on("load_record", self, function(){
+ form_controller.on("load_record", self, function(){
form_controller.fields[self.connectors.attrs.source].set_value(node_source_id);
form_controller.fields[self.connectors.attrs.source].dirty = true;
form_controller.fields[self.connectors.attrs.destination].set_value(node_dest_id);
form_controller.fields[self.connectors.attrs.destination].dirty = true;
- });
+ });
},
/**
diff --git a/addons/web_gantt/static/src/js/gantt.js b/addons/web_gantt/static/src/js/gantt.js
index ed9a49fa8c1..556167f7229 100644
--- a/addons/web_gantt/static/src/js/gantt.js
+++ b/addons/web_gantt/static/src/js/gantt.js
@@ -237,28 +237,20 @@ var GanttView = View.extend({
this.dataset.write(itask.id, data);
},
on_task_display: function(task) {
- var self = this;
- var pop = new form_common.FormOpenPopup(self);
- pop.on('write_completed',self,self.reload);
- pop.show_element(
- self.dataset.model,
- task.id,
- null,
- {}
- );
+ var pop = new form_common.FormViewDialog(this, {
+ res_model: this.dataset.model,
+ res_id: task.id,
+ }).open();
+ pop.on('write_completed', this, this.reload);
},
on_task_create: function() {
var self = this;
- var pop = new form_common.SelectCreatePopup(this);
- pop.on("elements_selected", self, function() {
- self.reload();
- });
- pop.select_element(
- self.dataset.model,
- {
- initial_view: "form",
+ new form_common.FormViewDialog(this, {
+ res_model: self.dataset.model,
+ on_selected: function() {
+ self.reload();
}
- );
+ }).open();
},
});
diff --git a/addons/web_view_editor/static/src/js/view_editor.js b/addons/web_view_editor/static/src/js/view_editor.js
index 16013e1b031..d45216ed19a 100644
--- a/addons/web_view_editor/static/src/js/view_editor.js
+++ b/addons/web_view_editor/static/src/js/view_editor.js
@@ -72,10 +72,10 @@ var ViewEditor = Widget.extend({
{text: _t("Create"), click: function() { self.on_create_view(); }},
{text: _t("Edit"), click: function() { self.xml_element_id = 0; self.get_arch(); }},
{text: _t("Remove"), click: function() { self.do_delete_view(); }},
- {text: _t("Close"), click: function() { self.view_edit_dialog.close(); window.location.reload(); }}
+ {text: _t("Close"), click: function() { window.location.reload(); }, close: true}
]
}).open();
- this.view_edit_dialog.on("closing", this, function(){window.location.reload();});
+ this.view_edit_dialog.on("closed", this, function(){window.location.reload();});
this.main_view_id = this.parent.fields_view.view_id;
this.action_manager = new ActionManager(this);
this.action_manager.appendTo(this.view_edit_dialog.$el);