[IMP] web client refactoring: action and view manager
authorGéry Debongnie <ged@odoo.com>
Wed, 20 Aug 2014 15:02:16 +0000 (17:02 +0200)
committerGéry Debongnie <ged@odoo.com>
Tue, 21 Oct 2014 07:33:49 +0000 (09:33 +0200)
large rewrite of action manager, view manager and
viewmanageraction.  The goal is to lay the foundation
for the redesign of the advanced search view.

This commit includes:
* improvements to the display order (no/less flickering)
* large simplification of the breadcrumbs code
* much better html layout for the header (no table)
* bootstrapisation of the view manager
* lots of optimizations/simplification
* a base.css.map, courtesy of the last sass version

addons/web/static/src/css/base.css
addons/web/static/src/css/base.sass
addons/web/static/src/js/search.js
addons/web/static/src/js/views.js
addons/web/static/src/xml/base.xml

index 23fb4ed..41d1f35 100644 (file)
 }
 .openerp .zebra tbody tr:hover td {
   background-color: #e6e6e6;
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#eeeeee), to(#dedede));
-  background-image: -webkit-linear-gradient(top, #eeeeee, #dedede);
-  background-image: -moz-linear-gradient(top, #eeeeee, #dedede);
-  background-image: -ms-linear-gradient(top, #eeeeee, #dedede);
-  background-image: -o-linear-gradient(top, #eeeeee, #dedede);
-  background-image: linear-gradient(to bottom, #eeeeee, #dedede);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#dedede));
+  background-image: -webkit-linear-gradient(top, #eee, #dedede);
+  background-image: -moz-linear-gradient(top, #eee, #dedede);
+  background-image: -ms-linear-gradient(top, #eee, #dedede);
+  background-image: -o-linear-gradient(top, #eee, #dedede);
+  background-image: linear-gradient(to bottom, #eee, #dedede);
 }
 .openerp input, .openerp textarea, .openerp select {
   padding: 2px 4px;
-  border: 1px solid #cccccc;
+  border: 1px solid #ccc;
   -moz-border-radius: 3px;
   -webkit-border-radius: 3px;
   border-radius: 3px;
   font-weight: bold;
   font-size: inherit;
 }
-.openerp a.button:link, .openerp a.button:visited, .openerp button, .openerp .oe_button, .openerp input[type='submit'] {
+.openerp a.button:link, .openerp a.button:visited, .openerp .oe_button, .openerp input[type='submit'] {
   display: inline-block;
   border: 1px solid rgba(0, 0, 0, 0.4);
   color: #4c4c4c;
   -webkit-font-smoothing: antialiased;
   outline: none;
 }
-.openerp a.button:hover, .openerp button:hover, .openerp .oe_button:hover, .openerp input[type='submit']:hover {
+.openerp a.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);
   cursor: pointer;
   background-position: 0;
 }
-.openerp a.button:focus, .openerp button:focus, .openerp .oe_button:focus, .openerp input[type='submit']:focus {
+.openerp a.button:focus, .openerp .oe_button:focus, .openerp input[type='submit']:focus {
   border: 1px solid #80bfff;
   background-position: 0;
   background-color: #ececec;
   -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 a.button:active, .openerp a.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);
   -webkit-box-shadow: none;
   box-shadow: none;
 }
-.openerp a.button.disabled, .openerp button:disabled, .openerp .oe_button:disabled, .openerp input[type='submit']:disabled {
+.openerp a.button.disabled, .openerp .oe_button:disabled, .openerp input[type='submit']:disabled {
   background: #efefef !important;
   border: 1px solid #d1d1d1 !important;
   -moz-box-shadow: none !important;
   -webkit-box-shadow: none !important;
   box-shadow: none !important;
-  color: #aaaaaa !important;
+  color: #aaa !important;
   cursor: default;
-  text-shadow: 0 1px 1px white !important;
+  text-shadow: 0 1px 1px #fff !important;
 }
 .openerp .ui-widget-content a {
-  color: #7c7bad;
+  color: #7C7BAD;
 }
 .openerp .oe_bounce_container {
   display: inline-block;
   cursor: wait;
 }
 .openerp .oe_fade {
-  color: #888888;
+  color: #888;
   font-weight: normal;
 }
 .openerp .oe_bold {
 }
 .openerp .oe_highlight {
   color: white;
-  background: #dc5f59;
+  background: #DC5F59;
 }
 .openerp button.oe_highlight {
   background-color: #c02c2c;
   background-image: linear-gradient(to bottom, #c52020, #d22323);
 }
 .openerp .oe_background_grey {
-  background: #eeeeee !important;
+  background: #eee !important;
 }
 .openerp .oe_form_dirty .oe_highlight_on_dirty {
   color: white;
   box-shadow: none;
 }
 .openerp .oe_form_dirty button.oe_highlight_on_dirty:hover {
-  background: #ed6f6a;
+  background: #ED6F6A;
 }
 .openerp .oe_warning_redirect {
   border: none !important;
   font-weight: normal;
   width: 132px !important;
   height: 40px;
-  color: #666666;
+  color: #666;
   margin: 0px -1px -1px 0px;
   padding: 0;
   border: 1px solid #dddddd;
   line-height: 120%;
 }
 .openerp .oe_stat_button .stat_button_icon {
-  color: #7c7bad;
+  color: #7C7BAD;
   font-size: 24px;
   padding: 0px 3px;
   width: 37px;
   -moz-box-shadow: none;
   -webkit-box-shadow: none;
   box-shadow: none;
-  color: #7c7bad;
+  color: #7C7BAD;
   font-weight: bold;
 }
 .openerp .oe_button.oe_link span:hover {
   max-width: 650px;
 }
 .openerp .oe_grey {
-  color: #aaaaaa;
+  color: #aaa;
 }
 .openerp .oe_error_detail hr {
   display: block;
   -webkit-border-radius: 6px;
   border-radius: 6px;
   background-position: center center;
-  background-image: -webkit-radial-gradient(circle, #eeeeee 0%, #cccccc 40%, #bbbbbb 100%);
-  background-image: -moz-radial-gradient(#eeeeee 0%, #cccccc 40%, #bbbbbb 100%);
-  background-image: -ms-radial-gradient(#eeeeee 0%, #cccccc 40%, #bbbbbb 100%);
-  background-image: radial-gradient(circle, #eeeeee 0%, #cccccc 40%, #bbbbbb 100%);
+  background-image: -webkit-radial-gradient(circle, #eee 0%, #ccc 40%, #bbb 100%);
+  background-image: -moz-radial-gradient(#eee 0%, #ccc 40%, #bbb 100%);
+  background-image: -ms-radial-gradient(#eee 0%, #ccc 40%, #bbb 100%);
+  background-image: radial-gradient(circle, #eee 0%, #ccc 40%, #bbb 100%);
 }
 .openerp .oe_kanban_status_green {
   background: green;
   -webkit-border-radius: 3px;
   border-radius: 3px;
   background: #f0f0fa;
-  color: #4c4c4c;
+  color: #4C4C4C;
 }
 .openerp .oe_tag_dark {
-  background: #7c7bad;
-  color: #eeeeee;
+  background: #7C7BAD;
+  color: #eee;
 }
 .openerp .oe_form_field_radio.oe_horizontal {
   white-space: nowrap;
 }
 .openerp .oe_notebook > li > a {
   display: block;
-  color: gray;
+  color: #808080;
 }
 .openerp .oe_notebook > li.ui-tabs-active > a {
   color: #4c4c4c;
 }
 .openerp .oe_notebook {
-  border-color: #dddddd;
+  border-color: #ddd;
   border-style: solid;
   border-width: 0 0 1px;
 }
 }
 .openerp .oe_notebook > li > a:hover {
   text-decoration: none;
-  background-color: #eeeeee;
-  border-color: #eeeeee #eeeeee #dddddd;
+  background-color: #eee;
+  border-color: #eee #eee #ddd;
 }
 .openerp .ui-tabs .oe_notebook.ui-tabs-nav li.ui-tabs-active {
   border-bottom: none;
   padding-bottom: 1px;
 }
 .openerp .oe_notebook > li.ui-state-active > a, .openerp .oe_notebook > li.ui-state-active > a:hover {
-  background-color: white;
-  border: 1px solid #dddddd;
+  background-color: #ffffff;
+  border: 1px solid #ddd;
   border-bottom-color: transparent;
   cursor: default;
 }
   cursor: pointer;
 }
 .openerp .oe_dropdown_toggle {
-  color: #2b2b2b;
+  color: #2B2B2B;
   font-weight: normal;
 }
 .openerp .oe_dropdown_hover:hover .oe_dropdown_menu, .openerp .oe_dropdown_menu.oe_opened {
   top: 0;
   right: 50%;
   padding: 4px 12px;
-  background: #a61300;
+  background: #A61300;
   color: white;
   text-align: center;
-  border: 1px solid #990000;
+  border: 1px solid #900;
   border-top: none;
   -moz-border-radius-bottomright: 8px;
   -moz-border-radius-bottomleft: 8px;
   width: 32px;
 }
 .openerp .oe_database_manager {
-  background: white;
-  color: black;
+  background: #fff;
+  color: #000;
   text-align: left;
 }
 .openerp .oe_database_manager .oe_database_manager_menu {
-  color: black;
+  color: #000;
 }
 .openerp .oe_webclient {
   width: 100%;
   width: 100%;
   display: none;
   text-align: center;
-  color: #eeeeee;
+  color: #eee;
   background: rgba(37, 37, 37, 0.9);
   -webkit-box-sizing: border-box;
   -moz-box-sizing: border-box;
 .openerp .oe_secondary_menu_section {
   font-weight: bold;
   margin-left: 8px;
-  color: #7c7bad;
+  color: #7C7BAD;
 }
 .openerp .oe_secondary_submenu {
   margin-bottom: 10px !important;
 }
 .openerp .oe_about .user-details .user-info-block .navigation li.active a {
   background: #a24689;
-  color: white;
+  color: #fff;
 }
 .openerp .oe_about .user-details .user-info-block .user-body {
   text-align: center;
   transform: scale(1.3);
 }
 .openerp .oe_about #social .social-fb:hover {
-  color: #3b5998;
+  color: #3B5998;
 }
 .openerp .oe_about #social .social-tw:hover {
-  color: #4099ff;
+  color: #4099FF;
 }
 .openerp .oe_about #social .social-gp:hover {
   color: #d34836;
   width: 100%;
   height: 100%;
 }
-.openerp .oe_application a {
-  color: #7c7bad;
+.openerp .oe_application .oe-view-manager-body a {
+  color: #7C7BAD;
+}
+.openerp .oe_application .oe-view-manager-body .oe-view-manager-view-kanban:not(:empty) {
+  height: 100%;
 }
 .openerp .oe_application > div {
   position: relative;
   overflow: hidden;
   font-weight: bold;
 }
+.openerp .oe-view-manager-header {
+  height: 90px;
+  overflow: hidden;
+  border-bottom: 1px solid black;
+  display: none;
+}
+.openerp .oe-view-manager-header .row {
+  height: 45px;
+}
+.openerp .oe-view-manager-header .oe-view-title {
+  float: left;
+  font-size: 18px;
+  font-weight: bold;
+  margin: 0;
+}
+.openerp .oe-view-manager-header .oe-header-title {
+  padding-left: 0;
+}
+.openerp .oe-view-manager-header .oe-view-manager-search-view {
+  float: right;
+  padding-top: 5px;
+}
+.openerp .oe-view-manager-header .oe-view-manager-switch {
+  float: right;
+}
+.openerp .oe-view-manager-header .oe-view-manager-switch .oe-vm-switch-kanban:before {
+  content: "";
+}
+.openerp .oe-view-manager-header .oe-view-manager-switch .oe-vm-switch-list:before {
+  content: "";
+}
+.openerp .oe-view-manager-header .oe-view-manager-switch .oe-vm-switch-form:before {
+  content: "";
+}
+.openerp .oe-view-manager-header .oe-view-manager-switch .oe-vm-switch-graph:before {
+  content: "";
+}
+.openerp .oe-view-manager-header .oe-view-manager-switch .oe-vm-switch-calendar:before {
+  content: "";
+}
+.openerp .oe-view-manager-header .oe-view-manager-switch .oe-vm-switch-gantt:before {
+  content: "";
+}
+.openerp .oe-view-manager-header .oe-view-manager-buttons {
+  float: left;
+}
+.openerp .oe-view-manager-header .oe-view-manager-buttons > div {
+  display: none;
+}
+.openerp .oe_application > div > div > .oe-view-manager-body {
+  position: absolute;
+  top: 90px;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  overflow: auto;
+}
 .openerp .oe_view_manager {
   display: table;
   height: inherit;
   line-height: 30px;
 }
 .openerp .oe_view_manager table.oe_view_manager_header h2 a {
-  color: #7c7bad;
+  color: #7C7BAD;
 }
 .openerp .oe_view_manager table.oe_view_manager_header .oe_dropdown_menu {
   line-height: normal;
   text-decoration: none;
 }
 .openerp .oe_view_manager table.oe_view_manager_header .oe_button_group .active {
-  background: #999999;
+  background: #999;
   -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) inset;
   -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) inset;
   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) inset;
 }
 .openerp .oe_view_manager table.oe_view_manager_header .oe_button_group .active a {
-  color: white;
+  color: #fff;
   text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
 }
 .openerp .oe_view_manager table.oe_view_manager_header .oe_view_manager_buttons {
   text-decoration: none;
 }
 .openerp .oe_pager_group .active {
-  background: #999999;
+  background: #999;
   -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) inset;
   -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) inset;
   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) inset;
 }
 .openerp .oe_pager_group .active a {
-  color: white;
+  color: #fff;
   text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
 }
 .openerp .oe_list_pager.oe_list_pager_single_page .oe_pager_group {
   display: none;
 }
-.openerp .oe_view_manager_current {
-  height: 100%;
-}
-.openerp .oe_view_manager_current > .oe_view_manager_header {
-  border-bottom: 1px solid #cacaca;
-  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);
-  -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 9px rgba(0, 0, 0, 0.1);
-  -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 9px rgba(0, 0, 0, 0.1);
-  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 9px rgba(0, 0, 0, 0.1);
-}
-.openerp .oe_view_manager_current > .oe_view_manager_header .oe_header_row td {
-  padding: 8px;
-}
-.openerp .oe_view_manager_current > .oe_view_manager_header .oe_header_row:first-child td {
-  padding-top: 8px;
-}
 .openerp .oe_view_manager_inline, .openerp .oe_view_manager_inlineview {
   height: 100%;
 }
 .openerp .oe_searchview {
   cursor: text;
   position: relative;
-  float: right;
   padding: 1px 0;
-  line-height: 18px;
   min-width: 400px;
-  border: 1px solid #ababab;
-  background: white;
+  width: 400px;
   -moz-border-radius: 13px;
   -webkit-border-radius: 13px;
   border-radius: 13px;
-  -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset;
-  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset;
-  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset;
 }
 .openerp .oe_searchview input, .openerp .oe_searchview textarea {
   padding: 3px;
 .openerp .oe_searchview .oe_searchview_clear {
   cursor: pointer;
   position: absolute;
-  top: 0;
+  top: 3px;
   right: 18px;
   width: 15px;
   height: 24px;
-  background: url(../img/search_reset.gif) center center no-repeat;
 }
 .openerp .oe_searchview .oe_searchview_unfold_drawer {
   position: absolute;
   top: 0;
   right: 0;
-  height: 24px;
-  padding: 0 7px 0 4px;
-  color: #cccccc;
+  color: #ccc;
   cursor: pointer;
 }
 .openerp .oe_searchview .oe_searchview_unfold_drawer:hover {
-  color: #999999;
+  color: #999;
 }
 .openerp .oe_searchview .oe_searchview_unfold_drawer:before {
   position: absolute;
-  top: 10px;
-  right: 7px;
+  top: 7px;
+  right: 18px;
   width: 0;
-  height: 0;
-  display: inline-block;
-  content: "";
-  vertical-align: top;
-  border-top: 5px solid #4c4c4c;
-  border-left: 5px solid transparent;
-  border-right: 5px solid transparent;
-  filter: alpha(opacity=50);
-  opacity: 0.5;
 }
 .openerp .oe_searchview .oe_searchview_search {
-  font-size: 1px;
-  letter-spacing: -1px;
-  color: transparent;
-  text-shadow: none;
-  font-weight: normal;
-  -moz-box-shadow: none;
-  -webkit-box-shadow: none;
-  box-shadow: none;
-  -moz-border-radius: 0;
-  -webkit-border-radius: 0;
-  border-radius: 0;
+  cursor: pointer;
   position: absolute;
-  left: 3px;
-  top: 1px;
-  padding: 0;
-  border: none;
-  background: transparent;
-}
-.openerp .oe_searchview .oe_searchview_search:before {
-  font: 21px "mnmliconsRegular";
-  content: "r";
-  color: #a3a3a3;
+  left: 6px;
+  top: 8px;
 }
 .openerp .oe_searchview .oe_searchview_facets {
   min-height: 22px;
-  margin: 0 35px 0 15px;
+  margin: 2px 35px 0 20px;
 }
 .openerp .oe_searchview .oe_searchview_facets * {
   vertical-align: top;
   display: inline-block;
-  line-height: 17px;
+  font-size: 100%;
 }
 .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet {
+  height: 20px;
   margin: 1px 0;
   font-size: 11px;
 }
   padding: 0;
   -webkit-font-smoothing: auto;
 }
+.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet span {
+  height: 18px;
+}
 .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet:focus {
   border-color: #a6a6fe;
   -moz-box-shadow: 0 0 3px 1px #a6a6fe;
 }
 .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_values {
   background: #f0f0fa;
-  -moz-border-radius: 0 3px 3px 0;
-  -webkit-border-radius: 0 3px 3px 0;
-  border-radius: 0 3px 3px 0;
 }
 .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_category, .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_value {
   padding: 0 4px;
   font-size: 16px;
 }
 .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_value {
-  border-left: 1px solid #afafb6;
-  text-shadow: 0 1px 1px white;
-  color: #4c4c4c;
+  color: #4C4C4C;
 }
 .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_value:last-child {
   padding-right: 16px;
   margin-bottom: 0;
 }
 .openerp .oe_searchview_drawer dt {
-  color: #7c7bad;
+  color: #7C7BAD;
   font-size: 13px;
   line-height: 24px;
 }
   display: inline-block;
 }
 .openerp .oe_form_invalid input, .openerp .oe_form_invalid select, .openerp .oe_form_invalid textarea {
-  background-color: #ff6666 !important;
-  border: 1px solid #dd0000 !important;
+  background-color: #F66 !important;
+  border: 1px solid #D00 !important;
 }
 .openerp .oe_view_manager_current .oe_form_editable .oe_highlight {
   color: #404040;
 }
 .openerp .oe_application .oe_form_sheetbg {
   background: url(/web/static/src/img/form_sheetbg.png);
-  border-bottom: 1px solid #dddddd;
+  border-bottom: 1px solid #ddd;
 }
 .openerp .oe_application .oe_form_sheetbg .oe_subtotal_footer label {
   font-weight: bold;
   padding: 16px 16px 48px;
 }
 .openerp .oe_form div.oe_form_configuration p, .openerp .oe_form div.oe_form_configuration ul, .openerp .oe_form div.oe_form_configuration ol {
-  color: #aaaaaa;
+  color: #aaa;
   max-width: 650px;
 }
 .openerp .oe_form div.oe_form_configuration label {
   font-weight: normal !important;
 }
 .openerp .oe_form .oe_form_box_info {
-  background: #ffee99;
-  border-bottom: 1px solid #ccbb66;
+  background: #fe9;
+  border-bottom: 1px solid #cb6;
   padding: 4px;
 }
 .openerp .oe_form .oe_form_box_info > p {
 }
 .openerp .oe_form .oe_form_box_warning {
   background: #bd362f;
-  border-bottom: 1px solid #990000;
+  border-bottom: 1px solid #900;
   padding: 4px;
 }
 .openerp .oe_form .oe_form_box_warning * {
   margin: 2px;
 }
 .openerp .oe_form td.oe_form_group_cell_label {
-  border-right: 1px solid #dddddd;
+  border-right: 1px solid #ddd;
   padding: 2px 0px;
 }
 .openerp .oe_form td.oe_form_group_cell_label label {
 }
 .openerp .oe_form .oe_form_label_help[for] span, .openerp .oe_form .oe_form_label[for] span {
   font-size: 80%;
-  color: darkgreen;
+  color: darkGreen;
   vertical-align: top;
   position: relative;
   top: -4px;
   font-weight: bold;
   font-size: 20px;
   margin: 15px 0px 10px 0px;
-  color: #7c7bad;
+  color: #7C7BAD;
 }
 .openerp .oe_horizontal_separator:empty {
   height: 5px;
 }
 .openerp .oe_vertical_separator {
-  border-left: 1px solid #666666;
+  border-left: 1px solid #666;
   padding: 0 4px 0 4px;
 }
 .openerp .oe_form_field_progressbar {
   -moz-box-sizing: border-box;
   -ms-box-sizing: border-box;
   box-sizing: border-box;
-  border: 1px solid #999999;
+  border: 1px solid #999;
   -moz-border-radius: 3px;
   -webkit-border-radius: 3px;
   border-radius: 3px;
   font-family: "Lucida Grande", Helvetica, Verdana, Arial, sans-serif;
 }
 .openerp .oe_form input[readonly], .openerp .oe_form select[readonly], .openerp .oe_form textarea[readonly], .openerp .oe_form input[disabled], .openerp .oe_form select[disabled] {
-  background: #e5e5e5 !important;
-  color: #666666;
+  background: #E5E5E5 !important;
+  color: #666;
 }
 .openerp .oe_form textarea[disabled] {
   border: none;
   color: #4c4c4c;
 }
 .openerp .oe_form textarea.oe_inline[disabled] {
-  border-left: 8px solid #eeeeee;
+  border-left: 8px solid #eee;
 }
 .openerp .oe_form .oe_form_field_url button img {
   vertical-align: top;
   display: inline-block;
 }
 .openerp .oe_form .oe_form_required input:not([disabled]):not([readonly]), .openerp .oe_form .oe_form_required select:not([disabled]):not([readonly]), .openerp .oe_form .oe_form_required textarea:not([disabled]):not([readonly]) {
-  background-color: #d2d2ff !important;
+  background-color: #D2D2FF !important;
 }
 .openerp .oe_form .oe_form_invalid input, .openerp .oe_form .oe_form_invalid select, .openerp .oe_form .oe_form_invalid textarea {
-  background-color: #ff6666 !important;
-  border: 1px solid #dd0000 !important;
+  background-color: #F66 !important;
+  border: 1px solid #D00 !important;
 }
 .openerp .oe_form .oe_input_icon {
   cursor: pointer;
   width: 100%;
   display: none;
   text-align: center;
-  color: #eeeeee;
+  color: #eee;
   background: rgba(37, 37, 37, 0.9);
   -moz-border-radius: 3px 3px 0 0;
   -webkit-border-radius: 3px 3px 0 0;
 .openerp .oe_fileupload .oe_add button.oe_attach {
   width: 24px;
   background: transparent;
-  color: #7c7bad;
+  color: #7C7BAD;
   box-shadow: none;
   border: none;
   text-shadow: none;
   cursor: pointer;
 }
 .openerp .oe_fileupload .oe_add .oe_attach_label {
-  color: #7c7bad;
+  color: #7C7BAD;
   margin-left: -3px;
 }
 .openerp .oe_fileupload .oe_attachments {
   background: white;
 }
 .openerp .oe_fileupload .oe_attachments .oe_attachment:nth-child(even) {
-  background: #f4f5fa;
+  background: #F4F5FA;
 }
 .openerp .oe_form_field_many2one {
   display: inline-block;
   background-image: linear-gradient(to bottom, #e8e8e8, #cacaca);
 }
 .openerp ul.oe_form_status_clickable li > .label {
-  color: #7c7bad;
+  color: #7C7BAD;
 }
 .openerp ul.oe_form_status_clickable li.oe_active:hover {
   background-color: #3a699f;
   background-color: #d2d2ff;
 }
 .openerp .oe_form_editable .oe_list_editable .oe_list_content td.oe_readonly {
-  background-color: #eeeeee;
+  background-color: #eee;
 }
 .openerp .oe_list_editable .oe_list_content td.oe_list_field_cell {
   padding: 4px 6px 3px;
   -moz-border-radius: 0;
   -webkit-border-radius: 0;
   border-radius: 0;
-  border: 1px solid #aaaaff;
+  border: 1px solid #aaf;
   margin: 0;
 }
 .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field input, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field textarea, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field select {
 }
 .openerp .oe_list_content > thead {
   border-bottom: 2px solid #cacaca;
-  background: #eeeeee;
+  background: #eee;
   vertical-align: top;
 }
 .openerp .oe_list_content td, .openerp .oe_list_content th {
   margin-top: 7px;
   border-width: 0 4px 4px;
   border-style: solid;
-  border-color: black transparent;
+  border-color: #000 transparent;
   visibility: hidden;
 }
 .openerp .oe_list_content th.sortup div:after {
   border-bottom: none;
   border-left: 4px solid transparent;
   border-right: 4px solid transparent;
-  border-top: 4px solid black;
+  border-top: 4px solid #000;
   visibility: visible;
   -moz-box-shadow: none;
   -webkit-box-shadow: none;
 }
 .openerp .oe_list_content > tbody > tr {
   height: 27px;
-  border-top: 1px solid #dddddd;
+  border-top: 1px solid #ddd;
 }
 .openerp .oe_list_content > tbody > tr > td.oe_list_field_cell {
   padding: 3px 6px;
 .openerp .oe_list_content > tfoot {
   border-top: 2px solid #cacaca;
   border-bottom: 1px solid #cacaca;
-  background: #eeeeee;
+  background: #eee;
   font-weight: bold;
 }
 .openerp .oe_list_content .numeric {
 .openerp .oe_list_content td.oe_list_field_handle .oe_list_handle:before {
   font: 18px "entypoRegular";
   content: "}";
-  color: #e0e0e0;
+  color: #E0E0E0;
 }
 .openerp .oe_list_content .oe_list_field_progressbar progress {
   width: 100%;
   -webkit-margin-end: 0px;
 }
 .openerp pre {
-  background-color: white;
+  background-color: #FFFFFF;
   border: none;
   padding: 10px 0 3px 0;
 }
   -moz-border-radius: 15px;
   -webkit-border-radius: 15px;
   border-radius: 15px;
-  -moz-box-shadow: 0 0 5px 5px #999999;
-  -webkit-box-shadow: 0 0 5px 5px #999999;
-  box-shadow: 0 0 5px 5px #999999;
+  -moz-box-shadow: 0 0 5px 5px #999;
+  -webkit-box-shadow: 0 0 5px 5px #999;
+  box-shadow: 0 0 5px 5px #999;
 }
 
 div.ui-widget-overlay {
@@ -3076,7 +3077,7 @@ div.ui-widget-overlay {
   background: #f0f0fa;
 }
 .ui-menu .ui-menu-item a.ui-state-hover, .ui-menu .ui-menu-item a.ui-state-active {
-  background: #7c7bad;
+  background: #7C7BAD;
 }
 
 .ui-corner-all {
@@ -3090,7 +3091,7 @@ div.ui-widget-overlay {
 }
 
 body.oe_single_form {
-  background: #eeeeee url(/web/static/src/img/form_sheetbg.png);
+  background: #eee url(/web/static/src/img/form_sheetbg.png);
   height: 100%;
 }
 body.oe_single_form .oe_single_form_logo {
@@ -3124,7 +3125,7 @@ body.oe_single_form .oe_single_form_container {
   width: 80px;
 }
 .openerp_ie .oe_form_field_boolean input {
-  background: white;
+  background: #fff;
 }
 .openerp_ie .db_option_table .oe_form_field_selection {
   width: auto;
@@ -3315,7 +3316,7 @@ body.oe_single_form .oe_single_form_container {
   max-width: 350px;
 }
 .tooltip .tooltip-inner .oe_tooltip_string {
-  color: #ffdd55;
+  color: #FD5;
   font-weight: bold;
   font-size: 13px;
 }
@@ -3339,7 +3340,7 @@ body.oe_single_form .oe_single_form_container {
   color: white;
 }
 .tooltip .tooltip-inner .oe_tooltip_close:hover {
-  color: #999999;
+  color: #999;
   cursor: pointer;
 }
 .tooltip .tooltip-inner .oe_tooltip_message {
@@ -3414,7 +3415,7 @@ div.tour-backdrop {
   bottom: 0;
   left: 0;
   z-index: 1100;
-  background-color: black;
+  background-color: #000;
   opacity: 0.8;
 }
 
index a8efd0f..5aeaccf 100644 (file)
@@ -267,7 +267,7 @@ $sheet-padding: 16px
         font-size: inherit
     // }}}
     // Button style {{{
-    a.button:link, a.button:visited, button, .oe_button, input[type='submit']
+    a.button:link, a.button:visited, .oe_button, input[type='submit']
         display: inline-block
         border: 1px solid rgba(0,0,0,0.4)
         color: #4c4c4c
@@ -282,22 +282,22 @@ $sheet-padding: 16px
         -webkit-font-smoothing: antialiased
         outline: none
 
-    a.button:hover, button:hover,.oe_button:hover, input[type='submit']:hover
+    a.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
+    a.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
+    a.button:active, a.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)
 
-    a.button.disabled, button:disabled, .oe_button:disabled, input[type='submit']:disabled
+    a.button.disabled, .oe_button:disabled, input[type='submit']:disabled
         background: #efefef !important
         border: 1px solid #d1d1d1 !important
         @include box-shadow(none !important)
@@ -899,8 +899,11 @@ $sheet-padding: 16px
     .oe_application
         width: 100%
         height: 100%
-        a
-            color: $link-color
+        .oe-view-manager-body
+            a
+                color: $link-color
+            .oe-view-manager-view-kanban:not(:empty)
+                height: 100%
         > div
             position: relative
             height: 100%
@@ -931,6 +934,52 @@ $sheet-padding: 16px
             font-weight: bold
     // }}}
     // ViewManager common {{{
+    .oe-view-manager-header
+        height: 90px
+        overflow: hidden
+        border-bottom: 1px solid black
+        display: none
+        .row
+            height: 45px
+        .oe-view-title
+            float: left
+            font-size: 18px
+            font-weight: bold
+            margin: 0
+        .oe-header-title
+            padding-left: 0
+        .oe-view-manager-search-view
+            float: right
+            padding-top: 5px
+        .oe-view-manager-switch
+            float: right
+            .oe-vm-switch-kanban:before
+                content: "\f009"
+            .oe-vm-switch-list:before
+                content: "\f0c9"
+            .oe-vm-switch-form:before
+                content: "\f044"
+            .oe-vm-switch-graph:before
+                content: "\f080"
+            .oe-vm-switch-calendar:before
+                content: "\f073"
+            .oe-vm-switch-gantt:before
+                content: "\f0ae"
+        .oe-view-manager-buttons
+            float: left
+            > div
+                display: none
+
+    .oe_application 
+        > div    
+            > div
+                > .oe-view-manager-body
+                    position: absolute
+                    top: 90px
+                    bottom: 0
+                    left: 0
+                    right: 0
+                    overflow: auto
     .oe_view_manager
         display: table
         height: inherit
@@ -1076,18 +1125,18 @@ $sheet-padding: 16px
         display: none
     // }}}
     // ViewManager application {{{
-    .oe_view_manager_current
-        height: 100%
-        > .oe_view_manager_header
-            border-bottom: 1px solid #cacaca
-            @include vertical-gradient(#fcfcfc, #dedede)
-            @include box-shadow((0 1px 0 rgba(255,255,255,0.4), 0 0 9px rgba(0,0,0,0.1)))
-            .oe_header_row
-                td
-                    padding: 8px
-            .oe_header_row:first-child
-                td
-                    padding-top: 8px
+    // .oe_view_manager_current
+    //     height: 100%
+    //     > .oe_view_manager_header
+    //         border-bottom: 1px solid #cacaca
+    //         @include vertical-gradient(#fcfcfc, #dedede)
+    //         @include box-shadow((0 1px 0 rgba(255,255,255,0.4), 0 0 9px rgba(0,0,0,0.1)))
+    //         .oe_header_row
+    //             td
+    //                 padding: 8px
+    //         .oe_header_row:first-child
+    //             td
+    //                 padding-top: 8px
     // }}}
     // ViewManager inline {{{
     .oe_view_manager_inline, .oe_view_manager_inlineview
@@ -1111,14 +1160,10 @@ $sheet-padding: 16px
     .oe_searchview
         cursor: text
         position: relative
-        float: right
         padding: 1px 0
-        line-height: 18px
         min-width: 400px
-        border: 1px solid #ababab
-        background: white
+        width: 400px
         @include radius(13px)
-        @include box-shadow(0 1px 2px rgba(0,0,0,0.2) inset)
         input, textarea
             padding: 3px
             height: 14px
@@ -1139,54 +1184,39 @@ $sheet-padding: 16px
         .oe_searchview_clear
             cursor: pointer
             position: absolute
-            top: 0
+            top: 3px
             right: 18px
             width: 15px
             height: 24px
-            background: url(../img/search_reset.gif) center center no-repeat
         .oe_searchview_unfold_drawer
             position: absolute
             top: 0
             right: 0
-            height: 24px
-            padding: 0 7px 0 4px
             color: #ccc
             cursor: pointer
             &:hover
                 color: #999
             &:before
                 position: absolute
-                top: 10px
-                right: 7px
+                top: 7px
+                right: 18px
                 width: 0
-                height: 0
-                display: inline-block
-                content: ""
-                vertical-align: top
-                border-top: 5px solid #4C4C4C
-                border-left: 5px solid transparent
-                border-right: 5px solid transparent
-                @include opacity()
 
         .oe_searchview_search
-            @include text-to-icon("r", #a3a3a3)
-            @include box-shadow(none)
-            @include radius(0)
+            cursor: pointer
             position: absolute
-            left: 3px
-            top: 1px
-            padding: 0
-            border: none
-            background: transparent
+            left: 6px
+            top: 8px
 
         .oe_searchview_facets
             min-height: 22px
-            margin: 0 35px 0 15px
+            margin: 2px 35px 0 20px
             *
                 vertical-align: top
                 display: inline-block
-                line-height: 17px
+                font-size: 100%
             .oe_searchview_facet
+                height: 20px
                 margin: 1px 0
                 font-size: 11px
                 &:focus
@@ -1204,12 +1234,13 @@ $sheet-padding: 16px
                 padding: 0
                 -webkit-font-smoothing: auto
                 // spacing for opera, FF
+                span
+                    height: 18px
                 &:focus
                     border-color: $tag-border-selected
                     @include box-shadow(0 0 3px 1px $tag-border-selected)
                 .oe_facet_values
                     background: $tag-bg-light
-                    @include radius(0 3px 3px 0)
                 .oe_facet_category, .oe_facet_value
                     padding: 0 4px
                 .oe_facet_category
@@ -1218,8 +1249,6 @@ $sheet-padding: 16px
                 .oe_facet_category.oe_i
                     font-size: 16px
                 .oe_facet_value
-                    border-left: 1px solid $tag-border
-                    text-shadow: 0 1px 1px white
                     color: #4C4C4C
                     &:last-child
                         padding-right: 16px
index f14b8c0..e28b118 100644 (file)
@@ -330,7 +330,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
             }
         },
         // search button
-        'click button.oe_searchview_search': function (e) {
+        'click i.oe_searchview_search': function (e) {
             e.stopImmediatePropagation();
             this.do_search();
         },
@@ -450,6 +450,10 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
         this.drawer = drawer;
     },
 
+    toggle_visibility: function (is_visible) {
+        this.$el.toggle(is_visible);
+    },
+
     show: function () {
         this.$el.show();
     },
index 2484363..ac8d146 100644 (file)
@@ -3,6 +3,7 @@
  *---------------------------------------------------------*/
 
 (function() {
+"use strict";
 
 var instance = openerp;
 openerp.web.views = {};
@@ -14,17 +15,14 @@ instance.web.ActionManager = instance.web.Widget.extend({
         this._super(parent);
         this.inner_action = null;
         this.inner_widget = null;
+        this.webclient = parent;
         this.dialog = null;
         this.dialog_widget = null;
-        this.breadcrumbs = [];
+        this.view_managers = [];
         this.on('history_back', this, function() {
             return this.history_back();
         });
     },
-    start: function() {
-        this._super.apply(this, arguments);
-        this.$el.on('click', 'a.oe_breadcrumb_item', this.on_breadcrumb_clicked);
-    },
     dialog_stop: function (reason) {
         if (this.dialog) {
             this.dialog.destroy(reason);
@@ -47,185 +45,132 @@ instance.web.ActionManager = instance.web.Widget.extend({
      * @param {String|Array} [item.title] title(s) of the view(s) to be displayed in the breadcrumb
      * @param {Function} [item.get_title] should return the title(s) of the view(s) to be displayed in the breadcrumb
      */
-    push_breadcrumb: function(item) {
-        var last = this.breadcrumbs.slice(-1)[0];
-        if (last) {
-            last.hide();
-        }
-        item = _.extend({
-            show: function(index) {
-                this.widget.$el.show();
-            },
-            hide: function() {
-                this.widget.$el.hide();
-            },
-            destroy: function() {
-                this.widget.destroy();
-            },
-            get_title: function() {
-                return this.title || this.widget.get('title');
-            }
-        }, item);
-        item.id = _.uniqueId('breadcrumb_');
-        this.breadcrumbs.push(item);
-    },
-    history_back: function() {
-        var last = this.breadcrumbs.slice(-1)[0];
-        if (!last) {
-            return false;
-        }
-        var title = last.get_title();
-        if (_.isArray(title) && title.length > 1) {
-            return this.select_breadcrumb(this.breadcrumbs.length - 1, title.length - 2);
-        } else if (this.breadcrumbs.length === 1) {
-            // Only one single titled item in breadcrumb, most of the time you want to trigger back to home
-            return false;
-        } else {
-            var prev = this.breadcrumbs[this.breadcrumbs.length - 2];
-            title = prev.get_title();
-            return this.select_breadcrumb(this.breadcrumbs.length - 2, _.isArray(title) ? title.length - 1 : undefined);
-        }
-    },
-    on_breadcrumb_clicked: function(ev) {
-        var $e = $(ev.target);
-        var id = $e.data('id');
-        var index;
-        for (var i = this.breadcrumbs.length - 1; i >= 0; i--) {
-            if (this.breadcrumbs[i].id == id) {
-                index = i;
-                break;
-            }
-        }
-        var subindex = $e.parent().find('a.oe_breadcrumb_item[data-id=' + $e.data('id') + ']').index($e);
-        this.select_breadcrumb(index, subindex);
-    },
-    select_breadcrumb: function(index, subindex) {
-        var next_item = this.breadcrumbs[index + 1];
-        if (next_item && next_item.on_reverse_breadcrumb) {
-            next_item.on_reverse_breadcrumb(this.breadcrumbs[index].widget);
+    push_view_manager: function(widget, action, clear_breadcrumbs) {
+        var self = this,
+            old_widget = this.inner_widget;
+
+        if (clear_breadcrumbs) {
+            var to_destroy = this.view_managers;
+            this.view_managers = [];
         }
-        for (var i = this.breadcrumbs.length - 1; i >= 0; i--) {
-            if (i > index) {
-                if (this.remove_breadcrumb(i) === false) {
-                    return false;
-                }
+        this.view_managers.push(widget);
+        this.inner_action = action;
+        this.inner_widget = widget;
+        return $.when(this.inner_widget.appendTo(this.$el)).done(function () {
+            widget.$header && widget.$header.show();
+            old_widget && old_widget.$el.hide();
+            if (clear_breadcrumbs) {
+                self.clear_view_managers(to_destroy)
             }
-        }
-        var item = this.breadcrumbs[index];
-        item.show(subindex);
-        this.inner_widget = item.widget;
-        this.inner_action = item.action;
-        return true;
+        });
     },
-    clear_breadcrumbs: function() {
-        for (var i = this.breadcrumbs.length - 1; i >= 0; i--) {
-            if (this.remove_breadcrumb(0) === false) {
-                break;
-            }
-        }
+    get_breadcrumbs: function () {
+        return _.flatten(_.map(this.view_managers, function (vm) {
+            return vm.view_stack.map(function (view, index) { 
+                return {
+                    title: view.controller.get('title') || vm.title,
+                    index: index,
+                    view_manager: vm,
+                }; 
+            });
+        }), true);
     },
-    remove_breadcrumb: function(index) {
-        var item = this.breadcrumbs.splice(index, 1)[0];
-        if (item) {
-            var dups = _.filter(this.breadcrumbs, function(it) {
-                return item.widget === it.widget;
+    history_back: function() {
+        // var last = this.breadcrumbs.slice(-1)[0];
+        // if (!last) {
+        //     return false;
+        // }
+        // var title = last.get_title();
+        // if (_.isArray(title) && title.length > 1) {
+        //     return this.select_breadcrumb(this.breadcrumbs.length - 1, title.length - 2);
+        // } else if (this.breadcrumbs.length === 1) {
+        //     // Only one single titled item in breadcrumb, most of the time you want to trigger back to home
+        //     return false;
+        // } else {
+        //     var prev = this.breadcrumbs[this.breadcrumbs.length - 2];
+        //     title = prev.get_title();
+        //     return this.select_breadcrumb(this.breadcrumbs.length - 2, _.isArray(title) ? title.length - 1 : undefined);
+        // }
+    },
+    select_view_manager: function(view_manager, index) {
+        var self = this;
+        var vm_index = this.view_managers.indexOf(view_manager);
+        view_manager.select_view(index).done(function () {
+            _.each(self.view_managers.splice(vm_index + 1), function (vm) {
+                vm.destroy();
             });
-            if (!dups.length) {
-                if (this.getParent().has_uncommitted_changes()) {
-                    this.inner_widget = item.widget;
-                    this.inner_action = item.action;
-                    this.breadcrumbs.splice(index, 0, item);
-                    return false;
-                } else {
-                    item.destroy();
-                }
-            }
-        }
-        var last_widget = this.breadcrumbs.slice(-1)[0];
-        if (last_widget) {
-            this.inner_widget = last_widget.widget;
-            this.inner_action = last_widget.action;
+            self.inner_widget = _.last(self.view_managers);
+            self.inner_widget.display_breadcrumbs();
+            self.inner_widget.$el.show();
+        });
+    },
+    clear_view_managers: function(vms) {
+        _.each(vms || this.view_managers, function (vm) {
+            vm.destroy();
+        });
+        if (!vms) {
+            this.view_managers = [];
+            this.inner_widget = null;            
         }
     },
     add_breadcrumb_url: function (url, label) {
         // Add a pseudo breadcrumb that will redirect to an url
-        this.push_breadcrumb({
-            show: function() {
-                instance.web.redirect(url);
-            },
-            hide: function() {},
-            destroy: function() {},
-            get_title: function() {
-                return label;
-            }
-        });
+        // this.push_breadcrumb({
+        //     show: function() {
+        //         instance.web.redirect(url);
+        //     },
+        //     hide: function() {},
+        //     destroy: function() {},
+        //     get_title: function() {
+        //         return label;
+        //     }
+        // });
     },
-    get_title: function() {
-        var titles = [];
-        for (var i = 0; i < this.breadcrumbs.length; i += 1) {
-            var item = this.breadcrumbs[i];
-            var tit = item.get_title();
-            if (item.hide_breadcrumb) {
-                continue;
+    do_push_state: function(state) {
+        if (!this.webclient || !this.webclient.do_push_state) {
+            return;
+        }
+        state = state || {};
+        if (this.inner_action) {
+            if (this.inner_action._push_me === false) {
+                // this action has been explicitly marked as not pushable
+                return;
             }
-            if (!_.isArray(tit)) {
-                tit = [tit];
+            state.title = this.inner_action.name;
+            if(this.inner_action.type == 'ir.actions.act_window') {
+                state.model = this.inner_action.res_model;
             }
-            for (var j = 0; j < tit.length; j += 1) {
-                var label = _.escape(tit[j]);
-                if (i === this.breadcrumbs.length - 1 && j === tit.length - 1) {
-                    titles.push(_.str.sprintf('<span class="oe_breadcrumb_item">%s</span>', label));
-                } else {
-                    titles.push(_.str.sprintf('<a href="#" class="oe_breadcrumb_item" data-id="%s">%s</a>', item.id, label));
-                }
+            if (this.inner_action.menu_id) {
+                state.menu_id = this.inner_action.menu_id;
             }
-        }
-        return titles.join(' <span class="oe_fade">/</span> ');
-    },
-    do_push_state: function(state) {
-        state = state || {};
-        if (this.getParent() && this.getParent().do_push_state) {
-            if (this.inner_action) {
-                if (this.inner_action._push_me === false) {
-                    // this action has been explicitly marked as not pushable
-                    return;
-                }
-                state['title'] = this.inner_action.name;
-                if(this.inner_action.type == 'ir.actions.act_window') {
-                    state['model'] = this.inner_action.res_model;
-                }
-                if (this.inner_action.menu_id) {
-                    state['menu_id'] = this.inner_action.menu_id;
-                }
-                if (this.inner_action.id) {
-                    state['action'] = this.inner_action.id;
-                } else if (this.inner_action.type == 'ir.actions.client') {
-                    state['action'] = this.inner_action.tag;
-                    var params = {};
-                    _.each(this.inner_action.params, function(v, k) {
-                        if(_.isString(v) || _.isNumber(v)) {
-                            params[k] = v;
-                        }
-                    });
-                    state = _.extend(params || {}, state);
-                }
-                if (this.inner_action.context) {
-                    var active_id = this.inner_action.context.active_id;
-                    if (active_id) {
-                        state["active_id"] = active_id;
-                    }
-                    var active_ids = this.inner_action.context.active_ids;
-                    if (active_ids && !(active_ids.length === 1 && active_ids[0] === active_id)) {
-                        // We don't push active_ids if it's a single element array containing the active_id
-                        // This makes the url shorter in most cases.
-                        state["active_ids"] = this.inner_action.context.active_ids.join(',');
+            if (this.inner_action.id) {
+                state.action = this.inner_action.id;
+            } else if (this.inner_action.type == 'ir.actions.client') {
+                state.action = this.inner_action.tag;
+                var params = {};
+                _.each(this.inner_action.params, function(v, k) {
+                    if(_.isString(v) || _.isNumber(v)) {
+                        params[k] = v;
                     }
-                }
+                });
+                state = _.extend(params || {}, state);
             }
-            if(!this.dialog) {
-                this.getParent().do_push_state(state);
+            if (this.inner_action.context) {
+                var active_id = this.inner_action.context.active_id;
+                if (active_id) {
+                    state.active_id = active_id;
+                }
+                var active_ids = this.inner_action.context.active_ids;
+                if (active_ids && !(active_ids.length === 1 && active_ids[0] === active_id)) {
+                    // We don't push active_ids if it's a single element array containing the active_id
+                    // This makes the url shorter in most cases.
+                    state.active_ids = this.inner_action.context.active_ids.join(',');
+                }
             }
         }
+        if(!this.dialog) {
+            this.webclient.do_push_state(state);
+        }
     },
     do_load_state: function(state, warm) {
         var self = this,
@@ -390,7 +335,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
     },
     null_action: function() {
         this.dialog_stop();
-        this.clear_breadcrumbs();
+        this.clear_view_managers();
     },
     /**
      *
@@ -403,14 +348,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
      * @return {*}
      */
     ir_actions_common: function(executor, options) {
-        if (this.inner_widget && executor.action.target !== 'new') {
-            if (this.getParent().has_uncommitted_changes()) {
-                return $.Deferred().reject();
-            } else if (options.clear_breadcrumbs) {
-                this.clear_breadcrumbs();
-            }
-        }
-        var widget = executor.widget();
+        var widget;
         if (executor.action.target === 'new') {
             var pre_dialog = (this.dialog && !this.dialog.isDestroyed()) ? this.dialog : null;
             if (pre_dialog){
@@ -442,6 +380,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
                 }
             };
             this.dialog.on("closing", null, this.dialog.on_close);
+            widget = executor.widget();
             if (widget instanceof instance.web.ViewManager) {
                 _.extend(widget.flags, {
                     $buttons: this.dialog.$buttons,
@@ -453,30 +392,33 @@ instance.web.ActionManager = instance.web.Widget.extend({
             var initialized = this.dialog_widget.appendTo(this.dialog.$el);
             this.dialog.open();
             return initialized;
-        } else  {
-            // explicitly passing a closing action to dialog_stop() prevents
-            // it from reloading the original form view - we're opening a
-            // completely new action anyway
-            this.dialog_stop(executor.action);
-            this.inner_action = executor.action;
-            this.inner_widget = widget;
-            executor.post_process(widget);
-            return this.inner_widget.appendTo(this.$el);
         }
+        if (this.inner_widget && this.webclient.has_uncommitted_changes()) {
+            return $.Deferred().reject();
+        }
+        widget = executor.widget();
+        this.dialog_stop(executor.action);
+        if (options.clear_breadcrumbs) {
+            // this.clear_view_managers();
+        }    
+        return this.push_view_manager(widget, executor.action, options.clear_breadcrumbs);
     },
     ir_actions_act_window: function (action, options) {
         var self = this;
 
         return this.ir_actions_common({
-            widget: function () { return new instance.web.ViewManagerAction(self, action); },
+            widget: function () { 
+                return new instance.web.ViewManagerAction(self, action); 
+            },
             action: action,
             klass: 'oe_act_window',
-            post_process: function (widget) {
-                widget.add_breadcrumb({
-                    on_reverse_breadcrumb: options.on_reverse_breadcrumb,
-                    hide_breadcrumb: options.hide_breadcrumb,
-                });
-            },
+            // post_process: function (widget) {
+            //     self.push_breadcrumb({
+            //         widget: widget,
+            //         on_reverse_breadcrumb: options.on_reverse_breadcrumb,
+            //         hide_breadcrumb: options.hide_breadcrumb,
+            //     });
+            // },
         }, options);
     },
     ir_actions_client: function (action, options) {
@@ -498,17 +440,17 @@ instance.web.ActionManager = instance.web.Widget.extend({
             widget: function () { return new ClientWidget(self, action); },
             action: action,
             klass: 'oe_act_client',
-            post_process: function(widget) {
-                self.push_breadcrumb({
-                    widget: widget,
-                    title: action.name,
-                    on_reverse_breadcrumb: options.on_reverse_breadcrumb,
-                    hide_breadcrumb: options.hide_breadcrumb,
-                });
-                if (action.tag !== 'reload') {
-                    self.do_push_state({});
-                }
-            }
+            // post_process: function(widget) {
+            //     self.push_breadcrumb({
+            //         widget: widget,
+            //         title: action.name,
+            //         on_reverse_breadcrumb: options.on_reverse_breadcrumb,
+            //         hide_breadcrumb: options.hide_breadcrumb,
+            //     });
+            //     if (action.tag !== 'reload') {
+            //         self.do_push_state({});
+            //     }
+            // }
         }, options);
     },
     ir_actions_act_window_close: function (action, options) {
@@ -578,247 +520,186 @@ instance.web.ActionManager = instance.web.Widget.extend({
 
 instance.web.ViewManager =  instance.web.Widget.extend({
     template: "ViewManager",
+    /**
+     * @param {Object} [dataset] null object (... historical reasons)
+     * @param {Array} [views] List of [view_id, view_type]
+     * @param {Object} [flags] various boolean describing UI state
+     */
     init: function(parent, dataset, views, flags) {
+        var self = this;
         this._super(parent);
-        this.url_states = {};
-        this.model = dataset ? dataset.model : undefined;
+
+        this.flags = flags;
         this.dataset = dataset;
-        this.searchview = null;
-        this.active_view = null;
-        this.views_src = _.map(views, function(x) {
-            if (x instanceof Array) {
-                var view_type = x[1];
-                var View = instance.web.views.get_object(view_type, true);
-                var view_label = View ? View.prototype.display_name : (void 'nope');
-                return {
-                    view_id: x[0],
-                    view_type: view_type,
-                    label: view_label,
-                    button_label: View ? _.str.sprintf(_t('%(view_type)s view'), {'view_type': (view_label || view_type)}) : (void 'nope'),
-                };
-            } else {
-                return x;
-            }
-        });
-        this.ActionManager = parent;
+        this.view_order = [];
+        this.url_states = {};
         this.views = {};
-        this.flags = flags || {};
+        this.view_stack = []; // used for breadcrumbs
+        this.active_view = null;
+        this.searchview = null;
+        this.active_search = null;
         this.registry = instance.web.views;
-        this.views_history = [];
-        this.view_completely_inited = $.Deferred();
+        this.title = this.action && this.action.name;
+
+        _.each(views, function (view) {
+            var view_type = view[1] || view.view_type,
+                View = instance.web.views.get_object(view_type, true),
+                view_label = View ? View.prototype.display_name : (void 'nope');
+            self.view_order.push(view_type);
+            self.views[view_type] = {
+                controller: null,
+                options: view.options || {},
+                view_id: view[0] || view.view_id,
+                type: view_type,
+                label: view_label,
+                embedded_view: view.embedded_view,
+                title: self.action && self.action.name,
+                button_label: View ? _.str.sprintf(_t('%(view_type)s view'), {'view_type': (view_label || view_type)}) : (void 'nope'),
+            };
+        });
     },
     /**
      * @returns {jQuery.Deferred} initial view loading promise
      */
     start: function() {
-        this._super();
         var self = this;
-        this.$el.find('.oe_view_manager_switch a').click(function() {
-            self.switch_mode($(this).data('view-type'));
-        }).tooltip();
-        var views_ids = {};
-        _.each(this.views_src, function(view) {
-            self.views[view.view_type] = $.extend({}, view, {
-                deferred : $.Deferred(),
-                controller : null,
-                options : _.extend({
-                    $buttons : self.$el.find('.oe_view_manager_buttons'),
-                    $sidebar : self.flags.sidebar ? self.$el.find('.oe_view_manager_sidebar') : undefined,
-                    $pager : self.$el.find('.oe_view_manager_pager'),
-                    action : self.action,
-                    action_views_ids : views_ids
-                }, self.flags, self.flags[view.view_type] || {}, view.options || {})
-            });
+        var default_view = this.flags.default_view || this.view_order[0],
+            default_options = this.flags[default_view] && this.flags[default_view].options;
 
-            views_ids[view.view_type] = view.view_id;
-        });
-        if (this.flags.views_switcher === false) {
-            this.$el.find('.oe_view_manager_switch').hide();
-        }
-        // If no default view defined, switch to the first one in sequence
-        var default_view = this.flags.default_view || this.views_src[0].view_type;
+        this._super();
+        var $sidebar = this.flags.sidebar ? this.$('.oe_view_manager_sidebar') : undefined,
+            $pager = this.$('.oe_view_manager_pager');
 
-        return this.switch_mode(default_view, null, this.flags[default_view] && this.flags[default_view].options);
+        this.$breadcrumbs = this.$('.oe-view-title');
+        this.$switch_buttons = this.$('.oe-view-manager-switch a');
+        this.$header = this.$('.oe-view-manager-header');
 
+        self.$switch_buttons.click(function () {
+            self.switch_mode($(this).data('view-type'));
+        });
+        var views_ids = {};
+        _.each(this.views, function (view) {
+            views_ids[view.type] = view.view_id;
+            view.options = _.extend({
+                $buttons: self.$('.oe-' + view.type + '-buttons'),
+                $sidebar : $sidebar,
+                $pager : $pager,
+                action : self.action,
+                action_views_ids : views_ids,
+            }, self.flags, self.flags[view.type], view.options);
+        });
 
+        var search_view_loaded = this.flags.search_view ? this.setup_search_view() : $.when(),
+            main_view_loaded = this.switch_mode(default_view, null, default_options);
+            
+        return $.when(main_view_loaded, search_view_loaded);   
     },
+
     switch_mode: function(view_type, no_store, view_options) {
-        var self = this;
-        var view = this.views[view_type];
-        var view_promise;
-        var form = this.views['form'];
-        if (!view || (form && form.controller && !form.controller.can_be_discarded())) {
-            return $.Deferred().reject();
-        }
-        if (!no_store) {
-            this.views_history.push(view_type);
+        var self = this,
+            view = this.views[view_type];
+
+        if (view_type !== 'form') {
+            this.view_stack = [];
         }
-        this.active_view = view_type;
 
-        if (!view.controller) {
-            view_promise = this.do_create_view(view_type);
-        } else if (this.searchview
-                && self.flags.auto_search
-                && view.controller.searchable !== false) {
-            this.searchview.ready.done(this.searchview.do_search);
+        this.view_stack.push(view);
+        this.active_view = view;
+        if (!view.created) {
+            view.created = this.create_view.bind(this)(view);
         }
+        this.active_search = $.Deferred();
 
-        if (this.searchview) {
-            this.searchview[(view.controller.searchable === false || this.searchview.options.hidden) ? 'hide' : 'show']();
+        if (this.searchview
+                && this.flags.auto_search
+                && view.controller.searchable !== false) {
+            $.when(this.searchview.ready, view.created).done(this.searchview.do_search);
+        } else {
+            this.active_search.resolve();
         }
 
-        this.$el.find('.oe_view_manager_switch a').parent().removeClass('active');
-        this.$el
-            .find('.oe_view_manager_switch a').filter('[data-view-type="' + view_type + '"]')
-            .parent().addClass('active');
-        this.$el.attr("data-view-type", view_type);
-        return $.when(view_promise).done(function () {
-            _.each(_.keys(self.views), function(view_name) {
-                var controller = self.views[view_name].controller;
-                if (controller) {
-                    var container = self.$el.find("> div > div > .oe_view_manager_body > .oe_view_manager_view_" + view_name);
-                    if (view_name === view_type) {
-                        container.show();
-                        controller.do_show(view_options || {});
-                    } else {
-                        container.hide();
-                        controller.do_hide();
-                    }
+        self.update_header();
+        return $.when(view.created, this.active_search).done(function () {
+            self.active_view = view;
+            self._display_view(view.type, view_options);
+            self.trigger('switch_mode', view_type, no_store, view_options);
+        });
+    },
+    update_header: function () {
+        this.$switch_buttons.removeClass('active');
+        this.$('.oe-vm-switch-' + this.active_view.type).addClass('active');
+    },
+    _display_view: function (view_type, view_options) {
+        var self = this;
+        this.active_view.$container.show();
+        $.when(this.active_view.controller.do_show(view_options)).done(function () { 
+            _.each(self.views, function (view) {
+                if (view.type !== view_type) {
+                    view.controller && view.controller.do_hide();
+                    view.$container && view.$container.hide();
+                    view.options.$buttons && view.options.$buttons.hide();
                 }
             });
-            self.trigger('switch_mode', view_type, no_store, view_options);
+            self.active_view.options.$buttons && self.active_view.options.$buttons.show();
+            if (self.searchview) {
+                var is_hidden = self.active_view.controller.searchable === false || self.searchview.options.hidden;
+                self.searchview.toggle_visibility(!is_hidden);
+            }
+            self.display_breadcrumbs();
         });
     },
-    do_create_view: function(view_type) {
-        // Lazy loading of views
+    display_breadcrumbs: function () {
         var self = this;
-        var view = this.views[view_type];
-        var viewclass = this.registry.get_object(view_type);
-        var options = _.clone(view.options);
-        if (view_type === "form" && this.action && (this.action.target == 'new' || this.action.target == 'inline')) {
+        if (!this.action_manager) return;
+        var breadcrumbs = this.action_manager.get_breadcrumbs();
+        var $breadcrumbs = _.map(_.initial(breadcrumbs), function (bc) {
+            var $link = $('<a>').text(bc.title);
+            $link.click(function () {
+                self.action_manager.select_view_manager(bc.view_manager, bc.index);
+            });
+            return $('<li>').append($link);
+        });
+        $breadcrumbs.push($('<li>').addClass('active').text(_.last(breadcrumbs).title));
+        this.$breadcrumbs
+            .empty()
+            .append($breadcrumbs);
+    },
+    create_view: function(view) {
+        var self = this,
+            View = this.registry.get_object(view.type),
+            options = _.clone(view.options);
+
+        if (view.type === "form" && this.action && (this.action.target === 'new' || this.action.target === 'inline')) {
             options.initial_mode = 'edit';
         }
-        var controller = new viewclass(this, this.dataset, view.view_id, options);
+        var controller = new View(this, this.dataset, view.view_id, options),
+            $container = this.$(".oe-view-manager-view-" + view.type + ":first");
 
-        controller.on('history_back', this, function() {
-            var am = self.getParent();
-            if (am && am.trigger) {
-                return am.trigger('history_back');
-            }
-        });
-
-        controller.on("change:title", this, function() {
-            if (self.active_view === view_type) {
-                self.set_title(controller.get('title'));
-            }
-        });
+        $container.hide();
+        view.controller = controller;
 
         if (view.embedded_view) {
             controller.set_embedded_view(view.embedded_view);
         }
-        controller.on('switch_mode', self, this.switch_mode);
-        controller.on('previous_view', self, this.prev_view);
+        controller.on('switch_mode', this, this.switch_mode.bind(this));
 
-        var container = this.$el.find("> div > div > .oe_view_manager_body > .oe_view_manager_view_" + view_type);
-        var view_promise = controller.appendTo(container);
-        this.views[view_type].controller = controller;
-        return $.when(view_promise).done(function() {
-            self.views[view_type].deferred.resolve(view_type);
-            if (self.searchview
-                    && self.flags.auto_search
-                    && view.controller.searchable !== false) {
-                self.searchview.ready.done(self.searchview.do_search);
-            } else {
-                self.view_completely_inited.resolve();
-            }
-            self.trigger("controller_inited",view_type,controller);
-        });
-    },
+        view.$container = $container;
 
-    /**
-     * @returns {Number|Boolean} the view id of the given type, false if not found
-     */
-    get_view_id: function(view_type) {
-        return this.views[view_type] && this.views[view_type].view_id || false;
-    },
-    set_title: function(title) {
-        this.$el.find('.oe_view_title_text:first').text(title);
-    },
-    add_breadcrumb: function(options) {
-        options = options || {};
-        var self = this;
-        var views = [this.active_view || this.views_src[0].view_type];
-        this.on('switch_mode', self, function(mode) {
-            var last = views.slice(-1)[0];
-            if (mode !== last) {
-                if (mode !== 'form') {
-                    views.length = 0;
-                }
-                views.push(mode);
-            }
-            instance.web.bus.trigger('view_switch_mode', self, mode);
+        var view_loaded = $.Deferred();
+        view.controller.on('view_loaded', this, function () {
+            view_loaded.resolve();
         });
-        var item = _.extend({
-            widget: this,
-            action: this.action,
-            show: function(index) {
-                var view_to_select = views[index];
-                var state = self.url_states[view_to_select];
-                self.do_push_state(state || {});
-                $.when(self.switch_mode(view_to_select)).done(function() {
-                    self.$el.show();
-                });
-            },
-            get_title: function() {
-                var id;
-                var currentIndex;
-                _.each(self.getParent().breadcrumbs, function(bc, i) {
-                    if (bc.widget === self) {
-                        currentIndex = i;
-                    }
-                });
-                var next = self.getParent().breadcrumbs.slice(currentIndex + 1)[0];
-                var titles = _.map(views, function(v) {
-                    var controller = self.views[v].controller;
-                    if (v === 'form') {
-                        id = controller.datarecord.id;
-                    }
-                    return controller.get('title');
+
+        return $.when(controller.appendTo($container), view_loaded)
+                .done(function () { 
+                    self.trigger("controller_inited", view.type, controller);
                 });
-                if (next && next.action && next.action.res_id && self.dataset &&
-                    self.active_view === 'form' && self.dataset.model === next.action.res_model && id === next.action.res_id) {
-                    // If the current active view is a formview and the next item in the breadcrumbs
-                    // is an action on same object (model / res_id), then we omit the current formview's title
-                    titles.pop();
-                }
-                return titles;
-            }
-        }, options);
-        this.getParent().push_breadcrumb(item);
     },
-    /**
-     * Returns to the view preceding the caller view in this manager's
-     * navigation history (the navigation history is appended to via
-     * switch_mode)
-     *
-     * @param {Object} [options]
-     * @param {Boolean} [options.created=false] resource was created
-     * @param {String} [options.default=null] view to switch to if no previous view
-     * @returns {$.Deferred} switching end signal
-     */
-    prev_view: function (options) {
-        options = options || {};
-        var current_view = this.views_history.pop();
-        var previous_view = this.views_history[this.views_history.length - 1] || options['default'];
-        if (options.created && current_view === 'form' && previous_view === 'list') {
-            // APR special case: "If creation mode from list (and only from a list),
-            // after saving, go to page view (don't come back in list)"
-            return this.switch_mode('form');
-        } else if (options.created && !previous_view && this.action && this.action.flags.default_view === 'form') {
-            // APR special case: "If creation from dashboard, we have no previous view
-            return this.switch_mode('form');
-        }
-        return this.switch_mode(previous_view, true);
+
+    select_view: function (index) {
+        var view_type = this.view_stack[index].type;
+        this.view_stack.splice(index);
+        return this.switch_mode(view_type);
     },
     /**
      * Sets up the current viewmanager's search view.
@@ -826,25 +707,37 @@ instance.web.ViewManager =  instance.web.Widget.extend({
      * @param {Number|false} view_id the view to use or false for a default one
      * @returns {jQuery.Deferred} search view startup deferred
      */
-    setup_search_view: function(view_id, search_defaults) {
-        var self = this;
+    setup_search_view: function() {
         if (this.searchview) {
             this.searchview.destroy();
         }
 
+        var view_id = (this.action && this.action.search_view_id && this.action.search_view_id[0]) || false;
+        var search_defaults = {};
+
+        var context = this.action ? this.action.context : [];
+        _.each(context, function (value, key) {
+            var match = /^search_default_(.*)$/.exec(key);
+            if (match) {
+                search_defaults[match[1]] = value;
+            }
+        });
+
+
         var options = {
             hidden: this.flags.search_view === false,
             disable_custom_filters: this.flags.search_disable_custom_filters,
         };
-        this.searchview = new instance.web.SearchView(this, this.dataset, view_id, search_defaults, options);
+        var SearchView = instance.web.SearchView;
+        this.searchview = new SearchView(this, this.dataset, view_id, search_defaults, options);
 
-        this.searchview.on('search_data', self, this.do_searchview_search);
-        return this.searchview.appendTo(this.$(".oe_view_manager_view_search"),
-                                      this.$(".oe_searchview_drawer_container"));
+        this.searchview.on('search_data', this, this.search.bind(this));
+        return this.searchview.appendTo(this.$(".oe-view-manager-search-view:first"),
+                this.$('.oe_searchview_drawer_container'));
     },
-    do_searchview_search: function(domains, contexts, groupbys) {
+    search: function(domains, contexts, groupbys) {
         var self = this,
-            controller = this.views[this.active_view].controller,
+            controller = this.active_view.controller,
             action_context = this.action.context || {};
         instance.web.pyeval.eval_domains_and_contexts({
             domains: [this.action.domain || []].concat(domains || []),
@@ -865,301 +758,48 @@ instance.web.ViewManager =  instance.web.Widget.extend({
                 groupby = [groupby];
             }
             $.when(controller.do_search(results.domain, results.context, groupby || [])).then(function() {
-                self.view_completely_inited.resolve();
+                self.active_search.resolve();
             });
         });
     },
-    /**
-     * Called when one of the view want to execute an action
-     */
-    on_action: function(action) {
-    },
-    on_create: function() {
-    },
-    on_remove: function() {
-    },
-    on_edit: function() {
-    },
-    /**
-     * Called by children view after executing an action
-     */
-    on_action_executed: function () {
-    },
-});
-
-instance.web.ViewManagerAction = instance.web.ViewManager.extend({
-    template:"ViewManagerAction",
-    /**
-     * @constructs instance.web.ViewManagerAction
-     * @extends instance.web.ViewManager
-     *
-     * @param {instance.web.ActionManager} parent parent object/widget
-     * @param {Object} action descriptor for the action this viewmanager needs to manage its views.
-     */
-    init: function(parent, action) {
-        // dataset initialization will take the session from ``this``, so if we
-        // do not have it yet (and we don't, because we've not called our own
-        // ``_super()``) rpc requests will blow up.
-        var flags = action.flags || {};
-        if (!('auto_search' in flags)) {
-            flags.auto_search = action.auto_search !== false;
-        }
-        if (action.res_model == 'board.board' && action.view_mode === 'form') {
-            // Special case for Dashboards
-            _.extend(flags, {
-                views_switcher : false,
-                display_title : false,
-                search_view : false,
-                pager : false,
-                sidebar : false,
-                action_buttons : false
-            });
-        }
-        this._super(parent, null, action.views, flags);
-        this.session = parent.session;
-        this.action = action;
-        var context = action.context;
-        if (action.target === 'current'){
-            var active_context = {
-                active_model: action.res_model,
-            };
-            context = new instance.web.CompoundContext(context, active_context).eval();
-            delete context['active_id'];
-            delete context['active_ids'];
-            if (action.res_id){
-                context['active_id'] = action.res_id;
-                context['active_ids'] = [action.res_id];
-            }
-        }
-        var dataset = new instance.web.DataSetSearch(this, action.res_model, context, action.domain);
-        if (action.res_id) {
-            dataset.ids.push(action.res_id);
-            dataset.index = 0;
-        }
-        this.dataset = dataset;
-    },
-    /**
-     * Initializes the ViewManagerAction: sets up the searchview (if the
-     * searchview is enabled in the manager's action flags), calls into the
-     * parent to initialize the primary view and (if the VMA has a searchview)
-     * launches an initial search after both views are done rendering.
-     */
-    start: function() {
-        var self = this,
-            searchview_loaded,
-            search_defaults = {};
-        _.each(this.action.context, function (value, key) {
-            var match = /^search_default_(.*)$/.exec(key);
-            if (match) {
-                search_defaults[match[1]] = value;
-            }
-        });
-        // init search view
-        var searchview_id = this.action['search_view_id'] && this.action['search_view_id'][0];
-
-        searchview_loaded = this.setup_search_view(searchview_id || false, search_defaults);
-
-        var main_view_loaded = this._super();
-
-        var manager_ready = $.when(searchview_loaded, main_view_loaded, this.view_completely_inited);
-
-        this.$el.find('.oe_debug_view').change(this.on_debug_changed);
-        this.$el.addClass("oe_view_manager_" + (this.action.target || 'current'));
-        return manager_ready;
-    },
-    on_debug_changed: function (evt) {
-        var self = this,
-            $sel = $(evt.currentTarget),
-            $option = $sel.find('option:selected'),
-            val = $sel.val(),
-            current_view = this.views[this.active_view].controller;
-        switch (val) {
-            case 'fvg':
-                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':
-                this.do_action({
-                    name: _t("JS Tests"),
-                    target: 'new',
-                    type : 'ir.actions.act_url',
-                    url: '/web/tests?mod=*'
-                });
-                break;
-            case 'get_metadata':
-                var ids = current_view.get_selected_ids();
-                if (ids.length === 1) {
-                    this.dataset.call('get_metadata', [ids]).done(function(result) {
-                        var dialog = new instance.web.Dialog(this, {
-                            title: _.str.sprintf(_t("Metadata (%s)"), self.dataset.model),
-                            size: 'medium',
-                        }, QWeb.render('ViewManagerDebugViewLog', {
-                            perm : result[0],
-                            format : instance.web.format_value
-                        })).open();
-                    });
-                }
-                break;
-            case 'toggle_layout_outline':
-                current_view.rendering_engine.toggle_layout_debugging();
-                break;
-            case 'set_defaults':
-                current_view.open_defaults_dialog();
-                break;
-            case 'translate':
-                this.do_action({
-                    name: _t("Technical Translation"),
-                    res_model : 'ir.translation',
-                    domain : [['type', '!=', 'object'], '|', ['name', '=', this.dataset.model], ['name', 'ilike', this.dataset.model + ',']],
-                    views: [[false, 'list'], [false, 'form']],
-                    type : 'ir.actions.act_window',
-                    view_type : "list",
-                    view_mode : "list"
-                });
-                break;
-            case 'fields':
-                this.dataset.call('fields_get', [false, {}]).done(function (fields) {
-                    var $root = $('<dl>');
-                    _(fields).each(function (attributes, name) {
-                        $root.append($('<dt>').append($('<h4>').text(name)));
-                        var $attrs = $('<dl>').appendTo($('<dd>').appendTo($root));
-                        _(attributes).each(function (def, name) {
-                            if (def instanceof Object) {
-                                def = JSON.stringify(def);
-                            }
-                            $attrs
-                                .append($('<dt>').text(name))
-                                .append($('<dd style="white-space: pre-wrap;">').text(def));
-                        });
-                    });
-                    new instance.web.Dialog(self, {
-                        title: _.str.sprintf(_t("Model %s fields"),
-                                             self.dataset.model),
-                        }, $root).open();
-                });
-                break;
-            case 'edit_workflow':
-                return this.do_action({
-                    res_model : 'workflow',
-                    domain : [['osv', '=', this.dataset.model]],
-                    views: [[false, 'list'], [false, 'form'], [false, 'diagram']],
-                    type : 'ir.actions.act_window',
-                    view_type : 'list',
-                    view_mode : 'list'
-                });
-            case 'edit':
-                this.do_edit_resource($option.data('model'), $option.data('id'), { name : $option.text() });
-                break;
-            case 'manage_filters':
-                this.do_action({
-                    res_model: 'ir.filters',
-                    views: [[false, 'list'], [false, 'form']],
-                    type: 'ir.actions.act_window',
-                    context: {
-                        search_default_my_filters: true,
-                        search_default_model_id: this.dataset.model
-                    }
-                });
-                break;
-            case 'print_workflow':
-                if (current_view.get_selected_ids  && current_view.get_selected_ids().length == 1) {
-                    instance.web.blockUI();
-                    var action = {
-                        context: { active_ids: current_view.get_selected_ids() },
-                        report_name: "workflow.instance.graph",
-                        datas: {
-                            model: this.dataset.model,
-                            id: current_view.get_selected_ids()[0],
-                            nested: true,
-                        }
-                    };
-                    this.session.get_file({
-                        url: '/web/report',
-                        data: {action: JSON.stringify(action)},
-                        complete: instance.web.unblockUI
-                    });
-                }
-                break;
-            default:
-                if (val) {
-                    console.log("No debug handler for ", val);
-                }
-        }
-        evt.currentTarget.selectedIndex = 0;
-    },
-    do_edit_resource: function(model, id, action) {
-        action = _.extend({
-            res_model : model,
-            res_id : id,
-            type : 'ir.actions.act_window',
-            view_type : 'form',
-            view_mode : 'form',
-            views : [[false, 'form']],
-            target : 'new',
-            flags : {
-                action_buttons : true,
-                form : {
-                    resize_textareas : true
-                }
-            }
-        }, action || {});
-        this.do_action(action);
-    },
-    switch_mode: function (view_type, no_store, options) {
-        var self = this;
-
-        return this.alive($.when(this._super.apply(this, arguments))).done(function () {
-            var controller = self.views[self.active_view].controller;
-            self.$el.find('.oe_debug_view').html(QWeb.render('ViewManagerDebug', {
-                view: controller,
-                view_manager: self
-            }));
-            self.set_title();
-        });
-    },
-    do_create_view: function(view_type) {
-        var self = this;
-        return this._super.apply(this, arguments).then(function() {
-            var view = self.views[view_type].controller;
-            view.set({ 'title': self.action.name });
-        });
-    },
-    get_action_manager: function() {
-        var cur = this;
-        while ((cur = cur.getParent())) {
-            if (cur instanceof instance.web.ActionManager) {
-                return cur;
-            }
-        }
-        return undefined;
-    },
-    set_title: function(title) {
-        this.$el.find('.oe_breadcrumb_title:first').html(this.get_action_manager().get_title());
-    },
     do_push_state: function(state) {
-        if (this.getParent() && this.getParent().do_push_state) {
-            state["view_type"] = this.active_view;
-            this.url_states[this.active_view] = state;
-            this.getParent().do_push_state(state);
+        if (this.action_manager) {
+            state.view_type = this.active_view.type;
+            this.action_manager.do_push_state(state);
         }
-    },
+    },    
     do_load_state: function(state, warm) {
         var self = this,
             defs = [];
-        if (state.view_type && state.view_type !== this.active_view) {
+        if (state.view_type && state.view_type !== this.active_view.type) {
             defs.push(
-                this.views[this.active_view].deferred.then(function() {
+                this.active_view.created.then(function() {
                     return self.switch_mode(state.view_type, true);
                 })
             );
         }
 
-        $.when(this.views[this.active_view] ? this.views[this.active_view].deferred : $.when(), defs).done(function() {
-            self.views[self.active_view].controller.do_load_state(state, warm);
+        $.when(this.active_view ? this.active_view.created : null, defs).done(function() {
+            self.active_view.controller.do_load_state(state, warm);
         });
     },
 });
 
+instance.web.ViewManagerAction = instance.web.ViewManager.extend({
+    template:"ViewManagerAction",
+
+    init: function (parent, action) {
+        var flags = action.flags || {};
+        if (!('auto_search' in flags)) {
+            flags.auto_search = action.auto_search !== false;
+        }
+        this.action = action;
+        this.action_manager = parent;
+        var dataset = new instance.web.DataSetSearch(this, action.res_model, action.context, action.domain);
+        this._super(parent, dataset, action.views, flags);
+    }
+});
+
 instance.web.Sidebar = instance.web.Widget.extend({
     init: function(parent) {
         var self = this;
@@ -1331,7 +971,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
                 a.url = prefix  + '&id=' + a.id + '&t=' + (new Date().getTime());
             }
         });
-        self.items['files'] = attachments;
+        self.items.files = attachments;
         self.redraw();
         this.$('.oe_sidebar_add_attachment .oe_form_binary_file').change(this.on_attachment_changed);
         this.$el.find('.oe_sidebar_delete_item').click(this.on_attachment_delete);
@@ -1519,9 +1159,7 @@ instance.web.View = instance.web.Widget.extend({
         this.$el.hide();
     },
     is_active: function () {
-        var manager = this.getParent();
-        return !manager || !manager.active_view
-             || manager.views[manager.active_view].controller === this;
+        return this.ViewManager.active_view.controller === this;
     }, /**
      * Wraps fn to only call it if the current view is the active one. If the
      * current view is not active, doesn't call fn.
@@ -1544,7 +1182,8 @@ instance.web.View = instance.web.Widget.extend({
             this.getParent().do_push_state(state);
         }
     },
-    do_load_state: function(state, warm) {
+    do_load_state: function (state, warm) {
+
     },
     /**
      * Switches to a specific view type
index f99a96b..656b1c9 100644 (file)
     </div>
 </t>
 
-<t t-name="ViewManager">
-    <div class="oe_view_manager">
-        <table class="oe_view_manager_header">
-            <col width="20%"/>
-            <col width="35%"/>
-            <col width="15%"/>
-            <col width="30%"/>
-            <tr class="oe_header_row oe_header_row_top">
-                <td colspan="2">
-                        <h2 class="oe_view_title" t-if="widget.flags.display_title !== false">
-                            <span class="oe_view_title_text oe_breadcrumb_title"/>
-                        </h2>
-                </td>
-                <td colspan="2">
-                        <div class="oe_view_manager_view_search"/>
-                </td>
-            </tr>
-            <tr class="oe_header_row">
-                <td>
-                        <div class="oe_view_manager_buttons"/>
-                </td>
-                <td colspan="2">
-                        <div class="oe_view_manager_sidebar"/>
-                </td>
-                <td>
-                    <ul class="oe_view_manager_switch oe_button_group oe_right">
-                        <t t-if="widget.views_src.length > 1" t-foreach="widget.views_src" t-as="view">
-                          <li class="oe_e">
-                            <a t-attf-class="oe_vm_switch_#{view.view_type}" t-att-data-view-type="view.view_type"
-                               t-att-title="view.button_label"/>
-                          </li>
+<div t-name="ViewManager">
+    <div class="oe-view-manager-header container-fluid">
+        <div class="row">
+            <div class="col-md-12 oe-header-title">
+                <ol class="oe-view-title breadcrumb" t-if="widget.flags.display_title !== false">
+                </ol>
+                <div class="oe-view-manager-search-view">
+                </div>
+            </div>            
+        </div>
+        <div class="row">
+            <div class="col-md-12">
+                <div class="oe-view-manager-buttons">
+                    <t t-foreach="widget.views" t-as="view">
+                        <div t-attf-class="oe-#{view}-buttons"/>
+                    </t>                    
+                </div>
+                <div class="oe-view-manager-sidebar"></div>
+                <div class="oe-view-manager-pager"></div>
+
+                <t t-if="widget.view_order.length > 1">
+                    <div class="oe-view-manager-switch btn-group btn-group-sm">
+                        <t t-foreach="widget.view_order" t-as="view_type">
+                            <a type="button" t-attf-class="btn btn-default fa oe-vm-switch-#{view_type}" t-att-data-view-type="view_type" t-att-title="view_type" t-if="view_type!=='form'">
+                            </a>
                         </t>
-                    </ul>
-                    <div class="oe_view_manager_pager oe_right"/>
-                </td>
-            </tr>
-        </table>
+                    </div>
+                </t>
 
-    <div class="oe_view_manager_wrapper">
-        <div>
-            <div class="oe_view_manager_body">
-                <div class="oe_searchview_drawer_container"/>
-                    <t t-foreach="widget.views_src" t-as="view">
-                        <div t-attf-class="oe_view_manager_view_#{view.view_type}"/>
-                    </t>
-                </div>
             </div>
         </div>
     </div>
-</t>
-
+    <div class="oe-view-manager-body">
+        <div class="oe_searchview_drawer_container"/>
+        <t t-foreach="widget.views" t-as="view">
+            <div t-attf-class="oe-view-manager-view-#{view}"/>
+        </t>
+    </div>
+</div>
 <t t-name="ViewManagerAction" t-extend="ViewManager">
     <t t-jquery="h2.oe_view_title" t-operation="before">
         <select t-if="widget.session.debug" class="oe_debug_view"/>
 <t t-name="ListView.buttons">
     <div class="oe_list_buttons">
     <t t-if="!widget.no_leaf and widget.options.action_buttons !== false and widget.options.addable and widget.is_action_enabled('create')">
-        <button type="button" class="oe_button oe_list_add oe_highlight">
+        <button type="button" class="oe_list_add btn btn-primary">
             <t t-esc="widget.options.addable"/>
         </button>
     </t>
         <span class="oe_form_buttons_view">
             <!-- required for the bounce effect on button -->
             <div t-if="widget.is_action_enabled('edit')" style="display: inline-block;">
-                <button type="button" class="oe_button oe_form_button_edit" accesskey="E">Edit</button>
+                <button type="button" class="oe_form_button_edit btn btn-default" accesskey="E">Edit</button>
             </div>
             <button t-if="widget.is_action_enabled('create')"
-                type="button" class="oe_button oe_form_button_create" accesskey="C">Create</button>
+                type="button" class="oe_form_button_create btn btn-default" accesskey="C">Create</button>
         </span>
         <span class="oe_form_buttons_edit">
-            <button type="button" class="oe_button oe_form_button_save oe_highlight" accesskey="S">Save</button>
+            <button type="button" class="oe_form_button_save btn btn-primary" accesskey="S">Save</button>
             <span class="oe_fade">or</span>
             <a href="#" class="oe_bold oe_form_button_cancel" accesskey="D">Discard</a>
         </span>
 
 <t t-name="One2Many.viewmanager" t-extend="ViewManager">
     <t t-jquery=".oe-view-manager-header">
-        this.attr('t-if', 'views.length != 1');
+        this.attr('t-if', 'widget.view_order.length != 1');
     </t>
 </t>
 <t t-name="One2Many.formview" t-extend="FormView">
     </t>
 </t>
 
-<div t-name="SearchView" class="oe_searchview">
+<div t-name="SearchView" class="oe_searchview form-control input-sm">
     <div class="oe_searchview_facets"/>
-    <div class="oe_searchview_clear"/>
-    <div class="oe_searchview_unfold_drawer" title="Advanced Search..."/>
-    <button type="button" class="oe_searchview_search"
-            title="Search Again">Search</button>
+    <div class="oe_searchview_clear"><i class="fa fa-times fa-lg"></i></div>
+    <div class="oe_searchview_unfold_drawer fa fa-lg fa-chevron-down" title="Advanced Search..."/>
+    <i type="button" class="oe_searchview_search fa fa-lg fa-search"
+            title="Search Again"></i>
 </div>
 
 <div t-name="SearchViewDrawer" class="oe_searchview_drawer" style="display:none;">
      tabindex="0"/>
 <!-- tabindex: makes div focusable -->
 <div t-name="SearchView.FacetView"
-     class="oe_tag oe_tag_dark oe_searchview_facet"
-     tabindex="0"
-    ><span class="oe_facet_remove">x</span
-    ><span class="oe_facet_category oe_i" t-if="widget.model.has('icon')">
+     class="oe_tag oe_searchview_facet"
+     tabindex="0">
+    <span class="oe_facet_remove">x</span>
+    <span class="label label-default oe_i" t-if="widget.model.has('icon')">
         <t t-esc="widget.model.get('icon')"/>
-    </span
-    ><span class="oe_facet_category" t-if="!widget.model.has('icon')">
+    </span>
+    <span class="label label-default" t-if="!widget.model.has('icon')">
         <t t-esc="widget.model.get('category')"/>
-    </span ><span class="oe_facet_values"
-/></div>
+    </span >
+    <span class="oe_facet_values"/>
+</div>
 <span t-name="SearchView.FacetView.Value" class="oe_facet_value">
     <t t-esc="widget.model.get('label')"/>
 </span>