summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
authorSanjay Gohel (Open ERP) <sgo@tinyerp.com>2012-07-27 10:31:54 +0530
committerSanjay Gohel (Open ERP) <sgo@tinyerp.com>2012-07-27 10:31:54 +0530
commit8220b2edf94db13e85b9bb10dd95559be32fd22e (patch)
tree9f2bb2e6247c9cf16fa15ee011cf4877ba4dca40 /addons/web/static/src
parent730d5555f6b8766c0f5871d89b5eb8e14d74dfa5 (diff)
parent9128e37231194592b6468ffa7922bbb39b5d7a33 (diff)
[MERGE]merge with trunk
bzr revid: sgo@tinyerp.com-20120727050154-148msw0jzppgc66w
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/css/base.css276
-rw-r--r--addons/web/static/src/css/base.sass203
-rw-r--r--addons/web/static/src/img/pattern.pngbin98 -> 0 bytes
-rw-r--r--addons/web/static/src/img/throbber2.gifbin7195 -> 0 bytes
-rw-r--r--addons/web/static/src/js/chrome.js81
-rw-r--r--addons/web/static/src/js/corelib.js12
-rw-r--r--addons/web/static/src/js/coresetup.js34
-rw-r--r--addons/web/static/src/js/data_export.js4
-rw-r--r--addons/web/static/src/js/search.js29
-rw-r--r--addons/web/static/src/js/view_form.js168
-rw-r--r--addons/web/static/src/js/view_list.js33
-rw-r--r--addons/web/static/src/js/view_list_editable.js188
-rw-r--r--addons/web/static/src/js/views.js83
-rw-r--r--addons/web/static/src/xml/base.xml177
14 files changed, 840 insertions, 448 deletions
diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css
index 2e26de30d5f..1e59897cd86 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");
@@ -20,6 +20,50 @@
font-style: normal;
}
+@-moz-keyframes bounce {
+ 0% {
+ -moz-transform: scale(0);
+ opacity: 0;
+ }
+
+ 50% {
+ -moz-transform: scale(1.3);
+ opacity: 0.4;
+ }
+
+ 75% {
+ -moz-transform: scale(0.9);
+ opacity: 0.7;
+ }
+
+ 100% {
+ -moz-transform: scale(1);
+ opacity: 1;
+ }
+}
+
+@-webkit-keyframes bounce {
+ 0% {
+ -webkit-transform: scale(0);
+ opacity: 0;
+ }
+
+ 50% {
+ -webkit-transform: scale(1.3);
+ opacity: 0.4;
+ }
+
+ 75% {
+ -webkit-transform: scale(0.9);
+ opacity: 0.7;
+ }
+
+ 100% {
+ -webkit-transform: scale(1);
+ opacity: 1;
+ }
+}
+
.openerp.openerp_webclient_container {
height: 100%;
position: relative;
@@ -186,6 +230,11 @@
.openerp .ui-menu .ui-menu-item a.ui-state-active {
background: #f0f0fa;
}
+.openerp div.ui-widget-overlay {
+ background: black;
+ filter: alpha(opacity=30);
+ opacity: 0.3;
+}
.openerp.ui-dialog {
display: none;
padding: 6px;
@@ -267,6 +316,45 @@
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: #8a89ba;
+}
+.openerp.ui-dialog .oe_about a:hover {
+ text-decoration: underline;
+}
+.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: #b41616;
+ 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;
}
@@ -458,6 +546,10 @@
.openerp .oe_webclient .oe_star_on {
color: gold;
}
+.openerp .oe_bounce {
+ -moz-animation: bounce 0.4s linear;
+ -webkit-animation: bounce 0.4s linear;
+}
.openerp .oe_tag {
border-radius: 2px;
-webkit-box-sizing: border-box;
@@ -584,7 +676,7 @@
z-index: 1;
border: 1px solid #afafb6;
background: white;
- padding: 6px 0;
+ padding: 4px 0;
min-width: 140px;
text-align: left;
-moz-border-radius: 3px;
@@ -599,6 +691,7 @@
float: none;
display: block;
position: relative;
+ padding: 2px 8px;
}
.openerp .oe_dropdown_menu > li:hover {
background-color: #f0f0fa;
@@ -615,7 +708,6 @@
.openerp .oe_dropdown_menu > li > a {
white-space: nowrap;
display: block;
- padding: 4px 15px;
color: #4c4c4c;
text-decoration: none;
}
@@ -711,7 +803,7 @@
z-index: 1050;
}
.openerp .oe_login {
- background: url("/web/static/src/img/pattern.png") repeat;
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=);
text-align: center;
font-size: 14px;
height: 100%;
@@ -945,11 +1037,12 @@
}
.openerp .oe_topbar .oe_dropdown_menu li {
float: none;
+ padding: 3px 12px;
}
.openerp .oe_topbar .oe_dropdown_menu li a {
color: #eeeeee;
}
-.openerp .oe_topbar .oe_dropdown_menu li a:hover {
+.openerp .oe_topbar .oe_dropdown_menu li:hover {
background-color: #292929;
background-image: -webkit-gradient(linear, left top, left bottom, from(#292929), to(#191919));
background-image: -webkit-linear-gradient(top, #292929, #191919);
@@ -1229,6 +1322,9 @@
.openerp .oe_view_manager .oe_view_manager_pager {
line-height: 26px;
}
+.openerp .oe_view_manager .oe_view_manager_pager .oe_list_pager_single_page .oe_pager_group {
+ display: none;
+}
.openerp .oe_view_manager .oe_pager_value {
float: left;
margin-right: 8px;
@@ -1408,20 +1504,31 @@
filter: alpha(opacity=50);
opacity: 0.5;
}
-.openerp .oe_searchview .oe_searchview_facets {
- min-height: 22px;
+.openerp .oe_searchview .oe_searchview_search {
+ font-size: 1px;
+ letter-spacing: -1px;
+ color: transparent;
+ -moz-box-shadow: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ -moz-border-radius: 0;
+ -webkit-border-radius: 0;
+ border-radius: 0;
+ position: absolute;
+ left: 3px;
+ top: 1px;
+ padding: 0;
+ border: none;
+ background: transparent;
}
-.openerp .oe_searchview .oe_searchview_facets:before {
- color: #cccccc;
- font-family: "mnmliconsRegular";
+.openerp .oe_searchview .oe_searchview_search:before {
+ font: 21px "mnmliconsRegular";
content: "r";
- font-size: 130%;
- display: inline;
- position: relative;
- left: 6px;
- top: 2px;
color: #a3a3a3;
- padding-right: 4px;
+}
+.openerp .oe_searchview .oe_searchview_facets {
+ min-height: 22px;
+ margin-left: 15px;
}
.openerp .oe_searchview .oe_searchview_facets * {
vertical-align: top;
@@ -1437,7 +1544,7 @@
outline: none;
}
.openerp .oe_searchview .oe_searchview_facets .oe_searchview_input {
- padding: 0 3px;
+ padding: 0 0 0 6px;
}
.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet {
position: relative;
@@ -1600,14 +1707,14 @@
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_section li:hover {
background-color: #f0f0fa;
}
-.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_section form {
+.openerp .oe_searchview .oe_searchview_drawer form {
margin-left: 12px;
}
-.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_section form p {
+.openerp .oe_searchview .oe_searchview_drawer form p {
margin: 4px 0;
line-height: 18px;
}
-.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_section form button {
+.openerp .oe_searchview .oe_searchview_drawer form button {
margin: 0 0 8px 0;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom {
@@ -2180,7 +2287,7 @@
height: auto;
line-height: 16px;
}
-.openerp .oe_form_field_one2many .oe_list_buttons.oe_editing .oe_list_save {
+.openerp .oe_form_field_one2many .oe_list_buttons.oe_editing .oe_list_save, .openerp .oe_form_field_many2many .oe_list_buttons.oe_editing .oe_list_save {
visibility: hidden;
}
.openerp .oe_form .oe_form_field_many2many > .oe_list .oe_list_pager_single_page {
@@ -2266,9 +2373,6 @@
padding: 3px 6px;
white-space: pre-line;
}
-.openerp .oe_list_content > tbody > tr > td.oe_list_field_cell progress {
- width: 100%;
-}
.openerp .oe_list_content > tbody > tr > td > button, .openerp .oe_list_content > tbody > tr > th > button {
border: none;
background: transparent;
@@ -2315,6 +2419,58 @@
.openerp .oe_list_content .numeric input {
text-align: right;
}
+.openerp .tree_header {
+ background-color: #f0f0f0;
+ border-bottom: 1px solid #cacaca;
+ color: #4c4c4c;
+ padding: 5px;
+ height: 25px;
+}
+.openerp .tree_header button {
+ float: right;
+ height: 27px;
+ margin-right: 5px;
+}
+.openerp .oe-treeview-table {
+ width: 100%;
+ background-color: white;
+ border-spacing: 0;
+}
+.openerp .oe-treeview-table th {
+ padding: 10px;
+ color: #4c4c4c;
+ font-weight: bold;
+ background-color: #f0f0f0;
+ border-bottom: 2px solid #cacaca;
+}
+.openerp .oe-treeview-table .treeview-tr, .openerp .oe-treeview-table .treeview-td {
+ cursor: pointer;
+ border-right: 1px dotted #afafb6;
+ vertical-align: top;
+ text-align: left;
+ border-bottom: 1px solid #cfcccc;
+}
+.openerp .oe-treeview-table tr:hover {
+ background-color: #e0e0f8;
+}
+.openerp .oe-treeview-table .oe-number {
+ text-align: right !important;
+}
+.openerp .oe-treeview-table span {
+ font-size: 90%;
+ font-weight: normal;
+ white-space: nowrap;
+ display: block;
+}
+.openerp .oe-treeview-table .treeview-tr.oe-treeview-first {
+ background: transparent url(/web/static/src/img/expand.gif) 0 50% no-repeat;
+}
+.openerp .oe-treeview-table .oe_open .treeview-tr.oe-treeview-first {
+ background-image: url(/web/static/src/img/collapse.gif);
+}
+.openerp .oe-treeview-table .treeview-tr.oe-treeview-first span, .openerp .oe-treeview-table .treeview-td.oe-treeview-first span {
+ margin-left: 16px;
+}
.openerp .oe_trad_field.touched {
border: 1px solid green !important;
}
@@ -2380,59 +2536,6 @@
color: #333333;
}
-.openerp .tree_header {
- background-color: #f0f0f0;
- border-bottom: 1px solid #cacaca;
- color: #4c4c4c;
- padding: 5px;
- height: 25px;
-}
-.openerp .tree_header button {
- float: right;
- height: 27px;
- margin-right: 5px;
-}
-.openerp .oe-treeview-table {
- width: 100%;
- background-color: white;
- border-spacing: 0;
-}
-.openerp .oe-treeview-table th {
- padding: 10px;
- color: #4c4c4c;
- font-weight: bold;
- background-color: #f0f0f0;
- border-bottom: 2px solid #cacaca;
-}
-.openerp .oe-treeview-table .treeview-tr, .openerp .oe-treeview-table .treeview-td {
- cursor: pointer;
- border-right: 1px dotted #afafb6;
- vertical-align: top;
- text-align: left;
- border-bottom: 1px solid #cfcccc;
-}
-.openerp .oe-treeview-table tr:hover {
- background-color: #e0e0f8;
-}
-.openerp .oe-treeview-table .oe-number {
- text-align: right !important;
-}
-.openerp .oe-treeview-table span {
- font-size: 90%;
- font-weight: normal;
- white-space: nowrap;
- display: block;
-}
-.openerp .oe-treeview-table .treeview-tr.oe-treeview-first {
- background: transparent url(/web/static/src/img/expand.gif) 0 50% no-repeat;
-}
-.openerp .oe-treeview-table .oe_open .treeview-tr.oe-treeview-first {
- background-image: url(/web/static/src/img/collapse.gif);
-}
-.openerp .oe-treeview-table .treeview-tr.oe-treeview-first span, .openerp .oe-treeview-table .treeview-td.oe-treeview-first span {
- margin-left: 16px;
-}
-
.kitten-mode-activated {
background-image: url(http://placekitten.com/g/1365/769);
background-size: cover;
@@ -2441,22 +2544,3 @@
.kitten-mode-activated > * {
opacity: 0.7;
}
-.kitten-mode-activated .oe_footer a {
- background-image: url(http://www.risacher.com/la-rache/zfiles/la-rache.png);
- font-size: 1px;
- letter-spacing: -1px;
- color: transparent;
- display: inline-block;
- height: 15px;
- width: 80px;
- vertical-align: top;
-}
-.kitten-mode-activated .oe_footer a span {
- display: none;
-}
-
-div.ui-widget-overlay {
- background: black;
- filter: alpha(opacity=30);
- opacity: 0.3;
-}
diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass
index c4314923867..3bb52497454 100644
--- a/addons/web/static/src/css/base.sass
+++ b/addons/web/static/src/css/base.sass
@@ -97,6 +97,35 @@ $sheet-max-width: 860px
color: $color
// }}}
+// CSS animation bounces {{{
+@-moz-keyframes bounce
+ 0%
+ -moz-transform: scale(0)
+ opacity: 0
+ 50%
+ -moz-transform: scale(1.3)
+ opacity: 0.4
+ 75%
+ -moz-transform: scale(0.9)
+ opacity: 0.7
+ 100%
+ -moz-transform: scale(1)
+ opacity: 1
+
+@-webkit-keyframes bounce
+ 0%
+ -webkit-transform: scale(0)
+ opacity: 0
+ 50%
+ -webkit-transform: scale(1.3)
+ opacity: 0.4
+ 75%
+ -webkit-transform: scale(0.9)
+ opacity: 0.7
+ 100%
+ -webkit-transform: scale(1)
+ opacity: 1
+// }}}
.openerp.openerp_webclient_container
height: 100%
@@ -200,7 +229,9 @@ $sheet-max-width: 860px
width: auto
a.ui-state-active
background: #f0f0fa
-
+ div.ui-widget-overlay
+ background: black
+ @include opacity(0.3)
// Modal box
&.ui-dialog
display: none
@@ -255,6 +286,29 @@ $sheet-max-width: 860px
&: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: #8A89BA
+ &:hover
+ text-decoration: underline
+ .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
@@ -367,6 +421,9 @@ $sheet-max-width: 860px
text-decoration: none
.oe_star_on
color: gold
+ .oe_bounce
+ -moz-animation: bounce .40s linear
+ -webkit-animation: bounce .40s linear
// }}}
// Tags (for many2many tags, among others) {{{
.oe_tag
@@ -469,7 +526,7 @@ $sheet-max-width: 860px
z-index: 1
border: 1px solid #afafb6
background: white
- padding: 6px 0
+ padding: 4px 0
min-width: 140px
text-align: left
@include radius(3px)
@@ -482,10 +539,10 @@ $sheet-max-width: 860px
float: none
display: block
position: relative
+ padding: 2px 8px
> a
white-space: nowrap
display: block
- padding: 4px 15px
color: #4c4c4c
text-decoration: none
&:hover
@@ -566,7 +623,7 @@ $sheet-max-width: 860px
// }}}
// Login {{{
.oe_login
- background: url("/web/static/src/img/pattern.png") repeat
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=)
text-align: center
font-size: 14px
height: 100%
@@ -734,11 +791,12 @@ $sheet-max-width: 860px
@include background-clip()
li
float: none
+ padding: 3px 12px
a
color: #eee
- &:hover
- @include vertical-gradient(#292929, #191919)
- @include box-shadow(none)
+ &:hover
+ @include vertical-gradient(#292929, #191919)
+ @include box-shadow(none)
// }}}
// Webclient.leftbar {{{
@@ -958,6 +1016,8 @@ $sheet-max-width: 860px
// ViewManager.pager {{{
.oe_view_manager_pager
line-height: 26px
+ .oe_list_pager_single_page .oe_pager_group
+ display: none
.oe_pager_value
float: left
margin-right: 8px
@@ -1101,19 +1161,20 @@ $sheet-max-width: 860px
border-right: 5px solid transparent
@include opacity()
+ .oe_searchview_search
+ @include text-to-icon("r", #a3a3a3)
+ @include box-shadow(none)
+ @include radius(0)
+ position: absolute
+ left: 3px
+ top: 1px
+ padding: 0
+ border: none
+ background: transparent
+
.oe_searchview_facets
min-height: 22px
- &:before
- color: #ccc
- font-family: "mnmliconsRegular"
- content: "r"
- font-size: 130%
- display: inline
- position: relative
- left: 6px
- top: 2px
- color: #a3a3a3
- padding-right: 4px
+ margin-left: 15px
*
vertical-align: top
display: inline-block
@@ -1125,7 +1186,7 @@ $sheet-max-width: 860px
&:focus
outline: none
.oe_searchview_input
- padding: 0 3px
+ padding: 0 0 0 6px
.oe_searchview_facet
position: relative
cursor: pointer
@@ -1247,13 +1308,13 @@ $sheet-max-width: 860px
// after oe_selected so background color is not overridden
&:hover
background-color: $hover-background
- form
- margin-left: 12px
- p
- margin: 4px 0
- line-height: 18px
- button
- margin: 0 0 8px 0
+ form
+ margin-left: 12px
+ p
+ margin: 4px 0
+ line-height: 18px
+ button
+ margin: 0 0 8px 0
.oe_searchview_custom
padding: 0 8px 8px 8px
form
@@ -1821,6 +1882,49 @@ $sheet-max-width: 860px
input
text-align: right
// }}}
+ // Tree view {{{
+ .tree_header
+ background-color: #f0f0f0
+ border-bottom: 1px solid #cacaca
+ color: #4c4c4c
+ padding: 5px
+ height: 25px
+ button
+ float: right
+ height: 27px
+ margin-right: 5px
+ .oe-treeview-table
+ width: 100%
+ background-color: white
+ border-spacing: 0
+ th
+ padding: 10px
+ color: #4c4c4c
+ font-weight: bold
+ background-color: #f0f0f0
+ border-bottom: 2px solid #cacaca
+ .treeview-tr, .treeview-td
+ cursor: pointer
+ border-right: 1px dotted #afafb6
+ vertical-align: top
+ text-align: left
+ border-bottom: 1px solid #cfcccc
+ tr:hover
+ background-color: #e0e0f8
+ .oe-number
+ text-align: right !important
+ span
+ font-size: 90%
+ font-weight: normal
+ white-space: nowrap
+ display: block
+ .treeview-tr.oe-treeview-first
+ background: transparent url(/web/static/src/img/expand.gif) 0 50% no-repeat
+ .oe_open .treeview-tr.oe-treeview-first
+ background-image: url(/web/static/src/img/collapse.gif)
+ .treeview-tr.oe-treeview-first span, .treeview-td.oe-treeview-first span
+ margin-left: 16px
+ // }}}
// Translation {{{
.oe_trad_field.touched
border: 1px solid green !important
@@ -1878,49 +1982,6 @@ $sheet-max-width: 860px
float: right
color: #333
// }}}
-//Tree view
-.openerp
- .tree_header
- background-color: #f0f0f0
- border-bottom: 1px solid #cacaca
- color: #4c4c4c
- padding: 5px
- height: 25px
- button
- float: right
- height: 27px
- margin-right: 5px
- .oe-treeview-table
- width: 100%
- background-color: white
- border-spacing: 0
- th
- padding: 10px
- color: #4c4c4c
- font-weight: bold
- background-color: #f0f0f0
- border-bottom: 2px solid #cacaca
- .treeview-tr, .treeview-td
- cursor: pointer
- border-right: 1px dotted #afafb6
- vertical-align: top
- text-align: left
- border-bottom: 1px solid #cfcccc
- tr:hover
- background-color: #e0e0f8
- .oe-number
- text-align: right !important
- span
- font-size: 90%
- font-weight: normal
- white-space: nowrap
- display: block
- .treeview-tr.oe-treeview-first
- background: transparent url(/web/static/src/img/expand.gif) 0 50% no-repeat
- .oe_open .treeview-tr.oe-treeview-first
- background-image: url(/web/static/src/img/collapse.gif)
- .treeview-tr.oe-treeview-first span, .treeview-td.oe-treeview-first span
- margin-left: 16px
// Kitten Mode {{{
.kitten-mode-activated
background-image: url(http://placekitten.com/g/1365/769)
@@ -1931,8 +1992,6 @@ $sheet-max-width: 860px
// }}}
-div.ui-widget-overlay
- background: black
- @include opacity(0.3)
+
// au BufWritePost,FileWritePost *.sass :!sass --style expanded --line-numbers <afile> > "%:p:r.css"
// vim:tabstop=4:shiftwidth=4:softtabstop=4:fdm=marker:
diff --git a/addons/web/static/src/img/pattern.png b/addons/web/static/src/img/pattern.png
deleted file mode 100644
index 7e3a2b37834..00000000000
--- a/addons/web/static/src/img/pattern.png
+++ /dev/null
Binary files differ
diff --git a/addons/web/static/src/img/throbber2.gif b/addons/web/static/src/img/throbber2.gif
deleted file mode 100644
index 5d2057ae0e7..00000000000
--- a/addons/web/static/src/img/throbber2.gif
+++ /dev/null
Binary files differ
diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js
index 71010ef6d74..a1759397e21 100644
--- a/addons/web/static/src/js/chrome.js
+++ b/addons/web/static/src/js/chrome.js
@@ -257,7 +257,7 @@ instance.web.Loading = instance.web.Widget.extend({
// Block UI after 3s
this.long_running_timer = setTimeout(function () {
self.blocked_ui = true;
- $.blockUI();
+ instance.web.blockUI();
}, 3000);
}
@@ -276,7 +276,7 @@ instance.web.Loading = instance.web.Widget.extend({
// Don't unblock if blocked by somebody else
if (self.blocked_ui) {
this.blocked_ui = false;
- $.unblockUI();
+ instance.web.unblockUI();
}
this.$element.fadeOut();
this.getParent().$element.removeClass('oe_wait');
@@ -287,7 +287,7 @@ instance.web.Loading = instance.web.Widget.extend({
instance.web.DatabaseManager = instance.web.Widget.extend({
init: function(parent) {
this._super(parent);
- this.unblockUIFunction = $.unblockUI;
+ this.unblockUIFunction = instance.web.unblockUI;
$.validator.addMethod('matches', function (s, _, re) {
return new RegExp(re).test(s);
}, _t("Invalid database name"));
@@ -354,16 +354,16 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
* from unblocking the UI
*/
blockUI: function () {
- $.blockUI();
- $.unblockUI = function () {};
+ instance.web.blockUI();
+ instance.web.unblockUI = function () {};
},
/**
* Reinstates $.unblockUI so third parties can play with blockUI, and
* unblocks the UI
*/
unblockUI: function () {
- $.unblockUI = this.unblockUIFunction;
- $.unblockUI();
+ instance.web.unblockUI = this.unblockUIFunction;
+ instance.web.unblockUI();
},
/**
* Displays an error dialog resulting from the various RPC communications
@@ -387,8 +387,16 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
var fields = $(form).serializeArray();
self.rpc("/web/database/create", {'fields': fields}, function(result) {
var form_obj = self.to_object(fields);
- self.getParent().do_login( form_obj['db_name'], 'admin', form_obj['create_admin_pwd']);
- self.destroy();
+ var client_action = {
+ type: 'ir.actions.client',
+ tag: 'login',
+ params: {
+ 'db': form_obj['db_name'],
+ 'login': 'admin',
+ 'password': form_obj['create_admin_pwd'],
+ },
+ };
+ self.do_action(client_action);
});
},
@@ -473,19 +481,22 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
});
},
do_exit: function () {
+ this.do_action("login");
}
});
+instance.web.client_actions.add("database_manager", "instance.web.DatabaseManager");
instance.web.Login = instance.web.Widget.extend({
template: "Login",
remember_credentials: true,
_db_list: null,
- init: function(parent) {
+ init: function(parent, params) {
this._super(parent);
this.has_local_storage = typeof(localStorage) != 'undefined';
this.selected_db = null;
this.selected_login = null;
+ this.params = params;
if (this.has_local_storage && this.remember_credentials) {
this.selected_db = localStorage.getItem('last_db_login_success');
@@ -495,26 +506,17 @@ instance.web.Login = instance.web.Widget.extend({
}
}
},
- open_db_manager: function(){
- var self = this;
- self.$element.find('.oe_login_bottom').hide();
- self.$element.find('.oe_login_pane').hide();
- self.databasemanager = new instance.web.DatabaseManager(self);
- self.databasemanager.appendTo(self.$element);
- self.databasemanager.do_exit.add_last(function() {
- self.databasemanager.destroy();
- self.$element.find('.oe_login_bottom').show();
- self.$element.find('.oe_login_pane').show();
- self.load_db_list(true).then(self.on_db_list_loaded);
- });
- },
start: function() {
var self = this;
self.$element.find("form").submit(self.on_submit);
self.$element.find('.oe_login_manage_db').click(function() {
- self.open_db_manager();
+ self.do_action("database_manager");
+ });
+ return self.load_db_list().then(self.on_db_list_loaded).then(function() {
+ if(self.params) {
+ self.do_login(self.params.db, self.params.login, self.params.password);
+ }
});
- return self.load_db_list().then(self.on_db_list_loaded);
},
load_db_list: function (force) {
var d = $.when(), self = this;
@@ -535,7 +537,7 @@ instance.web.Login = instance.web.Widget.extend({
var dbdiv = this.$element.find('div.oe_login_dbpane');
this.$element.find("[name=db]").replaceWith(instance.web.qweb.render('Login.dblist', { db_list: list, selected_db: this.selected_db}));
if(list.length === 0) {
- self.open_db_manager();
+ this.do_action("database_manager");
} else if(list && list.length === 1) {
dbdiv.hide();
} else {
@@ -582,13 +584,14 @@ instance.web.Login = instance.web.Widget.extend({
localStorage.setItem('last_password_login_success', '');
}
}
- self.trigger("login");
+ self.trigger('login_successful');
},function () {
self.$(".oe_login_pane").fadeIn("fast");
self.$element.addClass("oe_login_invalid");
});
}
});
+instance.web.client_actions.add("login", "instance.web.Login");
instance.web.Menu = instance.web.Widget.extend({
template: 'Menu',
@@ -864,7 +867,7 @@ instance.web.UserMenu = instance.web.Widget.extend({
window.location.href, 'debug');
});
instance.web.dialog($help, {autoOpen: true,
- modal: true, width: 960, title: _t("About")});
+ modal: true, width: 580, height: 290, resizable: false, title: _t("About")});
});
},
});
@@ -893,7 +896,7 @@ instance.web.Client = instance.web.Widget.extend({
this.$element.on('click', '.oe_dropdown_toggle', function(ev) {
ev.preventDefault();
var $toggle = $(this);
- var $menu = $toggle.find('.oe_dropdown_menu');
+ var $menu = $toggle.parent().find('.oe_dropdown_menu');
var state = $menu.is('.oe_opened');
setTimeout(function() {
// Do not alter propagation
@@ -903,7 +906,7 @@ instance.web.Client = instance.web.Widget.extend({
var doc_width = $(document).width();
var offset = $menu.offset();
var menu_width = $menu.width();
- var x = doc_width - offset.left - menu_width - 15;
+ var x = doc_width - offset.left - menu_width - 2;
if (x < 0) {
$menu.offset({ left: offset.left + x }).width(menu_width);
}
@@ -964,19 +967,15 @@ instance.web.WebClient = instance.web.Client.extend({
data: {debug: file + ':' + line}
});
};
- // TODO: deprecate and use login client action
- self.login = new instance.web.Login(self);
- self.login.on("login",self,self.show_application);
},
show_login: function() {
- var self = this;
- self.$('.oe_topbar').hide();
- self.login.appendTo(self.$element);
+ this.$('.oe_topbar').hide();
+ this.action_manager.do_action("login");
+ this.action_manager.inner_widget.on('login_successful', this, this.show_application);
},
show_application: function() {
var self = this;
self.$('.oe_topbar').show();
- self.login.$element.hide();
self.menu = new instance.web.Menu(self);
self.menu.replace(this.$element.find('.oe_menu_placeholder'));
self.menu.on('menu_click', this, this.on_menu_action);
@@ -1057,6 +1056,7 @@ instance.web.WebClient = instance.web.Client.extend({
},
do_push_state: function(state) {
this.set_title(state.title);
+ delete state.title;
var url = '#' + $.param(state);
this._current_state = _.clone(state);
$.bbq.pushState(url);
@@ -1083,10 +1083,13 @@ instance.web.WebClient = instance.web.Client.extend({
}
},
set_content_full_screen: function(fullscreen) {
- if (fullscreen)
+ if (fullscreen) {
$(".oe_webclient", this.$element).addClass("oe_content_full_screen");
- else
+ $("body").css({'overflow-y':'hidden'});
+ } else {
$(".oe_webclient", this.$element).removeClass("oe_content_full_screen");
+ $("body").css({'overflow-y':'scroll'});
+ }
}
});
diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js
index 1ed4c4788e3..a092b670ef1 100644
--- a/addons/web/static/src/js/corelib.js
+++ b/addons/web/static/src/js/corelib.js
@@ -378,7 +378,8 @@ instance.web.PropertiesMixin = _.extend({}, instance.web.EventDispatcherMixin, {
instance.web.EventDispatcherMixin.init.call(this);
this.__getterSetterInternalMap = {};
},
- set: function(map) {
+ set: function(map, options) {
+ options = options || {};
var self = this;
var changed = false;
_.each(map, function(val, key) {
@@ -387,10 +388,11 @@ instance.web.PropertiesMixin = _.extend({}, instance.web.EventDispatcherMixin, {
return;
changed = true;
self.__getterSetterInternalMap[key] = val;
- self.trigger("change:" + key, self, {
- oldValue: tmp,
- newValue: val
- });
+ if (! options.silent)
+ self.trigger("change:" + key, self, {
+ oldValue: tmp,
+ newValue: val
+ });
});
if (changed)
self.trigger("change", self);
diff --git a/addons/web/static/src/js/coresetup.js b/addons/web/static/src/js/coresetup.js
index a5a62b9bcc1..24441dc509f 100644
--- a/addons/web/static/src/js/coresetup.js
+++ b/addons/web/static/src/js/coresetup.js
@@ -550,7 +550,39 @@ $.async_when = function() {
/** Setup blockui */
if ($.blockUI) {
$.blockUI.defaults.baseZ = 1100;
- $.blockUI.defaults.message = '<img src="/web/static/src/img/throbber2.gif">';
+ $.blockUI.defaults.message = '<div class="oe_blockui_spin" style="height: 50px">';
+ $.blockUI.defaults.css.border = '0';
+ $.blockUI.defaults.css["background-color"] = '';
+ $.blockUI.spinners = [];
+}
+instance.web.blockUI = function() {
+ var tmp = $.blockUI.apply($, arguments);
+ var target = $(".oe_blockui_spin")[0];
+ var opts = {
+ lines: 13, // The number of lines to draw
+ length: 7, // The length of each line
+ width: 4, // The line thickness
+ radius: 10, // The radius of the inner circle
+ rotate: 0, // The rotation offset
+ color: '#FFF', // #rgb or #rrggbb
+ speed: 1, // Rounds per second
+ trail: 60, // Afterglow percentage
+ shadow: false, // Whether to render a shadow
+ hwaccel: false, // Whether to use hardware acceleration
+ className: 'spinner', // The CSS class to assign to the spinner
+ zIndex: 2e9, // The z-index (defaults to 2000000000)
+ top: 'auto', // Top position relative to parent in px
+ left: 'auto' // Left position relative to parent in px
+ };
+ var spinner = new Spinner(opts).spin(target);
+ $.blockUI.spinners.push(spinner);
+ return tmp;
+}
+instance.web.unblockUI = function() {
+ _.each($.blockUI.spinners, function(el) {
+ el.stop();
+ });
+ return $.unblockUI.apply($, arguments);
}
/** Setup default session */
diff --git a/addons/web/static/src/js/data_export.js b/addons/web/static/src/js/data_export.js
index ebe82ddb4b4..f8e669e1b4a 100644
--- a/addons/web/static/src/js/data_export.js
+++ b/addons/web/static/src/js/data_export.js
@@ -376,7 +376,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
exported_fields.unshift({name: 'id', label: 'External ID'});
var export_format = this.$element.find("#export_format").val();
- $.blockUI();
+ instance.web.blockUI();
this.session.get_file({
url: '/web/export/' + export_format,
data: {data: JSON.stringify({
@@ -387,7 +387,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
import_compat: Boolean(
this.$element.find("#import_compat").val())
})},
- complete: $.unblockUI
+ complete: instance.web.unblockUI
});
},
close: function() {
diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js
index 504510ef133..c3e7ad72dcb 100644
--- a/addons/web/static/src/js/search.js
+++ b/addons/web/static/src/js/search.js
@@ -330,6 +330,12 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
});
}
+ // Launch a search on clicking the oe_searchview_search button
+ this.$element.on('click', 'button.oe_searchview_search', function (e) {
+ e.stopImmediatePropagation();
+ self.do_search();
+ });
+
this.$element.on('keydown',
'.oe_searchview_input, .oe_searchview_facet', function (e) {
switch(e.which) {
@@ -510,7 +516,16 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
this.$element.addClass('oe_focused');
},
childBlurred: function () {
- this.$element.removeClass('oe_focused');
+ var val = this.$element.val();
+ this.$element.val('');
+ var complete = this.$element.data('autocomplete');
+ if ((val && complete.term === undefined) || complete.previous !== undefined) {
+ throw new Error("new jquery.ui version altering implementation" +
+ " details relied on");
+ }
+ delete complete.term;
+ this.$element.removeClass('oe_focused')
+ .trigger('blur');
},
/**
*
@@ -1475,7 +1490,17 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({
facet_for: function (value) {
var self = this;
if (value instanceof Array) {
- return $.when(facet_from(this, value));
+ if (value.length === 2 && _.isString(value[1])) {
+ return $.when(facet_from(this, value));
+ }
+ if (value.length > 1) {
+ // more than one search_default m2o id? Should we OR them?
+ throw new Error(
+ _("M2O search fields do not currently handle multiple default values"));
+ }
+ // there are many cases of {search_default_$m2ofield: [id]}, need
+ // to handle this as if it were a single value.
+ value = value[0];
}
return this.model.call('name_get', [value], {}).pipe(function (names) {
if (_(names).isEmpty()) { return null; }
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index 070ada62cc4..df7cd081338 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -33,6 +33,11 @@ instance.web.form.FieldManagerMixin = {
};
instance.web.views.add('form', 'instance.web.FormView');
+/**
+ * Properties:
+ * - actual_mode: always "view", "edit" or "create". Read-only property. Determines
+ * the mode used by the view.
+ */
instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerMixin, {
/**
* Indicates that this view is not searchable, and thus that no search
@@ -55,6 +60,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
* @property {instance.web.Registry} registry=instance.web.form.widgets widgets registry for this form view instance
*/
init: function(parent, dataset, view_id, options) {
+ var self = this;
this._super(parent);
this.set_default_options(options);
this.dataset = dataset;
@@ -82,6 +88,13 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
this.__blur_timeout = null;
this.rendering_engine = new instance.web.form.FormRenderingEngine(this);
this.qweb = null; // A QWeb instance will be created if the view is a QWeb template
+ self.set({actual_mode: self.options.initial_mode});
+ this.has_been_loaded.then(function() {
+ self.on("change:actual_mode", self, self.check_actual_mode);
+ self.check_actual_mode();
+ self.on("change:actual_mode", self, self.init_pager);
+ self.init_pager();
+ });
},
destroy: function() {
_.each(this.get_widgets(), function(w) {
@@ -125,17 +138,6 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
this.$buttons.on('click','.oe_form_button_save',this.on_button_save);
this.$buttons.on('click','.oe_form_button_cancel',this.on_button_cancel);
- this.$pager = $(QWeb.render("FormView.pager", {'widget':self}));
- if (this.options.$pager) {
- this.$pager.appendTo(this.options.$pager);
- } else {
- this.$element.find('.oe_form_pager').replaceWith(this.$pager);
- }
- this.$pager.on('click','a[data-pager-action]',function() {
- var action = $(this).data('pager-action');
- self.on_pager_action(action);
- });
-
this.$sidebar = this.options.$sidebar || this.$element.find('.oe_form_sidebar');
if (!this.sidebar && this.options.$sidebar) {
this.sidebar = new instance.web.Sidebar(this);
@@ -149,8 +151,15 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
{ label: _t('Set Default'), callback: function (item) { self.open_defaults_dialog(); } },
]);
}
- this.on("change:mode", this, this.switch_mode);
- this.set({mode: this.options.initial_mode});
+
+ // Add bounce effect on button 'Edit' when click on readonly page view.
+ this.$element.find(".oe_form_field, .oe_form_group_cell").on('click', function (e) {
+ if(self.get("actual_mode") == "view") {
+ var $button = self.options.$buttons.find(".oe_form_button_edit");
+ $button.wrap('<div>').css('margin-right','4px').addClass('oe_left oe_bounce');
+ }
+ });
+
this.has_been_loaded.resolve();
return $.when();
},
@@ -275,7 +284,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
}
return shown.pipe(function() {
if (options.editable) {
- self.set({mode: "edit"});
+ self.to_edit_mode();
}
self.$element.css('visibility', 'visible');
});
@@ -300,6 +309,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
return $.Deferred().reject();
}
this.datarecord = record;
+ this._actualize_mode();
this.set({ 'title' : record.id ? record.name : "New record" });
if (this.qweb) {
@@ -377,6 +387,24 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
this.reload();
}
},
+ init_pager: function() {
+ var self = this;
+ if (this.$pager)
+ this.$pager.remove();
+ if (this.get("actual_mode") === "create")
+ return;
+ this.$pager = $(QWeb.render("FormView.pager", {'widget':self}));
+ if (this.options.$pager) {
+ this.$pager.appendTo(this.options.$pager);
+ } else {
+ this.$element.find('.oe_form_pager').replaceWith(this.$pager);
+ }
+ this.$pager.on('click','a[data-pager-action]',function() {
+ var action = $(this).data('pager-action');
+ self.on_pager_action(action);
+ });
+ this.do_update_pager();
+ },
do_update_pager: function(hide_index) {
var index = hide_index ? '-' : this.dataset.index + 1;
this.$pager.find('button').prop('disabled', this.dataset.ids.length < 2).end()
@@ -576,9 +604,32 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
return $.Deferred().reject();
}
},
- switch_mode: function() {
+ /**
+ * Ask the view to switch to view mode if possible. The view may not do it
+ * if the current record is not yet saved. It will then stay in create mode.
+ */
+ to_view_mode: function() {
+ this._actualize_mode("view");
+ },
+ /**
+ * Ask the view to switch to edit mode if possible. The view may not do it
+ * if the current record is not yet saved. It will then stay in create mode.
+ */
+ to_edit_mode: function() {
+ this._actualize_mode("edit");
+ },
+ /**
+ * Reactualize actual_mode.
+ */
+ _actualize_mode: function(switch_to) {
+ var mode = switch_to || this.get("actual_mode");
+ if (! this.datarecord.id)
+ mode = "create";
+ this.set({actual_mode: mode});
+ },
+ check_actual_mode: function(source, options) {
var self = this;
- if(this.get("mode") == "view") {
+ if(this.get("actual_mode") === "view") {
self.$element.removeClass('oe_form_editable').addClass('oe_form_readonly');
self.$buttons.find('.oe_form_buttons_edit').hide();
self.$buttons.find('.oe_form_buttons_view').show();
@@ -596,11 +647,12 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
});
var fields_order = self.fields_order.slice(0);
if (self.default_focus_field) {
- fields_order.unshift(self.default_focus_field);
+ fields_order.unshift(self.default_focus_field.name);
}
for (var i = 0; i < fields_order.length; i += 1) {
var field = self.fields[fields_order[i]];
- if (!field.get('effective_invisible') && !field.get('effective_readonly') && field.focus() !== false) {
+ if (!field.get('effective_invisible') && !field.get('effective_readonly')) {
+ field.focus();
break;
}
}
@@ -609,19 +661,19 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
on_button_save: function() {
var self = this;
return this.do_save().then(function(result) {
- self.set({mode: "view"});
+ self.to_view_mode();
});
},
on_button_cancel: function(event) {
if (this.can_be_discarded()) {
- this.set({mode: "view"});
+ this.to_view_mode();
this.on_record_loaded(this.datarecord);
}
return false;
},
on_button_new: function() {
var self = this;
- this.set({mode: "edit"});
+ this.to_edit_mode();
return $.when(this.has_been_loaded).pipe(function() {
if (self.can_be_discarded()) {
return self.load_defaults();
@@ -629,7 +681,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
});
},
on_button_edit: function() {
- return this.set({mode: "edit"});
+ return this.to_edit_mode();
},
on_button_create: function() {
this.dataset.index = null;
@@ -642,7 +694,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
self.dataset.call('copy', [self.datarecord.id, {}, self.dataset.context]).then(function(new_id) {
return self.on_created({ result : new_id });
}).then(function() {
- return self.set({mode: "edit"});
+ return self.to_edit_mode();
}).then(function() {
def.resolve();
});
@@ -935,7 +987,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
register_field: function(field, name) {
this.fields[name] = field;
this.fields_order.push(name);
- if (field.node.attrs.default_focus == '1') {
+ if (JSON.parse(field.node.attrs.default_focus || "0")) {
this.default_focus_field = field;
}
@@ -957,7 +1009,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
return this.fields_view.fields[field_name];
},
is_create_mode: function() {
- return !this.datarecord.id;
+ return this.get("actual_mode") === "create";
},
open_translate_dialog: function(field) {
return this._super(field);
@@ -1641,10 +1693,13 @@ instance.web.form.WidgetButton = instance.web.form.FormWidget.extend({
this._super(view, node);
this.force_disabled = false;
this.string = (this.node.attrs.string || '').replace(/_/g, '');
- if (this.node.attrs.default_focus == '1') {
+ if (JSON.parse(this.node.attrs.default_focus || "0")) {
// TODO fme: provide enter key binding to widgets
this.view.default_focus_button = this;
}
+ if (this.node.attrs.icon && (! /\//.test(this.node.attrs.icon))) {
+ this.node.attrs.icon = '/web/static/src/img/icons/' + this.node.attrs.icon + '.png';
+ }
this.view.on('view_content_has_changed', this, this.check_disable);
},
start: function() {
@@ -2818,10 +2873,11 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
if (follow)
link += "<br />";
}
- this.$element.find('a')
+ var $link = this.$element.find('.oe_form_uri')
.unbind('click')
- .html(link)
- .click(function () {
+ .html(link);
+ if (! this.get_definition_options().no_open)
+ $link.click(function () {
self.do_action({
type: 'ir.actions.act_window',
res_model: self.field.relation,
@@ -2979,6 +3035,7 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({
}
if(view.view_type === "list") {
_.extend(view.options, {
+ addable: null,
selectable: self.multi_selection,
sortable: false,
import_enabled: false,
@@ -2986,7 +3043,6 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({
});
if (self.get("effective_readonly")) {
_.extend(view.options, {
- addable: null,
deletable: null,
reorderable: false,
});
@@ -3027,8 +3083,11 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({
this.viewmanager.on_controller_inited.add_last(function(view_type, controller) {
controller.o2m = self;
if (view_type == "list") {
- if (self.get("effective_readonly"))
- controller.set_editable(false);
+ if (self.get("effective_readonly")) {
+ controller.on('edit:before', self, function (e) {
+ e.cancel = true;
+ });
+ }
} else if (view_type === "form") {
if (self.get("effective_readonly")) {
$(".oe_form_buttons", controller.$element).children().remove();
@@ -3301,7 +3360,7 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({
.value();
},
do_add_record: function () {
- if (this.options.editable) {
+ if (this.editable()) {
this._super.apply(this, arguments);
} else {
var self = this;
@@ -3408,6 +3467,34 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({
this._super.apply(this, arguments);
}
});
+instance.web.form.One2ManyList = instance.web.ListView.List.extend({
+ pad_table_to: function (count) {
+ this._super(count > 0 ? count - 1 : 0);
+
+ // magical invocation of wtf does that do
+ if (this.view.o2m.get('effective_readonly')) {
+ return;
+ }
+
+ var self = this;
+ var columns = _(this.columns).filter(function (column) {
+ return column.invisible !== '1';
+ }).length;
+ if (this.options.selectable) { columns++; }
+ if (this.options.deletable) { columns++; }
+ var $cell = $('<td>', {
+ colspan: columns,
+ 'class': 'oe_form_field_one2many_list_row_add'
+ }).text(_t("Add a row"))
+ .click(function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ self.view.do_add_record();
+ });
+ this.$current.append(
+ $('<tr>').append($cell))
+ }
+});
instance.web.form.One2ManyFormView = instance.web.FormView.extend({
form_template: 'One2Many.formview',
@@ -3535,12 +3622,13 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in
render_value: function() {
var self = this;
var dataset = new instance.web.DataSetStatic(this, this.field.relation, self.view.dataset.get_context());
+ var values = self.get("value")
var handle_names = function(data) {
var indexed = {};
_.each(data, function(el) {
indexed[el[0]] = el;
});
- data = _.map(self.get("value"), function(el) { return indexed[el]; });
+ data = _.map(values, function(el) { return indexed[el]; });
if (! self.get("effective_readonly")) {
self.tags.containerElement().children().remove();
$("textarea", self.$element).css("padding-left", "3px");
@@ -3549,8 +3637,8 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in
self.$element.html(QWeb.render("FieldMany2ManyTag", {elements: data}));
}
};
- if (! self.get('values') || self.get('values').length > 0) {
- this._display_orderer.add(dataset.name_get(self.get("value"))).then(handle_names);
+ if (! values || values.length > 0) {
+ this._display_orderer.add(dataset.name_get(values)).then(handle_names);
} else {
handle_names([]);
}
@@ -4108,10 +4196,12 @@ instance.web.form.SelectCreatePopup = instance.web.form.AbstractFormPopup.extend
self.dataset, false,
_.extend({'deletable': false,
'selectable': !self.options.disable_multiple_selection,
- 'read_only': true,
'import_enabled': false,
'$buttons': self.$buttonpane,
}, self.options.list_view_options || {}));
+ self.view_list.on('edit:before', self, function (e) {
+ e.cancel = true;
+ });
self.view_list.popup = self;
self.view_list.appendTo($(".oe_popup_list", self.$element)).pipe(function() {
self.view_list.do_show();
@@ -4343,7 +4433,7 @@ instance.web.form.FieldBinary = instance.web.form.AbstractField.extend(instance.
//link.target = '_blank';
link.href = "data:application/octet-stream;base64," + value;
} else {
- $.blockUI();
+ instance.web.blockUI();
this.session.get_file({
url: '/web/binary/saveas_ajax',
data: {data: JSON.stringify({
@@ -4353,7 +4443,7 @@ instance.web.form.FieldBinary = instance.web.form.AbstractField.extend(instance.
filename_field: (this.node.attrs.filename || ''),
context: this.view.dataset.get_context()
})},
- complete: $.unblockUI,
+ complete: instance.web.unblockUI,
error: instance.webclient.crashmanager.on_rpc_error
});
ev.stopPropagation();
diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js
index f68f1354099..9c7bf88db1a 100644
--- a/addons/web/static/src/js/view_list.js
+++ b/addons/web/static/src/js/view_list.js
@@ -21,9 +21,6 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
// whether the view rows can be reordered (via vertical drag & drop)
'reorderable': true,
'action_buttons': true,
- // if true, the view can't be editable, ignoring the view's and the context's
- // instructions
- 'read_only': false,
// if true, the 'Import', 'Export', etc... buttons will be shown
'import_enabled': true,
},
@@ -360,6 +357,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
{ label: _t('Delete'), callback: this.do_delete_selected },
]);
this.sidebar.add_toolbar(this.fields_view.toolbar);
+ this.sidebar.$element.hide();
}
},
/**
@@ -378,6 +376,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
var total = dataset.size();
var limit = this.limit() || total;
+ this.$pager.toggle(total !== 0);
this.$pager.toggleClass('oe_list_pager_single_page', (total <= limit));
var spager = '-';
if (total) {
@@ -496,9 +495,6 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
},
do_show: function () {
this._super();
- if (this.sidebar) {
- this.sidebar.$element.show();
- }
if (this.$buttons) {
this.$buttons.show();
}
@@ -937,7 +933,6 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
'[data-id=' + record.get('id') + ']');
var index = $row.data('index');
$row.remove();
- self.refresh_zebra(index);
},
'reset': function () { return self.on_records_reset(); },
'change': function (event, record, attribute, value, old_value) {
@@ -972,8 +967,6 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
'[data-id=' + previous_record.get('id') + ']');
$new_row.insertAfter($previous_sibling);
}
-
- self.refresh_zebra(index, 1);
}
};
_(this.record_callbacks).each(function (callback, event) {
@@ -1113,7 +1106,6 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
this.$current
.children('tr:not([data-id])').remove().end()
.append(new Array(count - this.records.length + 1).join(row));
- this.refresh_zebra(this.records.length);
},
/**
* Gets the ids of all currently selected records, if any
@@ -1187,25 +1179,6 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
render_cell: function () {
return self.render_cell.apply(self, arguments); }
});
- },
- /**
- * Fixes fixes the even/odd classes
- *
- * @param {Number} [from_index] index from which to resequence
- * @param {Number} [offset = 0] selection offset for DOM, in case there are rows to ignore in the table
- */
- refresh_zebra: function (from_index, offset) {
- offset = offset || 0;
- from_index = from_index || 0;
- var dom_offset = offset + from_index;
- var sel = dom_offset ? ':gt(' + (dom_offset - 1) + ')' : null;
- this.$current.children(sel).each(function (i, e) {
- var index = from_index + i;
- // reset record-index accelerators on rows and even/odd
- var even = index%2 === 0;
- $(e).toggleClass('even', even)
- .toggleClass('odd', !even);
- });
}
});
instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.web.ListView.Groups# */{
@@ -1538,8 +1511,6 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we
}(dataset, record.get('id'), seq));
record.set('sequence', seq);
}
-
- list.refresh_zebra();
}
});
},
diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js
index 56df125c98b..ca889f68d8d 100644
--- a/addons/web/static/src/js/view_list_editable.js
+++ b/addons/web/static/src/js/view_list_editable.js
@@ -12,6 +12,8 @@ openerp.web.list_editable = function (instance) {
var self = this;
this._super.apply(this, arguments);
+ this._force_editability = null;
+ this._context_editable = false;
this.editor = this.make_editor();
// Stores records of {field, cell}, allows for re-rendering fields
// depending on cell state during and after resize events
@@ -37,6 +39,11 @@ openerp.web.list_editable = function (instance) {
}
});
+ this.on('edit:before', this, function (event) {
+ if (!self.editable() || self.editor.is_editing()) {
+ event.cancel = true;
+ }
+ });
this.on('edit:after', this, function () {
self.$element.add(self.$buttons).addClass('oe_editing');
});
@@ -62,26 +69,16 @@ openerp.web.list_editable = function (instance) {
do_edit: function (index, id, dataset) {
_.extend(this.dataset, dataset);
},
- /**
- * Sets editability status for the list, based on defaults, view
- * architecture and the provided flag, if any.
- *
- * @param {Boolean} [force] forces the list to editability. Sets new row edition status to "bottom".
- */
- set_editable: function (force) {
- // TODO: fix handling of editability status to be simpler & clearer & more coherent
- // If ``force``, set editability to bottom
- // otherwise rely on view default
- // view' @editable is handled separately as we have not yet
- // fetched and processed the view at this point.
- this.options.editable = (
- ! this.options.read_only && ((force && "bottom") || this.defaults.editable));
+ editable: function () {
+ return this.fields_view.arch.attrs.editable
+ || this._context_editable
+ || this.options.editable;
},
/**
* Replace do_search to handle editability process
*/
do_search: function(domain, context, group_by) {
- this.set_editable(context['set_editable']);
+ this._context_editable = !!context.set_editable;
this._super.apply(this, arguments);
},
/**
@@ -89,7 +86,7 @@ openerp.web.list_editable = function (instance) {
* as an editable row at the top or bottom of the list)
*/
do_add_record: function () {
- if (this.options.editable) {
+ if (this.editable()) {
this.$element.find('table:first').show();
this.$element.find('.oe_view_nocontent').remove();
this.start_edition();
@@ -103,9 +100,8 @@ openerp.web.list_editable = function (instance) {
this.editor.destroy();
}
// tree/@editable takes priority on everything else if present.
- this.options.editable = ! this.options.read_only && (data.arch.attrs.editable || this.options.editable);
var result = this._super(data, grouped);
- if (this.options.editable) {
+ if (this.editable()) {
// FIXME: any hook available to ensure this is only done once?
this.$buttons
.off('click', '.oe_list_save')
@@ -202,12 +198,20 @@ openerp.web.list_editable = function (instance) {
return;
}
+ // FIXME: need better way to get the field back from bubbling (delegated) DOM events somehow
+ field.$element.attr('data-fieldname', field_name);
self.fields_for_resize.push({field: field, cell: cell});
}, options).pipe(function () {
$recordRow.addClass('oe_edition');
self.resize_fields();
return record.attributes;
});
+ }).fail(function () {
+ // if the start_edition event is cancelled and it was a
+ // creation, remove the newly-created empty record
+ if (!record.get('id')) {
+ self.records.remove(record);
+ }
});
});
},
@@ -377,7 +381,7 @@ openerp.web.list_editable = function (instance) {
return this.reload_record(record);
},
prepends_on_create: function () {
- return this.options.editable === 'top';
+ return this.editable() === 'top';
},
setup_events: function () {
var self = this;
@@ -399,18 +403,20 @@ openerp.web.list_editable = function (instance) {
*
* @private
* @param {String} [next_record='succ'] method to call on the records collection to get the next record to edit
+ * @param {Object} [options]
+ * @param {String} [options.focus_field]
* @return {*}
*/
- _next: function (next_record) {
+ _next: function (next_record, options) {
next_record = next_record || 'succ';
var self = this;
return this.save_edition().pipe(function (saveInfo) {
if (saveInfo.created) {
return self.start_edition();
}
- return self.start_edition(
- self.records[next_record](
- saveInfo.record, {wraparound: true}));
+ var record = self.records[next_record](
+ saveInfo.record, {wraparound: true});
+ return self.start_edition(record, options);
});
},
keyup_ENTER: function () {
@@ -419,46 +425,142 @@ openerp.web.list_editable = function (instance) {
keyup_ESCAPE: function () {
return this.cancel_edition();
},
+ /**
+ * Gets the selection range (start, end) for the provided element,
+ * returns ``null`` if it can't get a range.
+ *
+ * @private
+ */
_text_selection_range: function (el) {
- if (el.selectionStart !== undefined) {
+ var selectionStart;
+ try {
+ selectionStart = el.selectionStart;
+ } catch (e) {
+ // radio or checkbox throw on selectionStart access
+ return null;
+ }
+ if (selectionStart !== undefined) {
return {
- start: el.selectionStart,
+ start: selectionStart,
end: el.selectionEnd
};
- } else if(document.body.createTextRange) {
+ } else if (document.body.createTextRange) {
throw new Error("Implement text range handling for MSIE");
var sel = document.body.createTextRange();
if (sel.parentElement() === el) {
}
}
+ // Element without selection ranges (select, div/@contenteditable)
+ return null;
},
_text_cursor: function (el) {
var selection = this._text_selection_range(el);
- if (selection.start !== selection.end) {
+ if (!selection) {
return null;
}
- return selection.start;
+ if (selection.start !== selection.end) {
+ return {position: null, collapsed: false};
+ }
+ return {position: selection.start, collapsed: true};
},
- keydown_UP: function (e) {
+ /**
+ * Checks if the cursor is at the start of the provided el
+ *
+ * @param {HTMLInputElement | HTMLTextAreaElement}
+ * @returns {Boolean}
+ * @private
+ */
+ _at_start: function (cursor, el) {
+ return cursor.collapsed && (cursor.position === 0);
+ },
+ /**
+ * Checks if the cursor is at the end of the provided el
+ *
+ * @param {HTMLInputElement | HTMLTextAreaElement}
+ * @returns {Boolean}
+ * @private
+ */
+ _at_end: function (cursor, el) {
+ return cursor.collapsed && (cursor.position === el.value.length);
+ },
+ /**
+ * @param DOMEvent event
+ * @param {String} record_direction direction to move into to get the next record (pred | succ)
+ * @param {Function} is_valid_move whether the edition should be moved to the next record
+ * @private
+ */
+ _key_move_record: function (event, record_direction, is_valid_move) {
if (!this.editor.is_editing('edit')) { return $.when(); }
- // FIXME: assumes editable widgets are input-type elements
- var index = this._text_cursor(e.target);
- // If selecting or not at the start of the input
- if (index === null || index !== 0) { return $.when(); }
+ var cursor = this._text_cursor(event.target);
+ // if text-based input (has a cursor)
+ // and selecting (not collapsed) or not at a field boundary
+ // don't move to the next record
+ if (cursor && !is_valid_move(event.target, cursor)) { return $.when(); }
- e.preventDefault();
- return this._next('pred');
+ event.preventDefault();
+ var source_field = $(event.target).closest('[data-fieldname]')
+ .attr('data-fieldname');
+ return this._next(record_direction, {focus_field: source_field});
+
+ },
+ keydown_UP: function (e) {
+ var self = this;
+ return this._key_move_record(e, 'pred', function (el, cursor) {
+ return self._at_start(cursor, el);
+ });
},
keydown_DOWN: function (e) {
- if (!this.editor.is_editing('edit')) { return $.when(); }
- // FIXME: assumes editable widgets are input-type elements
- var index = this._text_cursor(e.target);
- // If selecting or not at the end of the input
- if (index === null || index !== e.target.value.length) { return $.when(); }
+ var self = this;
+ return this._key_move_record(e, 'succ', function (el, cursor) {
+ return self._at_end(cursor, el);
+ });
+ },
- e.preventDefault();
- return this._next();
+ keydown_LEFT: function (e) {
+ // If the cursor is at the beginning of the field
+ var source_field = $(e.target).closest('[data-fieldname]')
+ .attr('data-fieldname');
+ var cursor = this._text_cursor(e.target);
+ if (cursor && !this._at_start(cursor, e.target)) { return $.when(); }
+
+ var fields_order = this.editor.form.fields_order;
+ var field_index = _(fields_order).indexOf(source_field);
+
+ // Look for the closest visible form field to the left
+ var fields = this.editor.form.fields;
+ var field;
+ do {
+ if (--field_index < 0) { return $.when(); }
+
+ field = fields[fields_order[field_index]];
+ } while (!field.$element.is(':visible'));
+
+ // and focus it
+ field.focus();
+ return $.when();
+ },
+ keydown_RIGHT: function (e) {
+ // same as above, but with cursor at the end of the field and
+ // looking for new fields at the right
+ var source_field = $(e.target).closest('[data-fieldname]')
+ .attr('data-fieldname');
+ var cursor = this._text_cursor(e.target);
+ if (cursor && !this._at_end(cursor, e.target)) { return $.when(); }
+
+ var fields_order = this.editor.form.fields_order;
+ var field_index = _(fields_order).indexOf(source_field);
+
+ var fields = this.editor.form.fields;
+ var field;
+ do {
+ if (++field_index >= fields_order.length) { return $.when(); }
+
+ field = fields[fields_order[field_index]];
+ } while (!field.$element.is(':visible'));
+
+ field.focus();
+ return $.when();
},
keydown_TAB: function (e) {
var form = this.editor.form;
@@ -642,7 +744,7 @@ openerp.web.list_editable = function (instance) {
instance.web.ListView.List.include(/** @lends instance.web.ListView.List# */{
row_clicked: function (event) {
- if (!this.options.editable) {
+ if (!this.view.editable()) {
return this._super.apply(this, arguments);
}
var record_id = $(event.currentTarget).data('id');
diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js
index ccf34576a1a..10f44a54f11 100644
--- a/addons/web/static/src/js/views.js
+++ b/addons/web/static/src/js/views.js
@@ -120,7 +120,9 @@ instance.web.ActionManager = instance.web.Widget.extend({
if (this.getParent() && this.getParent().do_push_state) {
if (this.inner_action) {
state['title'] = this.inner_action.name;
- state['model'] = this.inner_action.res_model;
+ if(this.inner_action.type == 'ir.actions.act_window') {
+ state['model'] = this.inner_action.res_model;
+ }
if (this.inner_action.id) {
state['action_id'] = this.inner_action.id;
}
@@ -178,7 +180,10 @@ instance.web.ActionManager = instance.web.Widget.extend({
});
},
do_action: function(action, on_close) {
- if (_.isNumber(action) || _.isString(action)) {
+ if (_.isString(action) && instance.web.client_actions.contains(action)) {
+ var action_client = { type: "ir.actions.client", tag: action };
+ return this.do_action(action_client);
+ } else if (_.isNumber(action) || _.isString(action)) {
var self = this;
return self.rpc("/web/action/load", { action_id: action }, function(result) {
self.do_action(result.result, on_close);
@@ -209,21 +214,30 @@ instance.web.ActionManager = instance.web.Widget.extend({
this.dialog_stop();
this.clear_breadcrumbs();
},
- ir_actions_act_window: function (action, on_close) {
- var self = this;
- if (_(['base.module.upgrade', 'base.setup.installer'])
- .contains(action.res_model)) {
- var old_close = on_close;
- on_close = function () {
- instance.webclient.do_reload().then(old_close);
- };
+
+ do_ir_actions_common: function(action, on_close) {
+ var self = this, klass, widget, add_breadcrumb;
+ if (action.type === 'ir.actions.client') {
+ var ClientWidget = instance.web.client_actions.get_object(action.tag);
+ widget = new ClientWidget(this, action.params);
+ klass = 'oe_act_client';
+ add_breadcrumb = function() {
+ self.push_breadcrumb({
+ widget: widget,
+ title: action.name
+ });
+ }
+ } else {
+ widget = new instance.web.ViewManagerAction(this, action);
+ klass = 'oe_act_window';
+ add_breadcrumb = widget.add_breadcrumb
}
if (action.target === 'new') {
if (this.dialog === null) {
// These buttons will be overwrited by <footer> if any
this.dialog = new instance.web.Dialog(this, {
buttons: { "Close": function() { $(this).dialog("close"); }},
- dialogClass: 'oe_act_window'
+ dialogClass: klass
});
if(on_close)
this.dialog.on_close.add(on_close);
@@ -231,7 +245,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
this.dialog_widget.destroy();
}
this.dialog.dialog_title = action.name;
- this.dialog_widget = new instance.web.ViewManagerAction(this, action);
+ this.dialog_widget = widget;
this.dialog_widget.appendTo(this.dialog.$element);
this.dialog.open();
} else {
@@ -242,11 +256,34 @@ instance.web.ActionManager = instance.web.Widget.extend({
});
}
this.inner_action = action;
- var inner_widget = this.inner_widget = new instance.web.ViewManagerAction(this, action);
- inner_widget.add_breadcrumb();
+ this.inner_widget = widget;
+ add_breadcrumb();
this.inner_widget.appendTo(this.$element);
}
},
+
+ ir_actions_act_window: function (action, on_close) {
+ var self = this;
+ if (_(['base.module.upgrade', 'base.setup.installer'])
+ .contains(action.res_model)) {
+ var old_close = on_close;
+ on_close = function () {
+ instance.webclient.do_reload().then(old_close);
+ };
+ }
+ if (action.target !== 'new') {
+ if(action.menu_id) {
+ this.dialog_stop();
+ return this.getParent().do_action(action, function () {
+ instance.webclient.menu.open_menu(action.menu_id);
+ });
+ }
+ }
+ return this.do_ir_actions_common(action, on_close);
+ },
+ ir_actions_client: function (action, on_close) {
+ return this.do_ir_actions_common(action, on_close);
+ },
ir_actions_act_window_close: function (action, on_closed) {
if (!this.dialog && on_closed) {
on_closed();
@@ -262,19 +299,9 @@ instance.web.ActionManager = instance.web.Widget.extend({
self.do_action(action, on_closed)
});
},
- ir_actions_client: function (action) {
- this.dialog_stop();
- var ClientWidget = instance.web.client_actions.get_object(action.tag);
- this.inner_widget = new ClientWidget(this, action.params);
- this.push_breadcrumb({
- widget: this.inner_widget,
- title: action.name
- });
- this.inner_widget.appendTo(this.$element);
- },
ir_actions_report_xml: function(action, on_closed) {
var self = this;
- $.blockUI();
+ instance.web.blockUI();
self.rpc("/web/session/eval_domain_and_context", {
contexts: [action.context],
domains: []
@@ -284,7 +311,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
self.session.get_file({
url: '/web/report',
data: {action: JSON.stringify(action)},
- complete: $.unblockUI,
+ complete: instance.web.unblockUI,
success: function(){
if (!self.dialog && on_closed) {
on_closed();
@@ -841,7 +868,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
} else {
self.do_attachement_update(self.dataset, self.model_id);
}
- $.unblockUI();
+ instance.web.unblockUI();
});
},
start: function() {
@@ -980,7 +1007,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
$e.parent().find('input[type=file]').prop('disabled', true);
$e.parent().find('button').prop('disabled', true).find('img, span').toggle();
this.$('.oe_sidebar_add_attachment span').text(_t('Uploading...'));
- $.blockUI();
+ instance.web.blockUI();
}
},
on_attachment_delete: function(e) {
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index b26e9169034..fc83ecd30ca 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -329,21 +329,20 @@
</span>
</t>
<t t-name="UserMenu.about">
- <div>
- <a class="oe_activate_debug_mode" href="?debug" style="float:right; font-size: 80%;">Activate the developer mode</a>
- <h1 style="margin:0;">OpenERP</h1>
- <h3 style="margin:15px 0;padding:0;">Version <t t-esc="version_info.version"/></h3>
- <p>
- Copyright © 2004-TODAY OpenERP SA. All Rights Reserved.<br />
- OpenERP is a trademark of the <a target="_blank" href="http://openerp.com/" style="text-decoration: underline;">OpenERP SA Company</a>.
- </p>
- <p>
- Licenced under the terms of <a target="_blank" href="http://www.gnu.org/licenses/agpl.html" style="text-decoration: underline;">GNU Affero General Public License</a>
- </p>
- <p>
- For more information visit <a target="_blank" href="http://openerp.com/" style="text-decoration: underline;">OpenERP.com</a>
- </p>
+
+ <div class="oe_about">
+ <a class="oe_activate_debug_mode oe_right" href="?debug">Activate the developer mode</a>
+ <img class="oe_logo" src="/web/static/src/img/logo2.png"/>
+ <h3>Version <t t-esc="version_info.version"/></h3>
+
+ <div class="oe_bottom">
+ <p>Copyright © 2004-TODAY OpenERP SA. All Rights Reserved.<br />
+ OpenERP is a trademark of the <a target="_blank" href="http://openerp.com/" style="text-decoration: underline;">OpenERP SA Company</a>.</p>
+ <p>Licenced under the terms of <a target="_blank" href="http://www.gnu.org/licenses/agpl.html" style="text-decoration: underline;">GNU Affero General Public License</a></p>
+ <p>For more information visit <a target="_blank" href="http://openerp.com/" style="text-decoration: underline;">OpenERP.com</a></p>
+ </div>
</div>
+
</t>
<t t-name="UserMenu.password">
<form name="change_password_form" method="POST">
@@ -519,25 +518,25 @@
<div class="oe_form_dropdown_section">
<button class="oe_dropdown_toggle oe_dropdown_arrow">
<t t-esc="section.label"/>
- <ul class="oe_dropdown_menu">
- <li t-foreach="widget.items[section.name]" t-as="item" t-att-class="item.classname">
- <a class="oe_sidebar_action_a" t-att-title="item.title" t-att-data-section="section.name" t-att-data-index="item_index" t-att-href="item.url" target="_blank">
- <t t-raw="item.label"/>
- </a>
- <a t-if="section.name == 'files'" class="oe_sidebar_delete_item" t-att-data-id="item.id" title="Delete this attachment">x</a>
- </li>
- <li t-if="section.name == 'files'" class="oe_sidebar_add_attachment">
- <t t-call="HiddenInputFile">
- <t t-set="fileupload_id" t-value="widget.fileupload_id"/>
- <t t-set="fileupload_action">/web/binary/upload_attachment</t>
- <input type="hidden" name="model" t-att-value="widget.dataset and widget.dataset.model"/>
- <input type="hidden" name="id" t-att-value="widget.model_id"/>
- <input type="hidden" name="session_id" t-att-value="widget.session.session_id"/>
- <span>Add...</span>
- </t>
- </li>
- </ul>
</button>
+ <ul class="oe_dropdown_menu">
+ <li t-foreach="widget.items[section.name]" t-as="item" t-att-class="item.classname">
+ <a class="oe_sidebar_action_a" t-att-title="item.title" t-att-data-section="section.name" t-att-data-index="item_index" t-att-href="item.url" target="_blank">
+ <t t-raw="item.label"/>
+ </a>
+ <a t-if="section.name == 'files'" class="oe_sidebar_delete_item" t-att-data-id="item.id" title="Delete this attachment">x</a>
+ </li>
+ <li t-if="section.name == 'files'" class="oe_sidebar_add_attachment">
+ <t t-call="HiddenInputFile">
+ <t t-set="fileupload_id" t-value="widget.fileupload_id"/>
+ <t t-set="fileupload_action">/web/binary/upload_attachment</t>
+ <input type="hidden" name="model" t-att-value="widget.dataset and widget.dataset.model"/>
+ <input type="hidden" name="id" t-att-value="widget.model_id"/>
+ <input type="hidden" name="session_id" t-att-value="widget.session.session_id"/>
+ <span>Add...</span>
+ </t>
+ </li>
+ </ul>
</div>
</t>
</div>
@@ -646,17 +645,14 @@
<t t-name="ListView.rows" t-foreach="records.length" t-as="index">
<t t-call="ListView.row">
<t t-set="record" t-value="records.at(index)"/>
- <t t-set="row_parity" t-value="index_parity"/>
</t>
</t>
-<tr t-name="ListView.row" t-att-class="row_parity"
+<tr t-name="ListView.row"
t-att-data-id="record.get('id')"
t-att-style="view.style_for(record)">
<t t-set="asData" t-value="record.toForm().data"/>
<t t-foreach="columns" t-as="column">
- <td t-if="column.meta">
-
- </td>
+ <td t-if="column.meta"> </td>
</t>
<th t-if="options.selectable" class="oe_list_record_selector" width="1">
<t t-set="checked" t-value="options.select_view_id == record.get('id') ? 'checked' : null"/>
@@ -675,7 +671,6 @@
<button type="button" name="delete" class="oe_i">d</button>
</td>
</tr>
-
<t t-extend="ListView.buttons">
<t t-jquery="button.oe_list_add" t-operation="after">
<button class="oe_button oe_list_save oe_highlight"
@@ -685,6 +680,15 @@
<a href="#" class="oe_bold oe_list_discard">discard</a>
</t>
</t>
+<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
+ missing columns
+ -->
+ <t t-jquery="&gt; :last" t-operation="after">
+ <td t-if="edited and !options.deletable" class="oe-listview-padding"/>
+ </t>
+</t>
<t t-name="FormView">
<div class="oe_formview">
@@ -956,11 +960,13 @@
<t t-name="FieldMany2One">
<span class="oe_form_field oe_form_field_many2one oe_form_field_with_button" t-att-style="widget.node.attrs.style">
<t t-if="widget.get('effective_readonly')">
- <a href="#" class="oe_form_uri"/>
+ <a t-if="! widget.get_definition_options().no_open" href="#" class="oe_form_uri"/>
+ <span t-if="widget.get_definition_options().no_open" href="#" class="oe_form_uri"/>
<span class="oe_form_m2o_follow"/>
</t>
<t t-if="!widget.get('effective_readonly')">
- <a href="#" tabindex="-1" class="oe_m2o_cm_button oe_e oe_right">/</a>
+ <a t-if="! widget.get_definition_options().no_open" href="#" tabindex="-1"
+ class="oe_m2o_cm_button oe_e oe_right">/</a>
<div>
<input type="text"
t-att-id="widget.id_for_label"
@@ -975,7 +981,6 @@
</t>
</span>
</t>
-<!-- Collection of m2m tags -->
<t t-name="FieldMany2ManyTags">
<div class="oe_form_field oe_tags" t-att-style="widget.node.attrs.style">
<t t-if="! widget.get('effective_readonly')">
@@ -984,7 +989,6 @@
</t>
</div>
</t>
-<!-- Individual m2m tag element -->
<t t-name="FieldMany2ManyTag">
<t t-set="i" t-value="0"/>
<t t-foreach="elements" t-as="el">
@@ -1132,7 +1136,7 @@
t-att-style="widget.node.attrs.style"
t-att-tabindex="widget.node.attrs.tabindex"
t-att-autofocus="widget.node.attrs.autofocus">
- <img t-if="widget.node.attrs.icon" t-att-src="_s + '/web/static/src/img/icons/' + widget.node.attrs.icon + '.png'" width="16" height="16"/>
+ <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>
</button>
</t>
@@ -1190,6 +1194,41 @@
</table>
</t>
+<t t-name="AbstractFormPopup.render">
+ <div>
+ <table style="width:100%">
+ <tr style="width:100%">
+ <td style="width:100%">
+ <div class="oe_popup_search" style="width:100%"></div>
+ </td>
+ </tr>
+ <tr style="width:100%">
+ <td style="width:100%">
+ <div class="oe_popup_list" style="width:100%"></div>
+ </td>
+ </tr>
+ </table>
+ <div class="oe_popup_form" style="width:100%"></div>
+ </div>
+</t>
+<t t-name="SelectCreatePopup.search.buttons">
+ <t t-if="! widget.options.disable_multiple_selection">
+ <button type="button" class="oe_button oe_selectcreatepopup-search-select" disabled="disabled">Select</button>
+ or
+ </t>
+ <a class="oe_button oe_selectcreatepopup-search-close oe_bold oe_form_button_cancel" href="javascript:void(0)">Cancel</a>
+</t>
+<t t-name="AbstractFormPopup.buttons">
+ <t t-if="! multi_select">
+ <button type="button" class="oe_button oe_abstractformpopup-form-save oe_highlight">Save</button>
+ </t>
+ <t t-if="multi_select">
+ <button type="button" class="oe_button oe_abstractformpopup-form-save-new oe_highlight">Save &amp; New</button>
+ <button type="button" class="oe_button oe_abstractformpopup-form-save oe_highlight">Save &amp; Close</button>
+ </t>
+ or <a class="oe_button oe_abstractformpopup-form-close oe_bold oe_form_button_cancel" href="javascript:void(0)">Discard</a>
+</t>
+
<t t-name="One2Many.viewmanager" t-extend="ViewManager">
<t t-jquery=".oe-view-manager-header">
this.attr('t-if', 'views.length != 1');
@@ -1220,6 +1259,8 @@
<div class="oe_searchview_clear"/>
<div class="oe_searchview_unfold_drawer" title="Advanced Search..."/>
<div class="oe_searchview_drawer"/>
+ <button type="button" class="oe_searchview_search"
+ title="Search Again">Search</button>
</div>
<div t-name="SearchView.InputView"
@@ -1240,7 +1281,6 @@
<span t-name="SearchView.FacetView.Value" class="oe_facet_value">
<t t-esc="widget.model.get('label')"/>
</span>
-
<t t-name="SearchView.managed-filters">
<option class="oe_search_filters_title" value="">Filters</option>
<optgroup label="-- Filters --">
@@ -1265,7 +1305,6 @@
<p>(Any existing filter with the same name will be replaced)</p>
</div>
</t>
-
<t t-name="SearchView.render_lines">
<table class="oe_search_render_line" border="0" cellspacing="0" cellpadding="0"
t-foreach="lines" t-as="line">
@@ -1407,8 +1446,8 @@
<div t-name="SearchView.addtodashboard" class="oe_searchview_dashboard">
<h4>Add to Dashboard</h4>
<form>
- <input placeholder ="Title of new Dashboard item" title = "Title of new Dashboard item" type="text"/>
- <button class="oe_apply" type="submit">save</button>
+ <p><input placeholder ="Title of new Dashboard item" title = "Title of new Dashboard item" type="text"/></p>
+ <button class="oe_apply" type="submit">Save</button>
</form>
</div>
<t t-name="SearchView.addtodashboard.selection">
@@ -1462,49 +1501,6 @@
</t>
</select>
</t>
-<t t-name="AbstractFormPopup.render">
- <div>
- <table style="width:100%">
- <tr style="width:100%">
- <td style="width:100%">
- <div class="oe_popup_search" style="width:100%"></div>
- </td>
- </tr>
- <tr style="width:100%">
- <td style="width:100%">
- <div class="oe_popup_list" style="width:100%"></div>
- </td>
- </tr>
- </table>
- <div class="oe_popup_form" style="width:100%"></div>
- </div>
-</t>
-<t t-name="SelectCreatePopup.search.buttons">
- <t t-if="! widget.options.disable_multiple_selection">
- <button type="button" class="oe_button oe_selectcreatepopup-search-select" disabled="disabled">Select</button>
- or
- </t>
- <a class="oe_button oe_selectcreatepopup-search-close oe_bold oe_form_button_cancel" href="javascript:void(0)">Cancel</a>
-</t>
-<t t-name="AbstractFormPopup.buttons">
- <t t-if="! multi_select">
- <button type="button" class="oe_button oe_abstractformpopup-form-save oe_highlight">Save</button>
- </t>
- <t t-if="multi_select">
- <button type="button" class="oe_button oe_abstractformpopup-form-save-new oe_highlight">Save &amp; New</button>
- <button type="button" class="oe_button oe_abstractformpopup-form-save oe_highlight">Save &amp; Close</button>
- </t>
- or <a class="oe_button oe_abstractformpopup-form-close oe_bold oe_form_button_cancel" href="javascript:void(0)">Cancel</a>
-</t>
-<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
- missing columns
- -->
- <t t-jquery="&gt; :last" t-operation="after">
- <td t-if="edited and !options.deletable" class="oe-listview-padding"/>
- </t>
-</t>
<t t-name="view_editor">
<table class="oe_view_editor">
@@ -1569,6 +1565,7 @@
<t t-name="vieweditor_boolean">
<input type="checkbox" t-att-id="widget.name"/>
</t>
+
<t t-name="ExportView">
<a id="exportview" href="javascript: void(0)" style="text-decoration: none;color: #3D3D3D;">Export</a>
</t>