diff options
| author | Xavier Morel <xmo@openerp.com> | 2011-12-07 10:14:04 +0100 |
|---|---|---|
| committer | Xavier Morel <xmo@openerp.com> | 2011-12-07 10:14:04 +0100 |
| commit | edcbc3830e58a37e6924417c68b199d5b929b694 (patch) | |
| tree | 4ff59f1ffa04a1e20f30c39aa382998c03856fb8 /addons/web/static/src | |
| parent | 986ff55624ea8dcb3d31140089f6237ff5238739 (diff) | |
| parent | 0fdda368713bde6df6a3d64e2827667043040f5d (diff) | |
[MERGE] trunk
bzr revid: xmo@openerp.com-20111207091404-1zdmhmsnvhveq7c4
Diffstat (limited to 'addons/web/static/src')
| -rw-r--r-- | addons/web/static/src/css/base.css | 276 | ||||
| -rw-r--r-- | addons/web/static/src/css/data_import.css | 2 | ||||
| -rw-r--r-- | addons/web/static/src/img/iconset-b-remove.png | bin | 0 -> 189 bytes | |||
| -rw-r--r-- | addons/web/static/src/js/chrome.js | 35 | ||||
| -rw-r--r-- | addons/web/static/src/js/core.js | 3 | ||||
| -rw-r--r-- | addons/web/static/src/js/data.js | 21 | ||||
| -rw-r--r-- | addons/web/static/src/js/data_import.js | 24 | ||||
| -rw-r--r-- | addons/web/static/src/js/formats.js | 11 | ||||
| -rw-r--r-- | addons/web/static/src/js/search.js | 12 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_editor.js | 1 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_form.js | 22 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_list.js | 21 | ||||
| -rw-r--r-- | addons/web/static/src/js/views.js | 77 | ||||
| -rw-r--r-- | addons/web/static/src/xml/base.xml | 68 |
14 files changed, 402 insertions, 171 deletions
diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index cad536c0f1f..067ea09cd38 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -1,4 +1,3 @@ -/* TODO: separate openerp web client page css from openerp views css */ body.openerp { padding: 0; margin: 0; @@ -6,10 +5,17 @@ body.openerp { min-width: 1000px; overflow-y: scroll; font-size: 80%; + font-family: Ubuntu, Helvetica, sans-serif; } body.openerp, .openerp textarea, .openerp input, .openerp select, .openerp option, .openerp button, .openerp .ui-widget { font-family: Ubuntu, Helvetica, sans-serif; + font-size:85%; +} + +.openerp .view-manager-main-content { + width: 100%; + padding: 0 8px 8px 8px; } .oe_box { @@ -29,6 +35,17 @@ body.openerp, .openerp textarea, .openerp input, .openerp select, .openerp optio .openerp .oe-listview .oe-number { text-align: right !important; } +.oe-listview-header-columns { + background: #444; /* Old browsers */ + background: -moz-linear-gradient(top, #ffffff 0%, #d1d1d1 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(100%,#d1d1d1)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #ffffff 0%,#d1d1d1 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #ffffff 0%,#d1d1d1 100%); /* Opera11.10+ */ + background: -ms-linear-gradient(top, #ffffff 0%,#d1d1d1 100%); /* IE10+ */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#FFFFFF', endColorstr='#d1d1d1',GradientType=0 ); /* IE6-9 */ + background: linear-gradient(top, #ffffff 0%,#d1d1d1 100%); /* W3C */ +} + .openerp .oe_hide { display: none !important; } @@ -261,7 +278,7 @@ label.error { filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#BD5E54', endColorstr='#90322A',GradientType=0 ); /* IE6-9 */ background: linear-gradient(top, #bd5e54 0%,#90322a 60%); /* W3C */ - border: 1px solid #6E2A24; + border: 1px solid #5E1A14; border-radius: 4px; -moz-border-radius: 4px; -webkit-border-radius: 4px; @@ -272,7 +289,7 @@ label.error { text-transform: uppercase; line-height: 20px; font-weight: bold; - font-size: 85%; + font-size: 75%; white-space: nowrap; } @@ -331,6 +348,7 @@ label.error { height: 100%; display: block; position: relative; + font-size:85%; } .openerp .secondary_menu.oe_folded { width: 20px; @@ -371,6 +389,10 @@ label.error { white-space: nowrap; color: white; text-shadow: 0 1px 0 #333; + +} +.openerp a.oe_secondary_submenu_item { + padding: 0 5px 2px 10px; } .openerp a.oe_secondary_submenu_item:hover, .openerp a.oe_secondary_submenu_item.leaf.active { @@ -383,7 +405,7 @@ label.error { background: -ms-linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%,#5a5858 96%); /* IE10+ */ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#FFFFFF', endColorstr='#5A5858',GradientType=0 ); /* IE6-9 */ background: linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%,#5a5858 96%); /* W3C */ - padding: 0 5px 2px 5px; + padding: 0 5px 2px 10px; line-height: 20px; color: #3f3d3d; text-decoration: none; @@ -431,6 +453,8 @@ label.error { margin: 0; padding: 4px 10px; text-shadow: 0 1px 0 #111111; + font-weight:normal; + line-height:14px; } .openerp .header_title small { color: #ccc; @@ -464,15 +488,11 @@ label.error { filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#929292', endColorstr='#4D4D4D',GradientType=0 ); } .openerp .header_corner ul.block { - /*float: left;*/ list-style: none; height: 34px; margin: 0; padding: 0 0 0 2px; - /*background: url(../images/top-sep-a.png) no-repeat;*/ line-height: 33px; - /*font-size: 1em;*/ - /*text-transform: uppercase;*/ } .openerp .header_corner ul.block li { float: left; @@ -498,6 +518,10 @@ label.error { font-weight: bold; } +.openerp .logout { + font-size:80%; +} + /* Footer */ .openerp div.oe_footer { background: none repeat scroll 0 0 #CCCCCC; @@ -530,7 +554,7 @@ label.error { } .openerp h2.oe_view_title { - font-size: 175%; + font-size: 110%; font-weight: normal; margin: 2px 0; color: #252424; @@ -541,12 +565,15 @@ label.error { .openerp .oe_vm_switch { float: right; } +.openerp .oe-view-manager-header .oe_view_title { + font-size:150%; +} /* SearchView */ .openerp .filter_label, .openerp .filter_icon { - border: 1px solid #666; border-left-width: 0; background: #F0F0F0; + border: 1px solid #999; background: -moz-linear-gradient(top, #F0F0F0 0%, #C0C0C0 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#F0F0F0), color-stop(100%,#C0C0C0)); filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#F0F0F0', endColorstr='#C0C0C0',GradientType=0 ); @@ -558,13 +585,13 @@ label.error { filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#F0F0F0', endColorstr='#A1A7CE',GradientType=0 ); } .openerp .filter_label:active, .openerp .filter_icon:active { - background: #AAAAAA; + background: #aaa; background: -moz-linear-gradient(top, #999999 0%, #EEEEEE 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#999999), color-stop(100%,#EEEEEE)); filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#999999', endColorstr='#EEEEEE',GradientType=0 ); } .openerp .filter_label.enabled, .openerp .filter_icon.enabled { - background: #AAAAAA; + background: #aaa; } .openerp .filter_icon { height: 22px; @@ -588,13 +615,16 @@ label.error { white-space: nowrap; } .openerp .filter_label_group button:first-child { - border-left: 1px solid #666; -webkit-border-top-left-radius: 7px; -webkit-border-bottom-left-radius: 7px; -moz-border-radius-topleft: 7px; -moz-border-radius-bottomleft: 7px; border-top-left-radius: 7px; border-bottom-left-radius: 7px; + border-right: none; +} +.openerp .filter_label_group button { + border-right: none; } .openerp .filter_label_group button:last-child { -webkit-border-top-right-radius: 7px; @@ -603,6 +633,20 @@ label.error { -moz-border-radius-bottomright: 7px; border-top-right-radius: 7px; border-bottom-right-radius: 7px; + border-right: 1px solid #999; +} +.openerp .filter_label_group button.filter_icon img { + padding: 1px 8px 0 8px; +} +.openerp .filter_label_group button.filter_icon:first-child { + border-left: solid 1px #999; + margin-left: -7px; + -webkit-border-top-left-radius: 0px; + -webkit-border-bottom-left-radius: 0px; + -moz-border-radius-topleft: 0px; + -moz-border-radius-bottomleft: 0px; + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; } .openerp .searchview_group_string { @@ -628,8 +672,16 @@ label.error { .openerp .searchview_group.expanded .searchview_group_content { display: block; } -.openerp .searchview_group_content { - padding-left: 10px; + +.openerp .searchview_group_content .oe_label, .openerp .searchview_group_content .oe_label_help { + font-weight: bold; + color: #4c4c4c; +} + +.openerp .oe-searchview-render-line .oe_label, .openerp .oe-searchview-render-line .oe_label_help { + font-weight: bold; + font-size: 80%; + white-space: nowrap; } .openerp .searchview_extended_group { @@ -715,20 +767,23 @@ label.error { text-align: left; padding: 1px 2px; } -.openerp .oe-listview th.oe-record-selector, -.openerp .oe-listview td.oe-button, -.openerp .oe-listview td.oe-record-delete { - padding: 0 1px; + +.openerp .oe-record-delete button{ + border: none; + height: 12px; + width: 12px; + background: url("/web/static/src/img/iconset-b-remove.png") no-repeat scroll center center transparent; + cursor: pointer; } /* Could use :not selectors if they were supported by MSIE8... */ .openerp .oe-listview tbody td { - border-left: 1px solid #dadada; + border-left: 1px solid #dadada; /*currently commenting to test with no vertical lines in list view*/ } .openerp .oe-listview tbody td:first-child, .openerp .oe-listview tbody td.oe-button, -.openerp .oe-listview tbody td.oe-button+td, -.openerp .oe-listview tbody th.oe-record-selector+td, +.openerp .oe-listview tbody td.oe-button, +.openerp .oe-listview tbody th.oe-record-selector, .openerp .oe-listview tbody td.oe-record-delete { border-left: none; } @@ -738,15 +793,36 @@ label.error { } .openerp .oe-listview th.oe-sortable { cursor: pointer; + font-size: 75%; + text-transform: uppercase; + padding: 0; + margin: 0; + padding-left: 3px; + color: #333; } .openerp .oe-listview th.oe-sortable .ui-icon { - height: 1em; + height: 60%; + margin: -6px 0 0; display: inline; display: inline-block; + vertical-align: middle; +} + +.openerp .oe-listview table tbody td { + border-bottom: 1px solid #E3E3E3; +} + +.openerp .oe-listview .oe-record-selector { + border-bottom: 1px solid #E3E3E3; } .openerp .oe-listview .oe-field-cell { cursor: pointer; + margin-top: 0; + margin-bottom: 0; + padding-top: 3px; + padding-bottom: 3px; + font-size: 80%; } .openerp .oe-listview .oe-field-cell progress { width: 100%; @@ -778,6 +854,8 @@ label.error { } .openerp .oe-list-pager .oe-pager-state { cursor: pointer; + font-size: 90%; + color: #555; } .openerp .oe-listview .oe-group-name { @@ -794,6 +872,8 @@ label.error { .openerp .oe-listview .oe-list-footer { text-align: center; white-space: nowrap; + color: #444; + font-size: 85%; } .openerp .oe-listview .oe-list-footer span { margin: 0 1em; @@ -846,28 +926,62 @@ label.error { } .openerp .oe_form_notebook .ui-tabs-panel { padding: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; } .openerp .oe_form_notebook ul.ui-tabs-nav { padding-left: 0; background: transparent; - border-width: 0 0 1px 0; + border-width: 0; border-radius: 0; -moz-border-radius: 0; -webkit-border-radius: 0; - line-height: 0.5em; + line-height: 0.8em; + font-size: 95%; + color: #555; } .openerp .oe_form_notebook ul.ui-tabs-nav li { font-weight: bold; } .openerp .oe_form_notebook .ui-tabs-panel { background: #f9f9f9; - border-width: 0 1px 1px 1px; + border-width: 1px; } .openerp .oe_form_notebook .ui-tabs-selected { background: #f9f9f9; } +/* Unedit Form */ +.openerp .field_char, .openerp .field_date, .openerp .field_float, .openerp .oe_form_field_many2one a { + vertical-align: middle; + padding-top: 3px; + font-size: 90%; + color: #222; +} +.openerp .oe_form_field_many2one a { + color: #9A0404; + line-height: 12px; +} + + /* Form */ + +.openerp .oe_form_frame_cell input[type="checkbox"] { + margin-top: 3px; + vertical-align: center; +} +.openerp .oe_form_frame_cell .input[type="text"] { + padding-bottom: 1px; +} + +.openerp table.oe_frame td { + color: #4c4c4c; +} +.openerp td.oe_form_frame_cell { + padding: 2px; + position: relative; +} .openerp .oe_frame.oe_forms { clear: both; } @@ -889,6 +1003,9 @@ label.error { padding: 2px; position: relative; } +.openerp td.oe_form_field_boolean { + padding-top: 4px; +} .openerp td.oe_form_frame_cell.oe_form_group { padding: 0; } @@ -900,14 +1017,31 @@ label.error { } .openerp .oe_form_pager, .openerp .oe_list_pager { float: right; + font-size: 80%; + color: gray; + font-weight: bold; +} + +.openerp .oe_form_pager { + margin-right: 3px; +} + + +.openerp label.oe_label_help, .openerp label.oe_label, .openerp .oe_forms input[type="text"], .openerp .oe_forms input[type="password"], .openerp .oe_forms select, .openerp .oe_forms .oe_button, .openerp .oe_forms textarea { + font-size: 85%; } .openerp label.oe_label_help, .openerp label.oe_label { display: block; + color: #4c4c4c; + font-weight: normal; } .openerp label.oe_label_help { cursor: help; } +.openerp .oe_form_frame_cell .oe_label, .openerp .oe_form_frame_cell .oe_label_help { + font-weight: normal; +} .openerp #tiptip_content { font-size: 12px; } @@ -926,8 +1060,12 @@ label.error { } .openerp .oe_forms label.oe_label, .openerp .oe_forms label.oe_label_help { - margin: 3px 0 0 10px; + margin: 4px 0 0 3px; } +.openerp .oe_forms .searchview_group_content label.oe_label, .openerp .searchview_group_content .oe_forms label.oe_label_help { /* making a distinction between labels in search view and other labels */ + margin: 3px 0 0 3px; +} + .openerp label.oe_label_help span { font-size: 80%; color: darkgreen; @@ -949,13 +1087,29 @@ label.error { margin: 3px 0 0 0; } +/* Uneditable Form View */ +.openerp .oe_form_readonly { + +} +.openerp .oe_form_readonly .field_char, .openerp .oe_form_readonly .oe_form_field_email { + padding-top: 4px; + background-color: white; +} + +.openerp .oe_form_readonly .field_selection { + padding-top: 2px; + background-color: white; +} + + /* Inputs */ .openerp .oe_forms input[type="text"], .openerp .oe_forms input[type="password"], .openerp .oe_forms select, .openerp .oe_forms textarea { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box; - padding: 0 2px 0 2px; + padding: 0 2px; + margin: 0 2px; border: 1px solid #999; -moz-border-radius: 3px; -webkit-border-radius: 3px; @@ -964,6 +1118,10 @@ label.error { min-width: 90px; color: #1f1f1f; } +.openerp .oe_forms select{ + padding-top: 2px; +} + .openerp .oe_forms textarea { resize:vertical; } @@ -979,6 +1137,9 @@ label.error { min-width: 100%; width: 100%; } +.openerp .oe_forms .button { + height: 22px; +} @-moz-document url-prefix() { /* Strange firefox behaviour on width: 100% + white-space: nowrap */ .openerp .oe_forms .oe_button { @@ -1055,10 +1216,14 @@ label.error { border: 0 solid #666; } .openerp .separator.horizontal { - font-weight: bold; + font-weight: bold; border-bottom-width: 1px; margin: 3px 4px 3px 1px; - height: 15px; + height: 17px; + font-size: 95%; +} +.openerp .separator.horizontal:empty { + height: 5px; } .openerp .oe_form_frame_cell.oe_form_separator_vertical { border-left: 1px solid #666; @@ -1095,6 +1260,14 @@ label.error { background: white; min-width: 90px; } +.openerp tbody.ui-widget-content { + margin-bottom: 10px; + border-spacing: 4px; +} +.openerp .ui-widget-header { + background-image: none; + background-color: white; +} /* Sidebar */ .openerp .view-manager-main-table { @@ -1108,16 +1281,13 @@ label.error { vertical-align: top; } -.openerp .view-manager-main-content { - width: 100%; -} .openerp .oe-view-manager-header { overflow: auto; } .openerp .oe-view-manager-header h2 { float: left; } -.openerp .oe-view-manager-header blockquote { +.openerp .oe_view_manager_menu_tips blockquote { display: none; font-size: 85%; margin: 0; @@ -1126,14 +1296,14 @@ label.error { padding: 1px 10px; color: #4C4C4C; } -.openerp .oe-view-manager-header blockquote p { +.openerp .oe_view_manager_menu_tips blockquote p { margin: 0; padding: 6px 1px 4px; } -.openerp .oe-view-manager-header blockquote div { +.openerp .oe_view_manager_menu_tips blockquote div { text-align: right; } -.openerp .oe-view-manager-header blockquote div button { +.openerp .oe_view_manager_menu_tips blockquote div button { border: none; background: none; padding: 0 4px; @@ -1310,14 +1480,6 @@ label.error { background: 1px 3px url(/web/static/src/img/icons/gtk-print.png) no-repeat; } -.openerp .oe-running-kitten { - display: none; -} - -.openerp.kitten-mode-activated .oe-running-kitten { - display: inherit; -} - .openerp.kitten-mode-activated .main_table { background: url(http://placekitten.com/g/1500/800) repeat; } @@ -1373,6 +1535,7 @@ label.error { } .openerp .oe_forms .oe-m2o input[type="text"] { padding-right: 20px; + padding-top: 2px; } .openerp .oe-m2o-drop-down-button { margin-left: -23px; @@ -1382,12 +1545,12 @@ label.error { margin-bottom: -4px; cursor: pointer; } -.openerp .oe-m2o-cm-button img { - margin-left: 4px; -} .openerp .oe-m2o-disabled-cm { color: grey; } +.openerp ul[role="listbox"] li a { + font-size:80%; +} .parent_top { vertical-align: text-top; } @@ -1433,20 +1596,19 @@ label.error { /* Shortcuts*/ .oe-shortcut-toggle { height: 20px; + margin-top: 3px; padding: 0; width: 24px; cursor: pointer; display: block; - background: url(/web/static/src/img/add-shortcut.png) no-repeat bottom; + background: url(/web/static/src/img/add-shortcut.png) no-repeat center center; float: left; } .oe-shortcut-remove{ - background: url(/web/static/src/img/remove-shortcut.png) no-repeat bottom; + background: url(/web/static/src/img/remove-shortcut.png) no-repeat center center; } -/* ================ */ .oe-shortcuts { position: absolute; - margin: 0; padding: 6px 15px; top: 37px; @@ -1471,9 +1633,14 @@ label.error { color: #fff; text-align: center; border-left: 1px solid #909090; - padding: 4px; - font-size: 90%; + padding: 0 4px; + font-size: 80%; font-weight: normal; + vertical-align: top; +} + +.oe-shortcuts li:hover { + background-color: #666; } .oe-shortcuts li:first-child { border-left: none; @@ -1543,4 +1710,3 @@ ul.oe-arrow-list li.oe-arrow-list-selected .oe-arrow-list-after { .openerp .oe_view_editor_tree_grid a { display: block; } - diff --git a/addons/web/static/src/css/data_import.css b/addons/web/static/src/css/data_import.css index e5d1c9a910c..a63a52802f0 100644 --- a/addons/web/static/src/css/data_import.css +++ b/addons/web/static/src/css/data_import.css @@ -27,7 +27,7 @@ .openerp .oe-import fieldset.oe-closed table { display: none; } -.openerp .separator.horizontal { +.openerp .oe-import .separator.horizontal { font-weight: bold; border-bottom-width: 1px; margin: 6px 4px 6px 1px; diff --git a/addons/web/static/src/img/iconset-b-remove.png b/addons/web/static/src/img/iconset-b-remove.png Binary files differnew file mode 100644 index 00000000000..497f03b4ceb --- /dev/null +++ b/addons/web/static/src/img/iconset-b-remove.png diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index f10ee9376f6..bac2c357c67 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -30,8 +30,6 @@ openerp.web.Notification = openerp.web.Widget.extend(/** @lends openerp.web.Not this.$element.notify('create', 'oe_notification_alert', { title: title, text: text - }, { - expires: false }); } @@ -242,6 +240,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database init: function(parent, element_id, option_id) { this._super(parent, element_id); this.$option_id = $('#' + option_id); + this.unblockUIFunction = $.unblockUI; }, start: function() { this._super(); @@ -337,11 +336,27 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database self.widget_parent.do_login( info.db, admin.login, admin.password); self.stop(); - $.unblockUI(); + self.unblockUI(); }); }); }, /** + * Blocks UI and replaces $.unblockUI by a noop to prevent third parties + * from unblocking the UI + */ + blockUI: function () { + $.blockUI(); + $.unblockUI = function () {}; + }, + /** + * Reinstates $.unblockUI so third parties can play with blockUI, and + * unblocks the UI + */ + unblockUI: function () { + $.unblockUI = this.unblockUIFunction; + $.unblockUI(); + }, + /** * Displays an error dialog resulting from the various RPC communications * failing over themselves * @@ -366,10 +381,10 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database self.$option_id.find("form[name=create_db_form]").validate({ submitHandler: function (form) { var fields = $(form).serializeArray(); - $.blockUI(); + self.blockUI(); self.rpc("/web/database/create", {'fields': fields}, function(result) { if (result.error) { - $.unblockUI(); + self.unblockUI(); self.display_error(result); return; } @@ -417,7 +432,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database .html(QWeb.render("BackupDB", self)) .find("form[name=backup_db_form]").validate({ submitHandler: function (form) { - $.blockUI(); + self.blockUI(); self.session.get_file({ form: form, error: function (body) { @@ -427,7 +442,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database error: error[1] }); }, - complete: $.unblockUI + complete: $.proxy(self, 'unblockUI') }); } }); @@ -438,7 +453,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database self.$option_id.find("form[name=restore_db_form]").validate({ submitHandler: function (form) { - $.blockUI(); + self.blockUI(); $(form).ajaxSubmit({ url: '/web/database/restore', type: 'POST', @@ -463,9 +478,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database }) } }, - complete: function () { - $.unblockUI(); - } + complete: $.proxy(self, 'unblockUI') }); } }); diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js index 8eeca33934f..c9255d31949 100644 --- a/addons/web/static/src/js/core.js +++ b/addons/web/static/src/js/core.js @@ -1029,7 +1029,8 @@ openerp.web.TranslationDataBase = openerp.web.Class.extend(/** @lends openerp.we set_bundle: function(translation_bundle) { var self = this; this.db = {}; - var modules = _.keys(translation_bundle.modules).sort(); + var modules = _.keys(translation_bundle.modules); + modules.sort(); if (_.include(modules, "web")) { modules = ["web"].concat(_.without(modules, "web")); } diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index 1f2520ee774..26147b4d4e0 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -265,14 +265,25 @@ openerp.web.DataSet = openerp.web.Widget.extend( /** @lends openerp.web.DataSet return this; }, select_id: function(id) { - var idx = _.indexOf(this.ids, id); - if (idx === -1) { + var idx = this.get_id_index(id); + if (idx === null) { return false; } else { this.index = idx; return true; } }, + get_id_index: function(id) { + for (var i=0, ii=this.ids.length; i<ii; i++) { + // Here we use type coercion because of the mess potentially caused by + // OpenERP ids fetched from the DOM as string. (eg: dhtmlxcalendar) + // OpenERP ids can be non-numeric too ! (eg: recursive events in calendar) + if (id == this.ids[i]) { + return i; + } + } + return null; + }, /** * Read records. * @@ -414,8 +425,8 @@ openerp.web.DataSet = openerp.web.Widget.extend( /** @lends openerp.web.DataSet return this.rpc('/web/dataset/call', { model: this.model, method: method, - domain_id: domain_index || null, - context_id: context_index || null, + domain_id: domain_index == undefined ? null : domain_index, + context_id: context_index == undefined ? null : context_index, args: args || [] }, callback, error_callback); }, @@ -433,7 +444,7 @@ openerp.web.DataSet = openerp.web.Widget.extend( /** @lends openerp.web.DataSet model: this.model, method: method, domain_id: null, - context_id: 1, + context_id: args.length - 1, args: args || [] }, callback, error_callback); }, diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js index d5e789ce3e7..cd699c0481d 100644 --- a/addons/web/static/src/js/data_import.js +++ b/addons/web/static/src/js/data_import.js @@ -183,6 +183,20 @@ openerp.web.DataImport = openerp.web.Dialog.extend({ this.$element.find('#result').empty(); var headers, result_node = this.$element.find("#result"); + if (results['error']) { + result_node.append(QWeb.render('ImportView.error', { + 'error': results['error']})); + this.$element.find('fieldset').removeClass('oe-closed'); + return; + } + if (results['success']) { + if (this.widget_parent.widget_parent.active_view == "list") { + this.widget_parent.reload_content(); + } + this.stop(); + return; + } + if (results['records']) { var lines_to_skip = parseInt(this.$element.find('#csv_skip').val(), 10), with_headers = this.$element.find('#file_has_headers').prop('checked'); @@ -195,16 +209,6 @@ openerp.web.DataImport = openerp.web.Dialog.extend({ : results.records })); this.$element.find('fieldset').addClass('oe-closed'); - } else if (results['error']) { - result_node.append(QWeb.render('ImportView.error', { - 'error': results['error']})); - this.$element.find('fieldset').removeClass('oe-closed'); - } else if (results['success']) { - if (this.widget_parent.widget_parent.active_view == "list") { - this.widget_parent.reload_content(); - } - this.stop(); - return; } this.$element.find('form').removeClass('oe-import-no-result'); diff --git a/addons/web/static/src/js/formats.js b/addons/web/static/src/js/formats.js index 3151b34636b..2df651158eb 100644 --- a/addons/web/static/src/js/formats.js +++ b/addons/web/static/src/js/formats.js @@ -158,16 +158,17 @@ openerp.web.parse_value = function (value, descriptor, value_if_empty) { var tmp = Number(value); if (!isNaN(tmp)) return tmp; - tmp = value.replace(openerp.web._t.database.parameters.decimal_point, "."); - var tmp2 = tmp; + + var tmp2 = value; do { tmp = tmp2; tmp2 = tmp.replace(openerp.web._t.database.parameters.thousands_sep, ""); } while(tmp !== tmp2); - tmp = Number(tmp); - if (isNaN(tmp)) + var reformatted_value = tmp.replace(openerp.web._t.database.parameters.decimal_point, "."); + var parsed = Number(reformatted_value); + if (isNaN(parsed)) throw new Error(value + " is not a correct float"); - return tmp; + return parsed; case 'float_time': var float_time_pair = value.split(":"); if (float_time_pair.length != 2) diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index 250960a342f..c3e27fc52be 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -198,17 +198,11 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search var self = this; var select = this.$element.find(".oe_search-view-filters-management"); var val = select.val(); - - if (val.slice(0,1) == "_") { // useless action - select.val("_filters"); - return; - } switch(val) { case 'add_to_dashboard': this.on_add_to_dashboard(); break; case 'manage_filters': - select.val("_filters"); this.do_action({ res_model: 'ir.filters', views: [[false, 'list'], [false, 'form']], @@ -216,12 +210,10 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search context: {"search_default_user_id": this.session.uid, "search_default_model_id": this.dataset.model}, target: "current", - limit : 80, - auto_search : true + limit : 80 }); break; case 'save_filter': - select.val("_filters"); var data = this.build_search_data(); var context = new openerp.web.CompoundContext(); _.each(data.contexts, function(x) { @@ -261,6 +253,8 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search val = parseInt(val, 10); var filter = this.managed_filters[val]; this.on_search([filter.domain], [filter.context], []); + } else { + select.val(''); } }, on_add_to_dashboard: function() { diff --git a/addons/web/static/src/js/view_editor.js b/addons/web/static/src/js/view_editor.js index 447cb1587ca..352856c2b6c 100644 --- a/addons/web/static/src/js/view_editor.js +++ b/addons/web/static/src/js/view_editor.js @@ -26,7 +26,6 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ type: 'ir.actions.act_window', target: "current", limit: this.dataset.limit || 80, - auto_search: true, flags: { sidebar: false, deletable: false, diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 91c457660c4..432ed4f3711 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -33,6 +33,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# this.widgets = {}; this.widgets_counter = 0; this.fields = {}; + this.fields_order = []; this.datarecord = {}; this.show_invalid = true; this.default_focus_field = null; @@ -87,6 +88,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# on_loaded: function(data) { var self = this; if (data) { + this.fields_order = []; this.fields_view = data; var frame = new (this.registry.get_object('frame'))(this, this.fields_view.arch); @@ -156,15 +158,16 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# deferred_stack.push('force resolution if no fields'); return deferred_stack.then(function() { if (!record.id) { - // New record: Second pass in order to trigger the onchanges self.show_invalid = false; - for (var f in record) { - var field = self.fields[f]; - if (field) { + // New record: Second pass in order to trigger the onchanges + // respecting the fields order defined in the view + _.each(self.fields_order, function(field_name) { + if (record[field_name] !== undefined) { + var field = self.fields[field_name]; field.dirty = true; self.do_onchange(field); } - } + }); } self.on_form_changed(); self.initial_mutating_lock.resolve(); @@ -380,6 +383,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# return def.promise(); }, can_be_discarded: function() { + return true; // Disabled until the page view and button refactoring is done return !this.is_dirty() || confirm(_t("Warning, the record has been modified, your changes will be discarded.")); }, /** @@ -1113,6 +1117,11 @@ openerp.web.form.WidgetLabel = openerp.web.form.Widget.extend({ if (this.node.tag == 'label' && (this.align === 'left' || this.node.attrs.colspan || (this.string && this.string.length > 32))) { this.template = "WidgetParagraph"; this.colspan = parseInt(this.node.attrs.colspan || 1, 10); + // Widgets default to right-aligned, but paragraph defaults to + // left-aligned + if (isNaN(parseFloat(this.node.attrs.align))) { + this.align = 'left'; + } } else { this.colspan = 1; this.width = '1%'; @@ -1153,6 +1162,7 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f this.name = node.attrs.name; this.value = undefined; view.fields[this.name] = this; + view.fields_order.push(this.name); this.type = node.attrs.widget || view.fields_view.fields[node.attrs.name].type; this.element_name = "field_" + this.name + "_" + this.type; @@ -2178,6 +2188,7 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ var self = this; if (!this.dataset) return []; + this.save_any_view(); var val = this.dataset.delete_all ? [commands.delete_all()] : []; val = val.concat(_.map(this.dataset.ids, function(id) { var alter_order = _.detect(self.dataset.to_create, function(x) {return x.id === id;}); @@ -2766,6 +2777,7 @@ openerp.web.form.FieldReference = openerp.web.form.Field.extend({ this.view_id = 'reference_' + _.uniqueId(); this.widgets = {}; this.fields = {}; + this.fields_order = []; this.selection = new openerp.web.form.FieldSelection(this, { attrs: { name: 'selection', widget: 'selection' diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index 53c8d634ad1..de7dd1a77f5 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -462,6 +462,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# * @param {Object} results results of evaluating domain and process for a search */ do_search: function (domain, context, group_by) { + this.page = 0; this.groups.datagroup = new openerp.web.DataGroup( this, this.model, domain, context, group_by); this.groups.datagroup.sort = this.dataset._sort; @@ -1191,7 +1192,7 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L } else if (column.type === 'float') { format = "%.2f"; } - $('<td>') + $('<td class="oe-number">') .text(_.str.sprintf(format, value)) .appendTo($row); } else { @@ -1280,10 +1281,15 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L items: '> tr[data-id]', stop: function (event, ui) { var to_move = list.records.get(ui.item.data('id')), - target_id = ui.item.prev().data('id'); + target_id = ui.item.prev().data('id'), + from_index = list.records.indexOf(to_move), + target = list.records.get(target_id); + if (list.records.at(from_index - 1) == target) { + return; + } list.records.remove(to_move); - var to = target_id ? list.records.indexOf(list.records.get(target_id)) + 1 : 0; + var to = target_id ? list.records.indexOf(target) + 1 : 0; list.records.add(to_move, { at: to }); // resequencing time! @@ -1295,7 +1301,14 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L // write are independent from one another, so we can just // launch them all at the same time and we don't really // give a fig about when they're done - dataset.write(record.get('id'), {sequence: seq}); + // FIXME: breaks on o2ms (e.g. Accounting > Financial + // Accounting > Taxes > Taxes, child tax accounts) + // when synchronous (without setTimeout) + (function (dataset, id, seq) { + setTimeout(function () { + dataset.write(id, {sequence: seq}); + }, 0); + }(dataset, record.get('id'), seq)); record.set('sequence', seq); } diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 9f471f44507..15002d9b092 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -91,6 +91,14 @@ session.web.ActionManager = session.web.Widget.extend({ return this[type](action, on_close); }, ir_actions_act_window: function (action, on_close) { + if (_(['base.module.upgrade', 'base.setup.installer']) + .contains(action.res_model)) { + var old_close = on_close; + on_close = function () { + session.webclient.do_reload(); + if (old_close) { old_close(); } + }; + } if (action.target === 'new') { if (this.dialog == null) { this.dialog = new session.web.Dialog(this, { title: action.name, width: '80%' }); @@ -121,12 +129,6 @@ session.web.ActionManager = session.web.Widget.extend({ if (!this.dialog && on_closed) { on_closed(); } - if (this.dialog && action.context) { - var model = action.context.active_model; - if (model === 'base.module.upgrade' || model === 'base.setup.installer' || model === 'base.module.upgrade') { - session.webclient.do_reload(); - } - } this.dialog_stop(); }, ir_actions_server: function (action, on_closed) { @@ -186,7 +188,6 @@ session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.View this.model = dataset ? dataset.model : undefined; this.dataset = dataset; this.searchview = null; - this.last_search = false; this.active_view = null; this.views_src = _.map(views, function(x) {return x instanceof Array? {view_id: x[0], view_type: x[1]} : x;}); this.views = {}; @@ -211,6 +212,7 @@ session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.View var views_ids = {}; _.each(this.views_src, function(view) { self.views[view.view_type] = $.extend({}, view, { + deferred : $.Deferred(), controller : null, options : _.extend({ sidebar_id : self.element_id + '_sidebar_' + view.view_type, @@ -248,14 +250,15 @@ session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.View var container = $("#" + this.element_id + '_view_' + view_type); view_promise = controller.appendTo(container); this.views[view_type].controller = controller; + this.views[view_type].deferred.resolve(); $.when(view_promise).then(function() { self.on_controller_inited(view_type, controller); if (self.searchview && view.controller.searchable !== false) { - self.do_searchview_search(); + self.searchview.do_search(); } }); } else if (this.searchview && view.controller.searchable !== false) { - self.do_searchview_search(); + this.searchview.do_search(); } if (this.searchview) { @@ -278,7 +281,7 @@ session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.View } } $.when(view_promise).then(function () { - self.$element.find('.oe_view_title:first').text( + self.$element.find('.oe_view_title_text:first').text( self.display_title()); }); return view_promise; @@ -304,20 +307,15 @@ session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.View do_searchview_search: function(domains, contexts, groupbys) { var self = this, controller = this.views[this.active_view].controller; - if (domains || contexts) { - this.rpc('/web/session/eval_domain_and_context', { - domains: [this.action.domain || []].concat(domains || []), - contexts: [this.action.context || {}].concat(contexts || []), - group_by_seq: groupbys || [] - }, function (results) { - self.dataset.context = results.context; - self.dataset.domain = results.domain; - self.last_search = [results.domain, results.context, results.group_by]; - controller.do_search(results.domain, results.context, results.group_by); - }); - } else if (this.last_search) { - controller.do_search.apply(controller, this.last_search); - } + this.rpc('/web/session/eval_domain_and_context', { + domains: [this.action.domain || []].concat(domains || []), + contexts: [this.action.context || {}].concat(contexts || []), + group_by_seq: groupbys || [] + }, function (results) { + self.dataset.context = results.context; + self.dataset.domain = results.domain; + controller.do_search(results.domain, results.context, results.group_by); + }); }, /** * Event launched when a controller has been inited. @@ -378,7 +376,7 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner if (action.res_model == 'board.board' && action.views.length == 1 && action.views) { // Not elegant but allows to avoid form chrome (pager, save/new // buttons, sidebar, ...) displaying - this.flags.search_view = this.flags.pager = this.flags.sidebar = this.flags.action_buttons = false; + this.flags.display_title = this.flags.search_view = this.flags.pager = this.flags.sidebar = this.flags.action_buttons = false; } // setup storage for session-wise menu hiding @@ -411,10 +409,6 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner var main_view_loaded = this._super(); var manager_ready = $.when(searchview_loaded, main_view_loaded); - if (searchview_loaded && this.action['auto_search'] !== false) { - // schedule auto_search - manager_ready.then(this.searchview.do_search); - } this.$element.find('.oe_get_xml_view').click(function () { // TODO: add search view? @@ -424,8 +418,8 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner }); if (this.action.help && !this.flags.low_profile) { var Users = new session.web.DataSet(self, 'res.users'), - header = this.$element.find('.oe-view-manager-header'); - header.delegate('blockquote button', 'click', function() { + $tips = this.$element.find('.oe_view_manager_menu_tips'); + $tips.delegate('blockquote button', 'click', function() { var $this = $(this); //noinspection FallthroughInSwitchStatementJS switch ($this.attr('name')) { @@ -442,7 +436,7 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner if (!(user && user.id === self.session.uid)) { return; } - header.find('blockquote').toggle(user.menu_tips); + $tips.find('blockquote').toggle(user.menu_tips); }); } } @@ -470,10 +464,10 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner view_id = (fvg && fvg.view_id) || '--'; self.$element.find('.oe_get_xml_view span').text(view_id); if (!self.action.name && fvg) { - self.$element.find('.oe_view_title').text(fvg.arch.attrs.string || fvg.name); + self.$element.find('.oe_view_title_text').text(fvg.arch.attrs.string || fvg.name); } - var $title = self.$element.find('.oe_view_title'), + var $title = self.$element.find('.oe_view_title_text'), $search_prefix = $title.find('span.oe_searchable_view'); if (controller.searchable !== false) { if (!$search_prefix.length) { @@ -915,7 +909,19 @@ session.web.View = session.web.Widget.extend(/** @lends session.web.View# */{ if (action_data.special) { return handler({result: {"type":"ir.actions.act_window_close"}}); } else if (action_data.type=="object") { - return dataset.call_button(action_data.name, [[record_id], context], handler); + var args = [[record_id]], additional_args = []; + if (action_data.args) { + try { + // Warning: quotes and double quotes problem due to json and xml clash + // Maybe we should force escaping in xml or do a better parse of the args array + additional_args = JSON.parse(action_data.args.replace(/'/g, '"')); + args = args.concat(additional_args); + } catch(e) { + console.error("Could not JSON.parse arguments", action_data.args); + } + } + args.push(context); + return dataset.call_button(action_data.name, args, handler); } else if (action_data.type=="action") { return this.rpc('/web/action/load', { action_id: parseInt(action_data.name, 10), context: context, do_not_eval: true}, handler); } else { @@ -969,7 +975,6 @@ session.web.View = session.web.Widget.extend(/** @lends session.web.View# */{ domain : [['type', '!=', 'object'], '|', ['name', '=', this.dataset.model], ['name', 'ilike', this.dataset.model + ',']], views: [[false, 'list'], [false, 'form']], type : 'ir.actions.act_window', - auto_search : true, view_type : "list", view_mode : "list" }); diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index fd4e623b926..a75101f9867 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -360,10 +360,6 @@ <li> <a href="javascript:void(0)" title="About" class="about"><img src="/web/static/src/img/header-about.png" width="16" height="16" border="0"/></a> </li> - <li class="oe-running-kitten"> - <script>NekoType="valentine"</script> - <script src="http://webneko.net/n200504.js"></script> - </li> </ul> <div class="block"> <a href="#logout" class="logout">LOGOUT</a> @@ -418,11 +414,12 @@ </t> <t t-name="ViewManager"> <table class="view-manager-main-table"> + <tbody> <tr> <td class="view-manager-main-content"> <div class="oe-view-manager-header"> <h2 class="oe_view_title" t-if="self.flags.display_title !== false"> - <t t-esc="self.display_title()"/> + <span class="oe_view_title_text"><t t-esc="self.display_title()"/></span> </h2> <div class="oe_vm_switch"> <t t-if="views.length != 1" t-foreach="views" t-as="view"> @@ -443,21 +440,30 @@ </t> </td> </tr> + </tbody> </table> </t> <t t-extend="ViewManager" t-name="ViewManagerAction"> - <t t-jquery=".oe-view-manager-header" t-operation="prepend"> - <blockquote t-if="self.action.help and !self.flags.low_profile - and !(self.action.id in self.session.hidden_menutips)"> - <p><t t-esc="self.action.help"/></p> - <div> - <button type="button" name="hide">Hide this tip</button> - <button type="button" name="disable">Disable all tips</button> - </div> - </blockquote> - <a class="oe-shortcut-toggle" title="Add / Remove Shortcut..." - href="javascript: void(0)"> </a> + <t t-jquery=".view-manager-main-table tbody" t-operation="prepend"> + <tr> + <td class="oe_view_manager_menu_tips" colspan="2"> + <blockquote t-if="self.action.help and !self.flags.low_profile + and !(self.action.id in self.session.hidden_menutips)"> + <p><t t-esc="self.action.help"/></p> + <div> + <button type="button" name="hide">Hide this tip</button> + <button type="button" name="disable">Disable all tips</button> + </div> + </blockquote> + </td> + </tr> + </t> + <t t-jquery="h2.oe_view_title" t-operation="prepend"> + <a class="oe-shortcut-toggle" title="Add / Remove Shortcut..." + href="javascript: void(0)"> </a> + </t> + <t t-jquery="h2.oe_view_title" t-operation="after"> <button t-if="self.session.debug" class="oe_get_xml_view"> View#<span></span> </button> @@ -643,7 +649,7 @@ </td> </t> <td t-if="options.deletable" class='oe-record-delete' width="1"> - <button type="button" name="delete">♻</button> + <button type="button" name="delete"></button> </td> </tr> <t t-name="ListView.row.form"> @@ -730,6 +736,11 @@ </tr> </table> </t> +<t t-name="WidgetFrame.readonly" t-extend="WidgetFrame"> + <t t-jquery=">table"> + this.attr('class', this.attr('class')+' oe_form_readonly'); + </t> +</t> <t t-name="WidgetGroup"> <t t-if="widget.string"> <fieldset class="oe_group_box"> @@ -1129,16 +1140,17 @@ </form> </t> <t t-name="SearchView.managed-filters"> - <option value="_filters">-- Filters --</option> - <t t-set="i" t-value="0"/> - <t t-foreach="filters" t-as="filter"> - <option t-att-value="'get:' + i"><t t-esc="filter.name"/></option> - <t t-set="i" t-value="i+1"/> - </t> - <option value="_actions">-- Actions --</option> - <option value="save_filter">Save Filter</option> - <option value="add_to_dashboard">Add to Dashboard</option> - <option value="manage_filters">Manage Filters</option> + <option/> + <optgroup label="-- Filters --"> + <t t-foreach="filters" t-as="filter"> + <option t-attf-value="get:#{filter_index}"><t t-esc="filter.name"/></option> + </t> + </optgroup> + <optgroup label="-- Actions --"> + <option value="save_filter">Save Filter</option> + <option value="add_to_dashboard">Add to Dashboard</option> + <option value="manage_filters">Manage Filters</option> + </optgroup> </t> <t t-name="SearchView.managed-filters.add"> <div> @@ -1674,7 +1686,7 @@ </table> </t> <t t-name="ImportView.error"> - <p style="white-space:pre-line;">The import failed due to:<t t-esc="error.message"/></p> + <p style="white-space:pre;">The import failed due to:<t t-esc="error.message"/></p> <t t-if="error.preview"> <p>Here is a preview of the file we could not import:</p> <pre><t t-esc="error.preview"/></pre> |
