summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
authorFrederic van der Essen <fva@openerp.com / fvdessen+o@gmail.com>2014-08-25 16:42:57 +0200
committerFrederic van der Essen <fva@openerp.com / fvdessen+o@gmail.com>2014-08-25 16:42:57 +0200
commitd7f93defb899b2b48a14d679e5dffffdb4a00eff (patch)
treef8572183b480477622917a1f504cf49a8e202f6e /addons/web/static/src
parent2b67528fe9e366829d44d8aba756bc6e359b4c61 (diff)
parent36146b3fadc47543f4b696ab75c31b3459afb15b (diff)
Merge branch 'master' into master-pos-new-payment-screen-fva
Conflicts: addons/point_of_sale/point_of_sale.py addons/point_of_sale/point_of_sale_view.xml
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/css/base.css33
-rw-r--r--addons/web/static/src/css/base.sass29
-rw-r--r--addons/web/static/src/js/chrome.js30
-rw-r--r--addons/web/static/src/js/core.js19
-rw-r--r--addons/web/static/src/js/data_export.js16
-rw-r--r--addons/web/static/src/js/formats.js48
-rw-r--r--addons/web/static/src/js/search.js1
-rw-r--r--addons/web/static/src/js/tour.js84
-rw-r--r--addons/web/static/src/js/view_form.js118
-rw-r--r--addons/web/static/src/js/view_list.js1
-rw-r--r--addons/web/static/src/js/views.js8
-rw-r--r--addons/web/static/src/xml/base.xml27
12 files changed, 260 insertions, 154 deletions
diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css
index b76bee29a59..06b1e844792 100644
--- a/addons/web/static/src/css/base.css
+++ b/addons/web/static/src/css/base.css
@@ -8,6 +8,7 @@
font-weight: normal;
font-style: normal;
}
+
@font-face {
font-family: "EntypoRegular";
src: url("/web/static/src/font/entypo-webfont.eot") format("eot");
@@ -18,6 +19,7 @@
font-weight: normal;
font-style: normal;
}
+
#oe_main_menu_navbar {
min-height: 34px;
z-index: 1001;
@@ -134,7 +136,6 @@
vertical-align: top;
}
.openerp .oe_title {
- width: 38%;
float: left;
}
.openerp .oe_title:after {
@@ -369,6 +370,16 @@
.openerp .oe_form_dirty button.oe_highlight_on_dirty:hover {
background: #ed6f6a;
}
+.openerp .oe_warning_redirect {
+ border: none !important;
+ padding: 0 !important;
+ margin-left: 20px !important;
+ background: #f5f7f9 !important;
+ box-shadow: none !important;
+}
+.openerp .oe_warning_redirect:hover {
+ text-decoration: underline !important;
+}
.openerp .oe_stat_button {
font-weight: normal;
width: 132px !important;
@@ -407,16 +418,6 @@
display: inline;
vertical-align: middle;
}
-.openerp .oe_warning_redirect {
- border: none !important;
- padding: 0 !important;
- margin-left: 20px !important;
- background: #f5f7f9 !important;
- box-shadow: none !important;
-}
-.openerp .oe_warning_redirect:hover {
- text-decoration: underline !important;
-}
.openerp .oe_stat_button:hover {
background: #7c7bad;
color: white;
@@ -583,9 +584,10 @@
height: 16px;
}
.openerp .oe_form_field_radio.oe_vertical label {
- margin-left: 4px;
+ display: inline-block;
+ margin-left: 20px;
}
-.openerp .oe_form_field_radio.oe_form_required .oe_radio_input {
+.openerp .oe_form_field_radio .oe_radio_input {
border: 2px solid transparent;
display: inline-block;
height: 12px;
@@ -593,6 +595,7 @@
vertical-align: top;
border-radius: 10px;
margin: 1px 0;
+ position: absolute;
}
.openerp .oe_form_field_radio.oe_form_required.oe_form_invalid .oe_radio_input {
border-color: red;
@@ -2147,9 +2150,6 @@
.openerp .oe_form .oe_form_field_boolean {
width: auto;
}
-.openerp .oe_form .oe_datepicker_container {
- display: none;
-}
.openerp .oe_form .oe_datepicker_root {
display: inline-block;
}
@@ -3001,6 +3001,7 @@
top: 0px;
}
}
+
.kitten-mode-activated {
background-size: cover;
background-attachment: fixed;
diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass
index f1f948170e5..38e3ebf40ce 100644
--- a/addons/web/static/src/css/base.sass
+++ b/addons/web/static/src/css/base.sass
@@ -239,8 +239,7 @@ $sheet-padding: 16px
td
vertical-align: top
.oe_title
- width: 38%
- float: left
+ float: left
.oe_title:after
content: "."
display: block
@@ -529,19 +528,19 @@ $sheet-padding: 16px
height: 16px
&.oe_vertical
label
- margin-left: 4px
- &.oe_form_required
- .oe_radio_input
- border: 2px solid transparent
display: inline-block
- height: 12px
- width: 12px
- vertical-align: top
- border-radius: 10px
- margin: 1px 0
- &.oe_form_invalid
- .oe_radio_input
- border-color: red
+ margin-left: 20px
+ .oe_radio_input
+ border: 2px solid transparent
+ display: inline-block
+ height: 12px
+ width: 12px
+ vertical-align: top
+ border-radius: 10px
+ margin: 1px 0
+ position: absolute
+ &.oe_form_required.oe_form_invalid .oe_radio_input
+ border-color: red
.oe_tags
&.oe_inline
min-width: 250px
@@ -1762,8 +1761,6 @@ $sheet-padding: 16px
white-space: nowrap
.oe_form_field_boolean
width: auto
- .oe_datepicker_container
- display: none
.oe_datepicker_root
display: inline-block
.oe_form_required
diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js
index f5f8129d502..608f76cd6ca 100644
--- a/addons/web/static/src/js/chrome.js
+++ b/addons/web/static/src/js/chrome.js
@@ -115,6 +115,7 @@ instance.web.Dialog = instance.web.Widget.extend({
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_modal.push(this.$dialog_box);
return this;
@@ -185,12 +186,12 @@ instance.web.Dialog = instance.web.Widget.extend({
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
- this.trigger("closing", reason);
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);
}
},
_closing: function() {
@@ -230,6 +231,9 @@ instance.web.Dialog = instance.web.Widget.extend({
if (opened_modal.length > 0){
//we still have other opened modal so we should focus it
opened_modal[opened_modal.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);
}
@@ -252,7 +256,7 @@ instance.web.CrashManager = instance.web.Class.extend({
return;
}
if (error.data.name === "openerp.http.SessionExpiredException" || error.data.name === "werkzeug.exceptions.Forbidden") {
- this.show_warning({type: "Session Expired", data: { message: _t("Your OpenERP session expired. Please refresh the current web page.") }});
+ this.show_warning({type: "Session Expired", data: { message: _t("Your Odoo session expired. Please refresh the current web page.") }});
return;
}
if (error.data.exception_type === "except_osv" || error.data.exception_type === "warning" || error.data.exception_type === "access_error") {
@@ -270,7 +274,7 @@ instance.web.CrashManager = instance.web.Class.extend({
}
new instance.web.Dialog(this, {
size: 'medium',
- title: "OpenERP " + (_.str.capitalize(error.type) || "Warning"),
+ title: "Odoo " + (_.str.capitalize(error.type) || "Warning"),
buttons: [
{text: _t("Ok"), click: function() { this.parents('.modal').modal('hide'); }}
],
@@ -285,7 +289,7 @@ instance.web.CrashManager = instance.web.Class.extend({
this.parents('.modal').modal('hide');
};
new instance.web.Dialog(this, {
- title: "OpenERP " + _.str.capitalize(error.type),
+ title: "Odoo " + _.str.capitalize(error.type),
buttons: buttons
}, QWeb.render('CrashManager.error', {session: instance.session, error: error})).open();
},
@@ -337,7 +341,7 @@ instance.web.RedirectWarningHandler = instance.web.Dialog.extend(instance.web.Ex
new instance.web.Dialog(this, {
size: 'medium',
- title: "OpenERP " + (_.str.capitalize(error.type) || "Warning"),
+ title: "Odoo " + (_.str.capitalize(error.type) || "Warning"),
buttons: [
{text: _t("Ok"), click: function() { self.$el.parents('.modal').modal('hide'); self.destroy();}},
{text: error.data.arguments[2],
@@ -910,7 +914,7 @@ instance.web.Menu = instance.web.Widget.extend({
}
// add a tooltip to cropped menu items
this.$secondary_menus.find('.oe_secondary_submenu li a span').each(function() {
- $(this).tooltip(this.scrollWidth > this.clientWidth ? {title: $(this).text().trim(), placement: 'auto right'} :'destroy');
+ $(this).tooltip(this.scrollWidth > this.clientWidth ? {title: $(this).text().trim(), placement: 'right'} :'destroy');
});
},
/**
@@ -1156,12 +1160,19 @@ instance.web.Client = instance.web.Widget.extend({
}, 0);
});
instance.web.bus.on('click', this, function(ev) {
- $.fn.tooltip('destroy');
+ $('.tooltip').remove();
if (!$(ev.target).is('input[type=file]')) {
self.$el.find('.oe_dropdown_menu.oe_opened, .oe_dropdown_toggle.oe_opened').removeClass('oe_opened');
}
});
},
+ on_logo_click: function(ev){
+ if (!this.has_uncommitted_changes()) {
+ return;
+ } else {
+ ev.preventDefault();
+ }
+ },
show_common: function() {
var self = this;
this.crashmanager = new instance.web.CrashManager();
@@ -1190,7 +1201,7 @@ instance.web.WebClient = instance.web.Client.extend({
this._current_state = null;
this.menu_dm = new instance.web.DropMisordered();
this.action_mutex = new $.Mutex();
- this.set('title_part', {"zopenerp": "OpenERP"});
+ this.set('title_part', {"zopenerp": "Odoo"});
},
start: function() {
var self = this;
@@ -1266,6 +1277,9 @@ instance.web.WebClient = instance.web.Client.extend({
self.logo_edit(ev);
});
+ this.$('.oe_logo img').click(function(ev) {
+ self.on_logo_click(ev);
+ });
// Menu is rendered server-side thus we don't want the widget to create any dom
self.menu = new instance.web.Menu(self);
self.menu.setElement(this.$el.parents().find('.oe_application_menu_placeholder'));
diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js
index 23645e22bf1..169547d78c0 100644
--- a/addons/web/static/src/js/core.js
+++ b/addons/web/static/src/js/core.js
@@ -311,9 +311,8 @@ instance.web.Session.include( /** @lends instance.web.Session# */{
self.module_list = all_modules;
var loaded = self.load_translations();
- var datejs_locale = "/web/static/lib/datejs/globalization/" + self.user_context.lang.replace("_", "-") + ".js";
-
- var file_list = [ datejs_locale ];
+ var locale = "/web/webclient/locale/" + self.user_context.lang || 'en_US';
+ var file_list = [ locale ];
if(to_load.length) {
loaded = $.when(
loaded,
@@ -772,7 +771,7 @@ instance.web.unblockUI = function() {
/* Bootstrap defaults overwrite */
$.fn.tooltip.Constructor.DEFAULTS.placement = 'auto top';
$.fn.tooltip.Constructor.DEFAULTS.html = true;
-$.fn.tooltip.Constructor.DEFAULTS.container = 'body';
+$.fn.tooltip.Constructor.DEFAULTS.trigger = 'hover focus click';
//overwrite bootstrap tooltip method to prevent showing 2 tooltip at the same time
var bootstrap_show_function = $.fn.tooltip.Constructor.prototype.show;
$.fn.tooltip.Constructor.prototype.show = function () {
@@ -786,6 +785,18 @@ $.fn.tooltip.Constructor.prototype.show = function () {
if (e.isDefaultPrevented() || !inDom) return;
return bootstrap_show_function.call(this);
};
+//overwrite bootstrap tooltip init method in order to check if tooltip is in a modal or not and
+//if so it needs to have a container body in order to be visible
+var bootstrap_init_tooltip_fnct = $.fn.tooltip.Constructor.prototype.init;
+$.fn.tooltip.Constructor.prototype.init = function (type, element, options) {
+ options = options || {}
+ if ($('.modal[aria-hidden="false"]').length !== 0){
+ if (options && !options.container){
+ options = _.extend({container: 'body'},options);
+ }
+ }
+ return bootstrap_init_tooltip_fnct.call(this, type, element, options);
+}
/**
* Registry for all the client actions key: tag value: widget
diff --git a/addons/web/static/src/js/data_export.js b/addons/web/static/src/js/data_export.js
index 2f7ff81d089..a6cb35423fb 100644
--- a/addons/web/static/src/js/data_export.js
+++ b/addons/web/static/src/js/data_export.js
@@ -27,6 +27,8 @@ instance.web.DataExport = instance.web.Dialog.extend({
this.$('#fields_list').empty();
},
'click #export_new_list': 'on_show_save_list',
+ 'click #move_up':'on_click_move_up',
+ 'click #move_down':'on_click_move_down',
},
init: function(parent, dataset) {
var self = this;
@@ -79,6 +81,20 @@ instance.web.DataExport = instance.web.Dialog.extend({
this.rpc('/web/export/formats', {}).done(this.do_setup_export_formats),
this.show_exports_list());
},
+ on_click_move_up: function () {
+ var prev_row = this.$el.find('#fields_list option:selected').first().prev();
+ if(prev_row.length){
+ var selected_rows = self.$('#fields_list option:selected').detach();
+ prev_row.before(selected_rows);
+ }
+ },
+ on_click_move_down: function () {
+ var next_row = this.$el.find('#fields_list option:selected').last().next();
+ if(next_row.length){
+ var selected_rows = self.$('#fields_list option:selected').detach();
+ next_row.after(selected_rows);
+ }
+ },
do_setup_export_formats: function (formats) {
var $fmts = this.$el.find('#export_format');
_(formats).each(function (format) {
diff --git a/addons/web/static/src/js/formats.js b/addons/web/static/src/js/formats.js
index 3d7b574e56a..14026f17681 100644
--- a/addons/web/static/src/js/formats.js
+++ b/addons/web/static/src/js/formats.js
@@ -361,4 +361,52 @@ instance.web.round_decimals = function(value, decimals){
return instance.web.round_precision(value, Math.pow(10,-decimals));
};
+/**
++ *
++ * convert python.strftime format into moment.js format
++ * inspired from : https://github.com/uruz/moment-datetime/blob/master/moment-datetime.js
++*/
+instance.web.convert_to_moment_format = function(format){
+ if (!format)
+ return false;
+ var replacements = {
+ 'a': 'ddd',
+ 'A': 'dddd',
+ 'b': 'MMM',
+ 'B': 'MMMM',
+ //'c': //%c is defined too vaguely
+ 'd': 'DD',
+ //'f': JS have no support for microseconds and moment.js have no support for milliseconds
+ 'H': 'HH',
+ 'I': 'hh',
+ 'j': 'DDDD',
+ 'm': 'MM',
+ 'M': 'mm',
+ 'p': 'A',
+ 'S': 'ss',
+ 'U': 'ww',//ww is for Sunday-based week
+ 'w': 'd',
+ //'W': 'ww',//%W is weeknumber for weeks starting from Monday and it is not implemented in moment.js
+ //'x':
+ //'X': //%x and %X are defined too vaguely to be implemented
+ 'y': 'YY',
+ 'Y': 'YYYY',
+ 'z': 'ZZ',
+ //'Z': 'z', - moment.js does not support timezone names
+ '%': '%'
+ }
+ var moment_format = '', directive_index = 0, replacement, unformatted;
+ while (format.indexOf('%') !== -1){
+ directive_index = format.indexOf('%') + 1;
+ replacement = replacements[format[directive_index]];
+ unformatted = format.substr(0, directive_index-1);
+ if (unformatted.length){
+ unformatted = '[' + unformatted.replace(/(\[|\])/g, '\\$&') +']';
+ }
+ moment_format += unformatted + (replacement ? replacement : format[directive_index]);
+ format = format.substr(directive_index+1);
+ }
+ return moment_format;
+};
+
})();
diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js
index 1bfdc86fb5a..566179c2a38 100644
--- a/addons/web/static/src/js/search.js
+++ b/addons/web/static/src/js/search.js
@@ -782,6 +782,7 @@ instance.web.SearchViewDrawer = instance.web.Widget.extend({
start: function() {
var self = this;
+ if (this.searchview.headless) return $.when(this._super(), this.searchview.ready);
var filters_ready = this.searchview.fields_view_get
.then(this.proxy('prepare_filters'));
return $.when(this._super(), filters_ready).then(function () {
diff --git a/addons/web/static/src/js/tour.js b/addons/web/static/src/js/tour.js
index fec189e06f5..0179d3eda65 100644
--- a/addons/web/static/src/js/tour.js
+++ b/addons/web/static/src/js/tour.js
@@ -329,18 +329,22 @@ var Tour = {
}
console.log(message);
},
- error: function (step, message) {
+ logError: function (step, message, all) {
var state = Tour.getState();
- message += '\n tour: ' + state.id
- + (step ? '\n step: ' + step.id + ": '" + (step._title || step.title) + "'" : '' )
- + '\n href: ' + window.location.href
- + '\n referrer: ' + document.referrer
- + (step ? '\n element: ' + Boolean(!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden"))) : '' )
- + (step ? '\n waitNot: ' + Boolean(!step.waitNot || !$(step.waitNot).size()) : '' )
- + (step ? '\n waitFor: ' + Boolean(!step.waitFor || $(step.waitFor).size()) : '' )
- + "\n localStorage: " + JSON.stringify(localStorage)
- + '\n\n' + $("body").html();
+ message += '\ntour: ' + state.id
+ + (step ? '\nstep: ' + step.id + ": '" + (step._title || step.title) + "'" : '' )
+ + (all ? '\nhref: ' + window.location.href : '' )
+ + (all ? '\nreferrer: ' + document.referrer : '' )
+ + (step ? '\nelement: ' + Boolean(!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden"))) : '' )
+ + (step ? '\nwaitNot: ' + Boolean(!step.waitNot || !$(step.waitNot).size()) : '' )
+ + (step ? '\nwaitFor: ' + Boolean(!step.waitFor || $(step.waitFor).size()) : '' )
+ + (all ? "\nlocalStorage: " + JSON.stringify(localStorage) : '' )
+ + (all ? '\n\n' + $("body").html() : '' );
Tour.log(message, true);
+ },
+ error: function (step, message) {
+ var state = Tour.getState();
+ Tour.logError(step, "Error: " + message, true);
Tour.endTour();
},
lists: function () {
@@ -403,7 +407,7 @@ var Tour = {
var state = Tour.getState();
var time = new Date().getTime();
var timer;
- var next = state.tour.steps[state.step.id+1];
+ var next = state.step.next ? Tour.search_step(state.step.next) : state.tour.steps[state.step.id+1];
var overlaps = state.mode === "test" ? Tour.errorDelay : 0;
window.onbeforeunload = function () {
@@ -418,20 +422,65 @@ var Tour = {
clearTimeout(Tour.timer);
if (Tour.check(next)) {
+
clearTimeout(Tour.currentTimer);
// use an other timeout for cke dom loading
Tour.saveState(state.id, state.mode, state.step.id, 0);
setTimeout(function () {
+ if (state.step.onend && Tour._goto(state.step.onend())) return;
Tour.nextStep(next);
}, Tour.defaultDelay);
+ return;
+
} else if (!overlaps || new Date().getTime() - time < overlaps) {
+
Tour.timer = setTimeout(checkNext, Tour.defaultDelay);
- } else {
- return Tour.error(next, "Can't reach the next step");
+ return;
+
+ } else if(next.onerror) {
+
+ Tour.logError(next, "Error: Can't reach the next step (call next step onerror)", false);
+ var id = next.onerror();
+ if (id) {
+ if (Tour._goto(id)) return;
+ if (id === true) {
+ Tour.nextStep(next);
+ return;
+ }
+ }
+
}
+
+ Tour.error(next, "Can't reach the next step");
+ return;
+
}
setTimeout(checkNext, 0);
},
+ search_step: function (id_or_title) {
+ var state = Tour.getState();
+ if (id_or_title !== undefined) {
+ if (isNaN(id_or_title)) {
+ for (var k=0; k<state.tour.steps.length; k++) {
+ if (state.tour.steps[k].title === id_or_title || state.tour.steps[k]._title === id_or_title) {
+ return state.tour.steps[k];
+ }
+ }
+ } else {
+ return state.tour.steps[id_or_title];
+ }
+ }
+ return undefined;
+ },
+ _goto: function (id_or_title) {
+ var state = Tour.getState();
+ if (!state) return true;
+ if (id_or_title === undefined) return false;
+ var step = Tour.search_step(id_or_title);
+ Tour.saveState(state.id, state.mode, step.id, 0);
+ Tour.nextStep(Tour.getState().step);
+ return true;
+ },
nextStep: function (step) {
var state = Tour.getState();
@@ -440,7 +489,7 @@ var Tour = {
}
step = step || state.step;
- var next = state.tour.steps[step.id+1];
+ var next = state.step.next ? Tour.search_step(state.step.next) : state.tour.steps[step.id+1];
if (state.mode === "test" && state.number > 3) {
return Tour.error(next, "Cycling. Can't reach the next step");
@@ -448,14 +497,15 @@ var Tour = {
Tour.saveState(state.id, state.mode, step.id, state.number);
- if (step.id !== state.step_id) {
+ if (state.number === 1) {
Tour.log("Tour '"+state.id+"' Step: '" + (step._title || step.title) + "' (" + (new Date().getTime() - this.time) + "ms)");
}
Tour.autoTogglePopover(true);
- if (step.onload) {
- step.onload();
+ // onload a step you can fallback to an other step
+ if (step.onload && Tour._goto(step.onload())) {
+ return;
}
if (state.mode === "test") {
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index 5767ffe5489..93ebc8b8167 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -302,6 +302,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
opacity: '1',
filter: 'alpha(opacity = 100)'
});
+ instance.web.bus.trigger('form_view_shown', self);
});
},
do_hide: function () {
@@ -705,6 +706,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
if (menu) {
menu.do_reload_needaction();
}
+ instance.web.bus.trigger('form_view_saved', self);
});
}).always(function(){
$(e.target).attr("disabled", false);
@@ -1835,7 +1837,6 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi
trigger = trigger || this.$el;
options = _.extend({
delay: { show: 500, hide: 0 },
- trigger: 'hover',
title: function() {
var template = widget.template + '.tooltip';
if (!QWeb.has_template(template)) {
@@ -2577,10 +2578,10 @@ instance.web.form.FieldCharDomain = instance.web.form.AbstractField.extend(insta
instance.web.DateTimeWidget = instance.web.Widget.extend({
template: "web.datepicker",
- jqueryui_object: 'datetimepicker',
type_of_date: "datetime",
events: {
- 'change .oe_datepicker_master': 'change_datetime',
+ 'dp.change .oe_datepicker_main': 'change_datetime',
+ 'dp.show .oe_datepicker_main': 'set_datetime_default',
'keypress .oe_datepicker_master': 'change_datetime',
},
init: function(parent) {
@@ -2589,82 +2590,32 @@ instance.web.DateTimeWidget = instance.web.Widget.extend({
},
start: function() {
var self = this;
+ var l10n = _t.database.parameters;
+ var options = {
+ pickTime: true,
+ useSeconds: true,
+ startDate: new moment({ y: 1900 }),
+ endDate: new moment().add(200, "y"),
+ calendarWeeks: true,
+ icons : {
+ time: 'fa fa-clock-o',
+ date: 'fa fa-calendar',
+ up: 'fa fa-chevron-up',
+ down: 'fa fa-chevron-down'
+ },
+ language : moment.locale(),
+ format : instance.web.convert_to_moment_format(l10n.date_format +' '+ l10n.time_format),
+ };
this.$input = this.$el.find('input.oe_datepicker_master');
- this.$input_picker = this.$el.find('input.oe_datepicker_container');
-
- $.datepicker.setDefaults({
- clearText: _t('Clear'),
- clearStatus: _t('Erase the current date'),
- closeText: _t('Done'),
- closeStatus: _t('Close without change'),
- prevText: _t('<Prev'),
- prevStatus: _t('Show the previous month'),
- nextText: _t('Next>'),
- nextStatus: _t('Show the next month'),
- currentText: _t('Today'),
- currentStatus: _t('Show the current month'),
- monthNames: Date.CultureInfo.monthNames,
- monthNamesShort: Date.CultureInfo.abbreviatedMonthNames,
- monthStatus: _t('Show a different month'),
- yearStatus: _t('Show a different year'),
- weekHeader: _t('Wk'),
- weekStatus: _t('Week of the year'),
- dayNames: Date.CultureInfo.dayNames,
- dayNamesShort: Date.CultureInfo.abbreviatedDayNames,
- dayNamesMin: Date.CultureInfo.shortestDayNames,
- dayStatus: _t('Set DD as first week day'),
- dateStatus: _t('Select D, M d'),
- firstDay: Date.CultureInfo.firstDayOfWeek,
- initStatus: _t('Select a date'),
- isRTL: false
- });
- $.timepicker.setDefaults({
- timeOnlyTitle: _t('Choose Time'),
- timeText: _t('Time'),
- hourText: _t('Hour'),
- minuteText: _t('Minute'),
- secondText: _t('Second'),
- currentText: _t('Now'),
- closeText: _t('Done')
- });
-
- this.picker({
- onClose: this.on_picker_select,
- onSelect: this.on_picker_select,
- changeMonth: true,
- changeYear: true,
- showWeek: true,
- showButtonPanel: true,
- firstDay: Date.CultureInfo.firstDayOfWeek
- });
- // Some clicks in the datepicker dialog are not stopped by the
- // datepicker and "bubble through", unexpectedly triggering the bus's
- // click event. Prevent that.
- this.picker('widget').click(function (e) { e.stopPropagation(); });
-
- this.$el.find('img.oe_datepicker_trigger').click(function() {
- if (self.get("effective_readonly") || self.picker('widget').is(':visible')) {
- self.$input.focus();
- return;
- }
- self.picker('setDate', self.get('value') ? instance.web.auto_str_to_date(self.get('value')) : new Date());
- self.$input_picker.show();
- self.picker('show');
- self.$input_picker.hide();
- });
+ if (this.type_of_date === 'date') {
+ options['pickTime'] = false;
+ options['useSeconds'] = false;
+ options['format'] = instance.web.convert_to_moment_format(l10n.date_format);
+ }
+ this.picker = this.$('.oe_datepicker_main').datetimepicker(options);
this.set_readonly(false);
this.set({'value': false});
},
- picker: function() {
- return $.fn[this.jqueryui_object].apply(this.$input_picker, arguments);
- },
- on_picker_select: function(text, instance_) {
- var date = this.picker('getDate');
- this.$input
- .val(date ? this.format_client(date) : '')
- .change()
- .focus();
- },
set_value: function(value_) {
this.set({'value': value_});
this.$input.val(value_ ? this.format_client(value_) : '');
@@ -2674,12 +2625,11 @@ instance.web.DateTimeWidget = instance.web.Widget.extend({
},
set_value_from_ui_: function() {
var value_ = this.$input.val() || false;
- this.set({'value': this.parse_client(value_)});
+ this.set_value(this.parse_client(value_));
},
set_readonly: function(readonly) {
this.readonly = readonly;
this.$input.prop('readonly', this.readonly);
- this.$el.find('img.oe_datepicker_trigger').toggleClass('oe_input_icon_disabled', readonly);
},
is_valid_: function() {
var value_ = this.$input.val();
@@ -2700,6 +2650,17 @@ instance.web.DateTimeWidget = instance.web.Widget.extend({
format_client: function(v) {
return instance.web.format_value(v, {"widget": this.type_of_date});
},
+ set_datetime_default: function(){
+ //when opening datetimepicker the date and time by default should be the one from
+ //the input field if any or the current day otherwise
+ if (this.type_of_date === 'datetime') {
+ value = new moment().second(0);
+ if (this.$input.val().length !== 0 && this.is_valid_()){
+ var value = this.$input.val();
+ }
+ this.$('.oe_datepicker_main').data('DateTimePicker').setValue(value);
+ }
+ },
change_datetime: function(e) {
if ((e.type !== "keypress" || e.which === 13) && this.is_valid_()) {
this.set_value_from_ui_();
@@ -2712,7 +2673,6 @@ instance.web.DateTimeWidget = instance.web.Widget.extend({
});
instance.web.DateWidget = instance.web.DateTimeWidget.extend({
- jqueryui_object: 'datepicker',
type_of_date: "date"
});
@@ -3161,9 +3121,9 @@ instance.web.form.FieldRadio = instance.web.form.AbstractField.extend(instance.w
this._super(field_manager, node);
this.selection = _.clone(this.field.selection) || [];
this.domain = false;
+ this.uniqueId = _.uniqueId("radio");
},
initialize_content: function () {
- this.uniqueId = _.uniqueId("radio");
this.on("change:effective_readonly", this, this.render_value);
this.field_manager.on("view_content_has_changed", this, this.get_selection);
this.get_selection();
diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js
index 9a192e4db90..fca5dd4f969 100644
--- a/addons/web/static/src/js/view_list.js
+++ b/addons/web/static/src/js/view_list.js
@@ -1623,6 +1623,7 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we
self.setup_resequence_rows(list, dataset);
}).always(function() {
if (post_render) { post_render(); }
+ self.view.trigger('view_list_rendered');
});
});
return $el;
diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js
index 8a6c8def9ca..93ca3fe7b4d 100644
--- a/addons/web/static/src/js/views.js
+++ b/addons/web/static/src/js/views.js
@@ -344,6 +344,8 @@ instance.web.ActionManager = instance.web.Widget.extend({
});
}
+ instance.web.bus.trigger('action', action);
+
// Ensure context & domain are evaluated and can be manipulated/used
var ncontext = new instance.web.CompoundContext(options.additional_context, action.context || {});
action.context = instance.web.pyeval.eval('context', ncontext);
@@ -691,8 +693,8 @@ instance.web.ViewManager = instance.web.Widget.extend({
var container = this.$el.find("> div > div > .oe_view_manager_body > .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).done(function() {
+ self.views[view_type].deferred.resolve(view_type);
if (self.searchview
&& self.flags.auto_search
&& view.controller.searchable !== false) {
@@ -725,6 +727,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
}
views.push(mode);
}
+ instance.web.bus.trigger('view_switch_mode', self, mode);
});
var item = _.extend({
widget: this,
@@ -1122,7 +1125,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
);
}
- $.when(defs).done(function() {
+ $.when(this.views[this.active_view] ? this.views[this.active_view].deferred : $.when(), defs).done(function() {
self.views[self.active_view].controller.do_load_state(state, warm);
});
},
@@ -1481,6 +1484,7 @@ instance.web.View = instance.web.Widget.extend({
},
do_show: function () {
this.$el.show();
+ instance.web.bus.trigger('view_shown', this);
},
do_hide: function () {
this.$el.hide();
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 2cce789480c..f37c282b01c 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -40,7 +40,7 @@
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 class="modal-title"><t t-raw="title"/></h3>
</div>
- <div class="modal-body" style="overflow-y: auto;">
+ <div class="modal-body">
</div>
</div>
</div>
@@ -85,7 +85,7 @@
</div>
</div>
<p class="oe_grey" style="margin: 10px">
- Fill in this form to create an OpenERP database. You can
+ Fill in this form to create an Odoo database. You can
create databases for different companies or for different
goals (testing, production). Once the database is created,
you will be able to install your first application.
@@ -112,7 +112,7 @@
<td class="oe_form_group_cell">
<span class="oe_form_field oe_form_field_boolean oe_grey" >
<input type="checkbox" name="demo_data" />
- Check this box to evaluate OpenERP.
+ Check this box to evaluate Odoo.
</span>
</td>
</tr>
@@ -372,7 +372,7 @@
<div class="oe_bottom">
<p>Copyright © 2004-TODAY OpenERP SA. All Rights Reserved.<br />
- OpenERP is a trademark of the <a target="_blank" href="https://www.odoo.com" style="text-decoration: underline;">OpenERP SA Company</a>.</p>
+ Odoo is a trademark of the <a target="_blank" href="https://www.odoo.com" style="text-decoration: underline;">OpenERP SA Company</a>.</p>
<p>Licenced under the terms of <a target="_blank" href="http://www.gnu.org/licenses/agpl.html" style="text-decoration: underline;">GNU Affero General Public License</a></p>
<p>For more information visit <a target="_blank" href="https://www.odoo.com" style="text-decoration: underline;">Odoo.com</a></p>
</div>
@@ -1053,14 +1053,15 @@
<t t-name="web.datepicker">
<span>
<t t-set="placeholder" t-value="widget.getParent().node and widget.getParent().node.attrs.placeholder"/>
- <input type="text" class="oe_datepicker_container" disabled="disabled" style="display: none;"/>
- <input type="text"
- t-att-name="widget.name"
- t-att-placeholder="placeholder"
- class="oe_datepicker_master"
- /><img class="oe_input_icon oe_datepicker_trigger" draggable="false"
- t-att-src='_s + "/web/static/src/img/ui/field_calendar.png"'
- title="Select date" width="16" height="16" border="0"/>
+ <div class="oe_datepicker_main input-group">
+ <input type="text"
+ t-att-name="widget.name"
+ t-att-placeholder="placeholder"
+ class="oe_datepicker_master"
+ /><span><img class="oe_input_icon oe_datepicker_trigger datepickerbutton" draggable="false"
+ t-att-src='_s + "/web/static/src/img/ui/field_calendar.png"'
+ title="Select date" width="16" height="16" border="0"/></span>
+ </div>
</span>
</t>
<t t-name="FieldDate">
@@ -1768,6 +1769,8 @@
<button class="oe_button" id="add_field">Add</button>
<button class="oe_button" id="remove_field">Remove</button>
<button class="oe_button" id="remove_all_field">Remove All</button>
+ <button class="oe_button" id="move_up">Move Up</button>
+ <button class="oe_button" id="move_down">Move Down</button>
</td>
<td class="oe_export_fields_selector_right">
<select name="fields_list" id="fields_list"