diff --git a/addons/point_of_sale/controllers/main.py b/addons/point_of_sale/controllers/main.py index 87244a9c90c..705fd853ec1 100644 --- a/addons/point_of_sale/controllers/main.py +++ b/addons/point_of_sale/controllers/main.py @@ -56,7 +56,6 @@ class PosController(http.Controller): @http.route('/pos/web', type='http', auth='none') def a(self, debug=False, **k): - print '\nDEBUG',debug,'\n' js_list = manifest_list('js',db=request.db, debug=debug) css_list = manifest_list('css',db=request.db, debug=debug) @@ -64,8 +63,6 @@ class PosController(http.Controller): print css_list print js_list - js_list = [ js for js in js_list if 'select2' not in js ] - js = "\n".join('' % i for i in js_list) css = "\n".join('' % i for i in css_list) r = html_template % { @@ -73,15 +70,18 @@ class PosController(http.Controller): 'css': css, 'modules': simplejson.dumps(module_boot(request.db)), 'init': """ - window.navigator.standalone = true; + console.log('LOADED'); var wc = new s.web.WebClient(); - wc.appendTo($(document.body)); wc.show_application = function(){ + console.log('SHOW APPLICATION'); wc.action_manager.do_action("pos.ui"); }; wc.show_login = function(){ + console.log('SHOW LOGIN'); window.location.href = '/'; } + wc.appendTo($(document.body)); + console.log('APPENDED'); """ } return r diff --git a/addons/point_of_sale/static/src/css/pos.css b/addons/point_of_sale/static/src/css/pos.css index 1d0cbb41589..9d728f8c7da 100644 --- a/addons/point_of_sale/static/src/css/pos.css +++ b/addons/point_of_sale/static/src/css/pos.css @@ -1163,7 +1163,8 @@ background: rgba(0,0,0,0.82); color: white; padding-bottom: 10px; - cursor:move; + cursor: move; + -webkit-transform: translate3d(0,0,0); } .pos .debug-widget .toggle{ position: absolute; diff --git a/addons/point_of_sale/static/src/css/pos_nohover.css b/addons/point_of_sale/static/src/css/pos_nohover.css deleted file mode 100644 index 6f24abda53b..00000000000 --- a/addons/point_of_sale/static/src/css/pos_nohover.css +++ /dev/null @@ -1,1168 +0,0 @@ -@font-face{ - font-family: 'Inconsolata'; - src: url(../fonts/Inconsolata.otf); -} - -.point-of-sale { - padding: 0; - margin: 0; - background-color: #f0eeee; - font-family: "Lucida Grande", Helvetica, Verdana, Arial; - color: #555555; - font-size: 12px; - position: absolute; - left: 0; - top: 0; - width: 100%; - height: 100%; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; -} - -.point-of-sale .shadow-top{ - position: absolute; - top:0; - left:0; - right:0; - height:10px; - background: -webkit-linear-gradient(top,rgba(0,0,0,0.09),rgba(0,0,0,0)); - background: -moz-linear-gradient(top,rgba(0,0,0,0.09),rgba(0,0,0,0)); - background: -ms-linear-gradient(top,rgba(0,0,0,0.09),rgba(0,0,0,0)); - background: linear-gradient(top,rgba(0,0,0,0.09),rgba(0,0,0,0)); -} - -.point-of-sale .darker-shadow-top{ - position: absolute; - top:0; - left:0; - right:0; - height:10px; - background: -webkit-linear-gradient(top,rgba(0,0,0,0.15),rgba(0,0,0,0)); - background: -moz-linear-gradient(top,rgba(0,0,0,0.15),rgba(0,0,0,0)); - background: -ms-linear-gradient(top,rgba(0,0,0,0.15),rgba(0,0,0,0)); - background: linear-gradient(top,rgba(0,0,0,0.15),rgba(0,0,0,0)); -} - -/* ********* The black loading screen ********* */ - -.point-of-sale .loader{ - background-color: #222; - position:absolute; - left:0px; - top:0px; - width:100%; - height:100%; - z-index: 999; - text-align: center; -} -.point-of-sale .loader img{ - position:absolute; - top:50%; - left:50%; -} - -/* ********* Generic element styling ********* */ - -.point-of-sale a { - text-decoration: none; - color: #555555; -} -.point-of-sale button, .point-of-sale a.button { - display: inline-block; - cursor: pointer; - padding: 4px 10px; - font-size: 11px; - border: 1px solid #cacaca; - border-radius: 4px; - background: #e2e2e2; - background: -webkit-gradient(linear, left top, left bottom, from(#f0f0f0), to(#e2e2e2)); - background: -moz-linear-gradient(#f0f0f0, #e2e2e2); - background: -ms-linear-gradient(#f0f0f0, #e2e2e2); - background: linear-gradient(#f0f0f0, #e2e2e2); -} -.point-of-sale ul, .point-of-sale ol { - padding: 0; - margin: 0; -} -.point-of-sale li { - list-style-type: none; -} -.point-of-sale .pos-right-align { - text-align: right; -} -.point-of-sale .pos-right-align input { - text-align: right; - border: 1px solid #cecbcb; - border-radius: 4px; -} - -/* ********* The black header bar ********* */ - - -.point-of-sale #topheader { - position:absolute; - left:0; - top:0; - width: 100%; - height: 33px; - margin:0; - padding:0; - color: gray; - border-top: solid 1px #d3d3d3; - border-bottom: solid 1px black; - background: #393939; - background: -moz-linear-gradient(#7b7979, #393939); - background: -webkit-gradient(linear, left top, left bottom, from(#7b7979), to(#393939)); -} - -/* a) The left part of the top-bar */ - -.point-of-sale #branding{ - position: absolute; - display: table-cell; - left:0; - top:0; - width:439px; - height:100%; - margin:0; - padding:0; - border-right: 1px solid #373737; - text-align:left; - line-height:100%; - vertical-align: middle; -} -.point-of-sale #branding img { - height: 32px; - width: 116px; - margin-left:5px; - vertical-align:middle; -} -.point-of-sale #branding .username{ - float:right; - color:#DDD; - font-size:16px; - margin-right:32px; - margin-top:10px; - font-style:italic; -} - -/* b) The right part of the top-bar */ - -.point-of-sale #rightheader { - position: absolute; - left:440px; - right:0; - top:0; - height:100%; -} - -.point-of-sale #rightheader button { - color: #273072; - height:27px; - margin:3px; - margin-right:0px; - border: 1px solid #353A7E; - background: #7f82ac; - background: -webkit-gradient(linear, left top, left bottom, from(#b2b3d7), to(#7f82ac)); - background: -moz-linear-gradient(#b2b3d7, #7f82ac); - background: -ms-linear-gradient(#b2b3d7, #7f82ac); - background: linear-gradient(#b2b3d7, #7f82ac); -} - -.point-of-sale #rightheader button.neworder-button { - width: 32px; - margin-left:4px; - margin-right:4px; -} - -.point-of-sale div#order-selector { - display: inline; -} -.point-of-sale ol#orders { - display: inline; -} -.point-of-sale li.order-selector-button { - display: inline; -} -.point-of-sale li.selected-order button { - font-weight: 900; -} - -/* c) The session buttons */ - -.point-of-sale #rightheader .header-button{ - float:right; - height:32px; - padding-left:10px; - padding-right:10px; - border-right: 1px solid #3a3a3a; - border-left: 1px solid #3a3a3a; - color:#DDD; - line-height:32px; - text-align:center; - cursor: pointer; - - -webkit-transition-property: background; - -webkit-transition-duration: 0.2s; - -webkit-transition-timing-function: ease-out; -} -.point-of-sale #rightheader .header-button:last-child{ - border-left: 1px solid #3a3a3a; -} - -/* c) The notifications indicator */ - -.point-of-sale .oe_pos_synch-notification{ - float:right; - color: rgba(255,255,255,0.4); - padding: 8px; - line-height:16px; - font-size:16px; - vertical-align:middle; - font-style: italic; - cursor:pointer; -} - -.point-of-sale .oe_pos_synch-notification .oe_status_red{ - display:inline-block; - cursor:pointer; - width:16px; height:16px; - background: url("../img/gtk-no.png") no-repeat ; -} - -.point-of-sale .oe_pos_synch-notification .oe_status_green{ - display:inline-block; - width:16px; height:16px; - background: url("../img/gtk-yes.png") no-repeat; -} - -/* ********* Contains everything below the bar ********* */ - -.point-of-sale #content { - width: 100%; - position: absolute; - top: 35px; - bottom: 0; - background: #F0EEEE; -} - -/* ********* The leftpane contains the order, numpad and paypad ********* */ - -.point-of-sale #leftpane { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - position:absolute; - left:0; - width:440px; - top:0px; - /*bottom:105px;*/ - bottom:0; - border-right: solid 1px #CECBCB; - background-color: white; -} -.point-of-sale #leftpane footer { - position: absolute; - bottom: 0; - left: 0; - width: 100%; - background: #F0EEEE; - white-space: nowrap; -} - -/* ********* The paypad contains the payment buttons ********* */ - -.point-of-sale #paypad { - padding: 8px 4px 8px 8px; - display: inline-block; - text-align: center; - vertical-align: top; -} -.point-of-sale #paypad button { - height: 54px; - width: 208px; - margin: 0 -3px; - font-weight: bold; - vertical-align: middle; - color: #555555; - border-top: 1px solid #efefef; - font-size: 14px; -} - -/* ********* The Numpad ********* */ - -.point-of-sale #numpad { - padding: 8px 8px 8px 4px; - display: inline-block; - text-align: center; -} -.point-of-sale #numpad button { - height: 54px; - width: 54px; - margin: 0 -3px; - font-weight: bold; - vertical-align: middle; - color: #555555; - border-top: 1px solid #efefef; -} -.point-of-sale #numpad .selected-mode { - color: white; - background: #7f82ac; - background: -webkit-gradient(linear, left top, left bottom, from(#9d9fc5), to(#7f82ac)); - background: -moz-linear-gradient(#9d9fc5, #7f82ac); - background: -ms-linear-gradient(#9d9fc5, #7f82ac); - background: linear-gradient(#9d9fc5, #7f82ac); -} -.point-of-sale .input-button { - font-size: 24px; -} -.point-of-sale .mode-button, .point-of-sale #numpad-delete, .point-of-sale #numpad-minus { - font-size: 14px; -} - -/* ********* The right pane contains the screens and headers ********* */ - -.point-of-sale #rightpane { - position: absolute; - top: 0; - /*bottom: 105px;*/ - bottom:0; - left: 440px; - right: 0; - vertical-align: top; -} - -.point-of-sale #rightpane header { - padding: 0; - height: 32px; - border-bottom: 1px solid #cecbcb; - background: #d3d3d3; - background: -moz-linear-gradient(white, #d3d3d3); - background: -webkit-gradient(linear, left top, left bottom, from(white), to(#d3d3d3)); -} - -/* ********* The product list ********* */ - -.point-of-sale .product-list { - padding:10px; -} - -.point-of-sale .product-list-scroller{ - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - width:100%; - height:100%; - overflow: hidden; -} -.point-of-sale .product-list-container { - position:absolute; - top:0px; - bottom:0px; - left:0px; - right:0px; - background: #eeedff; -} - -/* a) the product list navigation bar */ - -.point-of-sale .breadcrumb li { - float: left; - line-height: 32px; - height: 32px; -} -.point-of-sale .breadcrumb li:last-child { - padding-right: 3px; - border-right: 1px solid #c5c5c5; -} -.point-of-sale .breadcrumb a { - display: inline-block; - padding: 0 9px; - vertical-align: top; - text-shadow: #f7f7f7 0 1px 1px; - color: #555555; - font-weight: bold; -} -.point-of-sale .bc-arrow { - height: 33px; -} -.point-of-sale .homeimg { - width: 19px; - height: 19px; - margin: 6px 0; -} - -/* b) the search box */ - -.point-of-sale .searchbox { - position: absolute; - right: 2px; -} -.point-of-sale .searchbox input { - width: 130px; - border-radius: 11px; - border: 1px solid #cecbcb; - padding: 3px 19px; - margin: 6px; - background: url("../img/search.png") no-repeat 5px; - background-color: white; -} -.point-of-sale .search-clear { - position: absolute; - top: 11px; - right: 11px; - cursor: pointer; - display: none; -} - -/* c) the categories list */ - -.point-of-sale #categories { - /*background:#f0f0f0;*/ - position: relative; - background-image: url('../img/bg.png'); - border-bottom: 1px solid #cecbcb; -} -.point-of-sale #categories .white-gradient{ - position: absolute; - top:50%; - left:0; - right:0; - bottom:0; - background: -webkit-linear-gradient(bottom,rgba(255,255,255,0.5),rgba(255,255,255,0)); - background: -moz-linear-gradient(bottom,rgba(255,255,255,0.5),rgba(255,255,255,0)); - background: -ms-linear-gradient(bottom,rgba(255,255,255,0.5),rgba(255,255,255,0)); - background: linear-gradient(bottom,rgba(255,255,255,0.5),rgba(255,255,255,0)); -} -.point-of-sale #categories h4 { - display: inline-block; - margin: 9px 5px; -} - -.point-of-sale .category-list{ - padding:10px; -} -/* d) the category button */ - -.point-of-sale .category-button { - position: relative; - vertical-align: top; - display: inline-block; - font-size: 11px; - margin: 5px; - width: 120px; - height:120px; - background:#fff; - border: 1px solid #fff; - border-radius: 3px; - -webkit-box-shadow: 0px 1px 8px rgba(0,0,0,0.2); - -moz-box-shadow: 0px 1px 8px rgba(0,0,0,0.2); - box-shadow: 0px 1px 8px rgba(0,0,0,0.2); - cursor: pointer; -} - -.point-of-sale .category-simple-button{ - position: relative; - display: inline-block; - font-size: 14px; - margin-right:10px; - padding:5px; - - cursor: pointer; - border: 1px solid #cacaca; - border-radius: 4px; - - background: #e2e2e2; - background: -webkit-linear-gradient(#f0f0f0, #e2e2e2); - background: -moz-linear-gradient(#f0f0f0, #e2e2e2); - background: -ms-linear-gradient(#f0f0f0, #e2e2e2); - background: linear-gradient(#f0f0f0, #e2e2e2); - -webkit-box-shadow: 0px 2px 2px rgba(0,0,0, 0.1); - -moz-box-shadow: 0px 2px 2px rgba(0,0,0, 0.1); - box-shadow: 0px 2px 2px rgba(0,0,0, 0.1); -} - -.point-of-sale .category-button .category-img { - position: relative; - width: 120px; - height: 100px; - text-align: center; - cursor: pointer; -} - -.point-of-sale .category-button .category-img img { - max-height: 100px; - max-width: 120px; -} - -.point-of-sale .category-button .category-name { - position: absolute; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - top:auto; - left: 2px; - right: 2px; - bottom: 2px; - background: #8a89ba; /*-webkit-linear-gradient(-90deg,rgba(138,137,186,0),rgba(138,137,186,1), rgba(138,137,186,1));*/ - padding: 3px; - /*color:#8a89ba;*/ - color: #FFF; - cursor: pointer; - border-radius: 3px; -} - -/* e) the product */ - -.point-of-sale .product { - position:relative; - vertical-align: top; - display: inline-block; - line-height: 100px; - font-size: 11px; - margin: 5px; - width: 120px; - height:120px; - background:#fff; - border: 1px solid #fff; - border-radius: 3px; - -webkit-box-shadow: 0px 1px 8px rgba(127,130,172,0.4); - -moz-box-shadow: 0px 1px 8px rgba(127,130,172,0.4); - box-shadow: 0px 1px 8px rgba(127,130,172,0.4); -} - -.point-of-sale .product .product-img { - position: relative; - width: 120px; - height: 100px; - background: white; - text-align: center; -} - -.point-of-sale .product .product-img img { - max-height: 100px; - max-width: 120px; -} - -.point-of-sale .product .price-tag { - position: absolute; - top: 2px; - right: 2px; - vertical-align: top; - color: white; - line-height: 14px; - background: #7f82ac; - padding: 2px 5px; - border-radius: 3px; -} - -.point-of-sale .product .product-name { - position: absolute; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - bottom:0; - top:auto; - line-height: 14px; - width:100%; - background: -webkit-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); - background: -moz-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); - background: -ms-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); - background: linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); - /*background:#FFF;*/ - padding: 3px; - padding-top:15px; -} - - -/* ********* The Screens ********* */ - -.point-of-sale .screen { - position:absolute; - text-align: center; - top:0px; - bottom:0px; - width:100%; -} -.point-of-sale .screen header h2 { - margin-top: 0px; - padding-top: 7px; -} -.point-of-sale .screen p{ - font-size: 18px; -} - -/* a) Layout for the Product Screen */ - -.point-of-sale .screen .layout-table { - border:none; - width:100%; - height:100%; -} - -.point-of-sale .screen .header-row { - border:none; - width:100%; - height:0px; -} - -.point-of-sale .screen .header-cell{ - border:none; - width:100%; - height:0px; -} -.point-of-sale .screen .content-row { - width:100%; - height:100%; -} -.point-of-sale .screen .content-cell{ - width:100%; -} -.point-of-sale .screen .content-cell .content-container{ - height:100%; - position:relative; -} - -/* b) The payment screen */ - -.point-of-sale .pos-step-container { - display: inline-block; - font-size: 1.5em; -} -.point-of-sale .greyed-out{ - color: #AAA; -} -.point-of-sale .pos-step-container input{ - font-size: 1em; -} - -.point-of-sale .pos-payment-container { - text-align: left; - min-width: 500px; -} -.point-of-sale .pos-payment-container .left-block{ - display: inline-block; - width:49%; - margin:0; - padding:0; - text-align:left; -} -.point-of-sale .pos-payment-container .header{ - margin-top: 50px; - margin-bottom:20px; - font-weight: bold; -} -.point-of-sale .pos-payment-container .infoline{ - margin-top:5px; - margin-bottom:5px; -} -.point-of-sale .pos-payment-container .right-block{ - display: inline-block; - width:49%; - margin:0; - padding:0; - text-align:right; -} -.point-of-sale .pos-payment-container table { - width: 100%; - margin-bottom: 20px; -} -.point-of-sale .pos-payment-container td { - vertical-align: middle; -} -.point-of-sale .pos-payment-container .paymentline-type { - font-size: 1em; - font-weight: bold; - margin-right:10px; -} - -/* c) The receipt screen */ - -.point-of-sale .pos-receipt-container { - font-size: 0.75em; -} - -.point-of-sale .pos-sale-ticket { - text-align: left; - width: 300px; - background-color: white; - margin: 20px; - padding: 15px; - padding-bottom:30px; - display: inline-block; - font-family: "Inconsolata"; - -webkit-box-shadow: 0px 5px 16px rgba(0,0,0, 0.3); - -moz-box-shadow: 0px 5px 16px rgba(0,0,0, 0.3); - box-shadow: 0px 5px 16px rgba(0,0,0, 0.3); -} -.point-of-sale .pos-sale-ticket .emph{ - font-size: 20px; - margin:5px; -} -.point-of-sale .pos-sale-ticket table { - width: 100%; - border: 0; -} -.point-of-sale .pos-sale-ticket table td { - border: 0; -} - -@media print { - .point-of-sale #topheader, .point-of-sale #leftpane { - display: none !important; - } - .point-of-sale #content { - top: 0px !important; - } - .point-of-sale #rightpane { - left: 0px !important; - background-color: white; - } - #receipt-screen header { - display: none !important; - } - #receipt-screen { - text-align: left; - } - .pos-sale-ticket { - margin: 0; - } -} - -/* d) The Scale screen */ - -.point-of-sale .scale-screen .display{ - position:relative; - width:600px; - height:190px; - margin-top: 100px; - margin-left: auto; - margin-right: auto; -} - -.point-of-sale .scale-screen .product-picture { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - display: float; - float: right; - margin: 5px; - width: 180px; - height:180px; - line-height:180px; - cursor:pointer; - - background:#fff; - border: 1px solid #fff; - border-radius: 3px; - -webkit-box-shadow: 0px 1px 8px rgba(0,0,0,0.2); - -moz-box-shadow: 0px 1px 8px rgba(0,0,0,0.2); - box-shadow: 0px 1px 8px rgba(0,0,0,0.2); -} - -.point-of-sale .scale-screen .product-picture img{ - vertical-align: middle; - cursor:pointer; -} - -.point-of-sale .scale-screen .product-picture .product-price{ - position: absolute; - top:8px; - right:8px; - width:auto; - height:auto; - line-height:1; - color:white; - background: #7f82ac; - padding: 2px 5px; - border-radius: 3px; - cursor:pointer; -} - -.point-of-sale .scale-screen .product-name { - position: absolute; - left:0; - top:20px; - height:50px; - font-size:40px; - line-height:50px; - text-align:right; - right:225px; -} -.point-of-sale .scale-screen .weight{ - position: absolute; - left:0; - height:90px; - bottom:15px; - right:220px; - padding:5px; -} -.point-of-sale .scale-screen .weight p{ - display: inline-block; - text-align:right; - line-height: 90px; - font-size: 80px; - width:100%; - height:100%; - margin:0; - font-family: "Inconsolata"; -} - -/* e) The Welcome Screen */ -.point-of-sale .goodbye-message{ - position: absolute; - left:50%; - top:30%; - width:500px; - height:400px; - margin-left: -250px; - margin-top: -200px; - padding:10px; - padding-top:20px; - text-align:center; - font-size:20px; - font-weight:bold; - background-color: #F0EEEE; - border: 1px solid #E0DDDD; - -webkit-box-shadow: 0px 10px 20px rgba(0,0,0, 0.3); - -moz-box-shadow: 0px 10px 20px rgba(0,0,0, 0.3); - -ms-box-shadow: 0px 10px 20px rgba(0,0,0, 0.3); - z-index:1150; -} - -/* ********* The OrderWidget ********* */ - -.point-of-sale .order-container{ - position: absolute; - top: 0px; - bottom: 232px; - width:100%; - background: #F0EEEE; -} - -.point-of-sale .order-scroller{ - width:100%; - height:100%; - overflow:hidden; -} - -.point-of-sale .order{ - background: #F00; - background: -webkit-linear-gradient(0deg,rgba(245,245,245,1),rgba(255,255,255,1), rgba(245,245,245,1)); - background: -moz-linear-gradient(0deg,rgba(245,245,245,1),rgba(255,255,255,1), rgba(245,245,245,1)); - background: -ms-linear-gradient(0deg,rgba(245,245,245,1),rgba(255,255,255,1), rgba(245,245,245,1)); - background: linear-gradient(0deg,rgba(245,245,245,1),rgba(255,255,255,1), rgba(245,245,245,1)); - padding-bottom:15px; - padding-top:15px; - margin-left:16px; - margin-right:16px; - margin-top:16px; - margin-bottom:16px; - font-size:16px; - -webkit-box-shadow: 0px 5px 16px rgba(0,0,0, 0.3); - -moz-box-shadow: 0px 5px 16px rgba(0,0,0, 0.3); - box-shadow: 0px 5px 16px rgba(0,0,0, 0.3); - -} - -.point-of-sale .order .empty{ - text-align:center; - margin-top: 15px; - margin-bottom: 5px; - color:#999; - font-weight: normal; -} - -.point-of-sale .order .summary{ - width:100%; - text-align:right; - font-weight: bold; - margin-top:20px; - margin-bottom:10px; -} -.point-of-sale .order .summary .line{ - margin-right:15px; - padding-top:5px; - border-top: solid 2px; - border-color:#777; -} -.point-of-sale .order .summary .line.empty{ - border-color:#BBB; - color:#999; -} - -/* ********* The OrderLineWidget ********* */ - -.point-of-sale .order .orderline{ - width:100%; - margin:0px; - padding-top:3px; - padding-bottom:10px; - padding-left:15px; - padding-right:15px; - cursor: pointer; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - -webkit-transition: background 250ms ease-in-out; - -moz-transition: background 250ms ease-in-out; - transition: background 250ms ease-in-out; -} - -.point-of-sale .order .orderline.selected{ - background: rgba(140,143,183,0.2); - -webkit-transition: background 250ms ease-in-out; - -moz-transition: background 250ms ease-in-out; - transition: background 250ms ease-in-out; - cursor: default; -} -.point-of-sale .order .orderline .product-name{ - padding:0; - display:inline-block; - font-weight: bold; - width:80%; - overflow:hidden; -} -.point-of-sale .order .orderline .price{ - padding:0; - font-weight: bold; - float:right; -} -.point-of-sale .order .orderline .info-list{ - color: #888; - margin-left:10px; -} -.point-of-sale .order .orderline .info-list em{ - color: #777; - font-weight: bold; - font-style:normal; -} - -/* ********* The ActionBarWidget ********* */ - -.point-of-sale .pos-actionbar{ - position:absolute; - left: 0; - bottom: 0px; - height: 105px; - width: 100%; - margin: 0; - background: #f5f5f5; /*#ebebeb;*/ - border-top: solid 1px #afafb6; - z-index:900; -} - -.point-of-sale .pos-actionbar ul{ - list-style: none; -} - -.point-of-sale .pos-actionbar-left-pane{ - height: 100%; - width: 434px; - margin: 0px; - padding-left:3px; - padding-right:3px; - border-right: solid 1px #dfdfdf; - float: left; -} - -.point-of-sale .pos-actionbar-button-list{ - height: 100%; - margin: 0px; - padding-left:3px; - padding-right:3px; - overflow:hidden; -} - -.point-of-sale .pos-actionbar .button{ - width: 90px; - height: 90px; - text-align:center; - margin:3px; - margin-top:6px; - float:left; - - font-size: 14px; - font-weight: bold; - - cursor: pointer; - - border: 1px solid #cacaca; - border-radius: 4px; - - background: #e2e2e2; - background: -webkit-linear-gradient(#f0f0f0, #e2e2e2); - background: -moz-linear-gradient(#f0f0f0, #e2e2e2); - background: -ms-linear-gradient(#f0f0f0, #e2e2e2); - background: linear-gradient(#f0f0f0, #e2e2e2); - -webkit-box-shadow: 0px 2px 2px rgba(0,0,0, 0.1); - -moz-box-shadow: 0px 2px 2px rgba(0,0,0, 0.1); - box-shadow: 0px 2px 2px rgba(0,0,0, 0.1); -} -.point-of-sale .pos-actionbar .button .label{ - margin-top: 37px; -} -.point-of-sale .pos-actionbar .button .icon{ - margin-top: 10px; -} - -.point-of-sale .pos-actionbar .button.disabled *{ - opacity: 0.5; -} - -.point-of-sale .pos-actionbar .button.rightalign{ - float:right; -} - -/* ********* The PopupWidgets ********* */ - -.point-of-sale .modal-dialog{ - position: absolute; - left: 0; - top: 0; - width: 100%; - height:100%; - background-color: rgba(0,0,0,0.5); - z-index:1000; -} -.point-of-sale .modal-dialog .popup{ - position: absolute; - left:50%; - top:50%; - width:500px; - height:400px; - margin-left: -250px; - margin-top: -200px; - padding:10px; - padding-top:20px; - text-align:center; - font-size:20px; - font-weight:bold; - background-color: #F0EEEE; - border: 1px solid #E0DDDD; - -webkit-box-shadow: 0px 10px 20px rgba(0,0,0, 0.3); - -moz-box-shadow: 0px 10px 20px rgba(0,0,0, 0.3); - -ms-box-shadow: 0px 10px 20px rgba(0,0,0, 0.3); - z-index:1200; -} -.point-of-sale .popup .footer{ - position:absolute; - bottom:0; - left:0; - width:100%; - height:60px; - border-top: 1px solid #E0DDDD; -} -.point-of-sale .popup .button{ - float:right; - width: 110px; - height: 40px; - line-height:40px; - text-align:center; - margin:3px; - margin-top:10px; - margin-right:10px; - - font-size: 14px; - font-weight: bold; - - cursor: pointer; - - border: 1px solid #cacaca; - border-radius: 4px; - - background: #e2e2e2; - background: -webkit-linear-gradient(#f0f0f0, #e2e2e2); - background: -moz-linear-gradient(#f0f0f0, #e2e2e2); - background: -ms-linear-gradient(#f0f0f0, #e2e2e2); - background: linear-gradient(#f0f0f0, #e2e2e2); - -webkit-box-shadow: 0px 2px 2px rgba(0,0,0, 0.3); - -moz-box-shadow: 0px 2px 2px rgba(0,0,0, 0.3); - box-shadow: 0px 2px 2px rgba(0,0,0, 0.3); -} - -.point-of-sale .popup .button.big-left{ - position:absolute; - top: 120px; - left:40px; - width: 180px; - height: 180px; - line-height:180px; -} - -.point-of-sale .popup .button.big-right{ - position:absolute; - top: 120px; - right:40px; - width: 180px; - height: 180px; - line-height:180px; -} - -/* ********* The ScrollBarWidget ********* */ - -.point-of-sale .scrollbar{ - position:absolute; - top:7px; - right:7px; - width:48px; - bottom:7px; - background: rgba(0,0,0,0.1); - -} -.point-of-sale .scrollbar .button{ - width:100%; - height: 48px; - line-height: 38px; - text-align: center; - font-size:48px; - border-radius: 4px; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - transition: all 250ms ease-in-out; -} -.point-of-sale .scrollbar .button{ - color:white; - background: rgba(0,0,0,0.6); - -webkit-box-shadow: 0px 1px 4px rgba(0,0,0,0.01); - -moz-box-shadow: 0px 1px 4px rgba(0,0,0,0.01); - box-shadow: 0px 1px 4px rgba(0,0,0,0.01); - text-shadow: rgba(255,255,255,0.5) 0px 0px 10px; - -webkit-transition: all 250ms ease-in-out; - -moz-transition: all 250ms ease-in-out; - transition: all 250ms ease-in-out; -} -.point-of-sale .scrollbar .button.disabled{ - background: rgba(0,0,0,0.3); - color:rgba(255,255,255,0.5); - -webkit-transition: all 250ms ease-in-out; - -moz-transition: all 250ms ease-in-out; - transition: all 250ms ease-in-out; -} -.point-of-sale .scrollbar .down-button{ - position:absolute; - bottom:0px; -} -.point-of-sale .scrollbar .up-button{ - position:absolute; - top:0px; -} -.point-of-sale .scrollbar .scroller{ - position:absolute; - top:33%; - bottom:50%; - width:100%; - background: rgba(0,0,0,0.1); - border-radius: 4px; -} - diff --git a/addons/point_of_sale/static/src/js/TODO.txt b/addons/point_of_sale/static/src/js/TODO.txt deleted file mode 100644 index 1696f0b117d..00000000000 --- a/addons/point_of_sale/static/src/js/TODO.txt +++ /dev/null @@ -1,63 +0,0 @@ -v Affichage Catégories doivent respecter le poids -v Affichage Catégories par poids doivent avoir une hiérarchie plate -v Le Onscreen keyboard ne fonctionne plus -v Scrolling dans la sélection produit et dans - la liste de courses -v Réductions -v Redesign liste de courses -v bugs scans produits par prix par poids -v si pas photo photo par defaut -v WebSQL -v Redesign header, bouton retour aux backend en mode caissière -v bouton exit en mode caissière doit retourner au backend. -v posting orders -v bug ajout ligne payment à zero + curseur dedans + suppression + design plus grand -v si case print via proxy cochée, alors on skip l'ecran receipt -v bouton exit self checkout -v demarrage en mode self-checkout si self-checkout -v produits poid code barre non reconnus -v activer popup client aux écrans self-checkout -v discount pas plus grand que 100 -v numpad dans l'écran payment pour pouvoir entrer le montant -v différence de total. Methode d'arrondis - -- login alternatif -- user preferences : désactiver la balance etc. -- numpad state parfois sans state -- numpad state en mode pesée ?? le cacher ? -- Redesign du receipt -- retirer le receipt screen -- le numpad en mode paymenet marche pas -- l'écran de payement est hyper laid -- l'écran de pesée est hyper laid -x générer les données de printing -x popups d'erreur certainement buggés - -TODO AUG 20 ------------ - -* GREEN STATUS - - make it green ! - -* TRUNK - - Connection status tooltip - v Remove receipt screen - - Finish the receipt JSON generation - - Modifie le widget de liste course - v supprimer l'écran - v bloquer sur l'impression - v L'impression est foireuse - - description_sales - -* CLIENT - v create a new branch - - Self-checkout welcome screen - ~ removal of products for the root category - - Terminal de payement - - Code à barres - - Vidanges - - Design - - Backport - - CSS pour écran résistif - - Test sur matos - diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index 68acd4b874e..bd32e040304 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -43,7 +43,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal 'orders': new module.OrderCollection(), //this is the product list as seen by the product list widgets, it will change based on the category filters - 'products': new module.ProductCollection(), 'cashRegisters': null, 'bank_statements': null, @@ -444,11 +443,11 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal } if(parsed_code.type === 'price'){ - selectedOrder.addProduct(new module.Product(product), {price:parsed_code.value}); + selectedOrder.addProduct(product, {price:parsed_code.value}); }else if(parsed_code.type === 'weight'){ - selectedOrder.addProduct(new module.Product(product), {quantity:parsed_code.value, merge:false}); + selectedOrder.addProduct(product, {quantity:parsed_code.value, merge:false}); }else{ - selectedOrder.addProduct(new module.Product(product)); + selectedOrder.addProduct(product); } return true; }, @@ -461,16 +460,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal model: module.CashRegister, }); - module.Product = Backbone.Model.extend({ - get_image_url: function(){ - return instance.session.url('/web/binary/image', {model: 'product.product', field: 'image_medium', id: this.get('id')}); - }, - }); - - module.ProductCollection = Backbone.Collection.extend({ - model: module.Product, - }); - // An orderline represent one element of the content of a client's shopping cart. // An orderline contains a product, its quantity, its price, discount. etc. // An Order contains zero or more Orderlines. @@ -479,7 +468,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal this.pos = options.pos; this.order = options.order; this.product = options.product; - this.price = options.product.get('price'); + this.price = options.product.price; this.quantity = 1; this.quantityStr = '1'; this.discount = 0; @@ -492,7 +481,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal var disc = Math.min(Math.max(parseFloat(discount) || 0, 0),100); this.discount = disc; this.discountStr = '' + disc; - this.trigger('change'); + this.trigger('change',this); }, // returns the discount [0,100]% get_discount: function(){ @@ -522,7 +511,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal this.quantityStr = '' + this.quantity; } } - this.trigger('change'); + this.trigger('change',this); }, // return the quantity of product get_quantity: function(){ @@ -541,7 +530,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal }, // return the unit of measure of the product get_unit: function(){ - var unit_id = (this.product.get('uos_id') || this.product.get('uom_id')); + var unit_id = (this.product.uos_id || this.product.uom_id); if(!unit_id){ return undefined; } @@ -558,7 +547,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal // selects or deselects this orderline set_selected: function(selected){ this.selected = selected; - this.trigger('change'); + this.trigger('change',this); }, // returns true if this orderline is selected is_selected: function(){ @@ -567,7 +556,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal // when we add an new orderline we want to merge it with the last line to see reduce the number of items // in the orderline. This returns true if it makes sense to merge the two can_be_merged_with: function(orderline){ - if( this.get_product().get('id') !== orderline.get_product().get('id')){ //only orderline of the same product can be merged + if( this.get_product().id !== orderline.get_product().id){ //only orderline of the same product can be merged return false; }else if(this.get_product_type() !== orderline.get_product_type()){ return false; @@ -587,7 +576,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal qty: this.get_quantity(), price_unit: this.get_unit_price(), discount: this.get_discount(), - product_id: this.get_product().get('id'), + product_id: this.get_product().id, }; }, //used to create a json of the ticket, to be sent to the printer @@ -597,19 +586,19 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal unit_name: this.get_unit().name, price: this.get_unit_price(), discount: this.get_discount(), - product_name: this.get_product().get('name'), + product_name: this.get_product().name, price_display : this.get_display_price(), price_with_tax : this.get_price_with_tax(), price_without_tax: this.get_price_without_tax(), tax: this.get_tax(), - product_description: this.get_product().get('description'), - product_description_sale: this.get_product().get('description_sale'), + product_description: this.get_product().description, + product_description_sale: this.get_product().description_sale, }; }, // changes the base price of the product for this orderline set_unit_price: function(price){ this.price = round_di(parseFloat(price) || 0, 2); - this.trigger('change'); + this.trigger('change',this); }, get_unit_price: function(){ var rounding = this.pos.get('currency').rounding; @@ -637,8 +626,8 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal var product_list = this.pos.get('product_list'); var product = this.get_product(); - var taxes_ids = product.get('taxes_id');; - var taxes = self.pos.get('taxes'); + var taxes_ids = product.taxes_id; + var taxes = self.pos.taxes; var taxtotal = 0; _.each(taxes_ids, function(el) { var tax = _.detect(taxes, function(t) {return t.id === el;}); @@ -749,7 +738,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal }, addProduct: function(product, options){ options = options || {}; - var attr = product.toJSON(); + var attr = JSON.parse(JSON.stringify(product)); attr.pos = this.pos; attr.order = this; var line = new module.Orderline({}, {pos: this.pos, order: this, product: product}); @@ -951,6 +940,12 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal this.selected_orderline = undefined; } }, + deselectLine: function(){ + if(this.selected_orderline){ + this.selected_orderline.set_selected(false); + this.selected_orderline = undefined; + } + }, }); module.OrderCollection = Backbone.Collection.extend({ diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index 88a83fc52e1..965451ee0eb 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -634,7 +634,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa } var cashregister = selfCheckoutRegisters[0] || self.pos.get('cashRegisters').models[0]; - currentOrder.addPaymentLine(cashregister); + currentOrder.add_payment_line(cashregister); self.pos.push_order(currentOrder) currentOrder.destroy(); self.pos.proxy.transaction_end(); @@ -745,19 +745,23 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa start: function(){ //FIXME this should work as renderElement... but then the categories aren't properly set. explore why var self = this; - this.product_categories_widget = new module.ProductCategoriesWidget(this,{}); - this.product_categories_widget.replace($('.placeholder-ProductCategoriesWidget')); this.product_list_widget = new module.ProductListWidget(this,{ click_product_action: function(product){ - if(product.get('to_weight') && self.pos.iface_electronic_scale){ + if(product.to_weight && self.pos.iface_electronic_scale){ self.pos_widget.screen_selector.set_current_screen( self.cashier_mode ? self.scale_screen : self.client_scale_screen, {product: product}); }else{ self.pos.get('selectedOrder').addProduct(product); } }, + product_list: this.pos.db.get_product_by_category(0) }); this.product_list_widget.replace($('.placeholder-ProductListWidget')); + + this.product_categories_widget = new module.ProductCategoriesWidget(this,{ + product_list_widget: this.product_list_widget, + }); + this.product_categories_widget.replace($('.placeholder-ProductCategoriesWidget')); }, show: function(){ @@ -766,7 +770,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.product_categories_widget.reset_category(); - this.pos_widget.order_widget.set_numpad_state(this.pos_widget.numpad.state); + this.pos_widget.order_widget.set_editable(true); if(this.pos_widget.screen_selector.current_mode === 'client'){ this.add_action_button({ @@ -781,13 +785,13 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa close: function(){ this._super(); - this.pos_widget.order_widget.set_numpad_state(null); - this.pos_widget.payment_screen.set_numpad_state(null); + + this.pos_widget.order_widget.set_editable(false); + if(this.pos.iface_vkeyboard && this.pos_widget.onscreen_keyboard){ this.pos_widget.onscreen_keyboard.hide(); } }, - }); module.ReceiptScreenWidget = module.ScreenWidget.extend({ @@ -812,8 +816,6 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this._super(); var self = this; - this.pos_widget.set_numpad_visible(false); - var print_button = this.add_action_button({ label: _t('Print'), icon: '/point_of_sale/static/src/img/icons/png48/printer.png', @@ -876,7 +878,6 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa }, close: function(){ this._super(); - this.pos_widget.set_numpad_visible(true); } }); @@ -888,7 +889,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this._super(parent,options); this.model = options.model; this.pos.bind('change:selectedOrder', this.change_selected_order, this); - this.bindPaymentLineEvents(); + this.bind_payment_line_events(); this.bind_orderline_events(); this.paymentlinewidgets = []; this.focusedLine = null; @@ -899,7 +900,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.hotkey_handler = function(event){ if(event.which === 13){ - self.validateCurrentOrder(); + self.validate(); }else if(event.which === 27){ self.back(); } @@ -912,8 +913,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.pos.proxy.open_cashbox(); } - this.set_numpad_state(this.pos_widget.numpad.state); - + this.enable_numpad(); + this.add_action_button({ label: _t('Back'), icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png', @@ -927,7 +928,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa name: 'validation', icon: '/point_of_sale/static/src/img/icons/png48/validate.png', click: function(){ - self.validateCurrentOrder(); + self.validate(); }, }); @@ -937,7 +938,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa name: 'invoice', icon: '/point_of_sale/static/src/img/icons/png48/invoice.png', click: function(){ - self.validateCurrentOrder({invoice: true}); + self.validate({invoice: true}); }, }); } @@ -953,13 +954,12 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa }); } - this.updatePaymentSummary(); + this.update_payment_summary(); this.line_refocus(); }, close: function(){ this._super(); - this.pos_widget.order_widget.set_numpad_state(null); - this.pos_widget.payment_screen.set_numpad_state(null); + this.disable_numpad(); $('body').off('keyup',this.hotkey_handler); }, back: function() { @@ -970,13 +970,13 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa }); this.pos_widget.screen_selector.set_current_screen(this.back_screen); }, - validateCurrentOrder: function(options) { + validate: function(options) { var self = this; options = options || {}; var currentOrder = this.pos.get('selectedOrder'); - if(!this.isPaymentPaid()){ + if(!this.is_paid()){ return; } @@ -1018,19 +1018,19 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa $("input").blur(); },250); }, - bindPaymentLineEvents: function() { + bind_payment_line_events: function() { this.currentPaymentLines = (this.pos.get('selectedOrder')).get('paymentLines'); - this.currentPaymentLines.bind('add', this.addPaymentLine, this); + this.currentPaymentLines.bind('add', this.add_payment_line, this); this.currentPaymentLines.bind('remove', this.renderElement, this); - this.currentPaymentLines.bind('all', this.updatePaymentSummary, this); + this.currentPaymentLines.bind('all', this.update_payment_summary, this); }, bind_orderline_events: function() { this.currentOrderLines = (this.pos.get('selectedOrder')).get('orderLines'); - this.currentOrderLines.bind('all', this.updatePaymentSummary, this); + this.currentOrderLines.bind('all', this.update_payment_summary, this); }, change_selected_order: function() { this.currentPaymentLines.unbind(); - this.bindPaymentLineEvents(); + this.bind_payment_line_events(); this.currentOrderLines.unbind(); this.bind_orderline_events(); this.renderElement(); @@ -1045,7 +1045,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.focusedLine.focus(); } }, - addPaymentLine: function(newPaymentLine) { + add_payment_line: function(newPaymentLine) { var self = this; var l = new module.PaymentlineWidget(this, { payment_line: newPaymentLine, @@ -1069,21 +1069,21 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.paymentlinewidgets = []; this.currentPaymentLines.each(_.bind( function(paymentLine) { - this.addPaymentLine(paymentLine); + this.add_payment_line(paymentLine); }, this)); - this.updatePaymentSummary(); + this.update_payment_summary(); }, deleteLine: function(lineWidget) { this.currentPaymentLines.remove([lineWidget.payment_line]); lineWidget.destroy(); }, - isPaymentPaid: function(){ + is_paid: function(){ var currentOrder = this.pos.get('selectedOrder'); return (currentOrder.getTotalTaxIncluded() >= 0.000001 && currentOrder.getPaidTotal() + 0.000001 >= currentOrder.getTotalTaxIncluded()); }, - updatePaymentSummary: function() { + update_payment_summary: function() { var currentOrder = this.pos.get('selectedOrder'); var paidTotal = currentOrder.getPaidTotal(); var dueTotal = currentOrder.getTotalTaxIncluded(); @@ -1099,25 +1099,29 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa } if(this.pos_widget.action_bar){ - this.pos_widget.action_bar.set_button_disabled('validation', !this.isPaymentPaid()); - this.pos_widget.action_bar.set_button_disabled('invoice', !this.isPaymentPaid()); + this.pos_widget.action_bar.set_button_disabled('validation', !this.is_paid()); + this.pos_widget.action_bar.set_button_disabled('invoice', !this.is_paid()); } }, - set_numpad_state: function(numpadState) { - if (this.numpadState) { - this.numpadState.unbind('set_value', this.set_value); - this.numpadState.unbind('change:mode', this.setNumpadMode); - } - this.numpadState = numpadState; - if (this.numpadState) { - this.numpadState.bind('set_value', this.set_value, this); - this.numpadState.bind('change:mode', this.setNumpadMode, this); - this.numpadState.reset(); - this.setNumpadMode(); - } + enable_numpad: function(){ + this.disable_numpad(); //ensure we don't register the callbacks twice + this.numpad_state = this.pos_widget.numpad.state; + if(this.numpad_state){ + this.numpad_state.reset(); + this.numpad_state.changeMode('payment'); + this.numpad_state.bind('set_value', this.set_value, this); + this.numpad_state.bind('change:mode', this.set_mode_back_to_payment, this); + } + }, - setNumpadMode: function() { - this.numpadState.set({mode: 'payment'}); + disable_numpad: function(){ + if(this.numpad_state){ + this.numpad_state.unbind('set_value', this.set_value); + this.numpad_state.unbind('change:mode',this.set_mode_back_to_payment); + } + }, + set_mode_back_to_payment: function() { + this.numpad_state.set({mode: 'payment'}); }, set_value: function(val) { this.currentPaymentLines.last().set_amount(val); diff --git a/addons/point_of_sale/static/src/js/widget_scrollbar.js b/addons/point_of_sale/static/src/js/widget_scrollbar.js deleted file mode 100644 index 001e96d0bb6..00000000000 --- a/addons/point_of_sale/static/src/js/widget_scrollbar.js +++ /dev/null @@ -1,265 +0,0 @@ -/* - * This Widget provides a javascript scrollbar that is suitable to use with resistive - * tactile screens. - * - * Options: - * target_widget : the widget that will be scrolled. - * target_selector : if you don't want to scroll the root element of the the widget, you can provide a - * jquery selector string that will match on the widget's dom element. If there is no widget provided, - * it will match on the document - * step: on each click, the target will be scrolled by it's deplayed size multiplied by this value. - * duration: this is the duration of the scrolling animation - * wheel_step: the target will be scrolled by wheel_step pixels on each mouse scroll. - * track_bottom: the target will be kept on bottom when it's on the bottom and the size has changed - * on_show: this function will be called with the scrollbar as sole argument when the scrollbar is shown - * on_hide: this function will be called with the scrollbar as sole argument when the scrollbar is hidden - */ -function openerp_pos_scrollbar(instance, module){ //module is instance.point_of_sale - - module.ScrollbarWidget = instance.web.Widget.extend({ - template:'ScrollbarWidget', - - init: function(parent,options){ - var self = this; - options = options || {}; - this._super(parent,options); - this.target_widget = options.target_widget; - this.target_selector = options.target_selector; - this.scroll_target = this.target().scrollTop(); - this.scroll_step = options.step || 0.8; - this.scroll_duration = options.duration || 250; - this.wheel_step = options.wheel_step || 80; - this.name = options.name || 'unnamed'; - this.bottom = false; // true if the scroller cannot be scrolled further - this.track_bottom = options.track_bottom || false; - this.on_show = options.on_show || function(){}; - this.on_hide = options.on_hide || function(){}; - - // these handlers are declared once for the object's lifetime so that we can bind and unbind them. - this.resize_handler = function(){ - setTimeout(function(){ - if(self.bottom && self.track_bottom){ - self.set_position(Number.MAX_VALUE); - } - self.update_scroller_dimensions(); - self.update_button_status(); - self.auto_hide(false); - },0); - }; - this.target_mousewheel_handler = function(event,delta){ - self.scroll(delta*self.wheel_step); - } - }, - - renderElement: function(){ - this._super(); - var self = this; - this.$('.up-button').off('click').click(function(){ - self.page_up(); - }); - this.$('.down-button').off('click').click(function(){ - self.page_down(); - }); - this.update_scroller_dimensions(false); - this.update_button_status(); - this.auto_hide(false); - this.$el.bind('mousewheel',function(event,delta){ - self.scroll(delta*self.wheel_step); - return false; - }); - this.$el.bind('click',function(event){ - var vpos = event.pageY - self.$el.offset().top; - var spos = self.scroller_dimensions(); - if(vpos > spos.bar_pos && vpos < spos.pos){ - self.page_up(); - }else if( (vpos < spos.bar_pos + spos.bar_height) && - (vpos > spos.pos + spos.height) ){ - self.page_down(); - } - }); - // FIXME: use the event bus to handle window resize events - $(window).unbind('resize',this.resize_handler); - $(window).bind('resize',this.resize_handler); - - this.target().unbind('mousewheel',this.target_mousewheel_handler); - this.target().bind('mousewheel',this.target_mousewheel_handler); - - // because the rendering is asynchronous we must wait for the next javascript update - // for good dimensions values - setTimeout(function(){ - self.update_scroller_dimensions(false); - self.update_button_status(); - self.auto_hide(false); - },0); - }, - - destroy: function(){ - $(window).unbind('resize',this.resize_handler); - this.target().unbind('mousewheel',this.target_mousewheel_handler); - this._super(); - }, - - // shows the scrollbar. if animated is true, it will do it in an animated fashion - show: function(animated){ //FIXME: animated show and hide don't work ... ? - if(animated){ - this.$el.removeClass('oe_hidden').animate({'width':'48px'}, 500, 'swing'); - }else{ - this.$el.removeClass('oe_hidden').css('width','48px'); - } - this.on_show(this); - }, - - // hides the scrollbar. if animated is true, it will do it in a animated fashion - hide: function(animated){ - var self = this; - if(animated){ - this.$el.animate({'width':'0px'}, 500, 'swing', function(){ self.$el.addClass('oe_hidden');}); - }else{ - this.$el.addClass('oe_hidden').css('width','0px'); - } - this.on_hide(this); - }, - - // returns the scroller position and other information as a dictionnary with the following fields: - // pos: the position in pixels of the top of the scroller starting from the top of the scrollbar - // height: the height of the scroller in pixels - // bar_pos: the position of the top of the scrollbar's inner region, starting from the top - // bar_height: the height of the scrollbar's inner region - scroller_dimensions: function(){ - var target = this.target()[0]; - var scroller_height = target.clientHeight / target.scrollHeight || 0; - var scroller_pos = this.scroll_target / target.scrollHeight || 0; - var button_up_height = this.$('.up-button')[0].offsetHeight || 48; - var button_down_height = this.$('.down-button')[0].offsetHeight || 48; - - var bar_height = this.$el[0].offsetHeight || 96; - var scrollbar_height = bar_height - button_up_height - button_down_height; - - scroller_pos = scroller_pos * scrollbar_height + button_up_height; - scroller_height = scroller_height * scrollbar_height; - - return { pos: Math.round(scroller_pos), - height: Math.round(scroller_height), - bar_pos: button_up_height, - bar_height: scrollbar_height }; - }, - - - //checks if it should show or hide the scrollbar based on the target content and then show or hide it - // if animated is true, then the scrollbar will be shown or hidden with an animation - auto_hide: function(animated){ - var target = this.target()[0]; - if(target.clientHeight && (target.clientHeight === target.scrollHeight)){ - this.hide(animated); - }else{ - this.show(animated); - } - }, - - //returns the pageup/down scrolling distance in pixels - get_scroll_step: function(){ - var target = this.target()[0]; - var step = target.clientHeight * this.scroll_step; - var c = target.scrollHeight / step; - var c = Math.max(1,Math.ceil(c)); - return target.scrollHeight / c; - }, - - //sets the scroller to the correct size and position based on the target scrolling status - //if animated is true, the scroller will move smoothly to its destination - update_scroller_dimensions: function(animated){ - var dim = this.scroller_dimensions(); - var target = this.target()[0]; - if(animated){ - this.$('.scroller').animate({'top':dim.pos+'px', 'height': dim.height+'px'},this.scroll_duration); - }else{ - this.$('.scroller').css({'top':dim.pos+'px', 'height': dim.height+'px'}); - } - if(this.scroll_target + target.clientHeight >= target.scrollHeight){ - this.bottom = true; - }else{ - this.bottom = false; - } - }, - - //disable or enable the up/down buttons according to the scrolled position - update_button_status: function(){ - var target = this.target()[0]; - this.$('.up-button').removeClass('disabled'); - this.$('.down-button').removeClass('disabled'); - if(this.scroll_target === 0){ - this.$('.up-button').addClass('disabled'); - } - if(this.scroll_target + target.clientHeight >= target.scrollHeight){ - this.$('.down-button').addClass('disabled'); - } - }, - - //returns the jquery object of the scrolling target - target: function(){ - if(this.target_widget){ - if(this.target_selector){ - return this.target_widget.$(this.target_selector); - }else{ - return this.target_widget.$el; - } - }else if(this.target_selector){ - return $(this.target_selector); - }else{ - return undefined; - } - }, - - //scroll one page up - page_up: function(){ - return this.set_position(this.scroll_target - this.get_scroll_step(), true); - }, - - //scroll one page down - page_down: function(){ - return this.set_position(this.scroll_target + this.get_scroll_step(), true); - }, - - //scrolls up or down by pixels - scroll: function(pixels){ - return this.set_position(this.scroll_target - pixels, false); - }, - - //scroll to a specific position (in pixels). - //if animated is true, it will do this in an animated fashion with a duration equal to scroll_duration - set_position: function(position,animated){ - var self = this; - var target = this.target()[0]; - var bottom = target.scrollHeight-target.clientHeight; - this.scroll_target = Math.max(0,Math.min(bottom,position)); - if(this.scroll_target === 0){ - this.position = 'top'; - }else if(this.scroll_target === 'bottom'){ - this.position = 'bottom'; - }else{ - this.position = 'center'; - } - if(animated){ - this.target().animate({'scrollTop':this.scroll_target},this.scroll_duration); - this.update_button_status(); - this.update_scroller_dimensions(true); - }else{ - this.target().scrollTop(this.scroll_target); - this.update_scroller_dimensions(false); - this.update_button_status(); - } - return this.scroll_target; - }, - - //returns the current position of the scrollbar - get_position: function(){ - return this.scroll_target; - }, - - //returns true if it cannot be scrolled further down - is_at_bottom: function(){ - return this.bottom; - } - - }); -} diff --git a/addons/point_of_sale/static/src/js/widgets.js b/addons/point_of_sale/static/src/js/widgets.js index de571ff51f5..438dbc4bc00 100644 --- a/addons/point_of_sale/static/src/js/widgets.js +++ b/addons/point_of_sale/static/src/js/widgets.js @@ -58,6 +58,11 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa init: function(parent, options) { this._super(parent); this.state = new module.NumpadState(); + window.numpadstate = this.state; + var self = this; + this.state.bind('change:buffer',function(){ + console.log('BUFFER:',self.state.get('buffer')); + }) }, start: function() { this.state.bind('change:mode', this.changedMode, this); @@ -129,61 +134,50 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa }, }); - module.OrderlineWidget = module.PosBaseWidget.extend({ - template: 'OrderlineWidget', - init: function(parent, options) { - this._super(parent,options); - - this.model = options.model; - this.order = options.order; - - this.model.bind('change', this.refresh, this); - }, - renderElement: function() { - var self = this; - this._super(); - this.$el.click(function(){ - self.order.selectLine(self.model); - self.trigger('order_line_selected'); - }); - if(this.model.is_selected()){ - this.$el.addClass('selected'); - } - }, - refresh: function(){ - this.renderElement(); - this.trigger('order_line_refreshed'); - }, - destroy: function(){ - this.model.unbind('change',this.refresh,this); - this._super(); - }, - }); - module.OrderWidget = module.PosBaseWidget.extend({ template:'OrderWidget', init: function(parent, options) { + var self = this; this._super(parent,options); - this.display_mode = options.display_mode || 'numpad'; // 'maximized' | 'actionbar' | 'numpad' - this.set_numpad_state(options.numpadState); + this.editable = false; this.pos.bind('change:selectedOrder', this.change_selected_order, this); this.bind_orderline_events(); - this.orderlinewidgets = []; + this.line_click_handler = function(event){ + if(!self.editable){ + return; + } + self.pos.get('selectedOrder').selectLine(this.orderline); + self.pos_widget.numpad.state.reset(); + }; }, - set_numpad_state: function(numpadState) { - if (this.numpadState) { - this.numpadState.unbind('set_value', this.set_value); - } - this.numpadState = numpadState; - if (this.numpadState) { - this.numpadState.bind('set_value', this.set_value, this); - this.numpadState.reset(); - } + enable_numpad: function(){ + this.disable_numpad(); //ensure we don't register the callbacks twice + this.numpad_state = this.pos_widget.numpad.state; + if(this.numpad_state){ + this.numpad_state.reset(); + this.numpad_state.bind('set_value', this.set_value, this); + } + + }, + disable_numpad: function(){ + if(this.numpad_state){ + this.numpad_state.unbind('set_value', this.set_value); + this.numpad_state.reset(); + } + }, + set_editable: function(editable){ + this.editable = editable; + if(editable){ + this.enable_numpad(); + }else{ + this.disable_numpad(); + this.pos.get('selectedOrder').deselectLine(); + } }, set_value: function(val) { var order = this.pos.get('selectedOrder'); - if (order.get('orderLines').length !== 0) { - var mode = this.numpadState.get('mode'); + if (this.editable && order.getSelectedLine()) { + var mode = this.numpad_state.get('mode'); if( mode === 'quantity'){ order.getSelectedLine().set_quantity(val); }else if( mode === 'discount'){ @@ -194,81 +188,96 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa } }, change_selected_order: function() { - this.currentOrderLines.unbind(); this.bind_orderline_events(); this.renderElement(); }, bind_orderline_events: function() { - this.currentOrderLines = (this.pos.get('selectedOrder')).get('orderLines'); - this.currentOrderLines.bind('add', function(){ this.renderElement(true);}, this); - this.currentOrderLines.bind('remove', this.renderElement, this); + var lines = this.pos.get('selectedOrder').get('orderLines'); + lines.unbind(); + lines.bind('add', function(){ + this.numpad_state.reset(); + this.renderElement(true); + },this); + lines.bind('remove', function(line){ + this.remove_orderline(line); + this.numpad_state.reset(); + this.update_summary(); + },this); + lines.bind('change', function(line){ + this.rerender_orderline(line); + this.update_summary(); + },this); }, update_numpad: function() { this.selected_line = this.pos.get('selectedOrder').getSelectedLine(); if (this.numpadState) this.numpadState.reset(); }, - renderElement: function(goto_bottom) { - var self = this; - var scroller = this.$('.order-scroller')[0]; - var scrollbottom = true; - var scrollTop = 0; - if(scroller){ - var overflow_bottom = scroller.scrollHeight - scroller.clientHeight; - scrollTop = scroller.scrollTop; - if( !goto_bottom && scrollTop < 0.9 * overflow_bottom){ - scrollbottom = false; - } - } - this._super(); + render_orderline: function(orderline){ + var el_str = openerp.qweb.render('Orderline',{widget:this, line:orderline}); + var el_node = document.createElement('div'); + el_node.innerHTML = _.str.trim(el_str); + el_node = el_node.childNodes[0]; + el_node.orderline = orderline; + el_node.addEventListener('click',this.line_click_handler); - // freeing subwidgets - - for(var i = 0, len = this.orderlinewidgets.length; i < len; i++){ - this.orderlinewidgets[i].destroy(); + orderline.node = el_node; + return el_node; + }, + remove_orderline: function(order_line){ + if(this.pos.get('selectedOrder').get('orderLines').length === 0){ + this.renderElement(); + }else{ + order_line.node.parentNode.removeChild(order_line.node); } - this.orderlinewidgets = []; + }, + rerender_orderline: function(order_line){ + var node = order_line.node; + var replacement_line = this.render_orderline(order_line); + node.parentNode.replaceChild(replacement_line,node); + }, + replace: function($target){ + this.renderElement(); + var target = $target[0]; + target.parentNode.replaceChild(this.el,target); + }, + renderElement: function(scrollbottom){ + this.pos_widget.numpad.state.reset(); - var $content = this.$('.orderlines'); - this.currentOrderLines.each(_.bind( function(orderLine) { - var line = new module.OrderlineWidget(this, { - model: orderLine, - order: this.pos.get('selectedOrder'), - }); - line.on('order_line_selected', self, self.update_numpad); - line.on('order_line_refreshed', self, self.update_summary); - line.appendTo($content); - self.orderlinewidgets.push(line); - }, this)); - this.update_numpad(); + var order = this.pos.get('selectedOrder'); + var orderlines = order.get('orderLines').models; + + var el_str = openerp.qweb.render('OrderWidget',{widget:this, order:order, orderlines:orderlines}); + var el_node = document.createElement('div'); + el_node.innerHTML = _.str.trim(el_str); + el_node = el_node.childNodes[0]; + + var list_container = el_node.querySelector('.orderlines'); + for(var i = 0, len = orderlines.length; i < len; i++){ + var orderline = this.render_orderline(orderlines[i]); + list_container.appendChild(orderline); + } + + if(this.el && this.el.parentNode){ + this.el.parentNode.replaceChild(el_node,this.el); + } + this.el = el_node; this.update_summary(); - scroller = this.$('.order-scroller')[0]; - - if(scroller){ - if(scrollbottom){ - scroller.scrollTop = scroller.scrollHeight - scroller.clientHeight; - }else{ - scroller.scrollTop = scrollTop; - } + if(scrollbottom){ + this.el.querySelector('.order-scroller').scrollTop = 100 * orderlines.length; } }, update_summary: function(){ var order = this.pos.get('selectedOrder'); var total = order ? order.getTotalTaxIncluded() : 0; var taxes = order ? total - order.getTotalTaxExcluded() : 0; - this.$('.summary .total > .value').html(this.format_currency(total)); - this.$('.summary .total .subentry .value').html(this.format_currency(taxes)); - }, - set_display_mode: function(mode){ - if(this.display_mode !== mode){ - this.display_mode = mode; - this.renderElement(); - } + + this.el.querySelector('.summary .total > .value').innerText = this.format_currency(total); + this.el.querySelector('.summary .total .subentry .value').innerText = this.format_currency(taxes); }, }); - module.PaymentlineWidget = module.PosBaseWidget.extend({ template: 'PaymentlineWidget', init: function(parent, options) { @@ -439,8 +448,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa }, }); - module.CategoryButton = module.PosBaseWidget.extend({ - }); module.ProductCategoriesWidget = module.PosBaseWidget.extend({ template: 'ProductCategoriesWidget', init: function(parent, options){ @@ -451,7 +458,13 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa this.category = this.pos.root_category; this.breadcrumb = []; this.subcategories = []; + this.product_list_widget = options.product_list_widget || null; + this.category_cache = {}; this.set_category(); + this.switch_category_handler = function(event){ + self.set_category(self.pos.db.get_category_by_id(Number(this.dataset['categoryId']))); + self.renderElement(); + }; }, // changes the category. if undefined, sets to root category @@ -474,46 +487,77 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa }, get_image_url: function(category){ - return instance.session.url('/web/binary/image', {model: 'pos.category', field: 'image_medium', id: category.id}); + return window.location.origin + '/web/binary/image?model=pos.category&field=image_medium&id='+category.id; + }, + + render_category: function( category, with_image ){ + if(!this.category_cache[category.id]){ + + if(with_image){ + var image_url = this.get_image_url(category); + var category_html = QWeb.render('CategoryButton',{ + widget: this, + category: category, + }); + category_html = _.str.trim(category_html); + var category_node = document.createElement('div'); + category_node.innerHTML = category_html; + category_node = category_node.childNodes[0]; + var img = category_node.querySelector('img'); + img.parentNode.replaceChild(this.pos_widget.image_cache.get_image(image_url),img); + }else{ + var category_html = QWeb.render('CategorySimpleButton',{ + widget: this, + category: category, + }); + category_html = _.str.trim(category_html); + var category_node = document.createElement('div'); + category_node.innerHTML = category_html; + category_node = category_node.childNodes[0]; + } + this.category_cache[category.id] = category_node; + } + return this.category_cache[category.id]; + }, + + replace: function($target){ + this.renderElement(); + var target = $target[0]; + target.parentNode.replaceChild(this.el,target); }, renderElement: function(){ var self = this; - this._super(); + + var el_str = openerp.qweb.render(this.template, {widget: this}); + var el_node = document.createElement('div'); + el_node.innerHTML = el_str; + el_node = el_node.childNodes[1]; + + if(this.el && this.el.parentNode){ + this.el.parentNode.replaceChild(el_node,this.el); + } + + this.el = el_node; var hasimages = false; //if none of the subcategories have images, we don't display buttons with icons - _.each(this.subcategories, function(category){ - if(category.image){ + for(var i = 0; i < this.subcategories.length; i++){ + if(this.subcategories[i].image){ hasimages = true; + break; } - }); + } - _.each(this.subcategories, function(category){ - if(hasimages){ - var button = QWeb.render('CategoryButton',{category:category}); - var button = _.str.trim(button); - var button = $(button); - button.find('img').replaceWith(self.pos_widget.image_cache.get_image(self.get_image_url(category))); - }else{ - var button = QWeb.render('CategorySimpleButton',{category:category}); - button = _.str.trim(button); // we remove whitespace between buttons to fix spacing - var button = $(button); - } + var list_container = el_node.querySelector('.category-list'); + for(var i = 0, len = this.subcategories.length; i < len; i++){ + list_container.appendChild(this.render_category(this.subcategories[i],hasimages)); + }; + + var buttons = el_node.querySelectorAll('.js-category-switch'); + for(var i = 0; i < buttons.length; i++){ + buttons[i].addEventListener('click',this.switch_category_handler); + } - button.appendTo(this.$('.category-list')).click(function(event){ - var id = category.id; - var cat = self.pos.db.get_category_by_id(id); - self.set_category(cat); - self.renderElement(); - }); - }); - // breadcrumb click actions - this.$(".oe-pos-categories-list a").click(function(event){ - var id = $(event.target).data("category-id"); - var category = self.pos.db.get_category_by_id(id); - self.set_category(category); - self.renderElement(); - }); this.search_and_categories(); @@ -522,11 +566,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa } }, - set_product_type: function(type){ // 'all' | 'weightable' - this.product_type = type; - this.reset_category(); - }, - // resets the current category to the root category reset_category: function(){ this.set_category(); @@ -536,7 +575,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa // empties the content of the search box clear_search: function(){ var products = this.pos.db.get_product_by_category(this.category.id); - this.pos.get('products').reset(products); + this.product_list_widget.set_product_list(products); this.$('.searchbox input').val('').focus(); this.$('.search-clear').fadeOut(); }, @@ -547,9 +586,10 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa // find all products belonging to the current category var products = this.pos.db.get_product_by_category(this.category.id); - self.pos.get('products').reset(products); + this.product_list_widget.set_product_list(products); + /* var searchtimeout = null; // filter the products according to the search string this.$('.searchbox input').keyup(function(event){ @@ -562,17 +602,17 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa if(query){ if(event.which === 13){ if( self.pos.get('products').size() === 1 ){ - self.pos.get('selectedOrder').addProduct(self.pos.get('products').at(0)); + self.pos.get('selectedOrder').addProduct(self.pos.get('products').at(0)); // FIXME self.clear_search(); } }else{ var products = self.pos.db.search_product_in_category(self.category.id, query); - self.pos.get('products').reset(products); + this.product_list_widget.set_product_list(products); self.$('.search-clear').fadeIn(); } }else{ var products = self.pos.db.get_product_by_category(self.category.id); - self.pos.get('products').reset(products); + this.product_list_widget.set_product_list(products); self.$('.search-clear').fadeOut(); } },200); @@ -581,11 +621,11 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa //reset the search when clicking on reset this.$('.search-clear').click(function(){ self.clear_search(); - }); + });*/ }, }); - module.ProductListWidget = module.ScreenWidget.extend({ + module.ProductListWidget = module.PosBaseWidget.extend({ template:'ProductListWidget', init: function(parent, options) { var self = this; @@ -595,38 +635,65 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa this.weight = options.weight || 0; this.show_scale = options.show_scale || false; this.next_screen = options.next_screen || false; - this.click_product_action = options.click_product_action; - this.pos.get('products').bind('reset', function(){ - self.renderElement(); - }); + this.click_product_handler = function(event){ + var product = self.pos.db.get_product_by_id(this.dataset['productId']); + options.click_product_action(product); + }; + + this.product_list = options.product_list || []; + this.product_cache = {}; }, + set_product_list: function(product_list){ + this.product_list = product_list; + this.renderElement(); + }, + get_product_image_url: function(product){ + return window.location.origin + '/web/binary/image?model=product.product&field=image_medium&id='+product.id; + }, + replace: function($target){ + this.renderElement(); + var target = $target[0]; + target.parentNode.replaceChild(this.el,target); + }, + + render_product: function(product){ + if(!this.product_cache[product.id]){ + var image_url = this.get_product_image_url(product); + var product_html = QWeb.render('Product',{ + widget: this, + product: product, + }); + var product_node = document.createElement('div'); + product_node.innerHTML = product_html; + product_node = product_node.childNodes[1]; + var img = product_node.querySelector('img'); + img.parentNode.replaceChild(this.pos_widget.image_cache.get_image(image_url),img); + this.product_cache[product.id] = product_node; + } + return this.product_cache[product.id]; + }, + renderElement: function() { var self = this; - this._super(); - var products = this.pos.get('products').models || []; + // this._super() + var el_str = openerp.qweb.render(this.template, {widget: this}); + var el_node = document.createElement('div'); + el_node.innerHTML = el_str; + el_node = el_node.childNodes[1]; - _.each(products,function(product,i){ - var $product = $(QWeb.render('Product',{ widget:self, product: products[i] })); - $product.find('img').replaceWith(self.pos_widget.image_cache.get_image(products[i].get_image_url())); - $product.appendTo(self.$('.product-list')); - }); - - this.$el.delegate('.product','touchstart',function TOUCHSTART(){ - console.log('Touchstart',(new Date()).getTime()); - }); - - this.$el.delegate('.product','touchend',function TOUCHEND(){ - console.log('Touchend',(new Date()).getTime()); - }); - - this.$el.delegate('.product','click',function TOUCHCLICK(){ - console.log('ClickStart',(new Date()).getTime()); - self.click_product_action(new module.Product(self.pos.db.get_product_by_id(+$(this).data('product-id')))); - console.log('ClickEnd',(new Date()).getTime()); - }); + if(this.el && this.el.parentNode){ + this.el.parentNode.replaceChild(el_node,this.el); + } + this.el = el_node; + var list_container = el_node.querySelector('.product-list'); + for(var i = 0, len = this.product_list.length; i < len; i++){ + var product_node = this.render_product(this.product_list[i]); + product_node.addEventListener('click',this.click_product_handler); + list_container.appendChild(product_node); + }; }, }); @@ -1046,13 +1113,9 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa this.set_left_action_bar_visible(false); this.numpad.show(); this.paypad.show(); - this.order_widget.set_display_mode('numpad'); }else{ this.numpad.hide(); this.paypad.hide(); - if(this.order_widget.display_mode === 'numpad'){ - this.order_widget.set_display_mode('maximized'); - } } } }, @@ -1062,20 +1125,11 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa if(visible){ this.set_numpad_visible(false); this.left_action_bar.show(); - this.order_widget.set_display_mode('actionbar'); }else{ this.left_action_bar.hide(); - if(this.order_widget.display_mode === 'actionbar'){ - this.order_widget.set_display_mode('maximized'); - } } } }, - set_fullscreen: function(){ - if(this.el.webkitRequestFullscreen){ - this.el.webkitRequestFullscreen(); - } - }, //shows or hide the leftpane (contains the list of orderlines, the numpad, the paypad, etc.) set_leftpane_visible: function(visible){ if(visible !== this.leftpane_visible){ diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index d8ce116d749..941fdc8c80b 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -137,7 +137,7 @@ -
  • +
  • @@ -148,23 +148,24 @@ -
  • +
  • +
    + @@ -425,52 +427,36 @@
  • - + - + - + - +
    - +
  • - -
    -
    - &atilde; -
    - -
    -
    - -
    - &auml; -
    -
    -
    -
      - +
    • Your shopping cart is empty
    • -
    -
    +
    Total: 0.00 €
    Taxes: 0.00€
    @@ -480,8 +466,6 @@
    -
    -
    @@ -538,32 +522,32 @@
    - -
  • + +
  • - + - +
      - +
    • - + - + at - + / - +
    • - +
    • With a - % + % discount
    • @@ -621,7 +605,7 @@ - +
      With a % discount