diff options
| author | Fabien Meghazi <fme@openerp.com> | 2014-04-23 14:37:35 +0200 |
|---|---|---|
| committer | Fabien Meghazi <fme@openerp.com> | 2014-04-23 14:37:35 +0200 |
| commit | d4b534e7be3586fe17bbb237dd0fd7cdcdb7652c (patch) | |
| tree | 83ca6d215b4622dc23b6856f4429725c20f0a2ed /addons/web/static/src | |
| parent | bc1878e3e2d6bb8d76be6f02dfda0d844b5062c8 (diff) | |
| parent | 8ee8b7bde68a550e2950df75754ad387c8ae13b1 (diff) | |
[MERGE] upstream
bzr revid: fme@openerp.com-20140423123735-fc38fzp3mtai8xnb
Diffstat (limited to 'addons/web/static/src')
| -rw-r--r-- | addons/web/static/src/css/base.css | 271 | ||||
| -rw-r--r-- | addons/web/static/src/css/base.sass | 207 | ||||
| -rw-r--r-- | addons/web/static/src/js/chrome.js | 169 | ||||
| -rw-r--r-- | addons/web/static/src/js/core.js | 16 | ||||
| -rw-r--r-- | addons/web/static/src/js/data_export.js | 2 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_form.js | 253 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_list.js | 4 | ||||
| -rw-r--r-- | addons/web/static/src/js/views.js | 18 | ||||
| -rw-r--r-- | addons/web/static/src/js/watch.js | 58 | ||||
| -rw-r--r-- | addons/web/static/src/xml/base.xml | 63 |
10 files changed, 547 insertions, 514 deletions
diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index 08ae6df5e0b..916e4ffe9ba 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; @@ -494,9 +352,17 @@ width: 37px; text-align: center; } +.openerp .oe_button_box .oe_stat_button .oe_form_field_percent_pie { + width: 42px; +} +.openerp .oe_button_box .oe_stat_button .oe_form_field_bar_chart { + width: 42px; +} .openerp .oe_button_box .oe_stat_button svg { width: 38px; height: 38px; + display: inline; + vertical-align: middle; } .openerp .oe_avatar > img { max-height: 90px; @@ -612,7 +478,7 @@ display: inline-block; height: 12px; width: 12px; - vertical-align: bottom; + vertical-align: top; border-radius: 10px; margin: 1px 0; } @@ -638,40 +504,6 @@ font-style: italic; text-decoration: none; } -.openerp.oe_tooltip { - font-size: 12px; -} -.openerp.oe_tooltip .oe_tooltip_string { - color: #ffdd55; - font-weight: bold; - font-size: 13px; -} -.openerp.oe_tooltip .oe_tooltip_help { - white-space: pre-wrap; -} -.openerp.oe_tooltip .oe_tooltip_technical { - padding: 0 0 4px 0; - margin: 5px 0 0 15px; -} -.openerp.oe_tooltip .oe_tooltip_technical li { - list-style: circle; -} -.openerp.oe_tooltip .oe_tooltip_technical_title { - font-weight: bold; -} -.openerp.oe_tooltip .oe_tooltip_close { - margin: -5px 0 0 2px; - cursor: default; - float: right; - color: white; -} -.openerp.oe_tooltip .oe_tooltip_close:hover { - color: #999999; - cursor: pointer; -} -.openerp.oe_tooltip .oe_tooltip_message { - max-width: 310px; -} .openerp .oe_notebook { margin: 8px 0; padding: 0 16px; @@ -1233,11 +1065,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)); @@ -2063,7 +1890,7 @@ .openerp .oe_form > :not(.oe_form_nosheet) header { padding-left: 2px; } -.openerp .oe_form > :not(.oe_form_nosheet) header ul { +.openerp .oe_form > :not(.oe_form_nosheet) header ul:not(.oe_tooltip_technical):not(.oe_dropdown_menu) { display: inline-block; float: right; } @@ -2915,7 +2742,7 @@ padding: 3px 6px; white-space: pre-line; } -.openerp .oe_list_content > tbody > tr > td > button, .openerp .oe_list_content > tbody > tr > th > button { +.openerp .oe_list_content > tbody > tr > td > button.btn_img, .openerp .oe_list_content > tbody > tr > th > button.btn_img { border: none; background: transparent; padding: 0; @@ -3425,9 +3252,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 { @@ -3474,6 +3298,69 @@ body.oe_single_form .oe_single_form_container { height: 18px; } +.tooltip { + padding: 0; + margin: 0; + font-family: "Lucida Grande", Helvetica, Verdana, Arial, sans-serif; + color: #4c4c4c; + font-size: 12px; + background: white; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5); + background-color: transparent; + /*We need a greater z-index in order for tooltip to go over bootstrap modal z-index*/ + z-index: 1500; +} +.tooltip .tooltip-inner { + text-align: left !important; + max-width: 350px; +} +.tooltip .tooltip-inner .oe_tooltip_string { + color: #ffdd55; + font-weight: bold; + font-size: 13px; +} +.tooltip .tooltip-inner .oe_tooltip_help { + white-space: pre-wrap; +} +.tooltip .tooltip-inner .oe_tooltip_technical { + padding: 0 0 4px 0; + margin: 5px 0 0 15px; +} +.tooltip .tooltip-inner .oe_tooltip_technical li { + list-style: circle; +} +.tooltip .tooltip-inner .oe_tooltip_technical_title { + font-weight: bold; +} +.tooltip .tooltip-inner .oe_tooltip_close { + margin: -5px 0 0 2px; + cursor: default; + float: right; + color: white; +} +.tooltip .tooltip-inner .oe_tooltip_close:hover { + color: #999999; + cursor: pointer; +} +.tooltip .tooltip-inner .oe_tooltip_message { + max-width: 310px; +} +.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; +} +.modal .oe_button{ + margin: 0 4px 0 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 7ebc7408127..d83b09bc897 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 @@ -461,9 +362,15 @@ $sheet-padding: 16px padding: 0px 3px width: 37px text-align: center + .oe_form_field_percent_pie + width: 42px + .oe_form_field_bar_chart + width: 42px svg width: 38px height: 38px + display: inline + vertical-align: middle .oe_avatar > img max-height: 90px @@ -545,7 +452,7 @@ $sheet-padding: 16px display: inline-block height: 12px width: 12px - vertical-align: bottom + vertical-align: top border-radius: 10px margin: 1px 0 &.oe_form_invalid @@ -565,33 +472,6 @@ $sheet-padding: 16px text-decoration: none margin-bottom: 1px // }}} - // Tooltips {{{ - &.oe_tooltip - font-size: 12px - .oe_tooltip_string - color: #FD5 - font-weight: bold - font-size: 13px - .oe_tooltip_help - white-space: pre-wrap - .oe_tooltip_technical - padding: 0 0 4px 0 - margin: 5px 0 0 15px - li - list-style: circle - .oe_tooltip_technical_title - font-weight: bold - .oe_tooltip_close - margin: -5px 0 0 2px - cursor: default - float: right - color: white - &:hover - color: #999 - cursor: pointer - .oe_tooltip_message - max-width: 310px - // }}} // Notebook {{{ .oe_notebook margin: 8px 0 @@ -1030,11 +910,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 @@ -1675,7 +1550,7 @@ $sheet-padding: 16px // FormView.header {{{ .oe_form > :not(.oe_form_nosheet) header padding-left: 2px - ul + ul:not(.oe_tooltip_technical):not(.oe_dropdown_menu) display: inline-block float: right .oe_button @@ -2345,7 +2220,7 @@ $sheet-padding: 16px padding: 3px 6px white-space: pre-line > td, > th - > button + > button.btn_img border: none background: transparent padding: 0 @@ -2764,9 +2639,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 {{{ @@ -2804,6 +2676,44 @@ body.oe_single_form overflow: hidden !important // }}} +// End of customize + +// Customize bootstrap3 for tooltip +.tooltip + padding: 0 + margin: 0 + font-family: "Lucida Grande", Helvetica, Verdana, Arial, sans-serif + color: #4c4c4c + font-size: 12px + background: white + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5) + background-color: transparent + .tooltip-inner + text-align: left !important + max-width: 350px + .oe_tooltip_string + color: #FD5 + font-weight: bold + font-size: 13px + .oe_tooltip_help + white-space: pre-wrap + .oe_tooltip_technical + padding: 0 0 4px 0 + margin: 5px 0 0 15px + li + list-style: circle + .oe_tooltip_technical_title + font-weight: bold + .oe_tooltip_close + margin: -5px 0 0 2px + cursor: default + float: right + color: white + &:hover + color: #999 + cursor: pointer + .oe_tooltip_message + max-width: 310px // Hack for ui icon {{{ .ui-icon @@ -2811,6 +2721,21 @@ 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_button + margin: 0 4px 0 0 + .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 2462617a3d4..4f12a915a7c 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,57 +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, - 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) { @@ -162,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) { @@ -188,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.close(); + }); + this.$dialog_box.modal('show'); + this.dialog_inited = true; var res = this.start(); return res; @@ -206,9 +178,11 @@ 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(reason) { - if (this.dialog_inited && this.$el.is(":data(dialog)")) { + if (this.dialog_inited) { this.trigger("closing", reason); - this.$el.dialog('close'); + if (this.$el.is(":data(bs.modal)")) { // may have been destroyed by closing signal + this.$el.parents('.modal').modal('hide'); + } } }, _closing: function() { @@ -225,6 +199,7 @@ instance.web.Dialog = instance.web.Widget.extend({ */ destroy: function (reason) { this.$buttons.remove(); + var self = this; _.each(this.getChildren(), function(el) { el.destroy(); }); @@ -233,8 +208,14 @@ instance.web.Dialog = instance.web.Widget.extend({ 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 + var $parent = this.$el.parents('.modal'); + setTimeout(function () { + $parent.remove(); + },0); } this._super(); } @@ -272,12 +253,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) { @@ -285,17 +267,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({ @@ -342,16 +319,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(); } }); @@ -498,13 +476,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; @@ -731,13 +709,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"); @@ -1052,8 +1030,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(); }); }, }); @@ -1097,8 +1078,8 @@ instance.web.Client = instance.web.Widget.extend({ }, bind_events: function() { var self = this; - this.$el.on('mouseenter', '.oe_systray > div:not([data-tipsy=true])', function() { - $(this).attr('data-tipsy', 'true').tipsy().trigger('mouseenter'); + this.$el.on('mouseenter', '.oe_systray > div:not([data-toggle=tooltip])', function() { + $(this).attr('data-toggle', 'tooltip').tooltip().trigger('mouseenter'); }); this.$el.on('click', '.oe_dropdown_toggle', function(ev) { ev.preventDefault(); @@ -1122,7 +1103,7 @@ instance.web.Client = instance.web.Widget.extend({ }, 0); }); instance.web.bus.on('click', this, function(ev) { - $.fn.tipsy.clear(); + $.fn.tooltip('destroy'); if (!$(ev.target).is('input[type=file]')) { self.$el.find('.oe_dropdown_menu.oe_opened, .oe_dropdown_toggle.oe_opened').removeClass('oe_opened'); } diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js index 90c84ba9cda..a4bcd1922de 100644 --- a/addons/web/static/src/js/core.js +++ b/addons/web/static/src/js/core.js @@ -788,6 +788,22 @@ instance.web.unblockUI = function() { return $.unblockUI.apply($, arguments); }; + +/* Bootstrap defaults overwrite */ +$.fn.tooltip.Constructor.DEFAULTS.placement = 'auto top'; +$.fn.tooltip.Constructor.DEFAULTS.html = true; +$.fn.tooltip.Constructor.DEFAULTS.container = 'body'; +//overwrite bootstrap tooltip method to fix bug when using placement +//auto and the parent element does not exist anymore resulting in +//an error. This should be remove once bootstrap fix the bug +var bootstrap_show_function = $.fn.tooltip.Constructor.prototype.show; +$.fn.tooltip.Constructor.prototype.show = function (e) { + if (this.$element.parent().length === 0){ + return; + } + return bootstrap_show_function.call(this, e); +}; + /** * Registry for all the client actions key: tag value: widget */ diff --git a/addons/web/static/src/js/data_export.js b/addons/web/static/src/js/data_export.js index 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/view_form.js b/addons/web/static/src/js/view_form.js index 37c60a36f04..21a34db0036 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(); @@ -631,6 +631,9 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM }); } return $.when(); + }).fail(function() { + self.save_list.pop(); + return $.when(); }); } return iterate(); @@ -727,8 +730,9 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM } } }, - on_button_save: function() { + on_button_save: function(e) { var self = this; + $(e.target).attr("disabled", true); return this.save().done(function(result) { self.trigger("save", result); self.reload().then(function() { @@ -738,6 +742,8 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM parent.menu.do_reload_needaction(); } }); + }).always(function(){ + $(e.target).attr("disabled", false); }); }, on_button_cancel: function(event) { @@ -1080,7 +1086,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: { @@ -1833,7 +1838,7 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi this.$el.addClass(this.node.attrs["class"] || ""); }, destroy: function() { - $.fn.tipsy.clear(); + $.fn.tooltip('destroy'); this._super.apply(this, arguments); }, /** @@ -1864,10 +1869,17 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi do_attach_tooltip: function(widget, trigger, options) { widget = widget || this; trigger = trigger || this.$el; + var container = 'body'; + //in the case we have a modal currently showing, attach tooltip + //to the modal to prevent the tooltip to show in the body in the + //case we close the modal too fast + if (window.$('.modal.in').length>0){ + container = window.$('.modal.in:last()'); + } options = _.extend({ - delayIn: 500, - delayOut: 0, - fade: true, + delay: { show: 500, hide: 0 }, + trigger: 'hover', + container: container, title: function() { var template = widget.template + '.tooltip'; if (!QWeb.has_template(template)) { @@ -1878,12 +1890,12 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi widget: widget }); }, - gravity: $.fn.tipsy.autoBounds(50, 'nw'), - html: true, - opacity: 0.85, - trigger: 'hover' }, options || {}); - $(trigger).tipsy(options); + //only show tooltip if we are in debug or if we have a help to show, otherwise it will display + //as empty + if (instance.session.debug || widget.node.attrs.help || (widget.field && widget.field.help)){ + $(trigger).tooltip(options); + } }, /** * Builds a new context usable for operations related to fields by merging @@ -1956,26 +1968,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 = new 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(); @@ -2123,8 +2132,8 @@ instance.web.form.AbstractField = instance.web.form.FormWidget.extend(instance.w this.$el.find('.oe_field_translate').click(this.on_translate); } this.$label = this.view ? this.view.$el.find('label[for=' + this.id_for_label + ']') : $(); + this.do_attach_tooltip(this, this.$label[0] || this.$el); if (instance.session.debug) { - this.do_attach_tooltip(this, this.$label[0] || this.$el); this.$label.off('dblclick').on('dblclick', function() { console.log("Field '%s' of type '%s' in View: %o", self.name, (self.node.attrs.widget || self.field.type), self.view); window.w = self; @@ -2439,6 +2448,76 @@ instance.web.form.FieldFloat = instance.web.form.FieldChar.extend({ } }); +instance.web.form.FieldCharDomain = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin, { + init: function(field_manager, node) { + this._super.apply(this, arguments); + }, + start: function() { + var self = this; + this._super.apply(this, arguments); + this.on("change:effective_readonly", this, function () { + this.display_field(); + this.render_value(); + }); + this.display_field(); + return this._super(); + }, + render_value: function() { + this.$('button.select_records').css('visibility', this.get('effective_readonly') ? 'hidden': ''); + }, + set_value: function(value_) { + var self = this; + this.set('value', value_ || false); + this.display_field(); + }, + display_field: function() { + var self = this; + this.$el.html(instance.web.qweb.render("FieldCharDomain", {widget: this})); + if (this.get('value')) { + var model = this.options.model || this.field_manager.get_field_value(this.options.model_field); + var domain = instance.web.pyeval.eval('domain', this.get('value')); + var ds = new instance.web.DataSetStatic(self, model, self.build_context()); + ds.call('search_count', [domain]).then(function (results) { + $('.oe_domain_count', self.$el).text(results + ' records selected'); + $('button span', self.$el).text(' Change selection'); + }); + } else { + $('.oe_domain_count', this.$el).text('0 record selected'); + $('button span', this.$el).text(' Select records'); + }; + this.$('.select_records').on('click', self.on_click); + }, + on_click: function(ev) { + var self = this; + var model = this.options.model || this.field_manager.get_field_value(this.options.model_field); + this.pop = new instance.web.form.SelectCreatePopup(this); + this.pop.select_element( + model, {title: 'Select records...'}, + [], this.build_context()); + this.pop.on("elements_selected", self, function(element_ids) { + if (this.pop.$('input.oe_list_record_selector').prop('checked')) { + var search_data = this.pop.searchview.build_search_data(); + var domain_done = instance.web.pyeval.eval_domains_and_contexts({ + domains: search_data.domains, + contexts: search_data.contexts, + group_by_seq: search_data.groupbys || [] + }).then(function (results) { + return results.domain; + }); + } + else { + var domain = ["id", "in", element_ids]; + var domain_done = $.Deferred().resolve(domain); + } + $.when(domain_done).then(function (domain) { + var domain = self.pop.dataset.domain.concat(domain || []); + self.set_value(JSON.stringify(domain)) + }); + }); + event.preventDefault(); + }, +}); + instance.web.DateTimeWidget = instance.web.Widget.extend({ template: "web.datepicker", jqueryui_object: 'datetimepicker', @@ -2834,10 +2913,10 @@ instance.web.form.FieldPercentPie = instance.web.form.AbstractField.extend({ svg.innerHTML = ""; nv.addGraph(function() { - var size=43; + var width = 42, height = 42; var chart = nv.models.pieChart() - .width(size) - .height(size) + .width(width) + .height(height) .margin({top: 0, right: 0, bottom: 0, left: 0}) .donut(true) .showLegend(false) @@ -2850,11 +2929,11 @@ instance.web.form.FieldPercentPie = instance.web.form.AbstractField.extend({ .datum([{'x': 'value', 'y': value}, {'x': 'complement', 'y': 100 - value}]) .transition() .call(chart) - .attr({width:size, height:size}); + .attr('style', 'width: ' + width + 'px; height:' + height + 'px;'); d3.select(svg) .append("text") - .attr({x: size/2, y: size/2 + 3, 'text-anchor': 'middle'}) + .attr({x: width/2, y: height/2 + 3, 'text-anchor': 'middle'}) .style({"font-size": "10px", "font-weight": "bold"}) .text(formatted_value); @@ -2864,6 +2943,43 @@ instance.web.form.FieldPercentPie = instance.web.form.AbstractField.extend({ } }); +/** + The FieldBarChart expectsa list of values (indeed) +*/ +instance.web.form.FieldBarChart = instance.web.form.AbstractField.extend({ + template: 'FieldBarChart', + + render_value: function() { + var value = JSON.parse(this.get('value')); + var svg = this.$('svg')[0]; + svg.innerHTML = ""; + nv.addGraph(function() { + var width = 34, height = 34; + var chart = nv.models.discreteBarChart() + .x(function (d) { return d.tooltip }) + .y(function (d) { return d.value }) + .width(width) + .height(height) + .margin({top: 0, right: 0, bottom: 0, left: 0}) + .tooltips(false) + .showValues(false) + .transitionDuration(350) + .showXAxis(false) + .showYAxis(false); + + d3.select(svg) + .datum([{key: 'values', values: value}]) + .transition() + .call(chart) + .attr('style', 'width: ' + (width + 4) + 'px; height: ' + (height + 8) + 'px;'); + + nv.utils.windowResize(chart.update); + + return chart; + }); + + } +}); instance.web.form.FieldSelection = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin, { @@ -3234,7 +3350,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() { @@ -3302,7 +3418,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; @@ -3345,20 +3461,25 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc return; } var pop = new instance.web.form.FormOpenPopup(self); - pop.show_element( - self.field.relation, - self.get("value"), - self.build_context(), - { - title: _t("Open: ") + self.string - } - ); - pop.on('write_completed', self, function(){ - self.display_value = {}; - self.display_value_backup = {}; - self.render_value(); - self.focus(); - self.view.do_onchange(self); + var context = self.build_context().eval(); + var model_obj = new instance.web.Model(self.field.relation); + model_obj.call('get_formview_id', [self.get("value"), context]).then(function(view_id){ + pop.show_element( + self.field.relation, + self.get("value"), + self.build_context(), + { + title: _t("Open: ") + self.string, + view_id: view_id + } + ); + pop.on('write_completed', self, function(){ + self.display_value = {}; + self.display_value_backup = {}; + self.render_value(); + self.focus(); + self.view.do_onchange(self); + }); }); }); @@ -3395,7 +3516,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(); @@ -3420,7 +3541,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc } self.floating = false; } - if (used && self.get("value") === false && ! self.no_ed) { + if (used && self.get("value") === false && ! self.no_ed && (self.options.no_create === false || self.options.no_create === undefined)) { self.ed_def.reject(); self.uned_def.reject(); self.ed_def = $.Deferred(); @@ -3554,13 +3675,10 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc .html(link); if (! this.options.no_open) $link.click(function () { - self.do_action({ - type: 'ir.actions.act_window', - res_model: self.field.relation, - res_id: self.get("value"), - views: [[false, 'form']], - target: 'current', - context: self.build_context().eval(), + var context = self.build_context().eval(); + var model_obj = new instance.web.Model(self.field.relation); + model_obj.call('get_formview_action', [self.get("value"), context]).then(function(action){ + self.do_action(action); }); return false; }); @@ -4921,13 +5039,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(); }, @@ -4994,8 +5111,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(); }, @@ -5921,20 +6038,30 @@ instance.web.form.X2ManyCounter = instance.web.form.AbstractField.extend(instanc display a simple string "<value of field> <label of the field>" */ instance.web.form.StatInfo = instance.web.form.AbstractField.extend({ + is_field_number: true, init: function() { this._super.apply(this, arguments); - this.set("value", 0); + this.internal_set_value(0); + }, + set_value: function(value_) { + if (value_ === false || value_ === undefined) { + value_ = 0; + } + this._super.apply(this, [value_]); }, render_value: function() { var options = { value: this.get("value") || 0, - text: this.string, }; + if (! this.node.attrs.nolabel) { + options.text = this.string + } this.$el.html(QWeb.render("StatInfo", options)); }, }); + /** * Registry of form fields, called by :js:`instance.web.FormView`. * @@ -5948,6 +6075,7 @@ instance.web.form.widgets = new instance.web.Registry({ 'url' : 'instance.web.form.FieldUrl', 'text' : 'instance.web.form.FieldText', 'html' : 'instance.web.form.FieldTextHtml', + 'char_domain': 'instance.web.form.FieldCharDomain', 'date' : 'instance.web.form.FieldDate', 'datetime' : 'instance.web.form.FieldDatetime', 'selection' : 'instance.web.form.FieldSelection', @@ -5963,6 +6091,7 @@ instance.web.form.widgets = new instance.web.Registry({ 'boolean' : 'instance.web.form.FieldBoolean', 'float' : 'instance.web.form.FieldFloat', 'percentpie': 'instance.web.form.FieldPercentPie', + 'barchart': 'instance.web.form.FieldBarChart', 'integer': 'instance.web.form.FieldFloat', 'float_time': 'instance.web.form.FieldFloat', 'progressbar': 'instance.web.form.FieldProgressBar', diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index cdb9ff8302f..16d0310ab4d 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -2261,8 +2261,8 @@ instance.web.list.Button = instance.web.list.Column.extend({ attrs = this.modifiers_for(row_data); } if (attrs.invisible) { return ''; } - - return QWeb.render('ListView.row.button', { + var template = this.icon && 'ListView.row.button' || 'ListView.row.text_button'; + return QWeb.render(template, { widget: this, prefix: instance.session.prefix, disabled: attrs.readonly diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 2f401445f7e..b9015f6b311 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -410,10 +410,10 @@ instance.web.ActionManager = instance.web.Widget.extend({ } 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, @@ -581,7 +581,7 @@ instance.web.ViewManager = instance.web.Widget.extend({ var self = this; this.$el.find('.oe_view_manager_switch a').click(function() { self.switch_mode($(this).data('view-type')); - }).tipsy(); + }).tooltip(); var views_ids = {}; _.each(this.views_src, function(view) { self.views[view.view_type] = $.extend({}, view, { @@ -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': @@ -1157,10 +1157,8 @@ instance.web.Sidebar = instance.web.Widget.extend({ this.$('.oe_form_dropdown_section').each(function() { $(this).toggle(!!$(this).find('li').length); }); - - self.$("[title]").tipsy({ - 'html': true, - 'delayIn': 500, + self.$("[title]").tooltip({ + delay: { show: 500, hide: 0} }); }, /** @@ -1223,7 +1221,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 = { diff --git a/addons/web/static/src/js/watch.js b/addons/web/static/src/js/watch.js new file mode 100644 index 00000000000..efa80a1d529 --- /dev/null +++ b/addons/web/static/src/js/watch.js @@ -0,0 +1,58 @@ +(function() { +/* + * object.watch polyfill + * + * 2012-04-03 + * + * By Eli Grey, http://eligrey.com + * Public Domain. + * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + */ + +// object.watch +if (!Object.prototype.watch) { + Object.defineProperty(Object.prototype, "watch", { + enumerable: false + , configurable: true + , writable: false + , value: function (prop, handler) { + var + oldval = this[prop] + , newval = oldval + , getter = function () { + return newval; + } + , setter = function (val) { + oldval = newval; + return newval = handler.call(this, prop, oldval, val); + } + ; + + if (delete this[prop]) { // can't watch constants + Object.defineProperty(this, prop, { + get: getter + , set: setter + , enumerable: true + , configurable: true + }); + } + } + }); +} + +// object.unwatch +if (!Object.prototype.unwatch) { + Object.defineProperty(Object.prototype, "unwatch", { + enumerable: false + , configurable: true + , writable: false + , value: function (prop) { + var val = this[prop]; + delete this[prop]; // remove accessors + this[prop] = val; + } + }); +} + +})(); + diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 12827157c24..24c5ba625b0 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> @@ -599,10 +612,16 @@ <div class="oe_sidebar"> <t t-foreach="widget.sections" t-as="section"> <div class="oe_form_dropdown_section"> - <button class="oe_dropdown_toggle oe_dropdown_arrow"> + <button class="oe_dropdown_toggle oe_dropdown_arrow" t-if="section.name != 'buttons'"> <t t-if="section.name == 'files'" t-raw="widget.items[section.name].length || ''"/> <t t-esc="section.label"/> </button> + <t t-if="section.name == 'buttons'" t-foreach="widget.items[section.name]" t-as="item" t-att-class="item.classname"> + <button t-att-title="item.title or ''" t-att-data-section="section.name" t-att-data-index="item_index" t-att-href="item.url" + target="_blank" class="oe_sidebar_button oe_highlight"> + <t t-raw="item.label"/> + </button> + </t> <ul class="oe_dropdown_menu"> <li t-foreach="widget.items[section.name]" t-as="item" t-att-class="item.classname"> <t t-if="section.name == 'files'"> @@ -779,11 +798,16 @@ </span> </t> </t> +<button t-name="ListView.row.text_button" type="button" + t-att-title="widget.string" t-att-disabled="disabled || undefined" + t-att-class="disabled ? 'oe_list_button_disabled btn' : 'btn'"> + <t t-esc="widget.string"/> +</button> <button t-name="ListView.row.button" type="button" t-att-title="widget.string" t-att-disabled="disabled || undefined" - t-att-class="disabled ? 'oe_list_button_disabled' : undefined" - ><img t-attf-src="#{prefix}/web/static/src/img/icons/#{widget.icon}.png" - t-att-alt="widget.string"/></button> + t-att-class="disabled ? 'oe_list_button_disabled btn_img' : 'btn_img'" + ><img t-attf-src="#{prefix}/web/static/src/img/icons/#{widget.icon}.png" + t-att-alt="widget.string"/></button> <t t-extend="ListView.row"> <!-- adds back padding to row being rendered after edition, if necessary (if not deletable add back padding), otherwise the row being added is @@ -919,7 +943,6 @@ </t> <t t-name="FormRenderingLabel"> <label t-att-for="_for" - t-att-title="help" t-attf-class="#{classnames} oe_form_label#{help ? '_help' : ''} oe_align_#{align}"> <t t-esc="string"/> </label> @@ -981,7 +1004,7 @@ </li> <li t-if="widget.field and widget.field.selection" data-item="selection"> <span class="oe_tooltip_technical_title">Selection:</span> - <ul> + <ul class="oe_tooltip_technical"> <li t-foreach="widget.field.selection" t-as="option"> [<t t-esc="option[0]"/>] <t t-if="option[1]"> - </t> @@ -1056,6 +1079,16 @@ </t> </div> </t> +<t t-name="FieldCharDomain"> + <div class="oe_form_field"> + <span class="oe_domain_count"/> + <button class="oe_button oe_link select_records" type="button" + t-att-style="widget.node.attrs.style" + t-att-accesskey="widget.node.attrs.accesskey"> + <span class="fa fa-arrow-right"/> + </button> + </div> +</t> <t t-name="web.datepicker"> <span> <t t-set="placeholder" t-value="widget.getParent().node and widget.getParent().node.attrs.placeholder"/> @@ -1196,9 +1229,16 @@ </span> </t> <t t-name="FieldPercentPie"> - <span class="oe_form_field oe_form_field_percent_pie" t-att-style="widget.node.attrs.style"> + <div class="oe_form_field oe_form_field_percent_pie" t-att-style="widget.node.attrs.style"> <svg></svg> - </span> + <span t-if="widget.string"><t t-esc="widget.string"/></span> + </div> +</t> +<t t-name="FieldBarChart"> + <div class="oe_form_field oe_form_field_bar_chart" t-att-style="widget.node.attrs.style"> + <svg></svg> + <span t-if="widget.string"><t t-esc="widget.string"/></span> + </div> </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"/> @@ -1369,7 +1409,7 @@ t-att-autofocus="widget.node.attrs.autofocus" t-att-accesskey="widget.node.attrs.accesskey"> <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> + <div t-if="widget.is_stat_button and widget.icon" class="stat_button_icon"><t 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> @@ -1945,5 +1985,6 @@ <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> + <strong><t t-esc="value"/></strong> + <t t-esc="text"/></t> </templates> |
