diff options
| author | Darshan Kalola (OpenERP) <dka@tinyerp.com> | 2014-04-15 14:50:51 +0530 |
|---|---|---|
| committer | Darshan Kalola (OpenERP) <dka@tinyerp.com> | 2014-04-15 14:50:51 +0530 |
| commit | 9f72ddbeacd2c4af9f1c618bdb3a5fa9e478119f (patch) | |
| tree | ad72fd57e7b22a8aa75aeba0aa294d756425f9ca /addons/web/static/src | |
| parent | ad99e8cfaebd2d686d48f6d7928ebefaa852d547 (diff) | |
| parent | 6b020549f8e9e12acd0385e4dd0708137042bf20 (diff) | |
[MERGE]sync with trunk.
bzr revid: dka@tinyerp.com-20140415092051-ph2i1zzxji7evwuq
Diffstat (limited to 'addons/web/static/src')
| -rw-r--r-- | addons/web/static/src/css/base.css | 222 | ||||
| -rw-r--r-- | addons/web/static/src/css/base.sass | 171 | ||||
| -rw-r--r-- | addons/web/static/src/js/chrome.js | 175 | ||||
| -rw-r--r-- | addons/web/static/src/js/core.js | 7 | ||||
| -rw-r--r-- | addons/web/static/src/js/data.js | 53 | ||||
| -rw-r--r-- | addons/web/static/src/js/data_export.js | 2 | ||||
| -rw-r--r-- | addons/web/static/src/js/search.js | 3 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_form.js | 145 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_list.js | 3 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_list_editable.js | 11 | ||||
| -rw-r--r-- | addons/web/static/src/js/views.js | 22 | ||||
| -rw-r--r-- | addons/web/static/src/xml/base.xml | 32 |
12 files changed, 402 insertions, 444 deletions
diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index 6a20442ed41..ace5ef2dbf6 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -1,4 +1,4 @@ -@charset "utf-8"; +@charset "UTF-8"; @font-face { font-family: "mnmliconsRegular"; src: url("/web/static/src/font/mnmliconsv21-webfont.eot") format("eot"); @@ -127,7 +127,7 @@ font-weight: bold; font-size: inherit; } -.openerp a.button:link, .openerp a.button:visited, .openerp button, .openerp .oe_button, .openerp input[type='submit'], .openerp .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button { +.openerp a.button:link, .openerp a.button:visited, .openerp button, .openerp .oe_button, .openerp input[type='submit'] { display: inline-block; border: 1px solid rgba(0, 0, 0, 0.4); color: #4c4c4c; @@ -152,7 +152,7 @@ -webkit-font-smoothing: antialiased; outline: none; } -.openerp a.button:hover, .openerp button:hover, .openerp .oe_button:hover, .openerp input[type='submit']:hover, .openerp .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button.ui-state-hover { +.openerp a.button:hover, .openerp button:hover, .openerp .oe_button:hover, .openerp input[type='submit']:hover { background-color: #ececec; background-image: -webkit-gradient(linear, left top, left bottom, from(#f6f6f6), to(#e3e3e3)); background-image: -webkit-linear-gradient(top, #f6f6f6, #e3e3e3); @@ -163,7 +163,7 @@ cursor: pointer; background-position: 0; } -.openerp a.button:focus, .openerp button:focus, .openerp .oe_button:focus, .openerp input[type='submit']:focus, .openerp .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button.ui-state-focus { +.openerp a.button:focus, .openerp button:focus, .openerp .oe_button:focus, .openerp input[type='submit']:focus { border: 1px solid #80bfff; background-position: 0; background-color: #ececec; @@ -177,7 +177,7 @@ -webkit-box-shadow: 0 0 3px #80bfff, 0 1px 1px rgba(255, 255, 255, 0.8) inset; box-shadow: 0 0 3px #80bfff, 0 1px 1px rgba(255, 255, 255, 0.8) inset; } -.openerp a.button:active, .openerp a.button.active, .openerp button:active, .openerp .oe_button:active, .openerp .oe_button.active, .openerp input[type='submit']:active, .openerp input[type='submit'].active, .openerp .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button.ui-state-active { +.openerp a.button:active, .openerp a.button.active, .openerp button:active, .openerp .oe_button:active, .openerp .oe_button.active, .openerp input[type='submit']:active, .openerp input[type='submit'].active { background-color: #ececec; background-image: -webkit-gradient(linear, left top, left bottom, from(#e3e3e3), to(#f6f6f6)); background-image: -webkit-linear-gradient(top, #e3e3e3, #f6f6f6); @@ -212,148 +212,6 @@ .openerp .ui-tabs { position: static; } -.openerp.ui-dialog { - display: none; - height: auto !important; - padding: 6px; - background-color: rgba(60, 60, 60, 0.7); - border: 1px solid; - border-color: #888888 #555555 #444444; - -moz-border-radius: 8px; - -webkit-border-radius: 8px; - border-radius: 8px; - -moz-box-shadow: 0 1px 12px rgba(0, 0, 0, 0.6); - -webkit-box-shadow: 0 1px 12px rgba(0, 0, 0, 0.6); - box-shadow: 0 1px 12px rgba(0, 0, 0, 0.6); - -webkit-background-clip: padding-box; - -moz-background-clip: padding-box; - background-clip: padding-box; -} -.openerp.ui-dialog .ui-dialog-content { - padding: 0; -} -.openerp.ui-dialog .ui-dialog-titlebar, .openerp.ui-dialog .ui-dialog-content, .openerp.ui-dialog .ui-dialog-buttonpane { - padding: 16px; -} -.openerp.ui-dialog .ui-dialog-titlebar { - border-top: none; - border-left: none; - border-right: none; - border-bottom: 1px solid #cacaca; - -moz-border-radius: 2px 2px 0 0; - -webkit-border-radius: 2px 2px 0 0; - border-radius: 2px 2px 0 0; - background-color: #ededed; - background-image: -webkit-gradient(linear, left top, left bottom, from(#fcfcfc), to(#dedede)); - background-image: -webkit-linear-gradient(top, #fcfcfc, #dedede); - background-image: -moz-linear-gradient(top, #fcfcfc, #dedede); - background-image: -ms-linear-gradient(top, #fcfcfc, #dedede); - background-image: -o-linear-gradient(top, #fcfcfc, #dedede); - background-image: linear-gradient(to bottom, #fcfcfc, #dedede); -} -.openerp.ui-dialog .ui-dialog-titlebar .ui-dialog-title { - margin: 0; - padding: 0; -} -.openerp.ui-dialog .ui-dialog-content { - background: white; - width: auto !important; -} -.openerp.ui-dialog .ui-dialog-buttonpane { - border-top: 1px solid #e0e0e0; - background: #f5f7f9; - margin: 0; - -moz-border-radius: 0 0 2px 2px; - -webkit-border-radius: 0 0 2px 2px; - border-radius: 0 0 2px 2px; -} -.openerp.ui-dialog .ui-dialog-buttonpane button { - margin: 0 4px 0 0; -} -.openerp.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { - float: left; -} -.openerp.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button { - margin-right: 4px; -} -.openerp.ui-dialog .ui-dialog-titlebar-close { - padding: 0; -} -.openerp.ui-dialog .ui-dialog-titlebar-close .ui-icon-closethick { - display: none; -} -.openerp.ui-dialog .ui-dialog-titlebar-close:before { - content: "×"; - font-size: 18px; - font-weight: bold; - line-height: 16px; - color: black; - text-shadow: 0 1px 0 white; - padding: 0; - cursor: pointer; - background: transparent; - border: 0; -} -.openerp.ui-dialog .ui-dialog-titlebar-close:before:hover { - color: black; - text-decoration: none; -} -.openerp.ui-dialog .oe_about { - background-color: white; - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=); - -moz-border-radius: 0 0 2px 2px; - -webkit-border-radius: 0 0 2px 2px; - border-radius: 0 0 2px 2px; -} -.openerp.ui-dialog .oe_about a { - color: #7c7bad; -} -.openerp.ui-dialog .oe_about a:hover { - text-decoration: underline; -} -.openerp.ui-dialog .oe_about a:focus { - outline: none; -} -.openerp.ui-dialog .oe_about .oe_logo { - margin-left: -6px; -} -.openerp.ui-dialog .oe_about .oe_bottom { - position: absolute; - top: 50%; - left: 0; - right: 0; - bottom: 0; - text-shadow: 0 1px 1px #999999; - background-color: #8a0e0e; - background-image: -webkit-gradient(linear, left top, left bottom, from(#b41616), to(#600606)); - background-image: -webkit-linear-gradient(top, #b41616, #600606); - background-image: -moz-linear-gradient(top, #b41616, #600606); - background-image: -ms-linear-gradient(top, #b41616, #600606); - background-image: -o-linear-gradient(top, #b41616, #600606); - background-image: linear-gradient(to bottom, #b41616, #600606); - color: #eeeeee; - padding: 0 16px; - -moz-border-radius: 0 0 2px 2px; - -webkit-border-radius: 0 0 2px 2px; - border-radius: 0 0 2px 2px; -} -.openerp.ui-dialog .oe_about .oe_bottom a { - color: #eeeeee; -} -.openerp.ui-dialog.oe_act_window .ui-dialog-content { - padding: 0px; -} -.openerp .modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: black; - filter: alpha(opacity=30); - opacity: 0.3; -} .openerp .oe_i { font-family: "mnmliconsRegular" !important; font-size: 21px; @@ -368,6 +226,7 @@ .openerp .oe_left { float: left; margin-right: 8px; + width: 305px; } .openerp .oe_right { float: right; @@ -456,11 +315,46 @@ background: #ed6f6a; } .openerp .oe_button_box { - width: 270px; - text-align: right; + width: 400px; + text-align: left; +} +.openerp .oe_button_box .oe_stat_button:hover { + background: #7c7bad; + color: white; +} +.openerp .oe_button_box .oe_stat_button:hover .fa { + color: white; +} +.openerp .oe_button_box .oe_stat_button { + font-weight: normal; + display: inline-table; + width: 33% !important; + height: 42px; + margin: 0px -1px -1px 0px; + padding: 0; + color: #666666; + border: 1px solid #dddddd; + border-radius: 0; + box-shadow: none; + background: white; +} +.openerp .oe_button_box .oe_stat_button > div { + display: table-cell; + vertical-align: middle; + text-align: left; + padding: 0; + line-height: 120%; } -.openerp .oe_button_box button { - margin: 4px; +.openerp .oe_button_box .oe_stat_button .stat_button_icon { + color: #7c7bad; + font-size: 24px; + padding: 0px 3px; + width: 37px; + text-align: center; +} +.openerp .oe_button_box .oe_stat_button svg { + width: 38px; + height: 38px; } .openerp .oe_avatar > img { max-height: 90px; @@ -1197,11 +1091,6 @@ margin-left: -6px; } .openerp .oe_about .oe_bottom { - position: absolute; - top: 50%; - left: 0; - right: 0; - bottom: 0; text-shadow: 0 1px 1px #999999; background-color: #8a0e0e; background-image: -webkit-gradient(linear, left top, left bottom, from(#b41616), to(#600606)); @@ -1248,12 +1137,14 @@ width: 100%; } .openerp .oe_view_manager .oe_view_manager_body { - display: table-row; height: inherit; } .openerp .oe_view_manager .oe_view_manager_view_kanban:not(:empty) { height: inherit; } +.openerp .oe_view_manager[data-view-type=kanban] .oe_view_manager_body { + display: table-row; +} .openerp .oe_view_manager table.oe_view_manager_header { border-collapse: separate; width: 100%; @@ -3387,9 +3278,6 @@ body.oe_single_form .oe_single_form_container { .openerp_ie ul.oe_form_status li.oe_active > .arrow span, .openerp_ie ul.oe_form_status_clickable li.oe_active > .arrow span { background-color: #729fcf !important; } -.openerp_ie .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button { - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#EFEFEF', endColorstr='#D8D8D8'); -} @media print { .openerp { @@ -3435,7 +3323,19 @@ body.oe_single_form .oe_single_form_container { width: 18px; height: 18px; } - +.modal .modal-header button.close { + border: none; + background: none; + padding: 1px; + height: 18px; + font-size: 20px; +} +.modal .modal-footer { + text-align: left; +} +.modal .oe_act_window.modal-body{ + padding: 0; +} input[type="radio"], input[type="checkbox"] { margin-right: 4px; margin-left: 4px; diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass index 38a47eed1c5..c148d95d7b1 100644 --- a/addons/web/static/src/css/base.sass +++ b/addons/web/static/src/css/base.sass @@ -218,7 +218,7 @@ $sheet-padding: 16px font-size: inherit // }}} // Button style {{{ - a.button:link, a.button:visited, button, .oe_button, input[type='submit'], .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button + a.button:link, a.button:visited, button, .oe_button, input[type='submit'] display: inline-block border: 1px solid rgba(0,0,0,0.4) color: #4c4c4c @@ -233,18 +233,18 @@ $sheet-padding: 16px -webkit-font-smoothing: antialiased outline: none - a.button:hover, button:hover,.oe_button:hover, input[type='submit']:hover, .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button.ui-state-hover + a.button:hover, button:hover,.oe_button:hover, input[type='submit']:hover @include vertical-gradient(#f6f6f6, #e3e3e3) cursor: pointer background-position: 0 - a.button:focus, button:focus, .oe_button:focus, input[type='submit']:focus, .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button.ui-state-focus + a.button:focus, button:focus, .oe_button:focus, input[type='submit']:focus border: 1px solid #80bfff background-position: 0 @include vertical-gradient(#f6f6f6, #e3e3e3) @include box-shadow((0 0 3px #80bfff, 0 1px 1px rgba(255, 255, 255, .8) inset)) - a.button:active, a.button.active, button:active, .oe_button:active, .oe_button.active, input[type='submit']:active, input[type='submit'].active, .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button.ui-state-active + a.button:active, a.button.active, button:active, .oe_button:active, .oe_button.active, input[type='submit']:active, input[type='submit'].active @include vertical-gradient(#e3e3e3, #f6f6f6) @include box-shadow(none) @@ -272,105 +272,6 @@ $sheet-padding: 16px .ui-tabs position: static - // Modal box - &.ui-dialog - display: none - height: auto !important - padding: 6px - //overflow: hidden - background-color: rgba(60,60,60,0.7) - border: 1px solid - border-color: #888 #555 #444 - //overflow: hidden - @include radius(8px) - @include box-shadow(0 1px 12px rgba(0, 0, 0, 0.6)) - @include background-clip() - .ui-dialog-content - padding: 0 - .ui-dialog-titlebar, .ui-dialog-content, .ui-dialog-buttonpane - padding: 16px - .ui-dialog-titlebar - border-top: none - border-left: none - border-right: none - border-bottom: 1px solid #cacaca - @include radius(2px 2px 0 0) - @include vertical-gradient(#FCFCFC, #DEDEDE) - .ui-dialog-title - margin: 0 - padding: 0 - .ui-dialog-content - background: white - width: auto !important - .ui-dialog-buttonpane - border-top: 1px solid #e0e0e0 - background: #f5f7f9 - margin: 0 - @include radius(0 0 2px 2px) - button - margin: 0 4px 0 0 - .ui-dialog-buttonset - float: left - .ui-button - margin-right: 4px - .ui-dialog-titlebar-close - padding: 0 - .ui-icon-closethick - display: none - &:before - content: "×" - font-size: 18px - font-weight: bold - line-height: 16px - color: black - text-shadow: 0 1px 0 white - padding: 0 - cursor: pointer - background: transparent - border: 0 - &:hover - color: black - text-decoration: none - .oe_about - background-color: white - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=) - @include radius(0 0 2px 2px) - a - color: $link-color - &:hover - text-decoration: underline - &:focus - outline: none - .oe_logo - margin-left: -6px - .oe_bottom - position: absolute - top: 50% - left: 0 - right: 0 - bottom: 0 - text-shadow: 0 1px 1px #999999 - @include vertical-gradient(#b41616, #600606) - color: #eee - padding: 0 16px - @include radius(0 0 2px 2px) - a - color: #eee - - &.ui-dialog.oe_act_window - .ui-dialog-content - padding: 0px - - .modal-backdrop - position: fixed - top: 0 - right: 0 - bottom: 0 - left: 0 - z-index: 1040 - background-color: black - @include opacity(.3) - // }}} // Generic classes {{{ .oe_i @@ -385,6 +286,7 @@ $sheet-padding: 16px .oe_left float: left margin-right: 8px + width: 305px .oe_right float: right margin-left: 8px @@ -429,10 +331,40 @@ $sheet-padding: 16px &:hover background: #ED6F6A .oe_button_box - width: 270px - text-align: right - button - margin: 4px + width: 400px + text-align: left + .oe_stat_button:hover + background: #7c7bad + color: white + .fa + color: white + .oe_stat_button + font-weight: normal + display: inline-table + width: 33% !important + height: 42px + margin: 0px -1px -1px 0px + padding: 0 + color: #666 + border: 1px solid #dddddd + border-radius: 0 + box-shadow: none + background: white + > div + display: table-cell + vertical-align: middle + text-align: left + padding: 0 + line-height: 120% + .stat_button_icon + color: #7C7BAD + font-size: 24px + padding: 0px 3px + width: 37px + text-align: center + svg + width: 38px + height: 38px .oe_avatar > img max-height: 90px @@ -999,11 +931,6 @@ $sheet-padding: 16px .oe_logo margin-left: -6px .oe_bottom - position: absolute - top: 50% - left: 0 - right: 0 - bottom: 0 text-shadow: 0 1px 1px #999999 @include vertical-gradient(#b41616, #600606) color: #eee @@ -1037,10 +964,12 @@ $sheet-padding: 16px height: inherit width: 100% .oe_view_manager_body - display: table-row height: inherit .oe_view_manager_view_kanban:not(:empty) height: inherit + &[data-view-type=kanban] + .oe_view_manager_body + display: table-row table.oe_view_manager_header border-collapse: separate @@ -2731,9 +2660,6 @@ body.oe_single_form > .arrow span background-color: #729fcf !important - // jquery ui for ie - .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#EFEFEF', endColorstr='#D8D8D8') // }}} // @media print {{{ @@ -2778,6 +2704,19 @@ body.oe_single_form height: 18px // End hack}}} +// Customized modal according bootstrap3 +.modal + .modal-header button.close + border: none + background: none + padding: 1px + height: 18px + font-size: 20px + .modal-footer + text-align: left + .oe_act_window.modal-body + padding: 0 + input[type="radio"], input[type="checkbox"] margin-right: 4px margin-left: 4px diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index 8e5df84e2c3..b3fbb35134b 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -57,16 +57,6 @@ instance.web.action_warn = function(element, action) { instance.web.client_actions.add("action_warn", "instance.web.action_warn"); /** - * The very minimal function everything should call to create a dialog - * in OpenERP Web Client. - */ -instance.web.dialog = function(element) { - var result = element.dialog.apply(element, _.rest(_.toArray(arguments))); - result.dialog("widget").openerpClass(); - return result; -}; - -/** A useful class to handle dialogs. Attributes: @@ -81,6 +71,8 @@ instance.web.Dialog = instance.web.Widget.extend({ @param {Widget} parent @param {dictionary} options A dictionary that will be forwarded to jQueryUI Dialog. Additionaly, that dictionary can contain the following keys: + - size: one of the following: 'large', 'medium', 'small' + - dialogClass: class to add to the body of dialog - buttons: Deprecated. The buttons key is not propagated to jQueryUI Dialog. It must be a dictionary (key = button label, value = click handler) or a list of dictionaries (each element in the dictionary is send to the corresponding method of a jQuery element targeting the <button> tag). It is deprecated because all dialogs @@ -94,60 +86,15 @@ instance.web.Dialog = instance.web.Widget.extend({ this._super(parent); this.content_to_set = content; this.dialog_options = { - modal: true, destroy_on_close: true, - width: 900, - min_width: 0, - max_width: '95%', - height: 'auto', - min_height: 0, - max_height: $(window.top).height() - 200, - autoOpen: false, - position: [false, 40], + size: 'large', //'medium', 'small' buttons: null, - beforeClose: function () { - self.trigger("closing"); - }, - resizeStop: function() { - self.trigger("resized"); - }, }; if (options) { _.extend(this.dialog_options, options); } this.on("closing", this, this._closing); - this.$buttons = $('<div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"><span class="oe_dialog_custom_buttons"/></div>'); - }, - _get_options: function() { - var self = this; - var o = _.extend({}, this.dialog_options); - var sizes = { - width: $(window.top).width(), - height: $(window.top).height(), - }; - _.each(sizes, function(available_size, unit) { - o[unit] = self._get_size(o[unit], available_size); - o['min_' + unit] = self._get_size(o['min_' + unit] || 0, available_size); - o['max_' + unit] = self._get_size(o['max_' + unit] || 0, available_size); - if (o[unit] !== 'auto' && o['min_' + unit] && o[unit] < o['min_' + unit]) { - o[unit] = o['min_' + unit]; - } - if (o[unit] !== 'auto' && o['max_' + unit] && o[unit] > o['max_' + unit]) { - o[unit] = o['max_' + unit]; - } - }); - o.title = o.title || this.dialog_title; - return o; - }, - _get_size: function(val, available_size) { - val = val.toString(); - if (val === 'auto') { - return val; - } else if (val.slice(-1) === "%") { - return Math.round(available_size / 100 * parseInt(val.slice(0, -1), 10)); - } else { - return parseInt(val, 10); - } + this.$buttons = $('<div class="modal-footer"><span class="oe_dialog_custom_buttons"/></div>'); }, renderElement: function() { if (this.content_to_set) { @@ -165,8 +112,7 @@ instance.web.Dialog = instance.web.Widget.extend({ if (!this.dialog_inited) { this.init_dialog(); } - this.$el.dialog('open'); - this.$el.dialog("widget").append(this.$buttons); + this.$buttons.insertAfter(this.$dialog_box.find(".modal-body")); return this; }, _add_buttons: function(buttons) { @@ -191,16 +137,39 @@ instance.web.Dialog = instance.web.Widget.extend({ @return The result returned by start(). */ init_dialog: function() { - var options = this._get_options(); + var self = this; + var options = _.extend({}, this.dialog_options); + options.title = options.title || this.dialog_title; if (options.buttons) { this._add_buttons(options.buttons); delete(options.buttons); } this.renderElement(); - instance.web.dialog(this.$el, options); - if (options.height === 'auto' && options.max_height) { - this.$el.css({ 'max-height': options.max_height, 'overflow-y': 'auto' }); + + this.$dialog_box = $(QWeb.render('Dialog', options)).appendTo("body"); + this.$el.modal({ + 'backdrop': false, + 'keyboard': true, + }); + if (options.size !== 'large'){ + var dialog_class_size = this.$dialog_box.find('.modal-lg').removeClass('modal-lg') + if (options.size === 'small'){ + dialog_class_size.addClass('modal-sm'); + } } + + this.$el.appendTo(this.$dialog_box.find(".modal-body")); + var $dialog_content = this.$dialog_box.find('.modal-content'); + if (options.dialogClass){ + $dialog_content.find(".modal-body").addClass(options.dialogClass); + } + $dialog_content.openerpClass(); + + this.$dialog_box.on('hidden.bs.modal', this, function(){ + self.trigger("closing"); + }); + this.$dialog_box.modal('show'); + this.dialog_inited = true; var res = this.start(); return res; @@ -208,9 +177,9 @@ instance.web.Dialog = instance.web.Widget.extend({ /** Closes the popup, if destroy_on_close was passed to the constructor, it is also destroyed. */ - close: function() { - if (this.dialog_inited && this.$el.is(":data(dialog)")) { - this.$el.dialog('close'); + close: function(reason) { + if (this.dialog_inited && this.$el.is(":data(bs.modal)")) { + this.$el.parents('.modal').modal('hide'); } }, _closing: function() { @@ -225,18 +194,24 @@ instance.web.Dialog = instance.web.Widget.extend({ /** Destroys the popup, also closes it. */ - destroy: function () { + destroy: function (reason) { this.$buttons.remove(); + var self = this; _.each(this.getChildren(), function(el) { el.destroy(); }); if (! this.__tmp_dialog_closing) { this.__tmp_dialog_destroying = true; - this.close(); + this.close(reason); this.__tmp_dialog_destroying = undefined; } - if (this.dialog_inited && !this.isDestroyed() && this.$el.is(":data(dialog)")) { - this.$el.dialog('destroy'); + if (this.dialog_inited && !this.isDestroyed() && this.$el.is(":data(bs.modal)")) { + //we need this to put the instruction to remove modal from DOM at the end + //of the queue, otherwise it might already have been removed before the modal-backdrop + //is removed when pressing escape key + setTimeout(function () { + self.$el.parents('.modal').remove(); + },0); } this._super(); } @@ -256,7 +231,7 @@ instance.web.CrashManager = instance.web.Class.extend({ new (handler)(this, error).display(); return; } - if (error.data.name === "openerp.http.SessionExpiredException") { + 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.") }}); return; } @@ -274,12 +249,13 @@ instance.web.CrashManager = instance.web.Class.extend({ if (error.data.exception_type === "except_osv") { error = _.extend({}, error, {data: _.extend({}, error.data, {message: error.data.arguments[0] + "\n\n" + error.data.arguments[1]})}); } - instance.web.dialog($('<div>' + QWeb.render('CrashManager.warning', {error: error}) + '</div>'), { + new instance.web.Dialog(this, { + size: 'medium', title: "OpenERP " + (_.str.capitalize(error.type) || "Warning"), buttons: [ - {text: _t("Ok"), click: function() { $(this).dialog("close"); }} - ] - }); + {text: _t("Ok"), click: function() { this.parents('.modal').modal('hide'); }} + ], + }, $('<div>' + QWeb.render('CrashManager.warning', {error: error}) + '</div>')).open(); }, show_error: function(error) { if (!this.active) { @@ -287,17 +263,12 @@ instance.web.CrashManager = instance.web.Class.extend({ } var buttons = {}; buttons[_t("Ok")] = function() { - $(this).dialog("close"); + this.parents('.modal').modal('hide'); }; - var dialog = new instance.web.Dialog(this, { + new instance.web.Dialog(this, { title: "OpenERP " + _.str.capitalize(error.type), - width: '80%', - height: '50%', - min_width: '800px', - min_height: '600px', buttons: buttons - }).open(); - dialog.$el.html(QWeb.render('CrashManager.error', {session: instance.session, error: error})); + }, QWeb.render('CrashManager.error', {session: instance.session, error: error})).open(); }, show_message: function(exception) { this.show_error({ @@ -344,16 +315,17 @@ instance.web.RedirectWarningHandler = instance.web.Dialog.extend(instance.web.Ex error = this.error; error.data.message = error.data.arguments[0]; - instance.web.dialog($('<div>' + QWeb.render('CrashManager.warning', {error: error}) + '</div>'), { + new instance.web.Dialog(this, { + size: 'medium', title: "OpenERP " + (_.str.capitalize(error.type) || "Warning"), buttons: [ - {text: _t("Ok"), click: function() { $(this).dialog("close"); }}, + {text: _t("Ok"), click: function() { this.$el.parents('.modal').modal('hide'); }}, {text: error.data.arguments[2], click: function() { window.location.href='#action='+error.data.arguments[1]; - $(this).dialog("close"); + this.$el.parents('.modal').modal('hide'); }} - ] - }); + ], + }, QWeb.render('CrashManager.warning', {error: error})).open(); this.destroy(); } }); @@ -500,13 +472,13 @@ instance.web.DatabaseManager = instance.web.Widget.extend({ * @param {String} error.error message of the error dialog */ display_error: function (error) { - return instance.web.dialog($('<div>'), { - modal: true, + return new instance.web.Dialog(this, { + size: 'medium', title: error.title, buttons: [ - {text: _t("Ok"), click: function() { $(this).dialog("close"); }} + {text: _t("Ok"), click: function() { this.$el.parents('.modal').modal('hide'); }} ] - }).html(error.error); + }, $('<div>').html(error.error)).open(); }, do_create: function(form) { var self = this; @@ -733,13 +705,13 @@ instance.web.ChangePassword = instance.web.Widget.extend({ }); }, display_error: function (error) { - return instance.web.dialog($('<div>'), { - modal: true, + return new instance.web.Dialog(this, { + size: 'medium', title: error.title, buttons: [ - {text: _t("Ok"), click: function() { $(this).dialog("close"); }} + {text: _t("Ok"), click: function() { this.$el.parents('.modal').modal('hide'); }} ] - }).html(error.error); + }, $('<div>').html(error.error)).open(); }, }); instance.web.client_actions.add("change_password", "instance.web.ChangePassword"); @@ -1054,8 +1026,11 @@ instance.web.UserMenu = instance.web.Widget.extend({ e.preventDefault(); window.location = $.param.querystring( window.location.href, 'debug'); }); - instance.web.dialog($help, {autoOpen: true, - modal: true, width: 507, height: 290, resizable: false, title: _t("About")}); + new instance.web.Dialog(this, { + size: 'medium', + dialogClass: 'oe_act_window', + title: _t("About"), + }, $help).open(); }); }, }); @@ -1264,9 +1239,9 @@ instance.web.WebClient = instance.web.Client.extend({ }; self.action_manager.do_action(result); var form = self.action_manager.dialog_widget.views.form.controller; - form.on("on_button_cancel", self.action_manager.dialog, self.action_manager.dialog.close); + form.on("on_button_cancel", self.action_manager, self.action_manager.dialog_stop); form.on('record_saved', self, function() { - self.action_manager.dialog.close(); + self.action_manager.dialog_stop(); self.update_logo(); }); }); diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js index b92ca1d3ba5..90c84ba9cda 100644 --- a/addons/web/static/src/js/core.js +++ b/addons/web/static/src/js/core.js @@ -271,7 +271,12 @@ instance.web.Session.include( /** @lends instance.web.Session# */{ for(var i=0; i<cookies.length; ++i) { var cookie = cookies[i].replace(/^\s*/, ''); if(cookie.indexOf(nameEQ) === 0) { - return JSON.parse(decodeURIComponent(cookie.substring(nameEQ.length))); + try { + return JSON.parse(decodeURIComponent(cookie.substring(nameEQ.length))); + } catch(err) { + // wrong cookie, delete it + this.set_cookie(name, '', -1); + } } } return null; diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index 517afa7f5c2..6819634655d 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -27,6 +27,7 @@ instance.web.Query = instance.web.Class.extend({ this._fields = fields; this._filter = []; this._context = {}; + this._lazy = true; this._limit = false; this._offset = 0; this._order_by = []; @@ -36,6 +37,7 @@ instance.web.Query = instance.web.Class.extend({ var q = new instance.web.Query(this._model, this._fields); q._context = this._context; q._filter = this._filter; + q._lazy = this._lazy; q._limit = this._limit; q._offset = this._offset; q._order_by = this._order_by; @@ -51,6 +53,7 @@ instance.web.Query = instance.web.Class.extend({ q._context = new instance.web.CompoundContext( q._context, to_set.context); break; + case 'lazy': case 'limit': case 'offset': case 'order_by': @@ -140,6 +143,7 @@ instance.web.Query = instance.web.Class.extend({ domain: this._model.domain(this._filter), context: ctx, offset: this._offset, + lazy: this._lazy, limit: this._limit, orderby: instance.web.serialize_sort(this._order_by) || false }).then(function (results) { @@ -148,8 +152,9 @@ instance.web.Query = instance.web.Class.extend({ result.__context = result.__context || {}; result.__context.group_by = result.__context.group_by || []; _.defaults(result.__context, ctx); + var grouping_fields = self._lazy ? [grouping[0]] : grouping; return new instance.web.QueryGroup( - self._model.name, grouping[0], result); + self._model.name, grouping_fields, result); }); }); }, @@ -176,6 +181,18 @@ instance.web.Query = instance.web.Class.extend({ return this.clone({filter: domain}); }, /** + * Creates a new query with the provided parameter lazy replacing the current + * query's own. + * + * @param {Boolean} lazy indicates if the read_group should return only the + * first level of groupby records, or should return the records grouped by + * all levels at once (so, it makes only 1 db request). + * @returns {openerp.web.Query} + */ + lazy: function (lazy) { + return this.clone({lazy: lazy}); + }, + /** * Creates a new query with the provided limit replacing the current * query's own limit * @@ -213,7 +230,7 @@ instance.web.Query = instance.web.Class.extend({ }); instance.web.QueryGroup = instance.web.Class.extend({ - init: function (model, grouping_field, read_group_group) { + init: function (model, grouping_fields, read_group_group) { // In cases where group_by_no_leaf and no group_by, the result of // read_group has aggregate fields but no __context or __domain. // Create default (empty) values for those so that things don't break @@ -221,12 +238,12 @@ instance.web.QueryGroup = instance.web.Class.extend({ {__context: {group_by: []}, __domain: []}, read_group_group); - var raw_field = grouping_field && grouping_field.split(':')[0]; + var count_key = (grouping_fields[0] && grouping_fields[0].split(':')[0]) + '_count'; var aggregates = {}; _(fixed_group).each(function (value, key) { if (key.indexOf('__') === 0 - || key === raw_field - || key === raw_field + '_count') { + || _.contains(grouping_fields, key) + || (key === count_key)) { return; } aggregates[key] = value || 0; @@ -235,15 +252,21 @@ instance.web.QueryGroup = instance.web.Class.extend({ this.model = new instance.web.Model( model, fixed_group.__context, fixed_group.__domain); - var group_size = fixed_group[raw_field + '_count'] || fixed_group.__count || 0; + var group_size = fixed_group[count_key] || fixed_group.__count || 0; var leaf_group = fixed_group.__context.group_by.length === 0; + var value = (grouping_fields.length === 1) + ? fixed_group[grouping_fields[0]] + : _.map(grouping_fields, function (field) { return fixed_group[field]; }); + var grouped_on = (grouping_fields.length === 1) + ? grouping_fields[0] + : grouping_fields; this.attributes = { folded: !!(fixed_group.__fold), - grouped_on: grouping_field, + grouped_on: grouped_on, // if terminal group (or no group) and group_by_no_leaf => use group.__count length: group_size, - value: fixed_group[raw_field], + value: value, // A group is open-able if it's not a leaf in group_by_no_leaf mode has_children: !(leaf_group && fixed_group.__context['group_by_no_leaf']), @@ -457,9 +480,17 @@ instance.web.DataSet = instance.web.Class.extend(instance.web.PropertiesMixin, return $.Deferred().resolve([]); options = options || {}; - return this._model.call('read', - [ids, fields || false], - {context: this.get_context(options.context)}) + var method = 'read'; + var ids_arg = ids; + var context = this.get_context(options.context); + if (options.check_access_rule === true){ + method = 'search_read'; + ids_arg = [['id', 'in', ids]]; + context = new instance.web.CompoundContext(context, {active_test: false}); + } + return this._model.call(method, + [ids_arg, fields || false], + {context: context}) .then(function (records) { if (records.length <= 1) { return records; } var indexes = {}; diff --git a/addons/web/static/src/js/data_export.js b/addons/web/static/src/js/data_export.js index 252a5a378cc..2de933f45e8 100644 --- a/addons/web/static/src/js/data_export.js +++ b/addons/web/static/src/js/data_export.js @@ -46,7 +46,6 @@ instance.web.DataExport = instance.web.Dialog.extend({ start: function() { var self = this; this._super.apply(this, arguments); - self.$el.removeClass('ui-dialog-content ui-widget-content'); var got_fields = new $.Deferred(); this.$el.find('#import_compat').change(function() { @@ -413,7 +412,6 @@ instance.web.DataExport = instance.web.Dialog.extend({ }); }, close: function() { - this.$el.remove(); this._super(); } }); diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index 7c04ad40149..04bb1a61d99 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -1560,9 +1560,6 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({ this.model = new instance.web.Model(this.attrs.relation); }, complete: function (needle) { - if (this.attrs.operator || this.attrs.filter_domain) { - return this._super(needle); - } var self = this; // FIXME: "concurrent" searches (multiple requests, mis-ordered responses) var context = instance.web.pyeval.eval( diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 3dc148bc7c1..83745133a3b 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -586,13 +586,13 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM this._internal_set_values(result.value, processed); } if (!_.isEmpty(result.warning)) { - instance.web.dialog($(QWeb.render("CrashManager.warning", result.warning)), { + new instance.web.Dialog(this, { + size: 'medium', title:result.warning.title, - modal: true, buttons: [ - {text: _t("Ok"), click: function() { $(this).dialog("close"); }} + {text: _t("Ok"), click: function() { this.parents('.modal').modal('hide'); }} ] - }); + }, QWeb.render("CrashManager.warning", result.warning)).open(); } return $.Deferred().resolve(); @@ -967,9 +967,12 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM context: { 'bin_size': true, 'future_display_name': true - } + }, + check_access_rule: true }).then(function(r) { self.trigger('load_record', r); + }).fail(function (){ + self.do_action('history_back'); }); } }); @@ -1077,7 +1080,6 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM }; }) .value(); - var d = new instance.web.Dialog(this, { title: _t("Set Default"), args: { @@ -1277,6 +1279,9 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt var defs = []; _.each(this.to_replace, function(el) { defs.push(el[0].replace(el[1])); + if (el[1].children().length) { + el[0].$el.append(el[1].children()); + } }); this.to_replace = []; return $.when.apply($, defs); @@ -1304,7 +1309,7 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt var tagname = $tag[0].nodeName.toLowerCase(); if (this.tags_registry.contains(tagname)) { this.tags_to_init.push($tag); - return $tag; + return (tagname === 'button') ? this.process_button($tag) : $tag; } var fn = self['process_' + tagname]; if (fn) { @@ -1321,6 +1326,13 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt return $tag; } }, + process_button: function ($button) { + var self = this; + $button.children().each(function() { + self.process($(this)); + }); + return $button; + }, process_widget: function($widget) { this.widgets_to_init.push($widget); return $widget; @@ -1906,6 +1918,8 @@ instance.web.form.WidgetButton = instance.web.form.FormWidget.extend({ template: 'WidgetButton', init: function(field_manager, node) { node.attrs.type = node.attrs['data-button-type']; + this.is_stat_button = /\boe_stat_button\b/.test(node.attrs['class']); + this.icon = node.attrs.icon && "<span class=\"fa " + node.attrs.icon + " fa-fw\"></span>"; this._super(field_manager, node); this.force_disabled = false; this.string = (this.node.attrs.string || '').replace(/_/g, ''); @@ -1941,26 +1955,23 @@ instance.web.form.WidgetButton = instance.web.form.FormWidget.extend({ var exec_action = function() { if (self.node.attrs.confirm) { var def = $.Deferred(); - var dialog = instance.web.dialog($('<div/>').text(self.node.attrs.confirm), { + var dialog = instance.web.Dialog(this, { title: _t('Confirm'), - modal: true, buttons: [ {text: _t("Cancel"), click: function() { - $(this).dialog("close"); + this.parents('.modal').modal('hide'); } }, {text: _t("Ok"), click: function() { var self2 = this; self.on_confirmed().always(function() { - $(self2).dialog("close"); + self2.parents('.modal').modal('hide'); }); } } ], - beforeClose: function() { - def.resolve(); - }, - }); + }, $('<div/>').text(self.node.attrs.confirm)).open(); + dialog.on("closing", null, function() {def.resolve();}); return def.promise(); } else { return self.on_confirmed(); @@ -1976,11 +1987,12 @@ instance.web.form.WidgetButton = instance.web.form.FormWidget.extend({ var self = this; var context = this.build_context(); - return this.view.do_execute_action( _.extend({}, this.node.attrs, {context: context}), - this.view.dataset, this.view.datarecord.id, function () { - self.view.recursive_reload(); + this.view.dataset, this.view.datarecord.id, function (reason) { + if (!_.isObject(reason)) { + self.view.recursive_reload(); + } }); }, check_disable: function() { @@ -2253,7 +2265,7 @@ instance.web.form.ReinitializeFieldMixin = _.extend({}, instance.web.form.Reini /** Some hack to make placeholders work in ie9. */ -if ($.browser.msie && $.browser.version === "9.0") { +if (!('placeholder' in document.createElement('input'))) { document.addEventListener("DOMNodeInserted",function(event){ var nodename = event.target.nodeName.toLowerCase(); if ( nodename === "input" || nodename == "textarea" ) { @@ -2805,6 +2817,50 @@ instance.web.form.FieldProgressBar = instance.web.form.AbstractField.extend({ } }); +/** + The PercentPie field expect a float from 0 to 100. +*/ +instance.web.form.FieldPercentPie = instance.web.form.AbstractField.extend({ + template: 'FieldPercentPie', + + render_value: function() { + var value = this.get('value'), + formatted_value = Math.round(value || 0) + '%', + svg = this.$('svg')[0]; + + svg.innerHTML = ""; + nv.addGraph(function() { + var size=43; + var chart = nv.models.pieChart() + .width(size) + .height(size) + .margin({top: 0, right: 0, bottom: 0, left: 0}) + .donut(true) + .showLegend(false) + .showLabels(false) + .tooltips(false) + .color(['#7C7BAD','#DDD']) + .donutRatio(0.62); + + d3.select(svg) + .datum([{'x': 'value', 'y': value}, {'x': 'complement', 'y': 100 - value}]) + .transition() + .call(chart) + .attr({width:size, height:size}); + + d3.select(svg) + .append("text") + .attr({x: size/2, y: size/2 + 3, 'text-anchor': 'middle'}) + .style({"font-size": "10px", "font-weight": "bold"}) + .text(formatted_value); + + return chart; + }); + + } +}); + + instance.web.form.FieldSelection = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin, { template: 'FieldSelection', @@ -3174,7 +3230,7 @@ instance.web.form.M2ODialog = instance.web.Dialog.extend({ init: function(parent) { this._super(parent, { title: _.str.sprintf(_t("Add %s"), parent.string), - width: 312, + size: 'medium', }); }, start: function() { @@ -3242,7 +3298,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc delete this.$drop_down; } if (this.$input) { - this.$input.closest(".ui-dialog .ui-dialog-content").off('scroll'); + this.$input.closest(".modal .modal-content").off('scroll'); this.$input.off('keyup blur autocompleteclose autocompleteopen ' + 'focus focusout change keydown'); delete this.$input; @@ -3335,7 +3391,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc self.$input.autocomplete("close"); } }, 50); - this.$input.closest(".ui-dialog .ui-dialog-content").on('scroll', this, close_autocomplete); + this.$input.closest(".modal .modal-content").on('scroll', this, close_autocomplete); self.ed_def = $.Deferred(); self.uned_def = $.Deferred(); @@ -4303,7 +4359,7 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in if (data.id) { self.add_id(data.id); } else { - ignore_blur = true; + self.ignore_blur = true; data.action(); } this.trigger('setSuggestions', {result : []}); @@ -4343,7 +4399,7 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in if (this.get("effective_readonly")) return; var self = this; - var ignore_blur = false; + self.ignore_blur = false; self.$text = this.$("textarea"); self.$text.textext(self.initialize_texttext()).bind('getSuggestions', function(e, data) { var _this = this; @@ -4363,11 +4419,11 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in self.$text .focusin(function () { self.trigger('focused'); - ignore_blur = false; + self.ignore_blur = false; }) .focusout(function() { self.$text.trigger("setInputData", ""); - if (!ignore_blur) { + if (!self.ignore_blur) { self.trigger('blurred'); } }).keydown(function(e) { @@ -4445,6 +4501,10 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in width: width, minHeight: height }); + }, + _search_create_popup: function() { + self.ignore_blur = true; + return instance.web.form.CompletionFieldMixin._search_create_popup.apply(this, arguments); }, }); @@ -4857,13 +4917,12 @@ instance.web.form.AbstractFormPopup = instance.web.Widget.extend({ var self = this; this.renderElement(); var dialog = new instance.web.Dialog(this, { - min_width: '800px', dialogClass: 'oe_act_window', - close: function() { - self.check_exit(true); - }, title: this.options.title || "", }, this.$el).open(); + dialog.on('closing', this, function (e){ + self.check_exit(true); + }); this.$buttonpane = dialog.$buttons; this.start(); }, @@ -4930,8 +4989,8 @@ instance.web.form.AbstractFormPopup = instance.web.Widget.extend({ }, destroy: function () { this.trigger('closed'); - if (this.$el.is(":data(dialog)")) { - this.$el.dialog('close'); + if (this.$el.is(":data(bs.modal)")) { + this.$el.parents('.modal').modal('hide'); } this._super(); }, @@ -5852,6 +5911,26 @@ instance.web.form.X2ManyCounter = instance.web.form.AbstractField.extend(instanc }); /** + This widget is intended to be used on stat button numeric fields. It will display + the value many2many and one2many. It is a read-only field that will + display a simple string "<value of field> <label of the field>" +*/ +instance.web.form.StatInfo = instance.web.form.AbstractField.extend({ + init: function() { + this._super.apply(this, arguments); + this.set("value", 0); + }, + render_value: function() { + var options = { + value: this.get("value") || 0, + text: this.string, + }; + this.$el.html(QWeb.render("StatInfo", options)); + }, + +}); + +/** * Registry of form fields, called by :js:`instance.web.FormView`. * * All referenced classes must implement FieldInterface. Those represent the classes whose instances @@ -5878,6 +5957,7 @@ instance.web.form.widgets = new instance.web.Registry({ 'reference' : 'instance.web.form.FieldReference', 'boolean' : 'instance.web.form.FieldBoolean', 'float' : 'instance.web.form.FieldFloat', + 'percentpie': 'instance.web.form.FieldPercentPie', 'integer': 'instance.web.form.FieldFloat', 'float_time': 'instance.web.form.FieldFloat', 'progressbar': 'instance.web.form.FieldProgressBar', @@ -5888,6 +5968,7 @@ instance.web.form.widgets = new instance.web.Registry({ 'monetary': 'instance.web.form.FieldMonetary', 'many2many_checkboxes': 'instance.web.form.FieldMany2ManyCheckBoxes', 'x2many_counter': 'instance.web.form.X2ManyCounter', + 'statinfo': 'instance.web.form.StatInfo', }); /** diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index 7426c70838c..cdb9ff8302f 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -537,7 +537,8 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi [record.get('id')], _.pluck(_(this.columns).filter(function (r) { return r.tag === 'field'; - }), 'name') + }), 'name'), + {check_access_rule: true} ).done(function (records) { var values = records[0]; if (!values) { diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js index fc9af47dfe6..e2c63eb191a 100644 --- a/addons/web/static/src/js/view_list_editable.js +++ b/addons/web/static/src/js/view_list_editable.js @@ -126,10 +126,19 @@ * as an editable row at the top or bottom of the list) */ do_add_record: function () { + var self = this; if (this.editable()) { this.$el.find('table:first').show(); this.$el.find('.oe_view_nocontent').remove(); - this.start_edition(); + this.start_edition().then(function(){ + var fields = self.editor.form.fields; + self.editor.form.fields_order.some(function(field){ + if (fields[field].$el.is(':visible')){ + fields[field].$el.find("input").select(); + return true; + } + }); + }); } else { this._super(); } diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index c9229c3c70a..dc9f706d40e 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -25,9 +25,9 @@ instance.web.ActionManager = instance.web.Widget.extend({ this._super.apply(this, arguments); this.$el.on('click', 'a.oe_breadcrumb_item', this.on_breadcrumb_clicked); }, - dialog_stop: function () { + dialog_stop: function (reason) { if (this.dialog) { - this.dialog.destroy(); + this.dialog.destroy(reason); } this.dialog = null; }, @@ -408,12 +408,12 @@ instance.web.ActionManager = instance.web.Widget.extend({ if (this.dialog_widget && !this.dialog_widget.isDestroyed()) { this.dialog_widget.destroy(); } - this.dialog_stop(); + this.dialog_stop(executor.action); this.dialog = new instance.web.Dialog(this, { + title: executor.action.name, dialogClass: executor.klass, }); this.dialog.on("closing", null, options.on_close); - this.dialog.dialog_title = executor.action.name; if (widget instanceof instance.web.ViewManager) { _.extend(widget.flags, { $buttons: this.dialog.$buttons, @@ -426,7 +426,7 @@ instance.web.ActionManager = instance.web.Widget.extend({ this.dialog.open(); return initialized; } else { - this.dialog_stop(); + this.dialog_stop(executor.action); this.inner_action = executor.action; this.inner_widget = widget; executor.post_process(widget); @@ -639,7 +639,7 @@ instance.web.ViewManager = instance.web.Widget.extend({ this.$el .find('.oe_view_manager_switch a').filter('[data-view-type="' + view_type + '"]') .parent().addClass('active'); - + this.$el.attr("data-view-type", view_type); return $.when(view_promise).done(function () { _.each(_.keys(self.views), function(view_name) { var controller = self.views[view_name].controller; @@ -926,7 +926,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({ current_view = this.views[this.active_view].controller; switch (val) { case 'fvg': - var dialog = new instance.web.Dialog(this, { title: _t("Fields View Get"), width: '95%' }).open(); + var dialog = new instance.web.Dialog(this, { title: _t("Fields View Get") }).open(); $('<pre>').text(instance.web.json_node_to_xml(current_view.fields_view.arch, true)).appendTo(dialog.$el); break; case 'tests': @@ -943,7 +943,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({ this.dataset.call('perm_read', [ids]).done(function(result) { var dialog = new instance.web.Dialog(this, { title: _.str.sprintf(_t("View Log (%s)"), self.dataset.model), - width: 400 + size: 'medium', }, QWeb.render('ViewManagerDebugViewLog', { perm : result[0], format : instance.web.format_value @@ -986,7 +986,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({ new instance.web.Dialog(self, { title: _.str.sprintf(_t("Model %s fields"), self.dataset.model), - width: '95%'}, $root).open(); + }, $root).open(); }); break; case 'edit_workflow': @@ -1223,7 +1223,7 @@ instance.web.Sidebar = instance.web.Widget.extend({ domain = $.Deferred().resolve(undefined); } if (ids.length === 0) { - instance.web.dialog($("<div />").text(_t("You must choose at least one record.")), { title: _t("Warning"), modal: true }); + new instance.web.Dialog(this, { title: _t("Warning"), size: 'medium',}, $("<div />").text(_t("You must choose at least one record."))).open(); return false; } var active_ids_context = { @@ -1402,7 +1402,7 @@ instance.web.View = instance.web.Widget.extend({ // Wrong group_by values will simply fail and forbid rendering of the destination view var ncontext = new instance.web.CompoundContext( _.object(_.reject(_.pairs(dataset.get_context().eval()), function(pair) { - return pair[0].match('^(?:(?:default_|search_default_).+|group_by|group_by_no_leaf|active_id|active_ids)$') !== null; + return pair[0].match('^(?:(?:default_|search_default_).+|.+_view_ref|group_by|group_by_no_leaf|active_id|active_ids)$') !== null; })) ); ncontext.add(action_data.context || {}); diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 7ba06b69095..b03fc8fc168 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -32,7 +32,20 @@ <t t-esc="message"/> </div> </t> - +<t t-name="Dialog"> + <div class="modal" tabindex="-1" data-backdrop="static" role="dialog" aria-hidden="true"> + <div class="modal-dialog modal-lg"> + <div class="modal-content"> + <div class="modal-header"> + <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"> + </div> + </div> + </div> + </div> +</t> <t t-name="CrashManager.warning"> <table cellspacing="0" cellpadding="0" border="0" class="oe_dialog_warning"> <tr> @@ -1195,6 +1208,11 @@ <span></span> </span> </t> +<t t-name="FieldPercentPie"> + <span class="oe_form_field oe_form_field_percent_pie" t-att-style="widget.node.attrs.style"> + <svg></svg> + </span> +</t> <t t-name="FieldStatus"> <ul t-att-class="'oe_form_field_status ' + (widget.options.clickable ? 'oe_form_status_clickable' : 'oe_form_status')" t-att-style="widget.node.attrs.style"/> </t> @@ -1259,7 +1277,7 @@ <td> <t t-call="HiddenInputFile"> <t t-set="fileupload_id" t-value="widget.fileupload_id"/> - <t t-set="fileupload_style" t-translation="off">width: 83px;</t> + <t t-set="fileupload_style" t-translation="off">overflow-x: hidden</t> <button class="oe_button oe_field_button" type="button"> <img t-att-src='_s + "/web/static/src/img/icons/STOCK_DIRECTORY.png"'/> <span>Select</span> @@ -1358,13 +1376,15 @@ </div> </t> <t t-name="WidgetButton"> - <button type="button" class="oe_button oe_form_button" + <button type="button" t-att-class="widget.is_stat_button ? 'oe_stat_button btn btn-default' : 'oe_button oe_form_button'" t-att-style="widget.node.attrs.style" t-att-tabindex="widget.node.attrs.tabindex" t-att-autofocus="widget.node.attrs.autofocus" t-att-accesskey="widget.node.attrs.accesskey"> - <img t-if="widget.node.attrs.icon" t-att-src="_s + widget.node.attrs.icon" width="16" height="16"/> - <span t-if="widget.string"><t t-esc="widget.string"/></span> + <img t-if="!widget.is_stat_button and widget.node.attrs.icon " t-att-src="_s + widget.node.attrs.icon" width="16" height="16"/> + <div t-if="widget.is_stat_button" class="stat_button_icon"><t t-if="widget.icon" t-raw="widget.icon"/></div> + <span t-if="widget.string and !widget.is_stat_button"><t t-esc="widget.string"/></span> + <div t-if="widget.string and widget.is_stat_button"><t t-esc="widget.string"/></div> </button> </t> <t t-name="WidgetButton.tooltip" t-extend="WidgetLabel.tooltip"> @@ -1937,4 +1957,6 @@ <t t-name="X2ManyCounter"> <a href="javascript:void(0)"><t t-esc="text"/></a> </t> +<t t-name="StatInfo"> + <strong><t t-esc="value"/></strong><br/><t t-esc="text"/></t> </templates> |
