diff options
| author | Vidhin Mehta (OpenERP) <vme@tinyerp.com> | 2011-09-14 11:07:46 +0530 |
|---|---|---|
| committer | Vidhin Mehta (OpenERP) <vme@tinyerp.com> | 2011-09-14 11:07:46 +0530 |
| commit | b6076c3cc3ca5141349b99821268b8fd5e148b77 (patch) | |
| tree | bb875d3ef5127cf5b8c35de6475de14e5477dbbd /addons/base/static/src | |
| parent | 243e1bdb0079ea9f214696ead8228d464ecb2cfc (diff) | |
| parent | c7c2b5846d3775780bbaa9a84a93ad755bdb8756 (diff) | |
[Merge] upto revno 1024.
bzr revid: vme@tinyerp.com-20110914053746-ri6d5s341mm6tc7n
Diffstat (limited to 'addons/base/static/src')
245 files changed, 0 insertions, 12817 deletions
diff --git a/addons/base/static/src/css/base-ie7.css b/addons/base/static/src/css/base-ie7.css deleted file mode 100644 index 35599dbdd4b..00000000000 --- a/addons/base/static/src/css/base-ie7.css +++ /dev/null @@ -1,4 +0,0 @@ - -.openerp .menu span { - min-width: 0px; -} diff --git a/addons/base/static/src/css/base.css b/addons/base/static/src/css/base.css deleted file mode 100644 index c9894e42cef..00000000000 --- a/addons/base/static/src/css/base.css +++ /dev/null @@ -1,1277 +0,0 @@ -/* TODO: separate openerp web client page css from openerp views css */ -body.openerp { - padding: 0; - margin: 0; - height: 100%; - min-width: 1000px; - overflow-y: scroll; - font-size: 80%; -} - -body.openerp, .openerp textarea, .openerp input, .openerp select, .openerp option, .openerp button, .openerp .ui-widget { - font-family: Ubuntu, Helvetica, sans-serif; -} - -.oe_box { - border: 1px solid #aaf; - padding: 2px; - margin: 2px; -} - -#oe_header h2 { - margin: 2px 0; -} - -#oe_errors pre { - margin: 0; -} - -.openerp .oe-number { - text-align: right !important; -} -.openerp .oe_hide { - display: none !important; -} - -/* STATES */ -.openerp .on_logged, -.openerp .db_options_row { - display: none; -} - -/* Loading */ -.openerp .loading { - display: none; - z-index: 100; - position: fixed; - top: 0; - right: 50%; - padding: 4px 12px; - background: #A61300; - color: white; - text-align: center; - border: 1px solid #900; - border-top: none; - -moz-border-radius-bottomright: 8px; - -moz-border-radius-bottomleft: 8px; - border-bottom-right-radius: 8px; - border-bottom-left-radius: 8px; -} -.openerp .oe_notification { - z-index: 1001; - display: none; -} -.openerp .oe_notification * { - color: white; -} - -/* Login */ -.openerp .login { - display: none; -} -.openerp .login form { - float: left; - width: 420px; - margin-left: 40px; - margin-bottom: 60px; -} -.openerp .login fieldset { - padding-bottom: 5px; - min-width: 100px; - margin-top: 60px; - border-radius: 10px; - -moz-border-radius: 10px; - -webkit-border-radius: 10px; -} -.openerp .login fieldset legend { - padding: 4px; -} -.openerp .login .oe_box2 { - padding: 5px 5px 20px 5px; -} -.openerp .login .oe_box2 table { - width: 100%; - border:none; -} -.openerp .login .oe_box2 td { - padding: 3px; - text-align: right; -} -.openerp .login .oe_box2 td input, -.openerp .login .oe_box2 td select { - width: 100%; -} -.openerp .login .oe_box2 td.oe_remember { - text-align:left; -} -.openerp .login .oe_box2 td.oe_remember input { - width: inherit; -} -.openerp .login .oe_login_right_pane { - padding:70px 35px 5px 10px; - min-width: 200px; - margin-left: 500px; -} -.openerp .login .login_error_message { - display: none; - background-color: #9A0404; - border-radius: 3px; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - color: white; - font-size: 16px; - font-weight: bold; - padding: 5px; - margin-top: 5px; - text-align: center; -} -.openerp .login.login_invalid .login_error_message { - display: block; -} - -.openerp.login-mode .login-container { - height: 100%; -} -.openerp.login-mode .login { - display: block; -} -.openerp.login-mode .menu, -.openerp.login-mode .secondary_menu, -.openerp.login-mode .oe-application, -.openerp.login-mode .db_options_row { - display: none; -} - -/* Database */ -.openerp.database_block .db_options_row { - height: 100%; - display: table-row; -} - -.openerp.database_block .menu, -.openerp.database_block .secondary_menu, -.openerp.database_block .oe-application, -.openerp.database_block .login-container { - display: none; -} - -.db_container { - width: 15%; - background: #666666; -} - -ul.db_options li { - padding: 5px 0 10px 5px; - background: #949292; /* Old browsers */ - background: -moz-linear-gradient(top, #949292 30%, #6d6b6b 95%, #282828 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(30%,#949292), color-stop(95%,#6d6b6b), color-stop(100%,#282828)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #949292 30%,#6d6b6b 95%,#282828 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #949292 30%,#6d6b6b 95%,#282828 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #949292 30%,#6d6b6b 95%,#282828 100%); /* IE10+ */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#949292', endColorstr='#282828',GradientType=0 ); /* IE6-9 */ - background: linear-gradient(top, #949292 30%,#6d6b6b 95%,#282828 100%); /* W3C */ - /* for ie9 */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#949292', endColorstr='#5B5A5A',GradientType=0 ); /* IE6-9 */ - border: none; - /* overriding jquery ui */ - -moz-border-radius: 0px; -webkit-border-radius: 0px; border-radius: 0px; - display: block; - font-weight: bold; - text-transform: uppercase; - margin: 1px; - color: #EEEEEE; - cursor: pointer; - width: 196px; - font-size: 12px; -} - -.db_option_table { - border: 1px solid #5A5858; - padding: 5px; - -moz-border-radius: 10px; -} - -table.db_option_table input.required { - background-color: #D2D2FF !important; -} - -.db_option_table input[type="text"], .db_option_table input[type="password"], .db_option_table select { - width: 300px; -} - -.option_string { - font-weight: bold; - color: #555; - width: 100%; - text-align: center; - padding: 10px 0; - font-size: large; -} - -label.error { - float: none; - color: red; - padding-left: .5em; - vertical-align: top; -} - -/* Main*/ -.openerp .main_table { - width: 100%; - height: 100%; - background: #f0eeee; -} - -/* Menu */ -.openerp .sf-menu { - margin-bottom: 0; -} -/* -.sf-menu a { - padding: 5px 5px; -} -*/ - -.openerp .menu { - height: 34px; - background: #cc4e45; /* Old browsers */ - background: -moz-linear-gradient(top, #cc4e45 0%, #b52d20 8%, #7a211a 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#cc4e45), color-stop(8%,#b52d20), color-stop(100%,#7a211a)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #cc4e45 0%,#b52d20 8%,#7a211a 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #cc4e45 0%,#b52d20 8%,#7a211a 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #cc4e45 0%,#b52d20 8%,#7a211a 100%); /* IE10+ */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#CC4E45', endColorstr='#7A211A',GradientType=0 ); /* IE6-9 */ - background: linear-gradient(top, #cc4e45 0%,#b52d20 8%,#7a211a 100%); /* W3C */ -} -.openerp .menu td { - text-align: center; - padding:0; -} -.openerp .menu a { - display:block; - min-width: 60px; - height: 20px; - margin: 3px 2px; - padding: 0 8px; - - background: #bd5e54; /* Old browsers */ - background: -moz-linear-gradient(top, #bd5e54 0%, #90322a 60%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#bd5e54), color-stop(60%,#90322a)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #bd5e54 0%,#90322a 60%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #bd5e54 0%,#90322a 60%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #bd5e54 0%,#90322a 60%); /* IE10+ */ - 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-radius: 4px; - -moz-border-radius: 4px; - -webkit-border-radius: 4px; - - color: #eee; - text-shadow: #222 0 1px 0; - text-decoration: none; - text-transform: uppercase; - line-height: 20px; - font-weight: bold; - font-size: 85%; - - white-space: nowrap; -} -.openerp .menu a:hover, -.openerp .menu a:focus, -.openerp .menu a.active { - background: #c6c6c6; /* Old browsers */ - background: -moz-linear-gradient(top, #c6c6c6 0%, #5c5c5c 7%, #969595 86%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#c6c6c6), color-stop(7%,#5c5c5c), color-stop(86%,#969595)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #c6c6c6 0%,#5c5c5c 7%,#969595 86%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #c6c6c6 0%,#5c5c5c 7%,#969595 86%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #c6c6c6 0%,#5c5c5c 7%,#969595 86%); /* IE10+ */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#C6C6C6', endColorstr='#969595',GradientType=0 ); /* IE6-9 */ - background: linear-gradient(top, #c6c6c6 0%,#5c5c5c 7%,#969595 86%); /* W3C */ - /* for ie */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#5c5c5c', endColorstr='#969595',GradientType=0 ); /* IE6-9 */ - - color: #fff; -} -/* Secondary Menu */ -.openerp .secondary_menu { - width: 200px; - min-width: 200px; - border-right: 1px solid #3C3C3C; - border-bottom: 1px solid #5A5858; - background: #5A5858; - vertical-align: top; - height: 100%; -} -.openerp .secondary_menu .menu_content { - padding: 0; - border: none; - background: none; - overflow: hidden; -} -.openerp .secondary_menu h3 { - padding: 0 0 2px; - background: #949292; /* Old browsers */ - background: -moz-linear-gradient(top, #949292 0%, #6d6b6b 87%, #282828 99%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#949292), color-stop(87%,#6d6b6b), color-stop(99%,#282828)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #949292 0%,#6d6b6b 87%,#282828 99%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #949292 0%,#6d6b6b 87%,#282828 99%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #949292 0%,#6d6b6b 87%,#282828 99%); /* IE10+ */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#949292', endColorstr='#282828',GradientType=0 ); /* IE6-9 */ - background: linear-gradient(top, #949292 0%,#6d6b6b 87%,#282828 99%); /* W3C */ - /* for ie9 */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#949292', endColorstr='#5B5A5A',GradientType=0 ); /* IE6-9 */ - border: none; - /* overriding jquery ui */ - -moz-border-radius: 0px; -webkit-border-radius: 0px; border-radius: 0px; -} -.openerp .secondary_menu h4 { - padding: 0 0 2px 10px; - border: none; - background: none; -} -.openerp .secondary_menu h3 span, .openerp .secondary_menu h4 span { - left: 0 !important; -} -.openerp .secondary_menu a { - display: block; - height: 20px; - padding: 0 5px; - line-height: 20px; - white-space: nowrap; - color: white; - text-decoration: none; - text-shadow: 0 1px 0 #333; -} -.openerp .secondary_menu a.leaf:hover, -.openerp .secondary_menu a.leaf:active, -.openerp .secondary_menu a.leaf.active, -.openerp .secondary_menu h4:hover, -.openerp .secondary_menu h4:active, -.openerp .secondary_menu h4.active { - background: #ffffff; /* Old browsers */ - background: -moz-linear-gradient(top, #ffffff 0%, #d8d8d8 11%, #afafaf 86%, #333333 91%, #5a5858 96%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(11%,#d8d8d8), color-stop(86%,#afafaf), color-stop(91%,#333333), color-stop(96%,#5a5858)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%,#5a5858 96%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%,#5a5858 96%); /* Opera11.10+ */ - 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 */ - /* overriding jquery ui */ - -moz-border-radius-topright: 0; -webkit-border-top-right-radius: 0; border-top-right-radius: 0; - color: #3f3d3d; - text-shadow: #fff 0 1px 0; - border: none !important; -} - -.openerp .secondary_menu h4:hover a, -.openerp .secondary_menu h4:active a, -.openerp .secondary_menu h4.active a { - color: #3f3d3d; - text-shadow: #fff 0 1px 0; - border: none !important; -} -.openerp div.submenu_accordion div.menu_content a span { - padding-left: 20px; -} - -/* Header */ -.openerp .header { - height: 65px; - background: url("/base/static/src/img/header-background.png") repeat-x scroll left top transparent; - color: #FFFFFF; - letter-spacing: 0.5px; - text-shadow: 0 1px 0 #333333; -} -.openerp .company_logo_link { - display: block; - float: left; - height: 63px; - width: 200px; - border: 1px solid white; - border-right-color: black; - border-bottom-color: black; - background: #FFFFFF; - background: -moz-linear-gradient(top, #FFFFFF 0%, #CECECE 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#FFFFFF), color-stop(100%,#CECECE)); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#FFFFFF', endColorstr='#CECECE',GradientType=0 ); -} -.openerp .company_logo { - margin-top: 7px; - margin-left: 10px; - display: block; - background: url(/base/static/src/img/logo.png); - width:180px; - height:46px; -} -.openerp .header_title { - float: left; - font-size: 100%; - margin: 0; - padding: 4px 0; - text-shadow: 0 1px 0 #111111; -} -.openerp .header_title small { - color: #ccc; - font-size: 90%; - font-weight: normal; -} -.openerp .header_corner { - float: right; -} -.openerp .header_corner .block { - float: left; - height: 34px; - line-height: 34px; - /*background: url(../images/top-sep-a.png) no-repeat;*/ - border-left: 1px solid #6a6a6a; - background: #828282; - background: -moz-linear-gradient(top, #828282 0%, #4D4D4D 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#828282), color-stop(100%,#4D4D4D)); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#828282', endColorstr='#4D4D4D',GradientType=0 ); -} -.openerp .header_corner .block a { - display: block; - color: white; - text-decoration: none; - padding: 0 10px; -} -.openerp .header_corner .block a:hover { - background: #929292; - background: -moz-linear-gradient(top, #929292 0%, #4D4D4D 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#929292), color-stop(100%,#4D4D4D)); - 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; -} -.openerp .header_corner ul.block li a { - padding: 0 5px; - position: relative; - line-height: 32px; -} -.openerp .header_corner ul.block li a img { - vertical-align: middle; -} -.openerp .header_corner ul.block li a small { - position: absolute; - right: 0; - top: 5px; - padding: 1px 4px 2px; - background: rgba(0, 0, 0, 0.75); - border-radius: 7px; - -moz-border-radius: 7px; - -webkit-border-radius: 7px; - line-height: 1em; - font-weight: bold; -} - -/* Footer */ -.openerp div.oe_footer { - background: none repeat scroll 0 0 #CCCCCC; - overflow: hidden; - padding: 5px 0; - position: relative; - -moz-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.4); - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.4); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.4); -} -.openerp div.oe_footer p.oe_footer_powered { - left: 50%; - margin: 0; - padding: 0 15px; - color: #666666; - font-weight: bold; - font-size: 0.8em; - text-align: center; -} -.openerp div.oe_footer p.oe_footer_powered a { - text-decoration: none; - color: #666666; -} - -/* Main Application */ -.openerp .oe-main-content, -.openerp .oe-application { - padding: 0; - height: 100%; -} - -.openerp h2.oe_view_title { - font-size: 175%; - font-weight: normal; - margin: 2px 0; - color: #252424; - text-shadow: white 0 1px 0; -} - -/* View Manager */ -.openerp .oe_vm_switch { - float: right; -} - -/* SearchView */ -.openerp .filter_label, .openerp .filter_icon { - border: 1px solid #666; - border-left-width: 0; - background: #F0F0F0; - 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 ); -} -.openerp .filter_label:hover, .openerp .filter_icon:hover { - background: #F0F0F0; - background: -moz-linear-gradient(top, #F0F0F0 0%, #A1A7CE 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#F0F0F0), color-stop(100%,#A1A7CE)); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#F0F0F0', endColorstr='#A1A7CE',GradientType=0 ); -} -.openerp .filter_label:active, .openerp .filter_icon:active { - background: #AAAAAA; - 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; -} -.openerp .filter_icon { - height: 22px; - padding: 1px 2px 0 2px; - margin: 0; - vertical-align: bottom; -} -.openerp .filter_label { - font-weight: bold; - text-transform: uppercase; - text-shadow: #EEE 0 1px 0; - color: #4C4C4C; - white-space: nowrap; - min-height: 40px; - min-width: 75px; - padding: 2px 4px; - margin: 0; -} -.openerp .filter_label_group { - padding-right: 0.4em; - 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; -} -.openerp .filter_label_group button:last-child { - -webkit-border-top-right-radius: 7px; - -webkit-border-bottom-right-radius: 7px; - -moz-border-radius-topright: 7px; - -moz-border-radius-bottomright: 7px; - border-top-right-radius: 7px; - border-bottom-right-radius: 7px; -} - -.openerp .searchview_group_string { - display: block; - color: #7D7979; - font-weight: bold; - padding: 2px 0 2px 10px; - margin-top: 4px; - text-decoration: none; -} -.openerp .searchview_group_string:hover { - background-color: #ccc; -} -.openerp .searchview_group.folded .searchview_group_string { - background: url("/base/static/src/img/ui/group-folded.png") no-repeat scroll 0 50%; -} -.openerp .searchview_group.folded .searchview_group_content { - display: none; -} -.openerp .searchview_group.expanded .searchview_group_string { - background: url("/base/static/src/img/ui/group-expanded.png") no-repeat scroll 0 50%; -} -.openerp .searchview_group.expanded .searchview_group_content { - display: block; -} -.openerp .searchview_group_content { - padding-left: 10px; -} - -.openerp .searchview_extended_group { - padding: 3px; - margin: 2px; -} - -.openerp .searchview_extended_group .oe_adv_filters_and { - border-bottom: 1px solid #8E8E8E; - text-align: center; - margin-top: -10px; -} -.openerp .searchview_extended_group .oe_adv_filters_and span { - background: #F0EEEE; - position: relative; - top: 0.5em; - padding: 0 1em 0 1em; - color: #8E8E8E; -} - -.openerp .searchview_extended_group.last_group .oe_adv_filters_and { - display: none; -} - -.openerp .oe_search-view-custom-filter-btn span { - background: url(/base/static/src/img/icons/gtk-add.png) repeat-y; - padding-left: 18px; -} - -.openerp .searchview_extended_add_proposition span { - font-size: 0.9em; - background: url(/base/static/src/img/icons/gtk-add.png) repeat-y; - padding-left: 18px; -} - -.openerp .searchview_extended_delete_group { - float:right; - display: none; -} - -.openerp .searchview_extended_delete_prop { - text-decoration: none; -} - -.openerp .searchview_extended_delete_group span, -.openerp .searchview_extended_delete_prop span { - font-size: 0.9em; - background: url(/base/static/src/img/icons/gtk-close.png) repeat-y; - padding-left: 18px; -} -/* List */ -.openerp .oe-listview table { - clear: right; - width: 100%; - border-spacing: 0; - border: 1px solid silver; -} - -.openerp .oe-listview thead table { - width: 100%; - border: none; -} -.openerp .oe-listview tr.odd { - background-color: #f3f3f3; -} -.openerp .oe-listview tbody tr:hover { - background-color: #ecebf2; -} -.openerp .oe-listview tbody tr:hover { - background-color: #eae9f0; -} -.openerp .oe-listview thead table tr, -.openerp .oe-listview thead table tr:hover { - background: none; -} - -.openerp .oe-listview td, -.openerp .oe-listview th { - vertical-align: middle; - text-align: left; -} -.openerp .oe-listview td.oe-record-delete { - text-align: right; -} -.openerp .oe-listview th.oe-sortable { - cursor: pointer; -} -.openerp .oe-listview th.oe-sortable .ui-icon { - height: 1em; - display: inline; - display: inline-block; -} - -.openerp .oe-listview .oe-field-cell { - cursor: pointer; -} -.openerp .oe-listview .oe-field-cell button { - padding: 0; - border: none; - background: none; - width: 100%; -} -.openerp .oe-listview .oe-field-cell button:active { - opacity: 0.5; -} -.openerp .oe-listview .oe-field-cell button img { - cursor: pointer; -} -.openerp .oe-listview .oe-field-cell button img:hover { - opacity: 0.75; -} - -.openerp .oe-listview th.oe-actions { - text-align: left; - white-space: nowrap; -} -.openerp .oe-listview th.oe-list-pager { - text-align: right; - white-space: nowrap; -} -.openerp .oe-list-pager .oe-pager-state { - cursor: pointer; -} - -.openerp .oe-listview .oe-group-name { - padding-right: 1em; -} -.openerp .oe-listview .oe-group-name, -.openerp .oe-listview .oe-group-pagination { - white-space: nowrap; -} - -.openerp .oe-listview tfoot td { - padding: 3px 3px 0; -} -.openerp .oe-listview .oe-list-footer { - text-align: center; - white-space: nowrap; -} -.openerp .oe-listview .oe-list-footer span { - margin: 0 1em; -} - -/** list rounded corners - - rounded corners are a pain on tables: need to round not only table, but - also on the first and last children of the first and last row - */ -.openerp .oe-listview table.oe-listview-content { - -webkit-border-radius: 7px; - -moz-border-radius: 7px; - border-radius: 7px; -} -.openerp .oe-listview table.oe-listview-content thead tr:first-child th:first-child { - -webkit-border-top-left-radius: 7px; - -moz-border-radius-topleft: 7px; - border-top-left-radius: 7px; -} -.openerp .oe-listview table.oe-listview-content thead tr:first-child th:last-child { - -webkit-border-top-right-radius: 7px; - -moz-border-radius-topright: 7px; - border-top-right-radius: 7px; -} -.openerp .oe-listview table.oe-listview-content tfoot td:first-child, -.openerp .oe-listview table.oe-listview-content tbody:last-child tr:last-child th:first-child { - -webkit-border-bottom-left-radius: 7px; - -moz-border-radius-bottomleft: 7px; - border-bottom-left-radius: 7px; -} -.openerp .oe-listview table.oe-listview-content tfoot td:last-child, -.openerp .oe-listview table.oe-listview-content tbody:last-child tr:last-child td:last-child { - -webkit-border-bottom-right-radius: 7px; - -moz-border-radius-bottomright: 7px; - border-bottom-right-radius: 7px; -} - -/* Notebook */ -.openerp .oe_form_notebook { - padding: 0; - background: none; - border-width: 0; -} -.openerp .oe_form_notebook ul.ui-tabs-nav { - padding-left: 0; - background: transparent; - border-width: 0 0 1px 0; - border-radius: 0; - -moz-border-radius: 0; - -webkit-border-radius: 0; - line-height: 0.5em; -} -.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; -} -.openerp .oe_form_notebook .ui-tabs-selected { - background: #f9f9f9; -} - -/* Form */ -.openerp table.oe_frame td { - color: #4c4c4c; -} -.openerp td.oe_form_frame_cell { - padding: 2px; -} -.openerp td.oe_form_frame_cell.oe_form_group { - padding: 0px; -} -.openerp .required.error { - border: 1px solid #900; -} -.openerp .oe_form_buttons, .openerp .oe_list_buttons { - float: left; -} -.openerp .oe_form_pager, .openerp .oe_list_pager { - float: right; -} - -.openerp label.oe_label_help, .openerp label.oe_label { - display: block; -} -.openerp label.oe_label_help { - cursor: help; -} -.openerp .oe_form_field label.oe_label, .openerp .oe_form_field label.oe_label_help { - text-align: right; - margin: 3px 0 0 10px; -} -.openerp label.oe_label_help span { - font-size: 80%; - color: darkgreen; - vertical-align:top; - position: relative; - top: -4px; - padding: 0 2px; -} - -/* 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; - border: 1px solid #999; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - border-radius: 3px; - background: white; - min-width: 90px; - color: #1f1f1f; -} -.openerp .oe_forms textarea { - resize:vertical; -} -.openerp .oe_forms input[type="text"], .openerp .oe_forms input[type="password"], .openerp .oe_forms select, .openerp .oe_forms .button { - height: 22px; -} -.openerp .oe_forms input.field_datetime { - min-width: 11em; -} -.openerp .oe_forms .button { - color: #4c4c4c; - white-space: nowrap; -} -.openerp .oe_forms .button span { - position: relative; - vertical-align: top; -} -.openerp img.ui-datepicker-trigger { - margin-left: -20px; - vertical-align: middle; - cursor: pointer; - position: relative; - top: -1px; -} -.openerp img.oe_field_translate { - margin-left: -21px; - vertical-align: top; - cursor: pointer; - position: relative; - top: 4px; -} -.openerp .oe_trad_field.touched { - border: 1px solid green !important; -} - -/* http://www.quirksmode.org/dom/inputfile.html - * http://stackoverflow.com/questions/2855589/replace-input-type-file-by-an-image - */ -.openerp .oe-binary-file-set { - overflow: hidden; - position: relative; -} -.openerp input.oe-binary-file { - z-index: 2; - line-height: 0; - font-size: 50px; - position: absolute; - /* Should be adjusted for all browsers */ - top: -2px; - left: -700px; - opacity: 0; - filter: alpha(opacity = 0); - -ms-filter: "alpha(opacity=0)"; - margin: 0; - padding:0; -} - -/* Widgets */ -.openerp .separator { - border: 0 solid #666; -} -.openerp .separator.horizontal { - font-weight: bold; - border-bottom-width: 1px; - margin: 3px 4px 3px 1px; - height: 15px; -} -.openerp .oe_form_frame_cell.oe_form_separator_vertical { - border-left: 1px solid #666; -} -.openerp td.required input, .openerp td.required select { - background-color: #D2D2FF !important; -} -.openerp td.invalid input, .openerp td.invalid select, .openerp td.invalid textarea { - background-color: #F66 !important; - border: 1px solid #D00 !important; -} -.openerp div.oe-progressbar span { - position: absolute; - margin-left: 10px; - margin-top: 5px; - font-weight: bold; -} - -/* jQuery UI override */ -.openerp .ui-widget { - font-size: 1em; -} -.openerp .oe_form_field_progressbar .ui-progressbar { - height: 22px; - font-size: 10px; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - border: 1px solid #999; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - border-radius: 3px; - background: white; - min-width: 90px; -} - -/* Sidebar */ -.openerp .view-manager-main-table { - margin: 0; - width:100%; - border-collapse:collapse; - height:100%; -} - -.openerp .view-manager-main-table tbody { - vertical-align: top; -} - -.openerp .view-manager-main-content { - width: 100%; - padding: 6px; -} - -.openerp .view-manager-main-sidebar { - width: 180px; - padding: 0; - margin: 0; -} - -.openerp .sidebar-main-div { - height: 100%; - border-left: 1px solid #D2CFCF; -} - -.openerp .sidebar-content { - padding: 0; - margin: 0; - width: 180px; - height: 100%; - font-size: 0.9em; -} - -.openerp .closed-sidebar .sidebar-content { - width: 22px; -} - -.openerp .closed-sidebar .sidebar-content { - display: none; -} - -.openerp .sidebar-main-div a { - color: #555; - text-decoration: none; -} - -.openerp .sidebar-main-div a:hover { - color: black; -} - -.openerp .oe-sidebar-attachments-toolbar { - margin: 4px 0 0 4px; -} -.openerp .oe-sidebar-attachments-items { - clear: both; - padding-top: 5px !important; -} -.openerp .oe-sidebar-attachments-items li { - position: relative; - padding: 0 0 3px 10px !important; -} -.openerp .oe-sidebar-attachments-items li:hover { - background: #ddd; -} -.openerp .oe-sidebar-attachments-link { - display: block; - margin-right: 15px; - overflow: hidden; -} -.openerp .oe-sidebar-attachment-delete { - position: absolute; - right: 2px; - top: 1px; - overflow: hidden; - width: 15px; - height: 15px; - padding: 1px; - border-radius: 7px; - -moz-border-radius: 7px; - -webkit-border-radius: 7px; -} -.openerp .oe-sidebar-attachment-delete:hover { - background-color: white; -} - -.openerp .view-manager-main-sidebar h2 { - margin:0; - font-size: 1.15em; - color: #8E8E8E; - text-shadow: white 0 1px 0; - padding-left: 10px; - padding-right: 21px; - height: 21px; - - background: #ffffff; /* Old browsers */ - background: -moz-linear-gradient(top, #ffffff 0%, #ebe9e9 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(100%,#ebe9e9)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* IE10+ */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#FFFFFF', endColorstr='#EBE9E9',GradientType=0 ); /* IE6-9 */ - background: linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* W3C */ - - border: 1px solid #D2CFCF; - border-right-width: 0; - border-left-width: 0; -} - -.openerp .view-manager-main-sidebar ul { - list-style-type: none; - margin: 0; - padding: 0; - display: block; -} - -.openerp .view-manager-main-sidebar li { - display: block; - padding: 3px 3px 3px 10px; -} - -.openerp .toggle-sidebar { - cursor: pointer; - border: 1px solid #D2CFCF; - display: block; - background: url(/base/static/src/img/toggle-a-bg.png); - width: 21px; - height: 21px; - z-index: 10; -} -.openerp .open-sidebar .toggle-sidebar { - margin-left: 158px; - background-position: 21px 0; - position: absolute; -} -.openerp .closed-sidebar .toggle-sidebar { - border-left: none; -} -.openerp li.oe_sidebar_print { - padding-left: 20px; - background: 1px 3px url(/base/static/src/img/icons/gtk-print.png) no-repeat; -} - -.openerp.kitten-mode-activated .main_table { - background: url(http://placekitten.com/g/1500/800) repeat; -} - -.openerp.kitten-mode-activated .header { - background: url(http://placekitten.com/g/211/65) repeat; -} - -.openerp.kitten-mode-activated .secondary_menu { - background: url(http://placekitten.com/g/212/100) repeat; -} - -.openerp.kitten-mode-activated .menu { - background: #828282; - background: -moz-linear-gradient(top, #828282 0%, #4D4D4D 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#828282), color-stop(100%,#4D4D4D)); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#828282', endColorstr='#4D4D4D',GradientType=0 ); -} -.openerp.kitten-mode-activated .menu a { - background: none; -} -.openerp.kitten-mode-activated .menu span { - background: none; -} -.openerp.kitten-mode-activated .sidebar-content li a, -.openerp.kitten-mode-activated .oe-application .view-manager-main-content h2.oe_view_title, -.openerp.kitten-mode-activated .oe-application .view-manager-main-content a.searchview_group_string, -.openerp.kitten-mode-activated .oe-application .view-manager-main-content label { - color: white; -} -.openerp.kitten-mode-activated .menu, -.openerp.kitten-mode-activated .header_corner, -.openerp.kitten-mode-activated .header_title, -.openerp.kitten-mode-activated .secondary_menu div, -.openerp.kitten-mode-activated .oe-application, -.openerp.kitten-mode-activated .oe_footer, -.openerp.kitten-mode-activated .loading, -.openerp.kitten-mode-activated .ui-dialog { - opacity:0.8; - filter:alpha(opacity=80); -} -.openerp.kitten-mode-activated .header .company_logo { - background: url(http://placekitten.com/g/180/46); -} -.openerp.kitten-mode-activated .loading { - background: #828282; - border-color: #828282; -} - -.openerp .oe-m2o { - padding-right: 20px; - white-space: nowrap; -} -.openerp .oe_forms .oe-m2o input[type="text"] { - padding-right: 20px; -} -.openerp .oe-m2o-drop-down-button { - margin-left: -23px; -} -.openerp .oe-m2o-drop-down-button img, -.openerp .oe-m2o-cm-button img { - margin-bottom: -4px; - cursor: pointer; -} -.openerp .oe-m2o-cm-button img { - margin-left: 4px; -} -.openerp .oe-m2o-disabled-cm { - color: grey; -} -.parent_top { - vertical-align: text-top; -} - -.openerp .oe-dialog-warning p { - padding-left: 1em; - font-size: 1.2em; - font-weight: bold; -} - -.openerp .dhx_mini_calendar { - -moz-box-shadow: none; - -khtml-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; -} -.openerp .oe-treeview-table { - width: 100%; -} -.treeview-tr, .treeview-td { - cursor: pointer; - vertical-align: top; - text-align: left; -} -.treeview-tr span, .treeview-td span { - display: block; -} -.treeview-tr:first-of-type { - background: transparent url(/base/static/src/img/expand.gif) 0 50% no-repeat; -} -.oe-open .treeview-tr:first-of-type { - background-image: url(/base/static/src/img/collapse.gif); -} -.treeview-tr:first-of-type span, -.treeview-td:first-of-type span { - margin-left: 16px; -} - -.treeview-header { - text-align: left; - vertical-align: top; -} -/* Shortcuts*/ -.oe-shortcut-toggle { - height: 20px; - padding: 0; - width: 24px; - cursor: pointer; - display: block; - background: url(/base/static/src/img/add-shortcut.png) no-repeat bottom; - float: left; -} -.oe-shortcut-remove{ - background: url(/base/static/src/img/remove-shortcut.png) no-repeat bottom; -} -/* ================ */ -.oe-shortcuts { - position: absolute; - - margin: 0; - padding: 6px 5px; - top: 37px; - left: 197px; - right: 0; - height: 17px; - line-height: 1.2; -} -.oe-shortcuts ul { - display: block; - overflow: hidden; - list-style: none; - white-space: nowrap; - padding: 0; - margin: 0; -} -.oe-shortcuts li { - cursor: pointer; - display: -moz-inline-stack; - display: inline-block; - display: inline; /*IE7 */ - color: #fff; - text-align: center; - border-left: 1px solid #909090; - padding: 4px; - font-size: 90%; - font-weight: normal; -} -.oe-shortcuts li:first-child { - border-left: none; - padding-left: 0; -} diff --git a/addons/base/static/src/css/data_export.css b/addons/base/static/src/css/data_export.css deleted file mode 100644 index 7b4b9707b39..00000000000 --- a/addons/base/static/src/css/data_export.css +++ /dev/null @@ -1,85 +0,0 @@ -.openerp .oe_export_row tr{ - background-color: #FFFFFF; - font-size: 0.8em; - height: 22px; -} - -.openerp tr.ui-selected td { - background-color: #CCCCCC; -} - -.openerp .oe_export_requiredfield { - background-color: #D2D2FF; -} - -.openerp .oe_export_readonlyfield{ - background-color: #999999; -} - -.openerp .oe_export_row:hover{ - background-color: #F3F3F3; -} - -.openerp .oe_export_fields_selector_export { - width: 100%; - height: 400px; -} - -.openerp .oe_export_fields_selector_left { - width: 50%; -} - -.openerp div#left_field_panel { - overflow: scroll; - width: 100%; - height: 400px; - border: solid #999999 1px; -} - -.openerp .oe_export_fields_selector_center { - width: 102px; -} - -.openerp .oe_export_fields_selector_right { - width: 45%; - height: 400px; -} - -.openerp .oe_export_fields_selector_export select{ - width: 100%; - height: 100%; -} - -.openerp .oe_export_tree_header{ - border: 0.5px solid #E3E3E3; - text-align: left; - white-space: nowrap; - padding: 4px 5px; - background: url(/base/static/src/img/header.gif); -} - - -.openerp table.tree_grid{ - border: 1px solid #E3E3E3; - text-align: left; - white-space: nowrap; - background-color:#E3E3E3; - border-collapse: collapse; - width: 100%; -} - -.openerp table.tree_grid a:hover { - color: blue; - border: none; -} - -.openerp table.tree_grid a { - color: #5F5C5C; - border: none; - display: block; -} - -.openerp .oe_export_button_export { - border: 1px solid #006; - background-color: #F3F3F3; -} diff --git a/addons/base/static/src/img/accessories-archiver.png b/addons/base/static/src/img/accessories-archiver.png Binary files differdeleted file mode 100644 index 8bcbe4566bc..00000000000 --- a/addons/base/static/src/img/accessories-archiver.png +++ /dev/null diff --git a/addons/base/static/src/img/add-shortcut.png b/addons/base/static/src/img/add-shortcut.png Binary files differdeleted file mode 100644 index bcc0a09eb45..00000000000 --- a/addons/base/static/src/img/add-shortcut.png +++ /dev/null diff --git a/addons/base/static/src/img/attachments-close.png b/addons/base/static/src/img/attachments-close.png Binary files differdeleted file mode 100644 index 14d645534b8..00000000000 --- a/addons/base/static/src/img/attachments-close.png +++ /dev/null diff --git a/addons/base/static/src/img/collapse.gif b/addons/base/static/src/img/collapse.gif Binary files differdeleted file mode 100644 index 759e72ebcfe..00000000000 --- a/addons/base/static/src/img/collapse.gif +++ /dev/null diff --git a/addons/base/static/src/img/db.png b/addons/base/static/src/img/db.png Binary files differdeleted file mode 100644 index 83e42df26b3..00000000000 --- a/addons/base/static/src/img/db.png +++ /dev/null diff --git a/addons/base/static/src/img/down-arrow.png b/addons/base/static/src/img/down-arrow.png Binary files differdeleted file mode 100644 index b1288e52682..00000000000 --- a/addons/base/static/src/img/down-arrow.png +++ /dev/null diff --git a/addons/base/static/src/img/expand.gif b/addons/base/static/src/img/expand.gif Binary files differdeleted file mode 100644 index ca98d0b5f2b..00000000000 --- a/addons/base/static/src/img/expand.gif +++ /dev/null diff --git a/addons/base/static/src/img/favicon.ico b/addons/base/static/src/img/favicon.ico Binary files differdeleted file mode 100644 index a323cc21c00..00000000000 --- a/addons/base/static/src/img/favicon.ico +++ /dev/null diff --git a/addons/base/static/src/img/header-about.png b/addons/base/static/src/img/header-about.png Binary files differdeleted file mode 100644 index b53e9a86ebe..00000000000 --- a/addons/base/static/src/img/header-about.png +++ /dev/null diff --git a/addons/base/static/src/img/header-background.png b/addons/base/static/src/img/header-background.png Binary files differdeleted file mode 100644 index 774b3954124..00000000000 --- a/addons/base/static/src/img/header-background.png +++ /dev/null diff --git a/addons/base/static/src/img/header-help.png b/addons/base/static/src/img/header-help.png Binary files differdeleted file mode 100644 index 19e9906fdef..00000000000 --- a/addons/base/static/src/img/header-help.png +++ /dev/null diff --git a/addons/base/static/src/img/header-home.png b/addons/base/static/src/img/header-home.png Binary files differdeleted file mode 100644 index fd96742d15a..00000000000 --- a/addons/base/static/src/img/header-home.png +++ /dev/null diff --git a/addons/base/static/src/img/header-preferences.png b/addons/base/static/src/img/header-preferences.png Binary files differdeleted file mode 100644 index 6c978b49f55..00000000000 --- a/addons/base/static/src/img/header-preferences.png +++ /dev/null diff --git a/addons/base/static/src/img/header-requests.png b/addons/base/static/src/img/header-requests.png Binary files differdeleted file mode 100644 index 6577e7e6448..00000000000 --- a/addons/base/static/src/img/header-requests.png +++ /dev/null diff --git a/addons/base/static/src/img/header.gif b/addons/base/static/src/img/header.gif Binary files differdeleted file mode 100644 index f40bd9c0f6a..00000000000 --- a/addons/base/static/src/img/header.gif +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_ABOUT.png b/addons/base/static/src/img/icons/STOCK_ABOUT.png Binary files differdeleted file mode 100644 index 1b430a35758..00000000000 --- a/addons/base/static/src/img/icons/STOCK_ABOUT.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_ADD.png b/addons/base/static/src/img/icons/STOCK_ADD.png Binary files differdeleted file mode 100644 index 70612c181c6..00000000000 --- a/addons/base/static/src/img/icons/STOCK_ADD.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_APPLY.png b/addons/base/static/src/img/icons/STOCK_APPLY.png Binary files differdeleted file mode 100644 index 116f2e433bb..00000000000 --- a/addons/base/static/src/img/icons/STOCK_APPLY.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_BOLD.png b/addons/base/static/src/img/icons/STOCK_BOLD.png Binary files differdeleted file mode 100644 index 408f25aa20b..00000000000 --- a/addons/base/static/src/img/icons/STOCK_BOLD.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_CANCEL.png b/addons/base/static/src/img/icons/STOCK_CANCEL.png Binary files differdeleted file mode 100644 index 8cf6273281b..00000000000 --- a/addons/base/static/src/img/icons/STOCK_CANCEL.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_CDROM.png b/addons/base/static/src/img/icons/STOCK_CDROM.png Binary files differdeleted file mode 100644 index 27e8edd8a0b..00000000000 --- a/addons/base/static/src/img/icons/STOCK_CDROM.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_CLEAR.png b/addons/base/static/src/img/icons/STOCK_CLEAR.png Binary files differdeleted file mode 100644 index b2874fb84fa..00000000000 --- a/addons/base/static/src/img/icons/STOCK_CLEAR.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_CLOSE.png b/addons/base/static/src/img/icons/STOCK_CLOSE.png Binary files differdeleted file mode 100644 index 4966974e178..00000000000 --- a/addons/base/static/src/img/icons/STOCK_CLOSE.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_COLOR_PICKER.png b/addons/base/static/src/img/icons/STOCK_COLOR_PICKER.png Binary files differdeleted file mode 100644 index 232d54f8f3b..00000000000 --- a/addons/base/static/src/img/icons/STOCK_COLOR_PICKER.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_CONNECT.png b/addons/base/static/src/img/icons/STOCK_CONNECT.png Binary files differdeleted file mode 100644 index c820b54abcc..00000000000 --- a/addons/base/static/src/img/icons/STOCK_CONNECT.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_CONVERT.png b/addons/base/static/src/img/icons/STOCK_CONVERT.png Binary files differdeleted file mode 100644 index 6288b964cc0..00000000000 --- a/addons/base/static/src/img/icons/STOCK_CONVERT.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_COPY.png b/addons/base/static/src/img/icons/STOCK_COPY.png Binary files differdeleted file mode 100644 index 3d68da606d2..00000000000 --- a/addons/base/static/src/img/icons/STOCK_COPY.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_CUT.png b/addons/base/static/src/img/icons/STOCK_CUT.png Binary files differdeleted file mode 100644 index 96681d26968..00000000000 --- a/addons/base/static/src/img/icons/STOCK_CUT.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_DELETE.png b/addons/base/static/src/img/icons/STOCK_DELETE.png Binary files differdeleted file mode 100644 index 879d6fd1cbe..00000000000 --- a/addons/base/static/src/img/icons/STOCK_DELETE.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_DIALOG_AUTHENTICATION.png b/addons/base/static/src/img/icons/STOCK_DIALOG_AUTHENTICATION.png Binary files differdeleted file mode 100644 index eb411112f83..00000000000 --- a/addons/base/static/src/img/icons/STOCK_DIALOG_AUTHENTICATION.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_DIALOG_ERROR.png b/addons/base/static/src/img/icons/STOCK_DIALOG_ERROR.png Binary files differdeleted file mode 100644 index e97bc43504b..00000000000 --- a/addons/base/static/src/img/icons/STOCK_DIALOG_ERROR.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_DIALOG_INFO.png b/addons/base/static/src/img/icons/STOCK_DIALOG_INFO.png Binary files differdeleted file mode 100644 index ed46c3ecdb3..00000000000 --- a/addons/base/static/src/img/icons/STOCK_DIALOG_INFO.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_DIALOG_QUESTION.png b/addons/base/static/src/img/icons/STOCK_DIALOG_QUESTION.png Binary files differdeleted file mode 100644 index ef68f43f43f..00000000000 --- a/addons/base/static/src/img/icons/STOCK_DIALOG_QUESTION.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_DIALOG_WARNING.png b/addons/base/static/src/img/icons/STOCK_DIALOG_WARNING.png Binary files differdeleted file mode 100644 index 65a4d2c7220..00000000000 --- a/addons/base/static/src/img/icons/STOCK_DIALOG_WARNING.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_DIRECTORY.png b/addons/base/static/src/img/icons/STOCK_DIRECTORY.png Binary files differdeleted file mode 100644 index 8e41b7878a9..00000000000 --- a/addons/base/static/src/img/icons/STOCK_DIRECTORY.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_DISCONNECT.png b/addons/base/static/src/img/icons/STOCK_DISCONNECT.png Binary files differdeleted file mode 100644 index fd188701fc2..00000000000 --- a/addons/base/static/src/img/icons/STOCK_DISCONNECT.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_DND.png b/addons/base/static/src/img/icons/STOCK_DND.png Binary files differdeleted file mode 100644 index bf3b8068397..00000000000 --- a/addons/base/static/src/img/icons/STOCK_DND.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_DND_MULTIPLE.png b/addons/base/static/src/img/icons/STOCK_DND_MULTIPLE.png Binary files differdeleted file mode 100644 index aa4c65ad5b1..00000000000 --- a/addons/base/static/src/img/icons/STOCK_DND_MULTIPLE.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_EDIT.png b/addons/base/static/src/img/icons/STOCK_EDIT.png Binary files differdeleted file mode 100644 index 53b7d0855ed..00000000000 --- a/addons/base/static/src/img/icons/STOCK_EDIT.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_EXECUTE.png b/addons/base/static/src/img/icons/STOCK_EXECUTE.png Binary files differdeleted file mode 100644 index eddc0f86b25..00000000000 --- a/addons/base/static/src/img/icons/STOCK_EXECUTE.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_FILE.png b/addons/base/static/src/img/icons/STOCK_FILE.png Binary files differdeleted file mode 100644 index fa157156bcc..00000000000 --- a/addons/base/static/src/img/icons/STOCK_FILE.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_FIND.png b/addons/base/static/src/img/icons/STOCK_FIND.png Binary files differdeleted file mode 100644 index 7a23b0125b5..00000000000 --- a/addons/base/static/src/img/icons/STOCK_FIND.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_FIND_AND_REPLACE.png b/addons/base/static/src/img/icons/STOCK_FIND_AND_REPLACE.png Binary files differdeleted file mode 100644 index b8d8eeec1b2..00000000000 --- a/addons/base/static/src/img/icons/STOCK_FIND_AND_REPLACE.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_FLOPPY.png b/addons/base/static/src/img/icons/STOCK_FLOPPY.png Binary files differdeleted file mode 100644 index 7d8209cfb6f..00000000000 --- a/addons/base/static/src/img/icons/STOCK_FLOPPY.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_FULLSCREEN.png b/addons/base/static/src/img/icons/STOCK_FULLSCREEN.png Binary files differdeleted file mode 100644 index 8ddc31e7481..00000000000 --- a/addons/base/static/src/img/icons/STOCK_FULLSCREEN.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_GOTO_BOTTOM.png b/addons/base/static/src/img/icons/STOCK_GOTO_BOTTOM.png Binary files differdeleted file mode 100644 index be52840dee1..00000000000 --- a/addons/base/static/src/img/icons/STOCK_GOTO_BOTTOM.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_GOTO_FIRST.png b/addons/base/static/src/img/icons/STOCK_GOTO_FIRST.png Binary files differdeleted file mode 100644 index 3d00e36d696..00000000000 --- a/addons/base/static/src/img/icons/STOCK_GOTO_FIRST.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_GOTO_LAST.png b/addons/base/static/src/img/icons/STOCK_GOTO_LAST.png Binary files differdeleted file mode 100644 index 2028226996d..00000000000 --- a/addons/base/static/src/img/icons/STOCK_GOTO_LAST.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_GOTO_TOP.png b/addons/base/static/src/img/icons/STOCK_GOTO_TOP.png Binary files differdeleted file mode 100644 index 227a91e5157..00000000000 --- a/addons/base/static/src/img/icons/STOCK_GOTO_TOP.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_GO_BACK.png b/addons/base/static/src/img/icons/STOCK_GO_BACK.png Binary files differdeleted file mode 100644 index 568117dc170..00000000000 --- a/addons/base/static/src/img/icons/STOCK_GO_BACK.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_GO_DOWN.png b/addons/base/static/src/img/icons/STOCK_GO_DOWN.png Binary files differdeleted file mode 100644 index 5677cffe6a3..00000000000 --- a/addons/base/static/src/img/icons/STOCK_GO_DOWN.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_GO_FORWARD.png b/addons/base/static/src/img/icons/STOCK_GO_FORWARD.png Binary files differdeleted file mode 100644 index fa89d31b734..00000000000 --- a/addons/base/static/src/img/icons/STOCK_GO_FORWARD.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_GO_UP.png b/addons/base/static/src/img/icons/STOCK_GO_UP.png Binary files differdeleted file mode 100644 index 84f96fdfca2..00000000000 --- a/addons/base/static/src/img/icons/STOCK_GO_UP.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_HARDDISK.png b/addons/base/static/src/img/icons/STOCK_HARDDISK.png Binary files differdeleted file mode 100644 index 73e5ef0a82e..00000000000 --- a/addons/base/static/src/img/icons/STOCK_HARDDISK.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_HELP.png b/addons/base/static/src/img/icons/STOCK_HELP.png Binary files differdeleted file mode 100644 index f8e17009dd6..00000000000 --- a/addons/base/static/src/img/icons/STOCK_HELP.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_HOME.png b/addons/base/static/src/img/icons/STOCK_HOME.png Binary files differdeleted file mode 100644 index 9d3d50d0fcb..00000000000 --- a/addons/base/static/src/img/icons/STOCK_HOME.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_INDENT.png b/addons/base/static/src/img/icons/STOCK_INDENT.png Binary files differdeleted file mode 100644 index 19f2669447d..00000000000 --- a/addons/base/static/src/img/icons/STOCK_INDENT.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_INDEX.png b/addons/base/static/src/img/icons/STOCK_INDEX.png Binary files differdeleted file mode 100644 index 0b63cc25fa8..00000000000 --- a/addons/base/static/src/img/icons/STOCK_INDEX.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_INFO.png b/addons/base/static/src/img/icons/STOCK_INFO.png Binary files differdeleted file mode 100644 index 272019f5c99..00000000000 --- a/addons/base/static/src/img/icons/STOCK_INFO.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_ITALIC.png b/addons/base/static/src/img/icons/STOCK_ITALIC.png Binary files differdeleted file mode 100644 index 26c57226a31..00000000000 --- a/addons/base/static/src/img/icons/STOCK_ITALIC.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_JUMP_TO.png b/addons/base/static/src/img/icons/STOCK_JUMP_TO.png Binary files differdeleted file mode 100644 index 82d7896bdac..00000000000 --- a/addons/base/static/src/img/icons/STOCK_JUMP_TO.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_JUSTIFY_CENTER.png b/addons/base/static/src/img/icons/STOCK_JUSTIFY_CENTER.png Binary files differdeleted file mode 100644 index d5f514298eb..00000000000 --- a/addons/base/static/src/img/icons/STOCK_JUSTIFY_CENTER.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_JUSTIFY_FILL.png b/addons/base/static/src/img/icons/STOCK_JUSTIFY_FILL.png Binary files differdeleted file mode 100644 index 5e2f5c73f30..00000000000 --- a/addons/base/static/src/img/icons/STOCK_JUSTIFY_FILL.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_JUSTIFY_LEFT.png b/addons/base/static/src/img/icons/STOCK_JUSTIFY_LEFT.png Binary files differdeleted file mode 100644 index ecb76b117eb..00000000000 --- a/addons/base/static/src/img/icons/STOCK_JUSTIFY_LEFT.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_JUSTIFY_RIGHT.png b/addons/base/static/src/img/icons/STOCK_JUSTIFY_RIGHT.png Binary files differdeleted file mode 100644 index 3cd4d161420..00000000000 --- a/addons/base/static/src/img/icons/STOCK_JUSTIFY_RIGHT.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_LEAVE_FULLSCREEN.png b/addons/base/static/src/img/icons/STOCK_LEAVE_FULLSCREEN.png Binary files differdeleted file mode 100644 index 15bc8ab7d7b..00000000000 --- a/addons/base/static/src/img/icons/STOCK_LEAVE_FULLSCREEN.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_MEDIA_FORWARD.png b/addons/base/static/src/img/icons/STOCK_MEDIA_FORWARD.png Binary files differdeleted file mode 100644 index e5e198fbb79..00000000000 --- a/addons/base/static/src/img/icons/STOCK_MEDIA_FORWARD.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_MEDIA_NEXT.png b/addons/base/static/src/img/icons/STOCK_MEDIA_NEXT.png Binary files differdeleted file mode 100644 index e0aa2431cf0..00000000000 --- a/addons/base/static/src/img/icons/STOCK_MEDIA_NEXT.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_MEDIA_PAUSE.png b/addons/base/static/src/img/icons/STOCK_MEDIA_PAUSE.png Binary files differdeleted file mode 100644 index 6721994eb8d..00000000000 --- a/addons/base/static/src/img/icons/STOCK_MEDIA_PAUSE.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_MEDIA_PLAY.png b/addons/base/static/src/img/icons/STOCK_MEDIA_PLAY.png Binary files differdeleted file mode 100644 index b0832712c81..00000000000 --- a/addons/base/static/src/img/icons/STOCK_MEDIA_PLAY.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_MEDIA_PREVIOUS.png b/addons/base/static/src/img/icons/STOCK_MEDIA_PREVIOUS.png Binary files differdeleted file mode 100644 index 756899e0bc1..00000000000 --- a/addons/base/static/src/img/icons/STOCK_MEDIA_PREVIOUS.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_MEDIA_RECORD.png b/addons/base/static/src/img/icons/STOCK_MEDIA_RECORD.png Binary files differdeleted file mode 100644 index 904974c81e5..00000000000 --- a/addons/base/static/src/img/icons/STOCK_MEDIA_RECORD.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_MEDIA_REWIND.png b/addons/base/static/src/img/icons/STOCK_MEDIA_REWIND.png Binary files differdeleted file mode 100644 index 9c22d9e2778..00000000000 --- a/addons/base/static/src/img/icons/STOCK_MEDIA_REWIND.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_MEDIA_STOP.png b/addons/base/static/src/img/icons/STOCK_MEDIA_STOP.png Binary files differdeleted file mode 100644 index 128cc2313ec..00000000000 --- a/addons/base/static/src/img/icons/STOCK_MEDIA_STOP.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_MISSING_IMAGE.png b/addons/base/static/src/img/icons/STOCK_MISSING_IMAGE.png Binary files differdeleted file mode 100644 index cc69ed33e4b..00000000000 --- a/addons/base/static/src/img/icons/STOCK_MISSING_IMAGE.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_NETWORK.png b/addons/base/static/src/img/icons/STOCK_NETWORK.png Binary files differdeleted file mode 100644 index df94a515fec..00000000000 --- a/addons/base/static/src/img/icons/STOCK_NETWORK.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_NEW.png b/addons/base/static/src/img/icons/STOCK_NEW.png Binary files differdeleted file mode 100644 index 04a290fac7d..00000000000 --- a/addons/base/static/src/img/icons/STOCK_NEW.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_NO.png b/addons/base/static/src/img/icons/STOCK_NO.png Binary files differdeleted file mode 100644 index 047ddcd9289..00000000000 --- a/addons/base/static/src/img/icons/STOCK_NO.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_OK.png b/addons/base/static/src/img/icons/STOCK_OK.png Binary files differdeleted file mode 100644 index 7755b8769f0..00000000000 --- a/addons/base/static/src/img/icons/STOCK_OK.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_OPEN.png b/addons/base/static/src/img/icons/STOCK_OPEN.png Binary files differdeleted file mode 100644 index 9cdd8c66770..00000000000 --- a/addons/base/static/src/img/icons/STOCK_OPEN.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_PASTE.png b/addons/base/static/src/img/icons/STOCK_PASTE.png Binary files differdeleted file mode 100644 index 840f26c8b38..00000000000 --- a/addons/base/static/src/img/icons/STOCK_PASTE.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_PREFERENCES.png b/addons/base/static/src/img/icons/STOCK_PREFERENCES.png Binary files differdeleted file mode 100644 index 9ba17a0ab20..00000000000 --- a/addons/base/static/src/img/icons/STOCK_PREFERENCES.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_PRINT.png b/addons/base/static/src/img/icons/STOCK_PRINT.png Binary files differdeleted file mode 100644 index be0ed4efb44..00000000000 --- a/addons/base/static/src/img/icons/STOCK_PRINT.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_PRINT_PREVIEW.png b/addons/base/static/src/img/icons/STOCK_PRINT_PREVIEW.png Binary files differdeleted file mode 100644 index ab15fcbd307..00000000000 --- a/addons/base/static/src/img/icons/STOCK_PRINT_PREVIEW.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_PROPERTIES.png b/addons/base/static/src/img/icons/STOCK_PROPERTIES.png Binary files differdeleted file mode 100644 index 894415ec1ce..00000000000 --- a/addons/base/static/src/img/icons/STOCK_PROPERTIES.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_QUIT.png b/addons/base/static/src/img/icons/STOCK_QUIT.png Binary files differdeleted file mode 100644 index 50b5144660b..00000000000 --- a/addons/base/static/src/img/icons/STOCK_QUIT.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_REDO.png b/addons/base/static/src/img/icons/STOCK_REDO.png Binary files differdeleted file mode 100644 index 54055b3966d..00000000000 --- a/addons/base/static/src/img/icons/STOCK_REDO.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_REFRESH.png b/addons/base/static/src/img/icons/STOCK_REFRESH.png Binary files differdeleted file mode 100644 index 7474728b4c0..00000000000 --- a/addons/base/static/src/img/icons/STOCK_REFRESH.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_REMOVE.png b/addons/base/static/src/img/icons/STOCK_REMOVE.png Binary files differdeleted file mode 100644 index c2b6e915f77..00000000000 --- a/addons/base/static/src/img/icons/STOCK_REMOVE.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_REVERT_TO_SAVED.png b/addons/base/static/src/img/icons/STOCK_REVERT_TO_SAVED.png Binary files differdeleted file mode 100644 index eaf54584edf..00000000000 --- a/addons/base/static/src/img/icons/STOCK_REVERT_TO_SAVED.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_SAVE.png b/addons/base/static/src/img/icons/STOCK_SAVE.png Binary files differdeleted file mode 100644 index c61836548a7..00000000000 --- a/addons/base/static/src/img/icons/STOCK_SAVE.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_SAVE_AS.png b/addons/base/static/src/img/icons/STOCK_SAVE_AS.png Binary files differdeleted file mode 100644 index 1831e4e0a4b..00000000000 --- a/addons/base/static/src/img/icons/STOCK_SAVE_AS.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_SELECT_COLOR.png b/addons/base/static/src/img/icons/STOCK_SELECT_COLOR.png Binary files differdeleted file mode 100644 index 12b015df107..00000000000 --- a/addons/base/static/src/img/icons/STOCK_SELECT_COLOR.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_SELECT_FONT.png b/addons/base/static/src/img/icons/STOCK_SELECT_FONT.png Binary files differdeleted file mode 100644 index 66e606313a5..00000000000 --- a/addons/base/static/src/img/icons/STOCK_SELECT_FONT.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_SORT_ASCENDING.png b/addons/base/static/src/img/icons/STOCK_SORT_ASCENDING.png Binary files differdeleted file mode 100644 index a648fa0d359..00000000000 --- a/addons/base/static/src/img/icons/STOCK_SORT_ASCENDING.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_SORT_DESCENDING.png b/addons/base/static/src/img/icons/STOCK_SORT_DESCENDING.png Binary files differdeleted file mode 100644 index a90b588d797..00000000000 --- a/addons/base/static/src/img/icons/STOCK_SORT_DESCENDING.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_SPELL_CHECK.png b/addons/base/static/src/img/icons/STOCK_SPELL_CHECK.png Binary files differdeleted file mode 100644 index 698f7c24a43..00000000000 --- a/addons/base/static/src/img/icons/STOCK_SPELL_CHECK.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_STOP.png b/addons/base/static/src/img/icons/STOCK_STOP.png Binary files differdeleted file mode 100644 index 2ee93ed6415..00000000000 --- a/addons/base/static/src/img/icons/STOCK_STOP.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_STRIKETHROUGH.png b/addons/base/static/src/img/icons/STOCK_STRIKETHROUGH.png Binary files differdeleted file mode 100644 index 1c11f214622..00000000000 --- a/addons/base/static/src/img/icons/STOCK_STRIKETHROUGH.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_UNDELETE.png b/addons/base/static/src/img/icons/STOCK_UNDELETE.png Binary files differdeleted file mode 100644 index c44b940c03b..00000000000 --- a/addons/base/static/src/img/icons/STOCK_UNDELETE.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_UNDERLINE.png b/addons/base/static/src/img/icons/STOCK_UNDERLINE.png Binary files differdeleted file mode 100644 index 7dbb5d7e60a..00000000000 --- a/addons/base/static/src/img/icons/STOCK_UNDERLINE.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_UNDO.png b/addons/base/static/src/img/icons/STOCK_UNDO.png Binary files differdeleted file mode 100644 index 7a50de0c61e..00000000000 --- a/addons/base/static/src/img/icons/STOCK_UNDO.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_UNINDENT.png b/addons/base/static/src/img/icons/STOCK_UNINDENT.png Binary files differdeleted file mode 100644 index 8ace914c1bd..00000000000 --- a/addons/base/static/src/img/icons/STOCK_UNINDENT.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_YES.png b/addons/base/static/src/img/icons/STOCK_YES.png Binary files differdeleted file mode 100644 index 01fb373c251..00000000000 --- a/addons/base/static/src/img/icons/STOCK_YES.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_ZOOM_100.png b/addons/base/static/src/img/icons/STOCK_ZOOM_100.png Binary files differdeleted file mode 100644 index 5193406b787..00000000000 --- a/addons/base/static/src/img/icons/STOCK_ZOOM_100.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_ZOOM_FIT.png b/addons/base/static/src/img/icons/STOCK_ZOOM_FIT.png Binary files differdeleted file mode 100644 index 1e70e619466..00000000000 --- a/addons/base/static/src/img/icons/STOCK_ZOOM_FIT.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_ZOOM_IN.png b/addons/base/static/src/img/icons/STOCK_ZOOM_IN.png Binary files differdeleted file mode 100644 index 29e50e45d4a..00000000000 --- a/addons/base/static/src/img/icons/STOCK_ZOOM_IN.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/STOCK_ZOOM_OUT.png b/addons/base/static/src/img/icons/STOCK_ZOOM_OUT.png Binary files differdeleted file mode 100644 index 0da5ee7ec13..00000000000 --- a/addons/base/static/src/img/icons/STOCK_ZOOM_OUT.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-add.png b/addons/base/static/src/img/icons/gtk-add.png Binary files differdeleted file mode 100644 index 70612c181c6..00000000000 --- a/addons/base/static/src/img/icons/gtk-add.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-apply.png b/addons/base/static/src/img/icons/gtk-apply.png Binary files differdeleted file mode 100644 index 116f2e433bb..00000000000 --- a/addons/base/static/src/img/icons/gtk-apply.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-cancel.png b/addons/base/static/src/img/icons/gtk-cancel.png Binary files differdeleted file mode 100644 index 8cf6273281b..00000000000 --- a/addons/base/static/src/img/icons/gtk-cancel.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-close.png b/addons/base/static/src/img/icons/gtk-close.png Binary files differdeleted file mode 100644 index 4966974e178..00000000000 --- a/addons/base/static/src/img/icons/gtk-close.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-convert.png b/addons/base/static/src/img/icons/gtk-convert.png Binary files differdeleted file mode 100644 index 6288b964cc0..00000000000 --- a/addons/base/static/src/img/icons/gtk-convert.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-delete.png b/addons/base/static/src/img/icons/gtk-delete.png Binary files differdeleted file mode 100644 index 879d6fd1cbe..00000000000 --- a/addons/base/static/src/img/icons/gtk-delete.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-dnd.png b/addons/base/static/src/img/icons/gtk-dnd.png Binary files differdeleted file mode 100644 index bf3b8068397..00000000000 --- a/addons/base/static/src/img/icons/gtk-dnd.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-edit.png b/addons/base/static/src/img/icons/gtk-edit.png Binary files differdeleted file mode 100644 index 53b7d0855ed..00000000000 --- a/addons/base/static/src/img/icons/gtk-edit.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-execute.png b/addons/base/static/src/img/icons/gtk-execute.png Binary files differdeleted file mode 100644 index eddc0f86b25..00000000000 --- a/addons/base/static/src/img/icons/gtk-execute.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-find.png b/addons/base/static/src/img/icons/gtk-find.png Binary files differdeleted file mode 100644 index 7a23b0125b5..00000000000 --- a/addons/base/static/src/img/icons/gtk-find.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-go-back.png b/addons/base/static/src/img/icons/gtk-go-back.png Binary files differdeleted file mode 100644 index 568117dc170..00000000000 --- a/addons/base/static/src/img/icons/gtk-go-back.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-go-down.png b/addons/base/static/src/img/icons/gtk-go-down.png Binary files differdeleted file mode 100644 index 5677cffe6a3..00000000000 --- a/addons/base/static/src/img/icons/gtk-go-down.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-go-forward.png b/addons/base/static/src/img/icons/gtk-go-forward.png Binary files differdeleted file mode 100644 index fa89d31b734..00000000000 --- a/addons/base/static/src/img/icons/gtk-go-forward.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-go-up.png b/addons/base/static/src/img/icons/gtk-go-up.png Binary files differdeleted file mode 100644 index 84f96fdfca2..00000000000 --- a/addons/base/static/src/img/icons/gtk-go-up.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-goto-last.png b/addons/base/static/src/img/icons/gtk-goto-last.png Binary files differdeleted file mode 100644 index 2028226996d..00000000000 --- a/addons/base/static/src/img/icons/gtk-goto-last.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-indent.png b/addons/base/static/src/img/icons/gtk-indent.png Binary files differdeleted file mode 100644 index 19f2669447d..00000000000 --- a/addons/base/static/src/img/icons/gtk-indent.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-index.png b/addons/base/static/src/img/icons/gtk-index.png Binary files differdeleted file mode 100644 index 0b63cc25fa8..00000000000 --- a/addons/base/static/src/img/icons/gtk-index.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-jump-to.png b/addons/base/static/src/img/icons/gtk-jump-to.png Binary files differdeleted file mode 100644 index 82d7896bdac..00000000000 --- a/addons/base/static/src/img/icons/gtk-jump-to.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-justify-fill.png b/addons/base/static/src/img/icons/gtk-justify-fill.png Binary files differdeleted file mode 100644 index 5e2f5c73f30..00000000000 --- a/addons/base/static/src/img/icons/gtk-justify-fill.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-media-pause.png b/addons/base/static/src/img/icons/gtk-media-pause.png Binary files differdeleted file mode 100644 index 6721994eb8d..00000000000 --- a/addons/base/static/src/img/icons/gtk-media-pause.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-media-play.png b/addons/base/static/src/img/icons/gtk-media-play.png Binary files differdeleted file mode 100644 index b0832712c81..00000000000 --- a/addons/base/static/src/img/icons/gtk-media-play.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-network.png b/addons/base/static/src/img/icons/gtk-network.png Binary files differdeleted file mode 100644 index df94a515fec..00000000000 --- a/addons/base/static/src/img/icons/gtk-network.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-new.png b/addons/base/static/src/img/icons/gtk-new.png Binary files differdeleted file mode 100644 index 04a290fac7d..00000000000 --- a/addons/base/static/src/img/icons/gtk-new.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-no.png b/addons/base/static/src/img/icons/gtk-no.png Binary files differdeleted file mode 100644 index 047ddcd9289..00000000000 --- a/addons/base/static/src/img/icons/gtk-no.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-ok.png b/addons/base/static/src/img/icons/gtk-ok.png Binary files differdeleted file mode 100644 index 7755b8769f0..00000000000 --- a/addons/base/static/src/img/icons/gtk-ok.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-open.png b/addons/base/static/src/img/icons/gtk-open.png Binary files differdeleted file mode 100644 index 9cdd8c66770..00000000000 --- a/addons/base/static/src/img/icons/gtk-open.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-print.png b/addons/base/static/src/img/icons/gtk-print.png Binary files differdeleted file mode 100644 index be0ed4efb44..00000000000 --- a/addons/base/static/src/img/icons/gtk-print.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-redo.png b/addons/base/static/src/img/icons/gtk-redo.png Binary files differdeleted file mode 100644 index 54055b3966d..00000000000 --- a/addons/base/static/src/img/icons/gtk-redo.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-remove.png b/addons/base/static/src/img/icons/gtk-remove.png Binary files differdeleted file mode 100644 index c2b6e915f77..00000000000 --- a/addons/base/static/src/img/icons/gtk-remove.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-save.png b/addons/base/static/src/img/icons/gtk-save.png Binary files differdeleted file mode 100644 index c61836548a7..00000000000 --- a/addons/base/static/src/img/icons/gtk-save.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-sort-descending.png b/addons/base/static/src/img/icons/gtk-sort-descending.png Binary files differdeleted file mode 100644 index a90b588d797..00000000000 --- a/addons/base/static/src/img/icons/gtk-sort-descending.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-stop.png b/addons/base/static/src/img/icons/gtk-stop.png Binary files differdeleted file mode 100644 index 2ee93ed6415..00000000000 --- a/addons/base/static/src/img/icons/gtk-stop.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-undo.png b/addons/base/static/src/img/icons/gtk-undo.png Binary files differdeleted file mode 100644 index 7a50de0c61e..00000000000 --- a/addons/base/static/src/img/icons/gtk-undo.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-yes.png b/addons/base/static/src/img/icons/gtk-yes.png Binary files differdeleted file mode 100644 index 01fb373c251..00000000000 --- a/addons/base/static/src/img/icons/gtk-yes.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-zoom-fit.png b/addons/base/static/src/img/icons/gtk-zoom-fit.png Binary files differdeleted file mode 100644 index 1e70e619466..00000000000 --- a/addons/base/static/src/img/icons/gtk-zoom-fit.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/gtk-zoom-in.png b/addons/base/static/src/img/icons/gtk-zoom-in.png Binary files differdeleted file mode 100644 index 29e50e45d4a..00000000000 --- a/addons/base/static/src/img/icons/gtk-zoom-in.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/index1.jpeg b/addons/base/static/src/img/icons/index1.jpeg Binary files differdeleted file mode 100644 index f43c68d79ec..00000000000 --- a/addons/base/static/src/img/icons/index1.jpeg +++ /dev/null diff --git a/addons/base/static/src/img/icons/index2.jpeg b/addons/base/static/src/img/icons/index2.jpeg Binary files differdeleted file mode 100644 index ec9d1eb6d3c..00000000000 --- a/addons/base/static/src/img/icons/index2.jpeg +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-accessories-archiver+.png b/addons/base/static/src/img/icons/terp-accessories-archiver+.png Binary files differdeleted file mode 100644 index 14d6d02536e..00000000000 --- a/addons/base/static/src/img/icons/terp-accessories-archiver+.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-accessories-archiver-minus.png b/addons/base/static/src/img/icons/terp-accessories-archiver-minus.png Binary files differdeleted file mode 100644 index 024c8f692d8..00000000000 --- a/addons/base/static/src/img/icons/terp-accessories-archiver-minus.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-accessories-archiver.png b/addons/base/static/src/img/icons/terp-accessories-archiver.png Binary files differdeleted file mode 100644 index 8bcbe4566bc..00000000000 --- a/addons/base/static/src/img/icons/terp-accessories-archiver.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-account.png b/addons/base/static/src/img/icons/terp-account.png Binary files differdeleted file mode 100644 index 30dea82a105..00000000000 --- a/addons/base/static/src/img/icons/terp-account.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-administration.png b/addons/base/static/src/img/icons/terp-administration.png Binary files differdeleted file mode 100644 index ab129b2e4b3..00000000000 --- a/addons/base/static/src/img/icons/terp-administration.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-calendar.png b/addons/base/static/src/img/icons/terp-calendar.png Binary files differdeleted file mode 100644 index 37206565792..00000000000 --- a/addons/base/static/src/img/icons/terp-calendar.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-call-start.png b/addons/base/static/src/img/icons/terp-call-start.png Binary files differdeleted file mode 100644 index 602a1cdd4b8..00000000000 --- a/addons/base/static/src/img/icons/terp-call-start.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-camera_test.png b/addons/base/static/src/img/icons/terp-camera_test.png Binary files differdeleted file mode 100644 index e97e0416de3..00000000000 --- a/addons/base/static/src/img/icons/terp-camera_test.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-check.png b/addons/base/static/src/img/icons/terp-check.png Binary files differdeleted file mode 100644 index 003b09fdeb9..00000000000 --- a/addons/base/static/src/img/icons/terp-check.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-crm.png b/addons/base/static/src/img/icons/terp-crm.png Binary files differdeleted file mode 100644 index fdac61ca92d..00000000000 --- a/addons/base/static/src/img/icons/terp-crm.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-dialog-close.png b/addons/base/static/src/img/icons/terp-dialog-close.png Binary files differdeleted file mode 100644 index 8f51ec05fd6..00000000000 --- a/addons/base/static/src/img/icons/terp-dialog-close.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-document-new.png b/addons/base/static/src/img/icons/terp-document-new.png Binary files differdeleted file mode 100644 index 2815cbb403f..00000000000 --- a/addons/base/static/src/img/icons/terp-document-new.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-dolar.png b/addons/base/static/src/img/icons/terp-dolar.png Binary files differdeleted file mode 100644 index bca7021c82f..00000000000 --- a/addons/base/static/src/img/icons/terp-dolar.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-dolar_ok!.png b/addons/base/static/src/img/icons/terp-dolar_ok!.png Binary files differdeleted file mode 100644 index b1005aae7b9..00000000000 --- a/addons/base/static/src/img/icons/terp-dolar_ok!.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-emblem-important.png b/addons/base/static/src/img/icons/terp-emblem-important.png Binary files differdeleted file mode 100644 index a8321066abb..00000000000 --- a/addons/base/static/src/img/icons/terp-emblem-important.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-face-plain.png b/addons/base/static/src/img/icons/terp-face-plain.png Binary files differdeleted file mode 100644 index ea90aaa7ef4..00000000000 --- a/addons/base/static/src/img/icons/terp-face-plain.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-folder-blue.png b/addons/base/static/src/img/icons/terp-folder-blue.png Binary files differdeleted file mode 100644 index addc480d49a..00000000000 --- a/addons/base/static/src/img/icons/terp-folder-blue.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-folder-green.png b/addons/base/static/src/img/icons/terp-folder-green.png Binary files differdeleted file mode 100644 index 206cd39603e..00000000000 --- a/addons/base/static/src/img/icons/terp-folder-green.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-folder-orange.png b/addons/base/static/src/img/icons/terp-folder-orange.png Binary files differdeleted file mode 100644 index 726dbd7f00e..00000000000 --- a/addons/base/static/src/img/icons/terp-folder-orange.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-folder-violet.png b/addons/base/static/src/img/icons/terp-folder-violet.png Binary files differdeleted file mode 100644 index c6f5cfb87ff..00000000000 --- a/addons/base/static/src/img/icons/terp-folder-violet.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-folder-yellow.png b/addons/base/static/src/img/icons/terp-folder-yellow.png Binary files differdeleted file mode 100644 index cd7295dcdd7..00000000000 --- a/addons/base/static/src/img/icons/terp-folder-yellow.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-gdu-smart-failing.png b/addons/base/static/src/img/icons/terp-gdu-smart-failing.png Binary files differdeleted file mode 100644 index a4448fd553e..00000000000 --- a/addons/base/static/src/img/icons/terp-gdu-smart-failing.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-gnome-cpu-frequency-applet+.png b/addons/base/static/src/img/icons/terp-gnome-cpu-frequency-applet+.png Binary files differdeleted file mode 100644 index 23e246f3be9..00000000000 --- a/addons/base/static/src/img/icons/terp-gnome-cpu-frequency-applet+.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-go-home.png b/addons/base/static/src/img/icons/terp-go-home.png Binary files differdeleted file mode 100644 index 912256bf7a7..00000000000 --- a/addons/base/static/src/img/icons/terp-go-home.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-go-month.png b/addons/base/static/src/img/icons/terp-go-month.png Binary files differdeleted file mode 100644 index cf5e305053e..00000000000 --- a/addons/base/static/src/img/icons/terp-go-month.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-go-today.png b/addons/base/static/src/img/icons/terp-go-today.png Binary files differdeleted file mode 100644 index 2a4dbeed49a..00000000000 --- a/addons/base/static/src/img/icons/terp-go-today.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-go-week.png b/addons/base/static/src/img/icons/terp-go-week.png Binary files differdeleted file mode 100644 index b3ce6f562b2..00000000000 --- a/addons/base/static/src/img/icons/terp-go-week.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-go-year.png b/addons/base/static/src/img/icons/terp-go-year.png Binary files differdeleted file mode 100644 index f45efc9dd0c..00000000000 --- a/addons/base/static/src/img/icons/terp-go-year.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-graph.png b/addons/base/static/src/img/icons/terp-graph.png Binary files differdeleted file mode 100644 index 30dea82a105..00000000000 --- a/addons/base/static/src/img/icons/terp-graph.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-gtk-go-back-ltr.png b/addons/base/static/src/img/icons/terp-gtk-go-back-ltr.png Binary files differdeleted file mode 100644 index a76138d2e0d..00000000000 --- a/addons/base/static/src/img/icons/terp-gtk-go-back-ltr.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-gtk-go-back-rtl.png b/addons/base/static/src/img/icons/terp-gtk-go-back-rtl.png Binary files differdeleted file mode 100644 index 10d10b582fe..00000000000 --- a/addons/base/static/src/img/icons/terp-gtk-go-back-rtl.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-gtk-jump-to-ltr.png b/addons/base/static/src/img/icons/terp-gtk-jump-to-ltr.png Binary files differdeleted file mode 100644 index fa517749d10..00000000000 --- a/addons/base/static/src/img/icons/terp-gtk-jump-to-ltr.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-gtk-jump-to-rtl.png b/addons/base/static/src/img/icons/terp-gtk-jump-to-rtl.png Binary files differdeleted file mode 100644 index 7b5785c4963..00000000000 --- a/addons/base/static/src/img/icons/terp-gtk-jump-to-rtl.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-gtk-media-pause.png b/addons/base/static/src/img/icons/terp-gtk-media-pause.png Binary files differdeleted file mode 100644 index 2896ad8e27f..00000000000 --- a/addons/base/static/src/img/icons/terp-gtk-media-pause.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-gtk-select-all.png b/addons/base/static/src/img/icons/terp-gtk-select-all.png Binary files differdeleted file mode 100644 index b71a6493791..00000000000 --- a/addons/base/static/src/img/icons/terp-gtk-select-all.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-gtk-stop.png b/addons/base/static/src/img/icons/terp-gtk-stop.png Binary files differdeleted file mode 100644 index 5fe021e19df..00000000000 --- a/addons/base/static/src/img/icons/terp-gtk-stop.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-hr.png b/addons/base/static/src/img/icons/terp-hr.png Binary files differdeleted file mode 100644 index ba0241e6362..00000000000 --- a/addons/base/static/src/img/icons/terp-hr.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-idea.png b/addons/base/static/src/img/icons/terp-idea.png Binary files differdeleted file mode 100644 index fd5e2a25f14..00000000000 --- a/addons/base/static/src/img/icons/terp-idea.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-locked.png b/addons/base/static/src/img/icons/terp-locked.png Binary files differdeleted file mode 100644 index cd2b4c2c9c2..00000000000 --- a/addons/base/static/src/img/icons/terp-locked.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-mail-.png b/addons/base/static/src/img/icons/terp-mail-.png Binary files differdeleted file mode 100644 index cbc85e4c000..00000000000 --- a/addons/base/static/src/img/icons/terp-mail-.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-mail-forward.png b/addons/base/static/src/img/icons/terp-mail-forward.png Binary files differdeleted file mode 100644 index 3d4e694b6dc..00000000000 --- a/addons/base/static/src/img/icons/terp-mail-forward.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-mail-message-new.png b/addons/base/static/src/img/icons/terp-mail-message-new.png Binary files differdeleted file mode 100644 index 25b4d5b5d50..00000000000 --- a/addons/base/static/src/img/icons/terp-mail-message-new.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-mail-replied.png b/addons/base/static/src/img/icons/terp-mail-replied.png Binary files differdeleted file mode 100644 index 6615f4352cc..00000000000 --- a/addons/base/static/src/img/icons/terp-mail-replied.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-mail_delete.png b/addons/base/static/src/img/icons/terp-mail_delete.png Binary files differdeleted file mode 100644 index 90fb5239f02..00000000000 --- a/addons/base/static/src/img/icons/terp-mail_delete.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-marketing.png b/addons/base/static/src/img/icons/terp-marketing.png Binary files differdeleted file mode 100644 index 1b04b599734..00000000000 --- a/addons/base/static/src/img/icons/terp-marketing.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-mrp.png b/addons/base/static/src/img/icons/terp-mrp.png Binary files differdeleted file mode 100644 index c2b4ea31ec3..00000000000 --- a/addons/base/static/src/img/icons/terp-mrp.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-partner.png b/addons/base/static/src/img/icons/terp-partner.png Binary files differdeleted file mode 100644 index aab206a1d42..00000000000 --- a/addons/base/static/src/img/icons/terp-partner.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-personal+.png b/addons/base/static/src/img/icons/terp-personal+.png Binary files differdeleted file mode 100644 index 8afa4d7041d..00000000000 --- a/addons/base/static/src/img/icons/terp-personal+.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-personal-.png b/addons/base/static/src/img/icons/terp-personal-.png Binary files differdeleted file mode 100644 index a2554df3615..00000000000 --- a/addons/base/static/src/img/icons/terp-personal-.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-personal.png b/addons/base/static/src/img/icons/terp-personal.png Binary files differdeleted file mode 100644 index 0890c4d0e51..00000000000 --- a/addons/base/static/src/img/icons/terp-personal.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-product.png b/addons/base/static/src/img/icons/terp-product.png Binary files differdeleted file mode 100644 index 99f58d95a8b..00000000000 --- a/addons/base/static/src/img/icons/terp-product.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-project.png b/addons/base/static/src/img/icons/terp-project.png Binary files differdeleted file mode 100644 index cd95ae84e43..00000000000 --- a/addons/base/static/src/img/icons/terp-project.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-purchase.png b/addons/base/static/src/img/icons/terp-purchase.png Binary files differdeleted file mode 100644 index 1e801f57485..00000000000 --- a/addons/base/static/src/img/icons/terp-purchase.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-rating-rated.png b/addons/base/static/src/img/icons/terp-rating-rated.png Binary files differdeleted file mode 100644 index 9bff03fe584..00000000000 --- a/addons/base/static/src/img/icons/terp-rating-rated.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-report.png b/addons/base/static/src/img/icons/terp-report.png Binary files differdeleted file mode 100644 index ada36a2de24..00000000000 --- a/addons/base/static/src/img/icons/terp-report.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-sale.png b/addons/base/static/src/img/icons/terp-sale.png Binary files differdeleted file mode 100644 index ba0241e6362..00000000000 --- a/addons/base/static/src/img/icons/terp-sale.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-stage.png b/addons/base/static/src/img/icons/terp-stage.png Binary files differdeleted file mode 100644 index 591c1594f78..00000000000 --- a/addons/base/static/src/img/icons/terp-stage.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-stock.png b/addons/base/static/src/img/icons/terp-stock.png Binary files differdeleted file mode 100644 index 0365dfdb8e1..00000000000 --- a/addons/base/static/src/img/icons/terp-stock.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-stock_align_left_24.png b/addons/base/static/src/img/icons/terp-stock_align_left_24.png Binary files differdeleted file mode 100644 index 844367bb1a7..00000000000 --- a/addons/base/static/src/img/icons/terp-stock_align_left_24.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-stock_effects-object-colorize.png b/addons/base/static/src/img/icons/terp-stock_effects-object-colorize.png Binary files differdeleted file mode 100644 index 0ffd95a740a..00000000000 --- a/addons/base/static/src/img/icons/terp-stock_effects-object-colorize.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-stock_format-default.png b/addons/base/static/src/img/icons/terp-stock_format-default.png Binary files differdeleted file mode 100644 index e44b2b26be5..00000000000 --- a/addons/base/static/src/img/icons/terp-stock_format-default.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-stock_format-scientific.png b/addons/base/static/src/img/icons/terp-stock_format-scientific.png Binary files differdeleted file mode 100644 index 01f83950804..00000000000 --- a/addons/base/static/src/img/icons/terp-stock_format-scientific.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-stock_symbol-selection.png b/addons/base/static/src/img/icons/terp-stock_symbol-selection.png Binary files differdeleted file mode 100644 index 5773be57c9b..00000000000 --- a/addons/base/static/src/img/icons/terp-stock_symbol-selection.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-stock_zoom.png b/addons/base/static/src/img/icons/terp-stock_zoom.png Binary files differdeleted file mode 100644 index e96f05e5905..00000000000 --- a/addons/base/static/src/img/icons/terp-stock_zoom.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-tools.png b/addons/base/static/src/img/icons/terp-tools.png Binary files differdeleted file mode 100644 index 379f7617427..00000000000 --- a/addons/base/static/src/img/icons/terp-tools.png +++ /dev/null diff --git a/addons/base/static/src/img/icons/terp-translate.png b/addons/base/static/src/img/icons/terp-translate.png Binary files differdeleted file mode 100644 index 5ab41d49343..00000000000 --- a/addons/base/static/src/img/icons/terp-translate.png +++ /dev/null diff --git a/addons/base/static/src/img/iconset-d-drop.gif b/addons/base/static/src/img/iconset-d-drop.gif Binary files differdeleted file mode 100644 index 4907a927619..00000000000 --- a/addons/base/static/src/img/iconset-d-drop.gif +++ /dev/null diff --git a/addons/base/static/src/img/logo.png b/addons/base/static/src/img/logo.png Binary files differdeleted file mode 100644 index 8f1c5c6085f..00000000000 --- a/addons/base/static/src/img/logo.png +++ /dev/null diff --git a/addons/base/static/src/img/partner.png b/addons/base/static/src/img/partner.png Binary files differdeleted file mode 100644 index aab206a1d42..00000000000 --- a/addons/base/static/src/img/partner.png +++ /dev/null diff --git a/addons/base/static/src/img/placeholder.png b/addons/base/static/src/img/placeholder.png Binary files differdeleted file mode 100644 index 25af75ee815..00000000000 --- a/addons/base/static/src/img/placeholder.png +++ /dev/null diff --git a/addons/base/static/src/img/product.png b/addons/base/static/src/img/product.png Binary files differdeleted file mode 100644 index 99f58d95a8b..00000000000 --- a/addons/base/static/src/img/product.png +++ /dev/null diff --git a/addons/base/static/src/img/remove-shortcut.png b/addons/base/static/src/img/remove-shortcut.png Binary files differdeleted file mode 100644 index 9bff03fe584..00000000000 --- a/addons/base/static/src/img/remove-shortcut.png +++ /dev/null diff --git a/addons/base/static/src/img/stock_person.png b/addons/base/static/src/img/stock_person.png Binary files differdeleted file mode 100644 index 202cf0ee6c5..00000000000 --- a/addons/base/static/src/img/stock_person.png +++ /dev/null diff --git a/addons/base/static/src/img/throbber.gif b/addons/base/static/src/img/throbber.gif Binary files differdeleted file mode 100644 index ded8d36d486..00000000000 --- a/addons/base/static/src/img/throbber.gif +++ /dev/null diff --git a/addons/base/static/src/img/throbber2.gif b/addons/base/static/src/img/throbber2.gif Binary files differdeleted file mode 100644 index 5d2057ae0e7..00000000000 --- a/addons/base/static/src/img/throbber2.gif +++ /dev/null diff --git a/addons/base/static/src/img/toggle-a-bg.png b/addons/base/static/src/img/toggle-a-bg.png Binary files differdeleted file mode 100644 index b9837ab233e..00000000000 --- a/addons/base/static/src/img/toggle-a-bg.png +++ /dev/null diff --git a/addons/base/static/src/img/ui/field_calendar.png b/addons/base/static/src/img/ui/field_calendar.png Binary files differdeleted file mode 100644 index 99a1f3f9ef1..00000000000 --- a/addons/base/static/src/img/ui/field_calendar.png +++ /dev/null diff --git a/addons/base/static/src/img/ui/group-expanded.png b/addons/base/static/src/img/ui/group-expanded.png Binary files differdeleted file mode 100644 index 3f16536e123..00000000000 --- a/addons/base/static/src/img/ui/group-expanded.png +++ /dev/null diff --git a/addons/base/static/src/img/ui/group-folded.png b/addons/base/static/src/img/ui/group-folded.png Binary files differdeleted file mode 100644 index 2909b0c268f..00000000000 --- a/addons/base/static/src/img/ui/group-folded.png +++ /dev/null diff --git a/addons/base/static/src/img/warning.png b/addons/base/static/src/img/warning.png Binary files differdeleted file mode 100644 index cbfb25a89cd..00000000000 --- a/addons/base/static/src/img/warning.png +++ /dev/null diff --git a/addons/base/static/src/js/boot.js b/addons/base/static/src/js/boot.js deleted file mode 100644 index 8fe62d2e5a4..00000000000 --- a/addons/base/static/src/js/boot.js +++ /dev/null @@ -1,67 +0,0 @@ -/*--------------------------------------------------------- - * OpenERP Web Boostrap Code - *---------------------------------------------------------*/ - -/** - * @name openerp - * @namespace openerp - * @namespace window.openerp - */ -(function() { - if (this.openerp) - return; - var session_counter = 0; - - var openerp = this.openerp = { - // Per session namespace - // openerp.<module> will map to - // openerp.sessions.sessionname.<module> using a closure - sessions: {}, - /** - * OpenERP instance constructor - * - * @param {Boolean} skip_init if true, skips the built-in initialization - */ - init: function(skip_init) { - var new_instance = { - // links to the global openerp - _openerp: openerp, - // Only base will be loaded, the rest will be by loaded by - // openerp.base.Connection on the first connection - _modules_loaded: false, - // this unique id will be replaced by hostname_databasename by - // openerp.base.Connection on the first connection - _session_id: "session" + session_counter++, - base: {}, - web_mobile: {} - }; - openerp.sessions[new_instance._session_id] = new_instance; - if (!skip_init){ - openerp.base(new_instance); - } - return new_instance; - } - }; -})(); - -/*--------------------------------------------------------- - * OpenERP Web base module split - *---------------------------------------------------------*/ - -openerp.base = function(instance) { - openerp.base.core(instance); - if (openerp.base.dates) { - openerp.base.dates(instance); - } - openerp.base.formats(instance); - openerp.base.chrome(instance); - openerp.base.data(instance); - files = ["views","search","list","form","list_editable","web_mobile","view_tree","data_export","view_editor"]; - for(i=0; i<files.length; i++) { - if(openerp.base[files[i]]) { - openerp.base[files[i]](instance); - } - } -}; - -// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/base/static/src/js/chrome.js b/addons/base/static/src/js/chrome.js deleted file mode 100644 index ee20e393d67..00000000000 --- a/addons/base/static/src/js/chrome.js +++ /dev/null @@ -1,940 +0,0 @@ -/*--------------------------------------------------------- - * OpenERP Web chrome - *---------------------------------------------------------*/ - -openerp.base.chrome = function(openerp) { - -openerp.base.Notification = openerp.base.Widget.extend({ - init: function(parent, element_id) { - this._super(parent, element_id); - this.$element.notify({ - speed: 500, - expires: 1500 - }); - }, - notify: function(title, text) { - this.$element.notify('create', { - title: title, - text: text - }); - }, - warn: function(title, text) { - this.$element.notify('create', 'oe_notification_alert', { - title: title, - text: text - }); - } -}); - -openerp.base.Dialog = openerp.base.OldWidget.extend({ - dialog_title: "", - identifier_prefix: 'dialog', - init: function (parent, dialog_options) { - var self = this; - this._super(parent); - this.dialog_options = { - modal: true, - width: 'auto', - min_width: 0, - max_width: '100%', - height: 'auto', - min_height: 0, - max_height: '100%', - autoOpen: false, - buttons: {}, - beforeClose: function () { self.on_close(); } - }; - for (var f in this) { - if (f.substr(0, 10) == 'on_button_') { - this.dialog_options.buttons[f.substr(10)] = this[f]; - } - } - if (dialog_options) { - this.set_options(dialog_options); - } - }, - set_options: function(options) { - options = options || {}; - options.width = this.get_width(options.width || this.dialog_options.width); - options.min_width = this.get_width(options.min_width || this.dialog_options.min_width); - options.max_width = this.get_width(options.max_width || this.dialog_options.max_width); - options.height = this.get_height(options.height || this.dialog_options.height); - options.min_height = this.get_height(options.min_height || this.dialog_options.min_height); - options.max_height = this.get_height(options.max_height || this.dialog_options.max_width); - - if (options.width !== 'auto') { - if (options.width > options.max_width) options.width = options.max_width; - if (options.width < options.min_width) options.width = options.min_width; - } - if (options.height !== 'auto') { - if (options.height > options.max_height) options.height = options.max_height; - if (options.height < options.min_height) options.height = options.min_height; - } - if (!options.title && this.dialog_title) { - options.title = this.dialog_title; - } - _.extend(this.dialog_options, options); - }, - get_width: function(val) { - return this.get_size(val.toString(), $(window.top).width()); - }, - get_height: function(val) { - return this.get_size(val.toString(), $(window.top).height()); - }, - get_size: function(val, available_size) { - if (val === 'auto') { - return val; - } else if (val.slice(-1) == "%") { - return Math.round(available_size / 100 * parseInt(val.slice(0, -1), 10)); - } else { - return parseInt(val, 10); - } - }, - start: function () { - this.$dialog = $('<div id="' + this.element_id + '"></div>').dialog(this.dialog_options); - this._super(); - return this; - }, - open: function(dialog_options) { - // TODO fme: bind window on resize - if (this.template) { - this.$element.html(this.render()); - } - this.set_options(dialog_options); - this.$dialog.dialog(this.dialog_options).dialog('open'); - return this; - }, - close: function() { - // Closes the dialog but leave it in a state where it could be opened again. - this.$dialog.dialog('close'); - }, - on_close: function() { - }, - stop: function () { - // Destroy widget - this.close(); - this.$dialog.dialog('destroy'); - } -}); - -openerp.base.CrashManager = openerp.base.Dialog.extend({ - identifier_prefix: 'dialog_crash', - init: function(parent) { - this._super(parent); - this.session.on_rpc_error.add(this.on_rpc_error); - }, - on_button_Ok: function() { - this.close(); - }, - on_rpc_error: function(error) { - this.error = error; - if (error.data.fault_code) { - var split = error.data.fault_code.split('\n')[0].split(' -- '); - if (split.length > 1) { - error.type = split.shift(); - error.data.fault_code = error.data.fault_code.substr(error.type.length + 4); - } - } - if (error.code === 200 && error.type) { - this.dialog_title = "OpenERP " + _.capitalize(error.type); - this.template = 'DialogWarning'; - this.open({ - width: 'auto', - height: 'auto' - }); - } else { - this.dialog_title = "OpenERP Error"; - this.template = 'DialogTraceback'; - this.open({ - width: 'auto', - height: 'auto' - }); - } - } -}); - -openerp.base.Loading = openerp.base.Widget.extend({ - init: function(parent, element_id) { - this._super(parent, element_id); - this.count = 0; - this.session.on_rpc_request.add_first(this.on_rpc_event, 1); - this.session.on_rpc_response.add_last(this.on_rpc_event, -1); - }, - on_rpc_event : function(increment) { - this.count += increment; - if (this.count) { - //this.$element.html(QWeb.render("Loading", {})); - this.$element.html("Loading ("+this.count+")"); - this.$element.show(); - } else { - this.$element.fadeOut(); - } - } -}); - -openerp.base.Database = openerp.base.Widget.extend({ - init: function(parent, element_id, option_id) { - this._super(parent, element_id); - this.$option_id = $('#' + option_id); - }, - start: function() { - this.$element.html(QWeb.render("Database", this)); - this.$element.closest(".openerp") - .removeClass("login-mode") - .addClass("database_block"); - - var self = this; - - var fetch_db = this.rpc("/base/database/get_list", {}, function(result) { - self.db_list = result.db_list; - }); - var fetch_langs = this.rpc("/base/session/get_lang_list", {}, function(result) { - if (result.error) { - self.display_error(result); - return; - } - self.lang_list = result.lang_list; - }); - $.when(fetch_db, fetch_langs).then(function () {self.do_create();}); - - this.$element.find('#db-create').click(this.do_create); - this.$element.find('#db-drop').click(this.do_drop); - this.$element.find('#db-backup').click(this.do_backup); - this.$element.find('#db-restore').click(this.do_restore); - this.$element.find('#db-change-password').click(this.do_change_password); - this.$element.find('#back-to-login').click(function() { - self.stop(); - }); - }, - stop: function () { - this.$option_id.empty(); - - this.$element - .find('#db-create, #db-drop, #db-backup, #db-restore, #db-change-password, #back-to-login') - .unbind('click') - .end() - .closest(".openerp") - .addClass("login-mode") - .removeClass("database_block") - .end() - .empty(); - - }, - /** - * Converts a .serializeArray() result into a dict. Does not bother folding - * multiple identical keys into an array, last key wins. - * - * @param {Array} array - */ - to_object: function (array) { - var result = {}; - _(array).each(function (record) { - result[record.name] = record.value; - }); - return result; - }, - /** - * Waits until the new database is done creating, then unblocks the UI and - * logs the user in as admin - * - * @param {Number} db_creation_id identifier for the db-creation operation, used to fetch the current installation progress - * @param {Object} info info fields for this database creation - * @param {String} info.db name of the database being created - * @param {String} info.password super-admin password for the database - */ - wait_for_newdb: function (db_creation_id, info) { - var self = this; - self.rpc('/base/database/progress', { - id: db_creation_id, - password: info.password - }, function (result) { - var progress = result[0]; - // I'd display a progress bar, but turns out the progress status - // the server report kind-of blows goats: it's at 0 for ~75% of - // the installation, then jumps to 75%, then jumps down to either - // 0 or ~40%, then back up to 75%, then terminates. Let's keep that - // mess hidden behind a not-very-useful but not overly weird - // message instead. - if (progress < 1) { - setTimeout(function () { - self.wait_for_newdb(db_creation_id, info); - }, 500); - return; - } - - var admin = result[1][0]; - setTimeout(function () { - self.stop(); - self.widget_parent.do_login( - info.db, admin.login, admin.password); - $.unblockUI(); - }); - }); - }, - /** - * Displays an error dialog resulting from the various RPC communications - * failing over themselves - * - * @param {Object} error error description - * @param {String} error.title title of the error dialog - * @param {String} error.error message of the error dialog - */ - display_error: function (error) { - return $('<div>').dialog({ - modal: true, - title: error.title, - buttons: { - Ok: function() { - $(this).dialog("close"); - } - } - }).html(error.error); - }, - do_create: function() { - var self = this; - self.$option_id.html(QWeb.render("Database.CreateDB", self)); - self.$option_id.find("form[name=create_db_form]").validate({ - submitHandler: function (form) { - var fields = $(form).serializeArray(); - $.blockUI({message:'<img src="/base/static/src/img/throbber2.gif">'}); - self.rpc("/base/database/create", {'fields': fields}, function(result) { - if (result.error) { - $.unblockUI(); - self.display_error(result); - return; - } - self.db_list.push(self.to_object(fields)['db_name']); - self.db_list.sort(); - var form_obj = self.to_object(fields); - self.wait_for_newdb(result, { - password: form_obj['super_admin_pwd'], - db: form_obj['db_name'] - }); - }); - } - }); - }, - do_drop: function() { - var self = this; - self.$option_id.html(QWeb.render("DropDB", self)); - self.$option_id.find("form[name=drop_db_form]").validate({ - submitHandler: function (form) { - var $form = $(form), - fields = $form.serializeArray(), - $db_list = $form.find('select[name=drop_db]'), - db = $db_list.val(); - - if (!confirm("Do you really want to delete the database: " + db + " ?")) { - return; - } - self.rpc("/base/database/drop", {'fields': fields}, function(result) { - if (result.error) { - self.display_error(result); - return; - } - $db_list.find(':selected').remove(); - self.db_list.splice(_.indexOf(self.db_list, db, true), 1); - self.notification.notify("Dropping database", "The database '" + db + "' has been dropped"); - }); - } - }); - }, - wait_for_file: function (token, cleanup) { - var self = this, - cookie_name = 'fileToken', - cookie_length = cookie_name.length; - this.backup_timer = setInterval(function () { - var cookies = document.cookie.split(';'); - for(var i=0; i<cookies.length; ++i) { - var cookie = cookies[i].replace(/^\s*/, ''); - if(!cookie.indexOf(cookie_name) === 0) { continue; } - var cookie_val = cookie.substring(cookie_length + 1); - if(parseInt(cookie_val, 10) !== token) { continue; } - - // clear waiter - clearInterval(self.backup_timer); - // clear cookie - document.cookie = _.sprintf("%s=;expires=%s;path=/", - cookie_name, new Date().toGMTString()); - - if (cleanup) { cleanup(); } - } - }, 200); - }, - do_backup: function() { - var self = this; - self.$option_id.html(QWeb.render("BackupDB", self)); - - self.$option_id.find("form[name=backup_db_form]").validate({ - submitHandler: function (form) { - $.blockUI({message:'<img src="/base/static/src/img/throbber2.gif">'}); - // need to detect when the file is done downloading (not used - // yet, but we'll need it to fix the UI e.g. with a throbber - // while dump is being generated), iframe load event only fires - // when the iframe content loads, so we need to go smarter: - // http://geekswithblogs.net/GruffCode/archive/2010/10/28/detecting-the-file-download-dialog-in-the-browser.aspx - var $target = $('#backup-target'), - token = new Date().getTime(); - if (!$target.length) { - $target = $('<iframe id="backup-target" style="display: none;">') - .appendTo(document.body) - .load(function () { - $.unblockUI(); - clearInterval(self.backup_timer); - var error = this.contentDocument.body - .firstChild.data - .split('|'); - self.display_error({ - title: error[0], - error: error[1] - }); - }); - } - $(form).find('input[name=token]').val(token); - form.submit(); - - self.wait_for_file(token, function () { - $.unblockUI(); - }); - } - }); - }, - do_restore: function() { - var self = this; - self.$option_id.html(QWeb.render("RestoreDB", self)); - - self.$option_id.find("form[name=restore_db_form]").validate({ - submitHandler: function (form) { - $.blockUI({message:'<img src="/base/static/src/img/throbber2.gif">'}); - $(form).ajaxSubmit({ - url: '/base/database/restore', - type: 'POST', - resetForm: true, - success: function (body) { - // TODO: ui manipulations - // note: response objects don't work, but we have the - // HTTP body of the response~~ - - // If empty body, everything went fine - if (!body) { return; } - - if (body.indexOf('403 Forbidden') !== -1) { - self.display_error({ - title: 'Access Denied', - error: 'Incorrect super-administrator password' - }) - } else { - self.display_error({ - title: 'Restore Database', - error: 'Could not restore the database' - }) - } - }, - complete: function () { - $.unblockUI(); - } - }); - } - }); - }, - do_change_password: function() { - var self = this; - self.$option_id.html(QWeb.render("Change_DB_Pwd", self)); - - self.$option_id.find("form[name=change_pwd_form]").validate({ - messages: { - old_pwd: "Please enter your previous password", - new_pwd: "Please enter your new password", - confirm_pwd: { - required: "Please confirm your new password", - equalTo: "The confirmation does not match the password" - } - }, - submitHandler: function (form) { - self.rpc("/base/database/change_password", { - 'fields': $(form).serializeArray() - }, function(result) { - if (result.error) { - self.display_error(result); - return; - } - self.notification.notify("Changed Password", "Password has been changed successfully"); - }); - } - }); - } -}); - -openerp.base.Login = openerp.base.Widget.extend({ - remember_creditentials: true, - - init: function(parent, element_id) { - this._super(parent, element_id); - this.has_local_storage = typeof(localStorage) != 'undefined'; - this.selected_db = null; - this.selected_login = null; - - if (this.has_local_storage && this.remember_creditentials) { - this.selected_db = localStorage.getItem('last_db_login_success'); - this.selected_login = localStorage.getItem('last_login_login_success'); - } - if (jQuery.deparam(jQuery.param.querystring()).debug != undefined) { - this.selected_password = this.selected_password || "a"; - } - }, - start: function() { - var self = this; - this.rpc("/base/database/get_list", {}, function(result) { - self.db_list = result.db_list; - self.display(); - }, function() { - self.display(); - }); - }, - display: function() { - var self = this; - - this.$element.html(QWeb.render("Login", this)); - this.database = new openerp.base.Database( - this, "oe_database", "oe_db_options"); - - this.$element.find('#oe-db-config').click(function() { - self.database.start(); - }); - - this.$element.find("form").submit(this.on_submit); - }, - on_login_invalid: function() { - this.$element.closest(".openerp").addClass("login-mode"); - }, - on_login_valid: function() { - this.$element.closest(".openerp").removeClass("login-mode"); - }, - on_submit: function(ev) { - ev.preventDefault(); - var $e = this.$element; - var db = $e.find("form [name=db]").val(); - var login = $e.find("form input[name=login]").val(); - var password = $e.find("form input[name=password]").val(); - - this.do_login(db, login, password); - }, - /** - * Performs actual login operation, and UI-related stuff - * - * @param {String} db database to log in - * @param {String} login user login - * @param {String} password user password - */ - do_login: function (db, login, password) { - var self = this; - this.session.session_login(db, login, password, function() { - if(self.session.session_is_valid()) { - if (self.has_local_storage) { - if(self.remember_creditentials) { - localStorage.setItem('last_db_login_success', db); - localStorage.setItem('last_login_login_success', login); - } else { - localStorage.setItem('last_db_login_success', ''); - localStorage.setItem('last_login_login_success', ''); - } - } - self.on_login_valid(); - } else { - self.$element.addClass("login_invalid"); - self.on_login_invalid(); - } - }); - }, - do_ask_login: function(continuation) { - this.on_login_invalid(); - this.$element - .removeClass("login_invalid"); - this.on_login_valid.add({ - position: "last", - unique: true, - callback: continuation - }); - }, - on_logout: function() { - this.session.logout(); - } -}); - -openerp.base.Header = openerp.base.Widget.extend({ - template: "Header", - identifier_prefix: 'oe-app-header-', - init: function(parent) { - this._super(parent); - this.qs = "?" + jQuery.param.querystring(); - this.$content = $(); - }, - start: function() { - this._super(); - }, - do_update: function () { - this.$content = $(QWeb.render("Header-content", {widget: this})); - this.$content.appendTo(this.$element); - this.$element.find(".logout").click(this.on_logout); - this.$element.find("a.preferences").click(this.on_preferences); - return this.shortcut_load(); - }, - do_reset: function() { - this.$content.remove(); - }, - shortcut_load :function(){ - var self = this, - sc = self.session.shortcuts, - shortcuts_ds = new openerp.base.DataSet(this, 'ir.ui.view_sc'); - // TODO: better way to communicate between sections. - // sc.bindings, because jquery does not bind/trigger on arrays... - if (!sc.binding) { - sc.binding = {}; - $(sc.binding).bind({ - 'add': function (e, attrs) { - shortcuts_ds.create(attrs, function (out) { - $('<li>', { - 'data-shortcut-id':out.result, - 'data-id': attrs.res_id - }).text(attrs.name) - .appendTo(self.$element.find('.oe-shortcuts ul')); - attrs.id = out.result; - sc.push(attrs); - }); - }, - 'remove-current': function () { - var menu_id = self.session.active_id; - var $shortcut = self.$element - .find('.oe-shortcuts li[data-id=' + menu_id + ']'); - var shortcut_id = $shortcut.data('shortcut-id'); - $shortcut.remove(); - shortcuts_ds.unlink([shortcut_id]); - var sc_new = _.reject(sc, function(shortcut){ return shortcut_id === shortcut.id}); - sc.splice(0, sc.length); - sc.push.apply(sc, sc_new); - } - }); - } - return this.rpc('/base/session/sc_list', {}, function(shortcuts) { - sc.splice(0, sc.length); - sc.push.apply(sc, shortcuts); - - self.$element.find('.oe-shortcuts') - .html(QWeb.render('Shortcuts', {'shortcuts': shortcuts})) - .undelegate('li', 'click') - - .delegate('li', 'click', function(e) { - e.stopPropagation(); - var id = $(this).data('id'); - self.session.active_id = id; - self.rpc('/base/menu/action', {'menu_id':id}, function(ir_menu_data) { - if (ir_menu_data.action.length){ - self.on_action(ir_menu_data.action[0][2]); - } - }); - }); - }); - }, - - on_action: function(action) { - }, - on_preferences: function(){ - var self = this; - var action_manager = new openerp.base.ActionManager(this); - var dataset = new openerp.base.DataSet (this,'res.users',this.context); - dataset.call ('action_get','',function (result){ - self.rpc('/base/action/load', {action_id:result}, function(result){ - action_manager.do_action(_.extend(result['result'], { - res_id: self.session.uid, - res_model: 'res.users', - flags: { - action_buttons: false, - search_view: false, - sidebar: false, - views_switcher: false, - pager: false - } - })); - }); - }); - this.dialog = new openerp.base.Dialog(this,{ - modal: true, - title: 'Preferences', - width: 600, - height: 500, - buttons: { - "Change password": function(){ - self.change_password(); - }, - Cancel: function(){ - $(this).dialog('destroy'); - }, - Save: function(){ - var inner_viewmanager = action_manager.inner_viewmanager; - inner_viewmanager.views[inner_viewmanager.active_view].controller.do_save(function(){ - inner_viewmanager.start(); - }); - $(this).dialog('destroy') - } - } - }); - this.dialog.start().open(); - action_manager.appendTo(this.dialog); - action_manager.render(this.dialog); - }, - - change_password :function() { - var self = this; - this.dialog = new openerp.base.Dialog(this,{ - modal : true, - title : 'Change Password', - width : 'auto', - height : 'auto' - }); - this.dialog.start().open(); - this.dialog.$element.html(QWeb.render("Change_Pwd", self)); - this.dialog.$element.find("form[name=change_password_form]").validate({ - submitHandler: function (form) { - self.rpc("/base/session/change_password",{ - 'fields': $(form).serializeArray() - }, function(result) { - if (result.error) { - self.display_error(result); - return; - } - else { - if (result.new_password) { - self.session.password = result.new_password; - var session = new openerp.base.Session(self.session.server, self.session.port); - session.start(); - session.session_login(self.session.db, self.session.login, self.session.password) - } - } - self.notification.notify("Changed Password", "Password has been changed successfully"); - self.dialog.close(); - }); - } - }); -}, - display_error: function (error) { - return $('<div>').dialog({ - modal: true, - title: error.title, - buttons: { - Ok: function() { - $(this).dialog("close"); - } - } - }).html(error.error); - }, - on_logout: function() { - this.$element.find('.oe-shortcuts ul').empty(); - } -}); - -openerp.base.Menu = openerp.base.Widget.extend({ - init: function(parent, element_id, secondary_menu_id) { - this._super(parent, element_id); - this.secondary_menu_id = secondary_menu_id; - this.$secondary_menu = $("#" + secondary_menu_id).hide(); - this.menu = false; - }, - start: function() { - this.rpc("/base/menu/load", {}, this.on_loaded); - }, - on_loaded: function(data) { - this.data = data; - this.$element.html(QWeb.render("Menu", this.data)); - for (var i = 0; i < this.data.data.children.length; i++) { - var v = { menu : this.data.data.children[i] }; - this.$secondary_menu.append(QWeb.render("Menu.secondary", v)); - } - this.$secondary_menu.find("div.menu_accordion").accordion({ - animated : false, - autoHeight : false, - icons : false - }); - this.$secondary_menu.find("div.submenu_accordion").accordion({ - animated : false, - autoHeight : false, - active: false, - collapsible: true, - header: 'h4' - }); - - this.$element.add(this.$secondary_menu).find("a").click(this.on_menu_click); - }, - on_menu_click: function(ev, id) { - id = id || 0; - var $menu, $parent, $secondary; - - if (id) { - // We can manually activate a menu with it's id (for hash url mapping) - $menu = this.$element.find('a[data-menu=' + id + ']'); - if (!$menu.length) { - $menu = this.$secondary_menu.find('a[data-menu=' + id + ']'); - } - } else { - $menu = $(ev.currentTarget); - id = $menu.data('menu'); - } - if (this.$secondary_menu.has($menu).length) { - $secondary = $menu.parents('.menu_accordion'); - $parent = this.$element.find('a[data-menu=' + $secondary.data('menu-parent') + ']'); - } else { - $parent = $menu; - $secondary = this.$secondary_menu.find('.menu_accordion[data-menu-parent=' + $menu.attr('data-menu') + ']'); - } - - this.$secondary_menu.find('.menu_accordion').hide(); - // TODO: ui-accordion : collapse submenus and expand the good one - $secondary.show(); - - if (id) { - this.session.active_id = id; - this.rpc('/base/menu/action', {'menu_id': id}, - this.on_menu_action_loaded); - } - - $('.active', this.$element.add(this.$secondary_menu.show())).removeClass('active'); - $parent.addClass('active'); - $menu.addClass('active'); - $menu.parent('h4').addClass('active'); - - return !$menu.is(".leaf"); - }, - on_menu_action_loaded: function(data) { - var self = this; - if (data.action.length) { - var action = data.action[0][2]; - self.on_action(action); - } - }, - on_action: function(action) { - } -}); - -openerp.base.Homepage = openerp.base.Widget.extend({ -}); - -openerp.base.Preferences = openerp.base.Widget.extend({ -}); - -openerp.base.WebClient = openerp.base.Widget.extend({ - init: function(element_id) { - this._super(null, element_id); - openerp.webclient = this; - - QWeb.add_template("/base/static/src/xml/base.xml"); - var params = {}; - if(jQuery.param != undefined && jQuery.deparam(jQuery.param.querystring()).kitten != undefined) { - this.$element.addClass("kitten-mode-activated"); - } - this.$element.html(QWeb.render("Interface", params)); - - this.session = new openerp.base.Session(); - this.loading = new openerp.base.Loading(this,"oe_loading"); - this.crashmanager = new openerp.base.CrashManager(this); - this.crashmanager.start(); - - // Do you autorize this ? will be replaced by notify() in controller - openerp.base.Widget.prototype.notification = new openerp.base.Notification(this, "oe_notification"); - - - this.header = new openerp.base.Header(this); - this.login = new openerp.base.Login(this, "oe_login"); - this.header.on_logout.add(this.login.on_logout); - this.header.on_action.add(this.on_menu_action); - - this.session.on_session_invalid.add(this.login.do_ask_login); - this.session.on_session_valid.add_last(this.header.do_update); - this.session.on_session_invalid.add_last(this.header.do_reset); - this.session.on_session_valid.add_last(this.on_logged); - - this.menu = new openerp.base.Menu(this, "oe_menu", "oe_secondary_menu"); - this.menu.on_action.add(this.on_menu_action); - }, - start: function() { - this.header.appendTo($("#oe_header")); - this.session.start(); - this.login.start(); - this.menu.start(); - this.notification.notify("OpenERP Client", "The openerp client has been initialized."); - }, - on_logged: function() { - if(this.action_manager) - this.action_manager.stop(); - this.action_manager = new openerp.base.ActionManager(this); - this.action_manager.appendTo($("#oe_app")); - - // if using saved actions, load the action and give it to action manager - var parameters = jQuery.deparam(jQuery.param.querystring()); - if (parameters["s_action"] != undefined) { - var key = parseInt(parameters["s_action"], 10); - var self = this; - this.rpc("/base/session/get_session_action", {key:key}, function(action) { - self.action_manager.do_action(action); - }); - } else if (openerp._modules_loaded) { // TODO: find better option than this - this.load_url_state() - } else { - this.session.on_modules_loaded.add({ - callback: $.proxy(this, 'load_url_state'), - unique: true, - position: 'last' - }) - } - }, - /** - * Loads state from URL if any, or checks if there is a home action and - * loads that, assuming we're at the index - */ - load_url_state: function () { - var self = this; - // TODO: add actual loading if there is url state to unpack, test on window.location.hash - - // not logged in - if (!this.session.uid) { return; } - var ds = new openerp.base.DataSetSearch(this, 'res.users'); - ds.read_ids([this.session.uid], ['action_id'], function (users) { - var home_action = users[0].action_id; - if (!home_action) { - self.default_home(); - return; - } - self.execute_home_action(home_action[0], ds); - }) - }, - default_home: function () { - }, - /** - * Bundles the execution of the home action - * - * @param {Number} action action id - * @param {openerp.base.DataSet} dataset action executor - */ - execute_home_action: function (action, dataset) { - var self = this; - this.rpc('/base/action/load', { - action_id: action, - context: dataset.get_context() - }, function (meh) { - var action = meh.result; - action.context = _.extend(action.context || {}, { - active_id: false, - active_ids: [false], - active_model: dataset.model - }); - self.action_manager.do_action(action); - }); - }, - on_menu_action: function(action) { - this.action_manager.do_action(action); - }, - do_about: function() { - } -}); - -}; - -// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/base/static/src/js/core.js b/addons/base/static/src/js/core.js deleted file mode 100644 index 4cd46504a69..00000000000 --- a/addons/base/static/src/js/core.js +++ /dev/null @@ -1,915 +0,0 @@ -/*--------------------------------------------------------- - * OpenERP Web core - *--------------------------------------------------------*/ - -openerp.base.core = function(openerp) { -/** - * John Resig Class with factory improvement - */ -(function() { - var initializing = false, - fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; - // The base Class implementation (does nothing) - /** - * @class - */ - openerp.base.Class = function(){}; - - // Create a new Class that inherits from this class - openerp.base.Class.extend = function(prop) { - var _super = this.prototype; - - // Instantiate a base class (but only create the instance, - // don't run the init constructor) - initializing = true; - var prototype = new this(); - initializing = false; - - // Copy the properties over onto the new prototype - for (var name in prop) { - // Check if we're overwriting an existing function - prototype[name] = typeof prop[name] == "function" && - typeof _super[name] == "function" && - fnTest.test(prop[name]) ? - (function(name, fn) { - return function() { - var tmp = this._super; - - // Add a new ._super() method that is the same - // method but on the super-class - this._super = _super[name]; - - // The method only need to be bound temporarily, so - // we remove it when we're done executing - var ret = fn.apply(this, arguments); - this._super = tmp; - - return ret; - }; - })(name, prop[name]) : - prop[name]; - } - - // The dummy class constructor - function Class() { - // All construction is actually done in the init method - if (!initializing && this.init) { - var ret = this.init.apply(this, arguments); - if (ret) { return ret; } - } - return this; - } - Class.include = function (properties) { - for (var name in properties) { - if (typeof properties[name] !== 'function' - || !fnTest.test(properties[name])) { - prototype[name] = properties[name]; - } else if (typeof prototype[name] === 'function' - && prototype.hasOwnProperty(name)) { - prototype[name] = (function (name, fn, previous) { - return function () { - var tmp = this._super; - this._super = previous; - var ret = fn.apply(this, arguments); - this._super = tmp; - return ret; - } - })(name, properties[name], prototype[name]); - } else if (typeof _super[name] === 'function') { - prototype[name] = (function (name, fn) { - return function () { - var tmp = this._super; - this._super = _super[name]; - var ret = fn.apply(this, arguments); - this._super = tmp; - return ret; - } - })(name, properties[name]); - } - } - }; - - // Populate our constructed prototype object - Class.prototype = prototype; - - // Enforce the constructor to be what we expect - Class.constructor = Class; - - // And make this class extendable - Class.extend = arguments.callee; - - return Class; - }; -})(); - -openerp.base.callback = function(obj, method) { - var callback = function() { - var args = Array.prototype.slice.call(arguments); - var r; - for(var i = 0; i < callback.callback_chain.length; i++) { - var c = callback.callback_chain[i]; - if(c.unique) { - callback.callback_chain.splice(i, 1); - i -= 1; - } - r = c.callback.apply(c.self, c.args.concat(args)); - // TODO special value to stop the chain - // openerp.base.callback_stop - } - return r; - }; - callback.callback_chain = []; - callback.add = function(f) { - if(typeof(f) == 'function') { - f = { callback: f, args: Array.prototype.slice.call(arguments, 1) }; - } - f.self = f.self || null; - f.args = f.args || []; - f.unique = !!f.unique; - if(f.position == 'last') { - callback.callback_chain.push(f); - } else { - callback.callback_chain.unshift(f); - } - return callback; - }; - callback.add_first = function(f) { - return callback.add.apply(null,arguments); - }; - callback.add_last = function(f) { - return callback.add({ - callback: f, - args: Array.prototype.slice.call(arguments, 1), - position: "last" - }); - }; - - return callback.add({ - callback: method, - self:obj, - args:Array.prototype.slice.call(arguments, 2) - }); -}; - -/** - * Generates an inherited class that replaces all the methods by null methods (methods - * that does nothing and always return undefined). - * - * @param {Class} claz - * @param {dict} add Additional functions to override. - * @return {Class} - */ -openerp.base.generate_null_object_class = function(claz, add) { - var newer = {}; - var copy_proto = function(prototype) { - for (var name in prototype) { - if(typeof prototype[name] == "function") { - newer[name] = function() {}; - } - } - if (prototype.prototype) - copy_proto(prototype.prototype); - }; - copy_proto(claz.prototype); - newer.init = openerp.base.Widget.prototype.init; - var tmpclass = claz.extend(newer); - return tmpclass.extend(add || {}); -}; - -/** - * Base error for lookup failure - * - * @class - */ -openerp.base.NotFound = openerp.base.Class.extend( /** @lends openerp.base.NotFound# */ { -}); -openerp.base.KeyNotFound = openerp.base.NotFound.extend( /** @lends openerp.base.KeyNotFound# */ { - /** - * Thrown when a key could not be found in a mapping - * - * @constructs - * @extends openerp.base.NotFound - * @param {String} key the key which could not be found - */ - init: function (key) { - this.key = key; - }, - toString: function () { - return "The key " + this.key + " was not found"; - } -}); -openerp.base.ObjectNotFound = openerp.base.NotFound.extend( /** @lends openerp.base.ObjectNotFound# */ { - /** - * Thrown when an object path does not designate a valid class or object - * in the openerp hierarchy. - * - * @constructs - * @extends openerp.base.NotFound - * @param {String} path the invalid object path - */ - init: function (path) { - this.path = path; - }, - toString: function () { - return "Could not find any object of path " + this.path; - } -}); -openerp.base.Registry = openerp.base.Class.extend( /** @lends openerp.base.Registry# */ { - /** - * Stores a mapping of arbitrary key (strings) to object paths (as strings - * as well). - * - * Resolves those paths at query time in order to always fetch the correct - * object, even if those objects have been overloaded/replaced after the - * registry was created. - * - * An object path is simply a dotted name from the openerp root to the - * object pointed to (e.g. ``"openerp.base.Session"`` for an OpenERP - * session object). - * - * @constructs - * @param {Object} mapping a mapping of keys to object-paths - */ - init: function (mapping) { - this.map = mapping || {}; - }, - /** - * Retrieves the object matching the provided key string. - * - * @param {String} key the key to fetch the object for - * @returns {Class} the stored class, to initialize - * - * @throws {openerp.base.KeyNotFound} if the object was not in the mapping - * @throws {openerp.base.ObjectNotFound} if the object path was invalid - */ - get_object: function (key) { - var path_string = this.map[key]; - if (path_string === undefined) { - throw new openerp.base.KeyNotFound(key); - } - - var object_match = openerp; - var path = path_string.split('.'); - // ignore first section - for(var i=1; i<path.length; ++i) { - object_match = object_match[path[i]]; - - if (object_match === undefined) { - throw new openerp.base.ObjectNotFound(path_string); - } - } - return object_match; - }, - /** - * Tries a number of keys, and returns the first object matching one of - * the keys. - * - * @param {Array} keys a sequence of keys to fetch the object for - * @returns {Class} the first class found matching an object - * - * @throws {openerp.base.KeyNotFound} if none of the keys was in the mapping - * @trows {openerp.base.ObjectNotFound} if a found object path was invalid - */ - get_any: function (keys) { - for (var i=0; i<keys.length; ++i) { - try { - return this.get_object(keys[i]); - } catch (e) { - if (e instanceof openerp.base.KeyNotFound) { - continue; - } - throw e; - } - } - throw new openerp.base.KeyNotFound(keys.join(',')); - }, - /** - * Adds a new key and value to the registry. - * - * This method can be chained. - * - * @param {String} key - * @param {String} object_path fully qualified dotted object path - * @returns {openerp.base.Registry} itself - */ - add: function (key, object_path) { - this.map[key] = object_path; - return this; - }, - /** - * Creates and returns a copy of the current mapping, with the provided - * mapping argument added in (replacing existing keys if needed) - * - * @param {Object} [mapping={}] a mapping of keys to object-paths - */ - clone: function (mapping) { - return new openerp.base.Registry( - _.extend({}, this.map, mapping || {})); - } -}); - -openerp.base.CallbackEnabled = openerp.base.Class.extend({ - init: function() { - // Transform on_* method into openerp.base.callbacks - for (var name in this) { - if(typeof(this[name]) == "function") { - this[name].debug_name = name; - // bind ALL function to this not only on_and _do ? - if((/^on_|^do_/).test(name)) { - this[name] = openerp.base.callback(this, this[name]); - } - } - } - } -}); - -openerp.base.Session = openerp.base.CallbackEnabled.extend( /** @lends openerp.base.Session# */{ - /** - * @constructs - * @param server - * @param port - */ - init: function(server, port) { - this._super(); - this.server = (server == undefined) ? location.hostname : server; - this.port = (port == undefined) ? location.port : port; - this.rpc_mode = (server == location.hostname) ? "ajax" : "jsonp"; - this.debug = (window.location.search.indexOf('?debug') !== -1); - this.db = ""; - this.login = ""; - this.password = ""; - this.user_context= {}; - this.uid = false; - this.session_id = false; - this.module_list = []; - this.module_loaded = {"base": true}; - this.context = {}; - this.shortcuts = []; - this.active_id = null; - this.session = this; - }, - start: function() { - this.session_restore(); - }, - /** - * Executes an RPC call, registering the provided callbacks. - * - * Registers a default error callback if none is provided, and handles - * setting the correct session id and session context in the parameter - * objects - * - * @param {String} url RPC endpoint - * @param {Object} params call parameters - * @param {Function} success_callback function to execute on RPC call success - * @param {Function} error_callback function to execute on RPC call failure - * @returns {jQuery.Deferred} jquery-provided ajax deferred - */ - rpc: function(url, params, success_callback, error_callback) { - var self = this; - // Construct a JSON-RPC2 request, method is currently unused - params.session_id = this.session_id; - - // Call using the rpc_mode - var deferred = $.Deferred(); - this.rpc_ajax(url, { - jsonrpc: "2.0", - method: "call", - params: params, - id:null - }).then(function () {deferred.resolve.apply(deferred, arguments);}, - function(error) {deferred.reject(error, $.Event());}); - return deferred.fail(function() { - deferred.fail(function(error, event) { - if (!event.isDefaultPrevented()) { - self.on_rpc_error(error, event); - } - }); - }).then(success_callback, error_callback).promise(); - }, - /** - * Raw JSON-RPC call - * - * @returns {jQuery.Deferred} ajax-based deferred object - */ - rpc_ajax: function(url, payload) { - var self = this; - this.on_rpc_request(); - // url can be an $.ajax option object - if (_.isString(url)) { - url = { - url: url - } - } - var ajax = _.extend({ - type: "POST", - url: url, - dataType: 'json', - contentType: 'application/json', - data: JSON.stringify(payload), - processData: false - }, url); - var deferred = $.Deferred(); - $.ajax(ajax).done(function(response, textStatus, jqXHR) { - self.on_rpc_response(); - if (!response.error) { - deferred.resolve(response["result"], textStatus, jqXHR); - return; - } - if (response.error.data.type !== "session_invalid") { - deferred.reject(response.error); - return; - } - self.uid = false; - self.on_session_invalid(function() { - self.rpc(url, payload.params, - function() { - deferred.resolve.apply(deferred, arguments); - }, - function(error, event) { - event.preventDefault(); - deferred.reject.apply(deferred, arguments); - }); - }); - }).fail(function(jqXHR, textStatus, errorThrown) { - self.on_rpc_response(); - var error = { - code: -32098, - message: "XmlHttpRequestError " + errorThrown, - data: {type: "xhr"+textStatus, debug: jqXHR.responseText, objects: [jqXHR, errorThrown] } - }; - deferred.reject(error); - }); - return deferred.promise(); - }, - on_rpc_request: function() { - }, - on_rpc_response: function() { - }, - on_rpc_error: function(error) { - }, - /** - * The session is validated either by login or by restoration of a previous session - */ - on_session_valid: function() { - if(!openerp._modules_loaded) - this.load_modules(); - }, - on_session_invalid: function(contination) { - }, - session_is_valid: function() { - return this.uid; - }, - session_login: function(db, login, password, success_callback) { - var self = this; - this.db = db; - this.login = login; - this.password = password; - var params = { db: this.db, login: this.login, password: this.password }; - this.rpc("/base/session/login", params, function(result) { - self.session_id = result.session_id; - self.uid = result.uid; - self.user_context = result.context; - self.session_save(); - self.on_session_valid(); - if (success_callback) - success_callback(); - }); - }, - session_logout: function() { - this.uid = false; - }, - /** - * Reloads uid and session_id from local storage, if they exist - */ - session_restore: function () { - this.uid = this.get_cookie('uid'); - this.session_id = this.get_cookie('session_id'); - this.db = this.get_cookie('db'); - this.login = this.get_cookie('login'); - this.user_context = this.get_cookie("user_context"); - // we should do an rpc to confirm that this session_id is valid and if it is retrieve the information about db and login - // then call on_session_valid - this.on_session_valid(); - }, - /** - * Saves the session id and uid locally - */ - session_save: function () { - this.set_cookie('uid', this.uid); - this.set_cookie('session_id', this.session_id); - this.set_cookie('db', this.db); - this.set_cookie('login', this.login); - this.set_cookie('user_context', this.user_context); - }, - logout: function() { - delete this.uid; - delete this.session_id; - delete this.db; - delete this.login; - this.set_cookie('uid', ''); - this.set_cookie('session_id', ''); - this.set_cookie('db', ''); - this.set_cookie('login', ''); - this.on_session_invalid(function() {}); - }, - /** - * Fetches a cookie stored by an openerp session - * - * @private - * @param name the cookie's name - */ - get_cookie: function (name) { - var nameEQ = this.element_id + '|' + name + '='; - var cookies = document.cookie.split(';'); - for(var i=0; i<cookies.length; ++i) { - var cookie = cookies[i].replace(/^\s*/, ''); - if(cookie.indexOf(nameEQ) === 0) { - return JSON.parse(decodeURIComponent(cookie.substring(nameEQ.length))); - } - } - return null; - }, - /** - * Create a new cookie with the provided name and value - * - * @private - * @param name the cookie's name - * @param value the cookie's value - * @param ttl the cookie's time to live, 1 year by default, set to -1 to delete - */ - set_cookie: function (name, value, ttl) { - ttl = ttl || 24*60*60*365; - document.cookie = [ - this.element_id + '|' + name + '=' + encodeURIComponent(JSON.stringify(value)), - 'max-age=' + ttl, - 'expires=' + new Date(new Date().getTime() + ttl*1000).toGMTString() - ].join(';'); - }, - /** - * Load additional web addons of that instance and init them - */ - load_modules: function() { - var self = this; - this.rpc('/base/session/modules', {}, function(result) { - self.module_list = result; - var lang = self.user_context.lang; - params = { mods: ["base"].concat(result), lang: lang}; - self.rpc('/base/webclient/translations',params).then(function(transs) { - openerp.base._t.database.set_bundle(transs); - var modules = self.module_list.join(','); - var file_list = ["/base/static/lib/datejs/globalization/" + - self.user_context.lang.replace("_", "-") + ".js", - - ]; - if(self.debug) { - self.rpc('/base/webclient/csslist', {"mods": modules}, self.do_load_css); - self.rpc('/base/webclient/jslist', {"mods": modules}, function(files) { - self.do_load_js(file_list.concat(files)); - }); - } else { - self.do_load_css(["/base/webclient/css?mods="+modules]); - self.do_load_js(file_list.concat(["/base/webclient/js?mods="+modules])); - } - openerp._modules_loaded = true; - }); - }); - }, - do_load_css: function (files) { - _.each(files, function (file) { - $('head').append($('<link>', { - 'href': file, - 'rel': 'stylesheet', - 'type': 'text/css' - })); - }); - }, - do_load_js: function(files) { - var self = this; - if(files.length != 0) { - var file = files.shift(); - var tag = document.createElement('script'); - tag.type = 'text/javascript'; - tag.src = file; - tag.onload = tag.onreadystatechange = function() { - if ( (tag.readyState && tag.readyState != "loaded" && tag.readyState != "complete") || tag.onload_done ) - return; - tag.onload_done = true; - self.do_load_js(files); - }; - $('head').append(tag); - self.do_load_js(files); - } else { - this.on_modules_loaded(); - } - }, - on_modules_loaded: function() { - for(var j=0; j<this.module_list.length; j++) { - var mod = this.module_list[j]; - if(this.module_loaded[mod]) - continue; - openerp[mod] = {}; - // init module mod - if(openerp._openerp[mod] != undefined) { - openerp._openerp[mod](openerp); - this.module_loaded[mod] = true; - } - } - } -}); - -/** - * Utility class that any class is allowed to extend to easy common manipulations. - * - * It provides rpc calls, callback on all methods preceded by "on_" or "do_" and a - * logging facility. - */ -openerp.base.SessionAware = openerp.base.CallbackEnabled.extend({ - init: function(session) { - this._super(); - this.session = session; - }, - /** - * Performs a JSON-RPC call - * - * @param {String} url endpoint url - * @param {Object} data RPC parameters - * @param {Function} success RPC call success callback - * @param {Function} error RPC call error callback - * @returns {jQuery.Deferred} deferred object for the RPC call - */ - rpc: function(url, data, success, error) { - return this.session.rpc(url, data, success, error); - }, - log: function() { - var args = Array.prototype.slice.call(arguments); - var caller = arguments.callee.caller; - // TODO add support for line number using - // https://github.com/emwendelin/javascript-stacktrace/blob/master/stacktrace.js - // args.unshift("" + caller.debug_name); - this.on_log.apply(this,args); - }, - on_log: function() { - if(this.session.debug) { - var notify = false; - var body = false; - if(window.console) { - console.log(arguments); - } else { - body = true; - } - var a = Array.prototype.slice.call(arguments, 0); - for(var i = 0; i < a.length; i++) { - var v = a[i]==null ? "null" : a[i].toString(); - if(i==0) { - notify = v.match(/^not/); - body = v.match(/^bod/); - } - if(body) { - $('<pre></pre>').text(v).appendTo($('body')); - } - if(notify && this.notification) { - this.notification.notify("Logging:",v); - } - } - } - } -}); - -openerp.base.Widget = openerp.base.SessionAware.extend({ - /** - * The name of the QWeb template that will be used for rendering. Must be - * redefined in subclasses or the default render() method can not be used. - * - * @type string - */ - template: null, - /** - * The prefix used to generate an id automatically. Should be redefined in - * subclasses. If it is not defined, a generic identifier will be used. - * - * @type string - */ - identifier_prefix: 'generic-identifier-', - /** - * Construct the widget and set its parent if a parent is given. - * - * @constructs - * @param {openerp.base.Widget} parent Binds the current instance to the given Widget instance. - * When that widget is destroyed by calling stop(), the current instance will be - * destroyed too. Can be null. - * @param {String} element_id Deprecated. Sets the element_id. Only useful when you want - * to bind the current Widget to an already existing part of the DOM, which is not compatible - * with the DOM insertion methods provided by the current implementation of Widget. So - * for new components this argument should not be provided any more. - */ - init: function(parent, /** @deprecated */ element_id) { - this._super((parent || {}).session); - // if given an element_id, try to get the associated DOM element and save - // a reference in this.$element. Else just generate a unique identifier. - this.element_id = element_id; - this.element_id = this.element_id || _.uniqueId(this.identifier_prefix); - var tmp = document.getElementById(this.element_id); - this.$element = tmp ? $(tmp) : undefined; - - this.widget_parent = parent; - this.widget_children = []; - if(parent && parent.widget_children) { - parent.widget_children.push(this); - } - // useful to know if the widget was destroyed and should not be used anymore - this.widget_is_stopped = false; - }, - /** - * Render the current widget and appends it to the given jQuery object or Widget. - * - * @param target A jQuery object or a Widget instance. - */ - appendTo: function(target) { - var self = this; - return this._render_and_insert(function(t) { - self.$element.appendTo(t); - }, target); - }, - /** - * Render the current widget and prepends it to the given jQuery object or Widget. - * - * @param target A jQuery object or a Widget instance. - */ - prependTo: function(target) { - var self = this; - return this._render_and_insert(function(t) { - self.$element.prependTo(t); - }, target); - }, - /** - * Render the current widget and inserts it after to the given jQuery object or Widget. - * - * @param target A jQuery object or a Widget instance. - */ - insertAfter: function(target) { - var self = this; - return this._render_and_insert(function(t) { - self.$element.insertAfter(t); - }, target); - }, - /** - * Render the current widget and inserts it before to the given jQuery object or Widget. - * - * @param target A jQuery object or a Widget instance. - */ - insertBefore: function(target) { - var self = this; - return this._render_and_insert(function(t) { - self.$element.insertBefore(t); - }, target); - }, - _render_and_insert: function(insertion, target) { - var rendered = this.render(); - this.$element = $(rendered); - if (target instanceof openerp.base.Widget) - target = target.$element; - insertion(target); - return this.start(); - }, - /** - * Renders the widget using QWeb, `this.template` must be defined. - * The context given to QWeb contains the "widget" key that references `this`. - * - * @param {Object} additional Additional context arguments to pass to the template. - */ - render: function (additional) { - return QWeb.render(this.template, _.extend({widget: this}, additional || {})); - }, - /** - * Method called after rendering. Mostly used to bind actions, perform asynchronous - * calls, etc... - * - * By convention, the method should return a promise to inform the caller when - * this widget has been initialized. - * - * @returns {jQuery.Deferred} - */ - start: function() { - if (!this.$element) { - var tmp = document.getElementById(this.element_id); - this.$element = tmp ? $(tmp) : undefined; - } - return $.Deferred().done().promise(); - }, - /** - * Destroys the current widget, also destory all its children before destroying itself. - */ - stop: function() { - _.each(_.clone(this.widget_children), function(el) { - el.stop(); - }); - if(this.$element != null) { - this.$element.remove(); - } - if (this.widget_parent && this.widget_parent.widget_children) { - this.widget_parent.widget_children = _.without(this.widget_parent.widget_children, this); - } - this.widget_parent = null; - this.widget_is_stopped = true; - }, - /** - * Inform the action manager to do an action. Of course, this suppose that - * the action manager can be found amongst the ancestors of the current widget. - * If that's not the case this method will simply return `false`. - */ - do_action: function(action, on_finished) { - if (this.widget_parent) { - return this.widget_parent.do_action(action, on_finished); - } - return false; - }, - do_notify: function() { - if (this.widget_parent) { - return this.widget_parent.do_notify.apply(this,arguments); - } - return false; - }, - do_warn: function() { - if (this.widget_parent) { - return this.widget_parent.do_warn.apply(this,arguments); - } - return false; - }, - rpc: function(url, data, success, error) { - var def = $.Deferred().then(success, error); - var self = this; - this._super(url, data). then(function() { - if (!self.widget_is_stopped) - def.resolve.apply(def, arguments); - }, function() { - if (!self.widget_is_stopped) - def.reject.apply(def, arguments); - }); - return def.promise(); - } -}); - -/** - * @deprecated - * For retro compatibility only, the only difference with is that render() uses - * directly `this` instead of context with a "widget" key. - */ -openerp.base.OldWidget = openerp.base.Widget.extend({ - render: function (additional) { - return QWeb.render(this.template, _.extend(_.extend({}, this), additional || {})); - } -}); - -openerp.base.TranslationDataBase = openerp.base.Class.extend({ - init: function() { - this.db = {}; - this.parameters = {"direction": 'ltr', - "date_format": '%m/%d/%Y', - "time_format": '%H:%M:%S', - "grouping": "[]", - "decimal_point": ".", - "thousands_sep": ","}; - }, - set_bundle: function(translation_bundle) { - var self = this; - this.db = {}; - var modules = _.keys(translation_bundle.modules).sort(); - if (_.include(modules, "base")) { - modules = ["base"].concat(_.without(modules, "base")); - } - _.each(modules, function(name) { - self.add_module_translation(translation_bundle.modules[name]); - }); - if (translation_bundle.lang_parameters) { - this.parameters = translation_bundle.lang_parameters; - } - }, - add_module_translation: function(mod) { - var self = this; - _.each(mod.messages, function(message) { - if (self.db[message.id] === undefined) { - self.db[message.id] = message.string; - } - }); - }, - build_translation_function: function() { - var self = this; - var fcnt = function(str) { - var tmp = self.get(str); - return tmp === undefined ? str : tmp; - } - fcnt.database = this; - return fcnt; - }, - get: function(key) { - if (this.db[key]) - return this.db[key]; - return undefined; - } -}); - -openerp.base._t = new openerp.base.TranslationDataBase().build_translation_function(); - -}; - -// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/base/static/src/js/data.js b/addons/base/static/src/js/data.js deleted file mode 100644 index e95adaf8870..00000000000 --- a/addons/base/static/src/js/data.js +++ /dev/null @@ -1,787 +0,0 @@ - -openerp.base.data = function(openerp) { - -/** - * Serializes the sort criterion array of a dataset into a form which can be - * consumed by OpenERP's RPC APIs. - * - * @param {Array} criterion array of fields, from first to last criteria, prefixed with '-' for reverse sorting - * @returns {String} SQL-like sorting string (``ORDER BY``) clause - */ -openerp.base.serialize_sort = function (criterion) { - return _.map(criterion, - function (criteria) { - if (criteria[0] === '-') { - return criteria.slice(1) + ' DESC'; - } - return criteria + ' ASC'; - }).join(', '); -}; - -openerp.base.DataGroup = openerp.base.Widget.extend( /** @lends openerp.base.DataGroup# */{ - /** - * Management interface between views and grouped collections of OpenERP - * records. - * - * The root DataGroup is instantiated with the relevant information - * (a session, a model, a domain, a context and a group_by sequence), the - * domain and context may be empty. It is then interacted with via - * :js:func:`~openerp.base.DataGroup.list`, which is used to read the - * content of the current grouping level. - * - * @constructs - * @extends openerp.base.Widget - * - * @param {openerp.base.Session} session Current OpenERP session - * @param {String} model name of the model managed by this DataGroup - * @param {Array} domain search domain for this DataGroup - * @param {Object} context context of the DataGroup's searches - * @param {Array} group_by sequence of fields by which to group - * @param {Number} [level=0] nesting level of the group - */ - init: function(parent, model, domain, context, group_by, level) { - this._super(parent, null); - if (group_by) { - if (group_by.length || context['group_by_no_leaf']) { - return new openerp.base.ContainerDataGroup( this, model, domain, context, group_by, level); - } else { - return new openerp.base.GrouplessDataGroup( this, model, domain, context, level); - } - } - - this.model = model; - this.context = context; - this.domain = domain; - - this.level = level || 0; - }, - cls: 'DataGroup' -}); -openerp.base.ContainerDataGroup = openerp.base.DataGroup.extend( /** @lends openerp.base.ContainerDataGroup# */ { - /** - * - * @constructs - * @extends openerp.base.DataGroup - * - * @param session - * @param model - * @param domain - * @param context - * @param group_by - * @param level - */ - init: function (parent, model, domain, context, group_by, level) { - this._super(parent, model, domain, context, null, level); - - this.group_by = group_by; - }, - /** - * The format returned by ``read_group`` is absolutely dreadful: - * - * * A ``__context`` key provides future grouping levels - * * A ``__domain`` key provides the domain for the next search - * * The current grouping value is provided through the name of the - * current grouping name e.g. if currently grouping on ``user_id``, then - * the ``user_id`` value for this group will be provided through the - * ``user_id`` key. - * * Similarly, the number of items in the group (not necessarily direct) - * is provided via ``${current_field}_count`` - * * Other aggregate fields are just dumped there - * - * This function slightly improves the grouping records by: - * - * * Adding a ``grouped_on`` property providing the current grouping field - * * Adding a ``value`` and a ``length`` properties which replace the - * ``$current_field`` and ``${current_field}_count`` ones - * * Moving aggregate values into an ``aggregates`` property object - * - * Context and domain keys remain as-is, they should not be used externally - * but in case they're needed... - * - * @param {Object} group ``read_group`` record - */ - transform_group: function (group) { - var field_name = this.group_by[0]; - // In cases where group_by_no_leaf and no group_by, the result of - // read_group has aggregate fields but no __context or __domain. - // Create default (empty) values for those so that things don't break - var fixed_group = _.extend( - {__context: {group_by: []}, __domain: []}, - group); - - var aggregates = {}; - _(fixed_group).each(function (value, key) { - if (key.indexOf('__') === 0 - || key === field_name - || key === field_name + '_count') { - return; - } - aggregates[key] = value || 0; - }); - - return { - __context: fixed_group.__context, - __domain: fixed_group.__domain, - - grouped_on: field_name, - // if terminal group (or no group) and group_by_no_leaf => use group.__count - length: fixed_group[field_name + '_count'] || fixed_group.__count, - value: fixed_group[field_name], - - openable: !(this.context['group_by_no_leaf'] - && fixed_group.__context.group_by.length === 0), - - aggregates: aggregates - }; - }, - fetch: function (fields) { - // internal method - var d = new $.Deferred(); - var self = this; - - this.rpc('/base/group/read', { - model: this.model, - context: this.context, - domain: this.domain, - fields: _.uniq(this.group_by.concat(fields)), - group_by_fields: this.group_by, - sort: openerp.base.serialize_sort(this.sort) - }, function () { }).then(function (response) { - var data_groups = _(response).map( - _.bind(self.transform_group, self)); - self.groups = data_groups; - d.resolveWith(self, [data_groups]); - }, function () { - d.rejectWith.apply(d, [self, arguments]); - }); - return d.promise(); - }, - /** - * The items of a list have the following properties: - * - * ``length`` - * the number of records contained in the group (and all of its - * sub-groups). This does *not* provide the size of the "next level" - * of the group, unless the group is terminal (no more groups within - * it). - * ``grouped_on`` - * the name of the field this level was grouped on, this is mostly - * used for display purposes, in order to know the name of the current - * level of grouping. The ``grouped_on`` should be the same for all - * objects of the list. - * ``value`` - * the value which led to this group (this is the value all contained - * records have for the current ``grouped_on`` field name). - * ``aggregates`` - * a mapping of other aggregation fields provided by ``read_group`` - * - * @param {Array} fields the list of fields to aggregate in each group, can be empty - * @param {Function} ifGroups function executed if any group is found (DataGroup.group_by is non-null and non-empty), called with a (potentially empty) list of groups as parameters. - * @param {Function} ifRecords function executed if there is no grouping left to perform, called with a DataSet instance as parameter - */ - list: function (fields, ifGroups, ifRecords) { - var self = this; - this.fetch(fields).then(function (group_records) { - ifGroups(_(group_records).map(function (group) { - var child_context = _.extend({}, self.context, group.__context); - return _.extend( - new openerp.base.DataGroup( - self, self.model, group.__domain, - child_context, child_context.group_by, - self.level + 1), - group, {sort: self.sort}); - })); - }); - } -}); -openerp.base.GrouplessDataGroup = openerp.base.DataGroup.extend( /** @lends openerp.base.GrouplessDataGroup# */ { - /** - * - * @constructs - * @extends openerp.base.DataGroup - * - * @param session - * @param model - * @param domain - * @param context - * @param level - */ - init: function (parent, model, domain, context, level) { - this._super(parent, model, domain, context, null, level); - }, - list: function (fields, ifGroups, ifRecords) { - ifRecords(_.extend( - new openerp.base.DataSetSearch(this, this.model), - {domain: this.domain, context: this.context, _sort: this.sort})); - } -}); -openerp.base.StaticDataGroup = openerp.base.GrouplessDataGroup.extend( /** @lends openerp.base.StaticDataGroup# */ { - /** - * A specialization of groupless data groups, relying on a single static - * dataset as its records provider. - * - * @constructs - * @extends openerp.base.GrouplessDataGroup - * @param {openep.base.DataSetStatic} dataset a static dataset backing the groups - */ - init: function (dataset) { - this.dataset = dataset; - }, - list: function (fields, ifGroups, ifRecords) { - ifRecords(this.dataset); - } -}); - -openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.DataSet# */{ - /** - * DateaManagement interface between views and the collection of selected - * OpenERP records (represents the view's state?) - * - * @constructs - * @extends openerp.base.Widget - * - * @param {String} model the OpenERP model this dataset will manage - */ - init: function(source_controller, model, context) { - // we don't want the dataset to be a child of anything! - this._super(null); - this.session = source_controller ? source_controller.session : undefined; - this.model = model; - this.context = context || {}; - this.index = null; - }, - start: function() { - }, - previous: function () { - this.index -= 1; - if (this.index < 0) { - this.index = this.ids.length - 1; - } - return this; - }, - next: function () { - this.index += 1; - if (this.index >= this.ids.length) { - this.index = 0; - } - return this; - }, - /** - * Read records. - * - * @param {Array} ids identifiers of the records to read - * @param {Array} fields fields to read and return, by default all fields are returned - * @param {Function} callback function called with read result - * @returns {$.Deferred} - */ - read_ids: function (ids, fields, callback) { - return this.rpc('/base/dataset/get', { - model: this.model, - ids: ids, - fields: fields, - context: this.get_context() - }, callback); - }, - /** - * Read a slice of the records represented by this DataSet, based on its - * domain and context. - * - * @param {Array} [fields] fields to read and return, by default all fields are returned - * @params {Object} options - * @param {Number} [options.offset=0] The index from which selected records should be returned - * @param {Number} [options.limit=null] The maximum number of records to return - * @param {Function} callback function called with read_slice result - * @returns {$.Deferred} - */ - read_slice: function (fields, options, callback) { - return null; - }, - /** - * Reads the current dataset record (from its index) - * - * @params {Array} [fields] fields to read and return, by default all fields are returned - * @params {Function} callback function called with read_index result - * @returns {$.Deferred} - */ - read_index: function (fields, callback) { - var def = $.Deferred().then(callback); - if (_.isEmpty(this.ids)) { - def.reject(); - } else { - fields = fields || false; - return this.read_ids([this.ids[this.index]], fields).then(function(records) { - def.resolve(records[0]); - }, function() { - def.reject.apply(def, arguments); - }); - } - return def.promise(); - }, - /** - * Reads default values for the current model - * - * @param {Array} [fields] fields to get default values for, by default all defaults are read - * @param {Function} callback function called with default_get result - * @returns {$.Deferred} - */ - default_get: function(fields, callback) { - return this.rpc('/base/dataset/default_get', { - model: this.model, - fields: fields, - context: this.get_context() - }, callback); - }, - /** - * Creates a new record in db - * - * @param {Object} data field values to set on the new record - * @param {Function} callback function called with operation result - * @param {Function} error_callback function called in case of creation error - * @returns {$.Deferred} - */ - create: function(data, callback, error_callback) { - return this.rpc('/base/dataset/create', { - model: this.model, - data: data, - context: this.get_context() - }, callback, error_callback); - }, - /** - * Saves the provided data in an existing db record - * - * @param {Number|String} id identifier for the record to alter - * @param {Object} data field values to write into the record - * @param {Function} callback function called with operation result - * @param {Function} error_callback function called in case of write error - * @returns {$.Deferred} - */ - write: function (id, data, options, callback, error_callback) { - var options = options || {}; - return this.rpc('/base/dataset/save', { - model: this.model, - id: id, - data: data, - context: this.get_context(options.context) - }, callback, error_callback); - }, - /** - * Deletes an existing record from the database - * - * @param {Number|String} ids identifier of the record to delete - * @param {Function} callback function called with operation result - * @param {Function} error_callback function called in case of deletion error - */ - unlink: function(ids, callback, error_callback) { - var self = this; - return this.call_and_eval("unlink", [ids, this.get_context()], null, 1, - callback, error_callback); - }, - /** - * Calls an arbitrary RPC method - * - * @param {String} method name of the method (on the current model) to call - * @param {Array} [args] arguments to pass to the method - * @param {Function} callback - * @param {Function} error_callback - * @returns {$.Deferred} - */ - call: function (method, args, callback, error_callback) { - return this.rpc('/base/dataset/call', { - model: this.model, - method: method, - args: args || [] - }, callback, error_callback); - }, - /** - * Calls an arbitrary method, with more crazy - * - * @param {String} method - * @param {Array} [args] - * @param {Number} [domain_index] index of a domain to evaluate in the args array - * @param {Number} [context_index] index of a context to evaluate in the args array - * @param {Function} callback - * @param {Function }error_callback - * @returns {$.Deferred} - */ - call_and_eval: function (method, args, domain_index, context_index, callback, error_callback) { - return this.rpc('/base/dataset/call', { - model: this.model, - method: method, - domain_id: domain_index || null, - context_id: context_index || null, - args: args || [] - }, callback, error_callback); - }, - /** - * Calls a button method, usually returning some sort of action - * - * @param {String} method - * @param {Array} [args] - * @param {Function} callback - * @param {Function} error_callback - * @returns {$.Deferred} - */ - call_button: function (method, args, callback, error_callback) { - return this.rpc('/base/dataset/call_button', { - model: this.model, - method: method, - domain_id: null, - context_id: 1, - args: args || [] - }, callback, error_callback); - }, - /** - * Fetches the "readable name" for records, based on intrinsic rules - * - * @param {Array} ids - * @param {Function} callback - * @returns {$.Deferred} - */ - name_get: function(ids, callback) { - return this.call_and_eval('name_get', [ids, this.get_context()], null, 1, callback); - }, - /** - * - * @param {String} name name to perform a search for/on - * @param {Array} [domain=[]] filters for the objects returned, OpenERP domain - * @param {String} [operator='ilike'] matching operator to use with the provided name value - * @param {Number} [limit=100] maximum number of matches to return - * @param {Function} callback function to call with name_search result - * @returns {$.Deferred} - */ - name_search: function (name, domain, operator, limit, callback) { - return this.call_and_eval('name_search', - [name || '', domain || false, operator || 'ilike', this.get_context(), limit || 100], - 1, 3, callback); - }, - /** - * @param name - * @param callback - */ - name_create: function(name, callback) { - return this.call_and_eval('name_create', [name, this.get_context()], null, 1, callback); - }, - exec_workflow: function (id, signal, callback) { - return this.rpc('/base/dataset/exec_workflow', { - model: this.model, - id: id, - signal: signal - }, callback); - }, - get_context: function(request_context) { - if (request_context) { - return new openerp.base.CompoundContext(this.context, request_context); - } - return this.context; - } -}); -openerp.base.DataSetStatic = openerp.base.DataSet.extend({ - init: function(parent, model, context, ids) { - this._super(parent, model, context); - // all local records - this.ids = ids || []; - }, - read_slice: function (fields, options, callback) { - // TODO remove fields from options - var self = this, - offset = options.offset || 0, - limit = options.limit || false, - fields = fields || false; - var end_pos = limit && limit !== -1 ? offset + limit : undefined; - return this.read_ids(this.ids.slice(offset, end_pos), fields, callback); - }, - set_ids: function (ids) { - this.ids = ids; - if (this.index !== null) { - this.index = this.index <= this.ids.length - 1 ? - this.index : (this.ids.length > 0 ? this.length - 1 : 0); - } - }, - unlink: function(ids) { - this.on_unlink(ids); - return $.Deferred().resolve({result: true}); - }, - on_unlink: function(ids) { - this.set_ids(_.without.apply(null, [this.ids].concat(ids))); - } -}); -openerp.base.DataSetSearch = openerp.base.DataSet.extend({ - /** - * @constructs - * - * @param {Object} parent - * @param {String} model - * @param {Object} context - * @param {Array} domain - */ - init: function(parent, model, context, domain) { - this._super(parent, model, context); - this.domain = domain || []; - this._sort = []; - this.offset = 0; - // subset records[offset:offset+limit] - // is it necessary ? - this.ids = []; - }, - /** - * Read a slice of the records represented by this DataSet, based on its - * domain and context. - * - * @params {Object} options - * @param {Array} [options.fields] fields to read and return, by default all fields are returned - * @param {Object} [options.context] context data to add to the request payload, on top of the DataSet's own context - * @param {Array} [options.domain] domain data to add to the request payload, ANDed with the dataset's domain - * @param {Number} [options.offset=0] The index from which selected records should be returned - * @param {Number} [options.limit=null] The maximum number of records to return - * @param {Function} callback function called with read_slice result - * @returns {$.Deferred} - */ - read_slice: function (fields, options, callback) { - var self = this; - var options = options || {}; - var offset = options.offset || 0; - return this.rpc('/base/dataset/search_read', { - model: this.model, - fields: fields || false, - domain: this.get_domain(options.domain), - context: this.get_context(options.context), - sort: this.sort(), - offset: offset, - limit: options.limit || false - }, function (result) { - self.ids = result.ids; - self.offset = offset; - if (callback) { - callback(result.records); - } - }); - }, - get_domain: function (other_domain) { - if (other_domain) { - return new openerp.base.CompoundDomain(this.domain, other_domain); - } - return this.domain; - }, - /** - * Reads or changes sort criteria on the dataset. - * - * If not provided with any argument, serializes the sort criteria to - * an SQL-like form usable by OpenERP's ORM. - * - * If given a field, will set that field as first sorting criteria or, - * if the field is already the first sorting criteria, will reverse it. - * - * @param {String} [field] field to sort on, reverses it (toggle from ASC to DESC) if already the main sort criteria - * @param {Boolean} [force_reverse=false] forces inserting the field as DESC - * @returns {String|undefined} - */ - sort: function (field, force_reverse) { - if (!field) { - return openerp.base.serialize_sort(this._sort); - } - var reverse = force_reverse || (this._sort[0] === field); - this._sort.splice.apply( - this._sort, [0, this._sort.length].concat( - _.without(this._sort, field, '-' + field))); - - this._sort.unshift((reverse ? '-' : '') + field); - return undefined; - }, - unlink: function(ids, callback, error_callback) { - var self = this; - return this._super(ids, function(result) { - self.ids = _.without.apply(_, [self.ids].concat(ids)); - if (this.index !== null) { - self.index = self.index <= self.ids.length - 1 ? - self.index : (self.ids.length > 0 ? self.ids.length -1 : 0); - } - if (callback) - callback(result); - }, error_callback); - } -}); -openerp.base.BufferedDataSet = openerp.base.DataSetStatic.extend({ - virtual_id_prefix: "one2many_v_id_", - virtual_id_regex: /one2many_v_id_.*/, - debug_mode: true, - init: function() { - this._super.apply(this, arguments); - this.reset_ids([]); - }, - create: function(data, callback, error_callback) { - var cached = {id:_.uniqueId(this.virtual_id_prefix), values: data}; - this.to_create.push(cached); - this.cache.push(cached); - var to_return = $.Deferred().then(callback); - to_return.resolve({result: cached.id}); - return to_return.promise(); - }, - write: function (id, data, callback) { - var self = this; - var record = _.detect(this.to_create, function(x) {return x.id === id;}); - record = record || _.detect(this.to_write, function(x) {return x.id === id;}); - var dirty = false; - if (record) { - for (k in data) { - if (record.values[k] === undefined || record.values[k] !== data[k]) { - dirty = true; - break; - } - } - $.extend(record.values, data); - } else { - dirty = true; - record = {id: id, values: data}; - self.to_write.push(record); - } - var cached = _.detect(this.cache, function(x) {return x.id === id;}); - $.extend(cached.values, record.values); - if (dirty) - this.on_change(); - var to_return = $.Deferred().then(callback); - to_return.resolve({result: true}); - return to_return.promise(); - }, - unlink: function(ids, callback, error_callback) { - var self = this; - _.each(ids, function(id) { - if (! _.detect(self.to_create, function(x) { return x.id === id; })) { - self.to_delete.push({id: id}) - } - }); - this.to_create = _.reject(this.to_create, function(x) { return _.include(ids, x.id);}); - this.to_write = _.reject(this.to_write, function(x) { return _.include(ids, x.id);}); - this.cache = _.reject(this.cache, function(x) { return _.include(ids, x.id);}); - this.set_ids(_.without.apply(_, [this.ids].concat(ids))); - this.on_change(); - var to_return = $.Deferred().then(callback); - setTimeout(function () {to_return.resolve({result: true});}, 0); - return to_return.promise(); - }, - reset_ids: function(ids) { - this.set_ids(ids); - this.to_delete = []; - this.to_create = []; - this.to_write = []; - this.cache = []; - this.delete_all = false; - }, - on_change: function() {}, - read_ids: function (ids, fields, callback) { - var self = this; - var to_get = []; - _.each(ids, function(id) { - var cached = _.detect(self.cache, function(x) {return x.id === id;}); - var created = _.detect(self.to_create, function(x) {return x.id === id;}); - if (created) { - _.each(fields, function(x) {if (cached.values[x] === undefined) cached.values[x] = false;}); - } else { - if (!cached || !_.all(fields, function(x) {return cached.values[x] !== undefined})) - to_get.push(id); - } - }); - var completion = $.Deferred().then(callback); - var return_records = function() { - var records = _.map(ids, function(id) { - return _.extend({}, _.detect(self.cache, function(c) {return c.id === id;}).values, {"id": id}); - }); - if (self.debug_mode) { - if (_.include(records, undefined)) { - throw "Record not correctly loaded"; - } - } - setTimeout(function () {completion.resolve(records);}, 0); - } - if(to_get.length > 0) { - var rpc_promise = this._super(to_get, fields, function(records) { - _.each(records, function(record, index) { - var id = to_get[index]; - var cached = _.detect(self.cache, function(x) {return x.id === id;}); - if (!cached) { - self.cache.push({id: id, values: record}); - } else { - // I assume cache value is prioritary - _.defaults(cached.values, record); - } - }); - return_records(); - }); - $.when(rpc_promise).fail(function() {completion.reject();}); - } else { - return_records(); - } - return completion.promise(); - } -}); -openerp.base.ReadOnlyDataSetSearch = openerp.base.DataSetSearch.extend({ - create: function(data, callback, error_callback) { - this.on_create(data); - var to_return = $.Deferred().then(callback); - setTimeout(function () {to_return.resolve({"result": undefined});}, 0); - return to_return.promise(); - }, - on_create: function(data) {}, - write: function (id, data, callback) { - this.on_write(id, data); - var to_return = $.Deferred().then(callback); - setTimeout(function () {to_return.resolve({"result": true});}, 0); - return to_return.promise(); - }, - on_write: function(id, data) {}, - unlink: function(ids, callback, error_callback) { - this.on_unlink(ids); - var to_return = $.Deferred().then(callback); - setTimeout(function () {to_return.resolve({"result": true});}, 0); - return to_return.promise(); - }, - on_unlink: function(ids) {} -}); - -openerp.base.CompoundContext = openerp.base.Class.extend({ - init: function () { - this.__ref = "compound_context"; - this.__contexts = []; - this.__eval_context = null; - var self = this; - _.each(arguments, function(x) { - self.add(x); - }); - }, - add: function (context) { - this.__contexts.push(context); - return this; - }, - set_eval_context: function (eval_context) { - this.__eval_context = eval_context; - return this; - }, - get_eval_context: function () { - return this.__eval_context; - } -}); - -openerp.base.CompoundDomain = openerp.base.Class.extend({ - init: function () { - this.__ref = "compound_domain"; - this.__domains = []; - this.__eval_context = null; - var self = this; - _.each(arguments, function(x) { - self.add(x); - }); - }, - add: function(domain) { - this.__domains.push(domain); - return this; - }, - set_eval_context: function(eval_context) { - this.__eval_context = eval_context; - return this; - }, - get_eval_context: function() { - return this.__eval_context; - } -}); -}; - -// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/base/static/src/js/data_export.js b/addons/base/static/src/js/data_export.js deleted file mode 100644 index ad440302c69..00000000000 --- a/addons/base/static/src/js/data_export.js +++ /dev/null @@ -1,402 +0,0 @@ -openerp.base.data_export = function(openerp) { -openerp.base.DataExport = openerp.base.Dialog.extend({ - init: function(parent, dataset) { - this._super(parent); - this.dataset = dataset; - }, - start: function() { - var self = this; - self._super(false); - self.template = 'ExportTreeView'; - self.dialog_title = "Export Data"; - self.open({ - modal: true, - width: '55%', - height: 'auto', - position: 'top', - buttons : { - "Close" : function() { - self.close(); - }, - "Export To File" : function() { - self.on_click_export_data(); - } - }, - close: function(event, ui){ self.close();} - }); - self.on_show_exists_export_list(); - self.$element.removeClass('ui-dialog-content ui-widget-content'); - self.$element.find('#add_field').click(function() { - if ($('#field-tree-structure tr.ui-selected')) { - var fld = self.$element.find('#field-tree-structure tr.ui-selected').find('a'); - for (var i = 0; i < fld.length; i++) { - var id = $(fld[i]).attr('id').split('-')[1]; - var string = $(fld[i]).attr('string'); - self.add_field(id, string); - } - self.$element.find('#field-tree-structure tr').removeClass('ui-selected'); - } - }); - self.$element.find('#remove_field').click(function() { - self.$element.find('#fields_list option:selected').remove(); - }); - self.$element.find('#remove_all_field').click(function() { - self.$element.find('#fields_list option').remove(); - }); - self.$element.find('#export_new_list').click(function() { - self.on_show_save_list(); - }); - var import_comp = self.$element.find('#import_compat option:selected').val(), - params = { - import_compat: parseInt(import_comp) - }; - self.rpc('/base/export/get_fields', { model: self.dataset.model, params: params }, self.on_show_data); - - self.$element.find('#import_compat').change(function() { - self.$element.find('#fields_list option').remove(); - self.$element.find('#field-tree-structure').remove(); - var import_comp = self.$element.find("#import_compat option:selected").val(); - if (import_comp) { - var params = { - import_compat: parseInt(import_comp) - } - self.rpc("/base/export/get_fields", { model: self.dataset.model, params: params}, self.on_show_data); - } - }); - }, - on_show_exists_export_list: function() { - var self = this; - if (self.$element.find('#saved_export_list').is(':hidden')) { - self.$element.find('#ExistsExportList').show(); - } else { - this.rpc('/base/export/exist_export_lists', { 'model': this.dataset.model}, function(export_list) { - if (export_list.length) { - self.$element.find('#ExistsExportList').append(QWeb.render('Exists.ExportList', {'existing_exports': export_list})); - self.$element.find('#saved_export_list').change(function() { - self.$element.find('#fields_list option').remove(); - var export_id = self.$element.find('#saved_export_list option:selected').val(); - if (export_id) { - self.rpc('/base/export/namelist', {'model': self.dataset.model, export_id: parseInt(export_id)}, self.do_load_export_field); - } - }); - self.$element.find('#delete_export_list').click(function() { - var select_exp = self.$element.find('#saved_export_list option:selected'); - if (select_exp.val()) { - self.rpc('/base/export/delete_export', { export_id: parseInt(select_exp.val())}, {}); - select_exp.remove(); - if (self.$element.find('#saved_export_list option').length <= 1) { - self.$element.find('#ExistsExportList').hide(); - } - } - }); - } - }); - } - }, - do_load_export_field: function(field_list) { - var export_node = this.$element.find("#fields_list"); - for (var key in field_list) { - export_node.append(new Option(field_list[key], key)); - } - }, - on_show_save_list: function() { - var self = this; - var current_node = self.$element.find("#savenewlist"); - if (!(current_node.find("label")).length) { - current_node.append(QWeb.render('ExportNewList')); - current_node.find("#add_export_list").click(function() { - var value = current_node.find("#savelist_name").val(); - if (value) { - self.do_save_export_list(value); - } else { - alert("Pleae Enter Save Field List Name"); - } - }); - } else { - if (current_node.is(':hidden')) { - current_node.show(); - current_node.find("#savelist_name").val(""); - } else { - current_node.hide(); - } - } - }, - do_save_export_list: function(value) { - var self = this; - var export_field = self.get_fields(); - if (export_field.length) { - self.rpc("/base/export/save_export_lists", {"model": self.dataset.model, "name":value, "field_list":export_field}, function(exp_id) { - if (exp_id) { - if (self.$element.find("#saved_export_list").length > 0) { - self.$element.find("#saved_export_list").append(new Option(value, exp_id)); - } else { - self.on_show_exists_export_list(); - } - if (self.$element.find("#saved_export_list").is(":hidden")) { - self.on_show_exists_export_list(); - } - } - }); - self.on_show_save_list(); - self.$element.find("#fields_list option").remove(); - } - }, - on_click: function(id, result) { - var self = this; - self.field_id = id.split("-")[1]; - var is_loaded = 0; - _.each(result, function(record) { - if (record['id'] == self.field_id && (record['children']).length >= 1) { - var model = record['params']['model'], - prefix = record['params']['prefix'], - name = record['params']['name']; - $(record['children']).each(function(e, childid) { - if (self.$element.find("tr[id='treerow-" + childid + "']").length > 0) { - if (self.$element.find("tr[id='treerow-" + childid + "']").is(':hidden')) { - is_loaded = -1; - } else { - is_loaded++; - } - } - }); - if (is_loaded == 0) { - if (self.$element.find("tr[id='treerow-" + self.field_id +"']").find('img').attr('src') === '/base/static/src/img/expand.gif') { - if (model) { - var import_comp = self.$element.find("#import_compat option:selected").val(); - var params = { - import_compat: parseInt(import_comp), - parent_field_type : record['field_type'] - } - self.rpc("/base/export/get_fields", { - model: model, - prefix: prefix, - name: name, - field_parent : self.field_id, - params: params - }, function(results) { - self.on_show_data(results); - }); - } - } - } else if (is_loaded > 0) { - self.showcontent(self.field_id, true); - } else { - self.showcontent(self.field_id, false); - } - } - }); - }, - on_show_data: function(result) { - var self = this; - var imp_cmpt = parseInt(self.$element.find("#import_compat option:selected").val()); - var current_tr = self.$element.find("tr[id='treerow-" + self.field_id + "']"); - if (current_tr.length >= 1) { - current_tr.find('img').attr('src','/base/static/src/img/collapse.gif'); - current_tr.after(QWeb.render('ExportTreeView-Secondary.children', {'fields': result})); - } else { - self.$element.find('#left_field_panel').append(QWeb.render('ExportTreeView-Secondary', {'fields': result})); - } - _.each(result, function(record) { - if ((record.field_type == "one2many") && imp_cmpt) { - var o2m_fld = self.$element.find("tr[id='treerow-" + record.id + "']").find('#tree-column'); - o2m_fld.addClass("oe_export_readonlyfield"); - } - if ((record.required == true) || record.required == "True") { - var required_fld = self.$element.find("tr[id='treerow-" + record.id + "']").find('#tree-column'); - required_fld.addClass("oe_export_requiredfield"); - } - self.$element.find("img[id='parentimg-" + record.id +"']").click(function() { - self.on_click(this.id, result); - }); - - self.$element.find("tr[id='treerow-" + record.id + "']").click(function(e) { - if (e.shiftKey == true) { - var frst_click, scnd_click = ''; - if (self.row_index == 0) { - self.row_index = this.rowIndex; - frst_click = self.$element.find("tr[id^='treerow-']")[self.row_index-1]; - $(frst_click).addClass("ui-selected"); - } else { - if (this.rowIndex >=self.row_index) { - for (i = (self.row_index-1); i < this.rowIndex; i++) { - scnd_click = self.$element.find("tr[id^='treerow-']")[i]; - if (!$(scnd_click).find('#tree-column').hasClass("oe_export_readonlyfield")) { - $(scnd_click).addClass("ui-selected"); - } - } - } else { - for (i = (self.row_index-1); i >= (this.rowIndex-1); i--) { - scnd_click = self.$element.find("tr[id^='treerow-']")[i]; - if (!$(scnd_click).find('#tree-column').hasClass("oe_export_readonlyfield")) { - $(scnd_click).addClass("ui-selected"); - } - } - } - } - } - self.row_index = this.rowIndex; - - self.$element.find("tr[id='treerow-" + record.id + "']").keyup(function(e) { - self.row_index = 0; - }); - var o2m_selection = self.$element.find("tr[id='treerow-" + record.id + "']").find('#tree-column'); - if ($(o2m_selection).hasClass("oe_export_readonlyfield")) { - return false; - } - var selected = self.$element.find("tr.ui-selected"); - if ($(this).hasClass("ui-selected") && (e.ctrlKey == true)) { - $(this).find('a').blur(); - $(this).removeClass("ui-selected"); - } else if ($(this).hasClass("ui-selected") && (e.ctrlKey == false) && (e.shiftKey == false)) { - selected.find('a').blur(); - selected.removeClass("ui-selected"); - $(this).find('a').focus(); - $(this).addClass("ui-selected"); - } else if (!$(this).hasClass("ui-selected") && (e.ctrlKey == false) && (e.shiftKey == false)) { - selected.find('a').blur(); - selected.removeClass("ui-selected"); - $(this).find('a').focus(); - $(this).addClass("ui-selected"); - } else if (!$(this).hasClass("ui-selected") && (e.ctrlKey == true)) { - $(this).find('a').focus(); - $(this).addClass("ui-selected"); - } - return false; - }); - - self.$element.find("tr[id='treerow-" + record.id + "']").keydown(function(e) { - var keyCode = e.keyCode || e.which; - arrow = {left: 37, up: 38, right: 39, down: 40 }; - switch (keyCode) { - case arrow.left: - if ($(this).find('img').attr('src') === '/base/static/src/img/collapse.gif') { - self.on_click(this.id, result); - } - break; - case arrow.up: - var elem = this; - $(elem).removeClass("ui-selected"); - while ($(elem).prev().is(":visible") == false) { - elem = $(elem).prev(); - } - if (!$(elem).prev().find('#tree-column').hasClass("oe_export_readonlyfield")) { - $(elem).prev().addClass("ui-selected"); - } - $(elem).prev().find('a').focus(); - break; - case arrow.right: - if ($(this).find('img').attr('src') == '/base/static/src/img/expand.gif') { - self.on_click(this.id, result); - } - break; - case arrow.down: - var elem = this; - $(elem).removeClass("ui-selected"); - while($(elem).next().is(":visible") == false) { - elem = $(elem).next(); - } - if (!$(elem).next().find('#tree-column').hasClass("oe_export_readonlyfield")) { - $(elem).next().addClass("ui-selected"); - } - $(elem).next().find('a').focus(); - break; - } - }); - self.$element.find("tr[id='treerow-" + record.id + "']").dblclick(function(e) { - var $o2m_selection = self.$element.find("tr[id^='treerow-" + record.id + "']").find('#tree-column'); - if (!$o2m_selection.hasClass("oe_export_readonlyfield")) { - var field_id = $(this).find("a").attr("id"); - if (field_id) { - self.add_field(field_id.split('-')[1], $(this).find("a").attr("string")); - } - } - }); - }); - self.$element.find('#fields_list').mouseover(function(event) { - if (event.relatedTarget) { - if (event.relatedTarget.attributes['id'] && event.relatedTarget.attributes['string']) { - var field_id = event.relatedTarget.attributes["id"]["value"]; - if (field_id && field_id.split("-")[0] === 'export') { - if (!self.$element.find("tr[id='treerow-" + field_id.split("-")[1] + "']").find('#tree-column').hasClass("oe_export_readonlyfield")) { - self.add_field(field_id.split("-")[1], event.relatedTarget.attributes["string"]["value"]); - } - } - } - } - }); - }, - showcontent: function(id, flag) { - // show & hide the contents - var first_child = this.$element.find("tr[id='treerow-" + id + "']").find('img'); - if (flag) { - first_child.attr('src', '/base/static/src/img/expand.gif'); - } - else { - first_child.attr('src', '/base/static/src/img/collapse.gif'); - } - var child_field = this.$element.find("tr[id^='treerow-" + id +"/']"); - var child_len = (id.split("/")).length + 1; - for (var i = 0; i < child_field.length; i++) { - if (flag) { - $(child_field[i]).hide(); - } else { - if (child_len == (child_field[i].id.split("/")).length) { - if ($(child_field[i]).find('img').attr('src') == '/base/static/src/img/collapse.gif') { - $(child_field[i]).find('img').attr('src', '/base/static/src/img/expand.gif'); - } - $(child_field[i]).show(); - } - } - } - }, - add_field: function(field_id, string) { - var field_list = this.$element.find('#fields_list'); - if (this.$element.find("#fields_list option[value='" + field_id + "']") && !this.$element.find("#fields_list option[value='" + field_id + "']").length) { - field_list.append(new Option(string, field_id)); - } - }, - get_fields: function() { - var export_field = []; - this.$element.find("#fields_list option").each(function() { - export_field.push($(this).val()); - }); - if (!export_field.length) { - alert('Please select fields to save export list...'); - } - return export_field; - }, - on_click_export_data: function() { - var self = this; - var export_field = {}; - var flag = true; - self.$element.find("#fields_list option").each(function() { - export_field[$(this).val()] = $(this).text(); - flag = false; - }); - if (flag) { - alert('Please select fields to export...'); - return; - } - - var import_comp = self.$element.find("#import_compat option:selected").val(), - export_format = self.$element.find("#export_format").val(); - - self.rpc("/base/export/export_data", { - model: self.dataset.model, - fields: export_field, - ids: self.dataset.ids, - domain: self.dataset.domain, - import_compat: parseInt(import_comp), - export_format: export_format - }, function(data) { - window.location = "data:text/csv/excel;charset=utf8," + data; - self.close(); - }); - }, - close: function() { - $(this.$dialog).remove(); - this._super(); - } -}); - -}; diff --git a/addons/base/static/src/js/dates.js b/addons/base/static/src/js/dates.js deleted file mode 100644 index 71fdb759a63..00000000000 --- a/addons/base/static/src/js/dates.js +++ /dev/null @@ -1,138 +0,0 @@ - -openerp.base.dates = function(openerp) { - -/** - * Converts a string to a Date javascript object using OpenERP's - * datetime string format (exemple: '2011-12-01 15:12:35'). - * - * The timezone is assumed to be UTC (standard for OpenERP 6.1) - * and will be converted to the browser's timezone. - * - * @param {String} str A string representing a datetime. - * @returns {Date} - */ -openerp.base.str_to_datetime = function(str) { - if(!str) { - return str; - } - var regex = /^(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d)(?:\.\d+)?$/; - var res = regex.exec(str); - if ( !res ) { - throw "'" + str + "' is not a valid datetime"; - } - var obj = Date.parse(res[1] + " GMT"); - if (! obj) { - throw "'" + str + "' is not a valid datetime"; - } - return obj; -}; - -/** - * Converts a string to a Date javascript object using OpenERP's - * date string format (exemple: '2011-12-01'). - * - * @param {String} str A string representing a date. - * @returns {Date} - */ -openerp.base.str_to_date = function(str) { - if(!str) { - return str; - } - var regex = /^\d\d\d\d-\d\d-\d\d$/; - var res = regex.exec(str); - if ( !res ) { - throw "'" + str + "' is not a valid date"; - } - var obj = Date.parse(str); - if (! obj) { - throw "'" + str + "' is not a valid date"; - } - return obj; -}; - -/** - * Converts a string to a Date javascript object using OpenERP's - * time string format (exemple: '15:12:35'). - * - * @param {String} str A string representing a time. - * @returns {Date} - */ -openerp.base.str_to_time = function(str) { - if(!str) { - return str; - } - var regex = /^(\d\d:\d\d:\d\d)(?:\.\d+)?$/; - var res = regex.exec(str); - if ( !res ) { - throw "'" + str + "' is not a valid time"; - } - var obj = Date.parse(res[1]); - if (! obj) { - throw "'" + str + "' is not a valid time"; - } - return obj; -}; - -/* - * Left-pad provided arg 1 with zeroes until reaching size provided by second - * argument. - * - * @param {Number|String} str value to pad - * @param {Number} size size to reach on the final padded value - * @returns {String} padded string - */ -var zpad = function(str, size) { - str = "" + str; - return new Array(size - str.length + 1).join('0') + str; -}; - -/** - * Converts a Date javascript object to a string using OpenERP's - * datetime string format (exemple: '2011-12-01 15:12:35'). - * - * The timezone of the Date object is assumed to be the one of the - * browser and it will be converted to UTC (standard for OpenERP 6.1). - * - * @param {Date} obj - * @returns {String} A string representing a datetime. - */ -openerp.base.datetime_to_str = function(obj) { - if (!obj) { - return false; - } - return zpad(obj.getUTCFullYear(),4) + "-" + zpad(obj.getUTCMonth() + 1,2) + "-" - + zpad(obj.getUTCDate(),2) + " " + zpad(obj.getUTCHours(),2) + ":" - + zpad(obj.getUTCMinutes(),2) + ":" + zpad(obj.getUTCSeconds(),2); -}; - -/** - * Converts a Date javascript object to a string using OpenERP's - * date string format (exemple: '2011-12-01'). - * - * @param {Date} obj - * @returns {String} A string representing a date. - */ -openerp.base.date_to_str = function(obj) { - if (!obj) { - return false; - } - return zpad(obj.getFullYear(),4) + "-" + zpad(obj.getMonth() + 1,2) + "-" - + zpad(obj.getDate(),2); -}; - -/** - * Converts a Date javascript object to a string using OpenERP's - * time string format (exemple: '15:12:35'). - * - * @param {Date} obj - * @returns {String} A string representing a time. - */ -openerp.base.time_to_str = function(obj) { - if (!obj) { - return false; - } - return zpad(obj.getHours(),2) + ":" + zpad(obj.getMinutes(),2) + ":" - + zpad(obj.getSeconds(),2); -}; - -}; diff --git a/addons/base/static/src/js/form.js b/addons/base/static/src/js/form.js deleted file mode 100644 index 2a3c8ab476e..00000000000 --- a/addons/base/static/src/js/form.js +++ /dev/null @@ -1,2477 +0,0 @@ -openerp.base.form = function (openerp) { - -var _t = openerp.base._t; - -openerp.base.views.add('form', 'openerp.base.FormView'); -openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormView# */{ - /** - * Indicates that this view is not searchable, and thus that no search - * view should be displayed (if there is one active). - */ - searchable: false, - template: "FormView", - /** - * @constructs - * @param {openerp.base.Session} session the current openerp session - * @param {String} element_id this view's root element id - * @param {openerp.base.DataSet} dataset the dataset this view will work with - * @param {String} view_id the identifier of the OpenERP view object - * - * @property {openerp.base.Registry} registry=openerp.base.form.widgets widgets registry for this form view instance - */ - init: function(parent, element_id, dataset, view_id, options) { - this._super(parent, element_id); - this.set_default_options(options); - this.dataset = dataset; - this.model = dataset.model; - this.view_id = view_id; - this.fields_view = {}; - this.widgets = {}; - this.widgets_counter = 0; - this.fields = {}; - this.datarecord = {}; - this.ready = false; - this.show_invalid = true; - this.dirty = false; - this.default_focus_field = null; - this.default_focus_button = null; - this.registry = openerp.base.form.widgets; - this.has_been_loaded = $.Deferred(); - this.$form_header = null; - this.translatable_fields = []; - _.defaults(this.options, {"always_show_new_button": true}); - }, - start: function() { - //this.log('Starting FormView '+this.model+this.view_id) - if (this.embedded_view) { - var def = $.Deferred().then(this.on_loaded); - var self = this; - setTimeout(function() {def.resolve({fields_view: self.embedded_view});}, 0); - return def.promise(); - } else { - var context = new openerp.base.CompoundContext(this.dataset.get_context()); - return this.rpc("/base/formview/load", {"model": this.model, "view_id": this.view_id, - toolbar: this.options.sidebar, context: context}, this.on_loaded); - } - }, - stop: function() { - if (this.sidebar) { - this.sidebar.attachments.stop(); - this.sidebar.stop(); - } - _.each(this.widgets, function(w) { - w.stop(); - }); - }, - on_loaded: function(data) { - var self = this; - this.fields_view = data.fields_view; - var frame = new (this.registry.get_object('frame'))(this, this.fields_view.arch); - - this.$element.html(QWeb.render(this.template, { 'frame': frame, 'view': this })); - _.each(this.widgets, function(w) { - w.start(); - }); - this.$form_header = this.$element.find('#' + this.element_id + '_header'); - this.$form_header.find('div.oe_form_pager button[data-pager-action]').click(function() { - var action = $(this).data('pager-action'); - self.on_pager_action(action); - }); - - this.$form_header.find('button.oe_form_button_save').click(this.do_save); - this.$form_header.find('button.oe_form_button_save_edit').click(this.do_save_edit); - this.$form_header.find('button.oe_form_button_cancel').click(this.do_cancel); - this.$form_header.find('button.oe_form_button_new').click(this.on_button_new); - - if (this.session.debug) { - this.$form_header.find('button.oe_get_xml_view').click(function() { - $('<xmp>' + openerp.base.json_node_to_xml(self.fields_view.arch, true) + '</xmp>').dialog({ width: '95%', height: 600}); - }); - } - - if (this.options.sidebar && this.options.sidebar_id) { - this.sidebar = new openerp.base.Sidebar(this, this.options.sidebar_id); - this.sidebar.start(); - this.sidebar.do_unfold(); - this.sidebar.attachments = new openerp.base.form.SidebarAttachments(this.sidebar, this.sidebar.add_section('attachments', "Attachments"), this); - this.sidebar.add_toolbar(data.fields_view.toolbar); - this.set_common_sidebar_sections(this.sidebar); - } - this.has_been_loaded.resolve(); - }, - do_show: function () { - var promise; - if (this.dataset.index === null) { - // null index means we should start a new record - promise = this.on_button_new(); - } else { - promise = this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded); - } - this.$element.show(); - if (this.sidebar) { - this.sidebar.$element.show(); - } - return promise; - }, - do_hide: function () { - this.$element.hide(); - if (this.sidebar) { - this.sidebar.$element.hide(); - } - }, - on_record_loaded: function(record) { - if (!record) { - throw("Form: No record received"); - } - if (!record.id) { - this.$form_header.find('.oe_form_on_create').show(); - this.$form_header.find('.oe_form_on_update').hide(); - if (!this.options["always_show_new_button"]) { - this.$form_header.find('button.oe_form_button_new').hide(); - } - } else { - this.$form_header.find('.oe_form_on_create').hide(); - this.$form_header.find('.oe_form_on_update').show(); - this.$form_header.find('button.oe_form_button_new').show(); - } - this.dirty = false; - this.datarecord = record; - for (var f in this.fields) { - var field = this.fields[f]; - field.dirty = false; - field.set_value(this.datarecord[f] || false); - field.validate(); - } - if (!record.id) { - // New record: Second pass in order to trigger the onchanges - this.dirty = true; - this.show_invalid = false; - for (var f in record) { - var field = this.fields[f]; - if (field) { - field.dirty = true; - this.do_onchange(field); - } - } - } - this.on_form_changed(); - this.show_invalid = this.ready = true; - this.do_update_pager(record.id == null); - if (this.sidebar) { - this.sidebar.attachments.do_update(); - this.sidebar.$element.find('.oe_sidebar_translate').toggleClass('oe_hide', !record.id); - } - if (this.default_focus_field && !this.embedded_view) { - this.default_focus_field.focus(); - } - }, - on_form_changed: function() { - for (var w in this.widgets) { - w = this.widgets[w]; - w.process_modifiers(); - w.update_dom(); - } - }, - on_pager_action: function(action) { - switch (action) { - case 'first': - this.dataset.index = 0; - break; - case 'previous': - this.dataset.previous(); - break; - case 'next': - this.dataset.next(); - break; - case 'last': - this.dataset.index = this.dataset.ids.length - 1; - break; - } - this.reload(); - }, - do_update_pager: function(hide_index) { - var $pager = this.$element.find('#' + this.element_id + '_header div.oe_form_pager'); - var index = hide_index ? '-' : this.dataset.index + 1; - $pager.find('span.oe_pager_index').html(index); - $pager.find('span.oe_pager_count').html(this.dataset.ids.length); - }, - do_onchange: function(widget, processed) { - processed = processed || []; - if (widget.node.attrs.on_change) { - var self = this; - this.ready = false; - var onchange = _.trim(widget.node.attrs.on_change); - var call = onchange.match(/^\s?(.*?)\((.*?)\)\s?$/); - if (call) { - var method = call[1], args = []; - var context_index = null; - var argument_replacement = { - 'False' : function() {return false;}, - 'True' : function() {return true;}, - 'None' : function() {return null;}, - 'context': function(i) { - context_index = i; - var ctx = widget.build_context ? widget.build_context() : {}; - return ctx; - } - } - var parent_fields = null; - _.each(call[2].split(','), function(a, i) { - var field = _.trim(a); - if (field in argument_replacement) { - args.push(argument_replacement[field](i)); - return; - } else if (self.fields[field]) { - var value = self.fields[field].get_on_change_value(); - args.push(value == null ? false : value); - return; - } else { - var splitted = field.split('.'); - if (splitted.length > 1 && _.trim(splitted[0]) === "parent" && self.dataset.parent_view) { - if (parent_fields === null) { - parent_fields = self.dataset.parent_view.get_fields_values(); - } - var p_val = parent_fields[_.trim(splitted[1])]; - if (p_val !== undefined) { - args.push(p_val == null ? false : p_val); - return; - } - } - } - throw "Could not get field with name '" + field + - "' for onchange '" + onchange + "'"; - }); - var ajax = { - url: '/base/dataset/call', - async: false - }; - return this.rpc(ajax, { - model: this.dataset.model, - method: method, - args: [(this.datarecord.id == null ? [] : [this.datarecord.id])].concat(args), - context_id: context_index === null ? null : context_index + 1 - }, function(response) { - self.on_processed_onchange(response, processed); - }); - } else { - this.log("Wrong on_change format", on_change); - } - } - }, - on_processed_onchange: function(response, processed) { - var result = response; - if (result.value) { - for (var f in result.value) { - var field = this.fields[f]; - // If field is not defined in the view, just ignore it - if (field) { - var value = result.value[f]; - processed.push(field.name); - if (field.get_value() != value) { - field.set_value(value); - field.dirty = true; - if (_.indexOf(processed, field.name) < 0) { - this.do_onchange(field, processed); - } - } - } - } - this.on_form_changed(); - } - if (!_.isEmpty(result.warning)) { - $(QWeb.render("DialogWarning", result.warning)).dialog({ - modal: true, - buttons: { - Ok: function() { - $(this).dialog("close"); - } - } - }); - } - if (result.domain) { - // TODO: - } - this.ready = true; - }, - on_button_new: function() { - var self = this; - var def = $.Deferred(); - $.when(this.has_been_loaded).then(function() { - self.dataset.default_get( - _.keys(self.fields_view.fields)).then(self.on_record_loaded).then(function() { - def.resolve(); - }); - }); - return def.promise(); - }, - /** - * Triggers saving the form's record. Chooses between creating a new - * record or saving an existing one depending on whether the record - * already has an id property. - * - * @param {Function} success callback on save success - * @param {Boolean} [prepend_on_create=false] if ``do_save`` creates a new record, should that record be inserted at the start of the dataset (by default, records are added at the end) - */ - do_save: function(success, prepend_on_create) { - var self = this; - if (!this.ready) { - return false; - } - var form_dirty = false, - form_invalid = false, - values = {}, - first_invalid_field = null; - for (var f in this.fields) { - f = this.fields[f]; - if (!f.is_valid()) { - form_invalid = true; - f.update_dom(); - if (!first_invalid_field) { - first_invalid_field = f; - } - } else if (f.is_dirty()) { - form_dirty = true; - values[f.name] = f.get_value(); - } - } - if (form_invalid) { - first_invalid_field.focus(); - this.on_invalid(); - return false; - } else if (form_dirty) { - this.log("About to save", values); - if (!this.datarecord.id) { - return this.dataset.create(values, function(r) { - self.on_created(r, success, prepend_on_create); - }); - } else { - return this.dataset.write(this.datarecord.id, values, {}, function(r) { - self.on_saved(r, success); - }); - } - } else { - setTimeout(function() { - self.on_saved({ result: true }, success); - }); - return true; - } - }, - do_save_edit: function() { - this.do_save(); - //this.switch_readonly(); Use promises - }, - switch_readonly: function() { - }, - switch_editable: function() { - }, - on_invalid: function() { - var msg = "<ul>"; - _.each(this.fields, function(f) { - if (!f.is_valid()) { - msg += "<li>" + f.string + "</li>"; - } - }); - msg += "</ul>"; - this.notification.warn("The following fields are invalid :", msg); - }, - on_saved: function(r, success) { - if (!r.result) { - this.notification.warn("Record not saved", "Problem while saving record."); - } else { - this.notification.notify("Record saved", "The record #" + this.datarecord.id + " has been saved."); - if (success) { - success(r); - } - this.reload(); - } - }, - /** - * Updates the form' dataset to contain the new record: - * - * * Adds the newly created record to the current dataset (at the end by - * default) - * * Selects that record (sets the dataset's index to point to the new - * record's id). - * * Updates the pager and sidebar displays - * - * @param {Object} r - * @param {Function} success callback to execute after having updated the dataset - * @param {Boolean} [prepend_on_create=false] adds the newly created record at the beginning of the dataset instead of the end - */ - on_created: function(r, success, prepend_on_create) { - if (!r.result) { - this.notification.warn("Record not created", "Problem while creating record."); - } else { - this.datarecord.id = r.result; - if (!prepend_on_create) { - this.dataset.ids.push(this.datarecord.id); - this.dataset.index = this.dataset.ids.length - 1; - } else { - this.dataset.ids.unshift(this.datarecord.id); - this.dataset.index = 0; - } - this.do_update_pager(); - if (this.sidebar) { - this.sidebar.attachments.do_update(); - } - this.notification.notify("Record created", "The record has been created with id #" + this.datarecord.id); - if (success) { - success(_.extend(r, {created: true})); - } - this.reload(); - } - }, - do_search: function (domains, contexts, groupbys) { - this.notification.notify("Searching form"); - }, - on_action: function (action) { - this.notification.notify('Executing action ' + action); - }, - do_cancel: function () { - this.notification.notify("Cancelling form"); - }, - reload: function() { - if (this.dataset.index == null || this.dataset.index < 0) { - this.on_button_new(); - } else { - this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded); - } - }, - get_fields_values: function() { - var values = {}; - _.each(this.fields, function(value, key) { - var val = value.get_value(); - values[key] = val; - }); - return values; - }, - get_selected_ids: function() { - var id = this.dataset.ids[this.dataset.index]; - return id ? [id] : []; - } -}); - -/** @namespace */ -openerp.base.form = {}; - -openerp.base.form.SidebarAttachments = openerp.base.Widget.extend({ - init: function(parent, element_id, form_view) { - this._super(parent, element_id); - this.view = form_view; - }, - do_update: function() { - if (!this.view.datarecord.id) { - this.on_attachments_loaded([]); - } else { - (new openerp.base.DataSetSearch( - this, 'ir.attachment', this.view.dataset.get_context(), - [ - ['res_model', '=', this.view.dataset.model], - ['res_id', '=', this.view.datarecord.id], - ['type', 'in', ['binary', 'url']] - ])).read_slice(['name', 'url', 'type'], {}, this.on_attachments_loaded); - } - }, - on_attachments_loaded: function(attachments) { - this.attachments = attachments; - this.$element.html(QWeb.render('FormView.sidebar.attachments', this)); - this.$element.find('.oe-binary-file').change(this.on_attachment_changed); - this.$element.find('.oe-sidebar-attachment-delete').click(this.on_attachment_delete); - }, - on_attachment_changed: function(e) { - window[this.element_id + '_iframe'] = this.do_update; - var $e = $(e.target); - if ($e.val() != '') { - this.$element.find('form.oe-binary-form').submit(); - $e.parent().find('input[type=file]').attr('disabled', 'true'); - $e.parent().find('button').attr('disabled', 'true').find('img, span').toggle(); - } - }, - on_attachment_delete: function(e) { - var self = this, $e = $(e.currentTarget); - var name = _.trim($e.parent().find('a.oe-sidebar-attachments-link').text()); - if (confirm("Do you really want to delete the attachment " + name + " ?")) { - this.rpc('/base/dataset/unlink', { - model: 'ir.attachment', - ids: [parseInt($e.attr('data-id'))] - }, function(r) { - $e.parent().remove(); - self.notification.notify("Delete an attachment", "The attachment '" + name + "' has been deleted"); - }); - } - } -}); - -openerp.base.form.compute_domain = function(expr, fields) { - var stack = []; - for (var i = expr.length - 1; i >= 0; i--) { - var ex = expr[i]; - if (ex.length == 1) { - var top = stack.pop(); - switch (ex) { - case '|': - stack.push(stack.pop() || top); - continue; - case '&': - stack.push(stack.pop() && top); - continue; - case '!': - stack.push(!top); - continue; - default: - throw new Error('Unknown domain operator ' + ex); - } - } - - var field = fields[ex[0]]; - if (!field) { - throw new Error("Domain references unknown field : " + ex[0]); - } - var field_value = field.get_value ? fields[ex[0]].get_value() : fields[ex[0]].value; - var op = ex[1]; - var val = ex[2]; - - switch (op.toLowerCase()) { - case '=': - case '==': - stack.push(field_value == val); - break; - case '!=': - case '<>': - stack.push(field_value != val); - break; - case '<': - stack.push(field_value < val); - break; - case '>': - stack.push(field_value > val); - break; - case '<=': - stack.push(field_value <= val); - break; - case '>=': - stack.push(field_value >= val); - break; - case 'in': - stack.push(_(val).contains(field_value)); - break; - case 'not in': - stack.push(!_(val).contains(field_value)); - break; - default: - this.log("Unsupported operator in modifiers :", op); - } - } - return _.all(stack, _.identity); -}; - -openerp.base.form.Widget = openerp.base.Widget.extend({ - template: 'Widget', - init: function(view, node) { - this.view = view; - this.node = node; - this.modifiers = JSON.parse(this.node.attrs.modifiers || '{}'); - this.type = this.type || node.tag; - this.element_name = this.element_name || this.type; - this.element_id = [this.view.element_id, this.element_name, this.view.widgets_counter++].join("_"); - - this._super(view, this.element_id); - - this.view.widgets[this.element_id] = this; - this.children = node.children; - this.colspan = parseInt(node.attrs.colspan || 1, 10); - this.decrease_max_width = 0; - - this.string = this.string || node.attrs.string; - this.help = this.help || node.attrs.help; - this.invisible = this.modifiers['invisible'] === true; - this.classname = 'oe_form_' + this.type; - - this.width = this.node.attrs.width; - }, - start: function() { - this.$element = $('#' + this.element_id); - }, - stop: function() { - if (this.$element) { - this.$element.remove(); - } - }, - process_modifiers: function() { - var compute_domain = openerp.base.form.compute_domain; - for (var a in this.modifiers) { - this[a] = compute_domain(this.modifiers[a], this.view.fields); - } - }, - update_dom: function() { - this.$element.toggle(!this.invisible); - }, - render: function() { - var template = this.template; - return QWeb.render(template, { "widget": this }); - } -}); - -openerp.base.form.WidgetFrame = openerp.base.form.Widget.extend({ - template: 'WidgetFrame', - init: function(view, node) { - this._super(view, node); - this.columns = parseInt(node.attrs.col || 4, 10); - this.x = 0; - this.y = 0; - this.table = []; - this.add_row(); - for (var i = 0; i < node.children.length; i++) { - var n = node.children[i]; - if (n.tag == "newline") { - this.add_row(); - } else { - this.handle_node(n); - } - } - this.set_row_cells_with(this.table[this.table.length - 1]); - }, - add_row: function(){ - if (this.table.length) { - this.set_row_cells_with(this.table[this.table.length - 1]); - } - var row = []; - this.table.push(row); - this.x = 0; - this.y += 1; - return row; - }, - set_row_cells_with: function(row) { - var bypass = 0, - max_width = 100; - for (var i = 0; i < row.length; i++) { - bypass += row[i].width === undefined ? 0 : 1; - max_width -= row[i].decrease_max_width; - } - var size_unit = Math.round(max_width / (this.columns - bypass)), - colspan_sum = 0; - for (var i = 0; i < row.length; i++) { - var w = row[i]; - colspan_sum += w.colspan; - if (w.width === undefined) { - var width = (i === row.length - 1 && colspan_sum === this.columns) ? max_width : Math.round(size_unit * w.colspan); - max_width -= width; - w.width = width + '%'; - } - } - }, - handle_node: function(node) { - var type = {}; - if (node.tag == 'field') { - type = this.view.fields_view.fields[node.attrs.name] || {}; - } - var widget = new (this.view.registry.get_any( - [node.attrs.widget, type.type, node.tag])) (this.view, node); - if (node.tag == 'field') { - if (!this.view.default_focus_field || node.attrs.default_focus == '1') { - this.view.default_focus_field = widget; - } - if (node.attrs.nolabel != '1') { - var label = new (this.view.registry.get_object('label')) (this.view, node); - label["for"] = widget; - this.add_widget(label, widget.colspan + 1); - } - } - this.add_widget(widget); - }, - add_widget: function(widget, colspan) { - colspan = colspan || widget.colspan; - var current_row = this.table[this.table.length - 1]; - if (current_row.length && (this.x + colspan) > this.columns) { - current_row = this.add_row(); - } - current_row.push(widget); - this.x += widget.colspan; - return widget; - } -}); - -openerp.base.form.WidgetNotebook = openerp.base.form.Widget.extend({ - template: 'WidgetNotebook', - init: function(view, node) { - this._super(view, node); - this.pages = []; - for (var i = 0; i < node.children.length; i++) { - var n = node.children[i]; - if (n.tag == "page") { - var page = new openerp.base.form.WidgetNotebookPage(this.view, n, this, this.pages.length); - this.pages.push(page); - } - } - }, - start: function() { - this._super.apply(this, arguments); - this.$element.tabs(); - this.view.on_button_new.add_last(this.do_select_first_visible_tab); - }, - do_select_first_visible_tab: function() { - for (var i = 0; i < this.pages.length; i++) { - var page = this.pages[i]; - if (page.invisible === false) { - this.$element.tabs('select', page.index); - break; - } - } - } -}); - -openerp.base.form.WidgetNotebookPage = openerp.base.form.WidgetFrame.extend({ - template: 'WidgetNotebookPage', - init: function(view, node, notebook, index) { - this.notebook = notebook; - this.index = index; - this.element_name = 'page_' + index; - this._super(view, node); - this.element_tab_id = this.element_id + '_tab'; - }, - start: function() { - this._super.apply(this, arguments); - this.$element_tab = $('#' + this.element_tab_id); - }, - update_dom: function() { - if (this.invisible && this.index === this.notebook.$element.tabs('option', 'selected')) { - this.notebook.do_select_first_visible_tab(); - } - this.$element_tab.toggle(!this.invisible); - this.$element.toggle(!this.invisible); - } -}); - -openerp.base.form.WidgetSeparator = openerp.base.form.Widget.extend({ - init: function(view, node) { - this._super(view, node); - this.template = "WidgetSeparator"; - this.orientation = node.attrs.orientation || 'horizontal'; - if (this.orientation === 'vertical') { - this.width = '1'; - } - this.classname += '_' + this.orientation; - } -}); - -openerp.base.form.WidgetButton = openerp.base.form.Widget.extend({ - init: function(view, node) { - this._super(view, node); - this.template = "WidgetButton"; - if (this.string) { - // We don't have button key bindings in the webclient - this.string = this.string.replace(/_/g, ''); - } - if (node.attrs.default_focus == '1') { - // TODO fme: provide enter key binding to widgets - this.view.default_focus_button = this; - } - }, - start: function() { - this._super.apply(this, arguments); - this.$element.click(this.on_click); - }, - on_click: function(saved) { - var self = this; - if (!this.node.attrs.special && this.view.dirty && saved !== true) { - this.view.do_save(function() { - self.on_click(true); - }); - } else { - if (this.node.attrs.confirm) { - var dialog = $('<div>' + this.node.attrs.confirm + '</div>').dialog({ - title: 'Confirm', - modal: true, - buttons: { - Ok: function() { - self.on_confirmed(); - $(this).dialog("close"); - }, - Cancel: function() { - $(this).dialog("close"); - } - } - }); - } else { - this.on_confirmed(); - } - } - }, - on_confirmed: function() { - var self = this; - - this.view.execute_action( - this.node.attrs, this.view.dataset, this.view.datarecord.id, function () { - self.view.reload(); - }); - } -}); - -openerp.base.form.WidgetLabel = openerp.base.form.Widget.extend({ - init: function(view, node) { - this.element_name = 'label_' + node.attrs.name; - - this._super(view, node); - - // TODO fme: support for attrs.align - if (this.node.tag == 'label' && (this.node.attrs.colspan || (this.string && this.string.length > 32))) { - this.template = "WidgetParagraph"; - this.colspan = parseInt(this.node.attrs.colspan || 1, 10); - } else { - this.template = "WidgetLabel"; - this.colspan = 1; - this.width = '1%'; - this.decrease_max_width = 1; - this.nowrap = true; - } - }, - render: function () { - if (this['for'] && this.type !== 'label') { - return QWeb.render(this.template, {widget: this['for']}); - } - // Actual label widgets should not have a false and have type label - return QWeb.render(this.template, {widget: this}); - }, - start: function() { - this._super(); - var self = this; - this.$element.find("label").dblclick(function() { - var widget = self['for'] || self; - self.log(widget.element_id , widget); - window.w = widget; - }); - } -}); - -openerp.base.form.Field = openerp.base.form.Widget.extend({ - init: function(view, node) { - this.name = node.attrs.name; - this.value = undefined; - view.fields[this.name] = this; - this.type = node.attrs.widget || view.fields_view.fields[node.attrs.name].type; - this.element_name = "field_" + this.name + "_" + this.type; - - this._super(view, node); - - if (node.attrs.nolabel != '1' && this.colspan > 1) { - this.colspan--; - } - this.field = view.fields_view.fields[node.attrs.name] || {}; - this.string = node.attrs.string || this.field.string; - this.help = node.attrs.help || this.field.help; - this.nolabel = (this.field.nolabel || node.attrs.nolabel) === '1'; - this.readonly = this.modifiers['readonly'] === true; - this.required = this.modifiers['required'] === true; - this.invalid = false; - this.dirty = false; - - this.classname = 'oe_form_field_' + this.type; - }, - start: function() { - this._super.apply(this, arguments); - if (this.field.translate) { - this.view.translatable_fields.push(this); - this.$element.find('.oe_field_translate').click(this.on_translate); - } - }, - set_value: function(value) { - this.value = value; - this.invalid = false; - this.update_dom(); - this.on_value_changed(); - }, - set_value_from_ui: function() { - this.on_value_changed(); - }, - on_value_changed: function() { - }, - on_translate: function() { - this.view.open_translate_dialog(this); - }, - get_value: function() { - return this.value; - }, - is_valid: function() { - return !this.invalid; - }, - is_dirty: function() { - return this.dirty; - }, - get_on_change_value: function() { - return this.get_value(); - }, - update_dom: function() { - this._super.apply(this, arguments); - if (this.field.translate) { - this.$element.find('.oe_field_translate').toggle(!!this.view.datarecord.id); - } - if (!this.disable_utility_classes) { - this.$element.toggleClass('disabled', this.readonly); - this.$element.toggleClass('required', this.required); - if (this.view.show_invalid) { - this.$element.toggleClass('invalid', !this.is_valid()); - } - } - }, - on_ui_change: function() { - this.dirty = this.view.dirty = true; - this.validate(); - if (this.is_valid()) { - this.set_value_from_ui(); - this.view.do_onchange(this); - this.view.on_form_changed(); - } else { - this.update_dom(); - } - }, - validate: function() { - this.invalid = false; - }, - focus: function() { - }, - _build_view_fields_values: function() { - var a_dataset = this.view.dataset || {}; - var fields_values = this.view.get_fields_values(); - var parent_values = a_dataset.parent_view ? a_dataset.parent_view.get_fields_values() : {}; - fields_values.parent = parent_values; - return fields_values; - }, - /** - * Builds a new context usable for operations related to fields by merging - * the fields'context with the action's context. - */ - build_context: function() { - // I previously belevied contexts should be herrited, but now I doubt it - //var a_context = this.view.dataset.get_context() || {}; - var f_context = this.field.context || null; - // maybe the default_get should only be used when we do a default_get? - var v_context1 = this.node.attrs.default_get || {}; - var v_context2 = this.node.attrs.context || {}; - var v_context = new openerp.base.CompoundContext(v_context1, v_context2); - if (v_context1.__ref || v_context2.__ref || true) { //TODO niv: remove || true - var fields_values = this._build_view_fields_values(); - v_context.set_eval_context(fields_values); - } - // if there is a context on the node, overrides the model's context - var ctx = f_context || v_context; - return ctx; - }, - build_domain: function() { - var f_domain = this.field.domain || null; - var v_domain = this.node.attrs.domain || []; - if (!(v_domain instanceof Array) || true) { //TODO niv: remove || true - var fields_values = this._build_view_fields_values(); - v_domain = new openerp.base.CompoundDomain(v_domain).set_eval_context(fields_values); - } - // if there is a domain on the node, overrides the model's domain - return f_domain || v_domain; - } -}); - -openerp.base.form.FieldChar = openerp.base.form.Field.extend({ - init: function(view, node) { - this._super(view, node); - this.template = "FieldChar"; - }, - start: function() { - this._super.apply(this, arguments); - this.$element.find('input').change(this.on_ui_change); - }, - set_value: function(value) { - this._super.apply(this, arguments); - var show_value = openerp.base.format_value(value, this, ''); - this.$element.find('input').val(show_value); - }, - update_dom: function() { - this._super.apply(this, arguments); - this.$element.find('input').attr('disabled', this.readonly); - }, - set_value_from_ui: function() { - this.value = openerp.base.parse_value(this.$element.find('input').val(), this); - this._super(); - }, - validate: function() { - this.invalid = false; - try { - var value = openerp.base.parse_value(this.$element.find('input').val(), this, ''); - this.invalid = this.required && value === ''; - } catch(e) { - this.invalid = true; - } - }, - focus: function() { - this.$element.find('input').focus(); - } -}); - -openerp.base.form.FieldEmail = openerp.base.form.FieldChar.extend({ - init: function(view, node) { - this._super(view, node); - this.template = "FieldEmail"; - }, - start: function() { - this._super.apply(this, arguments); - this.$element.find('button').click(this.on_button_clicked); - }, - on_button_clicked: function() { - if (!this.value || !this.is_valid()) { - this.notification.warn("E-mail error", "Can't send email to invalid e-mail address"); - } else { - location.href = 'mailto:' + this.value; - } - }, - set_value: function(value) { - this._super.apply(this, arguments); - this.$element.find('a').attr('href', 'mailto:' + this.$element.find('input').val()); - } -}); - -openerp.base.form.FieldUrl = openerp.base.form.FieldChar.extend({ - init: function(view, node) { - this._super(view, node); - this.template = "FieldUrl"; - }, - start: function() { - this._super.apply(this, arguments); - this.$element.find('button').click(this.on_button_clicked); - }, - on_button_clicked: function() { - if (!this.value) { - this.notification.warn("Resource error", "This resource is empty"); - } else { - window.open(this.value); - } - } -}); - -openerp.base.form.FieldFloat = openerp.base.form.FieldChar.extend({ - set_value: function(value) { - if (value === false || value === undefined) { - // As in GTK client, floats default to 0 - value = 0; - this.dirty = true; - } - this._super.apply(this, [value]); - } -}); - -openerp.base.form.FieldDatetime = openerp.base.form.Field.extend({ - init: function(view, node) { - this._super(view, node); - this.template = "FieldDate"; - this.jqueryui_object = 'datetimepicker'; - }, - start: function() { - this._super.apply(this, arguments); - this.$element.find('input').change(this.on_ui_change)[this.jqueryui_object]({ - dateFormat: 'yy-mm-dd', - timeFormat: 'hh:mm:ss', - showOn: 'button', - buttonImage: '/base/static/src/img/ui/field_calendar.png', - buttonImageOnly: true, - constrainInput: false - }); - }, - set_value: function(value) { - this._super.apply(this, arguments); - if (!value) { - this.$element.find('input').val(''); - } else { - this.$element.find('input').unbind('change'); - // jQuery UI date picker wrongly call on_change event herebelow - this.$element.find('input')[this.jqueryui_object]('setDate', this.parse(value)); - this.$element.find('input').change(this.on_ui_change); - } - }, - set_value_from_ui: function() { - this.value = this.$element.find('input')[this.jqueryui_object]('getDate') || false; - if (this.value) { - this.value = this.format(this.value); - } - this._super(); - }, - update_dom: function() { - this._super.apply(this, arguments); - this.$element.find('input').datepicker(this.readonly ? 'disable' : 'enable'); - }, - validate: function() { - this.invalid = false; - var value = this.$element.find('input').val(); - if (value === "") { - this.invalid = this.required; - } else { - this.invalid = !this.$element.find('input')[this.jqueryui_object]('getDate'); - } - }, - focus: function() { - this.$element.find('input').focus(); - }, - parse: openerp.base.auto_str_to_date, - format: function(val) { - return openerp.base.auto_date_to_str(val, this.field.type); - } -}); - -openerp.base.form.FieldDate = openerp.base.form.FieldDatetime.extend({ - init: function(view, node) { - this._super(view, node); - this.jqueryui_object = 'datepicker'; - } -}); - -openerp.base.form.FieldText = openerp.base.form.Field.extend({ - init: function(view, node) { - this._super(view, node); - this.template = "FieldText"; - }, - start: function() { - this._super.apply(this, arguments); - this.$element.find('textarea').change(this.on_ui_change); - }, - set_value: function(value) { - this._super.apply(this, arguments); - var show_value = openerp.base.format_value(value, this, ''); - this.$element.find('textarea').val(show_value); - }, - update_dom: function() { - this._super.apply(this, arguments); - this.$element.find('textarea').attr('disabled', this.readonly); - }, - set_value_from_ui: function() { - this.value = openerp.base.parse_value(this.$element.find('textarea').val(), this); - this._super(); - }, - validate: function() { - this.invalid = false; - try { - var value = openerp.base.parse_value(this.$element.find('textarea').val(), this, ''); - this.invalid = this.required && value === ''; - } catch(e) { - this.invalid = true; - } - }, - focus: function() { - this.$element.find('textarea').focus(); - } -}); - -openerp.base.form.FieldBoolean = openerp.base.form.Field.extend({ - init: function(view, node) { - this._super(view, node); - this.template = "FieldBoolean"; - }, - start: function() { - var self = this; - this._super.apply(this, arguments); - this.$element.find('input').click(function() { - if ($(this).is(':checked') != self.value) { - self.on_ui_change(); - } - }); - }, - set_value: function(value) { - this._super.apply(this, arguments); - this.$element.find('input')[0].checked = value; - }, - set_value_from_ui: function() { - this.value = this.$element.find('input').is(':checked'); - this._super(); - }, - update_dom: function() { - this._super.apply(this, arguments); - this.$element.find('input').attr('disabled', this.readonly); - }, - validate: function() { - this.invalid = this.required && !this.$element.find('input').is(':checked'); - }, - focus: function() { - this.$element.find('input').focus(); - } -}); - -openerp.base.form.FieldProgressBar = openerp.base.form.Field.extend({ - init: function(view, node) { - this._super(view, node); - this.template = "FieldProgressBar"; - }, - start: function() { - this._super.apply(this, arguments); - this.$element.find('div').progressbar({ - value: this.value, - disabled: this.readonly - }); - }, - set_value: function(value) { - this._super.apply(this, arguments); - var show_value = Number(value); - if (isNaN(show_value)) { - show_value = 0; - } - this.$element.find('div').progressbar('option', 'value', show_value).find('span').html(show_value + '%'); - } -}); - -openerp.base.form.FieldTextXml = openerp.base.form.Field.extend({ -// to replace view editor -}); - -openerp.base.form.FieldSelection = openerp.base.form.Field.extend({ - init: function(view, node) { - this._super(view, node); - this.template = "FieldSelection"; - this.field_index = _.map(this.field.selection, function(x, index) { - return {"ikey": "" + index, "ekey": x[0], "label": x[1]}; - }); - }, - start: function() { - // Flag indicating whether we're in an event chain containing a change - // event on the select, in order to know what to do on keyup[RETURN]: - // * If the user presses [RETURN] as part of changing the value of a - // selection, we should just let the value change and not let the - // event broadcast further (e.g. to validating the current state of - // the form in editable list view, which would lead to saving the - // current row or switching to the next one) - // * If the user presses [RETURN] with a select closed (side-effect: - // also if the user opened the select and pressed [RETURN] without - // changing the selected value), takes the action as validating the - // row - var ischanging = false; - this._super.apply(this, arguments); - this.$element.find('select') - .change(this.on_ui_change) - .change(function () { ischanging = true; }) - .click(function () { ischanging = false; }) - .keyup(function (e) { - if (e.which !== 13 || !ischanging) { return; } - e.stopPropagation(); - ischanging = false; - }); - }, - set_value: function(value) { - value = value === null ? false : value; - value = value instanceof Array ? value[0] : value; - this._super(value); - var option = _.detect(this.field_index, function(x) {return x.ekey === value;}); - this.$element.find('select').val(option === undefined ? '' : option.ikey); - }, - set_value_from_ui: function() { - var ikey = this.$element.find('select').val(); - var option = _.detect(this.field_index, function(x) {return x.ikey === ikey;}); - this.value = option === undefined ? false : option.ekey; - this._super(); - }, - update_dom: function() { - this._super.apply(this, arguments); - this.$element.find('select').attr('disabled', this.readonly); - }, - validate: function() { - var ikey = this.$element.find('select').val(); - var option = _.detect(this.field_index, function(x) {return x.ikey === ikey;}); - this.invalid = this.required && (option === undefined || option.ekey === false); - }, - focus: function() { - this.$element.find('select').focus(); - } -}); - -// jquery autocomplete tweak to allow html -(function() { - var proto = $.ui.autocomplete.prototype, - initSource = proto._initSource; - - function filter( array, term ) { - var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); - return $.grep( array, function(value) { - return matcher.test( $( "<div>" ).html( value.label || value.value || value ).text() ); - }); - } - - $.extend( proto, { - _initSource: function() { - if ( this.options.html && $.isArray(this.options.source) ) { - this.source = function( request, response ) { - response( filter( this.options.source, request.term ) ); - }; - } else { - initSource.call( this ); - } - }, - - _renderItem: function( ul, item) { - return $( "<li></li>" ) - .data( "item.autocomplete", item ) - .append( $( "<a></a>" )[ this.options.html ? "html" : "text" ]( item.label ) ) - .appendTo( ul ); - } - }); -})(); - -openerp.base.form.dialog = function(content, options) { - options = _.extend({ - autoOpen: true, - width: '90%', - height: '90%', - min_width: '800px', - min_height: '600px' - }, options || {}); - options.autoOpen = true; - var dialog = new openerp.base.Dialog(null, options); - dialog.$dialog = $(content).dialog(dialog.dialog_options); - return dialog.$dialog; -} - -openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({ - init: function(view, node) { - this._super(view, node); - this.template = "FieldMany2One"; - this.limit = 7; - this.value = null; - this.cm_id = _.uniqueId('m2o_cm_'); - this.last_search = []; - this.tmp_value = undefined; - }, - start: function() { - this._super(); - var self = this; - this.$input = this.$element.find("input"); - this.$drop_down = this.$element.find(".oe-m2o-drop-down-button"); - this.$menu_btn = this.$element.find(".oe-m2o-cm-button"); - - // context menu - var init_context_menu_def = $.Deferred().then(function(e) { - var rdataset = new openerp.base.DataSetStatic(self, "ir.values", self.build_context()); - rdataset.call("get", ['action', 'client_action_relate', - [[self.field.relation, false]], false, rdataset.get_context()], false, 0) - .then(function(result) { - self.related_entries = result; - - var $cmenu = $("#" + self.cm_id); - $cmenu.append(QWeb.render("FieldMany2One.context_menu", {widget: self})); - var bindings = {}; - bindings[self.cm_id + "_search"] = function() { - self._search_create_popup("search"); - }; - bindings[self.cm_id + "_create"] = function() { - self._search_create_popup("form"); - }; - bindings[self.cm_id + "_open"] = function() { - if (!self.value) { - return; - } - var pop = new openerp.base.form.FormOpenPopup(self.view); - pop.show_element(self.field.relation, self.value[0],self.build_context(), {}); - pop.on_write_completed.add_last(function() { - self.set_value(self.value[0]); - }); - }; - _.each(_.range(self.related_entries.length), function(i) { - bindings[self.cm_id + "_related_" + i] = function() { - self.open_related(self.related_entries[i]); - }; - }); - var cmenu = self.$menu_btn.contextMenu(self.cm_id, {'leftClickToo': true, - bindings: bindings, itemStyle: {"color": ""}, - onContextMenu: function() { - if(self.value) { - $("#" + self.cm_id + " .oe_m2o_menu_item_mandatory").removeClass("oe-m2o-disabled-cm"); - } else { - $("#" + self.cm_id + " .oe_m2o_menu_item_mandatory").addClass("oe-m2o-disabled-cm"); - } - return true; - }, menuStyle: {width: "200px"} - }); - setTimeout(function() {self.$menu_btn.trigger(e);}, 0); - }); - }); - var ctx_callback = function(e) {init_context_menu_def.resolve(e); e.preventDefault()}; - this.$menu_btn.bind('contextmenu', ctx_callback); - this.$menu_btn.click(ctx_callback); - - // some behavior for input - this.$input.keyup(function() { - if (self.$input.val() === "") { - self._change_int_value(null); - } else if (self.value === null || (self.value && self.$input.val() !== self.value[1])) { - self._change_int_value(undefined); - } - }); - this.$drop_down.click(function() { - if (self.$input.autocomplete("widget").is(":visible")) { - self.$input.autocomplete("close"); - } else { - if (self.value) { - self.$input.autocomplete("search", ""); - } else { - self.$input.autocomplete("search"); - } - self.$input.focus(); - } - }); - var anyoneLoosesFocus = function() { - if (!self.$input.is(":focus") && - !self.$input.autocomplete("widget").is(":visible") && - !self.value) { - if(self.value === undefined && self.last_search.length > 0) { - self._change_int_ext_value(self.last_search[0]); - } else { - self._change_int_ext_value(null); - } - } - } - this.$input.focusout(anyoneLoosesFocus); - - var isSelecting = false; - // autocomplete - this.$input.autocomplete({ - source: function(req, resp) { self.get_search_result(req, resp); }, - select: function(event, ui) { - isSelecting = true; - var item = ui.item; - if (item.id) { - self._change_int_value([item.id, item.name]); - } else if (item.action) { - self._change_int_value(undefined); - item.action(); - return false; - } - }, - focus: function(e, ui) { - e.preventDefault(); - }, - html: true, - close: anyoneLoosesFocus, - minLength: 0, - delay: 0 - }); - // used to correct a bug when selecting an element by pushing 'enter' in an editable list - this.$input.keyup(function(e) { - if (e.which === 13) { - if (isSelecting) - e.stopPropagation(); - } - isSelecting = false; - }); - }, - // autocomplete component content handling - get_search_result: function(request, response) { - var search_val = request.term; - var self = this; - - var dataset = new openerp.base.DataSetStatic(this, this.field.relation, self.build_context()); - - dataset.name_search(search_val, self.build_domain(), 'ilike', - this.limit + 1, function(data) { - self.last_search = data; - // possible selections for the m2o - var values = _.map(data, function(x) { - return {label: $('<span />').text(x[1]).html(), name:x[1], id:x[0]}; - }); - - // search more... if more results that max - if (values.length > self.limit) { - values = values.slice(0, self.limit); - values.push({label: _t("<em> Search More...</em>"), action: function() { - dataset.name_search(search_val, self.build_domain(), 'ilike' - , false, function(data) { - self._change_int_value(null); - self._search_create_popup("search", data); - }); - }}); - } - // quick create - var raw_result = _(data.result).map(function(x) {return x[1];}) - if (search_val.length > 0 && - !_.include(raw_result, search_val) && - (!self.value || search_val !== self.value[1])) { - values.push({label: _.sprintf(_t('<em> Create "<strong>%s</strong>"</em>'), - $('<span />').text(search_val).html()), action: function() { - self._quick_create(search_val); - }}); - } - // create... - values.push({label: _t("<em> Create and Edit...</em>"), action: function() { - self._change_int_value(null); - self._search_create_popup("form", undefined, {"default_name": search_val}); - }}); - - response(values); - }); - }, - _quick_create: function(name) { - var self = this; - var dataset = new openerp.base.DataSetStatic(this, this.field.relation, self.build_context()); - dataset.name_create(name, function(data) { - self._change_int_ext_value(data); - }).fail(function(error, event) { - event.preventDefault(); - self._change_int_value(null); - self._search_create_popup("form", undefined, {"default_name": name}); - }); - }, - // all search/create popup handling - _search_create_popup: function(view, ids, context) { - var self = this; - var pop = new openerp.base.form.SelectCreatePopup(this); - pop.select_element(self.field.relation,{ - initial_ids: ids ? _.map(ids, function(x) {return x[0]}) : undefined, - initial_view: view, - disable_multiple_selection: true - }, self.build_domain(), - new openerp.base.CompoundContext(self.build_context(), context || {})); - pop.on_select_elements.add(function(element_ids) { - var dataset = new openerp.base.DataSetStatic(self, self.field.relation, self.build_context()); - dataset.name_get([element_ids[0]], function(data) { - self._change_int_ext_value(data[0]); - }); - }); - }, - _change_int_ext_value: function(value) { - this._change_int_value(value); - this.$input.val(this.value ? this.value[1] : ""); - }, - _change_int_value: function(value) { - this.value = value; - var back_orig_value = this.original_value; - if (this.value === null || this.value) { - this.original_value = this.value; - } - if (back_orig_value === undefined) { // first use after a set_value() - return; - } - if (this.value !== undefined && ((back_orig_value ? back_orig_value[0] : null) - !== (this.value ? this.value[0] : null))) { - this.on_ui_change(); - } - }, - set_value: function(value) { - value = value || null; - this.invalid = false; - var self = this; - this.tmp_value = value; - self.update_dom(); - self.on_value_changed(); - var real_set_value = function(rval) { - self.tmp_value = undefined; - self.value = rval; - self.original_value = undefined; - self._change_int_ext_value(rval); - }; - if(typeof(value) === "number") { - var dataset = new openerp.base.DataSetStatic(this, this.field.relation, self.build_context()); - dataset.name_get([value], function(data) { - real_set_value(data[0]); - }).fail(function() {self.tmp_value = undefined;}); - } else { - setTimeout(function() {real_set_value(value);}, 0); - } - }, - get_value: function() { - if (this.tmp_value !== undefined) { - if (this.tmp_value instanceof Array) { - return this.tmp_value[0]; - } - return this.tmp_value ? this.tmp_value : false; - } - if (this.value === undefined) - return this.original_value ? this.original_value[0] : false; - return this.value ? this.value[0] : false; - }, - validate: function() { - this.invalid = false; - var val = this.tmp_value !== undefined ? this.tmp_value : this.value; - if (val === null) { - this.invalid = this.required; - } - }, - open_related: function(related) { - var self = this; - if (!self.value) - return; - var additional_context = { - active_id: self.value[0], - active_ids: [self.value[0]], - active_model: self.field.relation - }; - self.rpc("/base/action/load", { - action_id: related[2].id, - context: additional_context - }, function(result) { - result.result.context = _.extend(result.result.context || {}, additional_context); - self.do_action(result.result); - }); - } -}); - -/* -# Values: (0, 0, { fields }) create -# (1, ID, { fields }) update -# (2, ID) remove (delete) -# (3, ID) unlink one (target id or target of relation) -# (4, ID) link -# (5) unlink all (only valid for one2many) -*/ -var commands = { - // (0, _, {values}) - CREATE: 0, - 'create': function (values) { - return [commands.CREATE, false, values]; - }, - // (1, id, {values}) - UPDATE: 1, - 'update': function (id, values) { - return [commands.UPDATE, id, values]; - }, - // (2, id[, _]) - DELETE: 2, - 'delete': function (id) { - return [commands.DELETE, id, false]; - }, - // (3, id[, _]) removes relation, but not linked record itself - FORGET: 3, - 'forget': function (id) { - return [commands.FORGET, id, false]; - }, - // (4, id[, _]) - LINK_TO: 4, - 'link_to': function (id) { - return [commands.LINK_TO, id, false]; - }, - // (5[, _[, _]]) - DELETE_ALL: 5, - 'delete_all': function () { - return [5, false, false]; - }, - // (6, _, ids) replaces all linked records with provided ids - REPLACE_WITH: 6, - 'replace_with': function (ids) { - return [6, false, ids]; - } -}; -openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({ - multi_selection: false, - init: function(view, node) { - this._super(view, node); - this.template = "FieldOne2Many"; - this.is_started = $.Deferred(); - this.form_last_update = $.Deferred(); - this.disable_utility_classes = true; - }, - start: function() { - this._super.apply(this, arguments); - - var self = this; - - this.dataset = new openerp.base.form.One2ManyDataSet(this, this.field.relation); - this.dataset.o2m = this; - this.dataset.parent_view = this.view; - this.dataset.on_change.add_last(function() { - self.on_ui_change(); - }); - - var modes = this.node.attrs.mode; - modes = !!modes ? modes.split(",") : ["tree", "form"]; - var views = []; - _.each(modes, function(mode) { - var view = { - view_id: false, - view_type: mode == "tree" ? "list" : mode, - options: { sidebar : false } - }; - if (self.field.views && self.field.views[mode]) { - view.embedded_view = self.field.views[mode]; - } - if(view.view_type === "list") { - view.options.selectable = self.multi_selection; - } - views.push(view); - }); - this.views = views; - - this.viewmanager = new openerp.base.ViewManager(this, this.dataset, views); - this.viewmanager.registry = openerp.base.views.clone({ - list: 'openerp.base.form.One2ManyListView', - form: 'openerp.base.form.One2ManyFormView' - }); - var once = $.Deferred().then(function() { - self.form_last_update.resolve(); - }); - this.viewmanager.on_controller_inited.add_last(function(view_type, controller) { - if (view_type == "list") { - controller.o2m = self; - } else if (view_type == "form") { - controller.on_record_loaded.add_last(function() { - once.resolve(); - }); - controller.on_pager_action.add_first(function() { - self.save_form_view(); - }); - controller.$element.find(".oe_form_button_save_edit").hide(); - } - self.is_started.resolve(); - }); - this.viewmanager.on_mode_switch.add_first(function() { - self.save_form_view(); - }); - setTimeout(function () { - self.viewmanager.appendTo(self.$element); - }, 0); - }, - reload_current_view: function() { - var self = this; - var view = self.viewmanager.views[self.viewmanager.active_view].controller; - if(self.viewmanager.active_view === "list") { - view.reload_content(); - } else if (self.viewmanager.active_view === "form") { - if (this.dataset.index === null && this.dataset.ids.length >= 1) { - this.dataset.index = 0; - } - this.form_last_update.then(function() { - this.form_last_update = view.do_show(); - }); - } - }, - set_value: function(value) { - value = value || []; - var self = this; - this.dataset.reset_ids([]); - if(value.length >= 1 && value[0] instanceof Array) { - var ids = []; - _.each(value, function(command) { - var obj = {values: command[2]}; - switch (command[0]) { - case commands.CREATE: - obj['id'] = _.uniqueId(self.dataset.virtual_id_prefix); - self.dataset.to_create.push(obj); - self.dataset.cache.push(_.clone(obj)); - ids.push(obj.id); - return; - case commands.UPDATE: - obj['id'] = command[1]; - self.dataset.to_write.push(obj); - self.dataset.cache.push(_.clone(obj)); - ids.push(obj.id); - return; - case commands.DELETE: - self.dataset.to_delete.push({id: command[1]}); - return; - case commands.LINK_TO: - ids.push(command[1]); - return; - case commands.DELETE_ALL: - self.dataset.delete_all = true; - return; - } - }); - this._super(ids); - this.dataset.set_ids(ids); - } else if (value.length >= 1 && typeof(value[0]) === "object") { - var ids = []; - this.dataset.delete_all = true; - _.each(value, function(command) { - var obj = {values: command}; - obj['id'] = _.uniqueId(self.dataset.virtual_id_prefix); - self.dataset.to_create.push(obj); - self.dataset.cache.push(_.clone(obj)); - ids.push(obj.id); - }); - this._super(ids); - this.dataset.set_ids(ids); - } else { - this._super(value); - this.dataset.reset_ids(value); - } - if (this.dataset.index === null && this.dataset.ids.length > 0) { - this.dataset.index = 0; - } - $.when(this.is_started).then(function() { - self.reload_current_view(); - }); - }, - get_value: function() { - var self = this; - if (!this.dataset) - return []; - 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;}); - if (alter_order) { - return commands.create(alter_order.values); - } - alter_order = _.detect(self.dataset.to_write, function(x) {return x.id === id;}); - if (alter_order) { - return commands.update(alter_order.id, alter_order.values); - } - return commands.link_to(id); - })); - return val.concat(_.map( - this.dataset.to_delete, function(x) { - return commands['delete'](x.id);})); - }, - save_form_view: function() { - if (this.viewmanager && this.viewmanager.views && this.viewmanager.active_view && - this.viewmanager.views[this.viewmanager.active_view] && - this.viewmanager.views[this.viewmanager.active_view].controller) { - var view = this.viewmanager.views[this.viewmanager.active_view].controller; - if (this.viewmanager.active_view === "form") { - var res = view.do_save(); - if (res === false) { - // ignore - } else if (res.isRejected()) { - throw "Save or create on one2many dataset is not supposed to fail."; - } else if (!res.isResolved()) { - throw "Asynchronous get_value() is not supported in form view."; - } - return res; - } - } - return false; - }, - is_valid: function() { - this.validate(); - return this._super(); - }, - validate: function() { - this.invalid = false; - var self = this; - var view = self.viewmanager.views[self.viewmanager.active_view].controller; - if (self.viewmanager.active_view === "form") { - for (var f in view.fields) { - f = view.fields[f]; - if (!f.is_valid()) { - this.invalid = true; - return; - } - } - } - }, - is_dirty: function() { - this.save_form_view(); - return this._super(); - }, - update_dom: function() { - this._super.apply(this, arguments); - this.$element.toggleClass('disabled', this.readonly); - } -}); - -openerp.base.form.One2ManyDataSet = openerp.base.BufferedDataSet.extend({ - get_context: function() { - this.context = this.o2m.build_context(); - return this.context; - } -}); - -openerp.base.form.One2ManyFormView = openerp.base.FormView.extend({ - -}); - -openerp.base.form.One2ManyListView = openerp.base.ListView.extend({ - do_add_record: function () { - if (this.options.editable) { - this._super.apply(this, arguments); - } else { - var self = this; - var pop = new openerp.base.form.SelectCreatePopup(this); - pop.select_element(self.o2m.field.relation,{ - initial_view: "form", - alternative_form_view: self.o2m.field.views ? self.o2m.field.views["form"] : undefined, - create_function: function(data) { - return self.o2m.dataset.create(data, function(r) { - self.o2m.dataset.set_ids(self.o2m.dataset.ids.concat([r.result])); - self.o2m.dataset.on_change(); - }); - }, - parent_view: self.o2m.view - }, self.o2m.build_domain(), self.o2m.build_context()); - pop.on_select_elements.add_last(function() { - self.o2m.reload_current_view(); - }); - } - }, - do_activate_record: function(index, id) { - var self = this; - var pop = new openerp.base.form.FormOpenPopup(self.o2m.view); - pop.show_element(self.o2m.field.relation, id, self.o2m.build_context(),{ - auto_write: false, - alternative_form_view: self.o2m.field.views ? self.o2m.field.views["form"] : undefined, - parent_view: self.o2m.view, - read_function: function() { - return self.o2m.dataset.read_ids.apply(self.o2m.dataset, arguments); - } - }); - pop.on_write.add(function(id, data) { - self.o2m.dataset.write(id, data, {}, function(r) { - self.o2m.reload_current_view(); - }); - }); - } -}); - -openerp.base.form.FieldMany2Many = openerp.base.form.Field.extend({ - multi_selection: false, - init: function(view, node) { - this._super(view, node); - this.template = "FieldMany2Many"; - this.list_id = _.uniqueId("many2many"); - this.is_started = $.Deferred(); - }, - start: function() { - this._super.apply(this, arguments); - - var self = this; - - this.dataset = new openerp.base.form.Many2ManyDataSet(this, this.field.relation); - this.dataset.m2m = this; - this.dataset.on_unlink.add_last(function(ids) { - self.on_ui_change(); - }); - - this.list_view = new openerp.base.form.Many2ManyListView(this, this.list_id, this.dataset, false, { - 'addable': 'Add', - 'selectable': self.multi_selection - }); - this.list_view.m2m_field = this; - this.list_view.on_loaded.add_last(function() { - self.is_started.resolve(); - }); - setTimeout(function () { - self.list_view.start(); - }, 0); - }, - set_value: function(value) { - value = value || []; - if (value.length >= 1 && value[0] instanceof Array) { - value = value[0][2]; - } - this._super(value); - this.dataset.set_ids(value); - var self = this; - $.when(this.is_started).then(function() { - self.list_view.reload_content(); - }); - }, - get_value: function() { - return [commands.replace_with(this.dataset.ids)]; - }, - validate: function() { - this.invalid = false; - // TODO niv - } -}); - -openerp.base.form.Many2ManyDataSet = openerp.base.DataSetStatic.extend({ - get_context: function() { - this.context = this.m2m.build_context(); - return this.context; - } -}); - -openerp.base.form.Many2ManyListView = openerp.base.ListView.extend({ - do_add_record: function () { - var pop = new openerp.base.form.SelectCreatePopup(this); - pop.select_element(this.model, {}, - new openerp.base.CompoundDomain(this.m2m_field.build_domain(), ["!", ["id", "in", this.m2m_field.dataset.ids]]), - this.m2m_field.build_context()); - var self = this; - pop.on_select_elements.add(function(element_ids) { - _.each(element_ids, function(element_id) { - if(! _.detect(self.dataset.ids, function(x) {return x == element_id;})) { - self.dataset.set_ids([].concat(self.dataset.ids, [element_id])); - self.m2m_field.on_ui_change(); - self.reload_content(); - } - }); - }); - }, - do_activate_record: function(index, id) { - var self = this; - var pop = new openerp.base.form.FormOpenPopup(this); - pop.show_element(this.dataset.model, id, this.m2m_field.build_context(), {}); - pop.on_write_completed.add_last(function() { - self.reload_content(); - }); - } -}); - -openerp.base.form.SelectCreatePopup = openerp.base.OldWidget.extend({ - identifier_prefix: "selectcreatepopup", - template: "SelectCreatePopup", - /** - * options: - * - initial_ids - * - initial_view: form or search (default search) - * - disable_multiple_selection - * - alternative_form_view - * - create_function (defaults to a naive saving behavior) - * - parent_view - */ - select_element: function(model, options, domain, context) { - var self = this; - this.model = model; - this.domain = domain || []; - this.context = context || {}; - this.options = _.defaults(options || {}, {"initial_view": "search", "create_function": function() { - return self.create_row.apply(self, arguments); - }}); - this.initial_ids = this.options.initial_ids; - this.created_elements = []; - openerp.base.form.dialog(this.render(), {close:function() { - self.check_exit(); - }}); - this.start(); - }, - start: function() { - this._super(); - this.dataset = new openerp.base.ReadOnlyDataSetSearch(this, this.model, - this.context); - this.dataset.parent_view = this.options.parent_view; - if (this.options.initial_view == "search") { - this.setup_search_view(); - } else { // "form" - this.new_object(); - } - }, - setup_search_view: function() { - var self = this; - if (this.searchview) { - this.searchview.stop(); - } - this.searchview = new openerp.base.SearchView(this, - this.element_id + "_search", this.dataset, false, { - "selectable": !this.options.disable_multiple_selection, - "deletable": false - }); - this.searchview.on_search.add(function(domains, contexts, groupbys) { - if (self.initial_ids) { - self.view_list.do_search.call(self, domains.concat([[["id", "in", self.initial_ids]], self.domain]), - contexts, groupbys); - self.initial_ids = undefined; - } else { - self.view_list.do_search.call(self, domains.concat([self.domain]), contexts, groupbys); - } - }); - this.searchview.on_loaded.add_last(function () { - var $buttons = self.searchview.$element.find(".oe_search-view-buttons"); - $buttons.append(QWeb.render("SelectCreatePopup.search.buttons")); - var $cbutton = $buttons.find(".oe_selectcreatepopup-search-close"); - $cbutton.click(function() { - self.stop(); - }); - var $sbutton = $buttons.find(".oe_selectcreatepopup-search-select"); - if(self.options.disable_multiple_selection) { - $sbutton.hide(); - } - $sbutton.click(function() { - self.on_select_elements(self.selected_ids); - self.stop(); - }); - self.view_list = new openerp.base.form.SelectCreateListView(self, - self.element_id + "_view_list", self.dataset, false, - {'deletable': false}); - self.view_list.popup = self; - self.view_list.do_show(); - self.view_list.start().then(function() { - self.searchview.do_search(); - }); - }); - this.searchview.start(); - }, - create_row: function(data) { - var self = this; - var wdataset = new openerp.base.DataSetSearch(this, this.model, this.context, this.domain); - wdataset.parent_view = this.options.parent_view; - return wdataset.create(data); - }, - on_select_elements: function(element_ids) { - }, - on_click_element: function(ids) { - this.selected_ids = ids || []; - if(this.selected_ids.length > 0) { - this.$element.find(".oe_selectcreatepopup-search-select").removeAttr('disabled'); - } else { - this.$element.find(".oe_selectcreatepopup-search-select").attr('disabled', "disabled"); - } - }, - new_object: function() { - var self = this; - if (this.searchview) { - this.searchview.hide(); - } - if (this.view_list) { - this.view_list.$element.hide(); - } - this.dataset.index = null; - this.view_form = new openerp.base.FormView(this, this.element_id + "_view_form", this.dataset, false); - if (this.options.alternative_form_view) { - this.view_form.set_embedded_view(this.options.alternative_form_view); - } - this.view_form.start(); - this.view_form.on_loaded.add_last(function() { - var $buttons = self.view_form.$element.find(".oe_form_buttons"); - $buttons.html(QWeb.render("SelectCreatePopup.form.buttons", {widget:self})); - var $nbutton = $buttons.find(".oe_selectcreatepopup-form-save-new"); - $nbutton.click(function() { - self._created = $.Deferred().then(function() { - self._created = undefined; - self.view_form.on_button_new(); - }); - self.view_form.do_save(); - }); - var $nbutton = $buttons.find(".oe_selectcreatepopup-form-save"); - $nbutton.click(function() { - self._created = $.Deferred().then(function() { - self._created = undefined; - self.check_exit(); - }); - self.view_form.do_save(); - }); - var $cbutton = $buttons.find(".oe_selectcreatepopup-form-close"); - $cbutton.click(function() { - self.check_exit(); - }); - }); - this.dataset.on_create.add(function(data) { - self.options.create_function(data).then(function(r) { - self.created_elements.push(r.result); - if (self._created) { - self._created.resolve(); - } - }); - }); - this.view_form.do_show(); - }, - check_exit: function() { - if (this.created_elements.length > 0) { - this.on_select_elements(this.created_elements); - } - this.stop(); - } -}); - -openerp.base.form.SelectCreateListView = openerp.base.ListView.extend({ - do_add_record: function () { - this.popup.new_object(); - }, - select_record: function(index) { - this.popup.on_select_elements([this.dataset.ids[index]]); - this.popup.stop(); - }, - do_select: function(ids, records) { - this._super(ids, records); - this.popup.on_click_element(ids); - } -}); - -openerp.base.form.FormOpenPopup = openerp.base.OldWidget.extend({ - identifier_prefix: "formopenpopup", - template: "FormOpenPopup", - /** - * options: - * - alternative_form_view - * - auto_write (default true) - * - read_function - * - parent_view - */ - show_element: function(model, row_id, context, options) { - this.model = model; - this.row_id = row_id; - this.context = context || {}; - this.options = _.defaults(options || {}, {"auto_write": true}); - jQuery(this.render()).dialog({title: '', - modal: true, - width: 960, - height: 600}); - this.start(); - }, - start: function() { - this._super(); - this.dataset = new openerp.base.form.FormOpenDataset(this, this.model, this.context); - this.dataset.fop = this; - this.dataset.ids = [this.row_id]; - this.dataset.index = 0; - this.dataset.parent_view = this.options.parent_view; - this.setup_form_view(); - }, - on_write: function(id, data) { - this.stop(); - if (!this.options.auto_write) - return; - var self = this; - var wdataset = new openerp.base.DataSetSearch(this, this.model, this.context, this.domain); - wdataset.parent_view = this.options.parent_view; - wdataset.write(id, data, {}, function(r) { - self.on_write_completed(); - }); - }, - on_write_completed: function() {}, - setup_form_view: function() { - var self = this; - this.view_form = new openerp.base.FormView(this, this.element_id + "_view_form", this.dataset, false); - if (this.options.alternative_form_view) { - this.view_form.set_embedded_view(this.options.alternative_form_view); - } - this.view_form.start(); - this.view_form.on_loaded.add_last(function() { - var $buttons = self.view_form.$element.find(".oe_form_buttons"); - $buttons.html(QWeb.render("FormOpenPopup.form.buttons")); - var $nbutton = $buttons.find(".oe_formopenpopup-form-save"); - $nbutton.click(function() { - self.view_form.do_save(); - }); - var $cbutton = $buttons.find(".oe_formopenpopup-form-close"); - $cbutton.click(function() { - self.stop(); - }); - self.view_form.do_show(); - }); - this.dataset.on_write.add(this.on_write); - } -}); - -openerp.base.form.FormOpenDataset = openerp.base.ReadOnlyDataSetSearch.extend({ - read_ids: function() { - if (this.fop.options.read_function) { - return this.fop.options.read_function.apply(null, arguments); - } else { - return this._super.apply(this, arguments); - } - } -}); - -openerp.base.form.FieldReference = openerp.base.form.Field.extend({ - init: function(view, node) { - this._super(view, node); - this.template = "FieldReference"; - this.fields_view = { - fields: { - selection: { - selection: view.fields_view.fields[this.name].selection - }, - m2o: { - relation: null - } - } - } - this.get_fields_values = view.get_fields_values; - this.do_onchange = this.on_form_changed = this.on_nop; - this.widgets = {}; - this.fields = {}; - this.selection = new openerp.base.form.FieldSelection(this, { attrs: { - name: 'selection', - widget: 'selection' - }}); - this.selection.on_value_changed.add_last(this.on_selection_changed); - this.m2o = new openerp.base.form.FieldMany2One(this, { attrs: { - name: 'm2o', - widget: 'many2one' - }}); - }, - on_nop: function() { - }, - on_selection_changed: function() { - this.m2o.field.relation = this.selection.get_value(); - this.m2o.set_value(null); - }, - start: function() { - this._super(); - this.selection.start(); - this.m2o.start(); - }, - is_valid: function() { - return this.required === false || typeof(this.get_value()) === 'string'; - }, - is_dirty: function() { - return this.selection.is_dirty() || this.m2o.is_dirty(); - }, - set_value: function(value) { - this._super(value); - if (typeof(value) === 'string') { - var vals = value.split(','); - this.selection.set_value(vals[0]); - this.m2o.set_value(parseInt(vals[1], 10)); - } - }, - get_value: function() { - var model = this.selection.get_value(), - id = this.m2o.get_value(); - if (typeof(model) === 'string' && typeof(id) === 'number') { - return model + ',' + id; - } else { - return false; - } - } -}); - -openerp.base.form.FieldBinary = openerp.base.form.Field.extend({ - init: function(view, node) { - this._super(view, node); - this.iframe = this.element_id + '_iframe'; - this.binary_value = false; - }, - start: function() { - this._super.apply(this, arguments); - this.$element.find('input.oe-binary-file').change(this.on_file_change); - this.$element.find('button.oe-binary-file-save').click(this.on_save_as); - this.$element.find('.oe-binary-file-clear').click(this.on_clear); - }, - update_dom: function() { - this._super.apply(this, arguments); - this.$element.find('.oe-binary').toggle(!this.readonly); - }, - human_filesize : function(size) { - var units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; - var i = 0; - while (size >= 1024) { - size /= 1024; - ++i; - } - return size.toFixed(2) + ' ' + units[i]; - }, - on_file_change: function(e) { - // TODO: on modern browsers, we could directly read the file locally on client ready to be used on image cropper - // http://www.html5rocks.com/tutorials/file/dndfiles/ - // http://deepliquid.com/projects/Jcrop/demos.php?demo=handler - window[this.iframe] = this.on_file_uploaded; - if ($(e.target).val() != '') { - this.$element.find('form.oe-binary-form input[name=session_id]').val(this.session.session_id); - this.$element.find('form.oe-binary-form').submit(); - this.toggle_progress(); - } - }, - toggle_progress: function() { - this.$element.find('.oe-binary-progress, .oe-binary').toggle(); - }, - on_file_uploaded: function(size, name, content_type, file_base64) { - delete(window[this.iframe]); - if (size === false) { - this.notification.warn("File Upload", "There was a problem while uploading your file"); - // TODO: use openerp web crashmanager - this.log("Error while uploading file : ", name); - } else { - this.on_file_uploaded_and_valid.apply(this, arguments); - this.on_ui_change(); - } - this.toggle_progress(); - }, - on_file_uploaded_and_valid: function(size, name, content_type, file_base64) { - }, - on_save_as: function() { - if (!this.view.datarecord.id) { - this.notification.warn("Can't save file", "The record has not yet been saved"); - } else { - var url = '/base/binary/saveas?session_id=' + this.session.session_id + '&model=' + - this.view.dataset.model +'&id=' + (this.view.datarecord.id || '') + '&field=' + this.name + - '&fieldname=' + (this.node.attrs.filename || '') + '&t=' + (new Date().getTime()) - window.open(url); - } - }, - on_clear: function() { - if (this.value !== false) { - this.value = false; - this.binary_value = false; - this.on_ui_change(); - } - return false; - } -}); - -openerp.base.form.FieldBinaryFile = openerp.base.form.FieldBinary.extend({ - init: function(view, node) { - this._super(view, node); - this.template = "FieldBinaryFile"; - }, - set_value: function(value) { - this._super.apply(this, arguments); - var show_value = (value != null && value !== false) ? value : ''; - this.$element.find('input').eq(0).val(show_value); - }, - on_file_uploaded_and_valid: function(size, name, content_type, file_base64) { - this.value = file_base64; - this.binary_value = true; - var show_value = this.human_filesize(size); - this.$element.find('input').eq(0).val(show_value); - this.set_filename(name); - }, - set_filename: function(value) { - var filename = this.node.attrs.filename; - if (this.view.fields[filename]) { - this.view.fields[filename].set_value(value); - this.view.fields[filename].on_ui_change(); - } - }, - on_clear: function() { - this._super.apply(this, arguments); - this.$element.find('input').eq(0).val(''); - this.set_filename(''); - } -}); - -openerp.base.form.FieldBinaryImage = openerp.base.form.FieldBinary.extend({ - init: function(view, node) { - this._super(view, node); - this.template = "FieldBinaryImage"; - }, - start: function() { - this._super.apply(this, arguments); - this.$image = this.$element.find('img.oe-binary-image'); - }, - set_value: function(value) { - this._super.apply(this, arguments); - this.set_image_maxwidth(); - var url = '/base/binary/image?session_id=' + this.session.session_id + '&model=' + - this.view.dataset.model +'&id=' + (this.view.datarecord.id || '') + '&field=' + this.name + '&t=' + (new Date().getTime()) - this.$image.attr('src', url); - }, - set_image_maxwidth: function() { - this.$image.css('max-width', this.$element.width()); - }, - on_file_change: function() { - this.set_image_maxwidth(); - this._super.apply(this, arguments); - }, - on_file_uploaded_and_valid: function(size, name, content_type, file_base64) { - this.value = file_base64; - this.binary_value = true; - this.$image.attr('src', 'data:' + (content_type || 'image/png') + ';base64,' + file_base64); - }, - on_clear: function() { - this._super.apply(this, arguments); - this.$image.attr('src', '/base/static/src/img/placeholder.png'); - } -}); - -/** - * Registry of form widgets, called by :js:`openerp.base.FormView` - */ -openerp.base.form.widgets = new openerp.base.Registry({ - 'frame' : 'openerp.base.form.WidgetFrame', - 'group' : 'openerp.base.form.WidgetFrame', - 'notebook' : 'openerp.base.form.WidgetNotebook', - 'separator' : 'openerp.base.form.WidgetSeparator', - 'label' : 'openerp.base.form.WidgetLabel', - 'button' : 'openerp.base.form.WidgetButton', - 'char' : 'openerp.base.form.FieldChar', - 'email' : 'openerp.base.form.FieldEmail', - 'url' : 'openerp.base.form.FieldUrl', - 'text' : 'openerp.base.form.FieldText', - 'text_wiki' : 'openerp.base.form.FieldText', - 'date' : 'openerp.base.form.FieldDate', - 'datetime' : 'openerp.base.form.FieldDatetime', - 'selection' : 'openerp.base.form.FieldSelection', - 'many2one' : 'openerp.base.form.FieldMany2One', - 'many2many' : 'openerp.base.form.FieldMany2Many', - 'one2many' : 'openerp.base.form.FieldOne2Many', - 'one2many_list' : 'openerp.base.form.FieldOne2Many', - 'reference' : 'openerp.base.form.FieldReference', - 'boolean' : 'openerp.base.form.FieldBoolean', - 'float' : 'openerp.base.form.FieldFloat', - 'integer': 'openerp.base.form.FieldFloat', - 'float_time': 'openerp.base.form.FieldFloat', - 'progressbar': 'openerp.base.form.FieldProgressBar', - 'image': 'openerp.base.form.FieldBinaryImage', - 'binary': 'openerp.base.form.FieldBinaryFile' -}); - -}; - -// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/base/static/src/js/formats.js b/addons/base/static/src/js/formats.js deleted file mode 100644 index 625868eee75..00000000000 --- a/addons/base/static/src/js/formats.js +++ /dev/null @@ -1,197 +0,0 @@ - -openerp.base.formats = function(openerp) { - -/** - * Formats a single atomic value based on a field descriptor - * - * @param {Object} value read from OpenERP - * @param {Object} descriptor union of orm field and view field - * @param {Object} [descriptor.widget] widget to use to display the value - * @param {Object} descriptor.type fallback if no widget is provided, or if the provided widget is unknown - * @param {Object} [descriptor.digits] used for the formatting of floats - * @param {String} [value_if_empty=''] returned if the ``value`` argument is considered empty - */ -openerp.base.format_value = function (value, descriptor, value_if_empty) { - // If NaN value, display as with a `false` (empty cell) - if (typeof value === 'number' && isNaN(value)) { - value = false; - } - switch (value) { - case false: - case Infinity: - case -Infinity: - return value_if_empty === undefined ? '' : value_if_empty; - } - switch (descriptor.widget || descriptor.type) { - case 'integer': - return _.sprintf('%d', value); - case 'float': - var precision = descriptor.digits ? descriptor.digits[1] : 2; - var int_part = Math.floor(value); - var dec_part = Math.abs(Math.floor((value % 1) * Math.pow(10, precision))); - return _.sprintf('%d%s%d', - int_part, - openerp.base._t.database.parameters.decimal_point, dec_part); - case 'float_time': - return _.sprintf("%02d:%02d", - Math.floor(value), - Math.round((value % 1) * 60)); - case 'progressbar': - return _.sprintf( - '<progress value="%.2f" max="100.0">%.2f%%</progress>', - value, value); - case 'many2one': - // name_get value format - return value[1]; - case 'datetime': - if (typeof(value) == "string") - value = openerp.base.auto_str_to_date(value); - try { - return value.toString(_.sprintf("%s %s", Date.CultureInfo.formatPatterns.shortDate, - Date.CultureInfo.formatPatterns.longTime)); - } catch (e) { - return value.format("%m/%d/%Y %H:%M:%S"); - } - return value; - case 'date': - if (typeof(value) == "string") - value = openerp.base.auto_str_to_date(value); - try { - return value.toString(Date.CultureInfo.formatPatterns.shortDate); - } catch (e) { - return value.format("%m/%d/%Y"); - } - case 'time': - if (typeof(value) == "string") - value = openerp.base.auto_str_to_date(value); - try { - return value.toString(Date.CultureInfo.formatPatterns.longTime); - } catch (e) { - return value.format("%H:%M:%S"); - } - default: - return value; - } -}; - -openerp.base.parse_value = function (value, descriptor, value_if_empty) { - switch (value) { - case false: - case "": - return value_if_empty === undefined ? false : value_if_empty; - } - switch (descriptor.widget || descriptor.type) { - case 'integer': - var tmp = Number(value); - if (isNaN(tmp)) - throw value + " is not a correct integer"; - return tmp; - case 'float': - var tmp = Number(value); - if (!isNaN(tmp)) - return tmp; - tmp = value.replace(openerp.base._t.database.parameters.decimal_point, "."); - var tmp2 = tmp; - do { - tmp = tmp2; - tmp2 = tmp.replace(openerp.base._t.database.parameters.thousands_sep, ""); - } while(tmp !== tmp2); - tmp = Number(tmp); - if (isNaN(tmp)) - throw value + " is not a correct float"; - return tmp; - case 'float_time': - var tmp = value.split(":"); - if (tmp.length != 2) - throw value + " is not a correct float_time"; - var tmp1 = openerp.base.parse_value(tmp[0], {type: "integer"}); - var tmp2 = openerp.base.parse_value(tmp[1], {type: "integer"}); - return tmp1 + (tmp2 / 60); - case 'progressbar': - return openerp.base.parse_value(value, {type: "float"}); - case 'datetime': - var tmp = Date.parseExact(value, _.sprintf("%s %s", Date.CultureInfo.formatPatterns.shortDate, - Date.CultureInfo.formatPatterns.longTime)); - if (tmp !== null) - return tmp; - tmp = Date.parse(value); - if (tmp !== null) - return tmp; - throw value + " is not a valid datetime"; - case 'date': - var tmp = Date.parseExact(value, Date.CultureInfo.formatPatterns.shortDate); - if (tmp !== null) - return tmp; - tmp = Date.parse(value); - if (tmp !== null) - return tmp; - throw value + " is not a valid date"; - case 'time': - var tmp = Date.parseExact(value, Date.CultureInfo.formatPatterns.longTime); - if (tmp !== null) - return tmp; - tmp = Date.parse(value); - if (tmp !== null) - return tmp; - throw value + " is not a valid time"; - } - return value; -}; - -openerp.base.auto_str_to_date = function(value, type) { - try { - return openerp.base.str_to_datetime(value); - } catch(e) {} - try { - return openerp.base.str_to_date(value); - } catch(e) {} - try { - return openerp.base.str_to_time(value); - } catch(e) {} - throw "'" + value + "' is not a valid date, datetime nor time" -}; - -openerp.base.auto_date_to_str = function(value, type) { - switch(type) { - case 'datetime': - return openerp.base.datetime_to_str(value); - case 'date': - return openerp.base.date_to_str(value); - case 'time': - return openerp.base.time_to_str(value); - default: - throw type + " is not convertible to date, datetime nor time" - } -}; - -/** - * Formats a provided cell based on its field type - * - * @param {Object} row_data record whose values should be displayed in the cell - * @param {Object} column column descriptor - * @param {"button"|"field"} column.tag base control type - * @param {String} column.type widget type for a field control - * @param {String} [column.string] button label - * @param {String} [column.icon] button icon - * @param {String} [value_if_empty=''] what to display if the field's value is ``false`` - */ -openerp.base.format_cell = function (row_data, column, value_if_empty) { - var attrs = column.modifiers_for(row_data); - if (attrs.invisible) { return ''; } - if (column.tag === 'button') { - return [ - '<button type="button" title="', column.string || '', '">', - '<img src="/base/static/src/img/icons/', column.icon, '.png"', - ' alt="', column.string || '', '"/>', - '</button>' - ].join('') - } - - if (!row_data[column.id]) { - return value_if_empty === undefined ? '' : value_if_empty; - } - return openerp.base.format_value( - row_data[column.id].value, column, value_if_empty); -} - -}; diff --git a/addons/base/static/src/js/list-editable.js b/addons/base/static/src/js/list-editable.js deleted file mode 100644 index 1cd43fd6ea8..00000000000 --- a/addons/base/static/src/js/list-editable.js +++ /dev/null @@ -1,324 +0,0 @@ -/** - * @namespace handles editability case for lists, because it depends on form and forms already depends on lists it had to be split out - */ -openerp.base.list_editable = function (openerp) { - var KEY_RETURN = 13, - KEY_ESCAPE = 27; - - // editability status of list rows - openerp.base.ListView.prototype.defaults.editable = null; - - // TODO: not sure second @lends on existing item is correct, to check - openerp.base.ListView.include(/** @lends openerp.base.ListView# */{ - init: function () { - var self = this; - this._super.apply(this, arguments); - $(this.groups).bind({ - 'edit': function (e, id, dataset) { - self.do_edit(dataset.index, id, dataset); - }, - 'saved': function () { - if (self.groups.get_selection().length) { - return; - } - self.compute_aggregates(); - } - }) - }, - /** - * Handles the activation of a record in editable mode (making a record - * editable), called *after* the record has become editable. - * - * The default behavior is to setup the listview's dataset to match - * whatever dataset was provided by the editing List - * - * @param {Number} index index of the record in the dataset - * @param {Object} id identifier of the record being edited - * @param {openerp.base.DataSet} dataset dataset in which the record is available - */ - do_edit: function (index, id, dataset) { - _.extend(this.dataset, dataset); - }, - /** - * Sets editability status for the list, based on defaults, view - * architecture and the provided flag, if any. - * - * @param {Boolean} [force] forces the list to editability. Sets new row edition status to "bottom". - */ - set_editable: function (force) { - // If ``force``, set editability to bottom - // otherwise rely on view default - // view' @editable is handled separately as we have not yet - // fetched and processed the view at this point. - this.options.editable = ( - (force && "bottom") - || this.defaults.editable); - }, - /** - * Replace do_actual_search to handle editability process - */ - do_actual_search: function (results) { - this.set_editable(results.context['set_editable']); - this._super(results); - }, - /** - * Replace do_add_record to handle editability (and adding new record - * as an editable row at the top or bottom of the list) - */ - do_add_record: function () { - if (this.options.editable) { - this.groups.new_record(); - } else { - this._super(); - } - }, - on_loaded: function (data, grouped) { - // tree/@editable takes priority on everything else if present. - this.options.editable = data.fields_view.arch.attrs.editable || this.options.editable; - return this._super(data, grouped); - } - }); - - openerp.base.ListView.Groups.include(/** @lends openerp.base.ListView.Groups# */{ - passtrough_events: openerp.base.ListView.Groups.prototype.passtrough_events + " edit saved", - new_record: function () { - // TODO: handle multiple children - this.children[null].new_record(); - } - }); - - openerp.base.ListView.List.include(/** @lends openerp.base.ListView.List */{ - row_clicked: function (event) { - if (!this.options.editable) { - return this._super(event); - } - this.edit_record($(event.currentTarget).data('id')); - }, - /** - * Checks if a record is being edited, and if so cancels it - */ - cancel_pending_edition: function () { - var self = this, cancelled = $.Deferred(); - if (!this.edition) { - cancelled.resolve(); - return cancelled.promise(); - } - - if (this.edition_id != null) { - this.reload_record(self.records.get(this.edition_id)).then(function () { - cancelled.resolve(); - }); - } else { - cancelled.resolve(); - } - cancelled.then(function () { - self.edition_form.stop(); - self.edition_form.$element.remove(); - delete self.edition_form; - delete self.edition_id; - delete self.edition; - }); - return cancelled.promise(); - }, - /** - * Adapts this list's view description to be suitable to the inner form - * view of a row being edited. - * - * @returns {Object} fields_view_get's view section suitable for putting into form view of editable rows. - */ - get_form_fields_view: function () { - // deep copy of view - var view = $.extend(true, {}, this.group.view.fields_view); - _(view.arch.children).each(function (widget) { - widget.attrs.nolabel = true; - if (widget.tag === 'button') { - delete widget.attrs.string; - } - }); - view.arch.attrs.col = 2 * view.arch.children.length; - return view; - }, - render_row_as_form: function (row) { - var self = this; - this.cancel_pending_edition().then(function () { - var record_id = $(row).data('id'); - var $new_row = $('<tr>', { - id: _.uniqueId('oe-editable-row-'), - 'data-id': record_id, - 'class': $(row).attr('class') + ' oe_forms', - click: function (e) {e.stopPropagation();} - }) - .delegate('button.oe-edit-row-save', 'click', function () { - self.save_row(); - }) - .delegate('button.oe-edit-row-cancel', 'click', function () { - self.cancel_edition(); - }) - .delegate('button', 'keyup', function (e) { - e.stopImmediatePropagation(); - }) - .keyup(function (e) { - switch (e.which) { - case KEY_RETURN: - self.save_row(true); - break; - case KEY_ESCAPE: - self.cancel_edition(); - break; - default: - return; - } - }); - if (row) { - $new_row.replaceAll(row); - } else if (self.options.editable === 'top') { - self.$current.prepend($new_row); - } else if (self.options.editable) { - self.$current.append($new_row); - } - self.edition = true; - self.edition_id = record_id; - self.edition_form = _.extend(new openerp.base.FormView( - self, $new_row.attr('id'), self.dataset, false), { - template: 'ListView.row.form', - registry: openerp.base.list.form.widgets - }); - $.when(self.edition_form.on_loaded({fields_view: self.get_form_fields_view()})).then(function () { - // put in $.when just in case FormView.on_loaded becomes asynchronous - $new_row.find('td') - .addClass('oe-field-cell') - .removeAttr('width') - .end() - .find('td:first').removeClass('oe-field-cell').end() - .find('td:last').removeClass('oe-field-cell').end(); - // pad in case of groupby - _(self.columns).each(function (column) { - if (column.meta) { - $new_row.prepend('<td>'); - } - }); - - self.edition_form.do_show(); - }); - }); - }, - handle_onwrite: function (source_record_id) { - var self = this; - var on_write_callback = self.view.fields_view.arch.attrs.on_write; - if (!on_write_callback) { return; } - this.dataset.call(on_write_callback, [source_record_id], function (ids) { - _(ids).each(function (id) { - var record = self.records.get(id); - if (!record) { - // insert after the source record - var index = self.records.indexOf( - self.records.get(source_record_id)) + 1; - record = new openerp.base.list.Record({id: id}); - self.records.add(record, {at: index}); - self.dataset.ids.splice(index, 0, id); - } - self.reload_record(record); - }); - }); - }, - /** - * Saves the current row, and triggers the edition of its following - * sibling if asked. - * - * @param {Boolean} [edit_next=false] should the next row become editable - */ - save_row: function (edit_next) { - var self = this; - this.edition_form.do_save(function (result) { - if (result.created && !self.edition_id) { - self.records.add({id: result.result}, - {at: self.options.editable === 'top' ? 0 : null}); - self.edition_id = result.result; - } - var edited_record = self.records.get(self.edition_id), - next_record = self.records.at( - self.records.indexOf(edited_record) + 1); - - self.handle_onwrite(self.edition_id); - self.cancel_pending_edition().then(function () { - $(self).trigger('saved', [self.dataset]); - if (!edit_next) { - return; - } - if (result.created) { - self.new_record(); - return; - } - var next_record_id; - if (next_record) { - next_record_id = next_record.get('id'); - self.dataset.index = _(self.dataset.ids) - .indexOf(next_record_id); - } else { - self.dataset.index = 0; - next_record_id = self.records.at(0).get('id'); - } - self.edit_record(next_record_id); - }); - }, this.options.editable === 'top'); - }, - /** - * Cancels the edition of the row for the current dataset index - */ - cancel_edition: function () { - this.cancel_pending_edition(); - }, - /** - * Edits record currently selected via dataset - */ - edit_record: function (record_id) { - this.render_row_as_form( - this.$current.find('[data-id=' + record_id + ']')); - $(this).trigger( - 'edit', - [record_id, this.dataset]); - }, - new_record: function () { - this.dataset.index = null; - this.render_row_as_form(); - } - }); - if (!openerp.base.list) { - openerp.base.list = {}; - } - if (!openerp.base.list.form) { - openerp.base.list.form = {}; - } - openerp.base.list.form.WidgetFrame = openerp.base.form.WidgetFrame.extend({ - template: 'ListView.row.frame' - }); - var form_widgets = openerp.base.form.widgets; - openerp.base.list.form.widgets = form_widgets.clone({ - 'frame': 'openerp.base.list.form.WidgetFrame' - }); - // All form widgets inherit a problematic behavior from - // openerp.base.form.WidgetFrame: the cell itself is removed when invisible - // whether it's @invisible or @attrs[invisible]. In list view, only the - // former should completely remove the cell. We need to override update_dom - // on all widgets since we can't just hit on widget itself (I think) - var list_form_widgets = openerp.base.list.form.widgets; - _(list_form_widgets.map).each(function (widget_path, key) { - if (key === 'frame') { return; } - var new_path = 'openerp.base.list.form.' + key; - - openerp.base.list.form[key] = (form_widgets.get_object(key)).extend({ - update_dom: function () { - this.$element.children().css('visibility', ''); - if (this.modifiers.tree_invisible) { - var old_invisible = this.invisible; - this.invisible = !!this.modifiers.tree_invisible; - this._super(); - this.invisible = old_invisible; - } else if (this.invisible) { - this.$element.children().css('visibility', 'hidden'); - } - } - }); - list_form_widgets.add(key, new_path); - }); -}; diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js deleted file mode 100644 index 786c8cb2068..00000000000 --- a/addons/base/static/src/js/list.js +++ /dev/null @@ -1,1467 +0,0 @@ -openerp.base.list = function (openerp) { -openerp.base.views.add('list', 'openerp.base.ListView'); -openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListView# */ { - defaults: { - // records can be selected one by one - 'selectable': true, - // list rows can be deleted - 'deletable': true, - // whether the column headers should be displayed - 'header': true, - // display addition button, with that label - 'addable': "New", - // whether the list view can be sorted, note that once a view has been - // sorted it can not be reordered anymore - 'sortable': true, - // whether the view rows can be reordered (via vertical drag & drop) - 'reorderable': true - }, - /** - * Core class for list-type displays. - * - * As a view, needs a number of view-related parameters to be correctly - * instantiated, provides options and overridable methods for behavioral - * customization. - * - * See constructor parameters and method documentations for information on - * the default behaviors and possible options for the list view. - * - * @constructs - * @param parent parent object - * @param element_id the id of the DOM elements this view should link itself to - * @param {openerp.base.DataSet} dataset the dataset the view should work with - * @param {String} view_id the listview's identifier, if any - * @param {Object} options A set of options used to configure the view - * @param {Boolean} [options.selectable=true] determines whether view rows are selectable (e.g. via a checkbox) - * @param {Boolean} [options.header=true] should the list's header be displayed - * @param {Boolean} [options.deletable=true] are the list rows deletable - * @param {void|String} [options.addable="New"] should the new-record button be displayed, and what should its label be. Use ``null`` to hide the button. - * @param {Boolean} [options.sortable=true] is it possible to sort the table by clicking on column headers - * @param {Boolean} [options.reorderable=true] is it possible to reorder list rows - * - * @borrows openerp.base.ActionExecutor#execute_action as #execute_action - */ - init: function(parent, element_id, dataset, view_id, options) { - var self = this; - this._super(parent, element_id); - this.set_default_options(_.extend({}, this.defaults, options || {})); - this.dataset = dataset; - this.model = dataset.model; - this.view_id = view_id; - - this.columns = []; - - this.records = new Collection(); - - this.set_groups(new openerp.base.ListView.Groups(this)); - - if (this.dataset instanceof openerp.base.DataSetStatic) { - this.groups.datagroup = new openerp.base.StaticDataGroup(this.dataset); - } - - this.page = 0; - this.records.bind('change', function (event, record, key) { - if (!_(self.aggregate_columns).chain() - .pluck('name').contains(key).value()) { - return; - } - self.compute_aggregates(); - }); - }, - /** - * Retrieves the view's number of records per page (|| section) - * - * options > defaults > parent.action.limit > indefinite - * - * @returns {Number|null} - */ - limit: function () { - if (this._limit === undefined) { - this._limit = (this.options.limit - || this.defaults.limit - || (this.widget_parent.action || {}).limit - || null); - } - return this._limit; - }, - /** - * Set a custom Group construct as the root of the List View. - * - * @param {openerp.base.ListView.Groups} groups - */ - set_groups: function (groups) { - var self = this; - if (this.groups) { - $(this.groups).unbind("selected deleted action row_link"); - delete this.groups; - } - - this.groups = groups; - $(this.groups).bind({ - 'selected': function (e, ids, records) { - self.do_select(ids, records); - }, - 'deleted': function (e, ids) { - self.do_delete(ids); - }, - 'action': function (e, action_name, id, callback) { - self.do_button_action(action_name, id, callback); - }, - 'row_link': function (e, id, dataset) { - self.do_activate_record(dataset.index, id, dataset); - } - }); - }, - /** - * View startup method, the default behavior is to set the ``oe-listview`` - * class on its root element and to perform an RPC load call. - * - * @returns {$.Deferred} loading promise - */ - start: function() { - this.$element.addClass('oe-listview'); - return this.reload_view(null, null, true); - }, - /** - * Called after loading the list view's description, sets up such things - * as the view table's columns, renders the table itself and hooks up the - * various table-level and row-level DOM events (action buttons, deletion - * buttons, selection of records, [New] button, selection of a given - * record, ...) - * - * Sets up the following: - * - * * Processes arch and fields to generate a complete field descriptor for each field - * * Create the table itself and allocate visible columns - * * Hook in the top-level (header) [New|Add] and [Delete] button - * * Sets up showing/hiding the top-level [Delete] button based on records being selected or not - * * Sets up event handlers for action buttons and per-row deletion button - * * Hooks global callback for clicking on a row - * * Sets up its sidebar, if any - * - * @param {Object} data wrapped fields_view_get result - * @param {Object} data.fields_view fields_view_get result (processed) - * @param {Object} data.fields_view.fields mapping of fields for the current model - * @param {Object} data.fields_view.arch current list view descriptor - * @param {Boolean} grouped Is the list view grouped - */ - on_loaded: function(data, grouped) { - var self = this; - this.fields_view = data.fields_view; - //this.log(this.fields_view); - this.name = "" + this.fields_view.arch.attrs.string; - - this.setup_columns(this.fields_view.fields, grouped); - - this.$element.html(QWeb.render("ListView", this)); - - // Head hook - this.$element.find('.oe-list-add') - .click(this.do_add_record) - .attr('disabled', grouped && this.options.editable); - this.$element.find('.oe-list-delete') - .attr('disabled', true) - .click(this.do_delete_selected); - this.$element.find('thead').delegate('th.oe-sortable[data-id]', 'click', function (e) { - e.stopPropagation(); - - var $this = $(this); - self.dataset.sort($this.data('id')); - if ($this.find('span').length) { - $this.find('span').toggleClass( - 'ui-icon-triangle-1-s ui-icon-triangle-1-n'); - } else { - $this.append('<span class="ui-icon ui-icon-triangle-1-s">') - .siblings('.oe-sortable').find('span').remove(); - } - - self.reload_content(); - }); - - this.$element.find('.oe-list-pager') - .delegate('button', 'click', function () { - var $this = $(this); - switch ($this.data('pager-action')) { - case 'first': - self.page = 0; break; - case 'last': - self.page = Math.floor( - self.dataset.ids.length / self.limit()); - break; - case 'next': - self.page += 1; break; - case 'previous': - self.page -= 1; break; - } - self.reload_content(); - }).find('.oe-pager-state') - .click(function (e) { - e.stopPropagation(); - var $this = $(this); - - var $select = $('<select>') - .appendTo($this.empty()) - .click(function (e) {e.stopPropagation();}) - .append('<option value="80">80</option>' + - '<option value="100">100</option>' + - '<option value="200">200</option>' + - '<option value="500">500</option>' + - '<option value="NaN">Unlimited</option>') - .change(function () { - var val = parseInt($select.val(), 10); - self._limit = (isNaN(val) ? null : val); - self.page = 0; - self.reload_content(); - }) - .val(self._limit || 'NaN'); - }); - if (!this.sidebar && this.options.sidebar && this.options.sidebar_id) { - this.sidebar = new openerp.base.Sidebar(this, this.options.sidebar_id); - this.sidebar.start(); - this.sidebar.add_toolbar(data.fields_view.toolbar); - this.set_common_sidebar_sections(this.sidebar); - } - }, - /** - * Configures the ListView pager based on the provided dataset's information - * - * Horrifying side-effect: sets the dataset's data on this.dataset? - * - * @param {openerp.base.DataSet} dataset - */ - configure_pager: function (dataset) { - this.dataset.ids = dataset.ids; - - var limit = this.limit(), - total = dataset.ids.length, - first = (this.page * limit), - last; - if (!limit || (total - first) < limit) { - last = total; - } else { - last = first + limit; - } - this.$element.find('span.oe-pager-state').empty().text(_.sprintf( - "[%d to %d] of %d", first + 1, last, total)); - - this.$element - .find('button[data-pager-action=first], button[data-pager-action=previous]') - .attr('disabled', this.page === 0) - .end() - .find('button[data-pager-action=last], button[data-pager-action=next]') - .attr('disabled', last === total); - }, - /** - * Sets up the listview's columns: merges view and fields data, move - * grouped-by columns to the front of the columns list and make them all - * visible. - * - * @param {Object} fields fields_view_get's fields section - * @param {Boolean} [grouped] Should the grouping columns (group and count) be displayed - */ - setup_columns: function (fields, grouped) { - var domain_computer = openerp.base.form.compute_domain; - - var noop = function () { return {}; }; - var field_to_column = function (field) { - var name = field.attrs.name; - var column = _.extend({id: name, tag: field.tag}, - field.attrs, fields[name]); - // modifiers computer - if (column.modifiers) { - var modifiers = JSON.parse(column.modifiers); - column.modifiers_for = function (fields) { - if (!modifiers.invisible) { - return {}; - } - return { - 'invisible': domain_computer(modifiers.invisible, fields) - }; - }; - if (modifiers['tree_invisible']) { - column.invisible = '1'; - } - } else { - column.modifiers_for = noop; - } - return column; - }; - - this.columns.splice(0, this.columns.length); - this.columns.push.apply( - this.columns, - _(this.fields_view.arch.children).map(field_to_column)); - if (grouped) { - this.columns.unshift({ - id: '_group', tag: '', string: "Group", meta: true, - modifiers_for: function () { return {}; } - }, { - id: '_count', tag: '', string: '#', meta: true, - modifiers_for: function () { return {}; } - }); - } - - this.visible_columns = _.filter(this.columns, function (column) { - return column.invisible !== '1'; - }); - - this.aggregate_columns = _(this.visible_columns) - .map(function (column) { - if (column.type !== 'integer' && column.type !== 'float') { - return {}; - } - var aggregation_func = column['group_operator'] || 'sum'; - - return _.extend({}, column, { - 'function': aggregation_func, - label: column[aggregation_func] - }); - }); - }, - /** - * Used to handle a click on a table row, if no other handler caught the - * event. - * - * The default implementation asks the list view's view manager to switch - * to a different view (by calling - * :js:func:`~openerp.base.ViewManager.on_mode_switch`), using the - * provided record index (within the current list view's dataset). - * - * If the index is null, ``switch_to_record`` asks for the creation of a - * new record. - * - * @param {Number|void} index the record index (in the current dataset) to switch to - * @param {String} [view="form"] the view type to switch to - */ - select_record:function (index, view) { - view = view || 'form'; - this.dataset.index = index; - _.delay(_.bind(function () { - this.do_switch_view(view); - }, this)); - }, - do_show: function () { - this.$element.show(); - if (this.sidebar) { - this.sidebar.$element.show(); - } - if (this.hidden) { - this.reload_content(); - } - }, - do_hide: function () { - this.$element.hide(); - if (this.sidebar) { - this.sidebar.$element.hide(); - } - this.hidden = true; - }, - /** - * Reloads the list view based on the current settings (dataset & al) - * - * @param {Boolean} [grouped] Should the list be displayed grouped - * @param {Object} [context] context to send the server while loading the view - */ - reload_view: function (grouped, context, initial) { - var self = this; - var callback = function (field_view_get) { - self.on_loaded(field_view_get, grouped); - }; - if (this.embedded_view) { - return $.Deferred().then(callback).resolve({fields_view: this.embedded_view}); - } else { - return this.rpc('/base/listview/load', { - model: this.model, - view_id: this.view_id, - context: this.dataset.get_context(context), - toolbar: this.options.sidebar - }, callback); - } - }, - /** - * re-renders the content of the list view - */ - reload_content: function () { - var self = this; - this.records.reset(); - this.$element.find('.oe-listview-content').append( - this.groups.render(function () { - if (self.dataset.index == null) { - var has_one = false; - self.records.each(function () { has_one = true; }); - if (has_one) { - self.dataset.index = 0; - } - } - self.compute_aggregates(); - })); - }, - /** - * Event handler for a search, asks for the computation/folding of domains - * and contexts (and group-by), then reloads the view's content. - * - * @param {Array} domains a sequence of literal and non-literal domains - * @param {Array} contexts a sequence of literal and non-literal contexts - * @param {Array} groupbys a sequence of literal and non-literal group-by contexts - * @returns {$.Deferred} fold request evaluation promise - */ - do_search: function (domains, contexts, groupbys) { - return this.rpc('/base/session/eval_domain_and_context', { - domains: [this.dataset.get_domain()].concat(domains), - contexts: [this.dataset.get_context()].concat(contexts), - group_by_seq: groupbys - }, $.proxy(this, 'do_actual_search')); - }, - /** - * Handler for the result of eval_domain_and_context, actually perform the - * searching - * - * @param {Object} results results of evaluating domain and process for a search - */ - do_actual_search: function (results) { - this.groups.datagroup = new openerp.base.DataGroup( - this, this.model, - results.domain, - results.context, - results.group_by); - this.groups.datagroup.sort = this.dataset._sort; - - if (_.isEmpty(results.group_by) && !results.context['group_by_no_leaf']) { - results.group_by = null; - } - - this.reload_view(!!results.group_by, results.context).then( - $.proxy(this, 'reload_content')); - }, - /** - * Handles the signal to delete lines from the records list - * - * @param {Array} ids the ids of the records to delete - */ - do_delete: function (ids) { - if (!ids.length) { - return; - } - var self = this; - return $.when(this.dataset.unlink(ids)).then(function () { - _(ids).each(function (id) { - self.records.remove(self.records.get(id)); - }); - self.compute_aggregates(); - }); - }, - /** - * Handles the signal indicating that a new record has been selected - * - * @param {Array} ids selected record ids - * @param {Array} records selected record values - */ - do_select: function (ids, records) { - this.$element.find('.oe-list-delete') - .attr('disabled', !ids.length); - - if (!records.length) { - this.compute_aggregates(); - return; - } - this.compute_aggregates(_(records).map(function (record) { - return {count: 1, values: record}; - })); - }, - /** - * Handles action button signals on a record - * - * @param {String} name action name - * @param {Object} id id of the record the action should be called on - * @param {Function} callback should be called after the action is executed, if non-null - */ - do_button_action: function (name, id, callback) { - var action = _.detect(this.columns, function (field) { - return field.name === name; - }); - if (!action) { return; } - this.execute_action(action, this.dataset, id, callback); - }, - /** - * Handles the activation of a record (clicking on it) - * - * @param {Number} index index of the record in the dataset - * @param {Object} id identifier of the activated record - * @param {openerp.base.DataSet} dataset dataset in which the record is available (may not be the listview's dataset in case of nested groups) - */ - do_activate_record: function (index, id, dataset) { - var self = this; - // TODO is it needed ? - this.dataset.read_slice([],{ - context: dataset.get_context(), - domain: dataset.get_domain() - }, function () { - self.select_record(index); - }); - }, - /** - * Handles signal for the addition of a new record (can be a creation, - * can be the addition from a remote source, ...) - * - * The default implementation is to switch to a new record on the form view - */ - do_add_record: function () { - this.select_record(null); - }, - /** - * Handles deletion of all selected lines - */ - do_delete_selected: function () { - this.do_delete(this.groups.get_selection().ids); - }, - /** - * Computes the aggregates for the current list view, either on the - * records provided or on the records of the internal - * :js:class:`~openerp.base.ListView.Group`, by calling - * :js:func:`~openerp.base.ListView.group.get_records`. - * - * Then displays the aggregates in the table through - * :js:method:`~openerp.base.ListView.display_aggregates`. - * - * @param {Array} [records] - */ - compute_aggregates: function (records) { - var columns = _(this.aggregate_columns).filter(function (column) { - return column['function']; }); - if (_.isEmpty(columns)) { return; } - - if (_.isEmpty(records)) { - records = this.groups.get_records(); - } - - var count = 0, sums = {}; - _(columns).each(function (column) { - switch (column['function']) { - case 'max': - sums[column.id] = -Infinity; - break; - case 'min': - sums[column.id] = Infinity; - break; - default: - sums[column.id] = 0; - } - }); - _(records).each(function (record) { - count += record.count || 1; - _(columns).each(function (column) { - var field = column.id, - value = record.values[field]; - switch (column['function']) { - case 'sum': - sums[field] += value; - break; - case 'avg': - sums[field] += record.count * value; - break; - case 'min': - if (sums[field] > value) { - sums[field] = value; - } - break; - case 'max': - if (sums[field] < value) { - sums[field] = value; - } - break; - } - }); - }); - - var aggregates = {}; - _(columns).each(function (column) { - var field = column.id; - switch (column['function']) { - case 'avg': - aggregates[field] = {value: sums[field] / count}; - break; - default: - aggregates[field] = {value: sums[field]}; - } - }); - - this.display_aggregates(aggregates); - }, - display_aggregates: function (aggregation) { - var $footer_cells = this.$element.find('.oe-list-footer'); - _(this.aggregate_columns).each(function (column) { - if (!column['function']) { - return; - } - - $footer_cells.filter(_.sprintf('[data-field=%s]', column.id)) - .html(openerp.base.format_cell(aggregation, column)); - }); - }, - get_selected_ids: function() { - var ids = this.groups.get_selection().ids; - return ids; - } -}); -openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base.ListView.List# */{ - /** - * List display for the ListView, handles basic DOM events and transforms - * them in the relevant higher-level events, to which the list view (or - * other consumers) can subscribe. - * - * Events on this object are registered via jQuery. - * - * Available events: - * - * `selected` - * Triggered when a row is selected (using check boxes), provides an - * array of ids of all the selected records. - * `deleted` - * Triggered when deletion buttons are hit, provide an array of ids of - * all the records being marked for suppression. - * `action` - * Triggered when an action button is clicked, provides two parameters: - * - * * The name of the action to execute (as a string) - * * The id of the record to execute the action on - * `row_link` - * Triggered when a row of the table is clicked, provides the index (in - * the rows array) and id of the selected record to the handle function. - * - * @constructs - * @param {Object} opts display options, identical to those of :js:class:`openerp.base.ListView` - */ - init: function (group, opts) { - var self = this; - this.group = group; - this.view = group.view; - this.session = this.view.session; - - this.options = opts.options; - this.columns = opts.columns; - this.dataset = opts.dataset; - this.records = opts.records; - - this.record_callbacks = { - 'remove': function (event, record) { - var $row = self.$current.find( - '[data-id=' + record.get('id') + ']'); - var index = $row.data('index'); - $row.remove(); - self.refresh_zebra(index); - }, - 'reset': $.proxy(this, 'on_records_reset'), - 'change': function (event, record) { - var $row = self.$current.find('[data-id=' + record.get('id') + ']'); - $row.replaceWith(self.render_record(record)); - }, - 'add': function (ev, records, record, index) { - var $new_row = $('<tr>').attr({ - 'data-id': record.get('id') - }); - - if (index === 0) { - $new_row.prependTo(self.$current); - } else { - var previous_record = records.at(index-1), - $previous_sibling = self.$current.find( - '[data-id=' + previous_record.get('id') + ']'); - $new_row.insertAfter($previous_sibling); - } - - self.refresh_zebra(index, 1); - } - }; - _(this.record_callbacks).each(function (callback, event) { - this.records.bind(event, callback); - }, this); - - this.$_element = $('<tbody class="ui-widget-content">') - .appendTo(document.body) - .delegate('th.oe-record-selector', 'click', function (e) { - e.stopPropagation(); - var selection = self.get_selection(); - $(self).trigger( - 'selected', [selection.ids, selection.records]); - }) - .delegate('td.oe-record-delete button', 'click', function (e) { - e.stopPropagation(); - var $row = $(e.target).closest('tr'); - $(self).trigger('deleted', [[self.row_id($row)]]); - }) - .delegate('td.oe-field-cell button', 'click', function (e) { - e.stopPropagation(); - var $target = $(e.currentTarget), - field = $target.closest('td').data('field'), - $row = $target.closest('tr'), - record_id = self.row_id($row); - - $(self).trigger('action', [field, record_id, function () { - return self.reload_record(self.records.get(record_id)); - }]); - }) - .delegate('tr', 'click', function (e) { - e.stopPropagation(); - self.dataset.index = self.records.indexOf( - self.records.get( - self.row_id(e.currentTarget))); - self.row_clicked(e); - }); - }, - row_clicked: function () { - $(this).trigger( - 'row_link', - [this.records.at(this.dataset.index).get('id'), - this.dataset]); - }, - render: function () { - if (this.$current) { - this.$current.remove(); - } - this.$current = this.$_element.clone(true); - this.$current.empty().append( - QWeb.render('ListView.rows', _.extend({ - render_cell: openerp.base.format_cell}, this))); - }, - /** - * Gets the ids of all currently selected records, if any - * @returns {Object} object with the keys ``ids`` and ``records``, holding respectively the ids of all selected records and the records themselves. - */ - get_selection: function () { - if (!this.options.selectable) { - return []; - } - var records = this.records; - var result = {ids: [], records: []}; - this.$current.find('th.oe-record-selector input:checked') - .closest('tr').each(function () { - var record = records.get($(this).data('id')); - result.ids.push(record.get('id')); - result.records.push(record.attributes); - }); - return result; - }, - /** - * Returns the identifier of the object displayed in the provided table - * row - * - * @param {Object} row the selected table row - * @returns {Number|String} the identifier of the row's object - */ - row_id: function (row) { - return $(row).data('id'); - }, - /** - * Death signal, cleans up list display - */ - on_records_reset: function () { - _(this.record_callbacks).each(function (callback, event) { - this.records.unbind(event, callback); - }, this); - if (!this.$current) { return; } - this.$current.remove(); - this.$current = null; - this.$_element.remove(); - }, - get_records: function () { - return this.records.map(function (record) { - return {count: 1, values: record.attributes}; - }); - }, - /** - * Reloads the provided record by re-reading its content from the server. - * - * @param {Record} record - * @returns {$.Deferred} promise to the finalization of the reloading - */ - reload_record: function (record) { - return this.dataset.read_ids( - [record.get('id')], - _.pluck(_(this.columns).filter(function (r) { - return r.tag === 'field'; - }), 'name'), - function (records) { - _(records[0]).each(function (value, key) { - record.set(key, value, {silent: true}); - }); - record.trigger('change', record); - } - ); - }, - /** - * Renders a list record to HTML - * - * @param {Record} record index of the record to render in ``this.rows`` - * @returns {String} QWeb rendering of the selected record - */ - render_record: function (record) { - var index = this.records.indexOf(record); - return QWeb.render('ListView.row', { - columns: this.columns, - options: this.options, - record: record, - row_parity: (index % 2 === 0) ? 'even' : 'odd', - render_cell: openerp.base.format_cell - }); - }, - /** - * Fixes fixes the even/odd classes - * - * @param {Number} [from_index] index from which to resequence - * @param {Number} [offset = 0] selection offset for DOM, in case there are rows to ignore in the table - */ - refresh_zebra: function (from_index, offset) { - offset = offset || 0; - from_index = from_index || 0; - var dom_offset = offset + from_index; - var sel = dom_offset ? ':gt(' + (dom_offset - 1) + ')' : null; - this.$current.children(sel).each(function (i, e) { - var index = from_index + i; - // reset record-index accelerators on rows and even/odd - var even = index%2 === 0; - $(e).toggleClass('even', even) - .toggleClass('odd', !even); - }); - } -}); -openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.base.ListView.Groups# */{ - passtrough_events: 'action deleted row_link', - /** - * Grouped display for the ListView. Handles basic DOM events and interacts - * with the :js:class:`~openerp.base.DataGroup` bound to it. - * - * Provides events similar to those of - * :js:class:`~openerp.base.ListView.List` - * - * @constructs - * @param {openerp.base.ListView} view - * @param {Object} [options] - * @param {Collection} [options.records] - * @param {Object} [options.options] - * @param {Array} [options.columns] - */ - init: function (view, options) { - options = options || {}; - this.view = view; - this.records = options.records || view.records; - this.options = options.options || view.options; - this.columns = options.columns || view.columns; - this.datagroup = null; - - this.$row = null; - this.children = {}; - - this.page = 0; - - this.records.bind('reset', $.proxy(this, 'on_records_reset')); - }, - make_fragment: function () { - return document.createDocumentFragment(); - }, - /** - * Returns a DOM node after which a new tbody can be inserted, so that it - * follows the provided row. - * - * Necessary to insert the result of a new group or list view within an - * existing groups render, without losing track of the groups's own - * elements - * - * @param {HTMLTableRowElement} row the row after which the caller wants to insert a body - * @returns {HTMLTableSectionElement} element after which a tbody can be inserted - */ - point_insertion: function (row) { - var $row = $(row); - var red_letter_tboday = $row.closest('tbody')[0]; - - var $next_siblings = $row.nextAll(); - if ($next_siblings.length) { - var $root_kanal = $('<tbody>').insertAfter(red_letter_tboday); - - $root_kanal.append($next_siblings); - this.elements.splice( - _.indexOf(this.elements, red_letter_tboday), - 0, - $root_kanal[0]); - } - return red_letter_tboday; - }, - make_paginator: function () { - var self = this; - var $prev = $('<button type="button" data-pager-action="previous"><</button>') - .click(function (e) { - e.stopPropagation(); - self.page -= 1; - - self.$row.closest('tbody').next() - .replaceWith(self.render()); - }); - var $next = $('<button type="button" data-pager-action="next">></button>') - .click(function (e) { - e.stopPropagation(); - self.page += 1; - - self.$row.closest('tbody').next() - .replaceWith(self.render()); - }); - this.$row.children().last() - .append($prev) - .append('<span class="oe-pager-state"></span>') - .append($next); - }, - open: function (point_insertion) { - this.render().insertAfter(point_insertion); - this.make_paginator(); - }, - close: function () { - this.$row.children().last().empty(); - this.records.reset(); - }, - /** - * Prefixes ``$node`` with floated spaces in order to indent it relative - * to its own left margin/baseline - * - * @param {jQuery} $node jQuery object to indent - * @param {Number} level current nesting level, >= 1 - * @returns {jQuery} the indentation node created - */ - indent: function ($node, level) { - return $('<span>') - .css({'float': 'left', 'white-space': 'pre'}) - .text(new Array(level).join(' ')) - .prependTo($node); - }, - render_groups: function (datagroups) { - var self = this; - var placeholder = this.make_fragment(); - _(datagroups).each(function (group) { - if (self.children[group.value]) { - self.records.proxy(group.value).reset(); - delete self.children[group.value]; - } - var child = self.children[group.value] = new openerp.base.ListView.Groups(self.view, { - records: self.records.proxy(group.value), - options: self.options, - columns: self.columns - }); - self.bind_child_events(child); - child.datagroup = group; - - var $row = child.$row = $('<tr>'); - if (group.openable) { - $row.click(function (e) { - if (!$row.data('open')) { - $row.data('open', true) - .find('span.ui-icon') - .removeClass('ui-icon-triangle-1-e') - .addClass('ui-icon-triangle-1-s'); - child.open(self.point_insertion(e.currentTarget)); - } else { - $row.removeData('open') - .find('span.ui-icon') - .removeClass('ui-icon-triangle-1-s') - .addClass('ui-icon-triangle-1-e'); - child.close(); - } - }); - } - placeholder.appendChild($row[0]); - - var $group_column = $('<th class="oe-group-name">').appendTo($row); - // Don't fill this if group_by_no_leaf but no group_by - if (group.grouped_on) { - var row_data = {}; - row_data[group.grouped_on] = group; - var group_column = _(self.columns).detect(function (column) { - return column.id === group.grouped_on; }); - $group_column.html(openerp.base.format_cell( - row_data, group_column, "Undefined" - )); - if (group.openable) { - // Make openable if not terminal group & group_by_no_leaf - $group_column - .prepend('<span class="ui-icon ui-icon-triangle-1-e" style="float: left;">'); - } - } - self.indent($group_column, group.level); - // count column - $('<td>').text(group.length).appendTo($row); - - if (self.options.selectable) { - $row.append('<td>'); - } - _(self.columns).chain() - .filter(function (column) {return !column.invisible;}) - .each(function (column) { - if (column.meta) { - // do not do anything - } else if (column.id in group.aggregates) { - var value = group.aggregates[column.id]; - var format; - if (column.type === 'integer') { - format = "%.0f"; - } else if (column.type === 'float') { - format = "%.2f"; - } - $('<td>') - .text(_.sprintf(format, value)) - .appendTo($row); - } else { - $row.append('<td>'); - } - }); - if (self.options.deletable) { - $row.append('<td class="oe-group-pagination">'); - } - }); - return placeholder; - }, - bind_child_events: function (child) { - var $this = $(this), - self = this; - $(child).bind('selected', function (e) { - // can have selections spanning multiple links - var selection = self.get_selection(); - $this.trigger(e, [selection.ids, selection.records]); - }).bind(this.passtrough_events, function (e) { - // additional positional parameters are provided to trigger as an - // Array, following the event type or event object, but are - // provided to the .bind event handler as *args. - // Convert our *args back into an Array in order to trigger them - // on the group itself, so it can ultimately be forwarded wherever - // it's supposed to go. - var args = Array.prototype.slice.call(arguments, 1); - $this.trigger.call($this, e, args); - }); - }, - render_dataset: function (dataset) { - var self = this, - list = new openerp.base.ListView.List(this, { - options: this.options, - columns: this.columns, - dataset: dataset, - records: this.records - }); - this.bind_child_events(list); - - var view = this.view, - limit = view.limit(), - d = new $.Deferred(), - page = this.datagroup.openable ? this.page : view.page; - - var fields = _.pluck(_.select(this.columns, function(x) {return x.tag == "field"}), 'name'); - var options = { offset: page * limit, limit: limit }; - dataset.read_slice(fields, options , function (records) { - if (!self.datagroup.openable) { - view.configure_pager(dataset); - } else { - var pages = Math.ceil(dataset.ids.length / limit); - self.$row - .find('.oe-pager-state') - .text(_.sprintf('%d/%d', page + 1, pages)) - .end() - .find('button[data-pager-action=previous]') - .attr('disabled', page === 0) - .end() - .find('button[data-pager-action=next]') - .attr('disabled', page === pages - 1); - } - - self.records.add(records, {silent: true}); - list.render(); - d.resolve(list); - }); - return d.promise(); - }, - setup_resequence_rows: function (list, dataset) { - // drag and drop enabled if list is not sorted and there is a - // "sequence" column in the view. - if ((dataset.sort && dataset.sort()) - || !_(this.columns).any(function (column) { - return column.name === 'sequence'; })) { - return; - } - // ondrop, move relevant record & fix sequences - list.$current.sortable({ - stop: function (event, ui) { - var to_move = list.records.get(ui.item.data('id')), - target_id = ui.item.prev().data('id'); - - list.records.remove(to_move); - var to = target_id ? list.records.indexOf(list.records.get(target_id)) : 0; - list.records.add(to_move, { at: to }); - - // resequencing time! - var record, index = to, - // if drag to 1st row (to = 0), start sequencing from 0 - // (exclusive lower bound) - seq = to ? list.records.at(to - 1).get('sequence') : 0; - while (++seq, record = list.records.at(index++)) { - // 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}); - record.set('sequence', seq); - } - - list.refresh_zebra(); - } - }); - }, - render: function (post_render) { - var self = this; - var $element = $('<tbody>'); - this.elements = [$element[0]]; - - this.datagroup.list( - _(this.view.visible_columns).chain() - .filter(function (column) { return column.tag === 'field' }) - .pluck('name').value(), - function (groups) { - $element[0].appendChild( - self.render_groups(groups)); - if (post_render) { post_render(); } - }, function (dataset) { - self.render_dataset(dataset).then(function (list) { - self.children[null] = list; - self.elements = - [list.$current.replaceAll($element)[0]]; - self.setup_resequence_rows(list, dataset); - if (post_render) { post_render(); } - }); - }); - return $element; - }, - /** - * Returns the ids of all selected records for this group, and the records - * themselves - */ - get_selection: function () { - var ids = [], records = []; - - _(this.children) - .each(function (child) { - var selection = child.get_selection(); - ids.push.apply(ids, selection.ids); - records.push.apply(records, selection.records); - }); - - return {ids: ids, records: records}; - }, - on_records_reset: function () { - this.children = {}; - $(this.elements).remove(); - }, - get_records: function () { - if (_(this.children).isEmpty()) { - return { - count: this.datagroup.length, - values: this.datagroup.aggregates - } - } - return _(this.children).chain() - .map(function (child) { - return child.get_records(); - }).flatten().value(); - } -}); - -/** - * @class - * @extends openerp.base.Class - */ -var Events = { - /** - * @param {String} event event to listen to on the current object, null for all events - * @param {Function} handler event handler to bind to the relevant event - * @returns this - */ - bind: function (event, handler) { - var calls = this['_callbacks'] || (this._callbacks = {}); - - if (event in calls) { - calls[event].push(handler); - } else { - calls[event] = [handler]; - } - return this; - }, - /** - * @param {String} event event to unbind on the current object - * @param {function} [handler] specific event handler to remove (otherwise unbind all handlers for the event) - * @returns this - */ - unbind: function (event, handler) { - var calls = this._callbacks || {}; - if (!(event in calls)) { return this; } - if (!handler) { - delete calls[event]; - } else { - var handlers = calls[event]; - handlers.splice( - _(handlers).indexOf(handler), - 1); - } - return this; - }, - /** - * @param {String} event - * @returns this - */ - trigger: function (event) { - var calls; - if (!(calls = this._callbacks)) { return this; } - var callbacks = (calls[event] || []).concat(calls[null] || []); - for(var i=0, length=callbacks.length; i<length; ++i) { - callbacks[i].apply(this, arguments); - } - return this; - } -}; -var Record = openerp.base.Class.extend(/** @lends Record# */{ - /** - * @constructs - * @extends openerp.base.Class - * @borrows Events#bind as this.bind - * @borrows Events#trigger as this.trigger - * @param {Object} [data] - */ - init: function (data) { - this.attributes = data || {}; - }, - /** - * @param {String} key - * @returns {Object} - */ - get: function (key) { - return this.attributes[key]; - }, - /** - * @param key - * @param value - * @param {Object} [options] - * @param {Boolean} [options.silent=false] - * @returns {Record} - */ - set: function (key, value, options) { - options = options || {}; - var old_value = this.attributes[key]; - if (old_value === value) { - return this; - } - this.attributes[key] = value; - if (!options.silent) { - this.trigger('change:' + key, this, value, old_value); - this.trigger('change', this, key, value, old_value); - } - return this; - }, - /** - * Converts the current record to the format expected by form views: - * - * .. code-block:: javascript - * - * data: { - * $fieldname: { - * value: $value - * } - * } - * - * - * @returns {Object} record displayable in a form view - */ - toForm: function () { - var form_data = {}; - _(this.attributes).each(function (value, key) { - form_data[key] = {value: value}; - }); - - return {data: form_data}; - } -}); -Record.include(Events); -var Collection = openerp.base.Class.extend(/** @lends Collection# */{ - /** - * Smarter collections, with events, very strongly inspired by Backbone's. - * - * Using a "dumb" array of records makes synchronization between the - * various serious - * - * @constructs - * @extends openerp.base.Class - * @borrows Events#bind as this.bind - * @borrows Events#trigger as this.trigger - * @param {Array} [records] records to initialize the collection with - * @param {Object} [options] - */ - init: function (records, options) { - options = options || {}; - _.bindAll(this, '_onRecordEvent'); - this.length = 0; - this.records = []; - this._byId = {}; - this._proxies = {}; - this._key = options.key; - this._parent = options.parent; - - if (records) { - this.add(records); - } - }, - /** - * @param {Object|Array} record - * @param {Object} [options] - * @param {Number} [options.at] - * @param {Boolean} [options.silent=false] - * @returns this - */ - add: function (record, options) { - options = options || {}; - var records = record instanceof Array ? record : [record]; - - for(var i=0, length=records.length; i<length; ++i) { - var instance = (records[i] instanceof Record) ? records[i] : new Record(records[i]); - instance.bind(null, this._onRecordEvent); - this._byId[instance.get('id')] = instance; - if (options.at == undefined) { - this.records.push(instance); - if (!options.silent) { - this.trigger('add', this, instance, this.records.length-1); - } - } else { - var insertion_index = options.at + i; - this.records.splice(insertion_index, 0, instance); - if (!options.silent) { - this.trigger('add', this, instance, insertion_index); - } - } - this.length++; - } - return this; - }, - - /** - * Get a record by its index in the collection, can also take a group if - * the collection is not degenerate - * - * @param {Number} index - * @param {String} [group] - * @returns {Record|undefined} - */ - at: function (index, group) { - if (group) { - var groups = group.split('.'); - return this._proxies[groups[0]].at(index, groups.join('.')); - } - return this.records[index]; - }, - /** - * Get a record by its database id - * - * @param {Number} id - * @returns {Record|undefined} - */ - get: function (id) { - if (!_(this._proxies).isEmpty()) { - var record = null; - _(this._proxies).detect(function (proxy) { - return record = proxy.get(id); - }); - return record; - } - return this._byId[id]; - }, - /** - * Builds a proxy (insert/retrieve) to a subtree of the collection, by - * the subtree's group - * - * @param {String} section group path section - * @returns {Collection} - */ - proxy: function (section) { - return this._proxies[section] = new Collection(null, { - parent: this, - key: section - }).bind(null, this._onRecordEvent); - }, - /** - * @param {Array} [records] - * @returns this - */ - reset: function (records) { - _(this._proxies).each(function (proxy) { - proxy.reset(); - }); - this._proxies = {}; - this.length = 0; - this.records = []; - this._byId = {}; - if (records) { - this.add(records); - } - this.trigger('reset', this); - return this; - }, - /** - * Removes the provided record from the collection - * - * @param {Record} record - * @returns this - */ - remove: function (record) { - var self = this; - var index = _(this.records).indexOf(record); - if (index === -1) { - _(this._proxies).each(function (proxy) { - proxy.remove(record); - }); - return this; - } - - this.records.splice(index, 1); - delete this._byId[record.get('id')]; - this.length--; - this.trigger('remove', record, this); - return this; - }, - - _onRecordEvent: function (event, record, options) { - // don't propagate reset events - if (event === 'reset') { return; } - this.trigger.apply(this, arguments); - }, - - // underscore-type methods - each: function (callback) { - for(var section in this._proxies) { - if (this._proxies.hasOwnProperty(section)) { - this._proxies[section].each(callback); - } - } - for(var i=0; i<this.length; ++i) { - callback(this.records[i]); - } - }, - map: function (callback) { - var results = []; - this.each(function (record) { - results.push(callback(record)); - }); - return results; - }, - pluck: function (fieldname) { - return this.map(function (record) { - return record.get(fieldname); - }); - }, - indexOf: function (record) { - return _(this.records).indexOf(record); - } -}); -Collection.include(Events); -openerp.base.list = { - Events: Events, - Record: Record, - Collection: Collection -} -}; -// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/base/static/src/js/search.js b/addons/base/static/src/js/search.js deleted file mode 100644 index 94a8fa51aa0..00000000000 --- a/addons/base/static/src/js/search.js +++ /dev/null @@ -1,1177 +0,0 @@ -openerp.base.search = function(openerp) { - -openerp.base.SearchView = openerp.base.Widget.extend({ - init: function(parent, element_id, dataset, view_id, defaults) { - this._super(parent, element_id); - this.dataset = dataset; - this.model = dataset.model; - this.view_id = view_id; - - this.defaults = defaults || {}; - - this.inputs = []; - this.enabled_filters = []; - - this.has_focus = false; - - this.ready = $.Deferred(); - }, - start: function() { - //this.log('Starting SearchView '+this.model+this.view_id) - this.rpc("/base/searchview/load", {"model": this.model, "view_id":this.view_id}, this.on_loaded); - return this.ready.promise(); - }, - show: function () { - this.$element.show(); - }, - hide: function () { - this.$element.hide(); - }, - /** - * Builds a list of widget rows (each row is an array of widgets) - * - * @param {Array} items a list of nodes to convert to widgets - * @param {Object} fields a mapping of field names to (ORM) field attributes - * @returns Array - */ - make_widgets: function (items, fields) { - var rows = [], - row = []; - rows.push(row); - var filters = []; - _.each(items, function (item) { - if (filters.length && item.tag !== 'filter') { - row.push( - new openerp.base.search.FilterGroup( - filters, this)); - filters = []; - } - - if (item.tag === 'newline') { - row = []; - rows.push(row); - } else if (item.tag === 'filter') { - if (!this.has_focus) { - item.attrs.default_focus = '1'; - this.has_focus = true; - } - filters.push( - new openerp.base.search.Filter( - item, this)); - } else if (item.tag === 'separator') { - // a separator is a no-op - } else { - if (item.tag === 'group') { - // TODO: group and field should be fetched from registries, maybe even filters - row.push( - new openerp.base.search.Group( - item, this, fields)); - } else if (item.tag === 'field') { - if (!this.has_focus) { - item.attrs.default_focus = '1'; - this.has_focus = true; - } - row.push( - this.make_field( - item, fields[item['attrs'].name])); - } - } - }, this); - if (filters.length) { - row.push(new openerp.base.search.FilterGroup(filters, this)); - } - - return rows; - }, - /** - * Creates a field for the provided field descriptor item (which comes - * from fields_view_get) - * - * @param {Object} item fields_view_get node for the field - * @param {Object} field fields_get result for the field - * @returns openerp.base.search.Field - */ - make_field: function (item, field) { - try { - return new (openerp.base.search.fields.get_object(field.type)) - (item, field, this); - } catch (e) { - if (! e instanceof openerp.base.KeyNotFound) { - throw e; - } - // KeyNotFound means unknown field type - console.group('Unknown field type ' + field.type); - console.error('View node', item); - console.info('View field', field); - console.info('In view', this); - console.groupEnd(); - return null; - } - }, - on_loaded: function(data) { - var self = this, - lines = this.make_widgets( - data.fields_view['arch'].children, - data.fields_view.fields); - - // for extended search view - var ext = new openerp.base.search.ExtendedSearch(this, this.model); - lines.push([ext]); - this.inputs.push(ext); - - var render = QWeb.render("SearchView", { - 'view': data.fields_view['arch'], - 'lines': lines, - 'defaults': this.defaults - }); - - // We don't understand why the following commented line does not work in Chrome but - // the non-commented line does. As far as we investigated, only God knows. - //this.$element.html(render); - jQuery(render).appendTo(this.$element); - this.$element.find(".oe_search-view-custom-filter-btn").click(ext.on_activate); - - var f = this.$element.find('form'); - this.$element.find('form') - .submit(this.do_search) - .bind('reset', this.do_clear); - // start() all the widgets - var widget_starts = _(lines).chain().flatten().map(function (widget) { - return widget.start(); - }).value(); - - $.when.apply(null, widget_starts).then(function () { - self.ready.resolve(); - }); - - this.reload_managed_filters(); - }, - reload_managed_filters: function() { - var self = this; - return this.rpc('/base/searchview/get_filters', { - model: this.dataset.model - }).then(function(result) { - self.managed_filters = result; - var filters = self.$element.find(".oe_search-view-filters-management"); - filters.html(QWeb.render("SearchView.managed-filters", {filters: result})); - filters.change(self.on_filters_management); - }); - }, - /** - * Handle event when the user make a selection in the filters management select box. - */ - on_filters_management: function(e) { - 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; - } - if (val.slice(0, "get:".length) == "get:") { - val = val.slice("get:".length); - val = parseInt(val); - var filter = this.managed_filters[val]; - this.on_search([filter.domain], [filter.context], []); - } else if (val == "save_filter") { - select.val("_filters"); - var data = this.build_search_data(); - var context = new openerp.base.CompoundContext(); - _.each(data.contexts, function(x) { - context.add(x); - }); - var domain = new openerp.base.CompoundDomain(); - _.each(data.domains, function(x) { - domain.add(x); - }); - var dial_html = QWeb.render("SearchView.managed-filters.add"); - var $dial = $(dial_html); - $dial.dialog({ - modal: true, - title: "Filter Entry", - buttons: { - Cancel: function() { - $(this).dialog("close"); - }, - OK: function() { - $(this).dialog("close"); - var name = $(this).find("input").val(); - self.rpc('/base/searchview/save_filter', { - model: self.dataset.model, - context_to_save: context, - domain: domain, - name: name - }).then(function() { - self.reload_managed_filters(); - }); - } - } - }); - } else { // manage_filters - select.val("_filters"); - this.do_action({ - res_model: 'ir.filters', - views: [[false, 'list'], [false, 'form']], - type: 'ir.actions.act_window', - context: {"search_default_user_id": this.session.uid, - "search_default_model_id": this.dataset.model}, - target: "current", - limit : 80, - auto_search : true - }); - } - }, - /** - * Performs the search view collection of widget data. - * - * If the collection went well (all fields are valid), then triggers - * :js:func:`openerp.base.SearchView.on_search`. - * - * If at least one field failed its validation, triggers - * :js:func:`openerp.base.SearchView.on_invalid` instead. - * - * @param e jQuery event object coming from the "Search" button - */ - do_search: function (e) { - // reset filters management - var select = this.$element.find(".oe_search-view-filters-management"); - select.val("_filters"); - - if (e && e.preventDefault) { e.preventDefault(); } - - var data = this.build_search_data(); - - if (data.errors.length) { - this.on_invalid(data.errors); - return; - } - - this.on_search(data.domains, data.contexts, data.groupbys); - }, - build_search_data: function() { - var domains = [], - contexts = [], - errors = []; - - _.each(this.inputs, function (input) { - try { - var domain = input.get_domain(); - if (domain) { - domains.push(domain); - } - - var context = input.get_context(); - if (context) { - contexts.push(context); - } - } catch (e) { - if (e instanceof openerp.base.search.Invalid) { - errors.push(e); - } else { - throw e; - } - } - }); - - // TODO: do we need to handle *fields* with group_by in their context? - var groupbys = _(this.enabled_filters) - .chain() - .map(function (filter) { return filter.get_context();}) - .compact() - .value(); - return {domains: domains, contexts: contexts, errors: errors, groupbys: groupbys}; - }, - /** - * Triggered after the SearchView has collected all relevant domains and - * contexts. - * - * It is provided with an Array of domains and an Array of contexts, which - * may or may not be evaluated (each item can be either a valid domain or - * context, or a string to evaluate in order in the sequence) - * - * It is also passed an array of contexts used for group_by (they are in - * the correct order for group_by evaluation, which contexts may not be) - * - * @event - * @param {Array} domains an array of literal domains or domain references - * @param {Array} contexts an array of literal contexts or context refs - * @param {Array} groupbys ordered contexts which may or may not have group_by keys - */ - on_search: function (domains, contexts, groupbys) { - }, - /** - * Triggered after a validation error in the SearchView fields. - * - * Error objects have three keys: - * * ``field`` is the name of the invalid field - * * ``value`` is the invalid value - * * ``message`` is the (in)validation message provided by the field - * - * @event - * @param {Array} errors a never-empty array of error objects - */ - on_invalid: function (errors) { - this.notification.notify("Invalid Search", "triggered from search view"); - }, - do_clear: function () { - $('.filter_label').removeClass('enabled'); - var string = $('a.searchview_group_string'); - _.each(string, function(str){ - $(str).closest('div.searchview_group').removeClass("expanded").addClass('folded'); - }); - this.$element.find('table:last').hide(); - - $('.searchview_extended_groups_list').empty(); - setTimeout(this.on_clear); - }, - /** - * Triggered when the search view gets cleared - * - * @event - */ - on_clear: function () { - this.do_search(); - }, - /** - * Called by a filter propagating its state changes - * - * @param {openerp.base.search.Filter} filter a filter which got toggled - * @param {Boolean} default_enabled filter got enabled through the default values, at render time. - */ - do_toggle_filter: function (filter, default_enabled) { - if (default_enabled || filter.is_enabled()) { - this.enabled_filters.push(filter); - } else { - this.enabled_filters = _.without( - this.enabled_filters, filter); - } - - if (!default_enabled) { - // selecting a filter after initial loading automatically - // triggers refresh - this.$element.find('form').submit(); - } - } -}); - -/** @namespace */ -openerp.base.search = {}; -/** - * Registry of search fields, called by :js:class:`openerp.base.SearchView` to - * find and instantiate its field widgets. - */ -openerp.base.search.fields = new openerp.base.Registry({ - 'char': 'openerp.base.search.CharField', - 'text': 'openerp.base.search.CharField', - 'boolean': 'openerp.base.search.BooleanField', - 'integer': 'openerp.base.search.IntegerField', - 'float': 'openerp.base.search.FloatField', - 'selection': 'openerp.base.search.SelectionField', - 'datetime': 'openerp.base.search.DateTimeField', - 'date': 'openerp.base.search.DateField', - 'many2one': 'openerp.base.search.ManyToOneField', - 'many2many': 'openerp.base.search.CharField', - 'one2many': 'openerp.base.search.CharField' -}); -openerp.base.search.Invalid = openerp.base.Class.extend( /** @lends openerp.base.search.Invalid# */{ - /** - * Exception thrown by search widgets when they hold invalid values, - * which they can not return when asked. - * - * @constructs - * @param field the name of the field holding an invalid value - * @param value the invalid value - * @param message validation failure message - */ - init: function (field, value, message) { - this.field = field; - this.value = value; - this.message = message; - }, - toString: function () { - return ('Incorrect value for field ' + this.field + - ': [' + this.value + '] is ' + this.message); - } -}); -openerp.base.search.Widget = openerp.base.Widget.extend( /** @lends openerp.base.search.Widget# */{ - template: null, - /** - * Root class of all search widgets - * - * @constructs - * @extends openerp.base.Widget - * - * @param view the ancestor view of this widget - */ - init: function (view) { - this.view = view; - }, - /** - * Sets and returns a globally unique identifier for the widget. - * - * If a prefix is specified, the identifier will be appended to it. - * - * @params prefix prefix sections, empty/falsy sections will be removed - */ - make_id: function () { - this.element_id = _.uniqueId( - ['search'].concat( - _.compact(_.toArray(arguments)), - ['']).join('_')); - return this.element_id; - }, - /** - * "Starts" the widgets. Called at the end of the rendering, this allows - * widgets to hook themselves to their view sections. - * - * On widgets, if they kept a reference to a view and have an element_id, - * will fetch and set their root element on $element. - */ - start: function () { - this._super(); - if (this.view && this.element_id) { - // id is unique, and no getElementById on elements - this.$element = $(document.getElementById( - this.element_id)); - } - }, - /** - * "Stops" the widgets. Called when the view destroys itself, this - * lets the widgets clean up after themselves. - */ - stop: function () { - delete this.view; - this._super(); - }, - render: function (defaults) { - return QWeb.render( - this.template, _.extend(this, { - defaults: defaults - })); - } -}); -openerp.base.search.FilterGroup = openerp.base.search.Widget.extend({ - template: 'SearchView.filters', - init: function (filters, view) { - this._super(view); - this.filters = filters; - this.length = filters.length; - }, - start: function () { - this._super(); - _.each(this.filters, function (filter) { - filter.start(); - }); - } -}); -openerp.base.search.add_expand_listener = function($root) { - $root.find('a.searchview_group_string').click(function (e) { - $root.toggleClass('folded expanded'); - e.stopPropagation(); - e.preventDefault(); - }); -}; -openerp.base.search.Group = openerp.base.search.Widget.extend({ - template: 'SearchView.group', - init: function (view_section, view, fields) { - this._super(view); - this.attrs = view_section.attrs; - this.lines = view.make_widgets( - view_section.children, fields); - this.make_id('group'); - }, - start: function () { - this._super(); - openerp.base.search.add_expand_listener(this.$element); - var widget_starts = _(this.lines).chain().flatten() - .map(function (widget) { return widget.start(); }) - .value(); - return $.when.apply(null, widget_starts); - } -}); - -openerp.base.search.Input = openerp.base.search.Widget.extend( /** @lends openerp.base.search.Input# */{ - /** - * @constructs - * @extends openerp.base.search.Widget - * - * @param view - */ - init: function (view) { - this._super(view); - this.view.inputs.push(this); - }, - get_context: function () { - throw new Error( - "get_context not implemented for widget " + this.attrs.type); - }, - get_domain: function () { - throw new Error( - "get_domain not implemented for widget " + this.attrs.type); - } -}); -openerp.base.search.Filter = openerp.base.search.Input.extend({ - template: 'SearchView.filter', - init: function (node, view) { - this._super(view); - this.attrs = node.attrs; - this.classes = [this.attrs.string ? 'filter_label' : 'filter_icon']; - this.make_id('filter', this.attrs.name); - }, - start: function () { - this._super(); - var self = this; - this.$element.click(function (e) { - $(this).toggleClass('enabled'); - self.view.do_toggle_filter(self); - }); - }, - /** - * Returns whether the filter is currently enabled (in use) or not. - * - * @returns a boolean - */ - is_enabled:function () { - return this.$element.hasClass('enabled'); - }, - /** - * If the filter is present in the defaults (and has a truthy value), - * enable the filter. - * - * @param {Object} defaults the search view's default values - */ - render: function (defaults) { - if (this.attrs.name && defaults[this.attrs.name]) { - this.classes.push('enabled'); - this.view.do_toggle_filter(this, true); - } - return this._super(defaults); - }, - get_context: function () { - if (!this.is_enabled()) { - return; - } - return this.attrs.context; - }, - get_domain: function () { - if (!this.is_enabled()) { - return; - } - return this.attrs.domain; - } -}); -openerp.base.search.Field = openerp.base.search.Input.extend( /** @lends openerp.base.search.Field# */ { - template: 'SearchView.field', - default_operator: '=', - /** - * @constructs - * @extends openerp.base.search.Input - * - * @param view_section - * @param field - * @param view - */ - init: function (view_section, field, view) { - this._super(view); - this.attrs = _.extend({}, field, view_section.attrs); - this.filters = new openerp.base.search.FilterGroup(_.map( - view_section.children, function (filter_node) { - return new openerp.base.search.Filter( - filter_node, view); - }), view); - this.make_id('input', field.type, this.attrs.name); - }, - start: function () { - this._super(); - this.filters.start(); - }, - get_context: function () { - var val = this.get_value(); - // A field needs a value to be "active", and a context to send when - // active - var has_value = (val !== null && val !== ''); - var context = this.attrs.context; - if (!(has_value && context)) { - return; - } - return _.extend( - {}, context, - {own_values: {self: val}}); - }, - /** - * Function creating the returned domain for the field, override this - * methods in children if you only need to customize the field's domain - * without more complex alterations or tests (and without the need to - * change override the handling of filter_domain) - * - * @param {String} name the field's name - * @param {String} operator the field's operator (either attribute-specified or default operator for the field - * @param {Number|String} value parsed value for the field - * @returns {Array<Array>} domain to include in the resulting search - */ - make_domain: function (name, operator, value) { - return [[name, operator, value]]; - }, - get_domain: function () { - var val = this.get_value(); - if (val === null || val === '') { - return; - } - - var domain = this.attrs['filter_domain']; - if (!domain) { - return this.make_domain( - this.attrs.name, - this.attrs.operator || this.default_operator, - val); - } - return _.extend({}, domain, {own_values: {self: val}}); - } -}); -/** - * Implementation of the ``char`` OpenERP field type: - * - * * Default operator is ``ilike`` rather than ``=`` - * - * * The Javascript and the HTML values are identical (strings) - * - * @class - * @extends openerp.base.search.Field - */ -openerp.base.search.CharField = openerp.base.search.Field.extend( /** @lends openerp.base.search.CharField# */ { - default_operator: 'ilike', - get_value: function () { - return this.$element.val(); - } -}); -openerp.base.search.NumberField = openerp.base.search.Field.extend(/** @lends openerp.base.search.NumberField# */{ - get_value: function () { - if (!this.$element.val()) { - return null; - } - var val = this.parse(this.$element.val()), - check = Number(this.$element.val()); - if (isNaN(val) || val !== check) { - this.$element.addClass('error'); - throw new openerp.base.search.Invalid( - this.attrs.name, this.$element.val(), this.error_message); - } - this.$element.removeClass('error'); - return val; - } -}); -/** - * @class - * @extends openerp.base.search.NumberField - */ -openerp.base.search.IntegerField = openerp.base.search.NumberField.extend(/** @lends openerp.base.search.IntegerField# */{ - error_message: "not a valid integer", - parse: function (value) { - return parseInt(value, 10); - } -}); -/** - * @class - * @extends openerp.base.search.NumberField - */ -openerp.base.search.FloatField = openerp.base.search.NumberField.extend(/** @lends openerp.base.search.FloatField# */{ - error_message: "not a valid number", - parse: function (value) { - return parseFloat(value); - } -}); -/** - * @class - * @extends openerp.base.search.Field - */ -openerp.base.search.SelectionField = openerp.base.search.Field.extend(/** @lends openerp.base.search.SelectionField# */{ - template: 'SearchView.field.selection', - get_value: function () { - return this.$element.val(); - } -}); -openerp.base.search.BooleanField = openerp.base.search.SelectionField.extend(/** @lends openerp.base.search.BooleanField# */{ - /** - * @constructs - * @extends openerp.base.search.BooleanField - */ - init: function () { - this._super.apply(this, arguments); - this.attrs.selection = [ - ['true', 'Yes'], - ['false', 'No'] - ]; - }, - /** - * Search defaults likely to be boolean values (for a boolean field). - * - * In the HTML, we only want/get strings, and our strings here are ``true`` - * and ``false``, so ensure we use precisely those by truth-testing the - * default value (iif there is one in the view's defaults). - * - * @param {Object} defaults default values for this search view - * @returns {String} rendered boolean field - */ - render: function (defaults) { - var name = this.attrs.name; - if (name in defaults) { - defaults[name] = defaults[name] ? "true" : "false"; - } - return this._super(defaults); - }, - get_value: function () { - switch (this.$element.val()) { - case 'false': return false; - case 'true': return true; - default: return null; - } - } -}); -openerp.base.search.DateField = openerp.base.search.Field.extend( /** @lends openerp.base.search.DateField# */{ - /** - * enables date picker on the HTML widgets - */ - start: function () { - this._super(); - this.$element.addClass('field_date').datepicker({ - dateFormat: 'yy-mm-dd' - }); - }, - stop: function () { - this.$element.datepicker('destroy'); - }, - get_value: function () { - return this.$element.val(); - } -}); -/** - * Implementation of the ``datetime`` openerp field type: - * - * * Uses the same widget as the ``date`` field type (a simple date) - * - * * Builds a slighly more complex, it's a datetime range (includes time) - * spanning the whole day selected by the date widget - * - * @class - * @extends openerp.base.DateField - */ -openerp.base.search.DateTimeField = openerp.base.search.DateField.extend(/** @lends openerp.base.search.DateTimeField# */{ - make_domain: function (name, operator, value) { - return ['&', [name, '>=', value + ' 00:00:00'], - [name, '<=', value + ' 23:59:59']]; - } -}); -openerp.base.search.ManyToOneField = openerp.base.search.CharField.extend({ - init: function (view_section, field, view) { - this._super(view_section, field, view); - var self = this; - this.got_name = $.Deferred().then(function () { - self.$element.val(self.name); - }); - this.dataset = new openerp.base.DataSet( - this.view, this.attrs['relation']); - }, - start: function () { - this._super(); - this.setup_autocomplete(); - var started = $.Deferred(); - this.got_name.then(function () { started.resolve();}, - function () { started.resolve(); }); - return started.promise(); - }, - setup_autocomplete: function () { - var self = this; - this.$element.autocomplete({ - source: function (req, resp) { - self.dataset.name_search( - req.term, self.attrs.domain, 'ilike', 8, function (data) { - resp(_.map(data, function (result) { - return {id: result[0], label: result[1]} - })); - }); - }, - select: function (event, ui) { - self.id = ui.item.id; - self.name = ui.item.label; - }, - delay: 0 - }) - }, - on_name_get: function (name_get) { - if (!name_get.length) { - delete this.id; - this.got_name.reject(); - return; - } - this.name = name_get[0][1]; - this.got_name.resolve(); - }, - render: function (defaults) { - if (defaults[this.attrs.name]) { - this.id = defaults[this.attrs.name]; - if (this.id instanceof Array) - this.id = this.id[0]; - // TODO: maybe this should not be completely removed - delete defaults[this.attrs.name]; - this.dataset.name_get([this.id], $.proxy(this, 'on_name_get')); - } else { - this.got_name.reject(); - } - return this._super(defaults); - }, - make_domain: function (name, operator, value) { - if (this.id && this.name) { - if (value === this.name) { - return [[name, '=', this.id]]; - } else { - delete this.id; - delete this.name; - } - } - return this._super(name, operator, value); - } -}); - -openerp.base.search.ExtendedSearch = openerp.base.OldWidget.extend({ - template: 'SearchView.extended_search', - identifier_prefix: 'extended-search', - init: function (parent, model) { - this._super(parent); - this.model = model; - }, - add_group: function() { - var group = new openerp.base.search.ExtendedSearchGroup(this, this.fields); - group.appendTo(this.$element.find('.searchview_extended_groups_list')); - this.check_last_element(); - }, - start: function () { - this._super(); - if (!this.$element) { - return; // not a logical state but sometimes it happens - } - this.$element.closest("table.oe-searchview-render-line").css("display", "none"); - var self = this; - this.rpc("/base/searchview/fields_get", - {"model": this.model}, function(data) { - self.fields = data.fields; - openerp.base.search.add_expand_listener(self.$element); - self.$element.find('.searchview_extended_add_group').click(function (e) { - self.add_group(); - }); - }); - }, - get_context: function() { - return null; - }, - get_domain: function() { - if (!this.$element) { - return null; // not a logical state but sometimes it happens - } - if(this.$element.closest("table.oe-searchview-render-line").css("display") == "none") { - return null; - } - return _.reduce(this.widget_children, - function(mem, x) { return mem.concat(x.get_domain());}, []); - }, - on_activate: function() { - this.add_group(); - var table = this.$element.closest("table.oe-searchview-render-line"); - table.css("display", ""); - if(this.$element.hasClass("folded")) { - this.$element.toggleClass("folded expanded"); - } - }, - hide: function() { - var table = this.$element.closest("table.oe-searchview-render-line"); - table.css("display", "none"); - if(this.$element.hasClass("expanded")) { - this.$element.toggleClass("folded expanded"); - } - }, - check_last_element: function() { - _.each(this.widget_children, function(x) {x.set_last_group(false);}); - if (this.widget_children.length >= 1) { - this.widget_children[this.widget_children.length - 1].set_last_group(true); - } - } -}); - -openerp.base.search.ExtendedSearchGroup = openerp.base.OldWidget.extend({ - template: 'SearchView.extended_search.group', - identifier_prefix: 'extended-search-group', - init: function (parent, fields) { - this._super(parent); - this.fields = fields; - }, - add_prop: function() { - var prop = new openerp.base.search.ExtendedSearchProposition(this, this.fields); - var render = prop.render({'index': this.widget_children.length - 1}); - this.$element.find('.searchview_extended_propositions_list').append(render); - prop.start(); - }, - start: function () { - this._super(); - var _this = this; - this.add_prop(); - this.$element.find('.searchview_extended_add_proposition').click(function () { - _this.add_prop(); - }); - this.$element.find('.searchview_extended_delete_group').click(function () { - _this.stop(); - }); - }, - get_domain: function() { - var props = _(this.widget_children).chain().map(function(x) { - return x.get_proposition(); - }).compact().value(); - var choice = this.$element.find(".searchview_extended_group_choice").val(); - var op = choice == "all" ? "&" : "|"; - return choice == "none" ? ['!'] : [].concat( - _.map(_.range(_.max([0,props.length - 1])), function() { return op; }), - props); - }, - stop: function() { - var parent = this.widget_parent; - if (this.widget_parent.widget_children.length == 1) - this.widget_parent.hide(); - this._super(); - parent.check_last_element(); - }, - set_last_group: function(is_last) { - this.$element.toggleClass('last_group', is_last); - } -}); - -openerp.base.search.ExtendedSearchProposition = openerp.base.OldWidget.extend({ - template: 'SearchView.extended_search.proposition', - identifier_prefix: 'extended-search-proposition', - init: function (parent, fields) { - this._super(parent); - this.fields = _(fields).chain() - .map(function(val, key) { return _.extend({}, val, {'name': key}); }) - .sortBy(function(field) {return field.string;}) - .value(); - this.attrs = {_: _, fields: this.fields, selected: null}; - this.value = null; - }, - start: function () { - this._super(); - this.select_field(this.fields.length > 0 ? this.fields[0] : null); - var _this = this; - this.$element.find(".searchview_extended_prop_field").change(function() { - _this.changed(); - }); - this.$element.find('.searchview_extended_delete_prop').click(function () { - _this.stop(); - }); - }, - stop: function() { - var parent; - if (this.widget_parent.widget_children.length == 1) - parent = this.widget_parent; - this._super(); - if (parent) - parent.stop(); - }, - changed: function() { - var nval = this.$element.find(".searchview_extended_prop_field").val(); - if(this.attrs.selected == null || nval != this.attrs.selected.name) { - this.select_field(_.detect(this.fields, function(x) {return x.name == nval;})); - } - }, - /** - * Selects the provided field object - * - * @param field a field descriptor object (as returned by fields_get, augmented by the field name) - */ - select_field: function(field) { - var _this = this; - if(this.attrs.selected != null) { - this.value.stop(); - this.value = null; - this.$element.find('.searchview_extended_prop_op').html(''); - } - this.attrs.selected = field; - if(field == null) { - return; - } - - var type = field.type; - try { - openerp.base.search.custom_filters.get_object(type); - } catch (e) { - if (! e instanceof openerp.base.KeyNotFound) { - throw e; - } - type = "char"; - this.log('Unknow field type ' + e.key); - } - this.value = new (openerp.base.search.custom_filters.get_object(type)) - (this); - if(this.value.set_field) { - this.value.set_field(field); - } - _.each(this.value.operators, function(operator) { - var option = jQuery('<option>', {value: operator.value}) - .text(operator.text) - .appendTo(_this.$element.find('.searchview_extended_prop_op')); - }); - this.$element.find('.searchview_extended_prop_value').html( - this.value.render({})); - this.value.start(); - - }, - get_proposition: function() { - if ( this.attrs.selected == null) - return null; - var field = this.attrs.selected.name; - var op = this.$element.find('.searchview_extended_prop_op').val(); - var value = this.value.get_value(); - return [field, op, value]; - } -}); - -openerp.base.search.ExtendedSearchProposition.Char = openerp.base.OldWidget.extend({ - template: 'SearchView.extended_search.proposition.char', - identifier_prefix: 'extended-search-proposition-char', - operators: [ - {value: "ilike", text: "contains"}, - {value: "not ilike", text: "doesn't contain"}, - {value: "=", text: "is equal to"}, - {value: "!=", text: "is not equal to"}, - {value: ">", text: "greater than"}, - {value: "<", text: "less than"}, - {value: ">=", text: "greater or equal than"}, - {value: "<=", text: "less or equal than"} - ], - get_value: function() { - return this.$element.val(); - } -}); -openerp.base.search.ExtendedSearchProposition.DateTime = openerp.base.OldWidget.extend({ - template: 'SearchView.extended_search.proposition.datetime', - identifier_prefix: 'extended-search-proposition-datetime', - operators: [ - {value: "=", text: "is equal to"}, - {value: "!=", text: "is not equal to"}, - {value: ">", text: "greater than"}, - {value: "<", text: "less than"}, - {value: ">=", text: "greater or equal than"}, - {value: "<=", text: "less or equal than"} - ], - get_value: function() { - return this.$element.val(); - }, - start: function() { - this._super(); - this.$element.datetimepicker({ - dateFormat: 'yy-mm-dd', - timeFormat: 'hh:mm:ss' - }); - } -}); -openerp.base.search.ExtendedSearchProposition.Date = openerp.base.OldWidget.extend({ - template: 'SearchView.extended_search.proposition.date', - identifier_prefix: 'extended-search-proposition-date', - operators: [ - {value: "=", text: "is equal to"}, - {value: "!=", text: "is not equal to"}, - {value: ">", text: "greater than"}, - {value: "<", text: "less than"}, - {value: ">=", text: "greater or equal than"}, - {value: "<=", text: "less or equal than"} - ], - get_value: function() { - return this.$element.val(); - }, - start: function() { - this._super(); - this.$element.datepicker({ - dateFormat: 'yy-mm-dd', - timeFormat: 'hh:mm:ss' - }); - } -}); -openerp.base.search.ExtendedSearchProposition.Integer = openerp.base.OldWidget.extend({ - template: 'SearchView.extended_search.proposition.integer', - identifier_prefix: 'extended-search-proposition-integer', - operators: [ - {value: "=", text: "is equal to"}, - {value: "!=", text: "is not equal to"}, - {value: ">", text: "greater than"}, - {value: "<", text: "less than"}, - {value: ">=", text: "greater or equal than"}, - {value: "<=", text: "less or equal than"} - ], - get_value: function() { - var value = parseFloat(this.$element.val()); - if(value != 0 && !value) { - return ""; - } - return Math.round(value); - } -}); -openerp.base.search.ExtendedSearchProposition.Float = openerp.base.OldWidget.extend({ - template: 'SearchView.extended_search.proposition.float', - identifier_prefix: 'extended-search-proposition-float', - operators: [ - {value: "=", text: "is equal to"}, - {value: "!=", text: "is not equal to"}, - {value: ">", text: "greater than"}, - {value: "<", text: "less than"}, - {value: ">=", text: "greater or equal than"}, - {value: "<=", text: "less or equal than"} - ], - get_value: function() { - var value = parseFloat(this.$element.val()); - if(value != 0 && !value) { - return ""; - } - return value; - } -}); -openerp.base.search.ExtendedSearchProposition.Selection = openerp.base.OldWidget.extend({ - template: 'SearchView.extended_search.proposition.selection', - identifier_prefix: 'extended-search-proposition-selection', - operators: [ - {value: "=", text: "is"}, - {value: "!=", text: "is not"} - ], - set_field: function(field) { - this.field = field; - }, - get_value: function() { - return this.$element.val(); - } -}); -openerp.base.search.ExtendedSearchProposition.Boolean = openerp.base.OldWidget.extend({ - template: 'SearchView.extended_search.proposition.boolean', - identifier_prefix: 'extended-search-proposition-boolean', - operators: [ - {value: "=", text: "is true"}, - {value: "!=", text: "is false"} - ], - get_value: function() { - return true; - } -}); - -openerp.base.search.custom_filters = new openerp.base.Registry({ - 'char': 'openerp.base.search.ExtendedSearchProposition.Char', - 'text': 'openerp.base.search.ExtendedSearchProposition.Char', - 'one2many': 'openerp.base.search.ExtendedSearchProposition.Char', - 'many2one': 'openerp.base.search.ExtendedSearchProposition.Char', - 'many2many': 'openerp.base.search.ExtendedSearchProposition.Char', - - 'datetime': 'openerp.base.search.ExtendedSearchProposition.DateTime', - 'date': 'openerp.base.search.ExtendedSearchProposition.Date', - 'integer': 'openerp.base.search.ExtendedSearchProposition.Integer', - 'float': 'openerp.base.search.ExtendedSearchProposition.Float', - 'boolean': 'openerp.base.search.ExtendedSearchProposition.Boolean', - 'selection': 'openerp.base.search.ExtendedSearchProposition.Selection' -}); - -}; - -// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/base/static/src/js/view_editor.js b/addons/base/static/src/js/view_editor.js deleted file mode 100644 index 753f9ac6d4e..00000000000 --- a/addons/base/static/src/js/view_editor.js +++ /dev/null @@ -1,147 +0,0 @@ -openerp.base.view_editor = function(openerp) { -openerp.base.ViewEditor = openerp.base.Widget.extend({ - init: function(parent, element_id, dataset, view, options) { - this._super(parent); - this.element_id = element_id - this.parent = parent - this.dataset = dataset; - this.model = dataset.model; - this.xml_id = 0; - }, - start: function() { - this.View_editor(); - }, - View_editor : function(){ - var self = this; - var action = { - name:'ViewEditor', - context:this.session.user_context, - domain: [["model", "=", this.dataset.model]], - res_model: 'ir.ui.view', - views : [[false, 'list']], - type: 'ir.actions.act_window', - target: "current", - limit : 80, - auto_search : true, - flags: { - sidebar: false, - views_switcher: false, - action_buttons:false, - search_view:false, - pager:false, - radio:true - }, - }; - var action_manager = new openerp.base.ActionManager(this); - this.dialog = new openerp.base.Dialog(this,{ - modal: true, - title: 'ViewEditor', - width: 750, - height: 500, - buttons: { - "Create": function(){ - - }, - "Edit": function(){ - self.xml_id=0; - self.edit_view(); - }, - "Close": function(){ - $(this).dialog('destroy'); - } - }, - - }); - this.dialog.start(); - this.dialog.open(); - action_manager.appendTo(this.dialog); - action_manager.do_action(action); - - - }, - check_attr:function(xml,tag){ - var obj = new Object(); - obj.child_id = []; - obj.id = this.xml_id++; - var att_list = []; - var name1 = "<" + tag; - $(xml).each(function() { - att_list = this.attributes; - att_list = _.select(att_list, function(attrs){ - if(attrs.nodeName == "string" || attrs.nodeName == "name" || attrs.nodeName == "index"){ - name1 += ' ' +attrs.nodeName+'='+'"'+attrs.nodeValue+'"';} - }); - name1+= ">"; - }); - obj.name = name1; - return obj; - }, - recursiveFunction : function(main_object,parent_id,child_id){ - var self = this; - var check = false; - var main_object = _.detect(main_object , function(node){ - if(node.id == parent_id){ - node.child_id = child_id; - check = true; - } - return main_object; - }); - if(check){ - return main_object; - }else{ - //todo recursion for saving object into objects - } - }, - children_function : function(xml,root,main_object,parent_id){ - var self = this; - var child_obj_list = []; - var main_object = main_object; - var children_list = $(xml).filter(root).children(); - _.each(children_list, function(child_node){ - var string = self.check_attr(child_node,child_node.tagName.toLowerCase()); - child_obj_list.push(string); - }); - if(children_list.length != 0){ - main_object = self.recursiveFunction(main_object,parent_id,child_obj_list); - } - for(var i=0;i<children_list.length;i++){ - self.children_function(children_list[i],children_list[i].tagName.toLowerCase(),main_object,child_obj_list[i].id); - } - return child_obj_list; - }, - edit_view : function(){ - var self = this; - var view_id =(($("input[name='radiogroup']:checked").parent()).parent()).attr('data-id'); - var ve_dataset = new openerp.base.DataSet(this,'ir.ui.view'); - ve_dataset.read_ids([parseInt(view_id)],['arch'],function (arch) { - var arch = arch[0].arch; - var root = $(arch).filter(":first")[0]; - var tag = root.tagName.toLowerCase(); - var root_object = self.check_attr(root,tag); - var all_list = self.children_function(arch,tag,[root_object],root_object.id); - - //todo render the final object of tree view so xml with it child node display... - }); - this.dialog = new openerp.base.Dialog(this,{ - modal: true, - title: 'Edit Xml', - width: 750, - height: 500, - buttons: { - "Inherited View": function(){ - - }, - "Preview": function(){ - - }, - "Close": function(){ - $(this).dialog('destroy'); - } - }, - - }); - this.dialog.start().open(); - } - -}); -}; diff --git a/addons/base/static/src/js/view_help.js b/addons/base/static/src/js/view_help.js deleted file mode 100644 index aa98f59c3ab..00000000000 --- a/addons/base/static/src/js/view_help.js +++ /dev/null @@ -1,15 +0,0 @@ -/*--------------------------------------------------------- - * OpenERP base library - *---------------------------------------------------------*/ - -openerp.base.view_help = function(openerp) { - -openerp.base.ProcessView = openerp.base.Widget.extend({ -}); - -openerp.base.HelpView = openerp.base.Widget.extend({ -}); - -}; - -// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/base/static/src/js/view_tree.js b/addons/base/static/src/js/view_tree.js deleted file mode 100644 index 59544a998b3..00000000000 --- a/addons/base/static/src/js/view_tree.js +++ /dev/null @@ -1,206 +0,0 @@ -/*--------------------------------------------------------- - * OpenERP base library - *---------------------------------------------------------*/ - -openerp.base.view_tree = function(openerp) { - -openerp.base.views.add('tree', 'openerp.base.TreeView'); -/** - * Genuine tree view (the one displayed as a tree, not the list) - */ -openerp.base.TreeView = openerp.base.View.extend({ - /** - * Indicates that this view is not searchable, and thus that no search - * view should be displayed (if there is one active). - */ - searchable : false, - - init: function(parent, element_id, dataset, view_id, options) { - this._super(parent, element_id); - this.dataset = dataset; - this.model = dataset.model; - this.view_id = view_id; - - this.records = {}; - - this.options = _.extend({}, this.defaults, options || {}); - }, - - start: function () { - this._super(); - return this.rpc("/base/treeview/load", { - model: this.model, - view_id: this.view_id, - toolbar: this.view_manager ? !!this.view_manager.sidebar : false - }, this.on_loaded); - }, - /** - * Returns the list of fields needed to correctly read objects. - * - * Gathers the names of all fields in fields_view_get, and adds the - * field_parent (children_field in the tree view) if it's not already one - * of the fields to fetch - * - * @returns {Array} an array of fields which can be provided to DataSet.read_slice and others - */ - fields_list: function () { - var fields = _.keys(this.fields); - if (!_(fields).contains(this.children_field)) { - fields.push(this.children_field); - } - return fields; - }, - on_loaded: function (fields_view) { - var self = this; - var has_toolbar = !!fields_view.arch.attrs.toolbar; - // field name in OpenERP is kinda stupid: this is the name of the field - // holding the ids to the children of the current node, why call it - // field_parent? - this.children_field = fields_view['field_parent']; - this.fields_view = fields_view; - _(this.fields_view.arch.children).each(function (field) { - if (field.attrs.modifiers) { - field.attrs.modifiers = JSON.parse(field.attrs.modifiers); - } - }); - this.fields = fields_view.fields; - this.hook_row_click(); - this.$element.html(QWeb.render('TreeView', { - 'title': this.fields_view.arch.attrs.string, - 'fields_view': this.fields_view.arch.children, - 'fields': this.fields, - 'toolbar': has_toolbar - })); - - this.dataset.read_slice(this.fields_list(), {}, function (records) { - if (!has_toolbar) { - // WARNING: will do a second read on the same ids, but only on - // first load so not very important - self.getdata(null, _(records).pluck('id')); - return; - } - - var $select = self.$element.find('select') - .change(function () { - var $option = $(this).find(':selected'); - self.getdata($option.val(), $option.data('children')); - }); - _(records).each(function (record) { - self.records[record.id] = record; - $('<option>') - .val(record.id) - .text(record.name) - .data('children', record[self.children_field]) - .appendTo($select); - }); - - if (!_.isEmpty(records)) { - $select.change(); - } - }); - }, - /** - * Sets up opening a row - */ - hook_row_click: function () { - var self = this; - this.$element.delegate('.treeview-td span, .treeview-tr span', 'click', function (e) { - e.stopImmediatePropagation(); - self.activate($(this).closest('tr').data('id')); - }); - - this.$element.delegate('.treeview-tr', 'click', function () { - var is_loaded = 0, - $this = $(this), - record_id = $this.data('id'), - record = self.records[record_id], - children_ids = record[self.children_field]; - - _(children_ids).each(function(childid) { - if (self.$element.find('#treerow_' + childid).length) { - if (self.$element.find('#treerow_' + childid).is(':hidden')) { - is_loaded = -1; - } else { - is_loaded++; - } - } - }); - if (is_loaded === 0) { - if (!$this.parent().hasClass('oe-open')) { - self.getdata(record_id, children_ids); - } - } else { - self.showcontent(record_id, is_loaded < 0); - } - }); - }, - // get child data of selected value - getdata: function (id, children_ids) { - var self = this; - - self.dataset.read_ids(children_ids, this.fields_list(), function (records) { - _(records).each(function (record) { - self.records[record.id] = record; - }); - - var $curr_node = self.$element.find('#treerow_' + id); - var children_rows = QWeb.render('TreeView.rows', { - 'records': records, - 'children_field': self.children_field, - 'fields_view': self.fields_view.arch.children, - 'fields': self.fields, - 'level': $curr_node.data('level') || 0, - 'render': openerp.base.format_value - }); - - if ($curr_node.length) { - $curr_node.addClass('oe-open'); - $curr_node.after(children_rows); - } else { - self.$element.find('tbody').html(children_rows); - } - }); - }, - - // Get details in listview - activate: function(id) { - var self = this; - this.rpc('/base/treeview/action', { - id: id, - model: this.dataset.model, - context: new openerp.base.CompoundContext( - this.dataset.get_context(), { - active_model: this.dataset.model, - active_id: id, - active_ids: [id]}) - }, function (actions) { - if (!actions.length) { return; } - var action = actions[0][2]; - self.do_action(action); - }); - }, - - // show & hide the contents - showcontent: function (record_id, show) { - this.$element.find('#treerow_' + record_id) - .toggleClass('oe-open', show); - - _(this.records[record_id][this.children_field]).each(function (child_id) { - var $child_row = this.$element.find('#treerow_' + child_id); - if ($child_row.hasClass('oe-open')) { - this.showcontent(child_id, false); - } - $child_row.toggle(show); - }, this); - }, - - do_show: function () { - this.$element.show(); - }, - - do_hide: function () { - this.$element.hide(); - this.hidden = true; - } -}); -}; diff --git a/addons/base/static/src/js/views.js b/addons/base/static/src/js/views.js deleted file mode 100644 index 11b45cbfeb0..00000000000 --- a/addons/base/static/src/js/views.js +++ /dev/null @@ -1,791 +0,0 @@ -/*--------------------------------------------------------- - * OpenERP base library - *---------------------------------------------------------*/ - -openerp.base.views = function(openerp) { - -var _t = openerp.base._t; - -/** - * Registry for all the client actions key: tag value: widget - */ -openerp.base.client_actions = new openerp.base.Registry(); - -openerp.base.ActionManager = openerp.base.Widget.extend({ - identifier_prefix: "actionmanager", - init: function(parent) { - this._super(parent); - this.inner_viewmanager = null; - this.dialog = null; - this.dialog_viewmanager = null; - this.client_widget = null; - this.url = {} - }, - render: function() { - return "<div id='"+this.element_id+"'></div>"; - }, - dialog_stop: function () { - if (this.dialog) { - this.dialog_viewmanager.stop(); - this.dialog_viewmanager = null; - this.dialog.stop(); - this.dialog = null; - } - }, - content_stop: function () { - if (this.inner_viewmanager) { - this.inner_viewmanager.stop(); - this.inner_viewmanager = null; - } - if (this.client_widget) { - this.client_widget.stop(); - this.client_widget = null; - } - }, - url_update: function(action) { - // this.url = { - // "model": action.model, - // "domain": action.domain, - // }; - // action.res_model - // action.domain - // action.context - // after - // action.views - // action.res_id - // mode - // menu - }, - url_stringify: function(action) { - }, - url_parse: function(action) { - }, - on_url_update: function(url) { - }, - do_url_action: function(url) { - }, - do_action: function(action, on_close) { - var type = action.type.replace(/\./g,'_'); - var popup = action.target === 'new'; - action.flags = _.extend({ - views_switcher : !popup, - search_view : !popup, - action_buttons : !popup, - sidebar : !popup, - pager : !popup - }, action.flags || {}); - if (!(type in this)) { - this.log("Action manager can't handle action of type " + action.type, action); - return; - } - this[type](action, on_close); - }, - ir_actions_act_window: function (action, on_close) { - if (action.target === 'new') { - if (this.dialog == null) { - this.dialog = new openerp.base.Dialog(this, { title: action.name, width: '80%' }); - if(on_close) - this.dialog.on_close.add(on_close); - this.dialog.start(); - } else { - this.dialog_viewmanager.stop(); - } - this.dialog_viewmanager = new openerp.base.ViewManagerAction(this, action); - this.dialog_viewmanager.appendTo(this.dialog.$element); - this.dialog.open(); - } else { - this.dialog_stop(); - this.content_stop(); - this.inner_viewmanager = new openerp.base.ViewManagerAction(this, action); - this.inner_viewmanager.appendTo(this.$element); - this.url_update(action); - } - /* new window code - this.rpc("/base/session/save_session_action", { the_action : action}, function(key) { - var url = window.location.protocol + "//" + window.location.host + window.location.pathname + "?" + jQuery.param({ s_action : "" + key }); - window.open(url,'_blank'); - }); - */ - }, - ir_actions_act_window_close: function (action, on_closed) { - this.dialog_stop(); - }, - ir_actions_server: function (action, on_closed) { - var self = this; - this.rpc('/base/action/run', { - action_id: action.id, - context: {active_id: 66, active_ids: [66], active_model: 'ir.ui.menu'} - }).then(function (action) { - self.do_action(action, on_closed) - }); - }, - ir_actions_client: function (action) { - this.content_stop(); - var ClientWidget = openerp.base.client_actions.get_object(action.tag); - (this.client_widget = new ClientWidget(this, action.params)).appendTo(this); - }, - ir_actions_report_xml: function(action) { - this.rpc('/base/report/get_report', { - action: action, - context: {} - }).then(function(result) { - debugger; - }); - } -}); - -openerp.base.ViewManager = openerp.base.Widget.extend({ - identifier_prefix: "viewmanager", - init: function(parent, dataset, views) { - this._super(parent); - this.model = dataset.model; - this.dataset = dataset; - this.searchview = null; - 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 = {}; - this.flags = this.flags || {}; - this.registry = openerp.base.views; - }, - render: function() { - return QWeb.render("ViewManager", {"prefix": this.element_id, views: this.views_src}) - }, - /** - * @returns {jQuery.Deferred} initial view loading promise - */ - start: function() { - this._super(); - var self = this; - this.dataset.start(); - this.$element.find('.oe_vm_switch button').click(function() { - self.on_mode_switch($(this).data('view-type')); - }); - var views_ids = {}; - _.each(this.views_src, function(view) { - self.views[view.view_type] = $.extend({}, view, { - controller : null, - options : _.extend({ - sidebar_id : self.element_id + '_sidebar_' + view.view_type, - action : self.action, - action_views_ids : views_ids - }, self.flags, view.options || {}) - }); - views_ids[view.view_type] = view.view_id; - }); - if (this.flags.views_switcher === false) { - this.$element.find('.oe_vm_switch').hide(); - } - // switch to the first one in sequence - return this.on_mode_switch(this.views_src[0].view_type); - }, - /** - * Asks the view manager to switch visualization mode. - * - * @param {String} view_type type of view to display - * @returns {jQuery.Deferred} new view loading promise - */ - on_mode_switch: function(view_type) { - var self = this, - view_promise; - this.active_view = view_type; - var view = this.views[view_type]; - if (!view.controller) { - // Lazy loading of views - var controllerclass = this.registry.get_object(view_type); - var controller = new controllerclass(this, this.element_id + '_view_' + view_type, - this.dataset, view.view_id, view.options); - if (view.embedded_view) { - controller.set_embedded_view(view.embedded_view); - } - controller.do_switch_view.add_last(this.on_mode_switch); - if (view_type === 'list' && this.flags.search_view === false && this.action && this.action['auto_search']) { - // In case the search view is not instantiated: manually call ListView#search - var domains = !_(self.action.domain).isEmpty() - ? [self.action.domain] : [], - contexts = !_(self.action.context).isEmpty() - ? [self.action.context] : []; - controller.on_loaded.add({ - callback: function () { - controller.do_search(domains, contexts, []); - }, - position: 'last', - unique: true - }); - } - view_promise = controller.start(); - $.when(view_promise).then(function() { - self.on_controller_inited(view_type, controller); - }); - this.views[view_type].controller = controller; - } - - - if (this.searchview) { - if (view.controller.searchable === false) { - this.searchview.hide(); - } else { - this.searchview.show(); - } - } - - this.$element - .find('.views-switchers button').removeAttr('disabled') - .filter('[data-view-type="' + view_type + '"]') - .attr('disabled', true); - - for (var view_name in this.views) { - if (!this.views.hasOwnProperty(view_name)) { continue; } - if (this.views[view_name].controller) { - if (view_name === view_type) { - $.when(view_promise).then(this.views[view_name].controller.do_show); - } else { - this.views[view_name].controller.do_hide(); - } - } - } - return view_promise; - }, - /** - * Event launched when a controller has been inited. - * - * @param {String} view_type type of view - * @param {String} view the inited controller - */ - on_controller_inited: function(view_type, view) { - }, - /** - * Sets up the current viewmanager's search view. - * - * @param 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; - if (this.searchview) { - this.searchview.stop(); - } - this.searchview = new openerp.base.SearchView(this, this.element_id + "_search", this.dataset, view_id, search_defaults); - if (this.flags.search_view === false) { - this.searchview.hide(); - } - this.searchview.on_search.add(function(domains, contexts, groupbys) { - var controller = self.views[self.active_view].controller; - controller.do_search.call(controller, domains, contexts, groupbys); - }); - return this.searchview.start(); - }, - /** - * Called when one of the view want to execute an action - */ - on_action: function(action) { - }, - on_create: function() { - }, - on_remove: function() { - }, - on_edit: function() { - } -}); - -openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({ - init: function(parent, action) { - this.session = parent.session; - this.action = action; - var dataset; - if (!action.res_id) { - dataset = new openerp.base.DataSetSearch(this, action.res_model, action.context, action.domain); - } else { - this.action.flags.search_view = false; - dataset = new openerp.base.DataSetStatic(this, action.res_model, action.context, [action.res_id]); - dataset.index = 0; - } - this._super(parent, dataset, action.views); - this.action = action; - this.flags = this.action.flags || {}; - if (action.res_model == 'board.board' && action.views.length == 1 && action.views) { - // Not elegant but allows to avoid flickering of SearchView#do_hide - this.flags.search_view = this.flags.pager = this.flags.sidebar = this.flags.action_buttons = false; - } - }, - start: function() { - var inital_view_loaded = this._super(); - - var search_defaults = {}; - _.each(this.action.context, function (value, key) { - var match = /^search_default_(.*)$/.exec(key); - if (match) { - search_defaults[match[1]] = value; - } - }); - - if (this.flags.search_view !== false) { - // init search view - var searchview_id = this.action.search_view_id && this.action.search_view_id[0]; - - var searchview_loaded = this.setup_search_view( - searchview_id || false, search_defaults); - - // schedule auto_search - if (searchview_loaded != null && this.action['auto_search']) { - $.when(searchview_loaded, inital_view_loaded) - .then(this.searchview.do_search); - } - } - }, - on_mode_switch: function (view_type) { - return $.when( - this._super(view_type), - this.shortcut_check(this.views[view_type])); - }, - shortcut_check : function(view) { - var self = this; - var grandparent = this.widget_parent && this.widget_parent.widget_parent; - // display shortcuts if on the first view for the action - var $shortcut_toggle = this.$element.find('.oe-shortcut-toggle'); - if (!(grandparent instanceof openerp.base.WebClient) || - !(view.view_type === this.views_src[0].view_type - && view.view_id === this.views_src[0].view_id)) { - $shortcut_toggle.hide(); - return; - } - $shortcut_toggle.removeClass('oe-shortcut-remove').show(); - if (_(this.session.shortcuts).detect(function (shortcut) { - return shortcut.res_id === self.session.active_id; })) { - $shortcut_toggle.addClass("oe-shortcut-remove"); - } - this.shortcut_add_remove(); - }, - shortcut_add_remove: function() { - var self = this; - var $shortcut_toggle = this.$element.find('.oe-shortcut-toggle'); - $shortcut_toggle - .unbind("click") - .click(function() { - if ($shortcut_toggle.hasClass("oe-shortcut-remove")) { - $(self.session.shortcuts.binding).trigger('remove-current'); - $shortcut_toggle.removeClass("oe-shortcut-remove"); - } else { - $(self.session.shortcuts.binding).trigger('add', { - 'user_id': self.session.uid, - 'res_id': self.session.active_id, - 'resource': 'ir.ui.menu', - 'name': self.action.name - }); - $shortcut_toggle.addClass("oe-shortcut-remove"); - } - }); - } -}); - -openerp.base.Sidebar = openerp.base.Widget.extend({ - init: function(parent, element_id) { - this._super(parent, element_id); - this.items = {}; - this.sections = {}; - }, - start: function() { - this._super(this); - var self = this; - this.$element.html(QWeb.render('Sidebar')); - this.$element.find(".toggle-sidebar").click(function(e) { - self.do_toggle(); - }); - }, - add_toolbar: function(toolbar) { - var self = this; - _.each([['print', "Reports"], ['action', "Actions"], ['relate', "Links"]], function(type) { - var items = toolbar[type[0]]; - if (items.length) { - for (var i = 0; i < items.length; i++) { - items[i] = { - label: items[i]['name'], - action: items[i], - classname: 'oe_sidebar_' + type[0] - } - } - self.add_section(type[0], type[1], items); - } - }); - }, - add_section: function(code, name, items) { - // For each section, we pass a name/label and optionally an array of items. - // If no items are passed, then the section will be created as a custom section - // returning back an element_id to be used by a custom controller. - // Else, the section is a standard section with items displayed as links. - // An item is a dictonary : { - // label: label to be displayed for the link, - // action: action to be launch when the link is clicked, - // callback: a function to be executed when the link is clicked, - // classname: optional dom class name for the line, - // title: optional title for the link - // } - // Note: The item should have one action or/and a callback - var self = this, - section_id = _.uniqueId(this.element_id + '_section_' + code + '_'); - if (items) { - for (var i = 0; i < items.length; i++) { - items[i].element_id = _.uniqueId(section_id + '_item_'); - this.items[items[i].element_id] = items[i]; - } - } - var $section = $(QWeb.render("Sidebar.section", { - section_id: section_id, - name: name, - classname: 'oe_sidebar_' + code, - items: items - })); - if (items) { - $section.find('a.oe_sidebar_action_a').click(function() { - var item = self.items[$(this).attr('id')]; - if (item.callback) { - item.callback(); - } - if (item.action) { - var ids = self.widget_parent.get_selected_ids(); - if (ids.length == 0) { - //TODO niv: maybe show a warning? - return false; - } - var additional_context = { - active_id: ids[0], - active_ids: ids, - active_model: self.widget_parent.dataset.model - }; - self.rpc("/base/action/load", { - action_id: item.action.id, - context: additional_context - }, function(result) { - result.result.context = _.extend(result.result.context || {}, - additional_context); - result.result.flags = result.result.flags || {}; - result.result.flags.new_window = true; - self.do_action(result.result); - }); - } - return false; - }); - } - $section.appendTo(this.$element.find('div.sidebar-actions')); - this.sections[code] = $section; - return section_id; - }, - do_fold: function() { - this.$element.addClass('closed-sidebar').removeClass('open-sidebar'); - }, - do_unfold: function() { - this.$element.addClass('open-sidebar').removeClass('closed-sidebar'); - }, - do_toggle: function() { - this.$element.toggleClass('open-sidebar closed-sidebar'); - } -}); - -openerp.base.TranslateDialog = openerp.base.Dialog.extend({ - dialog_title: _t("Translations"), - init: function(view) { - // TODO fme: should add the language to fields_view_get because between the fields view get - // and the moment the user opens the translation dialog, the user language could have been changed - this.view_language = view.session.user_context.lang; - this['on_button' + _t("Save")] = this.on_button_Save; - this['on_button' + _t("Close")] = this.on_button_Close; - this._super(view, { - width: '80%', - height: '80%' - }); - this.view = view; - this.view_type = view.fields_view.type || ''; - this.$fields_form = null; - this.$view_form = null; - this.$sidebar_form = null; - this.translatable_fields_keys = _.map(this.view.translatable_fields || [], function(i) { return i.name }); - this.languages = null; - this.languages_loaded = $.Deferred(); - (new openerp.base.DataSetSearch(this, 'res.lang', this.view.dataset.get_context(), - [['translatable', '=', '1']])).read_slice(['code', 'name'], { sort: 'id' }, this.on_languages_loaded); - }, - start: function() { - var self = this; - this._super(); - $.when(this.languages_loaded).then(function() { - self.$element.html(QWeb.render('TranslateDialog', { widget: self })); - self.$element.tabs(); - if (!(self.view.translatable_fields && self.view.translatable_fields.length)) { - self.hide_tabs('fields'); - self.select_tab('view'); - } - self.$fields_form = self.$element.find('.oe_translation_form'); - self.$fields_form.find('.oe_trad_field').change(function() { - $(this).toggleClass('touched', ($(this).val() != $(this).attr('data-value'))); - }); - }); - return this; - }, - on_languages_loaded: function(langs) { - this.languages = langs; - this.languages_loaded.resolve(); - }, - do_load_fields_values: function(callback) { - var self = this, - deffered = []; - this.$fields_form.find('.oe_trad_field').val('').removeClass('touched'); - _.each(self.languages, function(lg) { - var deff = $.Deferred(); - deffered.push(deff); - var callback = function(values) { - _.each(self.translatable_fields_keys, function(f) { - self.$fields_form.find('.oe_trad_field[name="' + lg.code + '-' + f + '"]').val(values[0][f] || '').attr('data-value', values[0][f] || ''); - }); - deff.resolve(); - } - if (lg.code === self.view_language) { - var values = {}; - _.each(self.translatable_fields_keys, function(field) { - values[field] = self.view.fields[field].get_value(); - }); - callback([values]); - } else { - self.rpc('/base/dataset/get', { - model: self.view.dataset.model, - ids: [self.view.datarecord.id], - fields: self.translatable_fields_keys, - context: self.view.dataset.get_context({ - 'lang': lg.code - })}, callback); - } - }); - $.when.apply(null, deffered).then(callback); - }, - show_tabs: function() { - for (var i = 0; i < arguments.length; i++) { - this.$element.find('ul.oe_translate_tabs li a[href$="' + arguments[i] + '"]').parent().show(); - } - }, - hide_tabs: function() { - for (var i = 0; i < arguments.length; i++) { - this.$element.find('ul.oe_translate_tabs li a[href$="' + arguments[i] + '"]').parent().hide(); - } - }, - select_tab: function(name) { - this.show_tabs(name); - var index = this.$element.find('ul.oe_translate_tabs li a[href$="' + arguments[i] + '"]').parent().index() - 1; - this.$element.tabs('select', index); - }, - open: function(field) { - var self = this, - sup = this._super; - $.when(this.languages_loaded).then(function() { - if (self.view.translatable_fields && self.view.translatable_fields.length) { - self.do_load_fields_values(function() { - sup.call(self); - if (field) { - // TODO: focus and scroll to field - } - }); - } else { - sup.call(self); - } - }); - }, - on_button_Save: function() { - var trads = {}, - self = this; - self.$fields_form.find('.oe_trad_field.touched').each(function() { - var field = $(this).attr('name').split('-'); - if (!trads[field[0]]) { - trads[field[0]] = {}; - } - trads[field[0]][field[1]] = $(this).val(); - }); - _.each(trads, function(data, code) { - if (code === self.view_language) { - _.each(data, function(value, field) { - self.view.fields[field].set_value(value); - }); - } else { - self.view.dataset.write(self.view.datarecord.id, data, { 'lang': code }); - } - }); - this.close(); - }, - on_button_Close: function() { - this.close(); - } -}); - -openerp.base.View = openerp.base.Widget.extend({ - set_default_options: function(options) { - this.options = options || {}; - _.defaults(this.options, { - // All possible views options should be defaulted here - sidebar_id: null, - sidebar: true, - action: null, - action_views_ids: {} - }); - }, - open_translate_dialog: function(field) { - if (!this.translate_dialog) { - this.translate_dialog = new openerp.base.TranslateDialog(this).start(); - } - this.translate_dialog.open(field); - }, - /** - * Fetches and executes the action identified by ``action_data``. - * - * @param {Object} action_data the action descriptor data - * @param {String} action_data.name the action name, used to uniquely identify the action to find and execute it - * @param {String} [action_data.special=null] special action handlers (currently: only ``'cancel'``) - * @param {String} [action_data.type='workflow'] the action type, if present, one of ``'object'``, ``'action'`` or ``'workflow'`` - * @param {Object} [action_data.context=null] additional action context, to add to the current context - * @param {openerp.base.DataSet} dataset a dataset object used to communicate with the server - * @param {Object} [record_id] the identifier of the object on which the action is to be applied - * @param {Function} on_closed callback to execute when dialog is closed or when the action does not generate any result (no new action) - */ - execute_action: function (action_data, dataset, record_id, on_closed) { - var self = this; - var handler = function (r) { - var action = r.result; - if (action && action.constructor == Object) { - action.context = action.context || {}; - _.extend(action.context, { - active_id: record_id || false, - active_ids: [record_id || false], - active_model: dataset.model - }); - self.do_action(action, on_closed); - } else if (on_closed) { - on_closed(action); - } - }; - - var context = new openerp.base.CompoundContext(dataset.get_context(), action_data.context || {}); - - if (action_data.special) { - 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); - } else if (action_data.type=="action") { - return this.rpc('/base/action/load', { action_id: parseInt(action_data.name, 10), context: context }, handler); - } else { - return dataset.exec_workflow(record_id, action_data.name, handler); - } - }, - /** - * Directly set a view to use instead of calling fields_view_get. This method must - * be called before start(). When an embedded view is set, underlying implementations - * of openerp.base.View must use the provided view instead of any other one. - * - * @param embedded_view A view. - */ - set_embedded_view: function(embedded_view) { - this.embedded_view = embedded_view; - this.options.sidebar = false; - }, - do_switch_view: function(view) { - }, - set_common_sidebar_sections: function(sidebar) { - sidebar.add_section('customize', "Customize", [ - { - label: "Manage Views", - callback: this.on_sidebar_manage_view, - title: "Manage views of the current object" - }, { - label: "Edit Workflow", - callback: this.on_sidebar_edit_workflow, - title: "Manage views of the current object", - classname: 'oe_hide oe_sidebar_edit_workflow' - }, { - label: "Customize Object", - callback: this.on_sidebar_customize_object, - title: "Manage views of the current object" - } - ]); - sidebar.add_section('other', "Other Options", [ - { - label: "Import", - callback: this.on_sidebar_import - }, { - label: "Export", - callback: this.on_sidebar_export - }, { - label: "Translate", - callback: this.on_sidebar_translate, - classname: 'oe_sidebar_translate oe_hide' - }, { - label: "View Log", - callback: this.on_sidebar_view_log, - classname: 'oe_hide oe_sidebar_view_log' - } - ]); - }, - on_sidebar_manage_view: function() { - if (this.fields_view && this.fields_view.arch) { -// $('<xmp>' + openerp.base.json_node_to_xml(this.fields_view.arch, true) + '</xmp>').dialog({ width: '95%', height: 600}); - var view_editor = new openerp.base.ViewEditor(this, this.$element, this.dataset, this.fields_view.arch) - view_editor.start(); - } else { - this.notification.warn("Manage Views", "Could not find current view declaration"); - } - }, - on_sidebar_edit_workflow: function() { - this.log('Todo'); - }, - on_sidebar_customize_object: function() { - this.log('Todo'); - }, - on_sidebar_import: function() { - }, - on_sidebar_export: function() { - var export_view = new openerp.base.DataExport(this, this.dataset); - export_view.start(); - }, - on_sidebar_translate: function() { - this.open_translate_dialog(); - }, - on_sidebar_view_log: function() { - } -}); - -/** - * Registry for all the main views - */ -openerp.base.views = new openerp.base.Registry(); - -openerp.base.json_node_to_xml = function(node, single_quote, indent) { - // For debugging purpose, this function will convert a json node back to xml - // Maybe usefull for xml view editor - if (typeof(node.tag) !== 'string' || !node.children instanceof Array || !node.attrs instanceof Object) { - throw("Node a json node"); - } - indent = indent || 0; - var sindent = new Array(indent + 1).join('\t'), - r = sindent + '<' + node.tag; - for (var attr in node.attrs) { - var vattr = node.attrs[attr]; - if (typeof(vattr) !== 'string') { - // domains, ... - vattr = JSON.stringify(vattr); - } - vattr = vattr.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); - if (single_quote) { - vattr = vattr.replace(/"/g, "'"); - } - r += ' ' + attr + '="' + vattr + '"'; - } - if (node.children.length) { - r += '>\n'; - var childs = []; - for (var i = 0, ii = node.children.length; i < ii; i++) { - childs.push(openerp.base.json_node_to_xml(node.children[i], single_quote, indent + 1)); - } - r += childs.join('\n'); - r += '\n' + sindent + '</' + node.tag + '>'; - return r; - } else { - return r + '/>'; - } -} - -}; - -// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/base/static/src/xml/base.xml b/addons/base/static/src/xml/base.xml deleted file mode 100644 index 48b6473feec..00000000000 --- a/addons/base/static/src/xml/base.xml +++ /dev/null @@ -1,1401 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- vim:fdl=1: ---> -<templates id="template" xml:space="preserve"> -<t t-name="Interface"> - <div id="oe_loading" class="loading"></div> - <div id="oe_notification" class="oe_notification"> - <div id="oe_notification_default"> - <a class="ui-notify-cross ui-notify-close" href="#">x</a> - <h1>#{title}</h1> - <p>#{text}</p> - </div> - <div id="oe_notification_alert" class="ui-state-error"> - <a class="ui-notify-cross ui-notify-close" href="#">x</a> - <span style="float:left; margin:2px 5px 0 0;" class="ui-icon ui-icon-alert"></span> - <h1>#{title}</h1> - <p>#{text}</p> - </div> - </div> - <table border="0" cellpadding="0" cellspacing="0" width="100%" height="100%" class="main_table"> - <tr> - <td colspan="2" valign="top"> - <div id="oe_header" class="header"></div> - <div id="oe_menu" class="menu"></div> - </td> - </tr> - <tr> - <td valign="top" class="login-container" colspan="2"> - <div id="oe_login" class="login"></div> - </td> - </tr> - <tr class="db_options_row"> - <td valign="top" class="db_container"> - <div id="oe_database" class="database"></div> - </td> - <td valign="top"> - <div id="oe_db_options"></div> - </td> - </tr> - <tr> - <td valign="top" id="oe_secondary_menu" class="secondary_menu"> - </td> - <td valign="top"> - <div id="oe_app" class="oe-application"> - </div> - </td> - </tr> - <tr> - <td colspan="2"> - <div id="oe_footer" class="oe_footer"> - <p class="oe_footer_powered">Powered by <a href="http://www.openerp.com">openerp.com</a>.</p> - </div> - </td> - </tr> - </table> -</t> -<t t-name="Loading"> - Loading... -</t> -<t t-name="Database"> - <ul class="db_options" style="padding: 0px; display: inline;"> - <li id="db-create">Create</li> - <li id="db-drop">Drop</li> - <li id="db-backup">Backup</li> - <li id="db-restore">Restore</li> - <li id="db-change-password">Password</li> - <li id="back-to-login">Back to Login</li> - </ul> -</t> -<t t-name="Database.CreateDB"> - <form name="create_db_form" class="oe_forms" method="POST"> - <table width="100%"> - <tr> - <td class="option_string"> - CREATE DATABASE - </td> - </tr> - </table> - <table align="center" class="db_option_table"> - <tr> - <td><label for="super_admin_pwd">Master password:</label></td> - <td><input type="password" name="super_admin_pwd" class="required" value="admin"/></td> - </tr> - <tr> - <td><label for="db_name">New database name:</label></td> - <td><input type="text" name="db_name" class="required"/></td> - </tr> - <tr> - <td><label for="demo_data">Load Demonstration data:</label></td> - <td><input type="checkbox" name="demo_data"/></td> - </tr> - <tr> - <td><label for="db_lang">Default language:</label></td> - <td> - <select name="db_lang" t-if="lang_list"> - <t t-foreach="lang_list" t-as="lang"> - <option t-att-value="lang[0]" t-att-selected="lang[0] === 'en_US' ? 'selected' : undefined"><t t-esc="lang[1]"/></option> - </t> - </select> - </td> - </tr> - <tr> - <td><label for="create_admin_pwd">Admin password:</label></td> - <td><input type="password" name="create_admin_pwd" class="required"/></td> - </tr> - <tr> - <td><label for="create_confirm_pwd">Confirm password:</label></td> - <td><input type="password" name="create_confirm_pwd" class="required" - equalTo="input[name=create_admin_pwd]"/></td> - </tr> - <tr> - <td colspan="2" align="right"><input type="submit" value="Create"/></td> - </tr> - </table> - </form> -</t> -<t t-name="DropDB"> - <form name="drop_db_form" class="oe_forms" method="POST"> - <table width="100%"> - <tr> - <td class="option_string"> - DROP DATABASE - </td> - </tr> - </table> - <table align="center" class="db_option_table"> - <tr> - <td><label for="drop_db">Database:</label></td> - <td> - <select t-if="db_list" name="drop_db" autofocus="autofocus"> - <t t-foreach="db_list" t-as="db"> - <option t-att-value="db"><t t-esc="db"/></option> - </t> - </select> - </td> - </tr> - <tr> - <td><label for="drop_password">Master Password:</label></td> - <td><input type="password" name="drop_pwd" class="required"/></td> - </tr> - <tr> - <td colspan="2" align="right"><input type="submit" value="Drop"/></td> - </tr> - </table> - </form> -</t> -<t t-name="BackupDB"> - <form name="backup_db_form" class="oe_forms" method="POST" target="backup-target" - action="/base/database/backup"> - <input type="hidden" name="token"/> - <table width="100%"> - <tr> - <td class="option_string"> - BACKUP DATABASE - </td> - </tr> - </table> - <table align="center" class="db_option_table"> - <tr> - <td><label for="backup_db">Database:</label></td> - <td> - <select t-if="db_list" name="backup_db" autofocus="autofocus"> - <t t-foreach="db_list" t-as="db"> - <option t-att-value="db"><t t-esc="db"/></option> - </t> - </select> - </td> - </tr> - <tr> - <td><label for="backup_pwd">Master Password:</label></td> - <td><input type="password" name="backup_pwd" class="required"/></td> - </tr> - <tr> - <td colspan="2" align="right"><input type="submit" value="Backup"/></td> - </tr> - </table> - </form> -</t> -<t t-name="RestoreDB"> - <form name="restore_db_form" class="oe_forms" method="POST"> - <table width="100%"> - <tr> - <td class="option_string"> - RESTORE DATABASE - </td> - </tr> - </table> - <table align="center" class="db_option_table"> - <tr> - <td><label for="restore_db">File:</label></td> - <td><input type="file" name="db_file" class="required" - autofocus="autofocus"/></td> - </tr> - <tr> - <td><label for="restore_pwd">Master Password:</label></td> - <td><input type="password" name="restore_pwd" class="required"/></td> - </tr> - <tr> - <td><label for="new_db">New database name:</label></td> - <td><input type="text" name="new_db" class="required"/></td> - </tr> - <tr> - <td colspan="2" align="right"><input type="submit" value="Restore"/></td> - </tr> - </table> - </form> -</t> -<t t-name="Change_DB_Pwd"> - <form name="change_pwd_form" class="oe_forms" method="POST"> - <table width="100%"> - <tr> - <td class="option_string"> - CHANGE MASTER PASSWORD - </td> - </tr> - </table> - <table align="center" class="db_option_table"> - <tr> - <td><label for="old_pwd">Master password:</label></td> - <td><input type="password" name="old_pwd" class="required" - minlength="1" autofocus="autofocus"/></td> - </tr> - <tr> - <td><label for="new_pwd">New master password:</label></td> - <td><input type="password" name="new_pwd" class="required" - minlength="1"/></td> - </tr> - <tr> - <td><label for="confirm_pwd">Confirm new master password:</label></td> - <td><input type="password" name="confirm_pwd" class="required" - equalTo="input[name=new_pwd]" minlength="1"/></td> - </tr> - <tr> - <td colspan="2" align="right"><input type="submit" value="Change Password"/></td> - </tr> - </table> - </form> -</t> -<t t-name="Login"> - <form class="oe_forms"> - <fieldset> - <legend style=""> - <img src="/base/static/src/img/stock_person.png" alt="" /> - </legend> - <div class="oe_box2"> - <table align="center" cellspacing="2px" cellpadding="0"> - <tr> - <td><label for="db">Database:</label></td> - <td> - <t t-if="!db_list"> - <input type="text" name="db" t-att-value="selected_db || ''" autofocus="true"/> - </t> - <t t-if="db_list"> - <select name="db"> - <t t-foreach="db_list" t-as="db"> - <t t-if="selected_db === db"> - <option t-att-value="db" selected="true"> - <t t-esc="db"/></option> - </t> - <t t-if="selected_db !== db"> - <option t-att-value="db"><t t-esc="db"/></option> - </t> - </t> - </select> - </t> - </td> - </tr> - <tr> - <td><label for="login">User:</label></td> - <td><input type="text" name="login" - t-att-value="selected_login || ''" autofocus="true"/></td> - </tr> - <tr> - <td><label for="password">Password:</label></td> - <td><input type="password" name="password" - t-att-value="selected_password || ''"/></td> - </tr> - <tr> - <td></td> - <td> - <button type="button" id="oe-db-config">Database</button> - <button type="submit" name="submit">Login</button> - </td> - </tr> - </table> - </div> - </fieldset> - <div class="login_error_message">Bad username or password</div> - </form> - <div class="oe_login_right_pane"> - <p>We think that daily job activities can be more intuitive, efficient, automated, .. and even fun.</p> - <h3>OpenERP's vision to be:</h3> - - <table cellpadding="0" cellspacing="0" width="100%" style="border:none;"> - <tbody> - <tr> - <td> - <img src="/base/static/src/img/product.png"/> - </td> - <td> - <strong>Full featured</strong><br /> - Today's enterprise challenges are multiple. We provide one module for each need. - </td> - </tr> - <tr> - <td> - <img src="/base/static/src/img/accessories-archiver.png"/> - </td> - <td> - <strong>Open Source</strong><br /> - To Build a great product, we rely on the knowledge of thousands of contributors. - </td> - </tr> - <tr> - <td> - <img src="/base/static/src/img/partner.png" /> - </td> - <td> - <strong>User Friendly</strong><br /> - In order to be productive, people need clean and easy to use interface. - </td> - </tr> - </tbody> - </table> - - </div> -</t> -<t t-name="Header"> - <div> - <a t-att-href="'/' + widget.qs" class="company_logo_link"> - <div class="company_logo" /> - </a> - </div> -</t> -<t t-name="Header-content"> - <h1 class="header_title"> - <span class="database"><t t-esc="widget.session.db"/></span> - <t t-esc="widget.session.login"/> <br/> - <small class="username">rpc_session_id: <t t-esc="widget.session.session_id"/></small> - </h1> - <div class="header_corner"> - <ul class="block"> - <li> - <a href="#home" title="Home" class="home"><img src="/base/static/src/img/header-home.png" width="16" height="16" border="0"/></a> - </li> - <li> - <a href="#requests" title="Requests" class="requests"><img src="/base/static/src/img/header-requests.png" width="16" height="16" border="0"/><small>1</small></a> - </li> - <li class="preferences"> - <a href="#preferences" title="Preferences" class="preferences"><img src="/base/static/src/img/header-preferences.png" width="16" height="16" border="0"/></a> - </li> - <li> - <a href="#about" title="About" class="about"><img src="/base/static/src/img/header-about.png" width="16" height="16" border="0"/></a> - </li> - <li> - <a href="http://doc.openerp.com/v6.0/book?version=$version" title="Help" target="_blank" class="help"><img src="/base/static/src/img/header-help.png" width="16" height="16" border="0"/></a> - </li> - </ul> - <div class="block"> - <a href="#logout" class="logout">LOGOUT</a> - </div> - - </div> - <div class="oe-shortcuts"> </div> -</t> -<ul t-name="Shortcuts"> - <li t-foreach="shortcuts" t-as="shortcut" - t-att-data-id="shortcut.res_id" - t-att-data-shortcut-id="shortcut.id" - ><t t-esc="shortcut.name"/></li> -</ul> -<t t-name="Menu"> - <table align="center"> - <tr> - <t t-foreach="data.children" t-as="menu"> - <td> - <a href="#" t-att-data-menu="menu.id"> - <t t-esc="menu.name"/> - </a> - </td> - </t> - </tr> - </table> -</t> -<t t-name="Menu.secondary"> - <div style="display: none" class="menu_accordion" t-att-data-menu-parent="menu.id"> - <t t-foreach="menu.children" t-as="menu"> - <t t-set="header">h3</t> - <t t-call="Menu.secondary.children"/> - </t> - </div> -</t> -<t t-name="Menu.secondary.children"> - <<t t-esc="header"/>> - <a href="#" t-attf-id="menu_#{menu.id}"> - <span><t t-esc="menu.name"/></span> - </a> - </<t t-esc="header"/>> - <div class="menu_content"> - <t t-foreach="menu.children" t-as="menu"> - <t t-if="!menu.children.length"> - <a href="#" class="leaf" t-att-data-menu="menu.id"> - <span><t t-esc="menu.name"/></span> - </a> - </t> - <t t-if="menu.children.length"> - <div class="submenu_accordion"> - <t t-call="Menu.secondary.children"> - <t t-set="header">h4</t> - </t> - </div> - </t> - </t> - </div> -</t> -<t t-name="ViewManager"> - <table class="view-manager-main-table"> - <tr> - <td class="view-manager-main-content"> - <a class="oe-shortcut-toggle" title="Add / Remove Shortcut..." - href="javascript: void(0)"> </a> - <div class="oe_vm_switch"> - <t t-if="views.length != 1" t-foreach="views" t-as="view"> - <button type="button" t-att-data-view-type="view.view_type"> - <t t-esc="view.view_type"/> - </button> - </t> - </div> - <div t-attf-id="#{prefix}_search" t-opentag="true"/> - <t t-foreach="views" t-as="view"> - <div t-attf-id="#{prefix}_view_#{view.view_type}"/> - </t> - </td> - <td class="view-manager-main-sidebar" height="100%"> - <t t-foreach="views" t-as="view"> - <div t-attf-id="#{prefix}_sidebar_#{view.view_type}" class="sidebar-main-div closed-sidebar" style="display: none"/> - </t> - </td> - </tr> - </table> -</t> -<t t-name="Sidebar"> - <a class="toggle-sidebar"></a> - <div class="sidebar-content"> - <div class="sidebar-actions"> - </div> - </div> -</t> -<t t-name="Sidebar.section"> - <h2><t t-esc="name"/></h2> - <div t-att-id="section_id" t-att-class="classname"> - <ul t-if="items"> - <li t-foreach="items" t-as="item" t-att-class="item.classname"> - <a class="oe_sidebar_action_a" t-att-id="item.element_id" t-att-title="item.title" href="#"> - <t t-esc="item.label"/> - </a> - </li> - </ul> - </div> -</t> -<t t-name="TranslateDialog"> - <ul class="oe_translate_tabs"> - <li><a t-attf-href="##{widget.element_id}_fields">Fields</a></li> - <li><a t-attf-href="##{widget.element_id}_view">View labels</a></li> - <li><a t-attf-href="##{widget.element_id}_sidebar">Sidebar Relates</a></li> - </ul> - <div t-attf-id="#{widget.element_id}_fields"> - <table t-if="widget.view.translatable_fields" class="oe_frame oe_forms oe_translation_form" border="0" cellpadding="0" cellspacing="0" width="100%"> - <tr> - <td class="oe_form_separator" width="1%" nowrap="nowrap"> - <div class="separator horizontal">Field</div> - </td> - <th t-foreach="widget.languages" align="left"> - <div class="separator horizontal"><t t-esc="name"/></div> - </th> - </tr> - <tr t-foreach="widget.view.translatable_fields" t-as="field"> - <td class="oe_form_frame_cell" width="1%" nowrap="nowrap"> - <label class="oe_label"><t t-esc="field.string"/>:</label> - </td> - <td t-foreach="widget.languages" t-as="lg" class="oe_form_frame_cell"> - <input t-if="field.type == 'char'" type="text" t-attf-name="#{lg.code}-#{field.name}" value="" data-value="" class="oe_trad_field" style="width: 100%"/> - <textarea t-if="field.type == 'text'" t-attf-name="#{lg.code}-#{field.name}" data-value="" class="oe_trad_field" style="width: 100%"></textarea> - </td> - </tr> - </table> - </div> - <div t-attf-id="#{widget.element_id}_view"> - Translate view - </div> - <div t-attf-id="#{widget.element_id}_sidebar"> - Translate sidebar - </div> -</t> -<t t-name="TreeView"> - <h2 class="oe_view_title"><t t-esc="title"/></h2> - <select t-if="toolbar" style="width: 30%"> - </select> - <table class="oe-treeview-table"> - <thead> - <tr> - <th t-foreach="fields_view" t-as="field" - t-if="!field.attrs.modifiers.tree_invisible" - class="treeview-header"> - <t t-esc="fields[field.attrs.name].string" /> - </th> - </tr> - </thead> - <tbody> - </tbody> - </table> -</t> -<tr t-name="TreeView.rows" - t-foreach="records" t-as="record" - t-att-id="'treerow_' + record.id" - t-att-data-id="record.id" t-att-data-level="level + 1"> - <t t-set="children" t-value="record[children_field]"/> - <t t-set="has_children" t-value="children and children.length"/> - - <td t-foreach="fields_view" t-as="field" - t-if="!field.attrs.modifiers.tree_invisible" - t-att-data-id="record.id" - t-att-style="!field_index ? 'background-position: ' + 19*level + 'px; padding-left: ' + 19*level + 'px' : undefined" - t-att-class="!field_index and has_children ? 'treeview-tr' : 'treeview-td'"> - <span t-if="!field.attrs.modifiers.invisible"> - <t t-esc="render(record[field.attrs.name], fields[field.attrs.name])" /> - </span> - </td> -</tr> -<table t-name="ListView" class="oe-listview-content"> - <t t-set="columns_count" t-value="visible_columns.length + (options.selectable ? 1 : 0) + (options.deletable ? 1 : 0)"/> - <thead class="ui-widget-header"> - <tr t-if="options.action_buttons !== false or options.pager !== false"> - <th t-att-colspan="columns_count"> - <table> - <tr> - <td t-if="options.action_buttons !== false" class="oe-actions"> - <button type="button" class="oe-list-add" - t-if="options.addable"> - <t t-esc="options.addable"/> - </button> - <button type="button" class="oe-list-delete" - t-if="options.selectable and options.deletable"> - Delete - </button> - </td> - <th t-if="options.pager !== false" class="oe-list-pager"> - <button type="button" disabled="disabled" - data-pager-action="first">First</button> - <button type="button" disabled="disabled" - data-pager-action="previous" - ><</button> - - <span class="oe-pager-state"> - </span> - - <button type="button" disabled="disabled" - data-pager-action="next">></button> - <button type="button" disabled="disabled" - data-pager-action="last">Last</button> - </th> - </tr> - </table> - </th> - </tr> - <tr t-if="options.header"> - <t t-foreach="columns" t-as="column"> - <th t-if="column.meta"> - <t t-esc="column.string"/> - </th> - </t> - <th t-if="options.selectable" width="1"/> - <t t-foreach="columns" t-as="column"> - <th t-if="!column.meta and column.invisible !== '1'" t-att-data-id="column.id" - t-att-class="((options.sortable and column.tag !== 'button') ? 'oe-sortable' : null)"> - <t t-if="column.tag !== 'button'" - ><t t-esc="column.string"/></t> - </th> - </t> - <th t-if="options.deletable" width="1"/> - </tr> - </thead> - <tfoot class="ui-widget-header"> - <tr> - <td t-if="options.selectable"/> - <td t-foreach="aggregate_columns" t-as="column" class="oe-list-footer oe-number" - t-att-data-field="column.id" t-att-title="column.label"> - </td> - <td t-if="options.deletable"/> - </tr> - </tfoot> -</table> -<t t-name="ListView.rows" t-foreach="records.length" t-as="index"> - <t t-call="ListView.row"> - <t t-set="record" t-value="records.at(index)"/> - <t t-set="row_parity" t-value="index_parity"/> - </t> -</t> -<tr t-name="ListView.row" t-att-class="row_parity" - t-att-data-id="record.get('id')"> - <t t-foreach="columns" t-as="column"> - <td t-if="column.meta"> - - </td> - </t> - <t t-if="options.radio"> - <th t-if="options.selectable" class="oe-record-selector" width="1"> - <input type="radio" name ="radiogroup"/> - </th> - </t> - <t t-if="!options.radio"> - <th t-if="options.selectable" class="oe-record-selector" width="1"> - <input type="checkbox"/> - </th> - </t> - - - <t t-foreach="columns" t-as="column"> - <t t-set="align" t-value="column.type === 'integer' or column.type == 'float'"/> - <td t-if="!column.meta and column.invisible !== '1'" t-att-title="column.help" - t-att-class="'oe-field-cell' + (align ? ' oe-number' : '')" - t-att-data-field="column.id"> - <t t-raw="render_cell(record.toForm().data, column)"/> - </td> - </t> - <td t-if="options.deletable" class='oe-record-delete' width="1"> - <button type="button" name="delete">♻</button> - </td> -</tr> -<t t-name="ListView.row.form"> - <t t-raw="frame.render()"/> -</t> -<t t-name="FormView"> - <div class="oe_form_header" t-att-id="view.element_id + '_header'"> - <h2 class="oe_view_title"><t t-esc="view.fields_view.arch.attrs.string"/> <button t-if="view.session.debug" class="oe_get_xml_view">View#<t t-esc="view.fields_view.view_id"/></button></h2> - <div class="oe_form_buttons" t-if="view.options.action_buttons !== false"> - <!--<button type="button" class="oe_form_button_save"> - <span class="oe_form_on_update">Save</span> - <span class="oe_form_on_create">Create</span> - </button>--> - <button type="button" class="oe_form_button_save_edit"> - <span class="oe_form_on_update">Save & Edit</span> - <span class="oe_form_on_create">Create & Edit</span> - </button> - <!--<button type="button" class="oe_form_button_cancel">Cancel</button>--> - <button type="button" class="oe_form_button_new">New</button> - </div> - <div class="oe_form_pager" t-if="view.options.pager !== false"> - <button type="button" data-pager-action="first">First</button> - <button type="button" data-pager-action="previous"><<</button> - - <span class="oe_pager_index">0</span> / <span class="oe_pager_count">0</span> - - <button type="button" data-pager-action="next">>></button> - <button type="button" data-pager-action="last">Last</button> - </div> - </div> - <t t-raw="frame.render()"/> -</t> -<t t-name="FormView.sidebar.attachments"> - <div class="oe-sidebar-attachments-toolbar"> - <div class="oe-binary-file-set" style="float: right"> - <form class="oe-binary-form" t-attf-target="#{element_id}_iframe" - method="post" enctype="multipart/form-data" action="/base/binary/upload_attachment"> - <input type="hidden" name="session_id" t-att-value="session.session_id"/> - <input type="hidden" name="callback" t-attf-value="#{element_id}_iframe"/> - <input type="hidden" name="model" t-att-value="view.dataset.model"/> - <input type="hidden" name="id" t-att-value="view.datarecord.id"/> - <button class="button" type="button"> - <img src="/base/static/src/img/throbber.gif" width="16" height="16" style="display: none"/> - <span>Add</span> - </button> - <input type="file" class="oe-binary-file" name="ufile" title="Add attachment" - t-att-onclick="view.datarecord.id ? null : 'alert(\'No record selected ! You can only attach to existing record.\'); return false;'"/> - </form> - <iframe t-attf-id="#{element_id}_iframe" t-attf-name="#{element_id}_iframe" style="display: none"> </iframe> - </div> - </div> - <br style="clear: both"/> - <ul class="oe-sidebar-attachments-items"> - <li t-foreach="attachments" t-as="attachment"> - <t t-if="attachment.type == 'binary'" t-set="attachment.url" t-value="'/base/binary/saveas?session_id=' - + session.session_id + '&model=ir.attachment&id=' + attachment.id - + '&field=datas&fieldname=name&t=' + (new Date().getTime())"/> - <a class="oe-sidebar-attachments-link" t-att-href="attachment.url" target="_blank"> - <t t-esc="attachment.name"/> - </a> - <a href="#" class="oe-sidebar-attachment-delete" t-att-data-id="attachment.id" t-attf-title="Delete the attachment #{attachment.name}"> - <img src="/base/static/src/img/attachments-close.png" width="15" height="15" border="0"/> - </a> - </li> - </ul> -</t> -<t t-name="Widget"> - Unhandled widget - <t t-raw="console.log('Unhandled widget', widget)"/> -</t> -<t t-name="WidgetFrame"> - <table border="0" width="100%" cellpadding="0" cellspacing="0" class="oe_frame oe_forms"> - <tr t-foreach="widget.table" t-as="row"> - <t t-foreach="row" t-as="td"> - <td t-att-colspan="td.colspan gt 1 ? td.colspan : undefined" - t-att-width="td.width" - t-att-nowrap="td.nowrap or td.is_field_m2o? 'true' : undefined" - t-att-valign="td.table ? 'top' : undefined" - t-att-id="td.element_id" - t-attf-class="oe_form_frame_cell #{td.classname}" - > - <t t-raw="td.render()"/> - </td> - </t> - </tr> - </table> -</t> -<t t-name="WidgetNotebook"> - <ul> - <li t-foreach="widget.pages" t-as="page" t-att-id="page.element_tab_id"> - <a t-att-href="'#' + page.element_id"> - <t t-esc="page.string"/> - </a> - </li> - </ul> - <t t-foreach="widget.pages" t-as="page"> - <t t-raw="page.render()"/> - </t> -</t> -<t t-name="WidgetNotebookPage"> - <div t-att-id="widget.element_id"> - <t t-call="WidgetFrame"/> - </div> -</t> -<t t-name="WidgetSeparator"> - <div t-if="widget.orientation !== 'vertical'" t-att-class="'separator ' + widget.orientation"> - <t t-esc="widget.string"/> - </div> -</t> -<t t-name="WidgetLabel"> - <label t-att-for="widget.element_id + '_field'" - t-att-class="'oe_label' + (widget.help ? '_help' : '')" - t-att-title="widget.help"> - <t t-esc="widget.string"/> - <span t-if="widget.help">?</span> - <t t-if="widget.string and widget.node.tag != 'label'">:</t> - </label> -</t> -<t t-name="WidgetParagraph"> - <p class="oe_form_paragraph"><t t-esc="widget.string"/></p> -</t> -<t t-name="FieldChar"> - <input type="text" size="1" - t-att-name="widget.name" - t-att-id="widget.element_id + '_field'" - t-att-class="'field_' + widget.type" - t-attf-style="width: #{widget.field.translate ? '99' : '100'}%" - /> - <img class="oe_field_translate" t-if="widget.field.translate" src="/base/static/src/img/icons/terp-translate.png" width="16" height="16" border="0"/> -</t> -<t t-name="FieldEmail"> - <table cellpadding="0" cellspacing="0" border="0" width="100%"> - <tr> - <td width="100%"> - <t t-call="FieldChar"/> - </td> - <td width="16"> - <button type="button" class="button" title="Send an e-mail with your default e-mail client"> - <img src="/base/static/src/img/icons/terp-mail-message-new.png"/> - </button> - </td> - </tr> - </table> -</t> -<t t-name="FieldUrl"> - <table cellpadding="0" cellspacing="0" border="0" width="100%"> - <tr> - <td width="100%"> - <t t-call="FieldChar"/> - </td> - <td width="16"> - <button type="button" class="button" title="Open this resource"> - <img src="/base/static/src/img/icons/gtk-ok.png"/> - </button> - </td> - </tr> - </table> -</t> -<t t-name="FieldText"> - <textarea rows="6" - t-att-name="widget.name" - t-att-id="widget.element_id + '_field'" - t-att-class="'field_' + widget.type" - t-attf-style="width: #{widget.field.translate ? '99' : '100'}%" - ></textarea> - <img class="oe_field_translate" t-if="widget.field.translate" src="/base/static/src/img/icons/terp-translate.png" width="16" height="16" border="0"/> -</t> -<t t-name="FieldDate"> - <input type="text" size="1" style="width: 100%" - t-att-name="widget.name" - t-att-id="widget.element_id + '_field'" - t-att-class="'field_' + widget.type" - /> -</t> -<t t-name="FieldSelection"> - <select - t-att-name="widget.name" - t-att-id="widget.element_id + '_field'" - t-att-class="'field_' + widget.type" - style="width: 100%"> - <t t-foreach="widget.field_index" t-as="options"> - <option t-att-value="options.ikey"> - <t t-esc="options.label"/> - </option> - </t> - </select> -</t> -<t t-name="FieldMany2One"> - <div t-att-id="widget.element_id" class="oe-m2o"> - <input t-att-id="widget.element_id + '_input'" type="text" size="1" style="width: 100%;"/> - <span class="oe-m2o-drop-down-button" t-att-id="widget.element_id + '_drop_down'"> - <img src="/base/static/src/img/down-arrow.png" /></span> - <span class="oe-m2o-cm-button" t-att-id="widget.name + '_open'"> - <img src="/base/static/src/img/icons/gtk-index.png"/></span> - <div t-att-id="widget.cm_id" class="contextMenu" style="display:none"> - </div> - </div> -</t> -<t t-name="FieldMany2One.context_menu"> - <ul> - <li t-att-id="widget.cm_id + '_open'" style="color:grey">Open...</li> - <li t-att-id="widget.cm_id + '_create'">Create...</li> - <li t-att-id="widget.cm_id + '_search'" class="oe_m2o_menu_item_mandatory">Search...</li> - <t t-set="i" t-value="0"/> - <t t-foreach="widget.related_entries" t-as="entry"> - <li t-att-id="widget.cm_id + '_related_' + i" style="color:grey" class="oe_m2o_menu_item_mandatory"> - ... <t t-esc="(entry[2] || {})['name'] || ''"/> - </li> - <t t-set="i" t-value="i+1"/> - </t> - </ul> -</t> -<t t-name="FieldOne2Many"> - <div t-att-id="widget.element_id"> - </div> -</t> -<t t-name="FieldMany2Many"> - <div t-att-id="widget.list_id"></div> -</t> -<t t-name="FieldReference"> - <table border="0" width="100%" cellpadding="0" cellspacing="0" class="oe_frame oe_forms"> - <tr> - <td t-att-id="widget.selection.element_id" class="oe_form_frame_cell oe_form_selection"> - <t t-raw="widget.selection.render()"/> - </td> - <td t-att-id="widget.m2o.element_id" class="oe_form_frame_cell oe_form_many2one" nowrap="true"> - <t t-raw="widget.m2o.render()"/> - </td> - </tr> - </table> -</t> -<t t-name="FieldBoolean"> - <input type="checkbox" - t-att-name="widget.name" - t-att-id="widget.element_id + '_field'" - t-att-class="'field_' + widget.type"/> -</t> -<t t-name="FieldProgressBar"> - <div t-opentag="true" class="oe-progressbar"> - <span></span> - </div> -</t> -<t t-name="FieldBinaryImage"> - <table cellpadding="0" cellspacing="0" border="0"> - <tr> - <td align="center"> - <img src="/base/static/src/img/placeholder.png" class="oe-binary-image" - t-att-border="widget.readonly ? 0 : 1" - t-att-id="widget.element_id + '_field'" - t-att-name="widget.name" - t-att-class="'field_' + widget.type" - t-att-width="widget.node.attrs.img_width || widget.node.attrs.width" - t-att-height="widget.node.attrs.img_height || widget.node.attrs.height" - /> - </td> - </tr> - <tr> - <td align="center" valign="bottom" height="25"> - <div class="oe-binary"> - <table cellspacing="0" cellpadding="0" border="0"> - <tr> - <td> - <div class="oe-binary-file-set" style="width: 40px; height:22px;"> - <form class="oe-binary-form" t-att-target="widget.iframe" - method="post" enctype="multipart/form-data" action="/base/binary/upload"> - <input type="hidden" name="session_id" value=""/> - <input type="hidden" name="callback" t-att-value="widget.iframe"/> - <button class="button" type="button" title="Set Image"> - <img src="/base/static/src/img/icons/STOCK_DIRECTORY.png"/> - </button> - <input type="file" class="oe-binary-file" name="ufile"/> - </form> - </div> - </td> - <td> - <button class="button oe-binary-file-clear" type="button" title="Clear"> - <img src="/base/static/src/img/icons/STOCK_MISSING_IMAGE.png"/> - </button> - </td> - </tr> - </table> - </div> - <div class="oe-binary-progress" style="display: none"> - <img src="/base/static/src/img/throbber.gif" width="16" height="16"/> - <b>Uploading ...</b> - </div> - <iframe t-att-id="widget.iframe" t-att-name="widget.iframe" style="display: none"> </iframe> - </td> - </tr> - </table> -</t> -<t t-name="FieldBinaryFile"> - <table cellpadding="0" cellspacing="0" border="0" width="100%"> - <tr> - <td width="100%"> - <input type="text" size="1" - t-att-name="widget.name" - t-att-id="widget.element_id + '_field'" - t-att-class="'field_' + widget.type" style="width: 100%" - /> - </td> - <td class="oe-binary" nowrap="true"> - <table cellspacing="0" cellpadding="0" border="0"> - <tr> - <td> - <div class="oe-binary-file-set" style="width: 80px; height:22px;"> - <form class="oe-binary-form" t-att-target="widget.iframe" - method="post" enctype="multipart/form-data" action="/base/binary/upload"> - <input type="hidden" name="session_id" value=""/> - <input type="hidden" name="callback" t-att-value="widget.iframe"/> - <button class="button" type="button" title="Set Image"> - <img src="/base/static/src/img/icons/STOCK_DIRECTORY.png"/> - <span>Select</span> - </button> - <input type="file" class="oe-binary-file" name="ufile"/> - </form> - </div> - </td> - <td> - <button class="button oe-binary-file-save" type="button" title="Save As"> - <img src="/base/static/src/img/icons/gtk-save.png"/> - <span>Save As</span> - </button> - </td> - <td> - <button class="button oe-binary-file-clear" type="button" title="Clear"> - <img src="/base/static/src/img/icons/STOCK_MISSING_IMAGE.png"/> - <span>Clear</span> - </button> - </td> - </tr> - </table> - </td> - <td class="oe-binary-progress" style="display: none" nowrap="true"> - <img src="/base/static/src/img/throbber.gif" width="16" height="16"/> - <b>Uploading ...</b> - <iframe t-att-id="widget.iframe" t-att-name="widget.iframe" style="display: none"> </iframe> - </td> - </tr> - </table> -</t> -<t t-name="WidgetButton"> - <button type="button" - t-att-id="widget.element_id + '_button'" - t-att-title="widget.help" - style="width: 100%" class="button"> - <img t-if="widget.node.attrs.icon" t-att-src="'/base/static/src/img/icons/' + widget.node.attrs.icon + '.png'" width="16" height="16"/> - <span t-if="widget.string"><t t-esc="widget.string"/></span> - </button> -</t> -<t t-name="SearchView"> - <h2 class="oe_view_title"><t t-esc="view.attrs['string']"/></h2> - <form class="oe_forms"> - <t t-call="SearchView.render_lines"/> - <div class="oe_search-view-buttons" style="text-align: right;"> - <input type="submit" value="Search"/> - <input type="reset" value="Clear"/> - <button class="oe_search-view-custom-filter-btn"><span>Advanced Filter</span></button> - <select class="oe_search-view-filters-management"> - </select> - </div> - </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="manage_filters">Manage Filters</option> -</t> -<t t-name="SearchView.managed-filters.add"> - <div> - <p>Filter Name:</p> - <input type="text"/> - <p>(Any existing filter with the same name will be replaced)</p> - </div> -</t> -<t t-name="SearchView.render_lines"> - <table class="oe-searchview-render-line" border="0" cellspacing="0" cellpadding="0" - t-foreach="lines" t-as="line"> - <tr> - <td t-foreach="line" t-as="widget"> - <t t-raw="widget.render(defaults)"/> - </td> - </tr> - </table> -</t> -<button t-name="SearchView.filter" type="button" - t-att-id="element_id" - t-att-title="attrs.help" - t-att-class="classes.join(' ')" - t-att-autofocus="attrs.default_focus === '1' ? 'autofocus' : undefined"> - <img t-if="attrs.icon" t-att-src="'/base/static/src/img/icons/' + attrs.icon + '.png'" width="16" height="16"/> - <br t-if="attrs.icon and attrs.string"/> - <t t-esc="attrs.string"/> -</button> -<span t-name="SearchView.filters" class="filter_label_group" - ><t t-foreach="filters" t-as="filter" - ><t t-raw="filter.render(defaults)"/></t -></span> -<t t-name="SearchView.field"> - <label t-att-class="'oe_label' + (attrs.help ? '_help' : '')" - t-att-title="attrs.help" - t-att-for="element_id"> - <t t-esc="attrs.string || attrs.name"/> - <span t-if="attrs.help">?</span> - </label> - <div style="white-space: nowrap;"> - <input type="text" size="15" t-att-name="attrs.name" - t-att-autofocus="attrs.default_focus === '1' ? 'autofocus' : undefined" - t-att-id="element_id" - t-att-value="defaults[attrs.name] || ''"/> - <t t-if="filters.length" t-raw="filters.render(defaults)"/> - </div> -</t> -<t t-name="SearchView.field.selection"> - <label t-att-title="attrs.help" - t-att-class="'oe_label' + (attrs.help ? '_help' : '')" - t-att-for="element_id"> - <t t-esc="attrs.string || attrs.name"/> - <span t-if="attrs.help">?</span> - </label> - <div style="white-space: nowrap;"> - <select t-att-name="attrs.name" t-att-id="element_id" - t-att-autofocus="attrs.default_focus === '1' || undefined"> - <option/> - <t t-foreach="attrs.selection" t-as="option"> - <t t-set="selected" t-value="defaults[attrs.name] === option[0]"/> - <option t-if="selected" - t-att-value="option[0]" selected="selected"> - <t t-esc="option[1]"/> - </option> - <option t-if="!selected" t-att-value="option[0]"> - <t t-esc="option[1]"/> - </option> - </t> - </select> - <t t-if="filters.length" t-raw="filters.render(defaults)"/> - </div> -</t> -<t t-name="SearchView.util.expand"> - <div t-att-class="'searchview_group ' + (expand == '0' ? 'folded' : 'expanded')" - t-att-id="element_id"> - <a t-if="label" class="searchview_group_string" href="#"> - <t t-esc="label"/> - </a> - <div class="searchview_group_content"> - <t t-raw="content"/> - </div> - </div> -</t> -<t t-name="SearchView.group"> - <t t-call="SearchView.util.expand"> - <t t-set="expand" t-value="attrs.expand"/> - <t t-set="label" t-value="attrs.string"/> - <t t-set="content"> - <t t-call="SearchView.render_lines"/> - </t> - </t> -</t> -<t t-name="SearchView.extended_search"> - <t t-call="SearchView.util.expand"> - <t t-set="expand" t-value="false"/> - <t t-set="label" t-value="'Advanced Filters'"/> - <t t-set="content"> - <div class="searchview_extended_groups_list"> - </div> - </t> - </t> -</t> -<t t-name="SearchView.extended_search.group"> - <div t-att-id="element_id" class="searchview_extended_group"> - <select class="searchview_extended_group_choice"> - <option value="any">Any of the following conditions must match</option> - <option value="all">All the following conditions must match</option> - <option value="none">None of the following conditions must match</option> - </select> - <a class="searchview_extended_delete_group" - href="javascript:void(0)"><span></span></a> - <div class="searchview_extended_propositions_list"> - </div> - <a class="searchview_extended_add_proposition" href="javascript:void(0)"> - <span>Add condition</span></a> - <div class="oe_adv_filters_and"><span>and</span></div> - </div> -</t> -<t t-name="SearchView.extended_search.proposition"> - <div t-att-id="element_id"> - <select class="searchview_extended_prop_field"> - <t t-foreach="attrs.fields" t-as="field"> - <option t-att="{'selected': field === attrs.selected ? 'selected' : null}" - t-att-value="field.name"> - <t t-esc="field.string"/> - </option> - </t> - </select> - <select class="searchview_extended_prop_op"/> - <span class="searchview_extended_prop_value"/> - <a class="searchview_extended_delete_prop" - href="javascript:void(0)"><span> </span></a> - </div> -</t> -<t t-name="SearchView.extended_search.proposition.char"> - <input t-att-id="element_id" class="field_char"/> -</t> -<t t-name="SearchView.extended_search.proposition.datetime"> - <input t-att-id="element_id" class="field_datetime"/> -</t> -<t t-name="SearchView.extended_search.proposition.date"> - <input t-att-id="element_id" class="field_date"/> -</t> -<t t-name="SearchView.extended_search.proposition.integer"> - <input type="number" t-att-id="element_id" class="field_integer" step="1"/> -</t> -<t t-name="SearchView.extended_search.proposition.float"> - <input type="number" t-att-id="element_id" class="field_float" step="0.01"/> -</t> -<t t-name="SearchView.extended_search.proposition.boolean"> -</t> -<t t-name="SearchView.extended_search.proposition.selection"> - <select t-att-id="element_id"> - <t t-foreach="field.selection" t-as="element"> - <option t-att-value="element[0]"><t t-esc="element[1]"/></option> - </t> - </select> -</t> -<t t-name="DialogWarning"> - <table cellspacing="0" cellpadding="0" border="0" class="oe-dialog-warning"> - <tr> - <td><img src="/base/static/src/img/warning.png" class="oe-dialog-icon"/></td> - <td> - <p> - <t t-js="d"> - var message = d.message ? d.message : d.error.data.fault_code; - d.html_error = context.engine.tools.html_escape(message) - .replace(/\n/g, '<br/>'); - </t> - <t t-raw="html_error"/> - </p> - </td> - </tr> - </table> -</t> -<t t-name="DialogTraceback"> - <pre><t t-esc="error.message"/></pre> - <hr/> - <pre><t t-esc="error.data.debug"/></pre> -</t> -<t t-name="SelectCreatePopup"> - <div t-att-id="element_id"> - <table style="width:100%"> - <tr style="width:100%"> - <td style="width:100%"> - <div t-att-id="element_id + '_search'" style="width:100%"></div> - </td> - </tr> - <tr style="width:100%"> - <td style="width:100%"> - <div t-att-id="element_id + '_view_list'" style="width:100%"></div> - </td> - </tr> - </table> - <div t-att-id="element_id + '_view_form'" style="width:100%"></div> - </div> -</t> -<t t-name="SelectCreatePopup.search.buttons"> - <button type="button" class="oe_selectcreatepopup-search-select" disabled="disabled">Select</button> - <button type="button" class="oe_selectcreatepopup-search-close">Cancel</button> -</t> -<t t-name="SelectCreatePopup.form.buttons"> - <t t-if="widget.options.disable_multiple_selection"> - <button type="button" class="oe_selectcreatepopup-form-save">Save</button> - </t> - <t t-if="! widget.options.disable_multiple_selection"> - <button type="button" class="oe_selectcreatepopup-form-save-new">Save & New</button> - <button type="button" class="oe_selectcreatepopup-form-save">Save & Close</button> - </t> - <button type="button" class="oe_selectcreatepopup-form-close">Cancel</button> -</t> -<t t-name="FormOpenPopup"> - <div t-att-id="element_id"> - <div t-att-id="element_id + '_view_form'" style="width:100%"></div> - </div> -</t> -<t t-name="FormOpenPopup.form.buttons"> - <button type="button" class="oe_formopenpopup-form-save">Save</button> - <button type="button" class="oe_formopenpopup-form-close">Cancel</button> -</t> -<t t-name="ListView.row.frame" t-extend="WidgetFrame"> - <t t-jquery="tr"> - $(document.createElement('t')) - .append(this.contents()) - .attr({ - 't-foreach': this.attr('t-foreach'), - 't-as': this.attr('t-as') - }) - .replaceAll(this) - .after($(document.createElement('td')).append( - $(document.createElement('button')).attr({ - 'class': 'oe-edit-row-save', 'type': 'button'}).text('Save'))) - .before($(document.createElement('td')).append( - $(document.createElement('button')).attr({ - 'class': 'oe-edit-row-cancel', 'type': 'button'}).text('Cancel'))) - .unwrap(); - </t> -</t> - -<t t-name="ExportView"> - <a id="exportview" href="javascript: void(0)" style="text-decoration: none;color: #3D3D3D;">Export</a> -</t> -<t t-name="ExportTreeView"> - <table class="view" style="background-color: #F3F3F3;"> - <tr> - <td align="left"> - This wizard will export all data that matches the current search criteria to a CSV file. - You can export all data or only the fields that can be reimported after modification. - </td> - </tr> - <tr> - <td> - <table> - <tr> - <td class="label"><label>Export Type:</label></td> - <td> - <select id="import_compat" name="import_compat"> - <option value="1">Import Compatible Export</option> - <option value="0">Export all Data</option> - </select> - </td> - <td class="label"><label>Export Format</label></td> - <td> - <select id="export_format" name="export_format"> - <option value="csv">CSV</option> - <option value="xls">Excel</option> - </select> - </td> - - </tr> - </table> - </td> - </tr> - - <tr> - <td> - <table class="oe_export_fields_selector_export"> - <tr> - <th class="oe_view_title" valign="bottom">Available fields</th> - <th class="oe_view_title"></th> - <th class="oe_view_title">Fields to export - <a style="color: blue; text-decoration: none;" href="#" id="export_new_list">Save fields list</a> - <div id="savenewlist"></div> - <div id="ExistsExportList"></div> - </th> - </tr> - <tr> - <td class="oe_export_fields_selector_left"> - <div id="left_field_panel"> - </div> - </td> - <td> - <table class="oe_export_fields_selector_center"> - <tr> - <td align="center"> - <button id="add_field" class="oe_export_button_export">Add</button> - </td> - </tr> - <tr> - <td align="center"> - <button id="remove_field" class="oe_export_button_export">Remove</button> - </td> - </tr> - <tr> - <td align="center"> - <button id="remove_all_field" class="oe_export_button_export">Remove All</button> - </td> - </tr> - </table> - </td> - <td class="oe_export_fields_selector_right"> - <select name="fields_list" id="fields_list" multiple="multiple"></select> - </td> - </tr> - </table> - </td> - </tr> - </table> -</t> - -<t t-name="ExportTreeView-Secondary"> - <table id="field-tree-structure" class="oe_export_fields_selector_export" cellspacing="0" cellpadding="0"> - <tr><th class="oe_export_tree_header"> Name </th></tr> - <t t-call="ExportTreeView-Secondary.children"/> - </table> -</t> -<t t-name="ExportTreeView-Secondary.children"> - <t t-foreach="fields" t-as="field" > - <tr t-att-id="'treerow-' + field.id" class="oe_export_row"> - <td> - <table class="tree_grid" border="0"> - <tr class="oe_export_row"> - <t t-foreach="(field.id).split('/')" t-as="level" > - <t t-if="(field.id).split('/')[0] != level"> - <td width="18">&nbsp;</td> - </t> - </t> - <td valign="top" align="left" style="cursor: pointer;" width="18"> - <t t-if="(field.children).length >= 1"> - <t t-if="(field.id).split('/').length != 3"> - <img t-att-id="'parentimg-' + field.id" src="/base/static/src/img/expand.gif" width="16" height="16" border="0"/> - </t> - </t> - </td> - <td id="tree-column" valign="middle" align="left" style="cursor: pointer;"> - <a t-att-id="'export-' + field.id" t-att-string="field.string" href="javascript: void(0);" style="text-decoration: none;"> - <t t-esc="field.string"/> - </a> - </td> - </tr> - </table> - </td> - </tr> - </t> -</t> - -<t t-name="ExportNewList"> - <tr> - <th><label>Save as:</label></th> - <td><input size="10" type="text" id="savelist_name"/></td> - <td><button class="oe_export_button_export" id="add_export_list">Ok</button></td> - </tr> -</t> - -<t t-name="Exists.ExportList"> - <tr><th align="right"><label >Saved exports:</label></th></tr> - <tr align="left"> - <td> - <select id="saved_export_list" style="width: 100%;"> - <option></option> - <t t-foreach="existing_exports" t-as="export"> - <option t-att-value="export.id"><t t-esc="export.name"/></option> - </t> - </select> - </td> - <td><button class="oe_export_button_export" id="delete_export_list">Delete</button></td> - </tr> -</t> -<t t-name="Change_Pwd"> - <form name="change_password_form" class="oe_forms" method="POST"> - <table align="center"> - <tr> - <td><label for="old_pwd">Old Password:</label></td> - <td><input type="password" name="old_pwd" - minlength="1" autofocus="autofocus"/></td> - </tr> - <tr> - <td><label for="new_password">New Password:</label></td> - <td><input type="password" name="new_password" - minlength="1" autofocus="autofocus"/></td> - </tr> - <tr> - <td><label for="confirm_pwd">Confirm Password:</label></td> - <td><input type="password" name="confirm_pwd" - minlength="1"/></td> - </tr> - <tr> - <td colspan="2" align="right"><input type="submit" value="Change Password"/></td> - </tr> - </table> - </form> -</t> -</templates> |
