diff options
Diffstat (limited to 'addons/web/static/src')
84 files changed, 562 insertions, 164 deletions
diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index 3003f9402ac..cc8b596e6f5 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -294,6 +294,9 @@ label.error { color: #fff; } +.openerp .oe-application-container { + height: 100%; +} /* Secondary Menu */ .openerp .secondary_menu { width: 200px; @@ -1276,3 +1279,39 @@ label.error { border-left: none; padding-left: 0; } + +ul.oe-arrow-list { + padding-left: 0.5em; + margin: 0; +} +ul.oe-arrow-list li { + display: inline-block; + margin-left: -0.5em; +} +ul.oe-arrow-list li span { + vertical-align: top; + display: inline-block; + border-width:1em; + border-style:solid; + border-color: white; + line-height:0em; +} +ul.oe-arrow-list .oe-arrow-list-before { + border-left-color: rgba(0,0,0,0); + border-right-width:0; +} +ul.oe-arrow-list .oe-arrow-list-after { + border-color: rgba(0,0,0,0); + border-left-color: white; + border-right-width:0; +} +ul.oe-arrow-list li.oe-arrow-list-selected span { + border-color: #CFCCCC; +} +ul.oe-arrow-list li.oe-arrow-list-selected .oe-arrow-list-before { + border-left-color: rgba(0,0,0,0); +} +ul.oe-arrow-list li.oe-arrow-list-selected .oe-arrow-list-after { + border-color: rgba(0,0,0,0); + border-left-color: #CFCCCC; +} diff --git a/addons/web/static/src/img/icons/color-picker.png b/addons/web/static/src/img/icons/color-picker.png Binary files differnew file mode 100644 index 00000000000..765294c6bdd --- /dev/null +++ b/addons/web/static/src/img/icons/color-picker.png diff --git a/addons/web/static/src/img/icons/gtk-about.png b/addons/web/static/src/img/icons/gtk-about.png Binary files differnew file mode 100644 index 00000000000..1b430a35758 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-about.png diff --git a/addons/web/static/src/img/icons/gtk-bold.png b/addons/web/static/src/img/icons/gtk-bold.png Binary files differnew file mode 100644 index 00000000000..408f25aa20b --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-bold.png diff --git a/addons/web/static/src/img/icons/gtk-cdrom.png b/addons/web/static/src/img/icons/gtk-cdrom.png Binary files differnew file mode 100644 index 00000000000..27e8edd8a0b --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-cdrom.png diff --git a/addons/web/static/src/img/icons/gtk-clear.png b/addons/web/static/src/img/icons/gtk-clear.png Binary files differnew file mode 100644 index 00000000000..b2874fb84fa --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-clear.png diff --git a/addons/web/static/src/img/icons/gtk-color-picker.png b/addons/web/static/src/img/icons/gtk-color-picker.png Binary files differnew file mode 100644 index 00000000000..232d54f8f3b --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-color-picker.png diff --git a/addons/web/static/src/img/icons/gtk-connect.png b/addons/web/static/src/img/icons/gtk-connect.png Binary files differnew file mode 100644 index 00000000000..c820b54abcc --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-connect.png diff --git a/addons/web/static/src/img/icons/gtk-copy.png b/addons/web/static/src/img/icons/gtk-copy.png Binary files differnew file mode 100644 index 00000000000..3d68da606d2 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-copy.png diff --git a/addons/web/static/src/img/icons/gtk-cut.png b/addons/web/static/src/img/icons/gtk-cut.png Binary files differnew file mode 100644 index 00000000000..96681d26968 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-cut.png diff --git a/addons/web/static/src/img/icons/gtk-dialog-authentication.png b/addons/web/static/src/img/icons/gtk-dialog-authentication.png Binary files differnew file mode 100644 index 00000000000..eb411112f83 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-dialog-authentication.png diff --git a/addons/web/static/src/img/icons/gtk-dialog-error.png b/addons/web/static/src/img/icons/gtk-dialog-error.png Binary files differnew file mode 100644 index 00000000000..e97bc43504b --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-dialog-error.png diff --git a/addons/web/static/src/img/icons/gtk-dialog-info.png b/addons/web/static/src/img/icons/gtk-dialog-info.png Binary files differnew file mode 100644 index 00000000000..ed46c3ecdb3 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-dialog-info.png diff --git a/addons/web/static/src/img/icons/gtk-dialog-question.png b/addons/web/static/src/img/icons/gtk-dialog-question.png Binary files differnew file mode 100644 index 00000000000..ef68f43f43f --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-dialog-question.png diff --git a/addons/web/static/src/img/icons/gtk-dialog-warning.png b/addons/web/static/src/img/icons/gtk-dialog-warning.png Binary files differnew file mode 100644 index 00000000000..65a4d2c7220 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-dialog-warning.png diff --git a/addons/web/static/src/img/icons/gtk-directory-remote.png b/addons/web/static/src/img/icons/gtk-directory-remote.png Binary files differnew file mode 100644 index 00000000000..34e737d7c07 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-directory-remote.png diff --git a/addons/web/static/src/img/icons/gtk-directory.png b/addons/web/static/src/img/icons/gtk-directory.png Binary files differnew file mode 100644 index 00000000000..8e41b7878a9 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-directory.png diff --git a/addons/web/static/src/img/icons/gtk-disconnect.png b/addons/web/static/src/img/icons/gtk-disconnect.png Binary files differnew file mode 100644 index 00000000000..fd188701fc2 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-disconnect.png diff --git a/addons/web/static/src/img/icons/gtk-dnd-multiple.png b/addons/web/static/src/img/icons/gtk-dnd-multiple.png Binary files differnew file mode 100644 index 00000000000..aa4c65ad5b1 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-dnd-multiple.png diff --git a/addons/web/static/src/img/icons/gtk-file.png b/addons/web/static/src/img/icons/gtk-file.png Binary files differnew file mode 100644 index 00000000000..fa157156bcc --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-file.png diff --git a/addons/web/static/src/img/icons/gtk-find-and-replace.png b/addons/web/static/src/img/icons/gtk-find-and-replace.png Binary files differnew file mode 100644 index 00000000000..b8d8eeec1b2 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-find-and-replace.png diff --git a/addons/web/static/src/img/icons/gtk-floppy.png b/addons/web/static/src/img/icons/gtk-floppy.png Binary files differnew file mode 100644 index 00000000000..7d8209cfb6f --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-floppy.png diff --git a/addons/web/static/src/img/icons/gtk-fullscreen.png b/addons/web/static/src/img/icons/gtk-fullscreen.png Binary files differnew file mode 100644 index 00000000000..8ddc31e7481 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-fullscreen.png diff --git a/addons/web/static/src/img/icons/gtk-goto-bottom.png b/addons/web/static/src/img/icons/gtk-goto-bottom.png Binary files differnew file mode 100644 index 00000000000..be52840dee1 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-goto-bottom.png diff --git a/addons/web/static/src/img/icons/gtk-goto-first.png b/addons/web/static/src/img/icons/gtk-goto-first.png Binary files differnew file mode 100644 index 00000000000..3d00e36d696 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-goto-first.png diff --git a/addons/web/static/src/img/icons/gtk-goto-top.png b/addons/web/static/src/img/icons/gtk-goto-top.png Binary files differnew file mode 100644 index 00000000000..227a91e5157 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-goto-top.png diff --git a/addons/web/static/src/img/icons/gtk-harddisk.png b/addons/web/static/src/img/icons/gtk-harddisk.png Binary files differnew file mode 100644 index 00000000000..73e5ef0a82e --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-harddisk.png diff --git a/addons/web/static/src/img/icons/gtk-help.png b/addons/web/static/src/img/icons/gtk-help.png Binary files differnew file mode 100644 index 00000000000..f8e17009dd6 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-help.png diff --git a/addons/web/static/src/img/icons/gtk-home.png b/addons/web/static/src/img/icons/gtk-home.png Binary files differnew file mode 100644 index 00000000000..9d3d50d0fcb --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-home.png diff --git a/addons/web/static/src/img/icons/gtk-info.png b/addons/web/static/src/img/icons/gtk-info.png Binary files differnew file mode 100644 index 00000000000..272019f5c99 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-info.png diff --git a/addons/web/static/src/img/icons/gtk-italic.png b/addons/web/static/src/img/icons/gtk-italic.png Binary files differnew file mode 100644 index 00000000000..26c57226a31 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-italic.png diff --git a/addons/web/static/src/img/icons/gtk-justify-center.png b/addons/web/static/src/img/icons/gtk-justify-center.png Binary files differnew file mode 100644 index 00000000000..d5f514298eb --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-justify-center.png diff --git a/addons/web/static/src/img/icons/gtk-justify-left.png b/addons/web/static/src/img/icons/gtk-justify-left.png Binary files differnew file mode 100644 index 00000000000..ecb76b117eb --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-justify-left.png diff --git a/addons/web/static/src/img/icons/gtk-justify-right.png b/addons/web/static/src/img/icons/gtk-justify-right.png Binary files differnew file mode 100644 index 00000000000..3cd4d161420 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-justify-right.png diff --git a/addons/web/static/src/img/icons/gtk-leave-fullscreen.png b/addons/web/static/src/img/icons/gtk-leave-fullscreen.png Binary files differnew file mode 100644 index 00000000000..15bc8ab7d7b --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-leave-fullscreen.png diff --git a/addons/web/static/src/img/icons/gtk-media-forward.png b/addons/web/static/src/img/icons/gtk-media-forward.png Binary files differnew file mode 100644 index 00000000000..e5e198fbb79 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-media-forward.png diff --git a/addons/web/static/src/img/icons/gtk-media-next.png b/addons/web/static/src/img/icons/gtk-media-next.png Binary files differnew file mode 100644 index 00000000000..e0aa2431cf0 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-media-next.png diff --git a/addons/web/static/src/img/icons/gtk-media-previous.png b/addons/web/static/src/img/icons/gtk-media-previous.png Binary files differnew file mode 100644 index 00000000000..756899e0bc1 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-media-previous.png diff --git a/addons/web/static/src/img/icons/gtk-media-record.png b/addons/web/static/src/img/icons/gtk-media-record.png Binary files differnew file mode 100644 index 00000000000..904974c81e5 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-media-record.png diff --git a/addons/web/static/src/img/icons/gtk-media-rewind.png b/addons/web/static/src/img/icons/gtk-media-rewind.png Binary files differnew file mode 100644 index 00000000000..9c22d9e2778 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-media-rewind.png diff --git a/addons/web/static/src/img/icons/gtk-media-stop.png b/addons/web/static/src/img/icons/gtk-media-stop.png Binary files differnew file mode 100644 index 00000000000..128cc2313ec --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-media-stop.png diff --git a/addons/web/static/src/img/icons/gtk-missing-image.png b/addons/web/static/src/img/icons/gtk-missing-image.png Binary files differnew file mode 100644 index 00000000000..cc69ed33e4b --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-missing-image.png diff --git a/addons/web/static/src/img/icons/gtk-paste-v.png b/addons/web/static/src/img/icons/gtk-paste-v.png Binary files differnew file mode 100644 index 00000000000..76ec896f70e --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-paste-v.png diff --git a/addons/web/static/src/img/icons/gtk-paste.png b/addons/web/static/src/img/icons/gtk-paste.png Binary files differnew file mode 100644 index 00000000000..840f26c8b38 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-paste.png diff --git a/addons/web/static/src/img/icons/gtk-preferences.png b/addons/web/static/src/img/icons/gtk-preferences.png Binary files differnew file mode 100644 index 00000000000..9ba17a0ab20 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-preferences.png diff --git a/addons/web/static/src/img/icons/gtk-print-preview.png b/addons/web/static/src/img/icons/gtk-print-preview.png Binary files differnew file mode 100644 index 00000000000..ab15fcbd307 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-print-preview.png diff --git a/addons/web/static/src/img/icons/gtk-properties.png b/addons/web/static/src/img/icons/gtk-properties.png Binary files differnew file mode 100644 index 00000000000..894415ec1ce --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-properties.png diff --git a/addons/web/static/src/img/icons/gtk-quit.png b/addons/web/static/src/img/icons/gtk-quit.png Binary files differnew file mode 100644 index 00000000000..50b5144660b --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-quit.png diff --git a/addons/web/static/src/img/icons/gtk-refresh.png b/addons/web/static/src/img/icons/gtk-refresh.png Binary files differnew file mode 100644 index 00000000000..7474728b4c0 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-refresh.png diff --git a/addons/web/static/src/img/icons/gtk-revert-to-saved.png b/addons/web/static/src/img/icons/gtk-revert-to-saved.png Binary files differnew file mode 100644 index 00000000000..eaf54584edf --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-revert-to-saved.png diff --git a/addons/web/static/src/img/icons/gtk-save-as.png b/addons/web/static/src/img/icons/gtk-save-as.png Binary files differnew file mode 100644 index 00000000000..1831e4e0a4b --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-save-as.png diff --git a/addons/web/static/src/img/icons/gtk-select-color.png b/addons/web/static/src/img/icons/gtk-select-color.png Binary files differnew file mode 100644 index 00000000000..12b015df107 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-select-color.png diff --git a/addons/web/static/src/img/icons/gtk-select-font.png b/addons/web/static/src/img/icons/gtk-select-font.png Binary files differnew file mode 100644 index 00000000000..66e606313a5 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-select-font.png diff --git a/addons/web/static/src/img/icons/gtk-sort-ascending.png b/addons/web/static/src/img/icons/gtk-sort-ascending.png Binary files differnew file mode 100644 index 00000000000..a648fa0d359 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-sort-ascending.png diff --git a/addons/web/static/src/img/icons/gtk-spell-check.png b/addons/web/static/src/img/icons/gtk-spell-check.png Binary files differnew file mode 100644 index 00000000000..698f7c24a43 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-spell-check.png diff --git a/addons/web/static/src/img/icons/gtk-strikethrough.png b/addons/web/static/src/img/icons/gtk-strikethrough.png Binary files differnew file mode 100644 index 00000000000..1c11f214622 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-strikethrough.png diff --git a/addons/web/static/src/img/icons/gtk-undelete.png b/addons/web/static/src/img/icons/gtk-undelete.png Binary files differnew file mode 100644 index 00000000000..c44b940c03b --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-undelete.png diff --git a/addons/web/static/src/img/icons/gtk-underline.png b/addons/web/static/src/img/icons/gtk-underline.png Binary files differnew file mode 100644 index 00000000000..7dbb5d7e60a --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-underline.png diff --git a/addons/web/static/src/img/icons/gtk-unindent.png b/addons/web/static/src/img/icons/gtk-unindent.png Binary files differnew file mode 100644 index 00000000000..8ace914c1bd --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-unindent.png diff --git a/addons/web/static/src/img/icons/gtk-zoom-100.png b/addons/web/static/src/img/icons/gtk-zoom-100.png Binary files differnew file mode 100644 index 00000000000..5193406b787 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-zoom-100.png diff --git a/addons/web/static/src/img/icons/gtk-zoom-out.png b/addons/web/static/src/img/icons/gtk-zoom-out.png Binary files differnew file mode 100644 index 00000000000..0da5ee7ec13 --- /dev/null +++ b/addons/web/static/src/img/icons/gtk-zoom-out.png diff --git a/addons/web/static/src/img/icons/lead-stage-lost.png b/addons/web/static/src/img/icons/lead-stage-lost.png Binary files differnew file mode 100644 index 00000000000..e1f98a26b59 --- /dev/null +++ b/addons/web/static/src/img/icons/lead-stage-lost.png diff --git a/addons/web/static/src/img/icons/lead-stage-pending.png b/addons/web/static/src/img/icons/lead-stage-pending.png Binary files differnew file mode 100644 index 00000000000..9e9544ee178 --- /dev/null +++ b/addons/web/static/src/img/icons/lead-stage-pending.png diff --git a/addons/web/static/src/img/icons/lead-stage-won.png b/addons/web/static/src/img/icons/lead-stage-won.png Binary files differnew file mode 100644 index 00000000000..02effd5f14c --- /dev/null +++ b/addons/web/static/src/img/icons/lead-stage-won.png diff --git a/addons/web/static/src/img/icons/star-off.png b/addons/web/static/src/img/icons/star-off.png Binary files differnew file mode 100644 index 00000000000..7cd0afd4f03 --- /dev/null +++ b/addons/web/static/src/img/icons/star-off.png diff --git a/addons/web/static/src/img/icons/star-on.png b/addons/web/static/src/img/icons/star-on.png Binary files differnew file mode 100644 index 00000000000..4f2295e1395 --- /dev/null +++ b/addons/web/static/src/img/icons/star-on.png diff --git a/addons/web/static/src/img/icons/stock.png b/addons/web/static/src/img/icons/stock.png Binary files differnew file mode 100644 index 00000000000..ca38181db90 --- /dev/null +++ b/addons/web/static/src/img/icons/stock.png diff --git a/addons/web/static/src/img/icons/stock_calendar.png b/addons/web/static/src/img/icons/stock_calendar.png Binary files differnew file mode 100644 index 00000000000..99a1f3f9ef1 --- /dev/null +++ b/addons/web/static/src/img/icons/stock_calendar.png diff --git a/addons/web/static/src/img/icons/stock_gantt.png b/addons/web/static/src/img/icons/stock_gantt.png Binary files differnew file mode 100644 index 00000000000..585761b9220 --- /dev/null +++ b/addons/web/static/src/img/icons/stock_gantt.png diff --git a/addons/web/static/src/img/icons/stock_graph.png b/addons/web/static/src/img/icons/stock_graph.png Binary files differnew file mode 100644 index 00000000000..4d8310621ea --- /dev/null +++ b/addons/web/static/src/img/icons/stock_graph.png diff --git a/addons/web/static/src/img/icons/stock_log.png b/addons/web/static/src/img/icons/stock_log.png Binary files differnew file mode 100644 index 00000000000..32af4dd6901 --- /dev/null +++ b/addons/web/static/src/img/icons/stock_log.png diff --git a/addons/web/static/src/img/icons/stock_person.png b/addons/web/static/src/img/icons/stock_person.png Binary files differnew file mode 100644 index 00000000000..202cf0ee6c5 --- /dev/null +++ b/addons/web/static/src/img/icons/stock_person.png diff --git a/addons/web/static/src/img/icons/stock_translate.png b/addons/web/static/src/img/icons/stock_translate.png Binary files differnew file mode 100644 index 00000000000..5ab41d49343 --- /dev/null +++ b/addons/web/static/src/img/icons/stock_translate.png diff --git a/addons/web/static/src/js/boot.js b/addons/web/static/src/js/boot.js index 2c00eb3d5a5..b9d5180b5c4 100644 --- a/addons/web/static/src/js/boot.js +++ b/addons/web/static/src/js/boot.js @@ -5,7 +5,6 @@ /** * @name openerp * @namespace openerp - * @namespace window.openerp */ (function() { if (this.openerp) @@ -48,6 +47,9 @@ * OpenERP Web web module split *---------------------------------------------------------*/ +/** + * @namespace + */ openerp.web = function(instance) { openerp.web.core(instance); if (openerp.web.dates) { diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index d58dadac210..c12d157a668 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -5,7 +5,14 @@ openerp.web.chrome = function(openerp) { var QWeb = openerp.web.qweb; -openerp.web.Notification = openerp.web.Widget.extend({ +openerp.web.Notification = openerp.web.Widget.extend(/** @lends openerp.web.Notification# */{ + /** + * @constructs openerp.web.Notification + * @extends openerp.web.Widget + * + * @param parent + * @param element_id + */ init: function(parent, element_id) { this._super(parent, element_id); this.$element.notify({ @@ -27,9 +34,16 @@ openerp.web.Notification = openerp.web.Widget.extend({ } }); -openerp.web.Dialog = openerp.web.OldWidget.extend({ +openerp.web.Dialog = openerp.web.OldWidget.extend(/** @lends openerp.web.Dialog# */{ dialog_title: "", identifier_prefix: 'dialog', + /** + * @constructs openerp.web.Dialog + * @extends openerp.web.OldWidget + * + * @param parent + * @param dialog_options + */ init: function (parent, dialog_options) { var self = this; this._super(parent); @@ -118,8 +132,14 @@ openerp.web.Dialog = openerp.web.OldWidget.extend({ } }); -openerp.web.CrashManager = openerp.web.Dialog.extend({ +openerp.web.CrashManager = openerp.web.Dialog.extend(/** @lends openerp.web.CrashManager# */{ identifier_prefix: 'dialog_crash', + /** + * @constructs opener.web.CrashManager + * @extends openerp.web.Dialog + * + * @param parent + */ init: function(parent) { this._super(parent); this.session.on_rpc_error.add(this.on_rpc_error); @@ -130,7 +150,7 @@ openerp.web.CrashManager = openerp.web.Dialog.extend({ on_rpc_error: function(error) { this.error = error; if (error.data.fault_code) { - var split = error.data.fault_code.split('\n')[0].split(' -- '); + var split = ("" + error.data.fault_code).split('\n')[0].split(' -- '); if (split.length > 1) { error.type = split.shift(); error.data.fault_code = error.data.fault_code.substr(error.type.length + 4); @@ -154,7 +174,14 @@ openerp.web.CrashManager = openerp.web.Dialog.extend({ } }); -openerp.web.Loading = openerp.web.Widget.extend({ +openerp.web.Loading = openerp.web.Widget.extend(/** @lends openerp.web.Loading# */{ + /** + * @constructs openerp.web.Loading + * @extends openerp.web.Widget + * + * @param parent + * @param element_id + */ init: function(parent, element_id) { this._super(parent, element_id); this.count = 0; @@ -173,7 +200,15 @@ openerp.web.Loading = openerp.web.Widget.extend({ } }); -openerp.web.Database = openerp.web.Widget.extend({ +openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database# */{ + /** + * @constructs openerp.web.Database + * @extends openerp.web.Widget + * + * @param parent + * @param element_id + * @param option_id + */ init: function(parent, element_id, option_id) { this._super(parent, element_id); this.$option_id = $('#' + option_id); @@ -427,9 +462,15 @@ openerp.web.Database = openerp.web.Widget.extend({ } }); -openerp.web.Login = openerp.web.Widget.extend({ +openerp.web.Login = openerp.web.Widget.extend(/** @lends openerp.web.Login# */{ remember_creditentials: true, - + /** + * @constructs openerp.web.Login + * @extends openerp.web.Widget + * + * @param parent + * @param element_id + */ init: function(parent, element_id) { this._super(parent, element_id); this.has_local_storage = typeof(localStorage) != 'undefined'; @@ -527,9 +568,15 @@ openerp.web.Login = openerp.web.Widget.extend({ } }); -openerp.web.Header = openerp.web.Widget.extend({ +openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# */{ template: "Header", identifier_prefix: 'oe-app-header-', + /** + * @constructs openerp.web.Header + * @extends openerp.web.Widget + * + * @param parent + */ init: function(parent) { this._super(parent); this.qs = "?" + jQuery.param.querystring(); @@ -540,6 +587,9 @@ openerp.web.Header = openerp.web.Widget.extend({ }, do_update: function () { var self = this; + this.$content.remove(); + if (! this.session.uid) + return; var func = new openerp.web.Model(self.session, "res.users").get_func("read"); func(self.session.uid, ["name", "company_id"]).then(function(res) { self.$content = $(QWeb.render("Header-content", {widget: self, user: res})); @@ -558,9 +608,6 @@ openerp.web.Header = openerp.web.Widget.extend({ modal: true, width: 960, title: "About"}); }); }, - do_reset: function() { - this.$content.remove(); - }, shortcut_load :function(){ var self = this, sc = self.session.shortcuts, @@ -707,11 +754,18 @@ openerp.web.Header = openerp.web.Widget.extend({ }).html(error.error); }, on_logout: function() { - this.$element.find('.oe-shortcuts ul').empty(); } }); -openerp.web.Menu = openerp.web.Widget.extend({ +openerp.web.Menu = openerp.web.Widget.extend(/** @lends openerp.web.Menu# */{ + /** + * @constructs openerp.web.Menu + * @extends openerp.web.Widget + * + * @param parent + * @param element_id + * @param secondary_menu_id + */ init: function(parent, element_id, secondary_menu_id) { this._super(parent, element_id); this.secondary_menu_id = secondary_menu_id; @@ -793,13 +847,13 @@ openerp.web.Menu = openerp.web.Widget.extend({ } }); -openerp.web.Homepage = openerp.web.Widget.extend({ -}); - -openerp.web.Preferences = openerp.web.Widget.extend({ -}); - -openerp.web.WebClient = openerp.web.Widget.extend({ +openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClient */{ + /** + * @constructs openerp.web.WebClient + * @extends openerp.web.Widget + * + * @param element_id + */ init: function(element_id) { this._super(null, element_id); openerp.webclient = this; @@ -827,7 +881,7 @@ openerp.web.WebClient = openerp.web.Widget.extend({ this.session.on_session_invalid.add(this.login.do_ask_login); this.session.on_session_valid.add_last(this.header.do_update); - this.session.on_session_invalid.add_last(this.header.do_reset); + this.session.on_session_invalid.add_last(this.header.do_update); this.session.on_session_valid.add_last(this.on_logged); this.menu = new openerp.web.Menu(this, "oe_menu", "oe_secondary_menu"); @@ -838,7 +892,7 @@ openerp.web.WebClient = openerp.web.Widget.extend({ this.session.start(); this.login.start(); this.menu.start(); - this.notification.notify("OpenERP Client", "The openerp client has been initialized."); + console.debug("The openerp client has been initialized."); }, on_logged: function() { if(this.action_manager) diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js index ae2c4d0d657..77b48820e83 100644 --- a/addons/web/static/src/js/core.js +++ b/addons/web/static/src/js/core.js @@ -4,6 +4,7 @@ openerp.web.core = function(openerp) { openerp.web.qweb = new QWeb2.Engine(); +openerp.web.qweb.debug = (window.location.search.indexOf('?debug') !== -1); /** * John Resig Class with factory improvement */ @@ -12,11 +13,17 @@ openerp.web.qweb = new QWeb2.Engine(); fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; // The web Class implementation (does nothing) /** + * Extended version of John Resig's Class pattern + * * @class */ openerp.web.Class = function(){}; - // Create a new Class that inherits from this class + /** + * Subclass an existing class + * + * @param {Object} prop class-level properties (class attributes and instance methods) to set on the new class + */ openerp.web.Class.extend = function(prop) { var _super = this.prototype; @@ -157,7 +164,7 @@ openerp.web.callback = function(obj, method) { * that does nothing and always return undefined). * * @param {Class} claz - * @param {dict} add Additional functions to override. + * @param {Object} add Additional functions to override. * @return {Class} */ openerp.web.generate_null_object_class = function(claz, add) { @@ -188,7 +195,7 @@ openerp.web.KeyNotFound = openerp.web.NotFound.extend( /** @lends openerp.web.Ke /** * Thrown when a key could not be found in a mapping * - * @constructs + * @constructs openerp.web.KeyNotFound * @extends openerp.web.NotFound * @param {String} key the key which could not be found */ @@ -204,7 +211,7 @@ openerp.web.ObjectNotFound = openerp.web.NotFound.extend( /** @lends openerp.web * Thrown when an object path does not designate a valid class or object * in the openerp hierarchy. * - * @constructs + * @constructs openerp.web.ObjectNotFound * @extends openerp.web.NotFound * @param {String} path the invalid object path */ @@ -228,7 +235,7 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry * object pointed to (e.g. ``"openerp.web.Session"`` for an OpenERP * session object). * - * @constructs + * @constructs openerp.web.Registry * @param {Object} mapping a mapping of keys to object-paths */ init: function (mapping) { @@ -309,7 +316,11 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry } }); -openerp.web.CallbackEnabled = openerp.web.Class.extend({ +openerp.web.CallbackEnabled = openerp.web.Class.extend(/** @lends openerp.web.CallbackEnabled# */{ + /** + * @constructs openerp.web.CallbackEnabled + * @extends openerp.web.Class + */ init: function() { // Transform on_* method into openerp.web.callbacks for (var name in this) { @@ -326,9 +337,11 @@ openerp.web.CallbackEnabled = openerp.web.Class.extend({ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web.Session# */{ /** - * @constructs - * @param server - * @param port + * @constructs openerp.web.Session + * @extends openerp.web.CallbackEnabled + * + * @param {String} [server] JSON-RPC endpoint hostname + * @param {String} [port] JSON-RPC endpoint port */ init: function(server, port) { this._super(); @@ -375,7 +388,7 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web jsonrpc: "2.0", method: "call", params: params, - id:null + id: _.uniqueId('browser-client-') }).then(function () {deferred.resolve.apply(deferred, arguments);}, function(error) {deferred.reject(error, $.Event());}); return deferred.fail(function() { @@ -576,9 +589,10 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web }); }, do_load_css: function (files) { + var self = this; _.each(files, function (file) { $('head').append($('<link>', { - 'href': file, + 'href': file + (self.debug ? '?debug=' + (new Date().getTime()) : ''), 'rel': 'stylesheet', 'type': 'text/css' })); @@ -590,7 +604,7 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web var file = files.shift(); var tag = document.createElement('script'); tag.type = 'text/javascript'; - tag.src = file; + tag.src = file + (this.debug ? '?debug=' + (new Date().getTime()) : ''); tag.onload = tag.onreadystatechange = function() { if ( (tag.readyState && tag.readyState != "loaded" && tag.readyState != "complete") || tag.onload_done ) return; @@ -708,13 +722,18 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web } }); -/** - * Utility class that any class is allowed to extend to easy common manipulations. - * - * It provides rpc calls, callback on all methods preceded by "on_" or "do_" and a - * logging facility. - */ -openerp.web.SessionAware = openerp.web.CallbackEnabled.extend({ +openerp.web.SessionAware = openerp.web.CallbackEnabled.extend(/** @lends openerp.web.SessionAware# */{ + /** + * Utility class that any class is allowed to extend to easy common manipulations. + * + * It provides rpc calls, callback on all methods preceded by "on_" or "do_" and a + * logging facility. + * + * @constructs openerp.web.SessionAware + * @extends openerp.web.CallbackEnabled + * + * @param {openerp.web.Session} session + */ init: function(session) { this._super(); this.session = session; @@ -758,15 +777,12 @@ openerp.web.SessionAware = openerp.web.CallbackEnabled.extend({ if(body) { $('<pre></pre>').text(v).appendTo($('body')); } - if(notify && this.notification) { - this.notification.notify("Logging:",v); - } } } } }); -openerp.web.Widget = openerp.web.SessionAware.extend({ +openerp.web.Widget = openerp.web.SessionAware.extend(/** @lends openerp.web.Widget# */{ /** * The name of the QWeb template that will be used for rendering. Must be * redefined in subclasses or the default render() method can not be used. @@ -784,7 +800,9 @@ openerp.web.Widget = openerp.web.SessionAware.extend({ /** * Construct the widget and set its parent if a parent is given. * - * @constructs + * @constructs openerp.web.Widget + * @extends openerp.web.SessionAware + * * @param {openerp.web.Widget} parent Binds the current instance to the given Widget instance. * When that widget is destroyed by calling stop(), the current instance will be * destroyed too. Can be null. @@ -860,8 +878,10 @@ openerp.web.Widget = openerp.web.SessionAware.extend({ if (target instanceof openerp.web.Widget) target = target.$element; insertion(target); + this.on_inserted(this.$element, this); return this.start(); }, + on_inserted: function(element, widget) {}, /** * Renders the widget using QWeb, `this.template` must be defined. * The context given to QWeb contains the "widget" key that references `this`. @@ -941,17 +961,23 @@ openerp.web.Widget = openerp.web.SessionAware.extend({ }); /** + * @class + * @extends openerp.web.Widget * @deprecated * For retro compatibility only, the only difference with is that render() uses - * directly `this` instead of context with a "widget" key. + * directly ``this`` instead of context with a ``widget`` key. */ -openerp.web.OldWidget = openerp.web.Widget.extend({ +openerp.web.OldWidget = openerp.web.Widget.extend(/** @lends openerp.web.OldWidget# */{ render: function (additional) { return openerp.web.qweb.render(this.template, _.extend(_.extend({}, this), additional || {})); } }); -openerp.web.TranslationDataBase = openerp.web.Class.extend({ +openerp.web.TranslationDataBase = openerp.web.Class.extend(/** @lends openerp.web.TranslationDataBase# */{ + /** + * @constructs openerp.web.TranslationDataBase + * @extends openerp.web.Class + */ init: function() { this.db = {}; this.parameters = {"direction": 'ltr', diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index 4b4523a2723..1eb57241fa6 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -29,7 +29,7 @@ openerp.web.DataGroup = openerp.web.Widget.extend( /** @lends openerp.web.DataG * :js:func:`~openerp.web.DataGroup.list`, which is used to read the * content of the current grouping level. * - * @constructs + * @constructs openerp.web.DataGroup * @extends openerp.web.Widget * * @param {openerp.web.Session} session Current OpenERP session @@ -60,7 +60,7 @@ openerp.web.DataGroup = openerp.web.Widget.extend( /** @lends openerp.web.DataG openerp.web.ContainerDataGroup = openerp.web.DataGroup.extend( /** @lends openerp.web.ContainerDataGroup# */ { /** * - * @constructs + * @constructs openerp.web.ContainerDataGroup * @extends openerp.web.DataGroup * * @param session @@ -197,7 +197,7 @@ openerp.web.ContainerDataGroup = openerp.web.DataGroup.extend( /** @lends opener openerp.web.GrouplessDataGroup = openerp.web.DataGroup.extend( /** @lends openerp.web.GrouplessDataGroup# */ { /** * - * @constructs + * @constructs openerp.web.GrouplessDataGroup * @extends openerp.web.DataGroup * * @param session @@ -220,7 +220,7 @@ openerp.web.StaticDataGroup = openerp.web.GrouplessDataGroup.extend( /** @lends * A specialization of groupless data groups, relying on a single static * dataset as its records provider. * - * @constructs + * @constructs openerp.web.StaticDataGroup * @extends openerp.web.GrouplessDataGroup * @param {openep.web.DataSetStatic} dataset a static dataset backing the groups */ @@ -237,7 +237,7 @@ openerp.web.DataSet = openerp.web.Widget.extend( /** @lends openerp.web.DataSet * DateaManagement interface between views and the collection of selected * OpenERP records (represents the view's state?) * - * @constructs + * @constructs openerp.web.DataSet * @extends openerp.web.Widget * * @param {String} model the OpenERP model this dataset will manage @@ -505,9 +505,10 @@ openerp.web.DataSetStatic = openerp.web.DataSet.extend({ this.set_ids(_.without.apply(null, [this.ids].concat(ids))); } }); -openerp.web.DataSetSearch = openerp.web.DataSet.extend({ +openerp.web.DataSetSearch = openerp.web.DataSet.extend(/** @lends openerp.web.DataSetSearch */{ /** - * @constructs + * @constructs openerp.web.DataSetSearch + * @extends openerp.web.DataSet * * @param {Object} parent * @param {String} model @@ -612,11 +613,12 @@ openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({ var cached = {id:_.uniqueId(this.virtual_id_prefix), values: data}; this.to_create.push(cached); this.cache.push(cached); + this.on_change(); var to_return = $.Deferred().then(callback); to_return.resolve({result: cached.id}); return to_return.promise(); }, - write: function (id, data, callback) { + write: function (id, data, options, callback) { var self = this; var record = _.detect(this.to_create, function(x) {return x.id === id;}); record = record || _.detect(this.to_write, function(x) {return x.id === id;}); @@ -721,7 +723,7 @@ openerp.web.ReadOnlyDataSetSearch = openerp.web.DataSetSearch.extend({ return to_return.promise(); }, on_create: function(data) {}, - write: function (id, data, callback) { + write: function (id, data, options, callback) { this.on_write(id, data); var to_return = $.Deferred().then(callback); setTimeout(function () {to_return.resolve({"result": true});}, 0); diff --git a/addons/web/static/src/js/form.js b/addons/web/static/src/js/form.js index 73695e93ea3..d419516dc77 100644 --- a/addons/web/static/src/js/form.js +++ b/addons/web/static/src/js/form.js @@ -12,7 +12,9 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# searchable: false, template: "FormView", /** - * @constructs + * @constructs openerp.web.FormView + * @extends openerp.web.View + * * @param {openerp.web.Session} session the current openerp session * @param {String} element_id this view's root element id * @param {openerp.web.DataSet} dataset the dataset this view will work with @@ -382,9 +384,9 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# }, on_saved: function(r, success) { if (!r.result) { - this.notification.warn("Record not saved", "Problem while saving record."); + // should not happen in the server, but may happen for internal purpose } else { - this.notification.notify("Record saved", "The record #" + this.datarecord.id + " has been saved."); + console.debug(_.sprintf("The record #%s has been saved.", this.datarecord.id)); if (success) { success(r); } @@ -406,7 +408,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# */ on_created: function(r, success, prepend_on_create) { if (!r.result) { - this.notification.warn("Record not created", "Problem while creating record."); + // should not happen in the server, but may happen for internal purpose } else { this.datarecord.id = r.result; if (!prepend_on_create) { @@ -420,7 +422,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# if (this.sidebar) { this.sidebar.attachments.do_update(); } - this.notification.notify("Record created", "The record has been created with id #" + this.datarecord.id); + console.debug("The record has been created with id #" + this.datarecord.id); if (success) { success(_.extend(r, {created: true})); } @@ -428,13 +430,13 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# } }, do_search: function (domains, contexts, groupbys) { - this.notification.notify("Searching form"); + console.debug("Searching form"); }, on_action: function (action) { - this.notification.notify('Executing action ' + action); + console.debug('Executing action', action); }, do_cancel: function () { - this.notification.notify("Cancelling form"); + console.debug("Cancelling form"); }, reload: function() { if (this.dataset.index == null || this.dataset.index < 0) { @@ -456,6 +458,34 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# return id ? [id] : []; } }); +openerp.web.FormDialog = openerp.web.Dialog.extend({ + init: function(parent, options, view_id, dataset) { + this._super(parent, options); + this.dataset = dataset; + this.view_id = view_id; + return this; + }, + start: function() { + this._super(); + this.form = new openerp.web.FormView(this, this.element_id, this.dataset, this.view_id, { + sidebar: false, + pager: false + }); + this.form.start(); + this.form.on_created.add_last(this.on_form_dialog_saved); + this.form.on_saved.add_last(this.on_form_dialog_saved); + return this; + }, + load_id: function(id) { + var self = this; + return this.dataset.read_ids([id], _.keys(this.form.fields_view.fields), function(records) { + self.form.on_record_loaded(records[0]); + }); + }, + on_form_dialog_saved: function(r) { + this.close(); + } +}); /** @namespace */ openerp.web.form = {}; @@ -571,8 +601,15 @@ openerp.web.form.compute_domain = function(expr, fields) { return _.all(stack, _.identity); }; -openerp.web.form.Widget = openerp.web.Widget.extend({ +openerp.web.form.Widget = openerp.web.Widget.extend(/** @lends openerp.web.form.Widget# */{ template: 'Widget', + /** + * @constructs openerp.web.form.Widget + * @extends openerp.web.Widget + * + * @param view + * @param node + */ init: function(view, node) { this.view = view; this.node = node; @@ -849,7 +886,14 @@ openerp.web.form.WidgetLabel = openerp.web.form.Widget.extend({ } }); -openerp.web.form.Field = openerp.web.form.Widget.extend({ +openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.form.Field# */{ + /** + * @constructs openerp.web.form.Field + * @extends openerp.web.form.Widget + * + * @param view + * @param node + */ init: function(view, node) { this.name = node.attrs.name; this.value = undefined; @@ -1223,11 +1267,16 @@ openerp.web.form.FieldTextXml = openerp.web.form.Field.extend({ openerp.web.form.FieldSelection = openerp.web.form.Field.extend({ init: function(view, node) { + var self = this; this._super(view, node); this.template = "FieldSelection"; - this.field_index = _.map(this.field.selection, function(x, index) { - return {"ikey": "" + index, "ekey": x[0], "label": x[1]}; + this.values = this.field.selection; + _.each(this.values, function(v, i) { + if (v[0] === false && v[1] === '') { + self.values.splice(i, 1); + } }); + this.values.unshift([false, '']); }, start: function() { // Flag indicating whether we're in an event chain containing a change @@ -1257,13 +1306,14 @@ openerp.web.form.FieldSelection = openerp.web.form.Field.extend({ value = value === null ? false : value; value = value instanceof Array ? value[0] : value; this._super(value); - var option = _.detect(this.field_index, function(x) {return x.ekey === value;}); - this.$element.find('select').val(option === undefined ? '' : option.ikey); + var index = 0; + for (var i = 0, ii = this.values.length; i < ii; i++) { + if (this.values[i][0] === value) index = i; + } + this.$element.find('select')[0].selectedIndex = index; }, set_value_from_ui: function() { - var ikey = this.$element.find('select').val(); - var option = _.detect(this.field_index, function(x) {return x.ikey === ikey;}); - this.value = option === undefined ? false : option.ekey; + this.value = this.values[this.$element.find('select')[0].selectedIndex][0]; this._super(); }, update_dom: function() { @@ -1271,9 +1321,8 @@ openerp.web.form.FieldSelection = openerp.web.form.Field.extend({ this.$element.find('select').attr('disabled', this.readonly); }, validate: function() { - var ikey = this.$element.find('select').val(); - var option = _.detect(this.field_index, function(x) {return x.ikey === ikey;}); - this.invalid = this.required && (option === undefined || option.ekey === false); + var value = this.values[this.$element.find('select')[0].selectedIndex]; + this.invalid = !(value && !(this.required && value[0] === false)); }, focus: function() { this.$element.find('select').focus(); @@ -1819,7 +1868,7 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ this.viewmanager.views[this.viewmanager.active_view].controller) { var view = this.viewmanager.views[this.viewmanager.active_view].controller; if (this.viewmanager.active_view === "form") { - var res = view.do_save(); + var res = $.when(view.do_save()); if (res === false) { // ignore } else if (res.isRejected()) { @@ -1971,7 +2020,11 @@ openerp.web.form.Many2ManyDataSet = openerp.web.DataSetStatic.extend({ } }); -openerp.web.form.Many2ManyListView = openerp.web.ListView.extend({ +/** + * @class + * @extends openerp.web.ListView + */ +openerp.web.form.Many2ManyListView = openerp.web.ListView.extend(/** @lends openerp.web.form.Many2ManyListView# */{ do_add_record: function () { var pop = new openerp.web.form.SelectCreatePopup(this); pop.select_element(this.model, {}, @@ -1998,7 +2051,11 @@ openerp.web.form.Many2ManyListView = openerp.web.ListView.extend({ } }); -openerp.web.form.SelectCreatePopup = openerp.web.OldWidget.extend({ +/** + * @class + * @extends openerp.web.OldWidget + */ +openerp.web.form.SelectCreatePopup = openerp.web.OldWidget.extend(/** @lends openerp.web.form.SelectCreatePopup# */{ identifier_prefix: "selectcreatepopup", template: "SelectCreatePopup", /** @@ -2167,7 +2224,11 @@ openerp.web.form.SelectCreateListView = openerp.web.ListView.extend({ } }); -openerp.web.form.FormOpenPopup = openerp.web.OldWidget.extend({ +/** + * @class + * @extends openerp.web.OldWidget + */ +openerp.web.form.FormOpenPopup = openerp.web.OldWidget.extend(/** @lends openerp.web.form.FormOpenPopup# */{ identifier_prefix: "formopenpopup", template: "FormOpenPopup", /** @@ -2351,7 +2412,7 @@ openerp.web.form.FieldBinary = openerp.web.form.Field.extend({ if (size === false) { this.notification.warn("File Upload", "There was a problem while uploading your file"); // TODO: use openerp web crashmanager - this.log("Error while uploading file : ", name); + console.warn("Error while uploading file : ", name); } else { this.on_file_uploaded_and_valid.apply(this, arguments); this.on_ui_change(); @@ -2445,6 +2506,50 @@ openerp.web.form.FieldBinaryImage = openerp.web.form.FieldBinary.extend({ } }); +openerp.web.form.FieldStatus = openerp.web.form.Field.extend({ + template: "FieldStatus", + start: function() { + this._super(); + this.selected_value = null; + + this.render_list(); + }, + set_value: function(value) { + this._super(value); + this.selected_value = value; + + this.render_list(); + }, + render_list: function() { + var self = this; + var shown = _.map(((this.node.attrs || {}).statusbar_visible || "").split(","), + function(x) { return x.trim(); }); + + if (shown.length == 0) { + this.to_show = this.field.selection; + } else { + this.to_show = _.select(this.field.selection, function(x) { + return _.indexOf(shown, x[0]) !== -1 || x[0] === self.selected_value; + }); + } + + var content = openerp.web.qweb.render("FieldStatus.content", {widget: this, _:_}); + this.$element.html(content); + + var colors = JSON.parse((this.node.attrs || {}).statusbar_colors || "{}"); + var color = colors[this.selected_value]; + if (color) { + var elem = this.$element.find("li.oe-arrow-list-selected span"); + elem.css("border-color", color); + elem = this.$element.find("li.oe-arrow-list-selected .oe-arrow-list-before"); + elem.css("border-left-color", "rgba(0,0,0,0)"); + elem = this.$element.find("li.oe-arrow-list-selected .oe-arrow-list-after"); + elem.css("border-color", "rgba(0,0,0,0)"); + elem.css("border-left-color", color); + } + } +}); + /** * Registry of form widgets, called by :js:`openerp.web.FormView` */ @@ -2474,7 +2579,8 @@ openerp.web.form.widgets = new openerp.web.Registry({ 'float_time': 'openerp.web.form.FieldFloat', 'progressbar': 'openerp.web.form.FieldProgressBar', 'image': 'openerp.web.form.FieldBinaryImage', - 'binary': 'openerp.web.form.FieldBinaryFile' + 'binary': 'openerp.web.form.FieldBinaryFile', + 'statusbar': 'openerp.web.form.FieldStatus' }); }; diff --git a/addons/web/static/src/js/list-editable.js b/addons/web/static/src/js/list-editable.js index 614c6fa42ef..c38c43a4c9c 100644 --- a/addons/web/static/src/js/list-editable.js +++ b/addons/web/static/src/js/list-editable.js @@ -1,5 +1,6 @@ /** - * @namespace handles editability case for lists, because it depends on form and forms already depends on lists it had to be split out + * handles editability case for lists, because it depends on form and forms already depends on lists it had to be split out + * @namespace */ openerp.web.list_editable = function (openerp) { var KEY_RETURN = 13, @@ -87,7 +88,7 @@ openerp.web.list_editable = function (openerp) { } }); - openerp.web.ListView.List.include(/** @lends openerp.web.ListView.List */{ + openerp.web.ListView.List.include(/** @lends openerp.web.ListView.List# */{ row_clicked: function (event) { if (!this.options.editable) { return this._super(event); @@ -112,6 +113,7 @@ openerp.web.list_editable = function (openerp) { cancelled.resolve(); } cancelled.then(function () { + self.view.unpad_columns(); self.edition_form.stop(); self.edition_form.$element.remove(); delete self.edition_form; @@ -183,7 +185,7 @@ openerp.web.list_editable = function (openerp) { template: 'ListView.row.form', registry: openerp.web.list.form.widgets }); - $.when(self.edition_form.on_loaded({fields_view: self.get_form_fields_view()})).then(function () { + $.when(self.edition_form.on_loaded(self.get_form_fields_view())).then(function () { // put in $.when just in case FormView.on_loaded becomes asynchronous $new_row.find('td') .addClass('oe-field-cell') @@ -197,6 +199,16 @@ openerp.web.list_editable = function (openerp) { $new_row.prepend('<td>'); } }); + // Add columns for the cancel and save buttons, if + // there are none in the list + if (!self.options.selectable) { + self.view.pad_columns( + 1, {except: $new_row, position: 'before'}); + } + if (!self.options.deletable) { + self.view.pad_columns( + 1, {except: $new_row}); + } self.edition_form.do_show(); }); diff --git a/addons/web/static/src/js/list.js b/addons/web/static/src/js/list.js index 6029b30f866..cca616d0055 100644 --- a/addons/web/static/src/js/list.js +++ b/addons/web/static/src/js/list.js @@ -27,7 +27,9 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# * See constructor parameters and method documentations for information on * the default behaviors and possible options for the list view. * - * @constructs + * @constructs openerp.web.ListView + * @extends openerp.web.View + * * @param parent parent object * @param element_id the id of the DOM elements this view should link itself to * @param {openerp.web.DataSet} dataset the dataset the view should work with @@ -49,6 +51,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# this.dataset = dataset; this.model = dataset.model; this.view_id = view_id; + this.previous_colspan = null; this.columns = []; @@ -58,6 +61,13 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# if (this.dataset instanceof openerp.web.DataSetStatic) { this.groups.datagroup = new openerp.web.StaticDataGroup(this.dataset); + } else { + this.groups.datagroup = new openerp.web.DataGroup( + this, this.model, + dataset.get_domain(), + dataset.get_context(), + {}); + this.groups.datagroup.sort = this.dataset._sort; } this.page = 0; @@ -346,7 +356,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# if (this.sidebar) { this.sidebar.$element.show(); } - if (this.hidden) { + if (!_(this.dataset.ids).isEmpty()) { this.reload_content(); } }, @@ -355,7 +365,6 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# if (this.sidebar) { this.sidebar.$element.hide(); } - this.hidden = true; }, /** * Reloads the list view based on the current settings (dataset & al) @@ -603,6 +612,49 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# get_selected_ids: function() { var ids = this.groups.get_selection().ids; return ids; + }, + /** + * Adds padding columns at the start or end of all table rows (including + * field names row) + * + * @param {Number} count number of columns to add + * @param {Object} options + * @param {"before"|"after"} [position="after"] insertion position for the new columns + * @param {Object} [except] content row to not pad + */ + pad_columns: function (count, options) { + options = options || {}; + // padding for action/pager header + var $first_header = this.$element.find('thead tr:first th'); + var colspan = $first_header.attr('colspan'); + if (colspan) { + if (!this.previous_colspan) { + this.previous_colspan = colspan; + } + $first_header.attr('colspan', parseInt(colspan, 10) + count); + } + // Padding for column titles, footer and data rows + var $rows = this.$element + .find('.oe-listview-header-columns, tr:not(thead tr)') + .not(options['except']); + var newcols = new Array(count+1).join('<td class="oe-listview-padding"></td>'); + if (options.position === 'before') { + $rows.prepend(newcols); + } else { + $rows.append(newcols); + } + }, + /** + * Removes all padding columns of the table + */ + unpad_columns: function () { + this.$element.find('.oe-listview-padding').remove(); + if (this.previous_colspan) { + this.$element + .find('thead tr:first th') + .attr('colspan', this.previous_colspan); + this.previous_colspan = null; + } } }); openerp.web.ListView.List = openerp.web.Class.extend( /** @lends openerp.web.ListView.List# */{ @@ -630,7 +682,9 @@ openerp.web.ListView.List = openerp.web.Class.extend( /** @lends openerp.web.Lis * Triggered when a row of the table is clicked, provides the index (in * the rows array) and id of the selected record to the handle function. * - * @constructs + * @constructs openerp.web.ListView.List + * @extends openerp.web.Class + * * @param {Object} opts display options, identical to those of :js:class:`openerp.web.ListView` */ init: function (group, opts) { @@ -835,7 +889,9 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L * Provides events similar to those of * :js:class:`~openerp.web.ListView.List` * - * @constructs + * @constructs openerp.web.ListView.Groups + * @extends openerp.web.Class + * * @param {openerp.web.ListView} view * @param {Object} [options] * @param {Collection} [options.records] @@ -1168,10 +1224,9 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L }); /** - * @class - * @extends openerp.web.Class + * @mixin Events */ -var Events = { +var Events = /** @lends Events# */{ /** * @param {String} event event to listen to on the current object, null for all events * @param {Function} handler event handler to bind to the relevant event @@ -1221,10 +1276,10 @@ var Events = { }; var Record = openerp.web.Class.extend(/** @lends Record# */{ /** - * @constructs + * @constructs Record * @extends openerp.web.Class - * @borrows Events#bind as this.bind - * @borrows Events#trigger as this.trigger + * + * @mixes Events * @param {Object} [data] */ init: function (data) { @@ -1288,10 +1343,10 @@ var Collection = openerp.web.Class.extend(/** @lends Collection# */{ * Using a "dumb" array of records makes synchronization between the * various serious * - * @constructs + * @constructs Collection * @extends openerp.web.Class - * @borrows Events#bind as this.bind - * @borrows Events#trigger as this.trigger + * + * @mixes Events * @param {Array} [records] records to initialize the collection with * @param {Object} [options] */ diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index 272e96b7d01..21f397c0867 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -1,7 +1,17 @@ openerp.web.search = function(openerp) { var QWeb = openerp.web.qweb; -openerp.web.SearchView = openerp.web.Widget.extend({ +openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.SearchView# */{ + /** + * @constructs openerp.web.SearchView + * @extends openerp.web.Widget + * + * @param parent + * @param element_id + * @param dataset + * @param view_id + * @param defaults + */ init: function(parent, element_id, dataset, view_id, defaults) { this._super(parent, element_id); this.dataset = dataset; @@ -380,7 +390,9 @@ openerp.web.search.Invalid = openerp.web.Class.extend( /** @lends openerp.web.se * Exception thrown by search widgets when they hold invalid values, * which they can not return when asked. * - * @constructs + * @constructs openerp.web.search.Invalid + * @extends openerp.web.Class + * * @param field the name of the field holding an invalid value * @param value the invalid value * @param message validation failure message @@ -400,7 +412,7 @@ openerp.web.search.Widget = openerp.web.Widget.extend( /** @lends openerp.web.se /** * Root class of all search widgets * - * @constructs + * @constructs openerp.web.search.Widget * @extends openerp.web.Widget * * @param view the ancestor view of this widget @@ -452,8 +464,18 @@ openerp.web.search.Widget = openerp.web.Widget.extend( /** @lends openerp.web.se })); } }); -openerp.web.search.FilterGroup = openerp.web.search.Widget.extend({ +openerp.web.search.FilterGroup = openerp.web.search.Widget.extend(/** @lends openerp.web.search.FilterGroup# */{ template: 'SearchView.filters', + /** + * Inclusive group of filters, creates a continuous "button" with clickable + * sections (the normal display for filters is to be a self-contained button) + * + * @constructs openerp.web.search.FilterGroup + * @extends openerp.web.search.Widget + * + * @param {Array<openerp.web.search.Filter>} filters elements of the group + * @param {openerp.web.SearchView} view view in which the filters are contained + */ init: function (filters, view) { this._super(view); this.filters = filters; @@ -494,7 +516,7 @@ openerp.web.search.Group = openerp.web.search.Widget.extend({ openerp.web.search.Input = openerp.web.search.Widget.extend( /** @lends openerp.web.search.Input# */{ /** - * @constructs + * @constructs openerp.web.search.Input * @extends openerp.web.search.Widget * * @param view @@ -512,8 +534,18 @@ openerp.web.search.Input = openerp.web.search.Widget.extend( /** @lends openerp. "get_domain not implemented for widget " + this.attrs.type); } }); -openerp.web.search.Filter = openerp.web.search.Input.extend({ +openerp.web.search.Filter = openerp.web.search.Input.extend(/** @lends openerp.web.search.Filter# */{ template: 'SearchView.filter', + /** + * Implementation of the OpenERP filters (button with a context and/or + * a domain sent as-is to the search view) + * + * @constructs openerp.web.search.Filter + * @extends openerp.web.search.Input + * + * @param node + * @param view + */ init: function (node, view) { this._super(view); this.attrs = node.attrs; @@ -566,7 +598,7 @@ openerp.web.search.Field = openerp.web.search.Input.extend( /** @lends openerp.w template: 'SearchView.field', default_operator: '=', /** - * @constructs + * @constructs openerp.web.search.Field * @extends openerp.web.search.Input * * @param view_section @@ -694,7 +726,7 @@ openerp.web.search.SelectionField = openerp.web.search.Field.extend(/** @lends o }); openerp.web.search.BooleanField = openerp.web.search.SelectionField.extend(/** @lends openerp.web.search.BooleanField# */{ /** - * @constructs + * @constructs openerp.web.search.BooleanField * @extends openerp.web.search.BooleanField */ init: function () { @@ -729,7 +761,11 @@ openerp.web.search.BooleanField = openerp.web.search.SelectionField.extend(/** @ } } }); -openerp.web.search.DateField = openerp.web.search.Field.extend( /** @lends openerp.web.search.DateField# */{ +/** + * @class + * @extends openerp.web.search.DateField + */ +openerp.web.search.DateField = openerp.web.search.Field.extend(/** @lends openerp.web.search.DateField# */{ /** * enables date picker on the HTML widgets */ @@ -944,9 +980,16 @@ openerp.web.search.ExtendedSearchGroup = openerp.web.OldWidget.extend({ } }); -openerp.web.search.ExtendedSearchProposition = openerp.web.OldWidget.extend({ +openerp.web.search.ExtendedSearchProposition = openerp.web.OldWidget.extend(/** @lends openerp.web.search.ExtendedSearchProposition# */{ template: 'SearchView.extended_search.proposition', identifier_prefix: 'extended-search-proposition', + /** + * @constructs openerp.web.search.ExtendedSearchProposition + * @extends openerp.web.OldWidget + * + * @param parent + * @param fields + */ init: function (parent, fields) { this._super(parent); this.fields = _(fields).chain() diff --git a/addons/web/static/src/js/view_tree.js b/addons/web/static/src/js/view_tree.js index a71e4010fcf..2a314f57fa8 100644 --- a/addons/web/static/src/js/view_tree.js +++ b/addons/web/static/src/js/view_tree.js @@ -6,16 +6,24 @@ openerp.web.view_tree = function(openerp) { var QWeb = openerp.web.qweb; openerp.web.views.add('tree', 'openerp.web.TreeView'); -/** - * Genuine tree view (the one displayed as a tree, not the list) - */ -openerp.web.TreeView = openerp.web.View.extend({ +openerp.web.TreeView = openerp.web.View.extend(/** @lends openerp.web.TreeView# */{ /** * Indicates that this view is not searchable, and thus that no search * view should be displayed (if there is one active). */ searchable : false, - + /** + * Genuine tree view (the one displayed as a tree, not the list) + * + * @constructs openerp.web.TreeView + * @extends openerp.web.View + * + * @param parent + * @param element_id + * @param dataset + * @param view_id + * @param options + */ init: function(parent, element_id, dataset, view_id, options) { this._super(parent, element_id); this.dataset = dataset; diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 2c616359f01..6c10174d109 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -115,7 +115,7 @@ openerp.web.ActionManager = openerp.web.Widget.extend({ var self = this; this.rpc('/web/action/run', { action_id: action.id, - context: {active_id: 66, active_ids: [66], active_model: 'ir.ui.menu'} + context: action.context || {} }).then(function (action) { self.do_action(action, on_closed) }); @@ -135,8 +135,17 @@ openerp.web.ActionManager = openerp.web.Widget.extend({ } }); -openerp.web.ViewManager = openerp.web.Widget.extend({ +openerp.web.ViewManager = openerp.web.Widget.extend(/** @lends openerp.web.ViewManager# */{ identifier_prefix: "viewmanager", + template: "ViewManager", + /** + * @constructs openerp.web.ViewManager + * @extends openerp.web.Widget + * + * @param parent + * @param dataset + * @param views + */ init: function(parent, dataset, views) { this._super(parent); this.model = dataset.model; @@ -149,7 +158,7 @@ openerp.web.ViewManager = openerp.web.Widget.extend({ this.registry = openerp.web.views; }, render: function() { - return QWeb.render("ViewManager", {"prefix": this.element_id, views: this.views_src}) + return QWeb.render(this.template, {"prefix": this.element_id, views: this.views_src}) }, /** * @returns {jQuery.Deferred} initial view loading promise @@ -257,7 +266,7 @@ openerp.web.ViewManager = openerp.web.Widget.extend({ /** * Sets up the current viewmanager's search view. * - * @param view_id the view to use or false for a default one + * @param {Number|false} view_id the view to use or false for a default one * @returns {jQuery.Deferred} search view startup deferred */ setup_search_view: function(view_id, search_defaults) { @@ -265,10 +274,10 @@ openerp.web.ViewManager = openerp.web.Widget.extend({ if (this.searchview) { this.searchview.stop(); } - this.searchview = new openerp.web.SearchView(this, this.element_id + "_search", this.dataset, view_id, search_defaults); - if (this.flags.search_view === false) { - this.searchview.hide(); - } + this.searchview = new openerp.web.SearchView( + this, this.element_id + "_search", this.dataset, + view_id, search_defaults); + this.searchview.on_search.add(function(domains, contexts, groupbys) { var controller = self.views[self.active_view].controller; controller.do_search.call(controller, domains, contexts, groupbys); @@ -288,50 +297,65 @@ openerp.web.ViewManager = openerp.web.Widget.extend({ } }); -openerp.web.ViewManagerAction = openerp.web.ViewManager.extend({ +openerp.web.ViewManagerAction = openerp.web.ViewManager.extend(/** @lends oepnerp.web.ViewManagerAction# */{ + template:"ViewManagerAction", + /** + * @constructs openerp.web.ViewManagerAction + * @extends openerp.web.ViewManager + * + * @param {openerp.web.ActionManager} parent parent object/widget + * @param {Object} action descriptor for the action this viewmanager needs to manage its views. + */ init: function(parent, action) { + // dataset initialization will take the session from ``this``, so if we + // do not have it yet (and we don't, because we've not called our own + // ``_super()``) rpc requests will blow up. this.session = parent.session; this.action = action; - var dataset; - if (!action.res_id) { - dataset = new openerp.web.DataSetSearch(this, action.res_model, action.context, action.domain); - } else { - this.action.flags.search_view = false; - dataset = new openerp.web.DataSetStatic(this, action.res_model, action.context, [action.res_id]); + var dataset = new openerp.web.DataSetSearch(this, action.res_model, action.context, action.domain); + if (action.res_id) { + dataset.ids.push(action.res_id); dataset.index = 0; } this._super(parent, dataset, action.views); - this.action = action; this.flags = this.action.flags || {}; if (action.res_model == 'board.board' && action.views.length == 1 && action.views) { - // Not elegant but allows to avoid flickering of SearchView#do_hide + // Not elegant but allows to avoid form chrome (pager, save/new + // buttons, sidebar, ...) displaying this.flags.search_view = this.flags.pager = this.flags.sidebar = this.flags.action_buttons = false; } }, + /** + * Initializes the ViewManagerAction: sets up the searchview (if the + * searchview is enabled in the manager's action flags), calls into the + * parent to initialize the primary view and (if the VMA has a searchview) + * launches an initial search after both views are done rendering. + */ start: function() { - var inital_view_loaded = this._super(); - - var search_defaults = {}; - _.each(this.action.context, function (value, key) { - var match = /^search_default_(.*)$/.exec(key); - if (match) { - search_defaults[match[1]] = value; - } - }); - + var searchview_loaded; if (this.flags.search_view !== false) { + var search_defaults = {}; + _.each(this.action.context, function (value, key) { + var match = /^search_default_(.*)$/.exec(key); + if (match) { + search_defaults[match[1]] = value; + } + }); // init search view - var searchview_id = this.action.search_view_id && this.action.search_view_id[0]; + var searchview_id = this.action['search_view_id'] && this.action['search_view_id'][0]; - var searchview_loaded = this.setup_search_view( + searchview_loaded = this.setup_search_view( searchview_id || false, search_defaults); + } + + var main_view_loaded = this._super(); + var manager_ready = $.when(searchview_loaded, main_view_loaded); + if (searchview_loaded && this.action['auto_search']) { // schedule auto_search - if (searchview_loaded != null && this.action['auto_search']) { - $.when(searchview_loaded, inital_view_loaded) - .then(this.searchview.do_search); - } + manager_ready.then(this.searchview.do_search); } + return manager_ready; }, on_mode_switch: function (view_type) { return $.when( @@ -444,7 +468,11 @@ openerp.web.Sidebar = openerp.web.Widget.extend({ if (item.action) { var ids = self.widget_parent.get_selected_ids(); if (ids.length == 0) { - //TODO niv: maybe show a warning? + //TODO: make prettier warning? + $("<div />").text(_t("You must choose at least one record.")).dialog({ + title: _t("Warning"), + modal: true + }); return false; } var additional_context = { @@ -454,7 +482,7 @@ openerp.web.Sidebar = openerp.web.Widget.extend({ }; self.rpc("/web/action/load", { action_id: item.action.id, - context: _.extend({"bin_size": true}, additional_context) + context: additional_context }, function(result) { result.result.context = _.extend(result.result.context || {}, additional_context); @@ -613,7 +641,11 @@ openerp.web.TranslateDialog = openerp.web.Dialog.extend({ } }); -openerp.web.View = openerp.web.Widget.extend({ +/** + * @class + * @extends openerp.web.Widget + */ +openerp.web.View = openerp.web.Widget.extend(/** @lends openerp.web.View# */{ set_default_options: function(options) { this.options = options || {}; _.defaults(this.options, { @@ -653,6 +685,7 @@ openerp.web.View = openerp.web.Widget.extend({ active_ids: [record_id || false], active_model: dataset.model }); + action.context = new openerp.web.CompoundContext(dataset.get_context(), action.context); self.do_action(action, on_closed); } else if (on_closed) { on_closed(action); @@ -675,7 +708,7 @@ openerp.web.View = openerp.web.Widget.extend({ * Directly set a view to use instead of calling fields_view_get. This method must * be called before start(). When an embedded view is set, underlying implementations * of openerp.web.View must use the provided view instead of any other one. - * + * * @param embedded_view A view. */ set_embedded_view: function(embedded_view) { diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 677488d9d7d..1b1745036c4 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -40,7 +40,7 @@ <tr> <td valign="top" id="oe_secondary_menu" class="secondary_menu"> </td> - <td valign="top"> + <td valign="top" class="oe-application-container"> <div id="oe_app" class="oe-application"> </div> </td> @@ -420,8 +420,6 @@ <table class="view-manager-main-table"> <tr> <td class="view-manager-main-content"> - <a class="oe-shortcut-toggle" title="Add / Remove Shortcut..." - href="javascript: void(0)"> </a> <div class="oe_vm_switch"> <t t-if="views.length != 1" t-foreach="views" t-as="view"> <button type="button" t-att-data-view-type="view.view_type"> @@ -442,6 +440,14 @@ </tr> </table> </t> + +<t t-extend="ViewManager" t-name="ViewManagerAction"> + <t t-jquery=".view-manager-main-content" t-operation="prepend"> + <a class="oe-shortcut-toggle" title="Add / Remove Shortcut..." + href="javascript: void(0)"> </a> + </t> +</t> + <t t-name="Sidebar"> <a class="toggle-sidebar"></a> <div class="sidebar-content"> @@ -566,7 +572,7 @@ </table> </th> </tr> - <tr t-if="options.header"> + <tr t-if="options.header" class="oe-listview-header-columns"> <t t-foreach="columns" t-as="column"> <th t-if="column.meta"> <t t-esc="column.string"/> @@ -799,10 +805,8 @@ t-att-id="widget.element_id + '_field'" t-att-class="'field_' + widget.type" style="width: 100%"> - <t t-foreach="widget.field_index" t-as="options"> - <option t-att-value="options.ikey"> - <t t-esc="options.label"/> - </option> + <t t-foreach="widget.values" t-as="option"> + <option><t t-esc="option[1]"/></option> </t> </select> </t> @@ -1113,7 +1117,8 @@ <div t-att-id="element_id"> <select class="searchview_extended_prop_field"> <t t-foreach="attrs.fields" t-as="field"> - <option t-att="{'selected': field === attrs.selected ? 'selected' : null}" + <option t-if="typeof field.store === 'undefined' || field.store || field.fnct_search" + t-att="{'selected': field === attrs.selected ? 'selected' : null}" t-att-value="field.name"> <t t-esc="field.string"/> </option> @@ -1388,4 +1393,17 @@ </p> </div> </t> +<t t-name="FieldStatus"> + <div t-att-id="widget.element_id"></div> +</t> +<t t-name="FieldStatus.content"> + <ul class="oe-arrow-list"> + <t t-set="size" t-value="widget.to_show.length"/> + <t t-foreach="_.range(size)" t-as="i"> + <li t-att-class="widget.to_show[i][0] === widget.selected_value ? 'oe-arrow-list-selected' : ''"> + <span class="oe-arrow-list-before" t-if="i > 0"></span><span><t t-esc="widget.to_show[i][1]"/></span><span class="oe-arrow-list-after" t-if="i < size - 1"></span> + </li> + </t> + </ul> +</t> </templates> |
