<link rel="apple-touch-icon" sizes="152x152" href="/point_of_sale/static/src/img/touch-icon-ipad-retina.png">
<link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon"/>
- <link rel="stylesheet" href="/web/static/src/css/full.css" />
- %(css)s
+ <link rel="stylesheet" href="/point_of_sale/static/src/css/pos.css" />
%(js)s
<script type="text/javascript">
$(function() {
print js_list
js = "\n".join('<script type="text/javascript" src="%s"></script>' % i for i in js_list)
- css = "\n".join('<link rel="stylesheet" href="%s">' % i for i in css_list)
+ #css = "\n".join('<link rel="stylesheet" href="%s">' % i for i in css_list)
r = html_template % {
'js': js,
- 'css': css,
+ # 'css': css,
'modules': simplejson.dumps(module_boot(request.db)),
'init': """
console.log('LOADED');
+/* --- Fonts --- */
+
@font-face{
font-family: 'Inconsolata';
src: url(../fonts/Inconsolata.otf);
}
+/* --- Generic Restyling and Resets --- */
+
+html {
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+table {
+ border-spacing: 0px;
+ border-collapse: collapse;
+}
+td {
+ padding: 0px;
+}
+
.oe_hidden{
display: none !important;
}
-
-.pos {
- padding: 0;
- margin: 0;
- background-color: #f0eeee;
- font-family: "Lato","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;
- text-shadow: none;
- overflow: hidden;
+.clearfix:after {
+ content:" ";
+ display: block;
+ visibility: hidden;
+ line-height: 0;
+ height: 0;
+ clear: both;
}
-.pos * {
- -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-}
.pos input::-webkit-outer-spin-button,
.pos input::-webkit-inner-spin-button {
list-style-type: none;
}
+.pos {
+ padding: 0;
+ margin: 0;
+ background-color: #f0eeee;
+ font-family: "Lato","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;
+ text-shadow: none;
+ overflow: hidden;
+}
+
/* ********* The black loading screen ********* */
.pos .loader{
height:100%;
z-index: 999;
text-align: center;
+ font-family: Lato;
}
/* ********* Generic Layout Constructs ********* */
font-size: 11px;
border: 1px solid #cacaca;
background: #e2e2e2;
+ border-radius: 3px;
}
.pos ul, .pos ol {
padding: 0;
.pos .pos-center-align {
text-align: center;
}
-.pos .pos-right-align input {
- text-align: right;
- border: 1px solid #cecbcb;
-}
.pos .pos-disc-font {
font-size: 12px;
font-style:italic;
line-height:100%;
vertical-align: middle;
}
-.pos .pos-branding img {
+.pos .pos-logo {
height: 32px;
width: 116px;
margin-left:5px;
height:100%;
}
-.pos .pos-rightheader button {
+.pos .order-button{
color: #273072;
height:27px;
margin:3px;
border: 1px solid #353A7E;
background: #7f82ac;
text-shadow: none;
+ border-radius: 3px;
+}
+.pos .order-button.selected{
+ font-weight: 900;
+ background: #666997;
+ color: rgb(236, 237, 255);
}
-.pos .pos-rightheader button.square{
+.pos .order-button.square{
width: 32px;
margin-left:4px;
}
.pos .order-selector {
- display: inline;
+ display: inline-block;
}
.pos .orders {
- display: inline;
+ display: inline-block;
+ vertical-align: top;
margin-left: 8px;
}
-.pos .order-selector-button {
- display: inline;
-}
-.pos .selected-order button {
- font-weight: 900;
- background: #7174A8 !important;
- color: rgb(236, 237, 255) !important;
-}
/* c) The session buttons */
height:32px;
padding-left:10px;
padding-right:10px;
- border-right: 1px solid #3a3a3a;
- border-left: 1px solid #3a3a3a;
+ border-right: 1px solid #292929;
+ border-left: 1px solid #292929;
color:#DDD;
line-height:32px;
text-align:center;
/* ********* The right pane contains the screens and headers ********* */
-.pos .pos-rightpane {
+.pos .rightpane {
position: absolute;
top: 0;
/*bottom: 105px;*/
left: 440px;
right: 0;
vertical-align: top;
+ -webkit-transform: translate3d(0,0,0);
}
-.pos .pos-rightpane header {
+.pos .rightpane-header {
padding: 0;
- height: 32px;
+ height: 48px;
border-bottom: 1px solid #c7c7c7;
background: #d3d3d3;
+ text-align: center;
}
/* ********* The product list ********* */
.pos .product-list {
- padding:10px !important;
+ padding: 10px;
+ text-align: left;
-webkit-transform: translate3d(0,0,0);
}
/* a) the product list navigation bar */
-.pos .breadcrumb li {
+.pos .breadcrumbs{
+ display: inline-block;
+ text-align: left;
+ float:left;
+}
+.pos .breadcrumb{
float: left;
- line-height: 32px;
- height: 32px;
+ display: inline-block;
+ line-height: 48px;
+ height: 48px;
+ min-width: 48px;
}
-.pos .breadcrumb li:last-child {
+.pos .breadcrumb:last-child {
padding-right: 3px;
border-right: 1px solid #c5c5c5;
}
-.pos .breadcrumb a {
+.pos .breadcrumb-button {
display: inline-block;
padding: 0 9px;
vertical-align: top;
- color: #555555;
- font-weight: bold;
+ color: #808080;
+ font-size: 14px;
+ cursor: pointer;
}
-.pos .bc-arrow {
- height: 33px;
+.pos .breadcrumb-arrow{
+ width: 28px;
}
-.pos .homeimg {
- width: 19px;
- height: 19px;
- margin: 6px 0;
+.pos .breadcrumb-homeimg {
+ width: 27px;
+ margin: 12px 6px;
}
/* b) the search box */
right: 2px;
}
.pos .searchbox input {
- width: 130px;
+ width: 100px;
border: 1px solid #cecbcb;
- padding: 3px 19px;
+ padding: 10px 20px;
+ padding-left: 38px;
margin: 6px;
- background: url("../img/search.png") no-repeat 5px;
+ background: url("../img/search.png") no-repeat 15px;
background-color: white;
+ border-radius: 20px;
+ font-family: Lato;
+}
+.pos .searchbox input:focus {
+ outline: none;
+ box-shadow: 0px 0px 0px 2px rgb(153, 153, 255) inset;
+ color: rgb(153, 153, 255);
}
.pos .search-clear {
position: absolute;
+ width: 30px;
+ height: 30px;
top: 11px;
- right: 11px;
+ left: 11px;
cursor: pointer;
- display: none;
}
/* c) the categories list */
}
.pos .category-list{
- padding:10px !important;
+ text-align: left;
+ padding: 10px;
}
/* d) the category button */
box-sizing: border-box;
border-radius: 3px;
}
+.pos .paymentline-name{
+ margin-bottom: 8px;
+}
.pos .paymentline-input{
font-size: 20px;
font-family: Lato;
background: white;
color: #484848;
text-align: right;
+ border-radius: 3px;
box-shadow: 0px 2px rgba(143, 143, 143, 0.3) inset;
}
padding-bottom:30px;
display: inline-block;
font-family: "Inconsolata";
+ border: solid 1px rgb(220,220,220);
+ border-radius: 3px;
}
.pos .pos-sale-ticket .emph{
font-size: 20px;
.pos .pos-content {
top: 0px !important;
}
- .pos .pos-rightpane {
+ .pos .rightpane {
left: 0px !important;
background-color: white;
}
cursor: pointer;
border: 1px solid #cacaca;
+ border-radius: 3px;
background: #e2e2e2;
}
}
},
selectPaymentline: function(line){
- console.log("SELECT_PAYMENTLINE",line);
if(line !== this.selected_paymentline){
if(this.selected_paymentline){
this.selected_paymentline.set_selected(false);
};
this.line_click_handler = function(event){
- console.log('click');
var node = this;
while(node && !node.classList.contains('paymentline')){
node = node.parentNode;
}
};
- },
- show: function(){
- this._super();
- var self = this;
-
- this.enable_numpad();
- this.update_payment_summary();
- this.focus_selected_line();
- window.removeall = function(){
- self.remove_empty_lines();
- };
- window.listlines = function(){
- var lines = self.pos.get('selectedOrder').get('paymentLines').models;
- for(var i = 0; i < lines.length; i++){
- console.log('LINE:',lines[i]);
- }
- };
-
- /*
-
this.hotkey_handler = function(event){
if(event.which === 13){
- self.validate();
+ self.validate_order();
}else if(event.which === 27){
self.back();
}
};
- $('body').on('keyup',this.hotkey_handler);
+ },
+ show: function(){
+ this._super();
+ var self = this;
+
+ this.enable_numpad();
+ this.focus_selected_line();
+
+ document.body.addEventListener('keyup', this.hotkey_handler);
- */
-
if( this.pos.iface_cashdrawer
&& this.pos.get('selectedOrder').get('paymentLines').find( function(pl){
return pl.cashregister.get('journal').type === 'cash';
});
}
+ this.update_payment_summary();
+
},
close: function(){
this._super();
this.disable_numpad();
- //$('body').off('keyup',this.hotkey_handler);
+ document.body.removeEventListener('keyup',this.hotkey_handler);
},
remove_empty_lines: function(){
var order = this.pos.get('selectedOrder');
focus_selected_line: function(){
var line = this.pos.get('selectedOrder').selected_paymentline;
if(line){
- debugger;
- if(!line.node){
- debugger;
- }
var input = line.node.querySelector('input');
if(!input){
return;
var new_node = this.render_paymentline(line);
old_node.parentNode.replaceChild(new_node,old_node);
- console.log('RERENDER',line);
},
remove_paymentline: function(line){
- console.log('Removing line from DOM:',line);
line.node.parentNode.removeChild(line.node);
line.node = undefined;
},
list_container.appendChild(this.render_paymentline(paymentlines[i]));
}
- //this.update_payment_summary();
+ this.update_payment_summary();
},
update_payment_summary: function() {
var currentOrder = this.pos.get('selectedOrder');
self.selectOrder();
});
if( this.order === this.pos.get('selectedOrder') ){
- this.$el.addClass('selected-order');
+ this.$el.addClass('selected');
}
},
selectOrder: function(event) {
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();
};
+
+ this.clear_search_handler = function(event){
+ console.log("CLEAR SEARCH");
+ self.clear_search();
+ };
+
+ var search_timeout = null;
+ this.search_handler = function(event){
+ clearTimeout(search_timeout);
+
+ var query = this.value;
+
+ search_timeout = setTimeout(function(){
+ self.perform_search(self.category, query, event.which === 13);
+ },70);
+ };
},
// changes the category. if undefined, sets to root category
buttons[i].addEventListener('click',this.switch_category_handler);
}
+ var products = this.pos.db.get_product_by_category(this.category.id);
+ this.product_list_widget.set_product_list(products);
- this.search_and_categories();
+ this.el.querySelector('.searchbox input').addEventListener('keyup',this.search_handler);
+
+ this.el.querySelector('.search-clear').addEventListener('click',this.clear_search_handler);
if(this.pos.iface_vkeyboard && this.pos_widget.onscreen_keyboard){
this.pos_widget.onscreen_keyboard.connect(this.$('.searchbox input'));
clear_search: function(){
var products = this.pos.db.get_product_by_category(this.category.id);
this.product_list_widget.set_product_list(products);
- this.$('.searchbox input').val('').focus();
- this.$('.search-clear').fadeOut();
+ var input = this.el.querySelector('.searchbox input');
+ input.value = '';
+ input.focus();
+ },
+ perform_search: function(category, query, buy_result){
+ if(query){
+ var products = this.pos.db.search_product_in_category(category.id,query)
+ if(buy_result && products.length === 1){
+ this.pos.get('selectedOrder').addProduct(products[0]);
+ this.clear_search();
+ }else{
+ this.product_list_widget.set_product_list(products);
+ }
+ }else{
+ var products = this.pos.db.get_product_by_category(this.category.id);
+ this.product_list_widget.set_product_list(products);
+ }
},
- // filters the products, and sets up the search callbacks
- search_and_categories: function(category){
- var self = this;
-
- // find all products belonging to the current category
- var products = this.pos.db.get_product_by_category(this.category.id);
- 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){
-
- clearTimeout(searchtimeout);
-
- var query = $(this).val().toLowerCase();
-
- searchtimeout = setTimeout(function(){
- if(query){
- if(event.which === 13){
- if( self.pos.get('products').size() === 1 ){
- 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);
- 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);
- this.product_list_widget.set_product_list(products);
- self.$('.search-clear').fadeOut();
- }
- },200);
- });
-
- //reset the search when clicking on reset
- this.$('.search-clear').click(function(){
- self.clear_search();
- });*/
- },
});
module.ProductListWidget = module.PosBaseWidget.extend({
var self = this;
return self.pos.ready.done(function() {
$('.oe_tooltip').remove(); // remove tooltip from the start session button
+
+ // remove default webclient handlers that induce click delay
+ $(document).off();
+ $(window).off();
+ $('html').off();
+ $('body').off();
+ $(self.$el).parent().off();
+ $('document').off();
+ $('.oe_web_client').off();
+ $('.openerp_webclient_container').off();
+
+ /*this.el.addEventHandler('click',function(event){
+ event.stopPropagation();
+ event.preventDefault();
+ });*/
self.build_currency_template();
self.renderElement();
<div class="pos">
<div class="pos-topheader">
<div class="pos-branding">
- <img src="/point_of_sale/static/src/img/logo.png" />
+ <img class="pos-logo" src="/point_of_sale/static/src/img/logo.png" />
<span class="placeholder-UsernameWidget"></span>
</div>
<div class="pos-rightheader">
<div class="order-selector">
- <button class="neworder-button square"><img src='/point_of_sale/static/src/img/plus.png' /></button>
- <button class="deleteorder-button square"><img src='/point_of_sale/static/src/img/minus.png' /></button>
- <ol class="orders"></ol>
+ <button class="order-button square neworder-button"><img src='/point_of_sale/static/src/img/plus.png' /></button>
+ <button class="order-button square deleteorder-button"><img src='/point_of_sale/static/src/img/minus.png' /></button>
+ <span class="orders"></span>
</div>
<!-- here goes header buttons -->
</div>
</div>
</div>
- <div class="pos-rightpane">
+ <div class="rightpane">
<div class='window'>
<div class='subwindow'>
<div class='subwindow-container screens'>
</t>
<t t-name="CategoryButton">
- <li class='category-button js-category-switch' t-att-data-category-id="category.id" >
+ <span class='category-button js-category-switch' t-att-data-category-id="category.id" >
<div class="category-img">
<img src="" />
</div>
<div class="category-name">
<t t-esc="category.name"/>
</div>
- </li>
+ </span>
</t>
<t t-name="CategorySimpleButton">
- <li class='category-simple-button js-category-switch' t-att-data-category-id="category.id" >
+ <span class='category-simple-button js-category-switch' t-att-data-category-id="category.id" >
<t t-esc="category.name"/>
- </li>
+ </span>
</t>
<t t-name="ProductCategoriesWidget">
<div>
- <header>
- <ol class="breadcrumb">
- <li class="oe-pos-categories-list">
- <a href="javascript:void(0)" class="js-category-switch">
- <img src="/point_of_sale/static/src/img/home.png" class="homeimg" />
- </a>
- </li>
+ <header class='rightpane-header'>
+ <div class="breadcrumbs">
+ <span class="breadcrumb">
+ <span class=" breadcrumb-button js-category-switch">
+ <img src="/point_of_sale/static/src/img/home.png" class="breadcrumb-homeimg" />
+ </span>
+ </span>
<t t-foreach="widget.breadcrumb" t-as="category">
- <li class="oe-pos-categories-list">
- <img src="/point_of_sale/static/src/img/bc-arrow.png" class="bc-arrow" />
- <a href="javascript:void(0)" class="js-category-switch" t-att-data-category-id="category.id">
+ <span class="breadcrumb">
+ <img src="/point_of_sale/static/src/img/bc-arrow-big.png" class="breadcrumb-arrow" />
+ <span class="breadcrumb-button js-category-switch" t-att-data-category-id="category.id">
<t t-esc="category.name"/>
- </a>
- </li>
+ </span>
+ </span>
</t>
- </ol>
+ </div>
<div class="searchbox">
<input placeholder="Search Products" />
- <img class="search-clear" src="/point_of_sale/static/src/img/search_reset.gif" />
+ <span class="search-clear"></span>
</div>
</header>
<t t-if="widget.subcategories.length > 0">
<div class="categories">
- <ol class="category-list">
- </ol>
+ <div class="category-list">
+ </div>
</div>
</t>
</div>
<t t-name="ProductListWidget">
<div class='product-list-container'>
<div class="product-list-scroller">
- <ol class="product-list">
- </ol>
+ <div class="product-list">
+ </div>
</div>
<span class="placeholder-ScrollbarWidget" />
</div>
<t t-name="ScaleScreenWidget">
<div class="scale-screen screen">
- <header><h2>Product Weighting</h2></header>
<div class="display">
<span class="weight">
<p>
<t t-name="PaymentScreenWidget">
<div class="payment-screen screen">
- <header><h2>Payment</h2></header>
<div class="pos-payment-container">
<div class='payment-due-total'></div>
<div class='payment-lines'></div>
<t t-name="ReceiptScreenWidget">
<div class="receipt-screen screen" >
- <header><h2>Receipt</h2></header>
<div class="pos-step-container">
<div class="pos-receipt-container">
</div>
<t t-name="WelcomeScreenWidget">
<div class="welcome-screen screen">
- <header><h2>Welcome</h2></header>
+ <header class='rightpane-header'><h2>Welcome</h2></header>
<div class="dialog">
<img src="/point_of_sale/static/src/img/scan.png" />
<p> Please scan an item or your member card </p>
<t t-name="ScanProductScreenWidget">
<div class="scan-product-screen screen">
- <header><h2>Please scan an item</h2></header>
+ <header class='rightpane-header'><h2>Please scan an item</h2></header>
<img src="/point_of_sale/static/src/img/scan.png" />
</div>
</t>
<t t-name="ClientPaymentScreenWidget">
<div class="scan-product-screen screen">
- <header><h2>Payment</h2></header>
+ <header class='rightpane-header'><h2>Payment</h2></header>
<div class="dialog">
<img src="/point_of_sale/static/src/img/bancontact.png" />
<p>Please insert your card in the reader and follow the instructions to complete
<t t-name="ScaleInviteScreenWidget">
<div class="scale-invite-screen screen">
- <header><h2>Please put your product on the scale</h2></header>
+ <header class='rightpane-header'><h2>Please put your product on the scale</h2></header>
<img src="/point_of_sale/static/src/img/scale.png" />
</div>
</t>
</t>
<t t-name="Product">
- <li class='product' t-att-data-product-id="product.id">
+ <span class='product' t-att-data-product-id="product.id">
<div class="product-img">
<img src='' /> <!-- the product thumbnail -->
<t t-if="!product.to_weight">
<div class="product-name">
<t t-esc="product.name"/>
</div>
- </li>
+ </span>
</t>
<t t-name="OrderWidget">
</li>
</t>
</ul>
- <div class="summary">
+ <div class="summary clearfix">
<div t-attf-class="line #{orderlines.length === 0 ? 'empty' : ''}">
<div class='entry total'>
<span class="label">Total: </span> <span class="value">0.00 €</span>
</t>
<t t-name="OrderButtonWidget">
- <li class="order-selector-button">
- <button class="select-order"><t t-esc="(widget.order.get_client() ? widget.order.get_client_name()+' : ':'') + widget.order.get('creationDate').toString('t')"/></button>
- </li>
+ <button class="order-button select-order"><t t-esc="(widget.order.get_client() ? widget.order.get_client_name()+' : ':'') + widget.order.get('creationDate').toString('t')"/></button>
</t>
<t t-name="UsernameWidget">